HandlerInterceptor
ermöglicht die Anpassung der Workflow-Schnittstelle der Ausführungskette des handler
-Prozessors. Wir können den Interceptor so anpassen, dass er den Handler-Prozessor abfängt (Sie können ihn als Schnittstelle der Controller-Schicht verstehen), sodass wir einige häufige sich wiederholende Verarbeitungsverhalten (z. B. Schnittstellenauthentifizierung, Schnittstellenprotokollierung, Leistungsüberwachung usw.) ohne hinzufügen können Ändern Sie die Implementierung jedes Handlers. 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
basiert. #🎜🎜##🎜🎜#Die HandlerInterceptor-Schnittstelle verfügt nur über drei standardmäßige leere Implementierungsmethoden. In niedrigeren Versionen sind diese drei Methoden keine Standardmethoden, sondern abstrakte Methoden. #🎜🎜#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"); } }#🎜🎜#Das Ausführungssequenzdiagramm dieser drei Methoden lautet wie folgt: #🎜🎜##🎜🎜##🎜🎜#
preHandle
Bei der Vorverarbeitung wird die Ausführung eines Handlers abgefangen. Die preHandle-Methode wird aufgerufen, nachdem HandlerMapping
ein geeignetes Handlerobjekt ermittelt hat, aber bevor HandlerAdapter
den Prozessor aufruft. Es kann einfach verstanden werden, dass die Controller-Schnittstelle ausgeführt wird, bevor sie aufgerufen wird. #🎜🎜##🎜🎜#Intercepter wird angekettet, das heißt, einer nach dem anderen hingerichtet. Wenn diese Methode „true“ zurückgibt, wird der nächste Interceptor oder Handler direkt ausgeführt. Wenn diese Methode false zurückgibt oder eine Ausnahme auslöst, wird die Ausführungskette beendet und der Handler nicht mehr aufgerufen. #🎜🎜##🎜🎜#Beachten Sie, dass postHandle
und afterCompletion
nicht ausgeführt werden, wenn diese Methode nicht „true“ zurückgibt. #🎜🎜##🎜🎜#Was nützt diese Methode also? Tatsächlich können Sie vor dem Aufruf der Schnittstelle einige Vorverarbeitungen durchführen, z. B. die Überprüfung der Benutzerberechtigungen. #🎜🎜#rrreeepostHandle
Die Nachbearbeitung erfolgt, nachdem HandlerAdapter
den Prozessor aufruft , wird aber aufgerufen, bevor DispatcherServlet
die Ansicht rendert. Hier können Sie ModelAndView
weiter bearbeiten. Es kann einfach verstanden werden, dass es nach dem Aufruf der Controller-Schnittstelle ausgeführt wird. #🎜🎜##🎜🎜#Beachten Sie, dass die Ausführungsreihenfolge dieser Methode in der Ausführungskette umgekehrt ist, dh der zuerst deklarierte Interceptor wird später ausgeführt. #🎜🎜#WebMvcConfigurer
registriert werden muss . #🎜🎜#rrreeeDas obige ist der detaillierte Inhalt vonSo verwenden Sie den SpringBoot-Interceptor. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!