User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Spring   ›   SpringBoot   ›   正文
SpringBoot

SpringBoot—WebMvcConfigurer详解

2020-03-16 23:45:15
1708  0 1
参考目录 隐藏
1) 为什么要使用WebMvcConfigurer?
2) WebMvcConfigurer方法介绍
3) 1.configurePathMatch
4) 2. configureContentNegotiation
5) 3. configureAsyncSupport
6) 4. configureDefaultServletHandling
7) 5. addFormatters
8) 6. addInterceptors
9) 7. addResourceHandlers
10) 8. addCorsMappings
11) 9. addViewControllers
12) 10. configureViewResolvers
13) 11. addArgumentResolvers
14) 12. addReturnValueHandlers
15) 13. configureMessageConverters
16) 14. extendMessageConverters
17) 15. configureHandlerExceptionResolvers
18) 16. extendHandlerExceptionResolvers
19) 17. getValidator
20) 18. getMessageCodesResolver

阅读完需:约 13 分钟

为什么要使用WebMvcConfigurer?

WebMvcConfigurer是一个接口,提供很多自定义的拦截器,例如跨域设置、类型转化器等等。可以说此接口为开发者提前想到了很多拦截层面的需求,方便开发者自由选择使用。由于Spring5.0废弃了WebMvcConfigurerAdapter,所以WebMvcConfigurer继承了WebMvcConfigurerAdapter大部分内容。

WebMvcConfigurer方法介绍

常用方法

 //拦截器配置 
void addInterceptors(InterceptorRegistry var1);
//视图跳转控制器 
void addViewControllers(ViewControllerRegistry registry);
//静态资源处理
void addResourceHandlers(ResourceHandlerRegistry registry);
//默认静态资源处理器 
void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
//这里配置视图解析器
void configureViewResolvers(ViewResolverRegistry registry);
//配置内容裁决的一些选项
void configureContentNegotiation(ContentNegotiationConfigurer configurer);
// 解决跨域问题
public void addCorsMappings(CorsRegistry registry) ;
//添加参数处理器
void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) ;
//添加返回值处理器
void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) ;
//添加消息转换器(Object->object)
void configureMessageConverters(List<HttpMessageConverter<?>> converters);
//添加格式转化器(String->Objrct)
void addFormatters(FormatterRegistry registry) ;

1.configurePathMatch

这个用到的比较少,这个是和访问路径有关的。举个例子,比如说PathMatchConfigurer 有个配置是setUseTrailingSlashMatch(),如果设置为true的话(默认为true),后面加个斜杠并不影响路径访问,例如“/user”等同于“/user/”。我们在开发中很少在访问路径上搞事情,所以这个方法如果有需要的请自行研究吧。

 // 用于在HandlerMappings中设置路径的匹配样式
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 配置是否使用通用后缀匹配符(".*")
        // 如果设为true则当设置匹配"/users"时也会对"/users.*"进行匹配
        // 默认值为true
        configurer.setUseSuffixPatternMatch(true);

        // 配置是否匹配url而不考虑是否存在拖尾斜杠
        // 如果设为true则当匹配"/users"时也会匹配"/users/"
        // 默认值为true
        configurer.setUseTrailingSlashMatch(true);

        // 配置是否后缀匹配模式只适用于显示注册的路径拓展
        // 如果设置为true,当传递的路径参数中有特殊含义和作用的"."符号时框架不会对其进行处理
        // 默认值为false
        configurer.setUseRegisteredSuffixPatternMatch(true);

        // 设置一个UrlPathHelper来帮助Spring解析路径
        // 使用这个自定义的UrlPathHelper来覆盖默认的UrlPathHelper
        // 或者是在多个HandlerMappings和MethodNameResolvers中共享UrlPathHelper
        configurer.setUrlPathHelper(new UrlPathHelper());

        // 设置一个PathMatcher用于匹配URL路径
        // 默认的是AntPathMatcher
        configurer.setPathMatcher(new AntPathMatcher());

        // 设置一个路径前缀来匹配controller中的方法,
        // 在Spring初始化阶段,如果第二个参数检测结果返回为true则
        // "/prefix"会作为一个前缀添加到requestMapping的前面,
        // 比如方法上的RequestMapping的注解为"/method",则这个方法
        // 最终的匹配路径是"/prefix/method"
        // 初始化的地方为RequestMappingHandler.getPathPrefix()
        configurer.addPathPrefix("/prefix", (aClass) -> true);
    }

2. configureContentNegotiation

