Spring MVC 시작 과정 소스 코드 분석 상세 설명

12458 단어 SpringMVC시작 과정
오늘 은 소스 차원 에서 Spring mvc 의 초기 화 과정 을 분석 하고 Spring mvc 의 진실 한 베일 을 벗 기 려 고 합 니 다.아마도 우 리 는 모두 spring mvc 를 사용 하 는 것 을 배 웠 거나 spring mvc 의 원 리 는 이론 적 으로 이미 줄줄 외 울 수 있 을 것 입 니 다.시작 하기 전에 이것 은 자바 EE 의 기본 지식 을 습득 해 야 할 수도 있 습 니 다.예 를 들 어 우 리 는 먼저 자바 EE 의 Servlet 기술 규범 을 배 워 야 합 니 다.왜냐하면 Spring mvc 구조 가 실현 되 고 밑바닥 은 Servlet 규범 을 따 르 기 때 문 입 니 다.
소스 코드 분석 을 시작 하기 전에 우 리 는 간단 한 사례 공정 이 필요 할 것 이다.당황 하지 않 고 작은 편집 은 이미 배정 되 었 다.
샘플 프로젝트 다운로드 주소:https://github.com/SmallerCoder/spring-mvc-test
그럼 이제 시작 합 시다!
선행 지식
알다 시 피 우 리 는 spring mvc 를 사용 할 때 보통web.xml파일 에서 다음 과 같은 설정 을 합 니 다.web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 
 
 <!--      ,         -->
 <context-param>
 	<param-name>contextConfigLocation</param-name>
 	<param-value>
  	classpath:applicationContext.xml
  </param-value>
 </context-param>
 
 
 <!--       -->
 <listener>
 	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 
 <!--         -->
 <servlet>
 	<servlet-name>dispatcher</servlet-name>
 	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 	<init-param>
 		<param-name>contextConfigLocation</param-name>
 		<param-value>classpath:applicationContext-mvc.xml</param-value>
 	</init-param>
 	<load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 	<servlet-name>dispatcher</servlet-name>
 	<url-pattern>/</url-pattern>
 </servlet-mapping>

