WebMvcConfigurer
是 Spring MVC 提供的一个扩展接口,用于配置 Spring MVC 的各种功能。在 Spring Boot 应用中,通过实现 WebMvcConfigurer
接口,可以定制和扩展默认的 Spring MVC 配置。WebMvcConfigurer
接口提供了一组回调方法,用于配置 Spring MVC 的各种方面,如视图解析器、拦截器、跨域请求、消息转换器等。通过实现这些方法,可以方便地自定义 MVC 配置。
1. 创建配置类
创建一个配置类并实现 WebMvcConfigurer 接口,通常加上 @Configuration 注解使其成为配置类。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class MyWebMvcConfig implements WebMvcConfigurer {
// 自定义配置在这里添加
}
2. 配置视图解析器:
通过实现 configureViewResolvers
方法,可以自定义视图解析器。
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
3. 添加拦截器:
通过实现 addInterceptors
方法,可以添加拦截器。
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/css/**");
}
- addInterceptor: 添加自定义拦截器。
- addPathPatterns: 指定拦截路径。
- excludePathPatterns: 排除某些路径不拦截。
4. 配置跨域请求:
通过实现 addCorsMappings
方法,可以配置跨域请求。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://example.com")
.allowedMethods("GET", "POST")
.allowCredentials(true);
}
注意事项
- 不要继承 WebMvcConfigurationSupport:除非你想完全接管 Spring MVC 配置。否则推荐直接实现 WebMvcConfigurer。
- 多个配置类:如果有多个类实现了 WebMvcConfigurer,可以使用 @Order 控制顺序。
- Spring Boot 2.x 及以上兼容性良好:大多数配置开箱即用,无需额外依赖。
5. 添加静态资源处理:
通过实现 addResourceHandlers
方法,可以配置静态资源的处理。
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
6. 配置消息转换器:
通过实现 configureMessageConverters
方法,可以添加或自定义消息转换器。
import org.springframework.http.converter.HttpMessageConverter;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MyCustomMessageConverter());
}
权限完整例子
import java.util.concurrent.ExecutorService;
import net.hworld.interceptor.AccessInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration(proxyBeanMethods = false)
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AccessInterceptor accessInterceptor;
@Autowired
private ExecutorService executorService;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessInterceptor).order(2).addPathPatterns("/**")
.excludePathPatterns("/actuator/**", "/favicon.ico", "/demo/**");
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(new TaskExecutorAdapter(executorService));
}
}
接口认证
/**
* 权限判断
*/
@Slf4j
@Component
@Order(2)
public class AccessInterceptor implements HandlerInterceptor {
@Autowired
private AuthUtils authUtils;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
//内网不需要token
NotVerifyToken notVerifyTokenCls = method.getMethod().getDeclaringClass().getAnnotation(NotVerifyToken.class);
NotVerifyToken notVerifyTokenMtd = method.getMethod().getAnnotation(NotVerifyToken.class);
if (notVerifyTokenCls != null || notVerifyTokenMtd != null) {
return true;
}
// 认证
String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
if (StringUtils.isBlank(authorization)){
authorization = request.getParameter("accessToken");
}
if (StringUtils.isNotBlank(authorization)) {
authorization = authorization.replace("Bearer ", "");
log.info("authorization is {}", authorization);
try {
authUtils.authorize(authorization, false);
} catch (RuntimeException e) {
log.warn("token error 401: {},{}", authorization, e.getMessage());
this.handle401(response, WebResponse.fail(WebResponseCode.AUTH_EXCEPTION));
return false;
}
} else {
log.warn("token is empty");
this.handle401(response, WebResponse.fail(WebResponseCode.AUTH_EXCEPTION));
return false;
}
}
return true;
}
void handle401(HttpServletResponse response, WebResponse<Object> webResponse) throws IOException {
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
IOUtils.write(JsonUtil.bean2Json(webResponse), response.getWriter());
response.getWriter().close();
}
}
绕开认证注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotVerifyToken {
}