위의 작업은 일반적으로 컨트롤러 레이어의 인터페이스를 나타냅니다.
2. 인터셉터 커스터마이징
(1) HandlerInterceptor 인터페이스를 구현하기 위한 인터셉터를 작성합니다.
(2) 인터셉터가 컨테이너에 등록됩니다.
(3) 차단 규칙을 구성합니다.
2.1 인터셉터 작성
import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 登录拦截器 */ @Slf4j public class LoginInterceptor implements HandlerInterceptor { /** * 目标方法执行之前执行 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 获取请求路径 String requestUrl = request.getRequestURI(); log.info("请求的路径是: {}", requestUrl); String username = request.getParameter("username"); if (username != null) { // 放行 return true; } request.setAttribute("msg", "请先登录"); // 携带msg跳转到登录页 request.getRequestDispatcher("/").forward(request, response); return false; } /** * 目标方法完成以后执行 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle执行"); } /** * 页面渲染以后执行 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion执行"); } }
2.2 인터셉터 등록 및 구성
import com.codeliu.interceptor.LoginInterceptor; 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 { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") // 拦截所有路径 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); // 不拦截这些路径 } }
모든 경로를 가로채도록 구성하는 경우 정적 리소스를 제외해야 합니다. 그렇지 않으면 이미지 스타일이 가로채어지게 됩니다.
위 단계를 거쳐 시스템에 인터셉터가 추가되도록 구현했습니다. 검증을 시작하시면 됩니다.
3. 인터셉터 원리
디버그 모드에서 애플리케이션을 시작하고, 모든 인터페이스에 액세스하고, 코드 프로세스를 추적합니다.
3.1 요청을 처리할 수 있는 핸들러와 핸들러의 모든 인터셉터를 찾습니다.
여기서 HandlerExecutionChain을 찾았고 세 개의 인터셉터가 있는 인터셉터 체인 Interceptor, 우리의 사용자 정의
및 시스템의 기본 두 개의 인터셉터.LoginInterceptor
3.2 인터셉터의 preHandle 메소드 실행
// 执行拦截器的preHandle方法,如果返回为fasle,则直接return,不执行目标方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 反射执行目标方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
우리는 메소드의 로직을 보기 위해 applyPreHandle 메소드에 들어갑니다
/** * Apply preHandle methods of registered interceptors. * @return {@code true} if the execution chain should proceed with the * next interceptor or the handler itself. Else, DispatcherServlet assumes * that this interceptor has already dealt with the response itself. */ boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { // 遍历拦截器 for (int i = 0; i < this.interceptorList.size(); i++) { HandlerInterceptor interceptor = this.interceptorList.get(i); // 执行当前拦截器的preHandle方法 if (!interceptor.preHandle(request, response, this.handler)) { // 如果preHandle方法返回为false,则执行当前拦截器的afterCompletion方法 triggerAfterCompletion(request, response, null); return false; } // 记录当前拦截器的下标 this.interceptorIndex = i; } return true; }
위의 코드를 통해 우리는 알 수 있습니다 현재 인터셉터의 경우 preHandle 메서드가 true를 반환하면 다음 인터셉터의 preHandle 메서드가 계속 실행되고, 그렇지 않으면 인터셉터의 afterCompletion 메서드가 실행됩니다.
그럼 TriggerAfterCompletion 메소드의 로직을 살펴보겠습니다.
/** * Trigger afterCompletion callbacks on the mapped HandlerInterceptors. * Will just invoke afterCompletion for all interceptors whose preHandle invocation * has successfully completed and returned true. */ void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) { // 反向遍历拦截器 for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); try { // 执行当前拦截器的afterCompletion方法 interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } }
위 코드를 통해 인터셉터의 afterCompletion 메소드가 역으로 실행되는 것을 알 수 있습니다.
3.3 대상 메서드 실행
다음 코드를 통해 타겟 메소드를 실행
// Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
구체적인 내부 실행을 보지 않고 실행 후의 로직을 살펴보겠습니다.
3.4 인터셉터의 postHandle 메소드 실행
mappedHandler.applyPostHandle(processedRequest, response, mv);
applyPostHandle의 로직 보기
/** * Apply postHandle methods of registered interceptors. */ void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { // 反向遍历 for (int i = this.interceptorList.size() - 1; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); // 执行当前拦截器的postHandle方法 interceptor.postHandle(request, response, this.handler, mv); } }
인셉터의 postHandle 메소드를 역순으로 실행
3.5 afterCompletion 실행 인터셉터의 메서드
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
로 이동하여 이 메서드를 입력합니다. 이 메서드는 실행 결과를 처리하고 페이지를 렌더링합니다. 이 메서드의 끝에서 다음 코드를 실행합니다.
3.6 예외 처리
실행을 트리거합니다.
위 내용은 SpringBoot 인터셉터 소스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!