</web-app>
위의 설정 은 요약 하면 몇 가지 내용 이 있 는데 그것 이 바로 Dispatcher Servlet 입 니 다.
우리 가 spring mvc 를 tomcat 에 배치 할 때,tomcat 는 시작 할 때 spring 웹 컨 텍스트 를 초기 화하 지 않 습 니 다.다시 말 하면 tomcat 는 spring 프레임 워 크 를 초기 화하 지 않 습 니 다.spring 의 설정 파일 을 어디 에 두 었 는 지 알려 주지 않 았 기 때 문 입 니 다.어떻게 불 러 오 는 지그래서context-param모니터 가 도움 을 주 었 습 니 다.그런데 왜 모니터 를 설정 한 후에 tomcat 에 어떻게 불 러 오 는 지 알려 줄 수 있 습 니까?listenerservlet 기술 규범 을 실현 한 모니터 구성 요소 이기 때문에 tomcat 는 시작 할 때 먼저 로드DispatcherServlet에 servlet 모니터 가 존재 하 는 지,있 으 면 시작 합 니 다.listener는 spring 프레임 워 크 가 servlet 모니터 에 대한 패키지 로 본질 적 으로 servlet 모니터 이기 때문에 실 행 됩 니 다.그러나listener소스 코드 는web.xmlContextLoaderListener두 개의 설정 매개 변 수 를 바탕 으로 해당 설정 을 불 러 오기 때문에 우리 가 설정 한ContextLoaderListener매개 변수 가 있 습 니 다.contextConfigLocation탭 의 초기 화 매개 변수 도 마찬가지 입 니 다.즉,웹 서버 가 시작 하 는 동시에 spring 웹 컨 텍스트contextClass도 초기 화 되 었 음 을 알려 줍 니 다.
위 에서 tomcat 에 spring mvc 응용 을 불 러 오 는 대체적인 절 차 를 말 했 고 그 다음 에 소스 코드 에 착안 하여 작 동 원 리 를 분석 할 것 이다.
2.Spring MVC 웹 컨 텍스트 시작 소스 분석
현재 우리 가 위context-param파일 의servlet를 제거 했다 고 가정 하면 기본 tomcat 가 시 작 될 때 spring 웹 컨 텍스트 만 초기 화 합 니 다.즉,WebApplicationContext이 파일 만 불 러 옵 니 다.web.xml이 프로필 은 불 러 올 수 없습니다.<load-on-startup>1</load-on-startup>applicationContext.xml을 사용 할 때applicationContext-mvc.xml로 늦 추고 초기 화 하 라 는 뜻 이다.
스프링 웹 이<load-on-startup>1</load-on-startup>표준 을 바탕 으로 봉인 되 었 다 는 것 을 알 고 있 습 니 다.servlet 가 어떻게 초기 화 되 었 는 지,DispatcherServlet웹 상하 문 이 어떻게 초기 화 되 었 는 지 분명 합 니 다.먼저 의 소스 코드 가 어떤 지 봅 시다.

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
 //      
 @Override
 public void contextInitialized(ServletContextEvent event) {
 	initWebApplicationContext(event.getServletContext());
 }
 //     
 @Override
 public void contextDestroyed(ServletContextEvent event) {
 	closeWebApplicationContext(event.getServletContext());
 	ContextCleanupListener.cleanupAttributes(event.getServletContext());
 }
}
servlet클래스 가 실현 되 었 습 니 다WebApplicationContext.본질 적 으로 servlet 모니터 입 니 다.tomcat 는 servlet 모니터 구성 요 소 를 우선 불 러 오고ContextLoaderListener방법 을 호출 합 니 다.ContextLoaderListener방법 에서 호출ServletContextListener방법 으로 Spring 웹 컨 텍스트 를 초기 화 합 니 다.이 를 통 해 알 수 있 듯 이 Spring mvc 의 입구 가 바로 여기에 있 습 니 다.하하~~~빨리 따라 들 어가contextInitialized방법 을 보 세 요!contextInitialized방법:

//   web   ,   XmlWebApplicationContext
if (this.context == null) {
 this.context = createWebApplicationContext(servletContext);
}

if (this.context instanceof ConfigurableWebApplicationContext) {
 ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
 //            
 if (!cwac.isActive()) {
 	if (cwac.getParent() == null) {
 		ApplicationContext parent = loadParentContext(servletContext);
 		cwac.setParent(parent);
 	}
 	//        
 	configureAndRefreshWebApplicationContext(cwac, servletContext);
 }
}
위의 방법 은 두 가지 일 만 했다.
1.spring 웹 용기 가 만 들 어 지지 않 았 다 면 새로운 spring 웹 용 기 를 만 들 고 이 용 기 는 루트 루트 루트 용기 입 니 다.다음 세 번 째 절 에서 말 한 servlet spring 웹 용 기 는 이 용기 에서 만 들 어 졌 습 니 다.
2.용기 설정 및 새로 고침
위 코드 설명 에 따 르 면 기본 으로 만 든 컨 텍스트 용 기 는initWebApplicationContext입 니 다.왜 다른 웹 컨 텍스트 가 아 닙 니까?왜 아래 문맥 의 어떤 것 도 아 닙 니까?

우 리 는 따라 들 어 갈 수 있 습 니 다initWebApplicationContext.기본 값 은initWebApplicationContext()파일 에서 설정 을 불 러 오 는 것 입 니 다.이 파일 의 내용 은 다음 과 같 습 니 다.
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
구체 적 인 실현 은:

