过滤器(Filter)
概念:Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等
Filter快速入门
1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法
2.配置Filter:Filter类上加@WebFilte 注解,配置拦截资源路径。引导类上@ServletComponentScan开启Servlet组件支持。
”/*“代表所有资源路径
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter{
@Override//初始化方法,只调用一次
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override//拦截到请求之后调用,调用多次
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override//销毁方法,只调用一次
public void destroy() {
Filter.super.destroy();
}
详解(执行流程、拦截路径、过滤器链)
在请求以后,过滤器拦截请求,执行拦截前的操作,执行完以后,放行,在访问完资源以后,响应之前还会再次回到Filter,此时可以执行放行后的逻辑
Filter拦截路径
Filter可以根据需求,配置不同的拦截资源路径。
过滤器链
一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链
顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序
登录校验Filter
步骤
获取请求url
判断请求url中是否包含login,如果包含,说明是登录操作,放行
获取请求头中的令牌
判断令牌是否存在,如果不存在,返回错误
解析令牌,解析失败,返回错误
放行
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//1.获取请求的url
String url = req.getRequestURL().toString();
log.info("请求的url:{}",url);
//判断url中是否包含login
if(url.contains("login")){
log.info("登录操作,放行");
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//获取请求头中的令牌
String jwt = req.getHeader("token");
//判断令牌是否存在
if(!StringUtils.hasLength(jwt)){
log.info("请求token为空");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//解析token 如果解析失败,返回错误结果
try{
JwtUtils.parseJWT(jwt);
}catch (Exception e){
e.printStackTrace();
log.info("解析令牌失败");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//放行
log.info("令牌合法,放行");
filterChain.doFilter(servletRequest,servletResponse);
}
拦截器Interceptor
概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。
作用:拦截请求,在指定的方法调用前后,根据业务需要执行预定的代码
入门
定义拦截器,实现HandlerInterceptor接口,并重写其所有方法
注册拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor{
@Override//目标资源方法运行前运行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override//目标资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle....");
}
@Override//视图渲染完毕后运行,最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
@Configuration//配置类
public class WebConfig implements WebMvcConfigurer{
@Resource
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
详解(拦截路径、执行流程)
拦截路径
执行流程
Filter与Interceptor的区别
接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。
拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。
登录校验
public class LoginCheckInterceptor implements HandlerInterceptor{
@Override//目标资源方法运行前运行
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
//1.获取请求的url
String url = req.getRequestURL().toString();
log.info("请求的url:{}",url);
//判断url中是否包含login
if(url.contains("login")){
log.info("登录操作,放行");
return true;
}
//获取请求头中的令牌
String jwt = req.getHeader("token");
//判断令牌是否存在
if(!StringUtils.hasLength(jwt)){
log.info("请求token为空");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//解析token 如果解析失败,返回错误结果
try{
JwtUtils.parseJWT(jwt);
}catch (Exception e){
e.printStackTrace();
log.info("解析令牌失败");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//放行
log.info("令牌合法,放行");
return true;
}
全局异常处理器
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)//捕获所有异常
public Result ex(Exception ex){
ex.printStackTrace();
return Result.error("对不起,操作失败");
}
}
@RestControllerAdvice = @ControllerAdvice + @ResponseBody