Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,使用更方便。
自定义拦截器
/** 通过路径进行权限拦截 */ @Component public class PermissionInterceptor implements HandlerInterceptor { @Autowired private RedisComponent redisComponent; //preHandle是在请求执行前执行的 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { String token = request.getRemoteUser(); if (StringUtils.isEmpty(token)){ throw new AuthorityException(); } ShareManagerPO shareManagerPO = (ShareManagerPO)redisComponent.getValue(token, ShareManagerPO.class); String requestURI = request.getRequestURI(); List<PermissionPO> permissionList = shareManagerPO.getPermissionList(); ArrayList<String> urls = new ArrayList<>(); for (PermissionPO permissionPO : permissionList) { urls.add(permissionPO.getPath()); } int indexOf = requestURI.lastIndexOf("/"); String substring = requestURI.substring(1,indexOf); if (urls.contains(substring)){ return true; }else { throw new AuthorityException(); } } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }拦截器的配置
```java @Configuration public class PermissionConfig implements WebMvcConfigurer { @Autowired PermissionInterceptor permissionInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //指定拦截器,指定拦截路径 registry.addInterceptor(permissionInterceptor).addPathPatterns("/**") //不被拦截的路径 .excludePathPatterns("/shareManager/**") .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); } //配置不被拦截的静态资源 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } } ```过滤器(Filter)是Servlet中常用的技术,可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,常用的场景有登录校验、权限控制、敏感词过滤
下面是springboot项目利用过滤器来获取登录成功用户的信息
GenericFilterBean 只需要在自定义类中重写doFilter方法
public class TokenAuthenticateFilter extends GenericFilterBean { private BaseTokenAuth service; public TokenAuthenticateFilter(BaseTokenAuth service) { this.service = service; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { Authentication authentication = service.getAuthentication((HttpServletRequest) request); //存放authentication到SecurityContextHolder 存储用户信息 SecurityContextHolder.getContext().setAuthentication(authentication); filterChain.doFilter(request, response); } }使用@WebFilter注解为声明当前类为filter,第一个参数为该filter起一个名字,第二个参数为说明要拦截的请求地址,当前类需要实现Filter接口,里面有三个方法,分别为过滤器初始化、过滤方法和过滤器销毁。
@Slf4j @WebFilter(filterName = "myFilter1", urlPatterns = "/*") public class MyFilter1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info(filterConfig.getFilterName() + " init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { log.info("myFilter1 begin"); try { log.info("业务方法执行"); chain.doFilter(request, response); } catch (Exception e) { log.error("error!", e); } log.info("myFilter1 end"); } @Override public void destroy() { } }启动类添加@ServletComponentScan注解,@ServletComponentScan注解所扫描的包路径必须包含该Filter,代码如下:
SpringBootApplication @ServletComponentScan(basePackages = "com.example.demo.filter") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }新建配置类WebConfig.java,配置bean,代码如下:
@Configuration public class WebConfig { @Bean public FilterRegistrationBean testFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(new MyFilter2()); registration.addUrlPatterns("/test"); // registration.setName("myFilter2"); return registration; } }