SpringBoot - WebMvcConfigurer的作用是什么?

写在前面

WebMvcConfigurer是一个接口,用于配置全局的SpringMVC的相关属性,采用JAVABEAN的方式来代替传统的XML配置文件,提供了跨域设置、静态资源处理器、类型转化器、自定义拦截器、页面跳转等能力。
WebMvcConfigurer 在 Spring Boot 2.x 中官方建议使用该接口来实现自定义配置。所以,Spring Boot 2.x 中,自定义 SpringMVC 配置可以通过实现 WebMvcConfigurer 接口来完成。

源码说明

public interface WebMvcConfigurer {
	//  配置路径匹配规则
    default void configurePathMatch(PathMatchConfigurer configurer) { }

	// 内容协商
    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) { }
	
	// 异步调用支持
    default void configureAsyncSupport(AsyncSupportConfigurer configurer) { }

	// 静态资源默认处理器
    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { }

	// 格式化器, 可以把时间转化成你需要时区或者格式,还可以将对象A转换为对象B。
    default void addFormatters(FormatterRegistry registry) { }

	// 请求拦截器
    default void addInterceptors(InterceptorRegistry registry) { }

	// 静态资源映射器
    default void addResourceHandlers(ResourceHandlerRegistry registry) { }

	// 跨域设置
    default void addCorsMappings(CorsRegistry registry) { }

	// 视图控制器
    default void addViewControllers(ViewControllerRegistry registry) { }

	// 视图解析器
    default void configureViewResolvers(ViewResolverRegistry registry) { }

	// 参数处理器
    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { }

	// 返回值处理器
    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) { }

	// 信息转化器
    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { }

	// 信息转化器扩展
    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) { }

	// 异常处理器
    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { }

	// 异常处理器扩展
    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

常用示例

① 配置路径匹配规则
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
	// 是否使用尾斜杠匹配, 默认为TRUE。TRUE, 表示"/hello"和"/hello/"都能匹配。
	configurer.setUseTrailingSlashMatch(false);
 
	// 为所有的接口添加统一前缀。如果的URL为: "/hello", 则转换为: "/api/hello"
	configurer.addPathPrefix("api", c -> c.isAnnotationPresent(RestController.class));
 
	// UrlPathHelper是一个处理URL地址的帮助类, 自带了一些优化URL的方法;
	// 如:getSanitizedPath,就是将"//"自动转换为"/", 所以当输入为"//"也是没有问题的,
	UrlPathHelper urlPathHelper = new UrlPathHelper();
	configurer.setUrlPathHelper(urlPathHelper);
}
② 配置静态资源映射器

用于自定义静态资源的映射目录。

// addResourceHandler:用于设置对外暴露的访问路径
// addResourceLocations:用于映射内部文件放置的目录,需要以“/”结尾

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    /** 本地文件上传路径 */
    // 对外暴露的访问路径
    registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
    // 映射内部文件放置的目录,以“/”结尾
            .addResourceLocations("file:" + ServicexConfig.getProfile() + "/");

    /** swagger配置 */
    registry.addResourceHandler("/swagger-ui/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
③ 配置请求拦截器

可以设置多个拦截器,如对特定的URL设定处理规则、打印处理用户请求耗费的时间、定义防止重复提交等功能。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    // 增加一个拦截器,对请求做一些自定义处理
    registry.addInterceptor(new HandlerInterceptor() {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Object user = request.getSession().getAttribute("loginUser");
            if (user == null) {   //未登陆,返回登陆页面
                request.setAttribute("msg", "没有权限请先登陆");
                request.getRequestDispatcher("/index.html").forward(request, response);
                return false;
            } else {  //已登陆,放行请求
                return true;
            }
        }
    })
    // 设置拦截器的过滤路径规则:只拦截/admin/形式的请求
    .addPathPatterns("/admin/**")
    // 设置不需要拦截的过滤规则:不拦截/admin/login请求
    .excludePathPatterns("/admin/login");
}
④ 跨域设置
方法一:
@Override
public void addCorsMappings(CorsRegistry registry) {
    // 设置允许跨域的路径
    registry.addMapping("/**")
            // 设置允许跨域请求的域名
            .allowedOrigins("*")
            // 是否允许证书
            .allowCredentials(true)
            // 设置允许的方法
            .allowedMethods("GET", "POST", "DELETE", "PUT")
            // 设置允许的header属性
            .allowedHeaders("*")
            // 跨域允许时间
            .maxAge(3600);
}
方法二:
/**
 * 跨域配置
 */
