Spring Boot通过WebMvcAutoConfiguration来提供一些默认配置;大多数时候使用默认的配置即可满足要求。但有时可能需要做一些个性化定制,此时就需要使用以下方式来进行。
此时会引入类WebMvcConfigurationSupport中的相关配置;而不会使用WebMvcAutoConfiguration中的配置。
EnableWebMvc注解需要与Configuration注解一起使用,否则将不会生效;
同时需要注意的是同一个应用中,只能有一个被EnableWebMvc注解的类。
示例如下:
@Configuration
@EnableWebMvc
public class BlankWebMvcConfigure {
}
通过这种方式引入WebMvcConfigurationSupport相关配置时,可以通过实现WebMvcConfigurer接口来对其配置做个性化修改。
如下所示:
@Configuration
@EnableWebMvc
public class BlankWebMvcConfigure implements WebMvcConfigurer {
}
WebMvcConfigurer提供的功能如下表所示:
配置接口 | 接口说明 |
---|---|
configurePathMatch | 配置HandlerMapping路径匹配参数 |
configureContentNegotiation | 配置路径到请求内容类型转换的相关参数,如.pdf结尾的请求解析成PDF类型或者其它等 |
configureAsyncSupport | 配置异步请求处理相关参数 |
configureDefaultServletHandling | 配置是否需要以下功能:如果一个请求没有被任何Handler处理,那是否使用DefaultServletHttpRequestHandler来进行处理? |
addFormatters | 增加额外的Converter和Formatter |
addInterceptors | 增加拦截器 |
addResourceHandlers | 增加处理静态资源的Handler |
addCorsMappings | 配置跨域请求相关参数 |
addViewControllers | 使用特殊的Controller来处理指定的URL请求; |
configureViewResolvers | 配置将Controller返回的视图名称转换成视图的视图解析器; 以便进行视图渲染 |
addArgumentResolvers | 添加支持个性化配置Controller的方法参数类型的Resolver。 |
addReturnValueHandlers | 添加支持个性化处理Controller返回数据类型的处理器; |
configureMessageConverters | 配置消息转换器; |
extendMessageConverters | 扩展消息转换器 |
configureHandlerExceptionResolvers | 配置异常处理器 |
extendHandlerExceptionResolvers | 扩展异常处理器 |
具体用法及说明见以下Java代码
/**
* 配置RequestMapping注解中指定的路径模式与实际访问路径之间映射的处理规则
* @param configurer
*/
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
logger.info("Begin to configure pathMatches!");
/**
* 是否包含.*来映射请求
* 假设RequestMapping注解中指定的路径是/test
* 如果设置成True,那么对于/test.do,/test.a等任何包含.的请求都会映射到/test上去;
* 如果设置成False,那么对于这种请求不会进行映射。
*
*/
configurer.setUseSuffixPatternMatch(true);
/**
* 设置路径后是否包含/
* 假设RequestMapping注解中指定的路径是/test
* 设置成True时,会同时处理/test/和/test的请求
* 设置成False时,只会处理/test的请求
* 默认是True
*/
configurer.setUseTrailingSlashMatch(false);
/**
* 配置后置模式匹配是否仅在配置内容协商中明确指定的路径扩展名称时生效
* 举个例子:假设WebMvcConfigurer中覆盖了configureContentNegotiation方法进行以下处理:
* @Override
* public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
* configurer.mediaType("pdf", MediaType.APPLICATION_PDF);
*}
* 当setUseRegisteredSuffixPatternMatch配置成TRUE时,即使setUseSuffixPatternMatch设置成True,
* 在访问/test.do时也不会命中被RequestMapping注解值为/test的Controller;
* 只有在访问/test.pdf时才能正常访问,其它任何的/test.txt或者/test.doc等均会报404;
* 默认情况下该值是False
*/
configurer.setUseRegisteredSuffixPatternMatch(true);
}
配置访问路径中的后缀与具体的访问内容类型的映射关系;
用法如下:
/**
* 配置路径后缀与访问的内容类型的映射关系
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
/**
* 设置后缀与访问的内容类型的映射关系;
* 如以下示例,默认情况下.txt表明是TXT类型,现在将其指定为PDF类型;
* 那么在访问http://localhost/test.txt时将会将其当成PDF文件类型使用PDF阅读工具打开。
*/
configurer.mediaType("txt", MediaType.APPLICATION_PDF);
/**
* 是否忽略请求报文头中的内容类型
* 默认情况下是False,即以请求报文头中的类型为准
*/
configurer.ignoreAcceptHeader(true);
/**
* 是否通过传入的参数(默认名称是format)来决定内容类型
* 需要结合mediaType方法一起使用;
* 如通过mediaType指定txt为PDF类型;则访问路径http://localhost/test?format=txt时会当成PDF类型处理
* 默认为False
*/
configurer.favorParameter(true);
/**
* 是否优先使用后缀为决定内容类型
* 为False时优先使用Header中的类型
* 为True时优先使用.后面指定的类型
* 默认为True
*/
configurer.favorPathExtension(false);
/**
* 是否仅处理明确通过mediaType注册的类型请求
*/
configurer.useRegisteredExtensionsOnly(true);
}
用于执行异步Controller时的相关参数配置;
关于Spring异步处理后续再行研究;
使用方式如下:
/**
* 配置当通过DispatcherServlet没有查找到对应的Handler处理时,是否使用默认的DefaultServletHttpRequestHandler来进行处理
* @param configurer
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
添加对象转换Convert和格式化Format,如设置日期的展示格式等。
如以下示例:
/**
* 增加对象转换方法和格式化方法
*
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
/**
* 处理前台传入类型为String且Controller中接入参数也是String的参数转换
* 将前台传入参数值附加[converted]后在调用Controller时使用;
* 如前台通过访问http://localhost/test?a=b调用Controller,在Controller获取到a的值时将会是a[converted]
*/
registry.addConverter(new Converter() {
@Nullable
@Override
public String convert(String source) {
return null == source? null : source + "[converted]";
}
});
/**
* 处理当前台传入是String类型而后台Controller接收的参数是Integer类型时的转换规则
*/
registry.addConverter(new Converter() {
@Nullable
@Override
public Integer convert(String source) {
return null == source? null : Integer.valueOf(source) + 100;
}
});
}
添加拦截器; 具体见http://blog.csdn.net/icarusliu/article/details/78833520
配置静态资源的路径规则以及查找静态资源的路径。
如果使用了EnableWebMvc注解时,static下的HTML页面将无法直接使用,此时就需要通过以下方式来进行处理。
示例如下:
/**
* 配置静态资源访问的路径规则以及查找静态资源的路径
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 处理所有HTML的请求,到static目录下查找对应的资源
*/
registry.addResourceHandler("/**.html") //处理的路径规则
.addResourceLocations("classpath:/static/") //到哪些目录下去查找静态资源
;
}
添加全局的跨域处理支持。
使用方法如下所示:
/**
* 进行跨域访问相关配置
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/test1/**") //可以跨域访问的URL路规则
.allowedOrigins("http://localhost:8080/") //可以跨域访问的访问者
.allowedMethods("GET", "POST", "PUT", "DELETE") //可以跨域访问的方法
.allowedHeaders("") //可以跨域访问的Headers
;
}
针对特定的URL,配置简单自动的Controller来使用指定的StatusCode或者是View生成返回结果;
它在以下场景中非常有用:当Controller不需要具体的处理逻辑而仅是返回一个视图时。
具体使用示例如下:
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/**
* 配置路径跳转;将某个路径的请求映射到另外一个路径
* 如将所有http://localhost/b/**的请求全部跳转到http://localhost/test上去
*/
registry.addRedirectViewController("/b/**", "/test");
/**
* 将路径映射到某个名称为指定值的视图上
* 访问/c会返回a.html的视图
* 一般与ViewResolver结合使用
*/
registry.addViewController("/c").setViewName("a");
/**
* 指定某个请求的状态码,而不返回任何的内容
* 如下面将/badRequest请求返回状态码为400,而没有返回其它内容
*/
registry.addStatusController("/badRequest", HttpStatus.BAD_REQUEST);
}
配置ViewResolvers来将Controller返回的String类型的视图名称转换成视图
示例如下:
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
/**
* 添加HTML的视图解析器
* 本示例完成以下功能:将Controller返回的String类型的视图名称添加前缀及后缀;
* 如返回的是a,那么处理后对应的视图将会是/a.html
*/
registry.viewResolver(new InternalResourceViewResolver("/", ".html"));
}
添加Resolver来支持定制Controller的方法参数类型;该方法不会覆盖内置的相关机制;
针对参数解析上要做定制化时可以使用该方法添加自定义的Resolver可以实现。
添加Resolver来支持定制Controller返回类型。
配置读写Request或者Response的BODY的HttpMessageConverter。会替换到默认的HttpMessageConverters;
与configureMessageConverters类似,但这里是进行扩展,不会替换到原本的HttpMessageConverters。
配置异常处理器;会替换到系统原本的异常处理器;
可以配置当遇到哪个异常时跳转到哪个页面;如果视图是JSP等就可以展现更多的错误信息了。
示例:
public void configureHandlerExceptionResolvers(List resolvers) {
resolvers.add(new HandlerExceptionResolver() {
@Nullable
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) {
//处理空指针异常,跳转到/a.html页面去;
if (ex instanceof NullPointerException) {
logger.error("Catch a NullPointerException!", ex);
ModelAndView view = new ModelAndView("a");
view.addObject("errorMessage", "NullPointerException!");
return view;
}
logger.error("Catch an other exception!", ex);
//处理其它异常
return new ModelAndView("myError");
}
});
扩展异常处理器;不会替换原本的异常处理器
继承自该类时,同时也需要添加Configuration注解才能生效; 也可以直接继承DelegatingWebMvcConfiguration这个类来进行定制。
通过继承这两个类来覆盖其某些方法,能够修改其默认的配置项。
但切记不能同时添加EnableWebMvc注解,否则使用的还是DelegatingWebMvcConfiguration中的配置,此处覆盖的方法不会生效。
@Configuration
public class MvcConfigurer extends WebMvcConfigurationSupport{
private static Logger logger = LoggerFactory.getLogger(WebMvcConfigurationSupport.class);
protected void configureHandlerExceptionResolvers(List exceptionResolvers) {
logger.info("Begin to configure handler exception resolvers!");
HandlerExceptionResolver resolver = new HandlerExceptionResolver() {
@Nullable
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
logger.error("Begin to resolve exception of " + ex.getMessage(), ex);
return new ModelAndView("test");
}
};
exceptionResolvers.add(resolver);
}
}