SpringBoot中WebMvcConfigurationSupport的各种配置

一、addResourceHandlers静态资源

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

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

@Configuration
public 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);
    }
}

这样就可以在浏览器中访问指定路径下的静态资源。
在这里插入图片描述

二、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则拦截
                 */
               boolean 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解决。
在这里插入图片描述
首先定义一个注解。

@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");
    }
 }

最终输出如下。上面代码不能更生层次解析对象,想要完整的话自己实现或者使用框架哦。
在这里插入图片描述

七、addFormatters 格式化

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

parse方法中的String s则是url中的对应参数。

@Configuration
public 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;
  }

输出如下
在这里插入图片描述

发布了42 篇原创文章 · 获赞 7 · 访问量 7739

猜你喜欢

转载自blog.csdn.net/HouXinLin_CSDN/article/details/104370727