Intercepter是由Spring提供的Intercepter拦截器,主要应用在日志记录、权限校验等安全管理方便。
使用过程
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 {
}
}
根据源码可看出HandlerInterceptor接口提供了三个default方法,这三个方法作用不同,用户想要自定义个一个指定拦截规则的拦截器,需要重写其中一个或者多个方法,这三个方法作用如下:
自定义一个获取并返回某个静态资源的内容已整个请求所花费时间的时间拦截器
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(MyInterceptor.class);
private static final ThreadLocal START_THREAD_LOCAL = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String uri = request.getRequestURI();
LOGGER.info(uri + " preHandle");
Long startTime = System.currentTimeMillis(); //获取开始时间
START_THREAD_LOCAL.set(startTime); //线程绑定变量(该数据只有当前请求的线程可见)
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
String uri = request.getRequestURI();
LOGGER.info(uri + " postHandle");
Long startTime = START_THREAD_LOCAL.get();//得到线程绑定的局部变量(开始时间)
Long endTime = System.currentTimeMillis(); //2、结束时间
Long time = endTime - startTime;
LOGGER.info("http request all time: " + time + "ms");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
String uri = request.getRequestURI();
LOGGER.info(uri + " afterCompletion");
if (START_THREAD_LOCAL != null) {
START_THREAD_LOCAL.remove(); // 移除ThreadLocal中的局部变量
}
}
}
WebMvcConfigurer源码:
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
default void addInterceptors(InterceptorRegistry registry) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List resolvers) {
}
default void addReturnValueHandlers(List handlers) {
}
default void configureMessageConverters(List> converters) {
}
default void extendMessageConverters(List> converters) {
}
default void configureHandlerExceptionResolvers(List resolvers) {
}
default void extendHandlerExceptionResolvers(List resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
根据源码可以看出,WebMvcConfigurer提供了多个方法,并且也都是default方法,也是根据我们自定义配置,重写其中一个或者多个方法,这里就介绍两个常用的方法:
实例:
import com.eureka.intercrpotor.MyInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor()) // 添加拦截器
.addPathPatterns("/**") // 配置拦截请求url( ** 表示拦截所有请求url)
.excludePathPatterns("/hello"); // 排除某些不需要拦截的请求url(即带有/hello请求不会被拦截)
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**") // 配置需要添加静态资源的请求url
.addResourceLocations("classpath:/mydata/"); //配置静态资源路径
}
}
测试:
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/interceptor")
public ResponseEntity testInterceptor() {
return ResponseEntity.ok("successful");
}
}
静态资源:
启动项目后访问 localhost:60011/test/interceptor:
控制台打印的日志:
我们再通过url访问静态资源请求 localhost:60011/test.jpg