1.
컨테이너 (Container)
== 객체를 생성하는 주체.
== 개발자가 (.xml) 설정만 해주면, new를 스스로 관리 한다.
== "객체 생성 및 관리를 스스로 처리" 한다.
컨테이너는 인공지능이 아니기 때문에,
개발자가 반드시 .xml 파일 내부에서 기능 설정을 작성해 줘야 한다.
2.
web.xml
톰캣 == 서블릿 컨테이너 에게 설정을 알려주는 파일 이다.
서블릿 컨테이너니까, 서블릿 관련 설정을 모두 web.xml 에서 할 수 있다.
그래서, 필터 서블릿도 여기서 등록 한다.
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
3.
서블릿 클래스에 대한 설정은 아래와 같이 작성 하면 된다.
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- <servlet-class>com.spring.view.controller.DispatcherServlet</servlet-class> -->
</servlet>
<servlet-name> 태그는
<bean> 태그 | @Component | new 의 기능을 하는 태그 이다.
위의 코드는,
기존, FrontController.java 에서 @WebServlet 로 작성 되어 있었다.
DispatcherServlet 이라는 이름으로 서블릿을 객체화 하기 위한 태그 이고,
서블릿 매핑에 대한 설정도 해줘야 한다.
4.
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
위의 코드는 서블릿 객체의 매핑에 대한 설정으로,
해당 서블릿 객체가 언제 동작 할지에 대한 설정 이다.
위의 코드는,
기존, FrontController.java 에서 @WebServlet("*.do") 로 작성 되어 있었다.
5.
정리하자면,
web.xml 파일 내부의 코드는 아래와 같다.
6.
서버가 동작 ? == 톰캣이 동작
톰캣이 동작 ? == 서블릿 컨테이너 동작 ( == web.xml 로딩)
즉, Xxx컨테이너는 반드시, Xxx.xml 설정 파일이 있어야 한다.
서블릿 컨테이너는, web.xml 이 있어야 동작 된다 !
7.
이제 서버가 동작 했을 때, 서블릿 컨테이너를 객체화 하고, 매핑 했기 때문에,
실제로, DispatcherServlet.xml 파일이 필요 하다.
이때,
DispatcherServlet 서블릿 내부에서 의존관계로 사용되는,
HandlerMapping 클래스와,
ViewResolver 클래스에
의존 주입 (DI) ( == 객체화) 하기 위해서,
해당 아이들에 대한 객체화 설정을 위한 !
.xml 파일을 생성해 준다.
이름은,
DispatcherServlet-servlet.xml 이라고 이름을 지어 준다.
이렇게 이름을 작성 하는 이유는,
어떤 메인이 되는 자료형 (클래스명, 클래스, ..)의 의존관계로 사용 되는
멤버에 .xml 기능 설정 파일 내부에서 의존 주입을 하려고 하려면,
서블릿명-servlet 이라고 지어 주면 된다.
규칙상, 이렇게 짓는거라고 생각하자.
DispatcherServlet-servlet.xml 내부 코드를 확인 하기.
코드를 보면, 이전에 구조 파악을 위해서, 자바에서 클래스를 만들었던,
HandlerMapping,
ViewResolver
가 작성 되어 있는 모습을 볼 수 있다.
이것은
DispatcherServlet 을 포함 해서,
HandlerMapping,
ViewResolver
까지
모두 Spring 에서 기본 제공 해주기 때문에,
기존에 com.spring.view.controller 하위 폴더 (패키지) 에 있었던,
DispatcherServlet,
HandlerMapping,
ViewResolver
클래스를 지운 모습을 확인 할 수 있다.
암튼,
HandlerMapping,
ViewResolver
를
DispatcherServlet.xml 내부에서 설정 하기 위해서는 아래와 같은 코드를 작성 한다.
1) HandlerMapping
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name = "mappings">
<props>
<prop key = "/main.do">main</prop> <!-- 키값에 대한 value 객체를 반환 -->
<prop key = "/login.do">login</prop>
<prop key = "/logout.do">logout</prop>
<prop key = "/insertBoardPage.do">insertBoardPage</prop>
<prop key = "/insertBoard.do">insertBoard</prop>
</props>
</property>
</bean>
<!-- Controller -->
<bean class = "com.spring.view.controller.MainController" id = "main" />
<bean class = "com.spring.view.controller.LoginController" id = "login" />
<bean class = "com.spring.view.controller.LogoutController" id = "logout" />
<bean class = "com.spring.view.controller.InsertBoardPageController" id = "insertBoardPage" />
<bean class = "com.spring.view.controller.InsertBoardController" id = "insertBoard" />
HandlerMapping 클래스 내부는 HashMap 으로 이루어져 있고,
키 (사용자 요청) 에 대한 값으로 필요한 자료형의 객체를 반환 한다.
그래서, Controller 인터페이스를 구현한 여러 XxxController 자료형의 객체들을
반환하는 개념인데,
이 Controller도 Spring에서 기본 제공 해주는 인터페이스 이기 때문에,
DispatcherServlet-servlet.xml 설정 파일 내부에서 설정을 해줄 수 있다.
의존주입을 setter 방식으로 했었기에, <property> 태그를 사용한다.
그래서, <bean> 태그를 사용해서 객체화를 하는 모습을 확인 할 수 있다.
싱글톤 패턴이 유지 되는 개념 이다.
Controller.java 인터페이스를 지웠지만,
implements가 된다.
왜 ? Spring 에서 제공 해주는 Controller 인터페이스를 import 해서 !!
이때, Spirng 에서 기본 제공 해주는 Controller 인터페이스 내부의
handleRequest() 메서드의 반환타입은 ModelAndView 이기 때문에,
내가 직접 작성 했었던,
Controller 인터페이스때, handleRequest() 메서드의
반환 타입이 String 이였지만,
이제는 handleRequest() 메서드의 반환타입이 ModelAndView 니까
이것을 강제 해야 하는 차이점이 생겼다.
그냥 그렇게 되있으니까 그대로 따라 하면 된다.
ModelAndView 도 Spring 에서 기본 제공 해주는 클래스 이기에,
얘도 import 해서 사용 하면 된다 ~
사용 예시는 아래와 같다.
반환 타입이 ModelAndView 로 변경 된 코드를 확인 할 수 있다.
이때 mav.setViewName() 의 인자의 모습이 다른것을 볼 수 있는데,
redirect: 를 붙히는지, 붙히지 않는지의 차이 이다.
ViewResolver를 통해야만 한다면 redirect: 를 붙혀 준다.
이것을 붙혀 주면, ViewResolver의 get() 메서드의 인자로 viewName이
들어가지 않게 된다.
바로 View로 보내야 한다 >> redirect: 를 붙히지 않기.
바로 View로 보내지 않는다 >> Controller에게 .do 요청을 보낸다 >> redirect: 를 붙히기.
참고로, ViewResolver는 디폴트값이 forward 방식 으로 되어 있다.
이 부분은 아래에서, ViewResolver 을 정리 하면서 자세히 정리 하겠다.
2) ViewResolver
<!-- ViewResolver -->
<bean id = "viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value = "/WEB-INF/views/" />
<property name = "suffix" value = ".jsp" />
</bean>
DispatcherServlet-servlet.xml 설정 파일 내부에서,
위와 같이 작성 되어 있다.
의존주입을 setter 방식으로 했었기에, <property> 태그를 사용한다.
프로퍼티의 값은 객체가 아니기에, <bean> 태그를 사용해서 객체화를 할 필요가 전혀 없다.
단순히 value 값이 String 문자열 이기 때문에, 위와 같이 코드를 작성 하면 된다.
이때,
HandlerMapping 과 다르게, ViewResolver는 id값이 반드시 있어야 돌아간다.
즉, 참조변수명 == 객체명 이 반드시 필요 하다.
(왜 반드시 필요 했지 ..?)
그래서 <bean id = "참조변수명 == 객체명" ... > 으로 되어 있는 것을 볼 수 있다.
암튼,
Spring 에서 기본 제공 해주는 ViewResolver 클래스는 내부에 get() 메서드를 가지고 있고,
이 get() 메서드는 인자로 viewName 을 받아서,
세팅해준 prefix 라는 이름의 프로퍼티의 값과 suffix 라는 이름의 프로퍼티의 값을,
viewName 문자열에, 각각 왼쪽 오른쪽으로 문자열을 붙혀 주는 기능을 한다.
즉, ViewResolver 에게 오는 mav 반환값을 모두 받아서 접두사와 접미사를 붙힌다.
대신에,
:redirect 가 붙어 있으면,
ViewResolver 내부의 get() 메서드 자체를 아예 호출 하지 않게 된다.
바로 View로 보내야 한다 >> redirect: 를 붙히지 않기.
바로 View로 보내지 않는다 >> Controller에게 .do 요청을 보낸다 >> redirect: 를 붙히기.
예시)
viewName 이 insertBoard 였다면,
:redirect 가 안붙어 있어서,
ViewResolver 내부의 get() 메서드의 인자로 들어오게 되고,
/WEB-INF/views/ + insertBoard + .jsp
즉,
/WEB-INF/views/insertBoard.jsp 가 된다.
[ 참고 ]
web.xml 는 서블릿 컨테이너 이다.
(POJO, Not POJO의 개념이 아니다)
DispatcherServlet >> Not POJO.xml
(기존에 DispatcherServlet .java 객체화를 web.xml 에서 함)
DispatcherServlet-servlet.xml >> POJO.xml
DispatcherServlet 에서 의존관계로 사용 되는 멤버에게 의존주입 (객체화) 하기 위해서 생성
HandlerMapping 클래스와, ViewResolver 클래스는 Spring 에서 제공 해주니까,
DispatcherServlet-servlet.xml 은 스프링 컨테이너 이다.
이름을 위와 같이 적는 이유는, 아래와 같다.
web.xml 에서 서블릿 컨테이너를 객체화 하기 위해 사용 되는 코드는
<servlet-name>DispatcherServlet</servlet-name> 이고,
이때, 객체화된 서블릿 파일의 이름을 DispatcherServlet 로 했고,
DispatcherServlet 서블릿 내부에서 의존관계로 사용되는 아이들에 대해,
의존 주입을 위해 생성하는 스프링 컨테이너는
DispatcherServlet 이름에 - (하이픈) servlet 을 붙힌다.
>> DispatcherServlet-servlet.xml
기존에,
HandlerMapping 클래스랑, ViewResolver 클래스 모두 POJO 클래스 였고,
setter 의존 주입 방법으로 의존 주입을 할 때,
DispatcherServlet-servlet.xml 에서 해야 한다.
그래서, DispatcherServlet-servlet.xml도 POJO.xml 의 개념으로 생각 하기.
'Spring 프레임워크 > 이론' 카테고리의 다른 글
@ModelAttribute("이름") 어노테이션 (2) | 2023.08.07 |
---|---|
Spring MVC 패턴의 구조 파악 4 (Controller 파트) (0) | 2023.08.04 |
Spring MVC 패턴의 구조 파악 2 (Controller 파트) (0) | 2023.08.03 |
Spring MVC 패턴의 구조 파악 (Model 파트) (0) | 2023.08.02 |
Spring MVC 패턴의 구조 파악 (Controller 파트) (0) | 2023.08.02 |