Interceptor可以在请求处理之前,请求处理之后进行干预,所以我们可以利用拦截器的特性进行一些例如日志打印,身份认证和授权,错误管理,接口限流等。
1 使用拦截器
- 通过实现HandlerInterceptor接口自定义拦截器。
- 添加自定义拦截器到WebMvcConfigurerAdapter
1.1 实现自定义拦截器
我们打印出日志查看拦截器执行的顺序。
public class UriInterceptor implements HandlerInterceptor{
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("UriInterceptor preHandle controller 执行之前");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.info("UriInterceptor postHandle controller 执行之后,渲染视图之前");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.info("UriInterceptor afterCompletion 渲染视图之后");
}
}
1.2 添加自定义拦截器到WebMvcConfigurerAdapter
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
@Bean
public UriInterceptor uriInterceptor(){
return new UriInterceptor();
}
/*
* 自定义拦截器添加到拦截器链中
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**");匹配所有请求
// addPathPatterns("*.do");匹配.do结尾的请求
registry.addInterceptor(uriInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
1.3 请求测试
@GetMapping("index")
public String demo(){
logger.info("DemoController index 正在执行!");
return "查看拦截器的顺序";
}
查看执行日志记录
请求先到拦截器的preHandle,再到控制器,再到postHandle ,再到afterCompletion 。
[nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor : UriInterceptor preHandle controller 执行之前
[nio-8080-exec-1] c.l.s.web.controller.DemoController : DemoController index 正在执行!
[nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor : UriInterceptor postHandle controller 执行之后,渲染视图之前
[nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor : UriInterceptor afterCompletion 渲染视图之后
2 我们通过拦截器实现登录验证?
- 定义接口白名单,例如首页,登录页,问题页,部分活动页不需要登录授权就可以访问。
- 获取token。
- token校验。
token的生成规则可以参考标准的JWT,或者自己内部定义即可。
一般包括如下信息:用户标识信息,时间戳,签名算法,随机数
例如 UID+时间戳(13位)+MD5+随机数
// 定义接口白名单
private static String[] INTERFACE_WHITE_LIST = {"login","index"};
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("UriInterceptor preHandle controller 执行之前");
String requestUri = request.getRequestURI();
// 如果在接口白名单之前放行
if (isWhilteList(requestUri)) {
return true;
}
// 方案一 从请求头获取token
String token = request.getHeader("token");
// 方案二 从cookie获取token
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")) {
token = cookie.getValue();
}
}
// token校验
if (isMatch(token,request)) {
// 判断token是否符合规则
// token解析
// 判断token是否正确
// 判断token是否过期
// 把用户信息放入request请求中
}
return false;
}
多个拦截器是怎么执行的?大家可以尝试一下,其实就是你添加到拦截器链中的先后顺序决定。
源码下载 :Github
网友评论