这个东西直译叫做内容协商机制,主要是方便一个请求路径返回多个数据格式。ContentNegotiationConfigurer这个配置里面你会看到MediaType,里面有众多的格式。此方法不在多赘述。

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

        // 设置解析用户请求的内容格式的策略,SpringMVC 默认加载两个该接口的实现类:
        // ServletPathExtensionContentNegotiationStrategy–根据文件扩展名。
        // HeaderContentNegotiationStrategy–根据HTTP Header里的Accept字段。
        configurer.strategies(new ArrayList<>());

        // 设置是否在URL中的path的拓展是否应该被用于作为被要求的内容格式
        // 默认设置为true
        // 如果一个请求的url为"/content.pdf"则会被认为是请求"application/pdf"
        // 同时直接忽略"Accept"头中的格式
        configurer.favorPathExtension(true);

        // 向mediaTypes集合中添加,这里添加的顺序必须要是有序的以方便参数策略工作
        // 在这里注册的所有的拓展名都是反射型文件下载攻击的白名单
        configurer.mediaType("pdf", MediaType.APPLICATION_PDF)
                .mediaType("json", MediaType.APPLICATION_JSON);

        // 将一个hashMap中所有的键值对都作为内容格式加入configurer中
        configurer.mediaTypes(new HashMap<>());

        // 将原来记录的MediaTypes清除并更换为新的HashMap中的内容
        configurer.replaceMediaTypes(new HashMap<>());

        // 设置当无法找到相匹配的类型时是否忽略URL路径中的类型
        // 设置为false则当找不到时会抛出HttpMediaTypeNotAcceptableException
        // 默认设置为true
        configurer.ignoreUnknownPathExtensions(true);

        // 当favorPathExtension被设置的时候,这个方法被用于确认是否只使用被注册
        // 的匹配类型来进行路径解析
        // 默认未设置值
        configurer.useRegisteredExtensionsOnly(true);

        // 设置一个request的parameter是否会被解析为media type
        // 如果要使用的话需要增加一个mediaType(String, MediaType)
        // 默认设置为false
        configurer.favorParameter(true);

        // 设置要用于确定请求的媒体类型的参数的名称
        // 默认值为"format"
        configurer.parameterName("format");

        // 设置时候禁止进行对request头的"Accept"的检查
        // 默认未false
        configurer.ignoreAcceptHeader(false);

        // 设置当请求的类型没有匹配的时候的默认类型,按优先级顺序排序
        // 如果想要支持所有的类型可以在最后使用MediaType.ALL
        // 默认下没有任何设置
        configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.APPLICATION_PDF);

        // 设置当没有任何类型被请求的时候的自定义类型处理策略
        // 默认没有进行设置
        configurer.defaultContentTypeStrategy(new PathExtensionContentNegotiationStrategy());
    }

3. configureAsyncSupport

顾名思义,这是处理异步请求的。只能设置两个值,一个超时时间(毫秒,Tomcat下默认是10000毫秒,即10秒),还有一个是AsyncTaskExecutor,异步任务执行器。

public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

        // 设置一个异步线程池
        // 默认使用SimpleAsyncTaskExecutor
        configurer.setTaskExecutor(new SimpleAsyncTaskExecutor());

        // 设置异步request等待被处理的超时时间
        // 默认的大小为10秒
        configurer.setDefaultTimeout(100);

        // 设置Callable任务的拦截器
        configurer.registerCallableInterceptors(new CallableProcessingInterceptor(){});

        // 设置Callable任务的带有延迟的拦截器
        configurer.registerDeferredResultInterceptors(new DeferredResultProcessingInterceptor() {});
    }

4. configureDefaultServletHandling

这个接口可以实现静态文件可以像Servlet一样被访问。

 public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

        // 激活默认的default servlet
        // 默认的servlet由tomcat提供,一般的名字叫做"default",匹配路径为"/"
        configurer.enable();

        // 设置default servlet的名称
        configurer.enable("default");
    }

5. addFormatters

增加转化器或者格式化器。这边不仅可以把时间转化成你需要时区或者样式。还可以自定义转化器和你数据库做交互,比如传进来userId,经过转化可以拿到user对象。

 //传入的FormatterRegister默认为WebConversionService
    public void addFormatters(FormatterRegistry registry) {

        // 增加一个formatter
        registry.addFormatter(new CurrencyStyleFormatter());

        // 增加一个为指定类型进行类型转换的formatter
        registry.addFormatterForFieldType(String.class, new CurrencyStyleFormatter());

        // 增加一个对注解进行formatter的FormatterFactory
        registry.addFormatterForFieldAnnotation(new AnnotationFormatterFactory<Annotation>() {
            @Override
            public Set<Class<?>> getFieldTypes() {
                return null;
            }

            @Override
            public Printer<?> getPrinter(Annotation annotation, Class<?> fieldType) {
                return null;
            }

            @Override
            public Parser<?> getParser(Annotation annotation, Class<?> fieldType) {
                return null;
            }
        });
    }

