Spring MVC
Spring MVC란 ?
Spring MVC란? 현재 가장 많이 사용하는 개발 패턴중 하나인 MVC 패턴에서 따온 것이다.
MVC 개념은 화면에서 보여주는 V(View), 데이터 처리 관리는 M(Model), V(View)와 M(Model)를 연결시켜주는 C(Controller) 각 첫글자를 따서 MVC 라고 한다.
Spring Framework를 MVC 패턴 개발시 편리하게 개발 가능하도록 제공한다. 일반적으로 Model View Controller의 형태로 제공하며, 최근에는 프론트와 백엔드의 서버 분리(스케일링이슈) 가 추세이다.
Spring MVC 구조와 처리 과정
- DispatcherServlet
- 어플리케이션으로 들어오는 모든 request를 받는 관문이다.
- request를 실제로 처리할 controller에게 전달하고 그 결과를 받아서 view에게 전달하는 적절한 응값을 생성할 수 있도록 흐름을 제어한다.
- HandlerMapping
- Request URL 각각을 어떤 Controller가 실제로 처리할 것인지 찾아주는 역할을 한다.
- Controller
- Request를 직접 처리한 후에 그 결과를 다시 DispatcherServlet에게 돌려준다.
- ModelAndView
- Controller가 처리한 결과와 그 결과를 보여줄 View에 관한 정보를 담고 있는 객체이다
- ViewResolver
- View 관련 정보를 갖고 실제 View를 찾아주는 역할을 한다.
- View
- Controller가 처리한 결과값을 보여줄 View를 생성한다.
Spring에서 filter, interceptor 차이
Filter
- 요청과 응답을 거른 후에 정제하는 역할을 한다.
- 서블릿 필터는 DispatcherServlet 이전에 실행이 되는데 필터가 동작하도록 지정된 자원의 앞단에서 요청내용을 변경하거나 여러가지 체크를 수행할 수 있다.
- 스프링 컨텍스트 외부에 존재하여 스프링과 무관한 자원에 대해 동작한다.
- 스프링 영역에 포함되어 있지 않다.
Interceptor
- 요청에 대한 작업 전/후로 가로챈다고 보면 된다.
- 스프링의 DispatcherSevlet이 컨트롤러를 호출하기 전, 후로 끼어들기 때문에 스프링 컨텍스트 내부에 Controller에 관한 요청과 응답에 대해 처리한다.
AOP
- Aspect Oriented Programming(관점 지향 프로그래밍)
- OOP를 보완하기 위해 나온 개념이고, OOP를 대체하는 개념은 아니다.
- 객체 지향의 프로그램을 했을 중복을 줄일 수 없는 부분을 줄이기 위해 종단점(관점)에서 바라보고 처리한다.
- 주로 ‘로깅’, ‘트랜잭션’, ‘에러 처리’ 등 비즈니스단의 메서드에서 조금 더 세밀하게 조정하고 싶을 때 사용한다.
- 메소드 전후의 지점에 자유롭게 설정 가능하다.
3가지의 차이점
- 처리 순서 “Filter > DispatcherServlet > Interceptor > AOP” 와 같다.
- Interceptor와 Filter는 주로 주소를 대상을 구분해서 걸러내야 하는 반면, AOP는 주소, 파라미터, 애노테이션 등 다양한 방법으로 대상을 지정할 수 있다.
Spring 설정 파일(web.xml) 생성
Spring설정 파일(Bean정의 파일)의 지정
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>springMVC</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 먼저
org.springframework.web.context.ContextLoaderListener
클래스를 리스너 등록한다. - 이것이 등록되어 있어서, Spring 설정 파일(
/WEB-INF/applicationContext.xml
)을 로드한다. - 이 경로 및 파일 이름은
contextConfigLocation
에서 변경 될 수 있다.
Spring 설정 파일명 변경
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- Spring 설정 파일이 /WEB-INF/spring/app.xml으로 변경되었다.
서블릿에 Spring 설정 파일을 적용
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/mvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
- Spring 설정 파일은 서블릿마다 설정할 수 있다. 설정하는 경우 init-param의 contextConfigLocation으로 설정한다.
- Spring 설정 파일을 /WEB-INF/spring/mvc-servlet.xml으로 지정하였다.
org.springframework.web.servlet.DispatcherServlet 대해
보통 WEB 어플리케이션에서는 Servlet을 만들지만, Spring Web MVC에서는 Spring이 제공 해주기 때문에 따로 생성하지 않고 org.springframework.web.servlet.DispatcherServlet
을 사용한다.
DispatcherServlet이 클라이언트의 요청을 받아 컨트롤러 클래스(@Controller)에 할당하여 컨트롤러 클래스에서 반환으로 뷰(jsp)를 할당하고 클라이언트에 돌려준다. Spring MVC의 전체 제어를 수행하며 web.xml에 설정된다.
그래서 Spring MVC에서 WEB 응용 프로그램을 개발할 때, 대부분 의식하지 않지만 뒤에서 다양하게 동작한다.
CharacterEncodingFilter
- 이전 예제에서는 생략했지만 CharacterEncodingFilter도 지정해야 한다.
- 클라이언트로부터 전송된 데이터를 지정한 문자 코드에 강제로 인코딩한다.
- 이것은 HttpServletRequest의 setCharacterEncoding을 뒤에서 실행해 줍니다.
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Bean정의 파일
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<context:component-scan base-package="spring.test" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
처음에 component-scan 요소는 지정한 패키지 아래에 있는 어노테이션을 적용한 클래스를 자동으로 로딩한다. 로딩하는 어노테이션은 @Controller, @Service, @Component, @Repository 등이 있다.
다음 annotation-driven 요소는 Spring Web MVC를 하기 위해 설정해야 하는 값들이 자동으도 로딩해준다. 해당 설정 어노테이션은 @RequestMapping, @ModelAttribute, @SessionAttribute, @RequestParam 등이 있다.
마지막으로 org.springframework.web.servlet.view.InternalResourceViewResolver을 선언하고 있다. 이것이 jsp 파일의 위치를 지정해 준다. prefix와 suffix를 선언하고 있고, 컨트롤의 반환 값 문자열과 함께 다음 jsp 파일이 적용된다.
prefix문자열 + 컨트롤의 반환 문자열 + suffix문자열
예를 들자면, 컨트롤에서 반환한 값이 test라면
"/WEB-INF/" + test + ".jsp" > "/WEB-INF/test.jsp"
이밖에 Csv 다운로드, Excel 다운로드 등보기 다운로드시킬 때는org.springframework.web.servlet.view.XmlViewResolver를 지정한다 이는 다음 기회에 설명한다.
<mvc:resources>
요소
이미지, CSS, JS 등 정적 리소스 파일에 액세스할 때, 다음과 같이 액세스할 디렉터리를 선언한다.
<mvc:resources mapping="/image/**" location="/WEB-INF/image/" />
위의 디렉터리에 이미지를 표시하는 jsp은 다음과 같이 작성한다.
<img src="./image/test.png"/>
JSP에서 Bean 사용
JSP에서 Spring Java Bean을 편하게 쓰기 위해 호출은 아래와 같이 한다.
먼저, 스프링 설정 파일에서 InternalResourceViewResolver 설정 시에 exposeContextBeansAsAttributes 속성을 true로 해준다.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposeContextBeansAsAttributes" value="true" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
아래와 같이 Java Bean 파일을 작성한다. 이름이 “foo” 인 싱글턴 객체가 생성된다.
@Component
public class Foo {
private String name;
public String getName() {
return name;
}
}
JSP에서 Spring Java Bean인 foo을 JSP EL 에서 호출한다.
<%@page language="java" contentType="text/html; charset=UTF-8"%>
<div class="foo-name">
<c:out value="${foo.name}"/>
</div>