Spring MVC 차단기 설정 및 원리 분석

원본 정리 가 쉽 지 않 습 니 다. 전재 출처: Spring MVC 차단기 설정 및 원리 분석 코드 다운로드 주소:http://www.zuidaima.com/share/1751865167973376.htm
SpringMVC 의 차단 기 는 Spring 의 차단기 와 다르다. SpringMVC 는 통 일 된 입구 Dispatcher Servlet 을 가지 고 있 으 며 모든 요청 이 Dispatcher Servlet 을 통과 하기 때문에 Dispatcher Servlet 에 글 을 쓰 면 된다. Dispatcher Servlet 에 도 대리 가 없고 SpringMVC 가 관리 하 는 Controller 에 도 대리 가 없다.
1. Servlet Filter 와 Spring interceptor 의 실행 순서
필터 순서 있어 요?필터 의 실행 순 서 를 어떻게 제어 합 니까?Tomcat 의 코드 분석 을 통 해 servlet 는 Filter 가 실 행 된 후에 야 호출 됩 니 다. 만약 에 여러 개의 filter 가 실행 순 서 를 어떻게 제어 하 는 지 먼저 웹. xml 에 특정한 인 자 를 설정 하 는 것 을 생각 합 니 다. 예 를 들 어 order 와 같은 것 을 찾 아 보 세 요. servlet 에는 이 인자 가 없습니다.filter Mapping 설정 의 우선 순 위 를 시험 해 보 세 요. 과연 유효 합 니 다. 원래 filter 의 실행 순 서 는 filter mapping 이 웹. xml 에서 의 순 서 를 시험 합 니 다.
spring interceptor 도 이러한 실행 순서 입 니 다. 그러나 interceptor 는 하나의 설정 매개 변수 order 를 통 해 interceptor 의 실행 순 서 를 실현 할 수 있 습 니 다.많은 응용 장면 에서 실행 순서 가 중요 하 다. 예 를 들 어 cache 와 transaction interceptor 의 실행 순 서 는 cache 가 transaction 하기 전에 명중 하면 사 무 를 열지 않 아 도 된다 는 것 을 알 수 있다. 만약 에 transaction 이 앞 에 있 으 면 매번 사 무 를 열 어도 cache 가 명중 하 더 라 도 이것 은 불필요 한 동작 이다.
2. springMVC 의 interceptor 를 이용 하여 페이지 성능 모니터링 (Filter 도 가능)
첫 번 째 단 계 를 조정 하여 시간 이 비교적 긴 페이지 를 찾 아 최적화 하 다.interceptor 를 이용 하면 쉽게 해결 할 수 있 습 니 다.interceptor 는 preHandle 과 post Handle, after Complete 세 가지 방법 을 제공 합 니 다.preHandle 은 controller 의 구체 적 인 방법 을 호출 하기 전에 호출 합 니 다. post Handle 은 구체 적 인 방법 을 완성 한 후에 호출 합 니 다. after Complete 는 페이지 에 대한 render 를 완성 한 후에 호출 합 니 다. 이로써 전체 페이지 렌 더 링 이 완 료 됩 니 다.즉, 우리 가 preHandle 에서 시작 하 는 시간 을 기록 하고 after Complete 에서 끝 나 는 시간 을 기록 하면 전체 페이지 가 생 성 되 는 시간 을 기록 할 수 있다 는 것 이다.Spring 은 자체 적 으로 StopWatch 도구 류 를 가지 고 시간 추적 을 실현 합 니 다. 관건 적 인 점 은 interceptor 가 스 레 드 안전 이 아 닙 니 다.우 리 는 threadlocal 을 통 해 스 레 드 안전 을 실현 해 야 한다.
@Override 
public boolean preHandle(HttpServletRequest request, 
		HttpServletResponse response, Object handler) throws Exception { 
	if(usePerformance){ 
		StopWatch stopWatch = new StopWatch(handler.toString()); 
		stopWatchLocal.set(stopWatch); 
		stopWatch.start(handler.toString()); 
	} 
	 
	return true; 
} 

