Spring Boot攔截器Intercepter詳解
Intercepter是由Spring提供的Intercepter攔截器,主要應(yīng)用在日志記錄、權(quán)限校驗等安全管理方便。
使用過程
1.創(chuàng)建自定義攔截器,實現(xiàn)HandlerInterceptor接口,并按照要求重寫指定方法
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 {
}
}
根據(jù)源碼可看出HandlerInterceptor接口提供了三個default方法,這三個方法作用不同,用戶想要自定義個一個指定攔截規(guī)則的攔截器,需要重寫其中一個或者多個方法,這三個方法作用如下:
- perHandle:preHandle方法的作用是,當請求在進入controller之前攔截請求,對請求進行預(yù)處理,比如登錄驗證(cookie,token,referer)或者單點登錄cookie解析都可以在這方法中進行。該方法的返回值,如果返回true,表示放行至controller業(yè)務(wù)層,如果false,表示請求非法,結(jié)束請求并返回錯誤信息。
- postHandler:postHandle方法是在請求被controller處理完但是還未傳遞到業(yè)務(wù)模板進行渲染攔截,即controller處理完,返回ModelAndView 之前執(zhí)行該方法,可以操控ModelAndView的值;所以該方法多了一個參數(shù),ModelAndView,這個參數(shù)包含了controller處理完后需要傳遞的Model參數(shù),因此,我們可以在該方法通過ModelAndView對象對返給前端的額視圖做一定的修改。
- afterCompletion:afterCompletion方法作用就是做些收尾工作,在ModelAndView返回前端進行渲染后執(zhí)行,比如有時候我們需要把每個線程的局部變量(如User信息)放入到TheradLocal中,為了防止內(nèi)存泄露,在最后需要清除ThreadLocal的內(nèi)容,此操作就可以放在該方法中執(zhí)行。
自定義一個獲取并返回某個靜態(tài)資源的內(nèi)容已整個請求所花費時間的時間攔截器
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<Long> 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); //線程綁定變量(該數(shù)據(jù)只有當前請求的線程可見)
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、結(jié)束時間
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中的局部變量
}
}
}
2.添加配置類,實現(xiàn)WebMvcController接口,并添加@Configuration注解,在配置類中,重寫addIntercepters方法,添加要攔截的url以及url白名單(需要排除攔截的url)
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<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
根據(jù)源碼可以看出,WebMvcConfigurer提供了多個方法,并且也都是default方法,也是根據(jù)我們自定義配置,重寫其中一個或者多個方法,這里就介紹兩個常用的方法:
- addInterceptors:從該方法名就可以了解到該方法是添加攔截器,即將攔截器交給IOC去執(zhí)行,攔截器需要攔截的路徑以及需要排除攔截的路徑在該方法中配置。
- addResourceHandlers:該方法的作用是配置靜態(tài)資源路徑。即某些請求需要讀取某個路徑下的靜態(tài)資源內(nèi)容,需要配置該靜態(tài)資源的路徑,通過該方法可以統(tǒng)一給這些請求配置指定靜態(tài)資源路徑?。
實例:
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("/**") // 配置需要添加靜態(tài)資源的請求url
.addResourceLocations("classpath:/mydata/"); //配置靜態(tài)資源路徑
}
}
測試:
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<String> testInterceptor() {
return ResponseEntity.ok("successful");
}
}
靜態(tài)資源:
?啟動項目后訪問 localhost:60011/test/interceptor:
?控制臺打印的日志:
?我們再通過url訪問靜態(tài)資源請求 localhost:60011/test.jpg文章來源:http://www.zghlxwxcb.cn/news/detail-643364.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-643364.html
到了這里,關(guān)于SpringBoot自定義攔截器interceptor使用詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!