SpringMVC HandlerInterceptor 기괴 한 문제 조사
5841 단어 SpringMVCHandlerInterceptor
최근 압력 측정 을 실시 한 결과 일부 인터페이스 가 좋 았 다 나 빴 다 하 는 것 을 발견 했다.sentry 로그 플랫폼 과 sky walking 플랫폼 추적 을 통 해 사용자 장 삼 이 얻 은 사용자 컨 텍스트 는 확실히 이사 라 는 것 을 발견 했다.
코드 통학
사용자 로그 인
/**
*
*
* @author : jamesfu
* @date : 22/5/2019
* @time : 9:18 AM
*/
@Data
public class UserContext {
private final static ThreadLocal<UserContext> threadLocal = new ThreadLocal<>();
private Long id;
private String loginName;
public static UserContext get() {
UserContext context = threadLocal.get();
if (context == null) {
// TODO(james.h.fu): token,
context = new UserContext() {{
setId(1L);
setLoginName("james.h.fu1");
}};
threadLocal.set(context);
}
return context;
}
public static void clear() {
threadLocal.remove();
}
public static void set(UserContext context) {
if (context != null) {
threadLocal.set(context);
}
}
}
차단기 에 UserContext.set 를 호출 하여 사용자 로그 인 컨 텍스트 를 복원 하고 요청 이 끝 날 때 UserContext.clear 를 호출 하여 사용자 로그 인 컨 텍스트 를 청소 합 니 다.차단기 등록 설정
/**
*
*
* @author : jamesfu
* @date : 22/5/2019
* @time : 9:15 AM
*/
@Configuration
public class FilterConfig implements WebMvcConfigurer {
@Autowired
private JsonRpcInterceptor jsonRpcInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jsonRpcInterceptor)
.addPathPatterns("/json.rpc");
}
}
debug 를 통 해 UserContext 의 ThreadLocal 청소 가 실행 되 지 않 았 음 을 알 수 있 습 니 다.요청 이 들 어 왔 을 때 ThreadLocal 이 존재 할 수도 있 습 니 다.요청 한 컨 텍스트 에 따라 복구 되 지 않 습 니 다.
springmvc 소스 코드 통독
tomcat 는 http 요청 을 받 은 후 최종 적 으로 spring mvc
DispatcherServlet
에 의 해 처 리 됩 니 다.여기 서 doDispatch 에서 그림 에 따라 준 마 를 찾 아 덩굴 을 더 듬 으 며 아래 를 내 려 다 볼 수 있다.원본 통학:Dispatcher Servlet
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception
요청 은 배 포 된 후 등 록 된 Handler 의 preHandle->post Handle->after Complete 를 실행 합 니 다.소스 코드 통독:HandlerExecutionChain 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 {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
preHandle 이 false 로 돌아 갈 때 이전 트 루 로 돌아 온 handler 에서 차례대로 after Complete 를 실행 합 니 다.자신의 after Complete 는 실행 되 지 않 습 니 다.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)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
triggerAfterComplete 는(1)에 만 이상 이 발생 합 니 다.(2)preHandle 은 false 로 되 돌아 가 거나(3)정상 적 인 실행 이 끝나 야 색인 interceptorIndex 에서 순서대로 실 행 됩 니 다.따라서 상기 소스 코드 를 바탕 으로 차단 기 를 쓸 때 preHandle 이 false 로 돌아 갈 때 after Complete 는 실행 되 지 않 는 다 는 것 을 알 수 있 습 니 다.그래서 일부 필요 한 정리 작업 이 실행 되 지 않 으 면 우리 가 만난 계 정 문자열 과 비슷 한 문제 가 발생 할 수 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ssm 프레임워크 업로드 이미지 로컬 및 데이터베이스에 저장 예시본고는 ssm 프레임워크 업로드 이미지를 로컬과 데이터베이스에 저장하는 예시를 소개하고 주로 Spring+SpringMVC+MyBatis 프레임워크를 사용하여 ssm 프레임워크 업로드 이미지의 실례를 실현했다. 구체...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.