protected Class<?> determineContextClass(ServletContext servletContext) {
 //       ,       XmlWebApplicationContext
 String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
 if (contextClassName != null) {
  try {
  	return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
  }
  catch (ClassNotFoundException ex) {
  	throw new ApplicationContextException(
  			"Failed to load custom context class [" + contextClassName + "]", ex);
  }
 }
 else {
  //           ,   org.springframework.web.context.support.XmlWebApplicationContext
  contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
  try {
  	return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
  }
  catch (ClassNotFoundException ex) {
  	throw new ApplicationContextException(
  			"Failed to load default context class [" + contextClassName + "]", ex);
  }
 }
}
위 에서 알 수 있 듯 이 사실 우 리 는 spring 웹 의 컨 텍스트 를 사용자 정의 할 수 있 습 니 다.그러면 우리 가 사용자 정의 컨 텍스트 를 어떻게 지정 합 니까?정 답 은XmlWebApplicationContext에서 지정 한createWebApplicationContext매개 변 수 를 통 해 이 루어 집 니 다.따라서 첫 번 째 소결 끝 에ContextLoader.properties매개 변수 와web.xml가 중요 합 니 다~contextClass매개 변 수 를 따라 가면contextClass다음 그림 을 볼 수 있 습 니 다.

요약:
spring mvc 시작 프로 세 스 는 크게contextConfigLocation라 는 이름 에서 시 작 됩 니 다.servlet 모니터 입 니 다.웹 용기 에 발견 되 고 불 러 올 수 있 습 니 다.모니터contextConfigLocation를 초기 화 한 다음 설정configureAndRefreshWebApplicationContextContextLoaderListener에 따라 웹 용 기 를 만 듭 니 다.ContextLoaderListener매개 변수 값 을 지정 하지 않 으 면,기본 으로 만 든 spring 웹 용기 형식 은contextConfigLocation입 니 다.마지막 단 계 는 설정 한contextClass파일 경로 에 따라 용 기 를 설정 하고 새로 고 치 는 것 입 니 다.
3.Dispatcher Servlet 컨트롤 러 초기 화
자,위 에서 우 리 는 Spring mvc 용기 초기 화의 소스 코드 를 간단하게 분 석 했 습 니 다.우 리 는 영원히 잊 지 않 을 것 입 니 다.우리 가 기본적으로 만 든 용기 유형 은contextClass입 니 다.물론 우 리 는 잊 지 않 을 것 입 니 다.XmlWebApplicationContext에서 우 리 는 중요 한 설정 이 있 습 니 다.그것 이 바로contextConfigLocation입 니 다.다음은XmlWebApplicationContext의 초기 화 과정 을 분석 해 보 겠 습 니 다.web.xml는 servlet 입 니 다.request 요청 을 처리 하 는 servlet 입 니 다.이것 은 spring mvc 의 핵심 입 니 다.모든 요청 이 이 를 거 쳤 고 후속 작업 을 어떻게 수행 해 야 하 는 지 지정 합 니 다.어떻게 보면 문 같 기 때문에 저 는'수문'이 라 고 부 릅 니 다.우리 가 계속 하기 전에 우 리 는 하나의 상식 을 지 켜 야 한다.그것 이 바로--모니터 든 servlet 이 든 모두 servlet 규범 구성 요소 이 고 웹 서버 는 그것들 을 발견 하고 불 러 올 수 있다.
다음은DispatcherServlet의 상속 관 계 를 살 펴 보 자.

이것 을 보고 우 리 는 한눈 에 알 수 있 습 니까?DispatcherServletDispatcherServlet과 같은 종 류 를 계승 하 였 습 니 다.DispatcherServletservlet 기술 규범 에서 http 요청 을 처리 하 는 servlet 입 니 다.이것 은 왜 spring mvc 가DispatcherServlet를 통일 요청 입구 로 하 는 지 설명 하기 어렵 지 않 습 니 다.
하나의 servlet 의 생명 주 기 는HttpServlet->HttpServlet->DispatcherServlet이기 때문에init()어떻게 초기 화 합 니까?위의 계승 도 를 보고 우 리 는service()에 들 어가 보 자.
아니 나 다 를 까,destory()유형 중 하나DispatcherServlet방법 이 있 는데HttpServletBean는 추상 적 인 유형 이다.HttpServletBean방법 은 다음 과 같다.

이 를 통 해 알 수 있 듯 이 방법 은init()으로 수식 하 는 것 이다.HttpServletBean수식 하 는 방법 은 이불 류 에 계승 할 수 없 기 때문이다.즉,자 류 는 똑 같은init()방법 이 없 기 때문이다.이final방법 은final의 입 구 를 초기 화 하 는 것 이다.
이어서 우리 가 따라 가 는init()방법:

