一、addResourceHandlers静态资源

SpringBoot默认把类路径下的/static、/resources、/public、/META-INF/resources文件夹映射为/**,可以通过addResourceHandlers来自定义映射路径。

以下例子根据不同系统环境添加不同的路径,映射地址为/imgs/**。也可以根据@Value注解拿到配置文件中的值。

@Configurationpublic class WebMvnConfig extends WebMvcConfigurationSupport { @Value("${application.static.res-path}") private String resPath;
@Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); String path = System.getProperty("os.name").equalsIgnoreCase("linux") ? "file:/home/imgs/" : "file:E:/imgs/";        registry.addResourceHandler("/imgs/**").addResourceLocations(path); }}

这样就可以在浏览器中访问指定路径下的静态资源。

SpringBoot中WebMvcConfigurationSupport的各种配置_java

二、addInterceptors拦截器

通过addInterceptors可以添加拦截器,拦截器需要实现HandlerInterceptor接口,并在preHandle中处理逻辑,返回true则不拦截,否则拦截,拦截器也可以对静态资源拦截。

addPathPatterns用于添加拦截的路径,通过一个可变参数接收,excludePathPatterns用于排除路径。

如下代码,对/admin/下除了login不拦截,其余都拦截。并且拦截/imgs/下除了2.jpg,其余都拦截。在preHandle中简单判断了请求参数user是否为听风逝夜并且pass为abc123,否则拦截,这时候应该跳转到其他界面。

@Configuration
public class WebMvnConfig extends WebMvcConfigurationSupport { 
@Override 
protected void addInterceptors(InterceptorRegistry registry) { 
super.addInterceptors(registry);        
registry.addInterceptor(new HandlerInterceptor() { 
@Override 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
System.out.println("preHandle------------->"+request.getRequestURL()); 
/** 
* 逻辑处理 
*/ 
/** 
* 返回true则不拦截,false则拦截 
*/ b
oolean result = request.getParameter("user") 
.equals("听风逝夜") && request.getParameter("pass").equals("abc123"); 
if (!result){                   
response.sendRedirect("/admin/login"); 
} 
return result;
 }
  @Override 
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//在Controller处理完之后回调,preHandle返回false则不走这里 
System.out.println("postHandle------------>"); 
} 
@Override 
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
//整个请求处理完毕回调方法,preHandle返回false则不走这里 System.out.println("afterCompletion-------------->"); 
} }).addPathPatterns("/admin/**","/imgs/**").excludePathPatterns("/imgs/2.jpg","/admin/login"); 
}
}

三、 addCorsMappings 添加跨域配置

不过这方法和@CrossOrigin感觉都有坑,还是用过滤器解决跨域问题吧。

 @Override 
 protected void addCorsMappings(CorsRegistry registry) { 
 super.addCorsMappings(registry);       
 registry.addMapping("/**") 
 .allowedOrigins("*") 
 .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
 .allowCredentials(true) 
 .allowedHeaders("*") 
 .maxAge(3600);
  }

四、addViewControllers 添加视图控制器

访问一个页面时在Controller中也许会这样做

 @GetMapping("/") 
 public String index(){ 
 return "index"; 
 }

但是这里面没什么逻辑,不能每个都这样写吧,所以可以使用addViewControllers来解决

 @Override
  protected void addViewControllers(ViewControllerRegistry registry) { 
  super.addViewControllers(registry);     
  registry.addViewController("/").setViewName("/index"); 
  }

以上两个方法相等。

五、resolveArgument 参数解析器

如果想实现自定义参数解析,如把以下格式的日期解析到LocalDateTime中,可以在resolveArgument中添加一个HandlerMethodArgumentResolver解决。

SpringBoot中WebMvcConfigurationSupport的各种配置_java_02

首先定义一个注解。


@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Date { 
String value(); 
boolean required() default true;
}

其次添加一个HandlerMethodArgumentResolver实现类,在supportsParameter中判断是否需要转换,也就是看看参数上是否有我们自定义的注解。如果返回true,则进入resolveArgument方法,进行转换,返回值将被SpringBoot设置到原来参数上。如果返回的类型和原来参数上的不一致,将报错。

以下例子判断参数上是否有自定义的Date注解,存在则进入resolveArgument方法,首先获取注解中的value值,然后通过NativeWebRequest获取url中的对应值,如果为null或者split后大小不为5,则返回null,否则转换成LocalDateTime类型并返回。

