首先我们,给出一个demo来看下拦截器方法执行顺序:
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("1-1 preHandle: ");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("2-1 postHandle: ");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("3-1 afterCompletion: ");}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebmvcConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor);}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello")public String hello() {System.out.println("controller:");return "hello, zhaoshuai-lc";}
}
在Spring MVC中,拦截器(Interceptor)的三个主要方法preHandle
、postHandle
和afterCompletion
的执行顺序是严格规定的,这些方法的执行时机和顺序对于理解Spring MVC的请求处理流程至关重要。以下是这三个方法的执行顺序的详细解释:
执行顺序
-
preHandle:
- 调用时间:该方法在请求处理之前执行,即Controller方法调用之前。
- 执行顺序:如果有多个拦截器,它们会按照配置的顺序(即拦截器数组中的正向顺序)依次执行。
- 返回值:
- 返回
true
:表示当前拦截器处理通过,请求会继续传递给下一个拦截器(如果有的话),或者如果没有其他拦截器了,就会传递给Controller处理。 - 返回
false
:表示当前拦截器拦截请求,不会继续执行后续的拦截器或Controller方法,而是直接中断执行流程,并会根据情况(如配置)执行afterCompletion
方法(但需要注意的是,不是所有返回false
的拦截器都会执行afterCompletion
,这取决于拦截器的具体配置和是否发生异常)。
- 返回
-
postHandle:
- 调用前提:
preHandle
方法必须返回true
,即请求被正常放行到Controller方法执行之后,但在DispatcherServlet进行视图渲染之前。 - 调用时间:Controller方法处理完请求并返回ModelAndView之后,但在视图渲染之前。
- 执行顺序:如果有多个拦截器,它们会按照配置的逆序(即拦截器数组的反向顺序)执行。
- 注意:如果Controller方法执行过程中抛出异常,将跳过
postHandle
方法,直接执行afterCompletion
方法。
- 调用前提:
总结
方法名 | 调用时机 | 执行顺序(多个拦截器时) | 主要作用 |
---|---|---|---|
preHandle | 请求处理之前,Controller方法调用之前 | 正向顺序 | 决定是否继续执行后续的拦截器或Controller |
postHandle | Controller方法处理完请求后,视图渲染前 | 反向顺序(如果执行) | 对ModelAndView进行操作(如果需要) |
afterCompletion (错误说法) | 整个请求处理结束之后,包括视图渲染之后 | 反向顺序 | 资源清理工作,如关闭数据库连接等 |
这个执行顺序和规则是Spring MVC框架中拦截器机制的核心,理解和掌握它们对于开发高质量的Web应用至关重要。