拦截器是一种动态拦截方法调用的机制,类似于过滤器,是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 {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public 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.获取请求的URL
String url = req.getRequestURL().toString();
log.info("请求的URL:{}",url);
//2.判断该url中是否包含login,如果包含,说明是登录操作,放行
if(url.contains("login"))
{
log.info("登录操作,放行");
return true;
}
//3.获取请求头中的令牌token
String jwt = req.getHeader("token");
// 4.判断令牌是否存在,如果不存在则需要报错
if(!StringUtils.hasLength(jwt))
{
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT LOGIN");
// 手动转换 对象-->JSON
String 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");
// 手动转换 对象-->JSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
// 令牌合法,放行
log.info("令牌合法,放行");
return true;
}
}
Filter是在阿帕奇服务器中实现,而Intercepter在Spring框架中实现,其更接近Controller,在调用过程中Filter一般会先出发请求、Intercepter后触发请求;而在响应过程中Intercepter先响应。