赞
踩
WebMvcConfigurer 是一个接口,用于配置全局的SpringMVC的相关属性,采用JAVABean的方式来代替传统的XML配置文件,提供了跨域设置、静态资源处理器、类型转化器、自定义拦截器、页面跳转等能力。
WebMvcConfigurationSupport是webmvc的配置类,如果在springboot项目中,有配置类继承了WebMvcConfigurationSupport,那么webmvc的自动配置类WebMvcAutoConfiguration就会失效。
官方推荐直接实现WebMvcConfigurer 或者 继承WebMvcConfigurationSupport,
方式一:实现WebMvcConfigurer接口(推荐),方式二:继承WebMvcConfigurationSupport(/səˈpɔːt/)类。
- package com.syh.pdd.config.web;
-
- import com.fasterxml.jackson.databind.DeserializationFeature;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.http.converter.HttpMessageConverter;
- import org.springframework.http.converter.StringHttpMessageConverter;
- import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
- import org.springframework.web.method.support.HandlerMethodArgumentResolver;
- import org.springframework.web.servlet.config.annotation.*;
-
- import java.nio.charset.Charset;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.List;
-
- @Configuration
- public class WebConfig implements WebMvcConfigurer {
-
- // 用户头像
- @Value("${file.userImage.writePath}")
- private String userImageWritePath;
- @Value("${file.userImage.readPath}")
- private String userImageReadPath;
-
- /**
- * 映射文件路径配置
- */
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
-
-
- registry.addResourceHandler("/webjars/**")
- .addResourceLocations("classpath:/META-INF/resources/webjars/");
-
- registry.addResourceHandler("BJTPReadpath")
- .addResourceLocations("file:"+ "BJTPSavepath");
-
- // 浏览器测试图片回显路径: http://IP:8080/file/ewm/Img/2023/10/12/图片名称.jpg
- registry
- // 图片回显路径
- .addResourceHandler("file/ewm/Img/**")
- // 图片存放路径
- .addResourceLocations("file:D:/file/ewm/Img/");
- }
- }
-
- /**
- * 跨域配置添加
- */
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- // 设置允许跨域的路径
- registry.addMapping("/**")
- // 设置允许跨域请求的域名
- // .allowedOrigins("*")
- .allowedOriginPatterns("*")
- // 是否允许证书 不再默认开启
- .allowCredentials(true)
- // 设置允许的方法
- .allowedMethods("*")
- // 跨域允许时间
- .maxAge(3600);
- }
-
- //解决中文乱码问题
- @Override
- public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
- //解决中文乱码
- converters.add(responseBodyConverter());
- //解决 添加解决中文乱码后 上述配置之后,返回json数据直接报错 500:no convertter for return value of type
- converters.add(messageConverter());
- }
- @Bean
- public HttpMessageConverter<String> responseBodyConverter(){
- StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
- return converter;
- }
- @Bean
- public MappingJackson2HttpMessageConverter messageConverter() {
- MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
- converter.setObjectMapper(getObjectMapper());
- return converter;
- }
- @Bean
- public ObjectMapper getObjectMapper() {
- return new ObjectMapper();
- }
-
- /**
- * 格式化返回的内容
- * https://my.oschina.net/u/3681868/blog/3075150
- * */
- @Override
- public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
- MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
- ObjectMapper objectMapper = converter.getObjectMapper();
- // 时间格式化
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
- // 设置格式化内容
- converter.setObjectMapper(objectMapper);
- converters.add(0, converter);
- }
-
- /**
- * 添加Web项目的拦截器
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //放行路径
- List<String> jwtExcludePatterns = new ArrayList();
- // 登录接口放行
- jwtExcludePatterns.add("/api/user/login");
- // 验证码放行
- jwtExcludePatterns.add("/api/user/getVerify/**");
- // 前端更换头像请求,没有走拦截器,此处放行
- jwtExcludePatterns.add("/api/user/updatePicture");
- // 对所有api开头的访问路径,都通过MyInterceptor拦截器进行拦截,MyInterceptor代码在下面
- registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**")
- .excludePathPatterns(jwtExcludePatterns);
- }
-
- /*解析器 使用方法在文章末尾*/
- @Override
- public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
- WebMvcConfigurer.super.addArgumentResolvers(resolvers);
- }
- }
什么是拦截器:在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略
为什么需要拦截器:在做身份认证或者是进行日志的记录时,我们需要通过拦截器达到我们的目的。最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情
- <dependency>
- <groupId>net.minidev</groupId>
- <artifactId>json-smart</artifactId>
- </dependency>
- <dependency>
- <groupId>com.vaadin.external.google</groupId>
- <artifactId>android-json</artifactId>
- <version>0.0.20131108.vaadin1</version>
- <scope>compile</scope>
- </dependency>
- package com.syh.pdd.config.web;
-
- import com.syh.pdd.Utils.token.JwtUtil;
- import lombok.extern.slf4j.Slf4j;
- import net.minidev.json.JSONObject;
- import org.springframework.http.HttpMethod;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- /**
- * 自定义拦截器类token认证
- * 注意:可以实现多个拦截器,只需要继续实现HandlerInterceptor即可
- */
- @Slf4j
- public class MyInterceptor implements HandlerInterceptor {
- /**
- * 访问控制器方法前执行
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
- // ==========!!!!!!注意注意注意 注意注意 注意注意 ========================
- /*
- * 前端在请求的时候会发送一个OPTION请求来验证本次请求是否安全,
- * 但是springboot的拦截器会拦截所有请求。因为第一次是OPTION没有携带JWT,所以验证失败
- * */
- if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
- return true;
- }
- // 获取token
- String token = request.getHeader("token");
- // 校验token
- if (JwtUtil.checkToken(token)) {
- log.info(request.getRequestURL() + ">>>" +
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "通过token验证");
- return true; // 放行
- } else{
- //设置response状态
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application/json; charset=utf-8");
- //设置失败响应数据
- JSONObject res = new JSONObject();
- res.put("status","101010");
- res.put("msg","登录过期,请重新登录");
- PrintWriter out = null ;
- out = response.getWriter();
- out.write(res.toString());
- out.flush();
- out.close();
- return false; // 拦截
- }
- }
-
- /**
- * 访问控制器方法后执行
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
- }
-
- /**
- * postHandle方法执行完成后执行,一般用于释放资源
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
- }
- }
-
- /**
- * Web配置类
- */
- @Configuration
- public class WebConfig implements WebMvcConfigurer {
- /**
- * 添加Web项目的拦截器
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //放行路径
- List<String> jwtExcludePatterns = new ArrayList();
- // 登录接口放行
- jwtExcludePatterns.add("/system/user/login");
- // 验证码放行
- jwtExcludePatterns.add("/system/user/getVerify/**");
- // 对所有图片资源放行
- jwtExcludePatterns.add("/Project/saveFile/**");
-
- // 拦截路径:对所有访问路径,都通过MyInterceptor类型的拦截器进行拦截
- registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
- .excludePathPatterns(jwtExcludePatterns);
-
- }
- }
- package com.hssmart.config.web;
-
- import com.fasterxml.jackson.databind.DeserializationFeature;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.http.converter.HttpMessageConverter;
- import org.springframework.http.converter.StringHttpMessageConverter;
- import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
- import org.springframework.web.servlet.config.annotation.CorsRegistry;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-
- import java.nio.charset.Charset;
- import java.text.SimpleDateFormat;
- import java.util.List;
-
- @Configuration
- public class WebConfig extends WebMvcConfigurationSupport{
-
- // 自定义一个拦截器
- @Autowired
- UserArgumentResolver userArgumentResolver;
-
-
- /**
- * 映射文件路径配置
- */
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
-
- registry.addResourceHandler("swagger-ui.html")
- .addResourceLocations("classpath:/META-INF/resources/");
-
- registry.addResourceHandler("/webjars/**")
- .addResourceLocations("classpath:/META-INF/resources/webjars/");
-
-
- /**
- * 说明:增加虚拟路径(经过本人测试:在此处配置的虚拟路径,用springboot内置的tomcat时有效,
- 用外部的tomcat也有效;所以用到外部的tomcat时不需在tomcat/config下的相应文件配置虚拟路径了,阿里云linux也没问题)
- */
- //registry.addResourceHandler("/pic/**").addResourceLocations("file:E:/pic/");
-
-
-
- registry.addResourceHandler("BJTPReadpath")
- .addResourceLocations("file:"+ "BJTPSavepath");
-
-
- //阿里云(映射路径去除盘符)
- //registry.addResourceHandler("/ueditor/image/**").addResourceLocations("/upload/image/");
- //registry.addResourceHandler("/ueditor/video/**").addResourceLocations("/upload/video/");
-
- //用户图片路径
- registry.addResourceHandler("/Project/saveFile/user/userImg/**"(网络路径,其实可以任意定义))
- .addResourceLocations("file:D:/JAVA/Project/saveFile/user/userImg/"(储存路径));
-
- super.addResourceHandlers(registry);
- }
-
-
- /**
- * 跨域配置添加
- */
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- // 设置允许跨域的路径
- registry.addMapping("/**")
- // 设置允许跨域请求的域名
- .allowedOrigins("*")
- // 是否允许证书 不再默认开启
- .allowCredentials(true)
- // 设置允许的方法 springboot较高版本不能使用*号
- // .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
- .allowedMethods("*")
- // 跨域允许时间
- .maxAge(3600);
- }
-
-
- //解决中文乱码问题
- @Override
- public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
- super.configureMessageConverters(converters);
- //解决中文乱码
- converters.add(responseBodyConverter());
- //解决 添加解决中文乱码后 上述配置之后,返回json数据直接报错 500:no convertter for return value of type
- converters.add(messageConverter());
- }
-
-
- @Bean
- public HttpMessageConverter<String> responseBodyConverter(){
- StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
- return converter;
- }
- @Bean
- public MappingJackson2HttpMessageConverter messageConverter() {
- MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
- converter.setObjectMapper(getObjectMapper());
- return converter;
- }
- @Bean
- public ObjectMapper getObjectMapper() {
- return new ObjectMapper();
- }
-
-
- /**
- * 格式化返回的内容(格式转换器)
- * https://my.oschina.net/u/3681868/blog/3075150
- * */
- @Override
- public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
- MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
- ObjectMapper objectMapper = converter.getObjectMapper();
- // 生成JSON时,将所有Long转换成String
- //SimpleModule simpleModule = new SimpleModule();
- //simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
- //simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
- //objectMapper.registerModule(simpleModule);
- // 时间格式化
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
- // 设置格式化内容
- converter.setObjectMapper(objectMapper);
- converters.add(0, converter);
- }
-
- /**
- * 解析器,该方法可实现可不实现,需要自定义。作用在调用Controller方法的参数传入之前,有返回值
- */
- @Override
- public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
- // userArgumentResolver该类对Controller传入的参数做了具体处理
- resolvers.add(userArgumentResolver);
- }
-
-
- }
-
(1)自定义解析器
- @Configuration
- public class UserArgumentResolver implements HandlerMethodArgumentResolver {
-
- @Autowired
- Userservice userservice;
-
- // 此方法返回true,下面的参数才会执行
- @Override
- public boolean supportsParameter(MethodParameter methodParameter) {
- // 获取传入参数的类型
- Class<?> type = methodParameter.getParameterType();
- // 如果参数类型有为User类的则符合,进入resolveArgument方法
- if (UserPojo.class == type) {
- return true;
- }
- return false;
- }
-
- // 该方法为拦截方法,将结果返回给controller
- @Override
- public Object resolveArgument(MethodParameter methodParameter,
- ModelAndViewContainer modelAndViewContainer,
- NativeWebRequest nativeWebRequest,
- WebDataBinderFactory webDataBinderFactory) throws Exception {
-
- HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
- HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
-
- String userTick = CookieUtil.getCookieValue(request, "userTicket");
- if (StringUtils.isBlank(userTick)) {
- return null;
- }
- UserPojo userPojo = userservice.getUserByCookie(userTick, request, response);
- if (userPojo == null) {
- return null;
- }
- return userPojo;
- }
- }
(2)在controller中使用
- @GetMapping("goods")
- public Result showGoods(UserPojo user){
- // 注意:这里的User参数不是由前端传入的,而是由addArgumentResolvers方法处理之后传进来的
- log.info(user.toString());
- // 根据处理之后传入的参数判断是否登录
- if (user == null)
- return Result.error();
- return Result.ok();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。