Springboot的starter封装了很多东西,包含了MessageConverter、ViewResolver等web的配置,若需要自定义。在之前1.5版本中自定义javaBean继承WebMvcConfigurerAdapter类,但是在2.0版本中此类标记过时,需要实现WebMvcConfigurer接口实现自定义配置。
个人学习总结:
链接:【springboot、springcloud、docker 等,学习目录】
配置类继承WebMvcConfigurerAdapter,重写方法。
/**
* WebMvcConfigurerAdapter(抽象类):
* 实现了WebMvcConfigurer接口
* 自定义web配置,只需重写方法即可
*/
@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
...
}
// 实现 WebMvcConfigurer 接口
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
// 方法没有任何逻辑
public WebMvcConfigurerAdapter() {
}
...
}
// WebMvcConfigurer 接口
public interface WebMvcConfigurer {
void configurePathMatch(PathMatchConfigurer var1);
...
}
设计技巧: 自定义web配置和WebMvcConfigurer接口之间加上抽象类WebMvcConfigurerAdapter ,该抽象类中没有抽象方法(子类必须重写抽象类中的抽象方法),为方法的空实现。继承抽象类之后就不必要去实现那些我们不需要的方法,自定义配置只需要针对某一个方法重写即可。
SpringBoot2.0及Spring5.0中WebMvcConfigurerAdapter已被废弃 。推荐直接实现WebMvcConfigurer接口或继承WebMvcConfigurationSupport类。
方式1、继承WebMvcConfigurationSupport类:
public class CustomWebMvcConfig extends WebMvcConfigurationSupport{
...
}
// 没有WebMvcConfigurationSupport类型的bean时改自动配置类才会生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
解决:重写相应的方法。例如:
@Configuration
public class WebAppConfig extends WebMvcConfigurationSupport {
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(LoginInterceptor()).addPathPatterns("/sys/**")
.excludePathPatterns("/sys/login.html", "/sys/login/**");
super.addInterceptors(registry);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
super.addResourceHandlers(registry);
}
}
不推荐此种方式。
方式2、实现 WebMvcConfigurer 接口:
推荐此种配置方式。
1、如下:以拦截器和消息转换器的配置为例
/**
* @Auther: xf
* @Date: 2019/1/8 19:25
* @Description: springboot 2.0 自定义webmvc的配置
* 方式:
* 1、继承 WebMvcConfigurationSupport 会导致 webmvc 自动配置失效
* 2、实现 WebMvcConfigurer 接口 推荐
*/
@Configuration
//public class CustomWebMvcConfig extends WebMvcConfigurationSupport{
public class CustomWebMvcConfig implements WebMvcConfigurer {
/**
* 拦截器配置
* addPathPatterns 用于添加拦截规则
* excludePathPatterns 用户排除拦截
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器会组成一个拦截器链
registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").excludePathPatterns("/login");
registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
}
/**
* 消息转换器 -- alibaba 开源的 fastjson
*/
@Override
public void configureMessageConverters(List> converters) {
/**
* springboot 2.0 配置FastJson失效,添加如下配置
*
* 自定义的 FastJsonHttpMessageConverter 在 MappingJackson2HttpMessageConverter 后面,导致失效
* 解决:加载FastJsonHttpMessageConverter 前删除 MappingJackson2HttpMessageConverter
*
* 参考链接:https://segmentfault.com/a/1190000015975405
*/
Iterator> iterator = converters.iterator();
while(iterator.hasNext()){
HttpMessageConverter> converter = iterator.next();
if(converter instanceof MappingJackson2HttpMessageConverter){
iterator.remove();
}
}
// 1、需要定义一个convert转换消息的对象;
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
// 2、添加fastJson的配置信息,比如:是否要格式化返回的json数据;
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(
SerializerFeature.PrettyFormat,
// list null -> []
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteDateUseDateFormat,
// String null -> ""
SerializerFeature.WriteNullStringAsEmpty,
// Number null -> 0
SerializerFeature.WriteNullNumberAsZero,
// Boolean null -> false
SerializerFeature.WriteNullBooleanAsFalse,
//禁止循环引用
SerializerFeature.DisableCircularReferenceDetect
);
// 3、处理中文乱码问题
List fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
// 4、在convert中添加配置信息.
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
// 5、将convert添加到converters当中.
converters.add(fastJsonHttpMessageConverter);
/**
* WriteNullListAsEmpty :List字段如果为null,输出为[],而非null
* WriteNullStringAsEmpty : 字符类型字段如果为null,输出为"",而非null
* DisableCircularReferenceDetect :消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
* WriteNullBooleanAsFalse:Boolean字段如果为null,输出为false,而非null
* WriteMapNullValue:是否输出值为null的字段,默认为false
*/
}
}
注意: springboot2.0中fastjson消息转换器配置失效的问题。
2、测试:拦截器、消息转换器均有效。