参考:
(70条消息) Spring过滤器和拦截器的区别_yjc0403的博客-CSDN博客
https://www.cnblogs.com/colin220/p/9606412.htm
概述
过滤器:是在javaweb中,你传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符
拦截器:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作
从具体实现区分
过滤器是servlet的
拦截器是spring aop
细节区别
①拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖于servlet容器,过滤器依赖于servlet容器
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑
关系和工作流程
执行日志
INFO [nio-9018-exec-2] cubeFilter : CubeFilter...进入cube 过滤器
INFO [nio-9018-exec-2] cubeFilter : CubeFilter...过滤器 验证cube权限
INFO [nio-9018-exec-2] cubeFilter : demo service impl
INFO [nio-9018-exec-2] LoginInterceptor : LoginInterceptor...进入拦截器 preHandle
INFO [nio-9018-exec-2] DemoController : DemoController... demo 1 ok
INFO [nio-9018-exec-2] LoginInterceptor : LoginInterceptor...进入拦截器 postHandle
INFO [nio-9018-exec-2] cubeFilter : CubeFilter...退出cube过滤器
代码
过滤器管理
package com.lq.filesystem.filter;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Log4j2
public class MangerFilter implements Filter {
private SsoFilter ssoFilter = new SsoFilter();
private WebApplicationContext wac;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
wac = (WebApplicationContext) filterConfig.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String from = httpRequest.getHeader("from");
if ("cube".equals(from)) {
CubeFilter cubeFiler = CubeFilter.getInstance();
cubeFiler.setWac(wac);
cubeFiler.doFilter(request, response, chain);
} else if ("sso".equals(from)) {
ssoFilter.doFilter(request, response, chain);
} else if ("wx".equals(from)) {
WxFilter instance = WxFilter.getInstance();
instance.doFilter(request, response, chain);
} else {
chain.doFilter(request, response);
}
}
}
cube 过滤器
package com.lq.filesystem.filter;
import com.lq.filesystem.service.DemoService;
import com.sun.istack.internal.NotNull;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.*;
import java.io.IOException;
import java.util.logging.Logger;
public class CubeFilter implements Filter {
Logger log = Logger.getLogger("cubeFilter");
private static final CubeFilter INSTANCE = new CubeFilter();
private WebApplicationContext wac;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("CubeFilter...进入cube 过滤器");
log.info("CubeFilter...过滤器 验证cube权限");
if (wac == null) {
throw new ServletException("请设置 WebApplicationContext ");
}
DemoService demoService = wac.getBean(DemoService.class);
log.info(demoService.getT());
chain.doFilter(request, response);
log.info("CubeFilter...退出cube过滤器");
}
public void setWac(@NotNull WebApplicationContext wac) {
this.wac = wac;
}
public static CubeFilter getInstance() {
return INSTANCE;
}
private CubeFilter() {
}
}
sso 过滤器
package com.lq.filesystem.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.logging.Logger;
public class SsoFilter implements Filter {
Logger log = Logger.getLogger("SsoFilter");
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("进入sso 拦截器");
log.info("验证sso权限");
chain.doFilter(request, response);
log.info("退出sso拦截器");
}
}
拦截器
package com.lq.filesystem.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.lq.filesystem.config.StoreProperties;
import com.lq.filesystem.utils.JwtUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.catalina.realm.MemoryRuleSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.logging.Logger;
/**
* @author seven
* @version 1.0
* @description 登录拦截,通过jwt校验
* @date 2022/10/30 21:32
*/
@Component
@Log4j2
public class LoginInterceptor implements HandlerInterceptor {
Logger log = Logger.getLogger("LoginInterceptor");
/**
* 拦截器,在进入controller之前被调用
* 返回 ture 则继续通行,flase 则将不会被继续处理
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("LoginInterceptor...进入拦截器 preHandle");
final String jwt = request.getHeader("jwt");
JSONObject userError = new JSONObject();
if (!StringUtils.isEmpty(jwt)) {
try {
JwtUtil.verify(jwt);
return true;
}catch (SignatureVerificationException e) {
userError.put("msg","无效签名");
} catch (TokenExpiredException e) {
userError.put("msg","token过期");
} catch (AlgorithmMismatchException e) {
userError.put("msg","token算法不一致");
} catch (Exception e) {
userError.put("msg","其他异常");
}
}else {
userError.put("msg","未携带jwt信息");
// todo 暂时不拦截
return true;
}
userError.put("code",1001);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(userError);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("LoginInterceptor...进入拦截器 postHandle");
}
}
web 配置,设置过滤器和拦截器
package com.lq.filesystem.config;
import com.lq.filesystem.filter.MangerFilter;
import com.lq.filesystem.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author seven
* @version 1.0
* @description web config
* @date 2022/10/30 21:38
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册TestInterceptor拦截器
InterceptorRegistration registration = registry.addInterceptor(loginInterceptor);
registration.addPathPatterns("/**"); //所有路径都被拦截
registration.excludePathPatterns( //添加不拦截路径
"/**/*.html", //html静态资源
"/**/*.js", //js静态资源
"/**/*.css", //css静态资源
"/demo/x/**"
);
}
// 生成一个过滤器bean对象,交过spring管理
@Bean
public FilterRegistrationBean MangerFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(new MangerFilter());
registration.addUrlPatterns("/demo/*");
registration.setName("mangerFilter");
registration.setOrder(1);
return registration;
}
}
注意事项
在Filter中是无法直接使用Srping容器中的bean的,因此不要使用@autowrite @resource 等获取bean对象,可以通过传进来的上线问对象获取bean
如果希望按照某些条件使用指定的Filter,就不要把Filter交给Spring管理(如果在Filter上加上@Compont等注解,spring会托管这个Filter,代理为ApplicationFilterConfig,进入 chain中),否则直接Filer都会执行