100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Spring HandlerInterceptor 拦截器实战

Spring HandlerInterceptor 拦截器实战

时间:2020-07-08 21:04:24

相关推荐

Spring HandlerInterceptor 拦截器实战

我是陈皮,一个在互联网 Coding 的 ITer,个人微信公众号「陈皮的JavaLib」关注第一时间阅读最新文章。

文章目录

HandlerInterceptor 详解preHandlepostHandleafterCompletion 注册拦截器

HandlerInterceptor 详解

HandlerInterceptor 是一个允许定制handler处理器执行链的工作流接口。我们可以自定义拦截器用于拦截 handlers 处理器(可以理解为 controller 控制层的接口),从而可以添加一些共同的重复性的处理行为(例如接口鉴权,接口日志记录,性能监控等等),而不用修改每一个 handler 的实现。

注意,此基于SpringBoot 2.5.8版本,即 Spring 5.3.14 版本讲解。

HandlerInterceptor 接口只有3个默认空实现方法,注意在 Spring 低版本中这3个方法不是默认方法,而是抽象方法。

package org.springframework.web.servlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.lang.Nullable;import org.springframework.web.method.HandlerMethod;public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {}}

这三个方法的执行顺序流程如下所示。

preHandle

preHandle 前置处理,拦截一个处理器(handler)的执行,preHandle 方法会在HandlerMapping确定一个适当的处理器对象之后,但在HandlerAdapter调用处理器之前被调用。可以简单理解为 controller 接口被调用之前执行。

Intercepter 是链式的,就是一个接着一个执行。如果此方法返回 true,则会执行下一个拦截器或者直接执行处理器。如果此方法返回 false 或者抛出异常则终止执行链,也不再调用处理器。

注意,此方法如果不返回 true,那么postHandleafterCompletion不会被执行。

那这个方法有什么用呢?其实可以做一些接口被调用前的预处理,例如用户权限校验。

package com.chenpi;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.lang.Nullable;import org.ponent;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerInterceptor;/*** @Description 用户权限验证拦截* @Author 陈皮* @Date /6/27* @Version 1.0*/@Componentpublic class UserPermissionInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;// 获取用户权限校验注解UserAuthenticate userAuthenticate =handlerMethod.getMethod().getAnnotation(UserAuthenticate.class);if (null == userAuthenticate) {userAuthenticate = handlerMethod.getMethod().getDeclaringClass().getAnnotation(UserAuthenticate.class);}if (userAuthenticate != null && userAuthenticate.permission()) {// 验证用户信息UserContext userContext = userContextManager.getUserContext(request);if (null == userContext) {return false;}}}return true;}}

postHandle

postHandle 后置处理,会在HandlerAdapter调用处理器之后,但在DispatcherServlet渲染视图之前被调用。可以在此对ModelAndView做一些额外的处理。可以简单理解为 controller 接口被调用之后执行。

注意,此方法在执行链中的执行顺序是倒着执行的,即先声明的拦截器后执行。

afterCompletion

afterCompletion 完成之后,在请求处理完之后被执行,也就是渲染完视图之后。一般用于做一些资源的清理工作,配合 preHandle 计算接口执行时间等。

注意,和 postHandle 一样,此方法在执行链中的执行顺序也是倒着执行的,即先声明的拦截器后执行。

@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, @Nullable Exception ex) {// 请求完后,清除当前线程的用户信息UserContextHolder.removeUserContext();}

注册拦截器

注意,我们自定义的拦截器要通过WebMvcConfigurer的实现类进行注册,才能生效。

package com.mon.config;import com.mon.context.UserContextResolver;import org.ponent;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import com.mon.interceptor.UserPermissionInterceptor;/*** @Description 注册拦截器* @Author 陈皮* @Date /6/27* @Version 1.0*/@Componentpublic class WebAppConfigurer implements WebMvcConfigurer {private UserPermissionInterceptor userPermissionInterceptor;public WebAppConfigurer(final UserPermissionInterceptor userPermissionInterceptor) {this.userPermissionInterceptor = userPermissionInterceptor;}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 匹配所有接口,排除/base/test接口registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/**").excludePathPatterns("/base/test");}}

本次分享到此结束啦~~

如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。