WebMvcConfigurerAdapter/HandlerInterceptorAdapter/FilterRegistrationBean

WebMvcConfigurerAdapter

WebMvcConfigurerAdapter作用

Spring内部的一种配置方式
采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制。

WebMvcConfigurerAdapter 的作用是进行SpringMVC的一些配置
在Spring中,为了减少xml的配置,引入了@Configuration注解。

总结: 该方法已弃用, Spring 5.0 以后WebMvcConfigurerAdapter会取消掉.
现用方式

@Configuration
public class WebMvcConfg implements WebMvcConfigurer {
	//TODO
}

WebMvcConfigurerAdapter常用的方法

/** 解决跨域问题 **/
public void addCorsMappings(CorsRegistry registry) ;

/** 添加拦截器 **/
void addInterceptors(InterceptorRegistry registry);

/** 这里配置视图解析器 **/
void configureViewResolvers(ViewResolverRegistry registry);

/** 配置内容裁决的一些选项 **/
void configureContentNegotiation(ContentNegotiationConfigurer configurer);

/** 视图跳转控制器 **/
void addViewControllers(ViewControllerRegistry registry);

/** 静态资源处理 **/
void addResourceHandlers(ResourceHandlerRegistry registry);

/** 默认静态资源处理器 **/
void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);

1、addInterceptors:拦截器
addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
addPathPatterns:用于设置拦截器的过滤路径规则
excludePathPatterns:用于设置不需要拦截的过滤规则

@Override
public void addInterceptors(InterceptorRegistry registry) {
    super.addInterceptors(registry);
    registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
}

WebMvcConfigurerAdapter过时的替换方法

WebMvcConfigurerAdapter过时的替换方法
转自:https://blog.csdn.net/tyvbpq/article/details/83588508

Spring 5.0后,WebMvcConfigurerAdapter被废弃,取代的方法有两种:

①implements WebMvcConfigurer(官方推荐)

②extends WebMvcConfigurationSupport

使用第一种方法是实现了一个接口,可以任意实现里面的方法,不会影响到Spring Boot自身的@EnableAutoConfiguration,而使用第二种方法相当于覆盖了@EnableAutoConfiguration里的所有方法,每个方法都需要重写,比如,若不实现方法addResourceHandlers(),则会导致静态资源无法访问,实现的方法如下:

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
            .addResourceLocations("classpath:/META-INF/resources/")
            .addResourceLocations("classpath:/resources/")
            .addResourceLocations("classpath:/static/")
            .addResourceLocations("classpath:/public/");
    super.addResourceHandlers(registry);
}

所以,采用第一种方法更加简单方便,不容易出现意料之外的bug

总结:
spring5以上版本不建议使用,所以把原来的继承 WebMvcConfigurerAdapter改为

public class CustomWebConigurer implements WebMvcConfigurer
可以实现相同的功能。

是1.8以后接口中可以不必实现接口的抽象方法才变化的。

WebMvcConfigurerAdapter 其实也是实现了 WebMvcConfigurer接口的

使用示例

第一种:


@Configuration
public class WebAppConfig implements WebMvcConfigurer{

    @Bean
    public HandlerInterceptor getLoginInterceptor(){
        return new LoginInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(getLoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/error")
                .excludePathPatterns("/static/*");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//设置允许跨域的路径
                .allowedOrigins("*")//设置允许跨域请求的域名
                .allowCredentials(true)//是否允许证书 不再默认开启
                .allowedMethods("GET", "POST", "PUT", "DELETE")//设置允许的方法
                .maxAge(3600);//跨域允许时间
    }
}

使用这个在升级springboot2.0之后会把Date类型字段自动给转成UTC字符串 如:1990-11-26T16:00:00.000+0000,如果想转成时间戳在application.properties配置文件增加以下配置:
···
spring.jackson.serialization.write-dates-as-timestamps=true
spring.jackson.time-zone=GMT+8
···
第二种(会导致springboot的自动配置失效):
···
@Configuration
public class WebAppConfig extends WebMvcConfigurationSupport{