6. addInterceptors

盼望着,盼望着,你一个常用的方法来了。这个方法可以自定义写拦截器,并指定拦截路径。

 public void addInterceptors(InterceptorRegistry registry) {

        // 增加一个拦截器
        InterceptorRegistration interceptorRegistration = registry.addInterceptor(new HandlerInterceptor() {});
        // 给拦截器拦截的pathPattern
        interceptorRegistration.addPathPatterns("/pathPattern1", "/pathPattern2");
        // 设置不拦截的pathPattern
        interceptorRegistration.excludePathPatterns("/pathPattern1", "/pathPattern2");
        // 给拦截器设置一个PathMatcher
        interceptorRegistration.pathMatcher(new AntPathMatcher());
        // 给拦截器设置一个顺序权重
        interceptorRegistration.order(1);

        // 增加一个对web请求的拦截器
        registry.addWebRequestInterceptor(new WebRequestInterceptor() {
            @Override
            public void preHandle(WebRequest request) throws Exception { }
            @Override
            public void postHandle(WebRequest request, ModelMap model) throws Exception { }
            @Override
            public void afterCompletion(WebRequest request, Exception ex) throws Exception { }
        });
    }

7. addResourceHandlers

自定义资源映射。这个东西也比较常用,业务场景就是自己的服务器作为文件服务器,不利用第三方的图床,就需要一个虚拟路径映射到我们服务器的地址。值得一提的是,如果你的项目是war包启动,一般都是再Tomcat中配置一下(配置方法请百度);如果是jar包启动(SpringBoot经常用这种方式启动),就可以用到这个方法了。

 public void addResourceHandlers(ResourceHandlerRegistry registry) {

        // 增加一个资源处理器用于针对URL中对静态资源的调用
        // 处理器将会对每一个匹配上的URL进行调用
        // 允许使用诸如"/static/**"或者/css/{filename:\\w+\\.css}
        ResourceHandlerRegistration registration = registry.addResourceHandler("/pathPatterns");
        // 添加一个或多个资源地址用于处理静态资源的请求,多个静态资源库如果
        // 有同样的文件会选择优先级高的
        registration.addResourceLocations("/resourceLocation1", "/resourceLocation2");
        // 设置静态资源处理器的缓存时间
        // 0表示没有缓存,大于0的数表示缓存过期的秒数
        registration.setCachePeriod(0);
        // 设置一个缓存管理器,管理器中的缓存时间设置会覆盖上一步中设置的缓存过期时间
        registration.setCacheControl(CacheControl.empty());
        // 返回一个资源处理器链,设置为true表示使用缓存,推荐为true
        ResourceChainRegistration resourceChainRegistration = registration.resourceChain(true);
        // 给ResourceChain添加一个resolver
        // ResourceResolver用于根据url解析获取静态文件
        resourceChainRegistration.addResolver(new ResourceResolver() {
            @Override
            public Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) {
                return null;
            }
            @Override
            public String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain) {
                return null;
            }
        });
        // 给resourceChain添加一个resourceTransformer
        // resourceTransformer用于给返回的静态文件进行一些自定义修改
        resourceChainRegistration.addTransformer(new ResourceTransformer() {
            @Override
            public Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain) throws IOException {
                return null;
            }
        });

        // 返回是否当前的pathPattern已经被注册
        Boolean has = registry.hasMappingForPattern("/pathPattern");

        // 为当前的资源处理器设置一个优先级
        registry.setOrder(1);
    }

8. addCorsMappings

这个是设置跨域问题的,几乎是每个后台服务器都需要配置的东西。