방법 에 서 는 첫 번 째 소절 과 다른 웹 용 기 를 초기 화 합 니 다.이 새로운 spring 웹 용 기 는init서 비 스 를 위 한 것 이 며,이 새 용 기 는 첫 번 째 소절 루트 루트 루트 루트 용 기 를 바탕 으로 만 들 어 졌 습 니 다.DispatcherServlet탭 에 설 치 된 초기 화 매개 변 수 는 새 용기 에 추 가 됩 니 다.
이로써FrameworkServlet의 초기 화 는 완성 되 었 고 듣 기 에는 약간 기만 적 이 었 다.그러나 사실은 위의 분석 은 하나의 방법 만 을 중심 으로initServletBean()이 라 고 하 는데 모든 servlet 초기 화 는 이 방법 을 호출 할 것 이다.
요약:dispactherServlet의 초기 화 는 두 가지 일 을 했 습 니 다.첫 번 째 일 은 루트 웹 용기,즉 우리 의 첫 번 째 소절 에 따라 만 든<servlet>다음 에DispatcherSevlet서 비 스 를 위 한 웹 용 기 를 만 드 는 것 입 니 다.두 번 째 일 은 웹.xml 파일 에서init()과 관련 된 설정 을 새 용기 에 불 러 오 는 것 입 니 다.
3.모든 request 호출 요청 은 어떤 과정 을 거 쳤 습 니까?
사실 이것 이 야 말로dispactherServlet컨트롤 러 의 핵심 입 니 다.웹 프레임 워 크 는 요청 을 받 아들 이 고 요청 을 처리 한 다음 에 요청 에 응답 하 는 것 이기 때 문 입 니 다.물론XmlWebApplicationContext단순히 처 리 를 받 아들 이 고 요청 에 응답 하 는 것 이 라면 너무 약 하기 때문에 spring 디자이너 는 많은 새로운 기능 을 추가 했다.예 를 들 어 차단기,메시지 변환기,요청 처리 맵 기 와 여러 가지dispactherServlet이기 때문에 spring mvc 는 매우 강하 다.dispactherServlet류 는 관련 소스 코드 분석 을 하지 않 습 니 다.왜냐하면 이것 은 고정된 집행 절차 이기 때 문 입 니 다.무슨 뜻 입 니까?하나의 request 가 들 어 오 면 대체적으로 이러한 과정 을 겪 습 니 다.
요청 수락->다양한 프로세서dispatcherServlet가 있 는 지->메시지 변환기dispactherServlet가 있 는 지-->응답 요청
위의 모든 단계 에 해당 하 는 구성 요소 가 존재 한다 면 프로젝트 에 관련 된 설정 이 있 으 면 설정 한 구성 요 소 를 실행 하고 마지막 으로 요청 에 응답 합 니 다.따라서 대체적인 절 차 를 알 게 된 후에 request 를 디 버 깅 하고 싶다 면ResolverdispatcherServlet방법 에서 단점 을 찍 을 수 있 습 니 다.코드 를 완성 한 후에 대체적으로 절차 가 많 지 않다 는 것 을 알 게 될 것 입 니 다.
뒷말
본 논문 의 프로젝트 는 전통 적 인 웹.xml 를 바탕 으로 웹 프로젝트 를 불 러 오 는 것 입 니 다.물론 spring mvc 에서 도 우 리 는 주 해 를 바탕 으로 설정 할 수 있 습 니 다.우 리 는 실현Handler을 통 해 자신의 웹 시작 기 를 만 들 수도 있 고 계승HandlerAdapter을 통 해 해당 하 는 spring 웹 용기(위 에서 말 한 루트 용기 와 servlet 웹 용기 포함)를 만 들 수도 있 습 니 다.마지막 으로 계승dispatcherServlet을 통 해 사용자 정의 설정(관련 차단기,bean 등)을 한 단계 더 진행 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기