使用WebMvcConfigurer配置SpringMVC
小豹子的技术笔记 2024-06-26 11:33:03 阅读 92
一、前言
WebMvcConfigurer配置类是使用Java代码代替传统的xml配置文件,对SpirngMvc进行配置的一种方式,需要创建一个配置类@Configuration
并实现WebMvcConfigurer 接口
(推荐
)。
二、使用方式
官方推荐使用实现WebMvcConfigurer接口(推荐)
或者继承WebMvcConfigurationSupport类
来实现代码配置。
1.配置类实现WebMvcConfigurer接口
@Configuration
public class WebMvcConfg implements WebMvcConfigurer {}
2.配置类继承WebMvcConfigurationSupport
@Configuration
public class WebMvcConfg extends WebMvcConfigurationSupport {}
三、WebMvcConfigurer接口常用方法
addInterceptors:拦截器
addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
addPathPatterns:用于设置拦截器的过滤路径规则;- addPathPatterns(“/**”)对所有请求都拦截
excludePathPatterns:用于设置不需要拦截的过滤规则
拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。
addCorsMappings:跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*") //浏览器允许所有的域访问 / 注意 * 不能满足带有cookie的访问,Origin 必须是全匹配
.allowCredentials(true) // 允许带cookie访问
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("token")
.maxAge(3600);
}
configureContentNegotiation:默认内容协商配置
内容协商:在 HTTP 协议中,内容协商是这样一种机制,通过为同一 URI 指向的资源提供不同的展现形式,可以使用户代理选择与用户需求相适应的最佳匹配
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// 是否通过请求Url的扩展名来决定media type
configurer.favorPathExtension(false);
//不检查Accept请求头 设置默认的media type
configurer.ignoreAcceptHeader(true).defaultContentType(MediaType.APPLICATION_JSON_UTF8);
}
上面代码说白了就是告诉系统什么类型用什么来标识。
addViewControllers:跳转指定页面
以前写SpringMVC的时候,如果需要访问一个页面,必须要写Controller类,然后再写一个方法跳转到页面,感觉好麻烦,其实重写WebMvcConfigurer中的addViewControllers方法即可达到效果了。
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 绑定指定URL访问的view名称,这行的意思是在访问/路径时会自动跳转到index.html;如/login则不受影响
registry.addViewController("/").setViewName("forward:/index.html");
}
resourceViewResolver:视图解析器
configureMessageConverters:信息转换器
配置在接收request (请求)和返回response (响应)时的数据转换器
,最常用到的就是fastJson的转换,配置如下所示
该方法会替换所有默认的MessageConverters,使用自定义添加converters,在实际项目中应用比例也比较小;
/**
* 消息内容转换配置
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//StringHttpMessageConverter默认使用的字符集是ISO-8859-1,改为输出的JSON字符串为UTF-8字符集
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
//添加fastjson消息转换器
converters.add(fastJsonHttpMessageConverters());
}
/**
* 引入Fastjson解析json,不使用默认的jackson,必须在pom.xml引入fastjson的jar包,并且版必须大于1.2.10
*
* @return
*/
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverters() {
//1、定义一个convert转换消息的对象
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//2、添加fastjson的配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig();
SerializerFeature[] serializerFeatures = new SerializerFeature[]{
// 输出key是包含双引号
//SerializerFeature.QuoteFieldNames,
// 是否输出为null的字段,若为null 则显示该字段
SerializerFeature.WriteMapNullValue,
// 数值字段如果为null,则输出为0
SerializerFeature.WriteNullNumberAsZero,
// List字段如果为null,输出为[],而非null
SerializerFeature.WriteNullListAsEmpty,
// 字符类型字段如果为null,输出为"",而非null
SerializerFeature.WriteNullStringAsEmpty,
// Boolean字段如果为null,输出为false,而非null
SerializerFeature.WriteNullBooleanAsFalse,
// Date的日期转换器
SerializerFeature.WriteDateUseDateFormat,
// 循环引用(如果不配置有可能会进入死循环)
SerializerFeature.DisableCircularReferenceDetect,
// 格式化JSON
SerializerFeature.PrettyFormat
};
fastJsonConfig.setSerializerFeatures(serializerFeatures);
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
//3.解决乱码问题。定义响应的MIME类型,设置响应的content-type为application/json;charset=UTF-8
List<MediaType> fastMediaType = new ArrayList<>();
fastMediaType.add(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
//4.converter消息转换器添加配置信息
fastConverter.setSupportedMediaTypes(fastMediaType);
//5、在convert中添加配置信息
fastConverter.setFastJsonConfig(fastJsonConfig);
return fastConverter;
}
extendMessageConverters:信息转换器
1.使用
springboot2.0版本以后推荐使用extendMessageConverters
来进行web配置,这个方法不会覆盖springmvc已默认添加的HttpMessageConverter
即:在默认加载的消息转换器基础上
继续添加自定义的converters实例
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customerMappingJackson2HttpMessageConverter());
}
@Bean
public MappingJackson2HttpMessageConverter customerMappingJackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
//设置日期格式
ObjectMapper objectMapper = messageConverter.getObjectMapper();
SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd");
objectMapper.setDateFormat(smt);
messageConverter.setObjectMapper(objectMapper);
//设置中文编码格式
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON);
messageConverter.setSupportedMediaTypes(list);
return messageConverter;
}
应用场景
空值处理
请求和返回的数据有很多空值,这些值有时候并没有实际意义,我们可以过滤掉和不返回,或设置成默认值。比如通过重写getObjectMapper
方法,将返回结果的空值不进行序列化:
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter
mappingJackson2HttpMessageConverter =
new MappingJackson2HttpMessageConverter();
// 调整ObjectMapper对象序列化行为
ObjectMapper objectMapper = mappingJackson2HttpMessageConverter.getObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(0,mappingJackson2HttpMessageConverter);
}
响应字段格式调整
将Long类型转为字符串方式返回,Date格式改为时间戳返回(底层原理:调整MappingJackson2HttpMessageConverter类中ObjectMapper序列化行为)
@Configuration
public class JacksonConfig implements WebMvcConfigurer {
@Value("${xss.enabled:false}")
private boolean enableXss;
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
SimpleModule simpleModule = new SimpleModule();
//Long类型序列化成字符串,避免Long精度丢失
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
// simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
// XSS序列化
if (enableXss) {
simpleModule.addDeserializer(String.class, new XssJacksonDeserializer());
}
// Date
simpleModule.addSerializer(Date.class, new JacksonDateSerializer());
simpleModule.addDeserializer(Date.class, new JacksonDateDeserializer());
simpleModule.addSerializer(LocalDateTime.class, new JacksonLocalDateTimeSerializer());
simpleModule.addDeserializer(LocalDateTime.class, new JacksonLocalDateTimeDeserializer());
objectMapper.registerModule(simpleModule)
.registerModule(new JavaTimeModule())
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module());
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
//放到第一个
converters.add(0, jackson2HttpMessageConverter);
}
}
addResourceHandlers:静态资源
addResoureHandler:请求静态资源的路径
addResourceLocations:静态资源存放位置,可以配置多个,按先后顺序查找
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 10 days
addCacheControl(registry, "img", 864000);
addCacheControl(registry, "vendor", 864000);
// 1 day
addCacheControl(registry, "scripts", 86400);
addCacheControl(registry, "styles", 86400);
addCacheControl(registry, "views", 86400);
}
private void addCacheControl(ResourceHandlerRegistry registry, String folder, int cachePeriod) {
registry.addResourceHandler(String.format("/%s/**", folder))
.addResourceLocations(String.format("classpath:/static/%s/", folder))
.setCachePeriod(cachePeriod);
}
可以对静态资源做缓存控制之类的。
HttpMessageConverter接口
Http请求响应报文其实都是字符串
,当请求报文到java程序会被封装为一个ServletInputStream流
,供开发人员读取请求报文,响应报文则通过ServletOutputStream流
,来输出响应报文。
从流中只能读取到原始的字符串报文,同样输出流也是。那么在报文SpringMVC 输入和输出都存在一个字符串到java对象的转化问题
。这一过程,在SpringMVC是通过HttpMessageConverter
来解决的。在SpringMVC的处理过程中,一次请求报文和一次响应报文
,分别被抽象为一个请求消息HttpInputMessage
和一个响应消息HttpOutputMessage
。处理请求时,由合适的消息转换器将请求报文绑定为方法中的形参对象,在这里同一个对象就有可能出现多种不同的消息形式,如json、xml。同样响应请求也是同样道理。
(1)HttpInputMessage 将请求的信息先转为 InputStream 对象,InputStream 再由 HttpMessageConverter 转换为 SpringMVC 需要的java对象;
(2)SpringMVC 返回一个 java 对象, 并通过 HttpMessageConverter 转为响应信息,接着 HttpOutputMessage 将响应的信息转换为OutputStream,接着给出响应。
简单说就是 HTTP request (请求)和response (响应)数据的转换器
通常实现HttpMessageConverter接口的转换器有以下几种:
ByteArrayHttpMessageConverter
: 负责读取二进制格式的数据和写出二进制格式的数据;StringHttpMessageConverter
: 负责读取字符串格式的数据和写出二进制格式的数据;ResourceHttpMessageConverter
:负责读取资源文件和写出资源文件数据;FormHttpMessageConverter: 负责读取form提交的数据(能读取的数据格式为 application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入application/x-www-from-urlencoded和multipart/form-data格式的数据;MappingJacksonHttpMessageConverter: 负责读取和写入json格式的数据;SourceHttpMessageConverter: 负责读取和写入 xml 中javax.xml.transform.Source定义的数据;Jaxb2RootElementHttpMessageConverter: 负责读取和写入xml 标签格式的数据;AtomFeedHttpMessageConverter: 负责读取和写入Atom格式的数据;RssChannelHttpMessageConverter: 负责读取和写入RSS格式的数据
在SpringMVC / SpringBoot中@ResponseBody
这类注解默认使用的是jackson来解析json
3.HttpMessageConverter请求信息转换器执行流程
当用户发送请求后,@Requestbody 注解
会读取请求body中的数据,默认的请求转换器HttpMessageConverter通过获取请求头Header中的Content-Type来确认请求头的数据格式
,从而来为请求数据适配合适的转换器。
例如contentType=applicatin/json,那么转换器会适配MappingJacksonHttpMessageConverter
响应时候的时候同理,@Responsebody注解
会启用HttpMessageConverter,通过检测Header中Accept属性
来适配的响应的转换器。
参考: https://blog.csdn.net/yuliantao/article/details/136517144
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。