@Bean
public CorsFilter corsFilter() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    // 设置访问源地址
    config.addAllowedOriginPattern("*");
    // 设置访问源请求头
    config.addAllowedHeader("*");
    // 设置访问源请求方法
    config.addAllowedMethod("*");
    // 有效期 1800秒
    config.setMaxAge(1800L);
    // 添加映射路径,拦截一切请求
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    // 返回新的CorsFilter
    return new CorsFilter(source);
}
⑤ 视图控制器

用于将请求的URL进行处理。

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    // 如果请求为:/admin,则重定向到/login
    registry.addRedirectViewController("/admin", "/login");
    // 如果请求为:/admin/delete,则返回500状态
    registry.addStatusController("/admin/delete", HttpStatus.INTERNAL_SERVER_ERROR);
	// 如果请求URL为:/hello,则直接跳转到hello页面
	registry.addViewController("/hello").setViewName("hello");
}
⑥ 内容协商

用于将一个URL直接跳转到页面。

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    // 自定义策略
    configurer.favorPathExtension(true)// 是否通过请求Url的扩展名来决定mediaType,默认true
            .ignoreAcceptHeader(true)// 不检查Accept请求头
            .parameterName("mediaType")
            .defaultContentType(MediaType.TEXT_HTML)// 设置默认的MediaType
            .mediaType("html", MediaType.TEXT_HTML)// 请求以.html结尾的会被当成MediaType.TEXT_HTML
            .mediaType("json", MediaType.APPLICATION_JSON)// 请求以.json结尾的会被当成MediaType.APPLICATION_JSON
            .mediaType("xml", MediaType.APPLICATION_ATOM_XML);// 请求以.xml结尾的会被当成MediaType.APPLICATION_ATOM_XML
}
⑦ 信息转化器扩展

自定义FASTJSON为JSON消息的转换器,完成的功能如下:
1、请求返回体使用FASTJSON来序列化;
2、配置如果字段类型为Date,输出为"yyyy-MM-dd HH:mm:ss"格式;
3、配置允许输出值为null的字段;
4、配置字符类型字段,如果为null,输出为"",而非null;
5、配置把Long类型的数据序列化成JSON后传给前端,解决前端可能会出现精度丢失的情况。

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    //1、首先定义一个convert消息转换对象
    FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

    //2、定义支持的mediaType类型,处理中文乱码的相关问题
    List<MediaType> mediaTypes = new ArrayList<>();
    mediaTypes.add(MediaType.APPLICATION_JSON);      // 返回JSON格式
    mediaTypes.add(MediaType.APPLICATION_JSON_UTF8); // 处理输出中文乱码
    mediaTypes.add(MediaType.TEXT_HTML);
    mediaTypes.add(new MediaType("application", "xml"));
    mediaTypes.add(new MediaType("text", "xml"));
    mediaTypes.add(new MediaType("application", "*+xml"));
    mediaTypes.add(MediaType.ALL);
    converter.setSupportedMediaTypes(mediaTypes);

    //3. 创建配置类
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setCharset(Charset.forName("UTF-8")); // 全局编码
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); // 全局时间格式化

    //4. 格式化返回内容
    SerializerFeature[] serializerFeatures = new SerializerFeature[]{
            SerializerFeature.PrettyFormat,             // 格式化
            SerializerFeature.WriteMapNullValue,        // 输出空值
            SerializerFeature.WriteNullListAsEmpty,     // List字段如果为null,输出为[],而非null
            SerializerFeature.WriteDateUseDateFormat,   // 日期格式化
            SerializerFeature.WriteNullStringAsEmpty,   // 字符类型字段如果为null,输出为"",而非null
            SerializerFeature.WriteNullBooleanAsFalse,  // Boolean字段如果为null,输出为false,而非null
            SerializerFeature.DisableCircularReferenceDetect, //消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
            SerializerFeature.WriteNullNumberAsZero     //数字类型如果为null,输出为0,而非null
    };
    fastJsonConfig.setSerializerFeatures(serializerFeatures);

    //5. 配置Java类型对应的序列化类,序列换成json时, 将所有的long变成string,解决Long转json精度丢失的问题,因为js中得数字类型不能包含所有的java long值
    SerializeConfig serializeConfig = SerializeConfig.globalInstance;
    serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
    serializeConfig.put(Long.class, ToStringSerializer.instance);
    serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
    fastJsonConfig.setSerializeConfig(serializeConfig);

    converter.setFastJsonConfig(fastJsonConfig);
    converters.add(0,converter);
}

其他方式

A. WebMvcConfigurerAdapter
B. WebMvcConfigurationSupport
C. @EnableWebMvc