public void addCorsMappings(CorsRegistry registry) {

        // 允许指定的pathPattern可以进行跨域请求
        CorsRegistration corsRegistration = registry.addMapping("/pathPattern");
        // 设置允许哪些可以进行跨域访问,设置为"*"表示允许所有
        // 默认设置为允许所有
        corsRegistration.allowedOrigins("http://domain1.com", "http://domain2.com");
        // 设置允许的跨域请求动作,设置为"*"表示允许所有
        // 默认设置为允许简单动作,包括GET POST HEAD
        corsRegistration.allowedMethods("GET", "POST");
        // 设置允许的请求头,默认设置为允许所有,即"*"
        corsRegistration.allowedHeaders("Cache-Control", "Content-Language");
        // 设置response的头结构,不支持"*"
        corsRegistration.exposedHeaders("Cache-Control", "Content-Language");
        // 设置浏览器是否需要发送认证信息
        corsRegistration.allowCredentials(true);
        // 设置客户端保存pre-flight request缓存的时间
        // pre-flight request 预检请求
        corsRegistration.maxAge(1);
    }

9. addViewControllers

这个方法可以实现,一个路径自动跳转到一个页面。不过现在多为前后端分离的项目,是不是可以把跳转路由的问题直接扔给前端。

 public void addViewControllers(ViewControllerRegistry registry) {
        // 为指定的url设置一个viewController
        ViewControllerRegistration viewControllerRegistration
                = registry.addViewController("/admin/**");
        // 为url设置返回值,默认值为200
        viewControllerRegistration.setStatusCode(HttpStatus.valueOf(404));
        // 设置真实有效的view名,如果不设置默认为null
        viewControllerRegistration.setViewName("/foo/bar");

        // 设置原url和跳转到的url
        RedirectViewControllerRegistration redirectViewControllerRegistration
                = registry.addRedirectViewController("/urlPath", "/redirectUrl");
        // 设置跳转url的状态码,默认为302
        redirectViewControllerRegistration.setStatusCode(HttpStatus.valueOf(302));
        // 是否将以斜杠("/")开头的定重定向URL解释为相对于当前ServletContext
        // 默认值为true
        redirectViewControllerRegistration.setContextRelative(true);
        //是否传播当前请求的查询参数,默认值为false
        redirectViewControllerRegistration.setKeepQueryParams(true);

        // 对于设置的url将直接返回状态码而不进行任何body的渲染
        registry.addStatusController("/urlPath", HttpStatus.valueOf(404));

        // 设置当前viewController的优先值,默认为1
        // 注解的Controller的优先值为0
        registry.setOrder(1);
    }

10. configureViewResolvers

public void configureViewResolvers(ViewResolverRegistry registry) {

        // 返回是否当前有resolver被注册
         boolean has = registry.hasRegistrations();

         // 启用contentNegotiatingViewResolver来前置所有其他配置的视图
         // 解析器,并根据客户端请求的媒体类型在所有选择的视图中进行选择
         registry.enableContentNegotiation();

         // 启用contentNegotiatingViewResolver来前置所有其他配置的视图
         // 解析器,并根据客户端请求的媒体类型在所有选择的视图中进行选择
         registry.enableContentNegotiation(true);
    }

11. addArgumentResolvers

 public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {

        // 添加一个方法参数处理器
        resolvers.add(new HandlerMethodArgumentResolver() {
            @Override
            public boolean supportsParameter(MethodParameter parameter) {
                return false;
            }

            @Override
            public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
                return null;
            }
        });
    }

12. addReturnValueHandlers

public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {

        // 添加一个方法返回值处理器
        handlers.add(new HandlerMethodReturnValueHandler() {
            @Override
            public boolean supportsReturnType(MethodParameter returnType) {
                return false;
            }

            @Override
            public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

            }
        });
    }

13. configureMessageConverters

 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        
        // 添加一个http消息转换器
        converters.add(new ByteArrayHttpMessageConverter());
    }

14. extendMessageConverters

    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

        // 用于扩展或修改已配置的转换器列表的钩子
        converters.add(1, new ByteArrayHttpMessageConverter());
    }

15. configureHandlerExceptionResolvers

public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {

        // 添加一个处理异常的解析器
        resolvers.add(new DefaultHandlerExceptionResolver());
    }

16. extendHandlerExceptionResolvers

public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {

        // 用于拓展活修改已经加入配置中的解析器
        resolvers.add(1, new DefaultHandlerExceptionResolver());
    }

17. getValidator

  public Validator getValidator() {
        return null;
    }

18. getMessageCodesResolver

public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

1 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 297点赞 621887浏览

随机文章
Kotlin-表达式—变量与常量(十一)
5年前
RBAC用户角色权限设计方案
5年前
SpringMVC—PathPattern路径模式
3年前
SpringMVC笔记9—文件上传与下载
5年前
Java—I/O模型与同步、异步、阻塞、非阻塞
3年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1973 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 621887 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付