( 十六 ) SpringBoot 定制 Spring MVC
( 十六 ) SpringBoot 定制 Spring MVC
1、简介
SpringBoot 抛弃了传统 xml 配置文件,通过配置类(标注 @Configuration 的类,相当于一个 xml 配置文件)以 JavaBean 形式进行相关配置。
SpringBoot 对 Spring MVC 的自动配置可以满足我们的大部分需求,但是我们也可以通过自定义配置类(标注 @Configuration 的类)并实现 WebMvcConfigurer 接口来定制 Spring MVC 配置。WebMvcConfigurer 配置类其实是Spring
内部的一种配置方式,采用JavaBean
的形式来代替传统的xml
配置文件形式进行针对框架个性化定制,可以自定义一些Handler,Interceptor,ViewResolver,MessageConverter。
SpringBoot 1.5 及以前是通过继承 WebMvcConfigurerAdapter 抽象类来定制 Spring MVC 配置的,但在 SpringBoot 2.0 后,WebMvcConfigurerAdapter 抽象类就被弃用了,改为实现 WebMvcConfigurer 接口来定制 Spring Mvc 配置 或者 直接 继承 WebMvcConfigurationSupport 类。推荐使用实现WebMvcConfigurer 接口。
2、WebMvcConfigurer
WebMvcConfigurer 是一个基于 Java 8 的接口,该接口定义了许多与 Spring MVC 相关的方法,其中大部分方法都是 default 类型的,且都是空实现。因此我们只需要定义一个配置类实现 WebMvcConfigurer 接口,并重写相应的方法便可以定制 Spring MVC 的配置。
方法 | 说明 |
---|---|
default void configurePathMatch(PathMatchConfigurer configurer) {} | HandlerMappings 路径的匹配规则。 |
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {} | 内容协商策略(一个请求路径返回多种数据格式)。 |
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {} | 处理异步请求。 |
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {} | 这个接口可以实现静态文件可以像 Servlet 一样被访问。 |
default void addFormatters(FormatterRegistry registry) {} | 添加格式化器或者转化器。 |
default void addInterceptors(InterceptorRegistry registry) {} | 添加 Spring MVC 生命周期拦截器,对请求进行拦截处理。 |
default void addResourceHandlers(ResourceHandlerRegistry registry) {} | 添加或修改静态资源(例如图片,js,css 等)映射; Spring Boot 默认设置的静态资源文件夹就是通过重写该方法设置的。 |
default void addCorsMappings(CorsRegistry registry) {} | 处理跨域请求。 |
default void addViewControllers(ViewControllerRegistry registry) {} | 主要用于实现无业务逻辑跳转,例如主页跳转,简单的请求重定向,错误页跳转等 |
default void configureViewResolvers(ViewResolverRegistry registry) {} | 配置视图解析器,将 Controller 返回的字符串(视图名称),转换为具体的视图进行渲染。 |
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {} | 添加解析器以支持自定义控制器方法参数类型,实现该方法不会覆盖用于解析处理程序方法参数的内置支持; 要自定义内置的参数解析支持, 同样可以通过 RequestMappingHandlerAdapter 直接配置 RequestMappingHandlerAdapter 。 |
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {} | 添加处理程序来支持自定义控制器方法返回值类型。使用此选项不会覆盖处理返回值的内置支持; 要自定义处理返回值的内置支持,请直接配置 RequestMappingHandlerAdapter。 |
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {} | 用于配置默认的消息转换器(转换 HTTP 请求和响应)。 |
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {} | 直接添加消息转换器,会关闭默认的消息转换器列表; 实现该方法即可在不关闭默认转换器的起提下,新增一个自定义转换器。 |
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {} | 配置异常解析器。 |
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {} | 扩展或修改默认的异常解析器列表。 |
在 Spring Boot 项目中,我们可以通过以下 2 中形式定制 Spring MVC:
- 扩展 Spring MVC
- (@EnableWebMvc)全面接管 Spring MVC
示例:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
//实现 WebMvcConfigurer 接口可以来扩展 SpringMVC 的功能
//@EnableWebMvc 不要完全接管SpringMVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//当访问 “/” 或 “/index.html” 时,都直接跳转到登陆页面
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
}
}
启动 Spring Boot,您会发现“http://localhost:8080/login”、“http://localhost:8080/”“http://localhost:8080/index.html”3 个 URL 都能跳转到登陆页 login.html
注意: 当我们全面接管 Spring MVC 后,Spring Boot 对 Spring MVC 的默认配置都会失效。所以非必要条件下请不要使用 @EnableWebMvc
3、常用的方法:
3.1、addInterceptors:拦截器
- addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
- addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
- excludePathPatterns:用于设置不需要拦截的过滤规则
- 拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(new TestInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/emp/toLogin","/emp/login","/js/**","/css/**","/images/**");
}
3.2、 addViewControllers:页面跳转
以前写SpringMVC的时候,如果需要访问一个页面,必须要写Controller类,然后再写一个方法跳转到页面,感觉好麻烦,其实重写WebMvcConfigurer中的addViewControllers方法即可达到效果了
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/toLogin").setViewName("login");
}
3.3、 addResourceHandlers:静态资源
比如,我们想自定义静态资源映射目录的话,只需重写addResourceHandlers方法即可
@Configuration
public class MyWebMvcConfigurerAdapter implements WebMvcConfigurer {
/**
* 配置静态访问资源
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/my/**").addResourceLocations("classpath:/my/");
}
}
- addResoureHandler:指的是对外暴露的访问路径
- addResourceLocations:指的是内部文件放置的目录
3.4、 configureDefaultServletHandling:默认静态资源处理器
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
configurer.enable("defaultServletName");
}
3.5、 configureViewResolvers:视图解析器
这个方法是用来配置视图解析器的,该方法的参数ViewResolverRegistry 是一个注册器,用来注册你想自定义的视图解析器等
/**
* 配置请求视图映射
* @return
*/
@Bean
public InternalResourceViewResolver resourceViewResolver()
{
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
//请求视图文件的前缀地址
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
//请求视图文件的后缀
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
/**
* 视图配置
* @param registry
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
super.configureViewResolvers(registry);
registry.viewResolver(resourceViewResolver());
/*registry.jsp("/WEB-INF/jsp/",".jsp");*/
3.7、 addCorsMappings:跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
super.addCorsMappings(registry);
registry.addMapping("/cors/**")
.allowedHeaders("*")
.allowedMethods("POST","GET")
.allowedOrigins("*");
}
3.8、 configureMessageConverters:信息转换器
/**
* 消息内容转换配置
* 配置fastJson返回json转换
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//调用父类的配置
super.configureMessageConverters(converters);
//创建fastJson消息转换器
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//创建配置类
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//修改配置返回内容的过滤
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty
);
fastConverter.setFastJsonConfig(fastJsonConfig);
//将fastjson添加到视图消息转换器列表内
converters.add(fastConverter);
}