拦截器是一种动态拦截方法调用的机制,类似于过滤器,是Spring框架提出的,用来动态拦截控制器方法的执行。
其作用是拦截请求,在指定方法调用前后,根据业务执行预设代码。
实现步骤
1.定义拦截器,实现HandlerInterceptor接口,并重写其所有方法
com.ztt.interceptor包下实现LoginCheckInterceptor类;
LoginCheckInterceptor类中主要有三个方法preHandle()、postHandle()、afterCompletion();这三个方法spring已经实现好,可以不重写,但是为了实现拦截作用,一般需要对preHandle()方法进行重写。
preHandle()的返回值是布尔类型,true表示放行、false表示拦截。
package com.ztt.interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override // 目标资源方法执行前执行,return true:放行,return false:不放行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, 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执行");}
}
2.注册拦截器
同时实现配置类,配置类中定义了拦截对象
package com.ztt.config;import com.ztt.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");}
}
具体样例
package com.ztt.interceptor;import com.alibaba.fastjson.JSONObject;
import com.ztt.pojo.Result;
import com.ztt.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override // 目标资源方法执行前执行,return true:放行,return false:不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {//1.获取请求的URLString url = req.getRequestURL().toString();log.info("请求的URL:{}",url);//2.判断该url中是否包含login,如果包含,说明是登录操作,放行if(url.contains("login")){log.info("登录操作,放行");return true;}//3.获取请求头中的令牌tokenString jwt = req.getHeader("token");// 4.判断令牌是否存在,如果不存在则需要报错if(!StringUtils.hasLength(jwt)){log.info("请求头token为空,返回未登录的信息");Result error = Result.error("NOT LOGIN");// 手动转换 对象-->JSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}// 5.解析token,如果解析失败说明,token过期或者被篡改try {JwtUtils.parseJWT(jwt);}catch (Exception e){// jwt解析失败e.printStackTrace();log.info("令牌解析失败,返回未登录错误信息");Result error = Result.error("NOT LOGIN");// 手动转换 对象-->JSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}// 令牌合法,放行log.info("令牌合法,放行");return true;}}
Filter是在阿帕奇服务器中实现,而Intercepter在Spring框架中实现,其更接近Controller,在调用过程中Filter一般会先出发请求、Intercepter后触发请求;而在响应过程中Intercepter先响应。