    ...

}

这种方式会把Date类型字段自动给转成时间戳,如果想用UTC字符串,在application.properties配置文件增加以下配置:

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8


# HandlerInterceptorAdapter
[推荐]SpringBoot中的HandlerInterceptorAdapter
参考URL: https://blog.csdn.net/zhaoruda/article/details/80206361


**在SpringBoot中我们可以使用HandlerInterceptorAdapter这个适配器来实现自己的拦截器。这样就可以拦截所有的请求并做相应的处理。** 

在HandlerInterceptorAdapter中主要提供了以下的方法:

* preHandle:在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true,则继续调用下一个拦截器。如果返回false,则中断执行,也就是说我们想调用的方法不会被执行,但是你可以修改response为你想要的响应。
* postHandle:在方法执行后调用。
* afterCompletion:在整个请求处理完毕后进行回调,也就是说视图渲染完毕或者调用方已经拿到响应。 

Spring Boot 之FilterRegistrationBean-自定义Filter

[推荐]spring boot 配置Filter过滤器方法总结
参考URL: https://blog.csdn.net/testcs_dn/article/details/80265196

在springboot 中,主要是靠FilterRegistrationBean 这个类来提供这样的功能。具体而言:
自定义Filter需要两个步骤:
实现Filter【javax.servlet.Filter】接口,实现Filter方法
添加 @Configuration 注解,将自定义Filter加入过滤链

@Configuration
public class WebAppConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean httpFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        //setFilter就是你所定义的过滤器filter类。
        // 另外当你有多个拦截器的时候,可以再添加registratrion.setOrder(**)进行设置。
        registrationBean.setFilter(new HttpFilter());
        registrationBean.addUrlPatterns("/threadLocal/*");
        return  registrationBean;
    }

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/*");
    }
}

一、在spring的应用中我们存在两种过滤的用法,一种是拦截器、另外一种当然是过滤器。我们这里介绍过滤器在springboot的用法,在springmvc中的用法基本上一样,只是配置上面有点区别。

二、filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response**,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.**换种说法,filter其实是一个”servlet chaining”(servlet 链).

一个Filter包括:
1)、在servlet被调用之前截获;
2)、在servlet被调用之前检查servlet request;
3)、根据需要修改request头和request数据;
4)、根据需要修改response头和response数据;
5)、在servlet被调用之后截获.

@Component
@ServletComponentScan
@WebFilter(urlPatterns = "/login/*",filterName = "loginFilter")
public class LoginFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {

    }
}
  1. @Component 这个注解的目的是将LoginFilter交给容器来处理。也就是让LoginFilter起作用
  2. @WebFilter 这个用处显而易见,针对于什么链接做过滤,filter的名称是为什么。

总结: Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截。但是它适合更粗粒度的拦截,在请求前后做一些编解码处理、日志记录等。

spring boot 配置Filter过滤器
1、通过 @WebFilter 注解来配置


@Component
@WebFilter(urlPatterns = "/webapi/*", filterName = "authFilter")
public class AuthFilter implements Filter {
    ......
}

2、通过 @Bean 注解来配置
我这个是写在带 @SpringBootApplication 注解的类里面的。

	@Bean
	public FilterRegistrationBean testFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter());
		registration.addUrlPatterns("/webapi/*"); //
		registration.addInitParameter("paramName", "paramValue"); //
		registration.setName("testFilter");
		return registration;
	}

那如果有多个过虑器,怎么指定执行的顺序呢?
通过 registration.setOrder(1); 来设置,例如:

	@Bean
	public FilterRegistrationBean testFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter());
		registration.addUrlPatterns("/webapi/*"); //
		registration.addInitParameter("paramName", "paramValue"); //
		registration.setName("testFilter");
		registration.setOrder(1);
		return registration;
	}
 
	@Bean
	public FilterRegistrationBean authFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean(new AuthFilter());
		registration.addUrlPatterns("/webapi/*"); //
		registration.addInitParameter("paramName", "paramValue"); //
		registration.setName("authFilter");
		registration.setOrder(2);
		return registration;
	}

注意:

1、如果指定了 Order 属性,执行的顺序与注册的顺序是无关的;
2、数字越小,优先级越高;

关于 @Order 注解
有文章提到使用 @Order 注解来指定顺序,亲测无效。

编码 filter Bean总结
思路1 :
定义一个HttpFilter类,不加@Component的情况,我们可以在 implements WebMvcConfigurer的配置类中使用@Bean返回,HttpFilter类的实例

@WebFilter(filterName = "HttpFilter")
@Slf4j
public class HttpFilter implements Filter {
@Configuration
public class WebAppConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean httpFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        //setFilter就是你所定义的过滤器filter类。
        // 另外当你有多个拦截器的时候,可以再添加registratrion.setOrder(**)进行设置。
        registrationBean.setFilter(new HttpFilter());
        registrationBean.addUrlPatterns("/threadLocal/*");
        return  registrationBean;
    }

思路2【推荐】: 完成使用注解,@Component注解实现implements Filter的类,让spring管理即可。
···
@WebFilter(filterName = “HttpFilter”, urlPatterns = “/threadLocal/*”)
@Slf4j
@Component
public class HttpFilter implements Filter {
@Override
public void destroy() {
}

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    log.info("do filter!{}{}",Thread.currentThread().getId(),((HttpServletRequest) req).getServletPath());
    RequestHolder.add(Thread.currentThread().getId());
    chain.doFilter(req,resp);
}

@Override
public void init(FilterConfig config) throws ServletException {
}

}
···

猜你喜欢

转载自blog.csdn.net/inthat/article/details/88658314