@Override 
public void afterCompletion(HttpServletRequest request, 
		HttpServletResponse response, Object handler, Exception ex) 
		throws Exception { 
	if(usePerformance){ 
		StopWatch stopWatch = stopWatchLocal.get(); 
		stopWatch.stop(); 
		String currentPath = request.getRequestURI(); 
		String queryString  = request.getQueryString(); 
		queryString = queryString == null ? "":"?" + queryString; 
		log.info("access url path:" + currentPath + queryString +  " |time:" + stopWatch.getTotalTimeMillis()); 
		stopWatchLocal.set(null); 
	} 
} 
 

3. SpringMVC 차단기 실현 분석
SpringMVC 의 차단 기 는 Spring 의 차단기 와 다르다. SpringMVC 는 통 일 된 입구 Dispatcher Servlet 을 가지 고 있 으 며 모든 요청 이 Dispatcher Servlet 을 통과 하기 때문에 Dispatcher Servlet 에 글 을 쓰 면 된다. Dispatcher Servlet 에 도 대리 가 없고 SpringMVC 가 관리 하 는 Controller 에 도 대리 가 없다.우리 가 controller 를 실행 하기 전에 어떤 동작 을 하고 어떤 동작 을 하고 render 가 어떤 동작 을 완성 할 것 이 라 고 생각 하기 어렵 지 않 습 니까?SpringMVC 의 차단 기 는 세 개의 preHandle, post Handle, after Complete 방법 을 제공 합 니 다.세 가지 방법 안에 우리 가 필요 로 하 는 논 리 를 쓰 면 된다. 많은 것 이 쓸데없는 말 인지, 아니면 코드 가 진실 한 지. 
 
springMVC 를 사용 하지 않 았 다 면 filter 를 사용 하여 완성 할 수 있 습 니 다:
stopWatch.start(); 
doFilterChain(); 
stopWatch.stop(); 

3. SpringMVC 차단기 실현 분석
SpringMVC 의 차단 기 는 Spring 의 차단기 와 다르다. SpringMVC 는 통 일 된 입구 Dispatcher Servlet 을 가지 고 있 으 며 모든 요청 이 Dispatcher Servlet 을 통과 하기 때문에 Dispatcher Servlet 에 글 을 쓰 면 된다. Dispatcher Servlet 에 도 대리 가 없고 SpringMVC 가 관리 하 는 Controller 에 도 대리 가 없다.우리 가 controller 를 실행 하기 전에 어떤 동작 을 하고 어떤 동작 을 하고 render 가 어떤 동작 을 완성 할 것 이 라 고 생각 하기 어렵 지 않 습 니까?SpringMVC 의 차단 기 는 세 개의 preHandle, post Handle, after Complete 방법 을 제공 합 니 다.세 가지 방법 안에 우리 가 필요 로 하 는 논 리 를 쓰 면 된다. 많은 것 이 쓸데없는 말 인지, 아니면 코드 가 진실 한 지.
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); 
if (interceptors != null) { 
	for (int i = 0; i < interceptors.length; i++) { 
		HandlerInterceptor interceptor = interceptors[i]; 
//ha.handle      controller      preHandle                      if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 
			return; 
		} 
		interceptorIndex = i; 
	} 
} 

// Actually invoke the handler. 
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

호출 이 완료 되면 render () 를 호출 하고 마지막 으로 after Complete () 를 실행 합 니 다.
if (interceptors != null) { 
		for (int i = interceptors.length - 1; i >= 0; i--) { 
			HandlerInterceptor interceptor = interceptors[i]; 
			interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); 
		} 
	} 
} 
catch (ModelAndViewDefiningException ex) { 
	logger.debug("ModelAndViewDefiningException encountered", ex); 
	mv = ex.getModelAndView(); 
} 
catch (Exception ex) { 
	Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 
	mv = processHandlerException(processedRequest, response, handler, ex); 
	errorView = (mv != null); 
} 

// Did the handler return a view to render? 
if (mv != null && !mv.wasCleared()) { 
	render(mv, processedRequest, response); 
	if (errorView) { 
		WebUtils.clearErrorRequestAttributes(request); 
	} 
} 
else { 
	if (logger.isDebugEnabled()) { 
		logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + 
				"': assuming HandlerAdapter completed request handling"); 
	} 
} 

// Trigger after-completion for successful outcome. 
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  

좋은 웹페이지 즐겨찾기