07. 뷰 영역 구현
01. ViewResolver 설정
-. 스프링의 컨트롤러는 뷰에 의존적이지 않다. 컨트롤러는 아래 코드와 같이 결과를 생성할 뷰의 이름만 지정한다.
-. 컨틀롤러가 지정한 뷰 이름으로부터 응답 결과 화면을 생성하는 View 객체는 ViewResolver가 구한다.@Controller public class HelloControoler { @RequestMapping("/hello.do") public String hello( ) { // 처리결과를 뷰 이름 지정 return "hello"; } } |
※ 스프링이 제공하는 주요 ViewResolver 구현 클래스
ViewResolver 구현 클래스 |
설명 |
InternalResourceViewResolver |
-. 뷰이름으로부터 JSP나 tILES 연동을 위한 View 객체를 리턴한다. |
VelocityViewResolver |
-. 뷰 이름으로부터 Velocity 연동을 위한 View 객체를 리턴한다. |
VelocityLayoutVioewResolver |
-. VelocityViewResolver와 동일한 기능을 제공하며, 추가로 vELOCITY의 레이아웃 기능을 제공한다. |
BeanNameViewResolver |
-. 뷰 이름과 동일한 이름을 갖는 빈 객체를 View 객체로 사용한다. |
ResourceBundleViewResolver |
-. 뷰 이름과 View 객체간의 매핑 정보를 저장하기 위해 자원파일을 사용한다. |
XmlViewResolver |
-. 뷰 이름과 View 객체간의 매핑 정보를 저장하기 위해 XML 파일을 사용한다. |
1.1 ViewResolver 인터페이스
package org.springframework.web.servlet; import java.util.Locale; public interface ViewResolver { View resolveViewName(String viewName, Locale locale) throws Exception; } |
-. ViewResolver는 뷰 이름과 지역화를 위한 Locale을 파라미터로 전달받으며, 매핑되는 View 객체를 리턴한다.
-. 매핑되는 View 객체가 존재하지 않으면 null을 리턴한다.
1.2 View 객체
-. View Resolver는 응답 결과를 생성할 뷰 객체를 리턴한다.
-. 모든 뷰 클래스는 View 인터페이스를 구현하고 있으며, View 인터페잇느느 다음과 같이 정의되어 있다.
package org.springframework.web.servlet; import java.util.Map; import javax.ervlet.httpHttpServletRequest; import javax.ervlet.httpHttpServletResponse; public interface View { String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus"; String getContentType(); void render(Map<String, ?> model. HttpServletRequest request, HttpServletResponse response) throws Exception; } |
-. getContentType() 메서드는 "text/html"과 응답 결과의 컨텐트 타입을 리턴한다.
-. render() 메서드는 실제로 응답 결과를 생성한다.
-. render() 메서드의 첫 번째 파라미터인 model에는 컨트롤러가 리턴한 ModelAndView 객체의 모델 데이터가 전달된다.
-. rkrrkdml View 객체는 이 모델 데이터로부터 응답 결과를 생성하는 데 필요한 정보를 구현한다.
1.3 InternalResourceViewResolver 설정
-. InternalResourceViewResolver 클래스는 JSP나 HTML 파일과 같이 웹 어플리케이션의 내부 자원을 이용하여 뷰를 생성하는
AbstractUrlBasedView 타입 뷰 객체를 리턴한다.
-. 기본적으로 사용하는 View 클래스는 InternalResourceView 클래스이다.
<bean id="viewResolver" |
-. InternalResourceViewResolver는 컨트롤러가 지정한 뷰 이름으로부터 실제로 사용될 뷰를 선택한다.
이 때 컨틀로러가 지정한 뷰 이름 앞뒤로 prefix 프로퍼티와 suffix 프로퍼티를 추가한 값이 실제로 사용될 자원의 경로가 된다.
ModelAndView = new ModelAndView("hello"); return mav; |
-. 기본적으로 사용되는 InternalResourceView 클래스는 단순히 지정한 자원 경로로(일반적으로 JSP) 요청을 전달한다.
-. 만약, 스프링의 국제화 관련 정보를 JSTL에서 사용하고 싶다면, 다음과 같이 JstlView 클래스를 viewClass 프로퍼티로 지정하면 된다.
<bean id="viewResolver" p:prefix="/WEB-INF/viewjsp/" p:suffix=".jsp" /> |
1.4 BeanNameViewResolver 설정
-. BeanNameViewResolver 클래스는 뷰 이름과 동일한 이름을 갖는 빈을 뷰 객체로 사용한다.
-. BeanNameViewResolver는 주로 커스텀 View를 뷰로 사용해야 하는 경우에 사용된다.
ex) 파일 다운로드를 위한 정보를 읽어와 뷰에 전달하는 컨트롤러가 다운로드 관련 정보를 뷰에 전달하는 예
@Controller public ModelAndView download(HttpServletRequest request, HttpServletResponse response) { File downloadFile = getFile(request); return new ModelAndView("download", "downloadFile", downloadFile); } |
※ 위 결과를 보여 줄 DownloadView 클래스
<bean id="viewResolver" <bean id="download" class="madvirus.spring.chap07.view.DownloadView"/> |
1.5 XmlViewResolver 설정
-. XmlViewResolver는 BeanNameViewResolver와 마찬가지로 뷰 이름과 동일한 이름을 갖는 빈을 뷰 객체로 사용한다.
-. 차이점은 XmlViewResolver는 별도의 XML 설정 파일로부터 빈 객체를 검색한다는 것이다.
-. XmlViewResolver는 다음과 같이 location 프로퍼티를 이용하여 외부 설정 파일의 경로를 지정한다.
<bean id="viewResolver" class="org.springframework.web.servlet.view.XmlViewResolver" p:location="/WEB-INF/nonHtml-view.xml"/> |
-. location 프로퍼티의 값을 지정하지 않을 경우 기본값은 "/WEB-INF/nonHtml-view.xml"이다.
-. location 프로퍼티에 지정하는 파일은 스프링 XML 설정 파일이다.
1.6 ResourceBundleViewResolver 설정
-. ResourceBundleViewResolve는 리소스 번들(프로퍼티 파일)로부터 뷰 이름과 매핑되는 View 클래스를 구한다.
-. ResourceBundleViewResolver는 ResourceBundleMessageSource와 마찬가지로 basename 프로퍼티나 basenames 프로퍼티를 이용해서
뷰 클래스 정보를 저장한 리소스 경로를 명시한다.
<bean id ="viewResolve" class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:basename="views/views" /> |
-. 위 설정에서 ResourceBundleViewResolve는 "views/views" 리소스로부터 설정 정보를 로딩한다.
즉, "views/views.properties", "views/views_en.properties"등 Locale에 따라 알맞은 프로퍼티 파일로부터 뷰 매핑 정보를 로딩하게 된다.
-. 프로퍼티 파일은 다음과 같이 "뷰이름.class=뷰클래스' 형태로 뷰 이름과 뷰 클래스 사이의 매핑을 입력한다.
download.class = madvirus.spring.chap07.view.DownloadView |
1.7 다수의 ViewResolver 설정하기
-. 하나의 DispatcherServlet은 한 개 이상의 ViewResolver를 설정할 수 있도록 하고 있다.
-. 다수의 ViewResolver를 설정한 경우 "order" 프로퍼티를 이용하여 뷰 이름을 검사할 ViewResolver의 순서를 결정할 수 있다.
-. "order" 프로퍼티의 값이 작은 ViewResolver가 높은 우선순위를 갖는다.
만약, 우선순위를 명시하지 않으면 Integer.MAX_VALUE를 "order"프로퍼티의 값으로 갖는다.
(즉, 가장 낮은 우선순위를 갖게 된다.)
-. ViewResolver 구현 클래스가 org.springframework.core.Ordered 인터페이스를 구현하지 않은 경우,
해당 ViewResolver 구현 클래스도 가장 낮은 우선순위를 갖게 된다.
하지만 스프링이 제공하는 ViewResolver 구현 클래스는 모든 Ordered 인터페이스를 구현하고 있다.
-. DispatcherServlet은 "order" 프로퍼티의 값이 작은, 즉, 우선순위가 높은 ViewResolver에게 뷰 객체를 요청한다.
만약, 우선순위가 높은 ViewResolve가 null을 리턴하면, 그 다음 우선순위를 갖는 ViewResolver에 뷰를 요청한다.
뷰 객체를구하면, 해당 뷰 객체를 이용하여 응답 결과를 생성한다.
ex) "order" 프로퍼티의 설정 예
<bean class="org.springframework.web.servlet.view.XmlViewResolver" p:location="/WEB-INF/nonHtml-view.xml" p:order="0" /> <bean class="org.springframework.webservlet.view.InternalResourceViewResolver" p"prefix="/WEB-INF/viewjsp/" p:suffix="/jsp" p:order="1" /> |
02. HTML 특수 문자 처리 방식 설정
-. 스프링은 각 뷰 기술과 관련하여 메시지나 커맨드 객체의 값을 출력할 수 있는 기능을 제공하고 있다.
-. JSP를 뷰 기술로 사용할 경우 다음의 커스텀 태그를 이용해서 메시지를 출력할 수 있다.
<title><spring:message code="login.form.title" /></title> |
-. 만약 위 커스텀 태그가 출력하는 값이 '<입력폼>'이라고 하자. 이때, '<'와 '>'는 HTML에서 특수문자이기 때문에
'<'나 '>'와 같은 엔티티 레퍼런스로 변환해 주어야 원하는 값이 출력된다.
-. 스프링은 이런 특수문자를 어떻게 처리할 지의 여부를 defaultHtmlEscape 컨텍스트 파라미터를 통해서 지정할 수 있다.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <context-param> <param-name>defaultHtmlEscape</param-name> <param-value>false</param-value> </context-param> … </web-app> |
-. defaultHtmlEscape 컨텍스트 파리미터의 값을 true로 지정하면 스프링이 제공하는 커스텀 태그나 Volcity 매크로는
HTML의 특수 문자를 엔티티 레퍼런스로 치환한다.
-. 반면에 defaultHtmlEscape 컨텍스트 파라미터의 값이 false이면, 특수 문자를 그대로 출력한다.
※ defaultHtmlEscape 컨텍스트 파라미터의 기본 값은 true 이다.
03. JSP를 이용한 뷰 구현
-. JSP를 뷰로 사용하려면 InternalResourceViewResolver를 사용하면 된다.
-. 아래 코드와 같이 suffix 프로퍼티의 값을 .jsp로 지정함으로써 논리적 뷰 이름을 특정 JSP에 매핑할 수 있다.
<bean id ="viewResolve" class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:prefix="/WEB-INF/viewjsp/" p:suffix=".jsp" /> </bean> |
3.1 메시지를 출력을 위한 <spring:message>커스텀 태그
-. 스프링은 MessageSource로부터 메시지를 가져와 출력해주는 <spring:message> 커스텀 태그를 제공하고 있다.
-. <spring:message> 커스텀 태그는 다음과 같이 code 속성을 이용하여 읽어 올 메시지의 코드를 지정한다.
<%@ page contentType="text/html; charset=EUC-KR" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title><spring:message code="login.form.title"/></title> </head> <body> <form:form commandName="login"> <form:errors /> <p> <label for="loginType"><spring:message code="login.form.type" /></label> <form:select path="loginType" items="${loginTypes}" /> </p> … <p> <input type="submit" value="<spring:message code="login.form.submit" />"> </p> </form:form> </body> </html> |
-. 위 코드에서 사용되는 메시지를 포함하고 있는 메시지 리소스 파일은 다음과 같이 각 코드 값에 해당되는 메시지를 설정하고 있다.
login.form.title=Login FORM login.form.id=ID login.form.password=Password login.form.submit=Login |
-. 메시지 리소스 파일은 {n} 형식을 잉요하여 변하는 부분을 명시할 수 있다.
greeting=\uc804 {0}\uc785\ub2c8\ub2e4.{1} |
-. <spring:message> 태그는 주어진 코드에 해당하는 메시지가 존재하지 않는다면 예외를 발생시킨다.
-. 코드에 해당하는 메시지가 없을 때 예외를 발생시키는 대신 지정한 메시지를 출력하고 싶다면 text 속성에 기본 메시지를 입력하면 된다.
<spring:message code="no_code" text="코드가 없습니다." /> |
-. <spring:message> 태그가 생성한 메시지를 출력하지 않고 request나 session과 같은 기본 객체의 속성에 저장할 수도 있다.
<spring:message code="login.form.password" var="label" scope="request"/> ${label}: <input type=.../> |
3.2 스프링이 제공하는 폼 관련 커스텀 태그
-. 스프링의 장점 중 하나는 입력 폼 값을 커맨드 객체에 저장하는 기능을 제공한다는 것이다.
-. 스프링은 또한 반대로 커맨드 객체의 값을 입력 폼에 출력해 주는 JSP 커스텀 태그를 제공하고 있어, 좀 더 쉽게 폼 관련 태그를 생성할 수 있도록 도와준다.
-. 스프링이 제공하는 폼 관련 커스텀 태그를 사용하려면 다음과 같이 커스텀 태그를 설정해 주어야 한다.
<%@ taglib prefix="for" uri="http://www.springframework.org/tags/form" %> |
(1) <form> 태그를 위한 커스텀 태그 : <form:form>
-. <form:form> 커스텀 태그는 <form> 태그를 생성할 때 사용된다. <form:for> 커스텀 태그를 사용하는 가장 간단한 방법은 다음과 같다.
<form:form> <form:select path="loginType" items="${loginTypes}" /> </p> … <p> <input type="submit" value="<spring:message code="login.form.submit" />> </p> <form:form> |
-. <form:form>태그의 method 속성과 action 속성을 표시하지 않으면 method 속성의 값은 "post"로 설정되고
action 속성의 값은 현재 요청 URL값이 설정된다.
<<form id="command" action="/chap07/login/login.do" method="post"> … </form> |
-. 생성된 <form> 태그의 id 속성은 입력 폼의 값을 저장하는 커맨드 객체의 이름이 할당된다.
-. 커댄드 객체의 이름이 기본값인 "command"가 아니라면 다음과 같이 com-mandName 속성에 커맨드 객체의 이름을 명시해 주어야 한다.
<form:form commandName="login"> |
-. <form:form> 커스텀 태그는 <form> 태그와 관련하여 다음의 속성들을 추가적으로 제공하고 있다.
◎ action - 폼 데이터를 정송할 URL을 입력(HTML <form> 태그 속성)
◎ enctype - 전송될 데이터의 인코딩 타입, HTML<form> 태그 속성과 동일
◎ method - 전송 방식, HTML<form> 태그 속성과 동일
-. <form:form> 택의 몸체에는 <input> 태그나 <select> 태그와 같이 입력 폼을 출력하는 데 필요한 HTML 태그를 입력할 수 있다.
이때 입력한 값이 잘못 되어 다시 값을 입력해야 하는 경우에는 다음과 같이 커맨드 객체의 값을 사용해서 이전에 입력한 값을 출력한다.
<form:form> … <input type="text" name="id" value="${login.id}"/> … </form:form> |
(2) <input>태그를 위한 커스텀 태그 : <form:input>, <form:password>, <form:hidden>
-. <input> 태그와 관련도니 기본 커스텀 태그
커스텀 태그 |
설명 |
<form:input> |
-. text 타입의 <input> 태그 |
<form:password> |
-. password 타입의 <input> 태그 |
<form:hidden> |
-. hidden 타입의 <intput> 태그 |
(3) <select> 태그를 위한 커스텀 태그 : <form:select>, <form:options>, <form:option>
-. <select> 태그와 관련된 커스텀 태그
커스텀 태그 |
설명 |
<form:select> |
-. <select> 태그를 생성한다. -. <option> 태그를 생성하는 데 필요한 콜렉션을 전달받을 수도 있다. |
<form:options> | -. 지정한 콜렉션 객체를 이용하여 <opton> 태그를 생성한다. |
<form:option> | -. 한 개의 <option> 태그를 생성한다. |
(4) checkbox 타입 <input> 태그를 위한 커스텀 태그 : <form:checkboxes>, <form:checkbox>
-. 한 개 이상의 값을 커맨드 객체의 특정 프로퍼티에 저장하고 싶은 경우, 배열이나 List와 같은 콜렉션 타입을 사용해서 값을 저장한다.
커스텀 태그 |
설명 |
<form:checkboxes> | -. 커맨드 객체의 특정 프로퍼티와 관련된 checkbox 타입의 <input> 태그 목록을 생성한다. |
<form:checkbox> | -. 커맨드 객체의 특정 프로퍼티와 관련도니 한 개의 checkbox 타입 <input> 태그를 생성한다. |
(5) radio 타입 <input> 태그를 위한 커스텀 태그 : <form:radiobuttons>, <form:radiobutton>
-. 여러 가지 옵션 중에서 한가지를 선택해야 하는 경우, radio 타입의 <input> 태그를 사용한다.
커스텀 태그 | 설명 |
<form:radiobuttons> | -. 커맨드 객체의 특정 프로퍼티와 관련도니 radio 타입의 <input> 태그 목록을 생성한다. |
<form:radiobutton> | -. 커맨드 객체의 특정 프로퍼티와 관련된 한 개의 radio 타입 <input> 태그를 생성한다. |
(6) <TEXTAREA> 태그를 위한 커스텀 태그 : <from:textarea>
-. 게시글 내용과 같이 여러 줄을 입력 받아야 하는 경우 <textarea> 태그를 사용한다.
-. 스프링은 <form:textarea> 커스텀 태그를 제공하고 있으며, 이 태그를 이용하면 커맨드 객체와 관련된 <textarea>태그를 생성할 수 있다.
<p> <form:label path="etc">기타</form:label> <form:textarea path="etc" cols="20" rows="3" /> </p> |
(7) CSS 및 HTML 태그와 관련된 공통 속성
-. <form:input>, <form:select> 등 스프링이 입력 폼과 관련해서 제공하는 커스텀 태그는 HTML의 CSS 및 이벤트 관련 속성을 제공하고 있다.
① CSS와 관련도니 속성
◎ cssClass - HTML의 class 속성값
◎ cssErrorClass - 폼 검증 에러가 발생했을 때 사용할 HTML의 class 속성 값
◎ cssStyle - HTML의 style 속성 값
② HTML 태그가 사용하는 속성값
◎ id, title, dir
◎ disabled, tabindex
◎ onfocus, onblur, onchange
◎ onclick, ondblclick
◎ onkeydown, onkeypress, onkeyup
◎ onmousedown, onmousemove, onmouseup
◎ onmouseout, onmouseover
3.3 스프링이 제공하는 에러 관련 커스텀 태그
-. Validator는 아래 코드와 같이 Errors를 이용하여 에러 정보를 저장하였다.
package madvirus.spring.chap07.controller; |
-. Errors나 BindingResult를 이용해서 에러 정보를 추가한 경우, <form:errors> 커스텀 태그를 이용해서 에러 메시지를 출력할 수 이쑈다.
-. <form:errors> 커스텀 태그는 path 속성을 이용해서 커맨드 객체의 특정 프로퍼티와 관련된 에러 메시지를 출력할 수 있다.
<form:form commandName="memberInfo"> <p> <form:label path="userId">회원 ID</FORM:LABEL> <form:input path="userId" /> <form:errors path="userId" /> </p> … |
-. 위 코드의 경우 "userId" 프로퍼티와 관련된 모든 에러 메시지를 출력한다.
에러 메시지는 에러 코드와 필드 이름, 그리고 커맨드 클래스 이름을 통해서 결정된다.
-. <form:errors> 커스텀 태그는 지정한 프로퍼티와 관련된 한 개 이상의 에러 메시지를 출력하게 된다.
각 에러 메시지를 생성할 때 다음과 같은 두 개의 속성이 사용된다.
◎ element - 각 에러 메시지를 출력할 때 사용될 HTML 태그, 기본 값은 span 이다.
◎ delimiter - 각 에러 메시지를 구분할 때 사용될 HTML 태그, 기본 값은 <br/> 이다.
※ element, delimiter 속성의 사용 예
<form:errors path="userId" element="div" delimeter=""/> |
3.4 <spring:htmlEscape> 커스텀 태그와 htmlEscape 속성
-. defaultHtmlEscape 컨텍스트 파라미터를 사용해서 웹 어플리케이션 전반에 걸쳐서 HTML의 특수 문자를 엔티티 레퍼런스로 치환할 지의 여부를 결정하는데,
만약 각 JSP 페이 별로 특수 문자 치환 여부를 설정해 주고 싶다면 다음과 같이 <spring:htmlEscape> 커스텀 태그를 사용하면 된다.
<%-- JSP 페이지의 앞 부분에서 설정 --%> <spring:htmlEscape defaultHtmlEscape="true"/> … <spring:message .../> <form:input .../> |
-. <spring:htmlEscape> 커스텀 태그를 설정하면, 이후로 실행되는 <spring:message> 커스텀 태그나 <form:input> 커스텀 태그와 같이
스프링이 제공하는 커스텀 태그는 <spring:htmlEscape> 커스텀 태그의 defaultHtmlEscape 속성에서 지정한 값을 기본 값으로 사용한다.
3.5 <form:form>의 RESTful 지원
-. 스프링 MVC는 HTTP의 GET, POST, PUT, DELETE 방식을 지원하고 있으며, 다음과 같이 컨트롤러 메서드에서 어떤 HTTP 방식을 지원할 지 선택할 수 있다.
package madvirus.spring.chap07.controller; |
※ 대부분의 웹 브라우저는 GET 방식과 POST 방식만을 지원하고 있어서 DELETE방식이나 PUT 방식의 요청을 전송 할 수 없기 때문에,
웹 브라우저를 이용할 경우 GET 방식과 POST 방식으로만 처리 해야 한다.
※ 스프링 3 버전부터는 PUT과 DELETE 방식을 이용해서 컨트롤러를 구현하면서 웹 브라우저에서도 그대로 해당 컨트롤러를 사용할 수 있도록 지원한다.
04. Tiles 2 연동을 이용한 레이아웃 템플리 처리
-. 레이아웃이 동일하고 공통된 내용이 들어가는 영역이 많은 경우에는 Tiles와 같은 템플릿 라이브러리를 사용해서 레이아웃을 처리하면
뷰 관련 코드에서 레이아웃을 처리하기 위한 코드의 중복을 제거할 수 있다는 장점이 있다.
※ 스프링은 테플릿 라이브러리인 Tiles 2 버전을 지원하고 있다.
4.1 TilesConfigurer를 이용한 Tiles 2 연동
-. Tiles 2 연동을 위해서는 다음의 jar 파일을 클래스 패스에 추가해 주어야 한다. (commons-logging.jar의 경우 spring core 모듈에서도 의존하는 모듈이다.)
◎ tiles-api2.1x.jar, tiles-core-2.1x.jar, tiles-jsp-2.1x.jar
◎ commons-beanutils, commons-digester,jar, commons-logging.jar
◎ 스프링 MVC 모듈
-. 스프링 3에서는 Tiles 2를 연동하기 위해서는 스프링 설정 파일에 다음의 두 가지 내용을 설정한다.
◎ TilesConfigurer를 이용하여 Tiles2 레이아웃 설정 파일 명시
◎ UrlBasedViewResolver의 viewClass 프로퍼티를 TilesView로 지정
ex) 설정 예
-. TilesConfigurer 클래스와 TilesView 클래스는 모두 tiles2 패키지에 포함된 클래스임에 유의해야 한다.
<bean id="tilesConfigurer" |
-. TilesConfigurer 빈 객체는 definitions 속성을 이용해서 Tiles 설정 파일 목록을 전달받는다.
-. Tiles 2 설정 파일은 다음과 같이 작성된다.
<?xml version="1.0" encoding="UTF-8" ?> …
|
-. TilesView 클래스는 컨틀롤러가 지정한 뷰 이름과 동일한 이름을 갖는 <definition> 태그를 사용하여 뷰를 생성한다.
예를 들어, 컨트롤러가 다음과 같이 뷰 이름을 "loginForm"으로 지정했다고 하자.
@Controller return "loginForm"; … } |
-. 이 경우 name 속성의 값이 "loginForm"인 <definition> 태그의 정보를 사용한다.
즉, 앞서 Tiles 설정 내용에서 봤듯이 layout.jsp를 레이아웃 템플릿으로 사용하고, 헤더와 푸터에 각각 header.jsp와 footer.jsp를 삽입하고,
그리고 내용에는 loginForm.jsp를 사용하게 된다.
-. 레이아웃 템플릿 파일은 다음과 같이 Tiles2가 제공하는 커스템 태그를 이용하여 레이아웃 정보를 설정한다.
<%@ page contentType="text/html; charset=EUC-KR"%> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title><tiles:getAsString name="title" /></title> <tiles:insertAttribute name="header" /> <hr/> <tiles:insertAttribute name="body" /> <hr/> <tiles:insertAttribute name="footer" /> </body> |
4.2 스프링 빈을 ViewPreparer로 사용하기
-. 메뉴 목록처럼 모든 뷰 코드에서 공통으로 사용되는 데이터가 존재할 경우 Tiles에서는 ViewPreparer를 잉요한다.
-. 보통 ViewPreparer는 아래 코드와 같이 Tiles 설정 파일에 완전한 클래스 이름을 적는 것이 보통이다.
<tiles-definitions> preparer="madvirus.spring.chap07.tiles2.MenuPreparer"> … </tiles-definitions> |
-. 그런데 이 경우 스프링이 제공하는 DI/AOP를 ViewPreparer에 적용할 수 없는 단점이 있다.
그래서 스프링 MVC는 Tiles의 ViewPreparer로 스프링 빈을 사용할 수 있는 기능을 제공하고 있다.
스프링 빈을 Tiles의 ViewPreparer로 사용하려면 다음의 세가지만 설정하면 된다.
◎ TilesConfigurer 설정에 preparerFactoryClass 프로퍼티 설정 추가
◎ ViewPreparer로 사용할 스프링 빈 등록
◎ Tiles 설정 파일의 preparer 속성에 스프링 빈 이름 등록
-. 먼저 아래 코드와 같이 TilesConfigurer의 preparerFactoryClass 프로퍼티의 값으로 SpringBeanPreparerFactory 클래스의 완전한 이름을 설정하고,
ViewPreparer로 사용할 클래스를 스프링 빈으로 등록한다.
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"> <property name="definitions"> <list> <value>/WEB-INF/tiles2def/tilesdef.xml</value> </list> </property> <property name="preparerFactoryClass" value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" /> </bean> <bean id="menuPreparer" class="madvirus.spring.chap07.tiles2.MenuPreparer" /> |
-. Tiles 설정 파일에서는 다음과 같이 <definition> 태그의 preparer 속성의 값으로 앞서 설정한 스프링 빈의 이름을 지정하면,
ViewPreparer로 해당 빈을 사용하게 된다.
<tiles-definitions> </tiles-definitions> |
05. Velocity를 이용한 뷰 구현
-. JSP와 더불어 뷰를 생성하는 데 많이 사용되는 기술 중의 하나가 Velocity이다.
-. Velocity는 템플릿 엔진으로서 템플릿 파일을 비교적 쉽게 작성할 수 있고, 자바 객체를 템플릿 파일에서 사용할 수 있기 때문에
생성하는 데 JSP 만큼 널리 사용되고 있다.
-. Velocity를 뷰로 사용하려면 다음의 Velocity 관련 jar 파일을 추가해 주어야 한다.
◎ Velocity 1.5
◎ Velocity Tools View 1.4
5.1 VelocityViewResolver와 VelocityConfigurer를 이용한 Velocity 연동
-. 스프링에서 Velocity를 연동할 때에는 VelocityViewResolver를 사용하면 된다.
-. VelocityViewResolver는 Velocity 템플릿 파일을 이용해서 뷰를 생성하며 VelocityConfigurer를 사용해서 Velocity와 관련된 설정 정보를 입력한다.
<bean id="velocityEngine" <property name="velocityProperties"> <props> class="org.springframework.web.servlet.view.velocity.VelocityViewResolver" p:suffix=".vm" p:contentType="text/html; charset=EUC-KR"/> |
-. VelocityConfigurer의 resourceLoaderPath 프로퍼티는 템플릿 파일을 로딩할 경로를 입력하며,
velocityProperties 프로퍼티는 velocityProperties 프로퍼티는 Velocity 설정 정보를 지정한다.
-. VelocityViewResolver는 VelocityConfigurer에서 설정한 경로에서 템플릿 파일을 읽어 와 뷰를 생성한다.
prefix 프로퍼티와 suffix 프로퍼티는 뷰 이름으로부터 템플릿 파일의 경롤르 생성할 때 사용된다.
-. 템플릿 파일에서는 컨트롤러에서 생성한 모델 정보를 사용할 수 있다.
package madvirus.spring.chap07.controller; |
-. 이 경우 템플릿 파일에서는 다음과 같이 모델의 이름을 사용해서 객체를 사용할 수 있다.
<html> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title>인사</title> </head> <body> 인사말 : <strong>${greeting}</strong> </body> </html> |
(1) Velocity Tools의 NumberTool과 DateTool 설정
-. Velocity는 템플릿 파일에서 유용하게 사용할 수 있는 다양한 툴을 구현한 VelocityTools를 제공한다.
-. 이 툴에는 숫자와 날짜를 형식에 맞게 출력해 주는 NumberTool과 DateTool을 제공하고 있다.
-. VelocityViewResolver는 이 두 가지 툴을 템플릿 파일에서 접근할 때 사용할 이름을 지정할 수 있는 프로퍼티를 제공하고 있다.
◎ dateToolAttribute - DateTool에 접근할 때 사용할 변수명을 지정
◎ numberToolAttribute - NumberTool에 접근할 때 사용할 변수명을 지정
(2) request 및 session 속성 템플릿 파일에서 사용하기
-. VelocityViewResolver는 모델에 저장도니 모델 데이터만 뷰에 전달한다. 하지만, 경우에 따라서 request 객체나 session 객체에 저장된 속성(attribute)을
템플릿에 접근하고 싶을 때가 있다. 예를 들어, session 객체[에 현재 로그인 한 사용자 정보가 저장되어 있는 경우를 생각해 보자. 템플릿 파일에서 session
객체의 속성에 접근 할 수 없다면, 다음과 같이 컨트롤러에서 일일이 필요한 값을 모델 객체에 추가해 주어야 한다.
-. 이러한 불편함을 없애기 위해, VelocityViewResolver는 다음의 두 프로퍼티의 값을 true로 지정함으로써
request나 session의 속성을 템플릿에 전달 할 수 있도록 하고 있다.
◎ exposeRequestAttributes
◎ exposeSessionAttributes
5.2 스프링이 제공하는 Velocity 매크로
-. 스프링이 JSP를 위한 다양한 커스텀 태그를 제공하고 있듯이, Velocity를 위한 매크로도 제공하고 있다.
-. 커스텀 태그와 마찬가지로 입력 폼을 위한 HTML 태그와 에러 메시지 등을 생성할 때 매크로를 유용하게 사용할 수 있다.
(1) 메시지 출력을 위한 #springMessage와 #springMessageText 매크로
◎ #springMessage(code) - 코드에 해당하는 메시지를 출력한다, 메시지가 존재하지 않을 경우 예외가 발생한다.
◎ #springMessageText(code text) - 코드에 해당하는 메시지를 출력한다. 메시지가 존재하지 않을 경우 text를 출력한다.
(2) 커맨드 객체 연동을 위한 #springBind 매크로와 #springBindEscaped 매크로
-. #springBind 매크로는 커맨드 객체와 관련도니 BindStratus 정보를 설정한다.
-. #springBind 매크로는 다음과 같이 커맨드 객체와 관련도니 경로를 설정하며, 관련 BindStatus 정보는 status 변수를 통해서 접근한다.
<p> <label for="id">#springMessage("login.form.id")</label> #springBind("login.id") <input type="text" name="${status.expression}" id"=${status.expression}" value="$!status.value" /> #springShowErrors("<br/>" "") </p> |
-. HTML 특수 문자 처리 여부를 직접 명시하고 싶다면, 다음과 같이 #springBindEscaped 매크로를 사용하면 된다.
<p> <label for="id">#springMessage("login.form.id")</label> #springBindEscaped("login.id", false) <input type="text" name="${status.expression}" id"=${status.expression}" value="$!status.value" /> #springShowErrors("<br/>" "") </p> |
(3) <input> 태그를 위한 매크로
-. #springFromInput 매크로를 사용하면 커맨드 객체와 관련된 <input> 태그를 손쉽게 출력할 수 있다.
◎ #springMessage($path $attributes)
-. hidden 타입의 <input> 태그나 password 타입의 <input> 태그를 생성하고 싶다면, 다음의 두 매크롤르 사용하면 된다.
◎ #springFormPasswordInput($path $attributes) - password 타입의 <input> 태그를 생성한다.
◎ #springFormHiddenInput($path $attributes) - hidden 타입의 <input> 태그를 생성한다.
(4) <select> 태그를 위한 매크로
-. 스프링은 <select> 태그와 관련하여 다음과 같이 두 개의 매크로를 제공하고 있다.
◎ #springFormSingleSelect($path $options $attributes)
◎ #springFormMultiSelect($path $options $attributes)
(5) checkbox 타입 <input> 태그를 위한 매크로
-. checkbox 타입을 위한 <input> 태그를 생성할 때에는 다음과 같은 매크로를 사용한다.
◎ #springFormCheckboxes($path $options $separator $attributes)
◎ #springFormCheckbox($path $attributes)
(6) radio 타입 <input> 태그를 위한 매크로
-. radio 타입의 <input> 태그를 생성하기 위한 스프링 매크로는 다음과 같다.
◎ #springFormRadioButton($path $options $separator $attributes)
(7) <textarea> 태그를 위한 매크로
-. <textarea> 태그를 생성하기 위한 매크로는 다음과 같다.
◎ #springFormTextarea($path $attributes)
(8) 에러 메시지 출력을 위한 #springShowErrors 매크로
-. #springShowErrors 매크로는 커맨드 객체와 관련된 에러 메시즈를 출력할 때 사용도니다.
◎ #springShowErrors($separator $class/style)
- #springBind/#springBindEscaped 매크로로 바인딩 된 BindStatus와 관련도니 에러 메시지들을 출력한다.
(9) VelocityLayoutViewResolver를 이용한 레이아웃 템플릿 적용
-. Tiles와 비슷하게 Velocity도 동일한 레이아웃 템플릿을 적용해 주는 기능을 제공하고 있다.
-. 레이아웃 템플릿을 모든 Velocity 템플릿에 적용하면 VelocityLayoutViewResolver를 ViewResolver로 사용하도록 설정해 주어야 한다.
<bean id="velocityConfigurer" … p:suffix=".vm" |
① 컨트롤러의 처리 결과를 보여 줄 템플릿 파일을 찾은 뒤, 템플릿 파일로부터 결과 화면을 생성한다.
이때 생성된 결과 화면을 screen_content 변수에 저장한다.
② layoutUrI 프로퍼티로 지정한 레이아웃 템플릿 파일을 파싱하여 결과 화면을 생성한다.
이때, 레이아웃 템플릿 파일은 $screen_content 변수를 사용하여 1단계에서 생성한 결과 화면을 내부에 포함시키게 된다.
(10) Velocity 레이아아웃 파일 생성
-. 레이아웃으로 사용될 Velocity 템플릿 파일은 일반적인 Velocity 템플릿 파일과 별다른 차이가 없다.
차이점이 있다면 앞서 설명했듯이 처리 결과로 생성된 결과를 포함하기 위한 $screen_content 변수가 사용된다는 점이다.
<html> |
06. HTML 이외의 뷰 구현
6.1 파일 다운로드 구현을 위한 커스텀 View
-. 파일 다운로드를 구현하는 경우, 컨트롤러 클래스는 다운로드 받을 파일과 관련된 정보를 생성해서 뷰에 전달할 것이다.
-. 아래 코드는 File 객체를 "download" 뷰에 전달하는 컨트롤러이다.
@Controller |
-. 파일을 다운로드를 위한 뷰는 JSP나 Velocity가 아니기 때문에, 파일 다운로드를 위한 커스텀 뷰 클래스를 구현해 주어야 한다.
-. 또한, BeanNameViewResolver나 XMLViewResolver를 이용해서 커스텀 뷰 클래스를 사용할 수 있도록 알맞게 설정해 주어야 한다.
<bean id ="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean id ="download" class="madvirus.spring.chap07.view.DownloadView" /> |
-. 파일을 다운로드를 구현하려면 컨텐츠 타입을 "application/octet-stream"과 같이 다운로드를 위한 타입으로 설정해 주어야 하며,
다운로드 받는 파일 이름을 알맞게 설정하기 위해서는 Content-Disposition 헤더의 값을 알맞게 설정해 주어야 한다.
package madvirus.spring.chap07.view; |
6.2 AbstractExcelView 클래스를 이용한 엑셀 다운로드 구현
-. 스프링은 엑셀 형식으로 뷰 데이터를 생성할 수 있도록 다음의 두 View 클래스를 제공하고 있다.
◎ AbstractExcelView - POI API를 이용하여 엑셀 응답을 생성한다.
◎ AbstractExcelView - JExcel API를 이용하여 엑셀 응답을 생성한다.
-. AbstractExcelView 클래스는 다음과 같은 메서드를 정의하고 있다.
protected abstract void buildExcelDocument ( Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception; |
-. HSSFWorkbook은 POI API가 제공하는 엑셀 관련 클래스이다.
-. 하위 클래스는 이 클래스를 이용해서 엑셀 문서를 생성하면 된다.
package madvirus.spring.chap07.view; |
6.3 AbstractPdfView 클래스를 이용한 PDF 다운로드 구현
-. 스프링은 iText API를 이용해서 PDF를 생성할 수 잇는 AbstractPdfView 클래슬르 제공하고 있다.
-. AbstractPdfView 클래슨느 다음과 같은 메서드를 정의하고 있다.
protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception |
-. com.lowagie.textDocument 클래스는 iText가 제공하는 클래스로서, Document 객체에 PDF 문설르 생성하느 데 필요한 객체를 추가함으로써
PDF 문서를 생성할 수 있다.
package madvirus.spring.chap07.view; |
6.4 MarshaalingView를 이용한 XML 응답 생성
-. 스프링 3 버전에는 자바 객체를 XML로 출력해주는 뷰 구현체인 MarshaalingView 클래스가 추가되었다.
-. MarshaalingView 클래스는 자바 객체를 XML 문서로 변환시켜주는 Marshaaler와 변환할 모델 키를 각각
marshaaler 프로퍼티와 modeKey 프로퍼티로 전달받는다.
<bean id="pageXmlReport" |
-. 위 설정에서 Jaxb2Marshaller는 PageRankReport 클래스를 매핑 대상 클래스로 설정하고 있는데,
PageRankReport 클래스 및 이 클래스가 포함하고 있는 PageRank 클래슨느 다음과 같이 JAXB 2 API를 사용해서 매핑 정보를 설정하고 있다.
@XmlAccessorType(XmlAccessType.FIELD)
|
-. PageRankReport 객체와 PageRank 객체를 생성해서 report 키 값으로 모델에 저장한 뒤 MarshallingView에 전달하는 컨트롤러를 구현
@RequestMapping("/pageXmlReport") |
6.5 MappingJacksonJsonView를 이용한 JSON 응답 생성
-. 스프링 3 버전은 자바 객체를 JSON으로 변환해서 보여주는 뷰 구현 클래스인 MappingJacksonJsonView를 제공하고 있다.
-. 아래 코드는 MappingJacksonJsonView의 설정 예를 보여주고 있다.
<bean id="pageJsonReport" <bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" /> |
-. 컨트롤러에서는 다음과 같이 뷰 이름으로 MappingJacksonJsonView 타입의 빈을 설정해 주면 된다.
@RequestMapping("/pageJsonReport") |
-. MappingJacksonJsonView는 모델에 저장도니 모든 객체를 JSON 형식으로 변환해 준다.
public String controllerMethod(Model model) { … model.addAttribute("report", report); model.addAttribute("summary", summary); … } |
-. 컨트롤러에서 위와 같이 모델을 설정한 경우 MappingJackson.JsonView는 다음과 같은 형식의 JSON 응답 결과를 생성한다.
{"report":..., "summary":...} |
-. 응답 결과로 생성되는 컨텐츠 타입은 application/json이며 캐리턱 인코딩은 UTF-8 이다.
07. Locale 처리
-. 스프링이 제공하는 <spring:message> 커스텀 태근느 웹 요청과 관련된 언어 정보를 이용해서 알맞은 언어의 메시지를 출력한다.
-. 실제로, 스프링 MVC는 LocaleResolver를 이용해서 웹 요청과 관련된 Locale을 추출하고, 이 Locale 객체를 이요해서 알맞은 언어의 메시지를 선택하게 된다.
7.1 LocaleResolver 인터페이스
-. org.springframework.web.servlet.LocaleResolver 인터페이스는 다음과 같이 정의되어 있다.
package org.springframework.web.servlet; import javax.ervlet.httpHttpServletRequest; import javax.ervlet.httpHttpServletResponse; public interface LocaleResolver { Locale resolveLocale(HttpServletRequest request); void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale); } |
-. resolveLocale() 메서드는 요청과 관련된 Locale을 리턴한다. DispatcherServlet은 등록되어 있는 LocaleResovler의 resolveLocale() 메서드를 호출해서
웹 요청을 처리할 때 사용할 Locale을 구한다.
-. setLocale() 메서드는 Locale을 변경할 때 사용된다. 예를 들어, 쿠키나 HttpSession에 Locale 정보를 저장할 때에 이 메서드가 사용된다.
7.2 LocaleResolver의 종류
-. 스프링이 제공하는 LocaleResolver 구현 클래스
클래스 |
설명 |
AcceptHeaderLocaleResolver |
-. 웹 브라우저가 전송한 Accept-Language 헤더로부터 Locale을 선택한다. -. setLocale() 메서드를 지원하지 않는다. |
CookieLocaleResolver |
-. 쿠키를 이용해서 Locale 정보를 구한다. -. setLocale() 메서드는 쿠키에 Locale 정보를 저장한다. |
SessionLocaleResolver |
-. 세션으로부터 Loclae 정보를 구한다. -. setLocale() 메서드는 세션에 Locale 정보를 저장한다. |
FixedLocaleResolver |
-. 웹 요청에 상관없이 특정한 Locale로 설정한다. -. setLocale() 메서드를 지원하지 않는다. |
※ LocaleResolver를 직접 등록할 경우 빈의 이름을 "localeResolver"로 등록해 주어야 한다.
7.3 LocaleResolver를 이용한 Locale 변경
-. LocaleResolver를 빈으로 등록했다면, 컨트롤러에서 LocaleResolver를 이용해서 Locale을 변경할 수 있게 된다.
<bean class="madvirus.spring.chap07.controller.LocaleChangeController"> <property name="localeResolver" ref="localeResolver" /> </bean> <bean id="viewResolver" |
-. 이 경우, 컨트롤러 클래스는 다음과 같이 LovaleResolver의 setLocale() 메서드를 호출해서 클라이언트의 웹 요청을 위한 Locale을 변경할 수 있다.
package madvirus.spring.chap07.controller; |
-. LocaleResolver를 이용해서 Locale을 변경하면, 이후 요청에 대해서는 지정한 Locale을 이용해서 메시지 등을 로딩하게 된다.
-. RequsetContextUtils 클래스는 웹 요청과 관련된 LocaleResolver를 구현할 수 있는 메서드를 제공하고 있으므로, 위 코드를 다음과 같이 변경할 수 있다.
package madvirus.spring.chap07.controller; |
7.4 LocaleChangeInterceptor를 이용한 Locale 변경
-. 스프링이 제공하는 LocaleChangeInterceptor 클래스를 사용하면 웹 요청 파라미터를 이용해서 손쉽게 Locale을 변경할 수 있다.
-. LocaleChangeInterceptor 클래스는 HandlerInterceptor로서 다음과 같이 HandlerMapping의 interceptors 프로퍼티에 등록만 하면 설정이 완료된다.
<bean id="localeChangeInterceptor" <bean |
-. paramName 프로퍼티는 Locale을 설정할 때 사용할 파라미터 이름을 명시한다.
예를 들어, 위 코드에서는 paramName 프로퍼티의 값으로 language를 설정했는데,
이 경우 language 요청 파라미터를 사용해서 Locale을 변경할 수 있다.
http://localhost:8080/chap07/jsp/login/login.do?language=en |
-. LocaleChangeInterceptor는 paramName 프로퍼티로 설정한 요청 파라미터가 존재할 경우,
파라미터의 값을 이용해서 Locale을 생성한 뒤 LocaleResolver를 이용해서 Locale을 변경한다. 이후, 요청에서는 변경된 Locale이 적용된다.