ToB企服应用市场:ToB评测及商务社交产业平台
标题:
WebMvcConfigurer和WebMvcConfigurationSupport(MVC配置)
[打印本页]
作者:
农民
时间:
2024-6-18 17:47
标题:
WebMvcConfigurer和WebMvcConfigurationSupport(MVC配置)
一:根本介绍
WebMvcConfigurer是接口,用于配置全局的SpringMVC的相关属性,采用JAVABean的方式来取代传统的XML配置文件,提供了跨域设置、静态资源处理器、类型转化器、自定义拦截器、页面跳转等能力。
WebMvcConfigurationSupport是webmvc的配置类,如果在springboot项目中,有配置类继续了WebMvcConfigurationSupport,那么webmvc的自动配置类WebMvcAutoConfiguration就会失效。
两者都是Spring MVC中的组件,详细的区别如下:
1.实现方式差异
WebMvcConfigurer:是一个接口,它提供了多个回调方法,可以用于自定义Spring MVC的配置(如消息转换器、拦截器等)。我们在使用时只必要实现该接口,重写此中的方法即可。
WebMvcConfigurationSupport:是一个抽象类,它也提供了多个回调方法,用于自定义Spring MVC的配置,但是必要继续该类并重写此中的方法。
2.作用差异
WebMvcConfigurer:
主要用于添加或修改Spring MVC的配置,如添加拦截器,自定义消息转换器等。
WebMvcConfigurationSupport:
主要用于完全自定义Spring MVC的配置,如果我们必要对Spring MVC的配置进行大量的自定义,可以选择继续该类并重写此中的方法。但是必要留意的是,继续该类会覆盖Spring MVC的部分默认配置。因此,当我们只必要对部分配置进行自定义时,应该使用WebMvcConfigurer。
3.继续关系差异
WebMvcConfigurer:
没有继续关系,我们只必要实现该接口即可使用。
WebMvcConfigurationSupport:
是一个抽象类,必要继续后才能使用。
4.总结
在日常开发中推荐优先使用WebMvcConfigurer的方式(官方推荐),因为简朴方便,也没有特殊复杂的定制需求;若我们项目中使用的MVC存在着更加复杂的配置需求推荐WebMvcConfigurationSupport,通过继续此类,我们可以说对官方的MVC代码进行重写利用,但是因为其配置量较大,实现比较复杂,因此在日常开发中使用WebMvcConfigurationSupport并不常见。
二:配置摘要
常用自定义配置如下:
1.addInterceptors(拦截器配置)
2.addCorsMappings(全局跨域处理)
3.addViewControllers(注册视图控制器)(可以让地址对应资源文件,如html文件)
4.addResourceHandlers(配置静态资源处理)(可以在客户端直接访问静态资源信息)
三:Spring和SpringBoot中配置步骤区别
1.Spring中配置WebMvcConfigurer方式:
①创建一个Java 类,实现WebMvcConfigurer接口
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
// 自定义配置代码
}
复制代码
②注入到Bean容器里
@Configuration
public class AppConfig {
@Bean
public MyWebMvcConfig myWebMvcConfig() {
return new MyWebMvcConfig();
}
}
复制代码
2.SpringBoot中配置WebMvcConfigurer方式:(这种方式简朴)
创建一个 Java 类,并实现WebMvcConfigurer接口
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
// 自定义配置代码
}
复制代码
四:拦截器(addInterceptors)
在SpringBoot中,可以使用拦截器来对哀求进行统一的预处理或后处理。拦截器用于日志记录、权限检查、性能监控、事务控制等方面。SpringBoot中实现拦截器,起主要创建一个实现HandlerInterceptor接口的拦截器类。该接口定义了三个方法,分别是preHandle、postHandle和afterCompletion,用于在哀求处理前、哀求处理后和哀求完成后进行处理。
1.HandlerInterceptor接口方法详解:
①preHandler
在哀求处理之前被调用。该方法在Interceptor类中开始实行,用来进行一些前置初始化利用或是对当前哀求做预处理,也可以进行一些判断来决定哀求是否要继续进行下去。该方法的返回值是Boolean类型,当它返回false时,表示哀求竣事,后续的Interceptor和Controller都不会再实行;当它返回为true时会继续调用下一个Interceptor的preHandle方法,如果已经是末了一个Interceptor的时候就会调用当前哀求的Controller方法。
②postHandler
在哀求处理完成之后调用。也就是Controller方法调用之后实行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行利用。
③afterCompletion
在整个哀求竣过后调用。就是对应的Interceptor类的postHandler方法返回true时才实行。就是说该方法将在整个哀求竣事之后,
也就是在DispatcherServlet渲染了对应的视图之后实行。此方法主要用来进行资源清理。
注:官方其实不建议我们非要把3个方法都重写,我们只要对必要的方法重写接口,就好比大部分项目只必要重写preHandler方法
2.InterceptorRegistry类方法介绍:
①addInterceptor
该方法用于向拦截器链中添加一个拦截器。interceptor参数为待添加的拦截器对象,可以是自定义的拦截器类或Spring提供的预置拦截器。返回值为InterceptorRegistration对象,用于进一步配置该拦截器的属性。
②addWebRequestInterceptor
该方法用于向WebRequest拦截器链中添加一个拦截器。interceptor参数为待添加的拦截器对象,可以是自定义的WebRequestInterceptor类或者Spring提供的预置拦截器。也是返回值为InterceptorRegistration对象,用于进一步配置该拦截器的属性。
③getInterceptors
用于获取当前已经添加到拦截器链中的所有拦截器,返回值为List<HandlerInterceptor>对象,表示拦截器列表。
3.InterceptorRegistration类方法介绍:
①order
该方法用于设置拦截器的实行顺序,即在拦截器链中的位置。order参数为一个整数,值越小表示越先实行。
②addPathPatterns
该方法用于设置必要拦截的哀求路径模式,即满足哪些哀求路径时才会触发该拦截器。若"/**"则拦截全部;传入的参数是一个字符串数组,包含多个Ant风格的路径模式,例如"/api/**"、"/user/*"等。
③excludePathPatterns
该方法用于设置不必要拦截的哀求路径模式,即满足哪些哀求路径时不会触发该拦截器。一样平常不拦截,如登录或者Swagger等传入的参数是一个字符串数组,包含多个Ant风格的路径模式,例如 "/api/login"、"/user/login"等。
④pathMatcher
该方法用于设置该拦截器所使用的PathMatcher实例,从而可以自定义路径匹配逻辑。
注:拦截的路径或者放行的路径是以Controller开始的,如我们在application.yml配置的地址前缀则不包含
五:跨域(addCorsMappings)
参考:SpringBoot办理跨域的三种方式
1.CorsRegistry类方法介绍:
①addMapping
该方法用于添加允许跨域访问的路径,String类型,若存在多个路径则必要在CorsRegistry里配置多个
2.CorsRegistration类方法介绍:
CorsRegistration是CorsRegistry的辅助类,使用它可以对单个跨域哀求进行更细粒度的配置。
①allowedOrigins(低版本使用,但是现在高版本也支持)
设置允许跨域哀求的来源URL。该方法担当多个参数,每个参数为一个允许的来源URL。或者设置"*"
②allowedOriginPatterns(一样平常使用这种方式)
设置允许跨域哀求的来源URL的模式。该方法担当多个参数,每个参数为一个允许的来源URL模式。或者设置"*"
③allowCredentials
设置是否允许跨域哀求携带凭据信息。默认环境下,浏览器不会向跨域哀求发送Cookie等凭据信息。如果希望携带凭据信息,则必要将allowCredentials方法设置为true。
④allowedMethods
设置允许跨域哀求的HTTP方法。该方法担当多个参数,每个参数为一种允许的HTTP哀求方式。
⑤allowedHeaders
设置允许哀求携带的HTTP头信息。该方法担当多个参数,每个参数为一种允许的HTTP头信息。(放行哪些哀求头部信息)
⑥exposedHeaders
设置响应头信息,这些信息允许客户端访问。该方法担当多个参数,每个参数为一种允许的响应头信息。(暴露哪些响应头信息)
⑦combine
将当前CorsRegistration对象与另一个CorsConfiguration对象归并,返回归并后的CorsConfiguration对象。可以使用该方法将多个CorsRegistration对象的配置归并到同一个CorsConfiguration对象中。
⑧maxAge
设置响应的缓存时间,单位为秒,默认30分钟。
例如,当设置maxAge为3600时,如果浏览器在一小时内再次向同一个目标URL发送跨域哀求,就可以直接使用从前的预检哀求效果,而不必要再次进行预检哀求。maxAge属性只影响预检哀求的缓存时间,而不会影响正常的跨域哀求,因此不会对现实的业务逻辑产生影响。此外,maxAge属性的详细值必要根据现实环境进行调解,过小的缓存时间可能会导致频繁的预检哀求,过大的缓存时间可能会使跨域哀求的控制权得不到及时更新,从而增加安全风险。
六:注册页面跳转(addViewControllers)
addViewControllers方法是SpringMVC中WebMvcConfigurer接口定义的一个方法,用于注册一个简朴的视图控制器,以便将哀求路径映射到一个详细的视图页面。在一些简朴的场景下,我们可能只必要将某个哀求路径直接映射到一个固定的视图页面,而不必要进行额外的逻辑处理。此时,可以使用addViewControllers方法来快速注册一个视图控制器,并指定对应的哀求路径和视图名称即可。但是我们必要额外留意的是,我们在SpringBoot中处理视图跳转时最好集成Thymeleaf,因为它是SpringBoot指定认可的而且,Thymeleaf与SpringMVC协同工作,可以方便地实现快速开发Web应用步伐。
1.配置
在SpringBoot配置Thymeleaf的一些信息:
导入Thymeleaf坐标:
<!--导入SpringBoot集成Thymeleaf启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
复制代码
在application.yml配置Thymeleaf配置信息:
spring:
# 配置Thymeleaf模板(默认启动会请求/templates/index.html)
thymeleaf:
cache: false # 是否有模板缓存
prefix: classpath:/templates/ # 模板放置的位置
suffix: .html # 模板后缀
mode: HTML # 模板类型
encoding: UTF-8 # 模板编码
复制代码
2.ViewControllerRegistry类说明:
①addViewController(String urlPath)
通过urlPath参数指定的哀求URL路径(例如"/home")注册一个简朴的视图控制器,该方法返回一个ViewControllerRegistration对象,通过该对象可以设置相关属性,如视图名称、哀求方式等。如:registry.addViewController(“/login”);
②setOrder(int order)
设置当前视图控制器的实行顺序,当有多个视图控制器针对同一哀求路径时,可以使用该方法进行优先级排序。默认环境下,差异的视图控制器按照它们被注册的顺序实行。
③addRedirectViewController(String urlPath, String redirectUrl)
注册一个重定向视图控制器,将urlPath哀求路径重定向到指定的重定向地址redirectUrl。
如:registry.addRedirectViewController(“/toBaidu”,“https://www.baidu.com”);
3.ViewControllerRegistration类说明:
①setViewName(String viewName)
资源路径的前缀
②setStatusCode(HttpStatus statusCode)
配置访问不存在资源的响应码,如下常见的:
HttpStatus.BAD_REQUEST:哀求参数错误或格式不正确,例如缺少必须参数、参数类型错误等。
HttpStatus.UNAUTHORIZED:未经授权访问,必要用户登录或提供凭据。
HttpStatus.FORBIDDEN:已经授权但访问被克制,通常意味着权限不足或必要进行进一步身份验证。
HttpStatus.NOT_FOUND:哀求的资源不存在,通常使用自定义的404错误页面进行提示。
HttpStatus.METHOD_NOT_ALLOWED:哀求方式不支持,例如GET哀求访问只支持POST的接口时会返回405错误。
HttpStatus.INTERNAL_SERVER_ERROR:服务器内部错误,必要在背景进行排查和修复。
示例:registry.addViewController(“/**”).setStatusCode(HttpStatus.NOT_FOUND);
说明:访问不存在的页面我一律按照404处理,但是我们templates/error/404.html页面必要存在
注:按照之前配置的thymeleaf配置来说,默认根路径为resources/templates,跳转的资源文件都是.html文件
七:静态资源处理(addResourceHandlers)
addResourceHandlers方法是SpringMVC框架提供的一种配置静态资源的方式,它可以将指定的资源路径映射到一个或多个URL路径上,并指定资源的缓存计谋、版本号以及是否允许目录列表等选项。详细来说,addResourceHandlers方法必要传入一个ResourceHandlerRegistry对象作为参数,然后在这个对象上调用addResourceHandler方法,来添加一个或多个处理器。
1.ResourceHandlerRegistry类方法介绍:
①addResourceHandler
该方法用于指定静态资源的URL路径,支持Ant风格的通配符,如"/resources/**"表示匹配所有以"/resources/"开头的哀求。
2.ResourceHandlerRegistration类方法介绍:
①addResourceLocations
该方法为静态资源地点的物理路径或URL。可以使用多个addResourceLocations方法指定多个路径,如下例:
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/static/", "file:/opt/files/")
复制代码
说明:
classpath:/static/表示在项目的Classpath下(即src/main/resources文件夹下)查找static文件夹,file:/opt/files/表示在系统中的/opt/files/目录下查找文件。
②setCacheControl
此方法用于设置缓存控制头(cache-control header),CacheControl是一个封装了缓存计谋的类。例如:
CacheControl cc = CacheControl.maxAge(30, TimeUnit.DAYS).cachePublic();
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/static/")
.setCacheControl(cc);
复制代码
说明:这将指示浏览器缓存静态资源30天,而且它们是public缓存,意味着中间代理服务器也可以缓存资源。
③setCachePeriod
该方法用于设置静态资源缓存时间,参数类型为Duration类型。如:
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/static/")
.setCachePeriod(Duration.ofMinutes(5));
复制代码
说明:静态资源缓存的过期时间为5分钟
④setOptimizeLocations
此方法用于启用或禁用位置优化。如果启用位置优化,则将优化静态资源的位置,以便并发访问静态资源时可以获得更好的性能。默认环境下,位置优化是禁用的。
⑤setUseLastModified
此方法用于启用或禁用上次修改时间检查(last-modified check)。如果启用上次修改时间检查,则在每个哀求中发送一个if-modified-since头,以检查是否必要返回新内容。默认环境下,上次修改时间检查是启用的。
⑥resourceChain
用于开启或关闭ResourceChain模式。当开启ResourceChain模式时,每个资源文件都会自动添加版本号,制止浏览器缓存问题。
例如:
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/static/")
.resourceChain(true);
复制代码
留意,要使ResourceChain收效,还必要设置addResolver如:
.resourceChain(false)
// 添加VersionResourceResolver,且指定版本号
.addResolver(new VersionResourceResolver()
.addFixedVersionStrategy("1.0.0", "/**")); // 下次访问地址:http://localhost:8881/resources/1.0.0/xxx.css
复制代码
八:代码示例(WebMvcConfigurer)
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);
}
}
复制代码
九:代码示例(拦截器)
<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);
}
}
复制代码
十:代码示例(WebMvcConfigurationSupport)
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);
}
}
复制代码
自定义解析器
@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;
}
}
复制代码
@GetMapping("goods")
public Result showGoods(UserPojo user){
// 注意:这里的User参数不是由前端传入的,而是由addArgumentResolvers方法处理之后传进来的
log.info(user.toString());
// 根据处理之后传入的参数判断是否登录
if (user == null)
return Result.error();
return Result.ok();
}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4