스프링 MVC는 모든 요청이 Dispatcher Servlet으로 간 후, Mapping 과정을 통해 요청에 적절한 Controller를 실행한다.
그렇기때문에 스프링 MVC가 웹 요청을 처리하기위해서는 Dispatcher Servlet이 등록되어있어야 한다.
Dispatcher Servlet 설정은 web.xml 파일에 등록한다.
- web.xml 파일은 tomcat 사용 시, tomcat 설치폴더/conf/web.xml 파일을 복사해서 <webapp> 태그 내부만 바꿔서 사용할 수도 있다.
MVC를 사용하기위해서 추가해야할 의존 라이브러리는 Spring WebMVC ( 해당 모듈 안에 Spring Context가 포함되어있기때문에 별도로 추가하지 않아도 된다. ) 다.
설정하기위해 사용해야하는 태그는 다음과 같다.
1) <servlet> : Dispatcher Servlet과 그 외 서블릿들을 등록할 때 사용한다.
1-1) 사용되는 태그
1-1-1) <servlet-name> : 해당 서블릿의 이름을 지정한다.
1-1-2) <servlet-class> : 해당 서블릿의 클래스 타입을 지정한다. 스프링에서 제공하는 Dispatcher Servlet 클래스가 있기때문에 이것을 지정한다.
1-1-3) <init-param> : servlet-class 태그에 해당하는 서블릿에 인자를 넘겨주는 태그.
1-1-3-1) <param-name> : 해당 클래스의 변수명을 적는다.
1-1-3-2) <param-value> : 해당 클래스의 변수에 넣을 값을 넣는다. ( 설정 xml파일 경로 등 )
1-1-2) <load-on-start-up> : 해당 클래스의 로드 우선순위를 지정한다. 낮을 수록 우선적으로 초기화된다. (선택)
1-1-3) <multipart-config> : multipart 형식의 데이터를 전송할 때 사용되는 태그. (선택)
1-1-3-1) <max-file-size> : multipart 형식의 데이터를 전송할 때 최대 크기를 지정할 수 있다.
2) <servlet-mapping> : 1)에서 등록한 서블릿을 url과 매핑한다.
2-1) <servlet-name> : 1-1-1)에서 입력한 서블릿명과 동일하게 지정한다.
2-2) <url-pattern> : 특정 url로 요청이 들어올 경우 해당 Dispatcher Servlet에 명령이 도착할 수 있도록 지정한다. (정규식 사용)
합치면 하나의 Dispatcher Servlet을 등록하는 태그는 다음과 같아진다.
[ web.xml ]
<servlet>
<servlet-name>req</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/req-servlet.xml</param-value>
// 2개 이상의 파일을 참조할 때는 <param-value> 태그의 내용을 다음처럼 줄단위로 구분하거나 쉼표로 구분하면 된다.
<param-value>
/WEB-INF/spring/req-servlet.xml
/WEB-INF/spring/req-cont.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
<multipart-config>
<max-file-size>5000000</max-file-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>req</servlet-name>
<url-pattern>/req/*</url-pattern>
</servlet-mapping>
기본문자열을 UTF-8로 바꾸기위해서는 스프링이 제공하는 CharcterEncodingFilter 클래스를 filter로 등록하면 된다.
[web.xml]
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern> // 모든 경로에 대해 필터를 적용
</filter-mapping>
servlet과 마찬가지로 <filter> -> <filter-mapping> 순으로 등록하는 것을 볼 수 있다.
req-servlet.xml 파일은 기존에 사용했던 설정 xml파일을 등록하면 된다. 빈객체 관리는 Dispatcher Servlet의 param-value 태그에 넘기는 xml파일에서 관리하면 된다.
[req-servlet.xml]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=" .....
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven/> // MVC 관련 어노테이션을 처리하기위해서는 해당 태그를 작성해야한다.
</beans>
위와 같은 작업을 통해 req라는 이름을 가진 Dispatcher Servlet이 등록됐다.
컨트롤러 클래스는 @RequestMapping을 통해 url과 매핑한다. Dispatcher Servlet은 이런 컨트롤러들을 찾아서 연결해주는 역할을 한다.
Controller 클래스는 사용자의 웹요청을 처리하고 그 결과를 View로 전달하는 클래스다.
[ReqController1.java]
import ...
@Controller
public class ReqController1 {
@RequestMapping("/method1")
public void method1() {
System.out.println("method1()");
}
@RequestMapping(value="/method2", method=RequestMethod.GET)
public void method2() {
System.out.println("method2()");
} // GET 요청에서만 작동하는 메소드
@GetMapping("/method3")
public void method3() {
System.out.println("method3()");
} // GET 요청에서만 작동하는 메소드
}
위 컨트롤러는 url이 ../req/method1일 경우 method1 메소드가 호출되고 ../reg/method2일 경우 method2 메소드가 호출된다.
단, method 속성에 RequestMethod 클래스의 상수값(GET, POST, PUT, DELETE)을 넘겨주면 특정 요청방식에 따라서만 실행되도록 지정할 수 있다.
혹은 스프링 5.1 이상의 버전이라면 GetMapping이나 PostMapping 등의 어노테이션을 사용할 수 있다.
스프링 MVC의 동작은 다음과 같다.
1) 웹브라우저로부터 요청이 들어온다. (웹브라우저 -> Dispatcher Servlet)
2) 디스패처 서블릿은 적절한 컨트롤러를 찾는다. 단, 디스패처 서블릿이 직접 검색하지않고 HandlerMapping이라는 빈객체를 통해 컨트롤러를 검색한다.(Dispatcher Servlet -> HandlerMapping)
3) HandlerMapping 빈객체는 클라이언트의 요청경로를 사용하여 해당 요청을 처리할 컨트롤러 빈객체를 디스패처 서블릿으로 전달한다. (HandlerMapping -> Dispatcher Servlet)
4) 디스패처 서블릿은 HandlerMapping이 찾아준 컨트롤러 객체를 처리할 수 있는 HandlerAdapter 빈에게 요청 처리를 위임한다.
HandlerAdapter는 해당 컨트롤러에서 요청과 일치하는 메소드를 실행하고 그 결과를 디스패처 서블릿으로 전달한다. (Dispatcher -> HandlerAdapter -> Dispatcher>
5) 디스패처 서블릿은 그 결과를 웹브라우저로 반환한다.
5-1) JSP를 사용하는 경우, 특정 저장소(request, session, pagecontext, model 등)에 데이터를 저장해둔 후 ViewResolver를 통해서 적절한 view를 선택하고 그 view에 데이터를 사용하여 화면을 구성한 후 클라이언트로 그 view를 전달한다. ViewResolver를 사용하지 않아도 직접 view를 선택할 수 있다.
5-2) 데이터만 보내는 경우 json 형태로 변형하여 view로 데이터를 보낸다. 객체를 json 형태로 바꿔주는 라이브러리를 사용하면 단순히 객체를 반환함으로 json 형태로 만들어 보낼 수 있다. ex) GSON, Jackson 라이브러리 등