1.概述
spring会加载所有实现了HandlerInterceptor的bean,这里使用的是拦截器设计模式,在请求处理前调用拦截器的preHandle方法,在处理完成调用拦截器的postHandle方法,在渲染完成后调用拦截器的afterCompletion方法
2.源码
/* * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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; /** * 工作流接口,允许自定义处理程序执行链。 * 应用程序可以注册任意数量的现有或自定义拦截器 * 对于某些处理程序组,添加常见的预处理行为 * 无需修改每个处理程序实现。 * * <p>在适当的HandlerAdapter之前调用HandlerInterceptor * 触发处理程序本身的执行。可以使用这种机制 * 适用于大量的预处理方面,例如用于授权检查 * 或常见的处理程序行为,例如语言环境或主题更改。其主要目的 * 是为了排除重复的处理程序代码。 * * <p>在异步处理方案中,处理程序可以在 * 在主线程退出时不渲染或调用该线程而分离线程 * {@code postHandle}和{@code afterCompletion}回调。并发时 * 处理程序执行完成,将请求分派回去 * 继续渲染模型,并调用该合同的所有方法 * 再次。有关更多选项和详细信息,请参见 * {@code org.springframework.web.servlet.AsyncHandlerInterceptor} * * <p>通常每个HandlerMapping bean定义一个拦截器链, * 共享其粒度。为了能够应用某些拦截器链 * 对于一组处理程序,需要通过一个处理程序映射所需的处理程序 * HandlerMapping bean。拦截器本身被定义为bean * 在应用程序上下文中,由映射bean定义引用 * 通过其“拦截器”属性(在XML中:<ref>的<list>)。 * * <p> HandlerInterceptor基本上类似于Servlet过滤器,但在 * 与后者相反,它仅允许使用选项进行自定义预处理 * 禁止执行处理程序本身和自定义后处理。 * 过滤器功能更强大,例如,它们允许交换请求 * 和传递到链上的响应对象。注意一个过滤器 * 在web.xml(在应用程序上下文中的HandlerInterceptor)中进行配置。 * * <p>作为基本准则,与处理程序相关的细粒度预处理任务是 * HandlerInterceptor实现的候选对象,尤其是分解后的实现 * 通用处理程序代码和授权检查。另一方面,过滤器 * 非常适合请求内容和视图内容处理,例如多部分 * 表格和GZIP压缩。这通常会显示何时需要映射 * 过滤某些内容类型(例如图像)或所有请求。 * * @author Juergen Hoeller * @see HandlerExecutionChain#getInterceptors * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter * @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors * @see org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor * @see org.springframework.web.servlet.i18n.LocaleChangeInterceptor * @see org.springframework.web.servlet.theme.ThemeChangeInterceptor * @see javax.servlet.Filter * @since 20.06.2003 */ public interface HandlerInterceptor { /** * 拦截处理程序的执行。在确定HandlerMapping之后调用 * 适当的处理程序对象,但在HandlerAdapter调用处理程序之前。 * <p> DispatcherServlet处理执行链中的处理程序,包括 * 任意数量的拦截器,最后是处理程序本身。 * 使用这种方法,每个拦截器都可以决定中止执行链, * 通常发送HTTP错误或编写自定义响应。 * <p> <strong>注意</ strong>:特殊注意事项适用于异步 * 请求处理。有关更多详细信息,请参见 * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}。 * <p>默认实现返回{@code true}。 * * @return {@code true},如果执行链应该继续执行 * 下一个拦截器或处理程序本身。否则,DispatcherServlet假设 * 该拦截器已经处理了响应本身。 * @throws Exception in case of errors * @param请求当前的HTTP请求 * @param响应当前的HTTP响应 * @param处理程序选择要执行的处理程序,用于类型和/或实例评估 */ default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * 拦截处理程序的执行。实际上在HandlerAdapter之后调用 * 调用处理程序,但在DispatcherServlet呈现视图之前。 * 可以通过给定的ModelAndView将其他模型对象公开给视图。 * <p> DispatcherServlet处理执行链中的处理程序,包括 * 任意数量的拦截器,最后是处理程序本身。 * 使用这种方法,每个拦截器都可以对执行进行后处理, * 以执行链的相反顺序应用。 * <p> <strong>注意</ strong>:特殊注意事项适用于异步 * 请求处理。有关更多详细信息,请参见 * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}。 * <p>默认实现为空。 * * @param request 当前的HTTP请求 * @param response 当前的HTTP响应 * @param handler 启动异步处理程序(或{@link HandlerMethod}) * 执行,用于类型和/或实例检查 * @param modelAndView 处理程序返回的{@code ModelAndView} * (也可以是{@code null}) * @throws Exception 如果有错误 */ default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * 完成请求处理后(即渲染后)的回调 * 风景。将在处理程序执行的任何结果上被调用,从而允许 * 用于适当的资源清理。 * <p>注意:仅当此拦截器的{@code preHandle}时才被调用 * 方法已成功完成并返回{@code true}! * <p>与{@code postHandle}方法一样,该方法将在每个 * 链中的拦截器的顺序相反,因此第一个拦截器将是 * 最后被调用。 * <p> <strong>注意</ strong>:特殊注意事项适用于异步 * 请求处理。有关更多详细信息,请参见 * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}。 * <p>默认实现为空。 * * @param request 当前的HTTP请求 * @param response 当前的HTTP响应 * @param handler 启动异步处理程序(或{@link HandlerMethod}) * 执行,用于类型和/或实例检查 * @param ex 处理程序执行时抛出的任何异常(如果有);这不 * 包含已通过异常解析器处理的异常 * @throws Exception 如果有错误 */ default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
3.在DispatcherServlet中的使用