Prologue
-
Spring의 핵심 개념인
-
DispatcherServlet가
-
WebApplicationContext를 생성하는
-
2가지 방법에 대해 알아보자.
DispatcherServlet
생성
-
DispatcherServlet는 1개만 생성하면 된다.
-
이 글에서는 XML or Java로 생성하는 법에 대해 알아본다.
-
만약 XML으로 DispatcherServlet를 생성한다면
WebApplication.java 파일(= Java 방법)은 삭제해도 된다.
-
만약 Java로 DispatcherServlet를 생성한다면
web.xml 파일(= XML 방법)은 삭제해도 된다.
구현체
-
Interface WebApplicationContext를 구현한 다양한 구현체가 있다.
-
그 중 Annotation 기반의 구현체인 AnnotationConfigWebApplicationContext를 사용한다.
Directory
- 프로젝트의 Directory는 다음과 같다.
Example
XML
-
web.xml 생성
-
DispatcherServlet가 사용할 Config 지정
-
DispatcherServlet가 처리할 요청 패턴 명시
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Web Application</display-name>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
최근엔 Annotation 기반의
Spring 프로젝트 개발을 하기 때문에
DispatcherServlet가 생성할
WebApplicationContext의 구현체로
AnnotationConfigWebApplicationContext 구현체를 사용한다.
-->
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<!-- Config 지정 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>be.goodgid.WebConfig</param-value>
</init-param>
</servlet>
<!--
* 요청 처리
* addMapping()의 값으로 `/*`을 지정하면 안된다.
* 자세한건 다음 글을 참고하자.
* https://www.baeldung.com/spring-mvc-404-error#2-incorrect-servlet-mapping
-->
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
WebConfig.java
@Configuration
@ComponentScan
public class WebConfig {
/**
* 특별한 설정은 없다.
* 핸들러가 view name을 Return 시
* Prefix / Suffix를 위한
* viewResolver만 Bean으로 추가
*
* 즉 아래 코드가 없어도 무방한다.
*/
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
}
-
동영상으로 학습을 원한다면 해당 영상을 다운받도록 하자.
Java
- WebApplicationInitializer 를 구현한다.
WebApplication.java
public class WebApplication implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
/**
* AnnotationConfigWebApplicationContext를 인스턴스를 생성한다.
*/
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
/**
* Config를 등록하는데 2가지 방법이 있다.
* 1. context.setConfigLocation()
* 2. context.register()
* 어느것을 사용해도 상관없다.
*/
// context.setConfigLocation("be.goodgid.WebConfig");
context.register(WebConfig.class);
context.refresh();
/**
위에서 생성한 AnnotationConfigWebApplicationContext 인스턴스를
DispatcherServlet 생성자 값으로 전달한다.
public DispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
this.setDispatchOptionsRequest(true);
}
Reference : org.springframework.web.servlet.DispatcherServlet#
DispatcherServlet(org.springframework.web.context.WebApplicationContext)
*/
DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
ServletRegistration.Dynamic app = servletContext.addServlet("dispatcher", dispatcherServlet);
/**
* <url-pattern>의 값으로 `/*`을 지정하면 안된다.
* 자세한건 다음 글을 참고하자.
* https://www.baeldung.com/spring-mvc-404-error#2-incorrect-servlet-mapping
*/
// app.addMapping("/*");
app.addMapping("/");
}
}
WebConfig.java
@Configuration
@ComponentScan
public class WebConfig {
/**
* 특별한 설정은 없다.
* 핸들러가 view name을 Return 시
* Prefix / Suffix를 위한
* viewResolver만 Bean으로 추가
*
* 즉 아래 코드가 없어도 무방한다.
*/
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
}
-
동영상으로 학습을 원한다면 해당 영상을 다운받도록 하자.
Trouble Shooting
AS-IS : servletContext.addServlet("app", dispatcherServlet);
TO-BE : servletContext.addServlet("dispatcher", dispatcherServlet);
CODE :
ServletRegistration.Dynamic app = servletContext.addServlet("app", dispatcherServlet);
app.addMapping("/");
-
servletContext에 Servlet을 등록하는 코드이다.
-
그런데 “app”이란 키워드로
-
등록을 하려했다가 NPE가 발생했다.
-
그 이유는
servletContext.addServlet 메소드의 Returns를 보면
Servlet key에 해당하는 값이
이미 존재하면 null을 return하기 때문에
app.addMapping(“/”); 에서 NPE가 발생했다.
-
그래서 servletContext에 등록되어있는
“app”이란 Key를 사용하면 안된다.
Summary
-
DispatcherServlet가
-
WebApplicationContext를 생성하는 방법으로 2가지 방법에 대해 살펴봤다.
-
XML 사용
-
Java 사용
-
-
필요한 상황에 따라 적절하게 사용을 하자.
-
전체 코드는 Github Repo를 참고하자.
-
Github : goodGid/Inflearn-Web-MVC