当我们使用Spring Boot构建Web应用程序时,HandlerInterceptor 是一个重要的组件,用于拦截请求的处理过程。HandlerInterceptor 接口定义了在请求处理的不同阶段执行的方法,允许我们在请求到达处理程序之前和之后执行自定义逻辑。
在Spring Boot中,我们通常通过实现HandlerInterceptor 接口来创建自定义的拦截器。以下是HandlerInterceptor 接口定义的主要方法:
要使用HandlerInterceptor,我们需要在配置类中注册它。例如,在Spring Boot中,我们可以创建一个继承自WebMvcConfigurerAdapter(在Spring 5中使用WebMvcConfigurer)的配置类,并重写addInterceptors 方法。
@Configuration public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyHandlerInterceptor()).addPathPatterns("/**"); } }
在这个例子中,MyHandlerInterceptor 是我们自定义的拦截器类,它需要实现HandlerInterceptor 接口。
public class MyHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理前执行的逻辑 return true; // 返回 true 允许请求继续,返回 false 则终止请求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在请求处理后、视图渲染前执行的逻辑 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在整个请求完成后执行的逻辑 } }
通过使用HandlerInterceptor,我们可以实现对请求处理过程的精细控制,例如添加全局的身份验证、记录请求日志等功能。
HandlerInterceptorAdapter 是 Spring 提供的一个适配器类,实现了 HandlerInterceptor 接口,并且提供了默认的空实现。它的存在使得我们在实现自定义拦截器时,只需要关注我们感兴趣的方法,而不需要实现所有方法。
具体来说,HandlerInterceptorAdapter 实现了 HandlerInterceptor 接口的三个方法:preHandle、postHandle、和 afterCompletion。默认情况下,这些方法的实现为空,允许我们只重写需要的方法,而不用关心其他方法。
以下是一个简单的例子,展示了如何使用 HandlerInterceptorAdapter:
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理前执行的逻辑 return true; // 返回 true 允许请求继续,返回 false 则终止请求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在请求处理后、视图渲染前执行的逻辑 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在整个请求完成后执行的逻辑 } }
在这个例子中,MyInterceptor 类继承了 HandlerInterceptorAdapter,并重写了 preHandle、postHandle 和 afterCompletion 方法,实现了自定义的拦截逻辑。
然后,我们可以将这个拦截器注册到 Spring MVC 的配置中,就像之前提到的方式一样:
@Configuration public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } }
使用 HandlerInterceptorAdapter 可以让拦截器的实现更加简洁,只需关注自己感兴趣的方法即可。
AsyncHandlerInterceptor 是 HandlerInterceptor 接口的一种扩展,专门用于处理异步请求。与同步请求不同,异步请求在处理过程中可能涉及到线程的切换,因此需要专门的拦截器来支持这种场景。
与普通的 HandlerInterceptor 相比,AsyncHandlerInterceptor 接口增加了对异步请求的支持,它定义了额外的方法来处理异步场景:
要使用 AsyncHandlerInterceptor,我们可以通过实现该接口并将其注册到配置中,就像使用普通的 HandlerInterceptor 一样。以下是一个简单的例子:
public class MyAsyncHandlerInterceptor implements AsyncHandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在异步请求开始前执行的逻辑 return true; // 返回 true 允许请求继续,返回 false 则中断异步请求的处理 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在异步请求的主处理线程完成处理后执行的逻辑 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在整个异步请求完成后执行的逻辑 } @Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在异步请求处理开始时执行的逻辑 } }
然后,将拦截器注册到配置中:
@Configuration public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter { @Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) { configurer.registerCallableInterceptors(new MyAsyncHandlerInterceptor()); } }
在这个例子中,MyAsyncHandlerInterceptor 是实现了 AsyncHandlerInterceptor 接口的自定义异步拦截器。
AsyncHandlerInterceptor 主要用于处理异步请求场景,其中异步请求是指在请求处理过程中,主处理线程可能会在处理的不同阶段释放出来,允许其他线程继续处理请求。以下是一些适合使用 AsyncHandlerInterceptor 的场景:
总的来说,使用 AsyncHandlerInterceptor 的场景通常涉及到异步请求的处理,而这些请求在执行过程中可能涉及到线程的切换和长时间运行的任务。在这些场景中,AsyncHandlerInterceptor 提供了一种机制,允许我们在异步请求的不同阶段执行自定义逻辑,以满足特定需求。
WebMvcConfigurer 接口是 Spring MVC 提供的用于配置 Web MVC 的接口。通过实现这个接口,可以对 Spring MVC 进行一些自定义配置,例如添加拦截器、修改视图解析器、配置消息转换器等。以下是一些常见的用法:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.*; @Configuration public class MyWebMvcConfigurer implements WebMvcConfigurer { // 1. 添加拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } // 这里的 MyInterceptor 是你自定义的拦截器,可以在其中实现需要的拦截逻辑。 // 2. 添加自定义静态资源处理 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } // 这样配置后,访问路径 /static/** 将会映射到 classpath:/static/ 目录下的资源。 // 3. 修改视图解析器 @Override public void configureViewResolvers(ViewResolverRegistry registry) { // 这里可以进行视图解析器的自定义配置,例如: // registry.jsp("/WEB-INF/views/", ".jsp"); // 表示使用 JSP 视图解析器,视图文件位于 /WEB-INF/views/ 目录下,后缀为 .jsp。 } // 4. 配置消息转换器 @Override public void configureMessageConverters(List> converters) { // 这里可以配置消息转换器,例如添加自定义的 JSON 转换器。 // converters.add(new MyJsonConverter()); } // 5. 配置跨域资源共享(CORS) @Override public void addCorsMappings(CorsRegistry registry) { // 配置跨域资源共享,允许 http://localhost:8080 发起的跨域请求访问 /api/** registry.addMapping("/api/**").allowedOrigins("http://localhost:8080"); } // 这是一个简单的例子,允许来自 http://localhost:8080 的请求跨域访问 /api/** 路径。 }
这个配置类通过实现 WebMvcConfigurer 接口,为 Spring MVC 提供了一些自定义配置。具体来说:
在实际应用中,你需要根据具体需求填充这些方法的具体实现,以满足项目的要求。在配置完成后,确保这个配置类被 Spring Boot 应用程序正确地扫描到,以确保这些配置生效。
WebMvcConfigurationSupport 是 Spring MVC 提供的用于进行更深层次自定义配置的基类。
与 WebMvcConfigurer 不同,WebMvcConfigurationSupport 提供的配置更为底层,允许你对 Spring MVC 的默认配置进行更彻底的改变。这里解释一下示例中的各个重要方法:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.*; @Configuration @EnableWebMvc public class MyWebMvcConfig extends WebMvcConfigurationSupport { // 1. 添加拦截器 @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } // 这里的 MyInterceptor 是自定义的拦截器,你可以在其中实现需要的拦截逻辑。 // 2. 添加自定义静态资源处理 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } // 这样配置后,访问路径 /static/** 将会映射到 classpath:/static/ 目录下的资源。 // 3. 修改视图解析器 @Override protected void configureViewResolvers(ViewResolverRegistry registry) { // 在这里可以进行视图解析器的自定义配置,例如: // registry.jsp("/WEB-INF/views/", ".jsp"); // 表示使用 JSP 视图解析器,视图文件位于 /WEB-INF/views/ 目录下,后缀为 .jsp。 } // 4. 配置消息转换器 @Override protected void configureMessageConverters(List> converters) { // 在这里可以配置消息转换器,例如添加自定义的 JSON 转换器。 // converters.add(new MyJsonConverter()); } // 5. 配置跨域资源共享(CORS) @Override protected void addCorsMappings(CorsRegistry registry) { // 配置跨域资源共享,允许 http://localhost:8080 发起的跨域请求访问 /api/** registry.addMapping("/api/**").allowedOrigins("http://localhost:8080"); } // 这是一个简单的例子,允许来自 http://localhost:8080 的请求跨域访问 /api/** 路径。 //------------------------- 其它方法 ----------------------------- // 配置路径匹配 @Override protected void configurePathMatch(PathMatchConfigurer configurer) { // 在这里可以设置路径匹配的行为,例如是否在路径末尾添加斜杠 // configurer.setUseTrailingSlashMatch(false); } // 配置异步请求的支持 @Override protected void configureAsyncSupport(AsyncSupportConfigurer configurer) { // 在这里可以设置异步请求的超时时间、线程池等 // configurer.setDefaultTimeout(30000); } // 配置内容协商策略 @Override protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) { // 在这里可以设置默认的内容类型、请求参数中的内容类型等 // configurer.defaultContentType(MediaType.APPLICATION_JSON); } // 扩展消息转换器 @Override protected void extendMessageConverters(List > converters) { // 在这里可以在已有的转换器列表上进行扩展 // converters.add(new MyAdditionalConverter()); } // 配置默认的 Servlet 处理 @Override protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { // 在这里可以启用或禁用对静态资源的默认 Servlet 处理 // configurer.enable(); } // 添加简单的视图控制器 @Override protected void addViewControllers(ViewControllerRegistry registry) { // 在这里可以添加简单的视图控制器,将某个 URL 直接映射到某个视图 // registry.addViewController("/home").setViewName("home"); } // 扩展异常处理器 @Override protected void extendHandlerExceptionResolvers(List exceptionResolvers) { // 在这里可以在已有的异常处理器列表上进行扩展 // exceptionResolvers.add(new MyAdditionalExceptionResolver()); } // 配置异常处理器 @Override protected void configureHandlerExceptionResolvers(List exceptionResolvers) { // 在这里可以设置异常处理器的顺序和是否开启默认异常处理器 // exceptionResolvers.order(1); // exceptionResolvers.setUseDefaultExceptionHandler(false); } // 配置消息代码解析器 @Override protected void configureMessageCodesResolver(MessageCodesResolver codesResolver) { // 在这里可以设置消息代码的解析策略 // codesResolver.setMessageCodeFormatter(new MyMessageCodeFormatter()); } // 配置视图解析器 @Override protected void configureViewResolvers(ViewResolverRegistry registry) { // 在这里可以设置视图解析器的顺序和是否开启默认视图解析器 // registry.order(1); // registry.enableContentNegotiation(new MappingJackson2JsonView()); } // 添加自定义的参数解析器 @Override protected void addArgumentResolvers(List argumentResolvers) { // 在这里可以添加自定义的参数解析器,可以在已有的解析器列表上进行添加 // argumentResolvers.add(new MyAdditionalArgumentResolver()); } // 添加自定义的返回值处理器 @Override protected void addReturnValueHandlers(List returnValueHandlers) { // 在这里可以添加自定义的返回值处理器,可以在已有的处理器列表上进行添加 // returnValueHandlers.add(new MyAdditionalReturnValueHandler()); } // ......... }
需要注意的是,在使用 WebMvcConfigurationSupport 时,Spring Boot 的默认配置可能会失效,因此需要手动配置一些默认行为。此外,虽然 WebMvcConfigurationSupport 提供更灵活的配置,但也更为底层,可能会增加配置的复杂性。因此,一般情况下推荐使用 WebMvcConfigurer 进行轻量级的配置。只有在需要更深层次的自定义时,才考虑使用 WebMvcConfigurationSupport。
使用WebMvcConfigurationSupport时,Spring Boot的一些默认配置可能会失效,因为WebMvcConfigurationSupport提供了更高级别的自定义配置,可能会覆盖或替代Spring Boot的默认配置。以下是一些可能会受影响的默认配置:
WebMvcAutoConfiguration是Spring Boot自动配置Web MVC的类,当你使用WebMvcConfigurationSupport时,它可能不再生效,因为你自己提供了更高级别的配置。
Spring Boot默认提供了静态资源的处理,例如/static/路径下的资源会被映射到classpath下的/static/目录。使用WebMvcConfigurationSupport时,你可能需要手动配置静态资源处理,因为默认的可能会失效。
WebMvcConfigurationSupport中的configureContentNegotiation方法可以配置内容协商策略,这可能会替代Spring Boot默认的协商策略。
使用configureMessageConverters或extendMessageConverters方法可能会替代或扩展默认的消息转换器。如果你没有显式地配置自己的转换器列表,可能会丢失Spring Boot默认配置的一些消息转换器。
configureHandlerExceptionResolvers和extendHandlerExceptionResolvers方法可以配置异常处理器,这可能会替代或扩展默认的异常处理器。
configureViewResolvers方法可以配置视图解析器,这可能会覆盖Spring Boot默认的视图解析器配置。
总的来说,使用WebMvcConfigurationSupport时,你需要更加谨慎地配置,确保你自己提供的配置不会完全覆盖Spring Boot的默认配置,以免造成意外的问题。通常情况下,建议在必要时使用WebMvcConfigurer接口进行轻量级的配置,而不是直接使用WebMvcConfigurationSupport。
WebMvcConfigurer 和 WebMvcConfigurationSupport 都是用于配置 Spring MVC 的接口/类,但它们有不同的使用场景和适用范围。
选择建议:
通常情况下,绝大多数项目可以通过实现 WebMvcConfigurer 接口来满足配置需求,而无需使用 WebMvcConfigurationSupport。只有在需要非常深度和全面的自定义时,才考虑使用 WebMvcConfigurationSupport。