본문 바로가기
카테고리 없음

[자바로 스프링 구현하기] 2. DispatcherServlet

by 서피 2021. 6. 5.

[SpringRealize 프로젝트] - 자바로 스프링 프레임워크 구현하기

 

스프링의 동작을 이해하기 위해 자바 코드로 스프링을 직접 구현해가는 과정이다.

스프링의 각 노드들을 도식화하여, 스프링 프레임워크 코어 지도를 그리는 것이 최종 목적이다.

Spring Framework Core 공식 문서(영문)를 통해 공부하였으므로 의역이 있다.

 

이전 글 - [자바로 스프링 구현하기] 1. IoC 컨테이너


시작하기에 앞서 DispatcherServlet의 동작 순서를 짚어본다.

(1) 클라이언트가 요청을 보내면 WebApplicationContext를 검색해서 요청에 맞는 url을 찾는다.

이 때 DispatcherServlet의 필드변수인 WEB_APPLICATION_CONTEXT_ATTRIBUTE가 이용된다.

(2) request을 인코딩하고 다국어 기능을 적용한다.

(3) 테마 기능을 사용 중이라면, 이 단계에서 테마 기능이 적용된다.

(4) multipart 요청일 경우 MultipartHttpServletRequest를 통해 처리한다.

(5) 요청을 처리할 적합한 handler가 있다면 preprocessors, postprocessors, controller가 실행되어 Model을 렌더링한다.

(6) Model이 렌더링 되었다면 클라이언트로 보낼 view를 준비한다.

스프링 시큐리티 혹은 인터셉터 등에 의해 request가 가로채어져서 model이 렌더링되지 않을 경우도 있다. 이 경우 view가 준비되지 않는다.

 

 

1. pom.xml

pom.xml 파일을 열고, 다음 의존성이 없다면 추가한다.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

<properties>태그 내부에서 스프링 버전을 5.2.5.RELEASE로 설정하고, 자바 버전을 1.8로 올려주었다 (기존 1.6)

<properties>
	<java-version>1.8</java-version>
	<org.springframework-version>5.2.5.RELEASE</org.springframework-version>
    ...
    ...

 

하단의 <build> 태그 내부 maven-compiler-plugin에서 source, target의 값을 자바 버전에 맞춰 각각 1.8로 올려준다.

프로젝트 우클릭 - Maven - Update project... 를 클릭하여 메이븐 업데이트.

 

 

 

2. 설정 파일 생성

com.kdh.dispatcherservlet패키지에 SpringRealizeAppConfig 클래스를 생성.

@ComponentScan - Bean을 스캔할 패키지를 지정

setPrefix - jsp파일 경로의 앞 부분

setSuffix - jsp파일 경로의 뒷 부분

 

@EnableWebMvc
@Configuration
@ComponentScan(basePackages="com.kdh.student.controller")
public class SpringRealizeAppConfig {
	
	@Bean
	public InternalResourceViewResolver viewResolver () {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
}

 

 

 

3. WebApplicationInitializer 생성

동일한 패키지에 SpringRealizeApplicationInitializer.java 클래스를 생성.

SpringRealizeAppConfig.class - 앞서 만든 설정파일의 클래스

addServlet - 이 클래스로 실행할 DispatcherServlet의 이름

setLoadOnStartUp - 양수로 설정할 경우, 서버 시작과 동시에 서블릿을 실행한다. (init 메소드)

    기본값으로 둔다면 첫 번째 request가 전달됐을 때 실행한다.

addMapping - /springrealize.com/* 으로 접속시 해당 springRealizeDispatcherServlet으로 연결한다.

public class SpringRealizeApplicationInitializer implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(SpringRealizeAppConfig.class);
		
		DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
		
		ServletRegistration.Dynamic springRealizeDispatcherServlet = 
				servletContext.addServlet("springRealizeDispatcherServlet", dispatcherServlet);
		
		springRealizeDispatcherServlet.setLoadOnStartup(1);
		springRealizeDispatcherServlet.addMapping("/springrealize.com/*");
	}
}

 

 

 

4. Controller 수정

StudentController.java 클래스를 아래처럼 수정한다.

StudentService는 iocContainer의 싱글턴 인스턴스를 통해 가져온다.

@Controller
public class StudentController {
	
	SpringRealizeIocContainer iocContainer = SpringRealizeIocContainer.getInstance();
	StudentService service;
	
	public StudentController () {
		service = iocContainer.getStudentService();
	}
	
	@RequestMapping("/student")
	public String studentView(HttpServletRequest request) {
		List<String> studentList = service.printStudentNameList();
		request.setAttribute("studentList", studentList);
		return "student";
	}
}

 

 

 

5. view 생성

src/main/webapp/WEB-INF/views/student.jsp 파일을 생성.

간단한 내용을 입력했다.

student.jsp 경로
student.jsp

 

 

6. 서버 실행

직접 설정한 springRealizeDispatcherServlet의 실행이 콘솔에 출력된다.

appServlet은 스프링 기본 서블릿이다.

springRealizeDispatcherServlet 로그

 

 

 

7. 맵핑한 주소로 접속

DispatcherServlet이 정상 설정되었을 경우 localhost:8080/SpringRealize/springrealize.com/student로 접속하면 student.jsp가 보여진다.

localhost:8080 - 톰캣 주소

SpringRealize - 톰캣 프로젝트 Path

springrealize.com - WebApplicationInitializer구현체의 onStartUp메소드에 설정한 맵핑

student - StudentController.java에 설정한 맵핑

 

 

 

 

여기까지 DispatcherServlet의 설정 과정은 완료되었다.

WebApplicationInitializer 클래스를 이용해 DispatcherServlet을 설정했다.

이를 AbstractAnnotationConfigDispatcherServletInitializer 방식으로 변환해본다.

 

8. WebApplicationInitializer

SpringRealizeApplicationInitializer.java클래스를 주석 처리해준다.

 

 

9. AbstractAnnotationConfigDispatcherServletInitializer

SpringRealizeAbstractAnnotationConfigDispatcherServletInitializer.java 클래스를 생성한다.

getServletConfigClasses() - 서블릿 설정파일을 불러오는 메소드이다. SpringRealizeAppConfig.class를 리턴해준다.

getServletMappings() - 서블릿에 맵핑할 url을 설정하는 메소드이다. "/springrealize.com/*"를 리턴해준다.

public class SpringRealizeAbstractAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return null;
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[] {SpringRealizeAppConfig.class};
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] {"/springrealize.com/*"};
	}
}

 

 

10. web.xml

web.xml파일의 이름을 web_unuse.xml로 변경한다.

web.xml에 담겨있던 기존 설정은 SpringRealizeAppConfig.java 클래스에 자바 코드로 넣어주었고, 이를 SpringRealizeAbstractAnnotationConfigDispatcherServletInitializer.java 를 통해 불러오게 되었다.

따라서 더이상 web.xml은 필요하지 않다.

DispatcherServlet 설정을 두 가지로 진행하면 오류가 발생하므로, 이름을 변경하여 web.xml을 인식하지 않도록 한다.

 

 

 

11. pom.xml

pom.xml의 build - plugins 태그 내부에 아래와 같이 plugin 태그를 추가한다.

web.xml이 인식되지 않으면 오류가 발생한다. failOnMissingWebXml을 false로 설정하여 오류를 지워준다. [출처]

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.5</version>
    <configuration>
    	<failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>

 

 

12. 실행

저장 후 서버를 실행하여 localhost:8080/SpringRealize/springrealize.com/student 로 접속한다.

7.의 접속 결과와 동일하면 정상이다.

 

댓글