定义
WebMvcConfigurationAdapter是一个配置类,该配置类主要利用@Bean方式来配置,该配置类里的配置主要功能是针对Http请求作统一处理。我们想要使用这样的配置方式,需要自定义一个类取继承这个配置类。
具体的API方法功能
以下的API中WebConfig 类也是我自己定义的,它是继承WebMvcConfigurerAdapter类,并且里边什么也没做。
public void addFormatters(FormatterRegistry registry)
该方法的功能是添加一个实例,这个实例的功能在请求到达之前将数据进行格式化或者转换,以及请求之后对返回给前端的数据进行转换与格式化
@Configuration
public class SysWebConfig extends WebConfig {
/**
* 全局处理http请求,主要用于用于对象与字符串之间的转换
*
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new TestForamtter());
}
}
/**
* 该类是线程安全的,类似于PropertyEditer功能,用于对象与字符串之间的转换
*
*/
public class TestForamtter implements Formatter<Test> {
/**
* 将请求中的字符串转换成对象
* Test实体是自己瞎定义的对象,用于测试,这里就不贴了
* @param s
* @param locale
* @return
* @throws ParseException
*/
@Override
public Test parse(String s, Locale locale) throws ParseException {
Test test = new Test();
test.setA("i am is a");
test.setB("i am is b ");
return test;
}
/**
* 将请求中的对象转换成字符串类
*
* @param test
* @param locale
* @return
*/
@Override
public String print(Test test, Locale locale) {
return "this is test!";
}
}
public void addInterceptors(InterceptorRegistry registry)
该方法功能是添加拦截器实例,这个实例需要实现HandlerInterceptor接口
/**
* WEB配置类
*/
@Configuration
public class SysWebConfig extends WebConfig {
/**
* 添加拦截器实例。该实例需要实现HandlerInterceptor
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册一个拦截器,addPathPatterns指定拦截的RUl,默认除了/login之外的对所有请求进行拦截
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");
super.addInterceptors(registry);
}
}
/**
* 这是一个拦截器,用于处理请求
*/
public class TestInterceptor implements HandlerInterceptor {
/**
* 这个方法是在请求controller之前执行的
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
Exception {
String token = request.getHeader("Authorization");
System.err.println("请求controller之前获取Token:" + token);
return true;
}
/**
* 这个方法只在请求controller之后,还未熏染视图执行的
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
modelAndView) throws Exception {
System.err.println("请求controller之后");
}
/**
* 这个方法是在渲染视图之后执行的
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
ex) throws Exception {
}
}
public void configurePathMatch(PathMatchConfigurer configurer)
该个方法的功能是设置匹配路由请求规则
/**
* WEB配置类
*/
@Configuration
public class SysWebConfig extends WebConfig {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 系统对外暴露的 URL 不会识别和匹配 .* 后缀,例如你请求的是/user.*,那么系统
//不会匹配到/user.html
configurer.setUseSuffixPatternMatch(false)
.setUseTrailingSlashMatch(true); // 系统不区分 URL 的最后一个字符是否是斜杠 /
}
}
public void addCorsMappings(CorsRegistry registry)
该方法的功能是配置哪些请求可以跨域请求,以及哪些机器可以访问跨域请求。所谓的跨域大部分是针对前后端分离的项目,并且前端跟后端没有部署在同一台服务器上
/**
* WEB配置类
*/
@Configuration
public class SysWebConfig extends WebConfig {
/**
* 增加跨域支持
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//对哪些请求支持跨域访问
.allowedOrigins("*")//哪些机器可以跨域访问
.allowCredentials(true)//是否支持用户凭证
.allowedMethods("", "", "", "")//支持跨域请求的请求方式
.maxAge(3600);//准备响应前的缓存持续的最大时间(以秒为单位)。
super.addCorsMappings(registry);
}
}
public void addResourceHandlers(ResourceHandlerRegistry registry)
该方法的功能就是添加静态路径,这个方法中的静态路径会覆盖application.yml里的配置
public class SysWebConfig extends WebConfig {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//请求的地址
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");//映射的项目中的路径,这个路径也可以是额外路劲,例如E://file路径
super.addResourceHandlers(registry);
}
}
public void addViewControllers(ViewControllerRegistry registry)
该方法的功能用于自定义视图控制器
public class SysWebConfig extends WebConfig {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//对于/hello的请求 重定向到/home
registry.addRedirectViewController("/test/test", "/test/redirect");
//对于/loginou请求,响应200状态码
registry.addStatusController("/loginout", HttpStatus.OK);
//对于/home请求,返回home视图
registry.addViewController("/home").setViewName("home");
super.addViewControllers(registry);
}
}
public void configureViewResolvers(ViewResolverRegistry registry)
该方法功能是配置视图解析器的
public class SysWebConfig extends WebConfig {
/**
* 配置视图解析器
* @param registry
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
//注册一个Jsp解析器
registry.jsp("/static/jsp", ".jsp");/
//视图解析器会根据返回的视图名称在Spring容器中找到视图名字对应的Bean,这个Bean是View.class类型的,如果找到就直接返回
registry.beanName();
//用于注册各种各样的视图解析器的包括自己定义的视图解析器
registry.viewResolver();
//开启视图解析器裁决功能
registry.enableContentNegotiation(new MappingJackson2JsonView());
super.configureViewResolvers(registry);
}
@Bean
public TestViewResolver testViewResolver() {
return new TestViewResolver(testView());
}
@Bean
public TestView testView() {
return new TestView();
}
}
public class TestView implements View {
@Override
public String getContentType() {
return null;
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
}
}
public class TestViewResolver implements ViewResolver {
private View view;
public TestViewResolver(View view) {
this.view = view;
}
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return view;
}
}
public void addResourceHandlers(ResourceHandlerRegistry registry)
该的方法功能是处理静态文件用的,由于DispatcherSevelet对所有请求都进行拦截,当我们请求静态文件的时候,因为后端没有对应的Controller,那么这个请求就会交由DefaultServletHandler去处理。
public class SysWebConfig extends WebConfig {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//请求的地址
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");//映射的项目中的路径,这个路径也可以是额外路劲,例如E://file路径
super.addResourceHandlers(registry);
}
}
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer)
该方法的功能用于自定义视图控制器
public class SysWebConfig extends WebConfig {
/**
* 这个方法的的作用注册一个Handler,当请求静态资源的时候,如果没有找到相应Controller,就会把这个请求交由defaultservlethandler处理,
* 其实就是对DispatcherServlet的一种增强
*
* @param configurer
*/
@Override
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
// 等价于<mvc:default-servlet-handler />, 对静态资源文件的访问, 将无法 mapping 到 Controller 的 path 交给 default servlet handler 处理
configurer.enable();
}
}
public void addArgumentResolvers(List argumentResolvers)
该方法的功能用于注册Controller的参数解析器,并且这个参数可以注册多个参数解析器,将前端传过来的参数根据业务需求进行参数的解析,解析成我们想要的类型或者格式。
public class SysWebConfig extends WebConfig {
/**
* 添加参数解析器
* @param argumentResolvers
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(testArgumentResolver());
super.addArgumentResolvers(argumentResolvers);
}
/**
* 配置参数解析器的实例
* @return
*/
@Bean
public TestArgumentResolver testArgumentResolver() {
return new TestArgumentResolver();
}
}
public class TestArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
//判断Controller上是否存在该注解,如果存在就之下下边的resovleArgument方法进行参数解析
return methodParameter.hasParameterAnnotation(TestParam.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)
throws Exception {
//获取参数上的对应的主注解
TestParam testParamAnn = methodParameter.getParameterAnnotation(TestParam.class);
//获取注解上的参数
String paramName = testParamAnn.name();
if (paramName.equals("")) {
paramName = methodParameter.getParameterName();
}
//获取request请求中的参数,
Object parameter = nativeWebRequest.getNativeRequest(HttpServletRequest.class).getParameter(paramName);
//可以根据具体的业务在此进行具体的参数转换逻辑。。。。。
return parameter == null || parameter.equals("") ? testParamAnn.defaultVaule() : parameter;
}
}
@Target(value = ElementType.PARAMETER)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TestParam {
String name() default "";
String value() default "";
String defaultVaule() default "";
}
addReturnValueHandlers
该方法的功能是一个注册返回值解析器的,这个返回值解析器可以统一的将数据以一定的格式返回给前端。以下代码中有很多注意的地方,请认真查看,具体的原因我就不一一细说了,百度上有很多这些资料。
@Configuration
public class SysWebConfig extends WebConfig {
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
returnValueHandlers.add(testReturnValueHandler());
super.addReturnValueHandlers(returnValueHandlers);
}
@Bean
public TestReturnValueHandler testReturnValueHandler() {
return new TestReturnValueHandler();
}
}
public class TestReturnValueHandler implements HandlerMethodReturnValueHandler {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supportsReturnType(MethodParameter returnType) {
//只有带有TestReturnValue的注解参会相应的Controller的返回值进行转换或者封装
return returnType.hasMethodAnnotation(TestReturnValue.class);
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
//特别注意的是,如果不想返回视图那么这里一定要设置成true,他的作用类似于@ResponseBody的功能
mavContainer.setRequestHandled(true);
//统一的返回类型
ReturnInfo<Object> returnInfo = new ReturnInfo<>();
returnInfo.OK();
returnInfo.setT(returnValue);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
response.addHeader("Content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().append(objectMapper.writeValueAsString(returnInfo));
}
}
@Target ( {ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TestReturnValue {
}
@Validated
@Controller
@RequestMapping("/test")
public class TestController {
/**
* 特别注意的是,这里的Controller方法一定不能返回一个String类型,因为如果返回的是String类型
* 他默认的就会去找对应的视图,早晨请求404
* @return
*/
@RequestMapping(value = "/returnValue")
@TestReturnValue
public Object returnValue() {
return "liyuzhi";
}
}
configureHandlerExceptionResolver
该方法的功能是注册Controller异常处理器的,其中的异常处理器可以统一处理Controller的异常
@Configuration
public class SysWebConfig extends WebConfig {
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(testExceptionHandler());
super.configureHandlerExceptionResolvers(exceptionResolvers);
}
@Bean
public TestExceptionHandler testExceptionHandler() {
return new TestExceptionHandler();
}
}
public class TestExceptionHandler extends AbstractHandlerExceptionResolver {
//由于spring自带了异常处理器,我们想要执行我们自己的异常处理器
//那么就需要将我们的异常处理器的处理顺序放在前边,否则该异常处理器不会生效
@Override
public int getOrder() {
return 0;
}
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object
handler, Exception ex) {
ex.printStackTrace();
//如果Controller遇到异常就会跳转到这个视图
//具体业务逻辑肯定是很复杂的,可以根据具体的业务来将这一块细化一下
return new ModelAndView("liyuzhi");
}
}
@Validated
@Controller
@RequestMapping("/test")
public class TestController {
/**
* 特别注意的是,这里的Controller方法一定不能返回一个String类型,因为如果返回的是String类型
* 他默认的就会去找对应的视图,早晨请求404
*
* @return
*/
@RequestMapping(value = "/returnValue")
@TestReturnValue
public Object returnValue() {
return 1;
}
/**
* 特别注意的是,这里的Controller方法一定不能返回一个String类型,因为如果返回的是String类型
* 他默认的就会去找对应的视图,早晨请求404
*
* @return
*/
@RequestMapping(value = "/exceptionResult")
@TestReturnValue
public Object exceptionResult() {
throw new RuntimeException("");
}
}