A. WebMvcConfigurerAdapter

在 Spring Boot 1.x 中我们自定义 SpringMVC 时继承的一个抽象类,这个抽象类本身是实现了 WebMvcConfigurer 接口。从 Spring5 开始,官方建议直接实现 WebMvcConfigurer 接口,而不是继承 WebMvcConfigurerAdapter。

B. WebMvcConfigurationSupport

在纯 Java 配置的 SSM 环境中,如果我们要自定义 SpringMVC 配置,有两种办法:
第一种就是直接继承自 WebMvcConfigurationSupport 来完成 SpringMVC 配置;
还有一种方案就是实现 WebMvcConfigurer 接口来完成自定义 SpringMVC 配置,如果使用第二种方式,则需要给 SpringMVC 的配置类上额外添加 @EnableWebMvc 注解,表示启用 WebMvcConfigurationSupport,这样配置才会生效。

C. @EnableWebMvc

如果在 Spring Boot 中使用了 @EnableWebMvc 注解,就会导致 Spring Boot 中默认的 SpringMVC 自动化配置失效,所以不建议使用该方式。

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
springboot学习笔记 spring基础 Spring概述 Spring的简史 xml配置 注解配置 java配置 Spring概述 Spring的模块 核心容器CoreContainer Spring-Core Spring-Beans Spring-Context Spring-Context-Support Spring-Expression AOP Spring-AOP Spring-Aspects Messaging Spring-Messaging WEB Spring-Web Spring-Webmvc Spring-WebSocket Spring-Webmvc-Portlet 数据访问/集成(DataAccess/Intefration) Spring-JDBC Spring-TX Spring-ORM Spring-OXM Spring-JMS Spring的生态 Spring Boot Spring XD Spring Cloud Spring Data Spring Integration Spring Batch Spring Security Spring HATEOAS Spring Social Spring AMQP Spring Mobile Spring for Android Spring Web Flow Spring Web Services Spring LDAP Spring Session Spring项目快速搭建 Maven简介 Maven安装 Maven的pom.xml dependencies dependency 变量定义 编译插件 Spring项目的搭建 Spring Tool Suite https://spring.io/tools/sts/all IntelliJ IDEA NetBeans https://netbeans.org/downloads/ Spring基础配置 依赖注入 声明Bean的注解 @Component组件,没有明确的角色 @Service在业务逻辑层(service层) @Repository在数据访问层(dao层) @Controller在展现层(MVCSpringMVC) 注入Bean的注解 @Autowired:Spring提供的注解 @Inject:JSR-330提供的注解 @Resource:JSR-250提供的注解 Java配置 @Configuration声明当前类是一个配置类 @Bean注解在方法上,声明当前方法的返回值为一个Bean AOP @Aspect 声明是一个切面 拦截规则@After @Before @Around PointCut JoinPoint Spring常用配置 Bean的Scope Singleton Prototype Request Session GlobalSession SpringEL和资源调用 注入普通字符 注入操作系统属性 注入表达式云算结果 注入其他Bean的属性 注入文件内容 注入网址内容 注入属性文件 Bean的初始化和销毁 Java配置方式 注解方式 Profile @Profile 通过设定jvm的spring.profiles.active参数 web项目设置在Servlet的context parameter中 事件Application Event 自定义事件,集成ApplicationEvent 定义事件监听器,实现ApplicationListener 使用容器发布事件 Spring高级话题 Spring Aware BeanNameAware BeanFactoryAware
Spring Boot提供了多种方法来解决跨域问题,其中之一是通过实现WebMvcConfigurer接口来自定义处理器、拦截器、视图解析器、转换器以及设置跨域等。 具体而言,可以通过实现WebMvcConfigurer接口来配置跨域。其中,configureDefaultServletHandling方法是用来配置默认的Servlet处理,可以使用DefaultServletHandlerConfigurer的enable方法来开启默认的Servlet处理器,这样可以处理静态资源请求。另外,也可以通过enable方法指定默认的Servlet名称。 除了实现WebMvcConfigurer接口,还可以继承WebMvcConfigurationSupport类来实现定制化的配置。这个类提供了更加灵活的配置选项。 总结起来,通过实现WebMvcConfigurer接口或继承WebMvcConfigurationSupport类可以在Spring Boot中实现跨域功能。具体的配置方法可以根据实际需求选择适合的方式来进行配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot配置接口:WebMvcConfigurer](https://blog.csdn.net/JokerLJG/article/details/123224002)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [【springboot】--跨域问题及webMvcConfigurer介绍](https://blog.csdn.net/xunmengyou1990/article/details/124557829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值