@Configuration
public class WebMvnConfig extends WebMvcConfigurationSupport { 
    @Override 
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {                 super.addArgumentResolvers(argumentResolvers);        
       argumentResolvers.add(new HandlerMethodArgumentResolver() { 
          @Override 
          public boolean supportsParameter(MethodParameter methodParameter) { 
             return methodParameter.hasParameterAnnotation(Date.class); 
          } 
          @Override 
          public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                             NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { 
              Date date =methodParameter.getParameterAnnotation(Date.class); 
              String parameter = nativeWebRequest.getParameter(date.value()); 
              if (parameter!=null){ 
                 String[] split = parameter.split(","); 
                 if (split.length==5){ 
                    return LocalDateTime.of(converInteger(split[0]),converInteger(split[1]),converInteger(split[2]),converInteger(split[3]),converInteger(split[4])); 
                 } 
              } 
              return null; 
           } 
         });
      } 
      private Integer converInteger(String param){ 
         return Integer.valueOf(param); 
     }
   }

接着就可以在方法中使用,在参数上加上@Date注解,就可以接收date=2020,2,18,8,8这种格式日期数据

@GetMapping("/")
public String index(@Date("date") LocalDateTime date){ 
     System.out.println("index"+date); 
     return "index";
}

六、addReturnValueHandlers 返回值处理

通过@ResponseBody可以把对象转换成json返回。于是有一天你想这样做,有一个注解,标记在Controller方法上,则会返回这个对象的xml格式数据,实现方法就可以在addReturnValueHandlers中添加一个HandlerMethodReturnValueHandler。

首先编写一个注解,用来标明返回值是xml类型。

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface ResponseXmlBody {}

其次,在HandlerMethodReturnValueHandler的supportsReturnType方法中判断方法上是否有ResponseXmlBody注解,为true则进入handleReturnValue。

handleReturnValue中的o参数则是Controller方法的返回值,通过反射一系列操作后,拼接成一个xml格式的数据,并使用nativeWebRequest获取到输出流,设置Content-Type为text/plain;charset=utf-8,但是这里一定要设置modelAndViewContainer.setRequestHandled(true);。

@Configuration
public class WebMvnConfig extends WebMvcConfigurationSupport { 
   @Override 
   protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) { 
      super.addReturnValueHandlers(returnValueHandlers);        
      returnValueHandlers.add(new HandlerMethodReturnValueHandler() { 
         @Override 
         public boolean supportsReturnType(MethodParameter methodParameter) { 
            return methodParameter.hasMethodAnnotation(ResponseXmlBody.class); 
         } 
         @Override 
         public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {                
         modelAndViewContainer.setRequestHandled(true); 
         HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);             response.addHeader("Content-Type", "text/plain;charset=utf-8"); 
         Class<?> aClass = o.getClass(); 
         StringBuffer value =new StringBuffer(); 
         Field[] declaredFields = aClass.getDeclaredFields(); 
         for (int i = 0; i < declaredFields.length; i++) {                                             declaredFields[i].setAccessible(true);                                                 addNode(value,declaredFields[i].getName(),declaredFields[i].get(o)); 
         } 
         StringBuffer rootStringBuffer =new StringBuffer();                                         addNode(rootStringBuffer,aClass.getSimpleName(),value);                                       response.getWriter().append(rootStringBuffer); 
       } 
     }); 
    } 
    private void addNode(StringBuffer stringBuffer,String name,Object value){        
       stringBuffer.append("<");        
       stringBuffer.append(name);        
       stringBuffer.append(">");        
       stringBuffer.append(value);        
       stringBuffer.append("<");        
       stringBuffer.append(name);        
       stringBuffer.append(">");        
       stringBuffer.append("\n"); 
      } 
    }

最终输出如下。上面代码不能更深层次解析对象,想要完整的话自己实现或者使用框架哦。

SpringBoot中WebMvcConfigurationSupport的各种配置_java_03

七、addFormatters 格式化

比如使用@RequestParam接收Book对象,url中格式是:?book=书名,价格 这样的,@RequestParam无法直接转换,可以通过addFormatters自定义格式化来解决。

parse方法中的String s则是url中的对应参数,通过自己的处理逻辑返回Book对象。

@Configurationpublic class WebMvnConfig extends WebMvcConfigurationSupport {    @Override    protected void addFormatters(FormatterRegistry registry) {        super.addFormatters(registry);        registry.addFormatter(new Formatter<Book>() {            @Override            public Book parse(String s, Locale locale) throws ParseException {                String[] split = s.split(",");                if (split.length==2){                    return  new Book(split[0],Float.valueOf(split[1]));                }                return null;            }            @Override            public String print(Book book, Locale locale) {
               return null;            }        });    } }  public class Book {    public Book() {    }
   public Book(String bookName, Float price) {        this.bookName = bookName;        this.price = price;    }
   private String bookName;    private Float price;
   public Float getPrice() {        return price;    }
   public void setPrice(Float price) {        this.price = price;    }
   public String getBookName() {        return bookName;    }
   public void setBookName(String bookName) {        this.bookName = bookName;    }
   
}
 @GetMapping("addBook") 
 @ResponseBody 
 public Object date(@RequestParam("book")Book book){ 
 System.out.println(book); 
 return book; 
 }

输出如下

SpringBoot中WebMvcConfigurationSupport的各种配置_java_04