HandlerInterceptor
permet de personnaliser l'interface de workflow de la chaîne d'exécution du processeur handler
. Nous pouvons personnaliser l'intercepteur pour intercepter le processeur du gestionnaire (vous pouvez le comprendre comme l'interface de la couche contrôleur), afin de pouvoir ajouter certains comportements de traitement répétitifs courants (tels que l'authentification de l'interface, la journalisation de l'interface, la surveillance des performances, etc.) sans Modifiez l’implémentation de chaque gestionnaire. HandlerInterceptor
允许定制 handler
处理器执行链的工作流接口。我们可以自定义拦截器用于拦截 handlers 处理器(你可以理解为 controller 层的接口),从而可以添加一些共同的重复性的处理行为(例如接口鉴权,接口日志记录,性能监控等),而不用修改每一个 handler 的实现。
注意,此基于 SpringBoot 2.3.12.RELEASE
版本讲解。
HandlerInterceptor 接口只有三个默认空实现方法,在低版本中这三个方法不是默认方法,而是抽象方法。
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
前置处理,拦截一个处理器(handler)的执行,preHandle 方法会在 HandlerMapping
确定一个适当的处理器对象之后,但在 HandlerAdapter
调用处理器之前被调用。可以简单理解为 controller 接口被调用之前执行。
Intercepter 是链式的,就是一个接着一个执行。如果此方法返回 true,则会执行下一个拦截器或者直接执行处理器。如果此方法返回 false 或者抛出异常则终止执行链,也不再调用处理器。
注意,此方法如果不返回 true,那么 postHandle
和 afterCompletion
不会被执行。
那这个方法有什么用呢?其实可以做一些接口被调用前的预处理,例如用户权限校验。
package com.chenpi; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; /** * @Description 用户权限验证拦截 * @Author 陈皮 * @Date 2021/6/27 * @Version 1.0 */ @Component public class UserPermissionInterceptor implements HandlerInterceptor { @Override public 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
后置处理,会在 HandlerAdapter
调用处理器之后,但在 DispatcherServlet
渲染视图之前被调用。可以在此对 ModelAndView
做一些额外的处理。可以简单理解为 controller 接口被调用之后执行。
注意,此方法在执行链中的执行顺序是倒着执行的,即先声明的拦截器后执行。
afterCompletion 完成之后,在请求处理完之后被执行,也就是渲染完视图之后。一般用于做一些资源的清理工作,配合 preHandle 计算接口执行时间等。
注意,和 postHandle 一样,此方法在执行链中的执行顺序也是倒着执行的,即先声明的拦截器后执行。
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) { // 请求完后,清除当前线程的用户信息 UserContextHolder.removeUserContext(); }
注意,我们自定义的拦截器要通过 WebMvcConfigurer
SpringBoot 2.3.12.RELEASE
. 🎜🎜L'interface HandlerInterceptor n'a que trois méthodes d'implémentation vides par défaut. Dans les versions inférieures, ces trois méthodes ne sont pas des méthodes par défaut, mais des méthodes abstraites. 🎜package com.yzj.ehr.common.config; import com.yzj.ehr.common.context.UserContextResolver; import org.springframework.stereotype.Component; 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.yzj.ehr.common.interceptor.UserPermissionInterceptor; /** * @Description 注册拦截器 * @Author 陈皮 * @Date 2021/6/27 * @Version 1.0 */ @Component public class WebAppConfigurer implements WebMvcConfigurer { private UserPermissionInterceptor userPermissionInterceptor; public WebAppConfigurer(final UserPermissionInterceptor userPermissionInterceptor) { this.userPermissionInterceptor = userPermissionInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { // 匹配所有接口,排除/base/test接口 registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/**") .excludePathPatterns("/base/test"); } }
preHandle
pour intercepter l'exécution d'un processeur (handler), la méthode preHandle sera dans HandlerMapping est appelé après avoir déterminé un objet gestionnaire approprié, mais avant que HandlerAdapter
appelle le gestionnaire. On peut simplement comprendre que l'interface du contrôleur est exécutée avant d'être appelée. 🎜🎜Les intercepteurs sont enchaînés, c'est-à-dire exécutés les uns après les autres. Si cette méthode renvoie vrai, l'intercepteur suivant est exécuté ou le gestionnaire est exécuté directement. Si cette méthode renvoie false ou lève une exception, la chaîne d'exécution est terminée et le gestionnaire n'est plus appelé. 🎜🎜Notez que si cette méthode ne renvoie pas vrai, alors postHandle
et afterCompletion
ne seront pas exécutés. 🎜🎜Alors à quoi sert cette méthode ? En fait, vous pouvez effectuer un prétraitement avant l'appel de l'interface, comme la vérification des autorisations de l'utilisateur. 🎜rrreeepostHandle
le post-traitement sera effectué après que HandlerAdapter
appelle le processeur, mais après DispatcherServlet code> code> est appelé avant le rendu de la vue. Vous pouvez effectuer un traitement supplémentaire sur <code>ModelAndView
ici. On peut simplement comprendre qu'il est exécuté après l'appel de l'interface du contrôleur. 🎜🎜Notez que l'ordre d'exécution de cette méthode dans la chaîne d'exécution est inversé, c'est-à-dire que l'intercepteur déclaré en premier est exécuté plus tard. 🎜WebMvcConfigurer
pour prendre effet. 🎜rrreeeCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!