[Spring] springframework.DispatcherServlet 구조
org.springframework.web.servlet.DispatcherServlet
DispatcherServlet은 이름에도 쓰여있듯이 Servlet 파일이다. Spring에서는 페이지 이동 구분을 ViewResolver가 해주기 때문에 ViewResolver에 대한 의존성을 가지고 있으며, 객체관리를 위해 HandlerMapping을 사용하기 때문에 HandlerMapping에 대한 의존성도 가지고 있다.
그 외의 형태는 JSP기반 FrontController와 유사한 형태를 가지고 있다.
1. 사용자의 요청을 추출
2. 요청에 해당하는 기능을 수행 (HandlerMapping사용)
3. 응답 (ViewResolver사용)
Servlet으로 구조를 보면 이러한 형태를 가지고 있다고 볼 수 있다.
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver;
public DispatcherServlet() {
super();
}
public void init() {
this.handlerMapping = new HandlerMapping();
this.viewResolver = new ViewResolver();
//세터주입
this.viewResolver.setPrefic("./");
this.viewResolver.setSuffix(".jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 사용자(클라이언트,브라우저)의 요청 추출
String uri=request.getRequestURI();
String command=uri.substring(uri.lastIndexOf("/"));
// 2. 요청에 해당하는 Controller 기능을 수행
// 팩토리 패턴을 활용하는 handlerMapping
String path=this.handlerMapping.getController(command).execute(request, response);
// 3. 응답(페이지 이동)
//viewResolver를 사용하여 응답
if(!path.contains(".do")){
this.viewResolver.getView(path); //뷰로 갈 수 있게 요청완성
}
response.sendRedirect(path);
}
}
DispatcherServlet은 오래된 코드이므로 생성자가 아닌 init을 통해 초기화하고 있다.
DispatcherServlet은 springframework에서 제공하고 있는데, web.xml(톰캣)에서 태그로 생성해줄 수 있다.
일반 @WebServlet이 대체한 태그와 동일한데, 클래스를 불러오는 곳이 springframework이다.
<servlet>
<servlet-name>ds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--스프링에서 제공하는 Servlet 사용-->
</servlet>
<servlet-mapping>
<servlet-name>ds</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
ds라는 이름으로 DispacherServlet을 불러오고 있으며, 이 ds는 .do로 끝나는 모든 요청을 처리한다.
ds는 ds(설정한 서블릿명)-servlet.xml라는 설정 파일을 필요로 하므로 web-inf 하위에 생성해야한다.
ds-servlet.xml에는 DispacherServlet이 의존성을 가지고 있는 HandlerMapping과 ViewResolve가 등록되어 있어야한다.
(1007 아직 ViewResolve 진도가 덜 나가 여기까지 정리했다.)
(1008 VeiwResolver 진도 후 추가)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--HandlerMapping과 ViewResolver에 대한 의존성을 가지고 있으므로 추가-->
<!--ds의 HandlerMapping은 한 개라 id 생략가능-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<!--SI 주입-->
<property name="mappings">
<props>
<!--<prop key="키 값 ">밸류 값</prop>-->
<prop key="/login.do">login</prop>
<prop key="/boardWrite.do">boardWrite</prop>
</props>
</property>
</bean>
<!--Bean 등록-->
<bean class="com.koreait.app.view.member.LoginController" id="login"/>
<bean class="com.koreait.app.view.board.BoardWriteController" id="boardWrite"/>
<!--어노테이션 스캔-->
<!--컨트롤러 Autowired 스캔 이후 Repository도 필요하므로 같이 스캔-->
<context:component-scan base-package="com.koreait.app.view"/>
<context:component-scan base-package="com.koreait.app.biz"/>
<!--ViewResolver는 여러 개 될 수 있으므로 id를 반드시 기입-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<!--SI 주입-->
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
HandlerMapping을 등록하기 위해서는 생성할 객체에 대한 Bean이 필요하고 해당 Controller 객체와 Controller 객체가 의존하는 객체가 어노테이션으로 설정되어 있기 때문에 해당 어노테이션을 인지할 수 있도록 context:compent-scan 태그를 사용해 스캔 범위를 지정한다.
ViewResolver에서는 SI주입(setter 주입)을 통해 String 값에 대한 의존성을 주입할 수 있으며, 웹 페이지 구동 시 데이터가 필요한 페이지는 사용자가 함부러 접근할 수 없는 WEB-INF 하위에 있으므로 필요한 경로를 작성한다.
다시 말해 ViewResolver는 WEB-INF 하위에 있는 페이지에 접근할 때만 사용된다. 사용하지 않을 때는 path앞에 redirect:를 붙여 해당 요청이 리다이렉트이고 ViewResolver를 사용하지 않을 것임을 설정할 수 있다.