关于spring boot中过滤器与拦截器的实现与区别!!!简单通俗易懂~新手进

我们一个一个的的来!!!

一、什么是过滤器??

过滤器就是过滤的作用,在web开发中过滤一些我们指定的url。它能够在请求传送给 Servlet 之前,对 ServletRequest 和 ServletResponse 做检查和修改,起到了过滤的作用。那么它能帮我们过滤什么呢?那功能可就多了:
比如过拦截掉我们不需要的接口请求
修改请求(request)和响应(response)内容
完成CORS跨域请求等等。过滤器的工作流程去下图所示:

在这里插入图片描述

1.1 如何在springboot中实现过滤器(两个步骤)

第一步 自定义过滤器

由于spring boot中的过滤器属于servlet容器,所以自定义的类必须继承Filter接口。

public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)//在这里进行过滤操作
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//这里是对请求放行,程序继续执行!
	}
 
	@Override
	public void destroy() {
	
	}
}

ps:注意这里需要将ServletRequest强转为HttpServletRequest,不然后面会出问题!!

第二步 注册过滤器(这里有三个方法)

方法一: 在配置类中实现一个 FilterRegistrationBean 对象

@Configuration
public class WebConfig {
	   @Bean
	   public FilterRegistrationBean<MyFilter> abcFilter() {
		   FilterRegistrationBean<MyFilter> filterRegBean = new FilterRegistrationBean<>();
		   filterRegBean.setFilter(new MyFilter());//设置过滤器 对应上面的过滤器
		   filterRegBean.addUrlPatterns("/*"); //在这里指定过滤地址
		   //如果出现多个过滤器,order可以设置过滤器执行顺序。 1>2>3 这里的LOWEST_PRECEDENCE是最低优先级
		   filterRegBean.setOrder(Ordered.LOWEST_PRECEDENCE);
		   return filterRegBean;
	   }
}

方法2:使用@Component 和@Order 注解注册

@Order(Ordered.LOWEST_PRECEDENCE -1)
@Component
public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//这步使得请求能够继续传导下去,如果没有的话,请求就在此结束
	}
 
	@Override
	public void destroy() {
	
	}
}

这种方法的缺点是不能再指定 UrlPatterns,默认的 URL 模式就是/*

方法三: 使用@WebFilter 和@ServletComponentScan 注解,@WebFilter 注解是 Servlet3.0 中的注解,SpringBoot 能够支持该注解,通过@ServletComponentScan 注解,能够扫描并注册到 Servlet 容器中

@WebFilter(urlPatterns="/api/*")
public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//这步使得请求能够继续传导下去,如果没有的话,请求就在此结束
	}
 
	@Override
	public void destroy() {
	
	}
}

还需要在springboot启动类中加入@ServletComponentScan注解

@ServletComponentScan
@SpringBootApplication
public class SpringbootlearnApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(SpringbootlearnApplication.class, args);
	}
}

@WebFilter 方式,可以支持 UrlPatterns 的设置,但是不支持 Order 的设置。
综上所述,第 1 种方法是最灵活的,也是最常用的一种。

二、拦截器

上面我们看了过滤的配置方法,下面我们来看一下拦截器的。网上常用的是实现HandlerInterceptor接口,这里我用的是另一种差不多的方法继承HandlerInterceptorAdapter。(建议用HandlerInterceptorAdapter,可以根据需求覆盖方法)

自定义DjmIntercepter类

public class DjmIntercepter extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle调用");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle调用");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }
}

ps:主要包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。afterConcurrentHandlingStarted用的比较少 大家可以自行百度!! 然后需要配置WebConfigurer类,通过实现WebMvcConfigurer接口。

WebConfigurer类 注册自定义拦截器

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //用于拦截静态资源
    }

    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        return new StringHttpMessageConverter(Charset.forName("UTF-8"));
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(responseBodyConverter());
    }

    /**
     *  这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
     * @param registry 拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DjmIntercepter()).addPathPatterns("/*");
        super.addInterceptors(registry);
    }
}

然后启动项目,在任意地址运行。结果如下:

MyFilter: /ddddd
preHandle调用
postHandle调用
preHandle调用
postHandle调用

通过以上的例子,想必大家也知道了过滤器与拦截器的一些区别。下面我给大家总结一下:

1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

在这里插入图片描述

2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。

这里有一张图很好的展示了过滤器与拦截器的使用:
在这里插入图片描述

3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射,代理分静态代理和动态代理,动态代理是拦截器的简单实现。

何时使用拦截器?何时使用过滤器?
如果是非spring项目,那么拦截器不能用,只能使用过滤器。
如果是处理controller前后,既可以使用拦截器也可以使用过滤器。
如果是处理dispaterServlet前后,只能使用过滤器。

以上就是spring boot中过滤器与拦截器的实现与区别!!!!

猜你喜欢

转载自blog.csdn.net/qq_43419029/article/details/91980288
今日推荐