스프링 MVC에서 제공하는 모듈화 기능이다.
기존에는 jsp 액션 태그<jsp:include page=".." />
를 사용해 모듈화 하거나 web.xml
에서 include
태그를 통해 모듈화를 진행했는데
스프링 프레임 워크에서도 비슷하게 구현 가능하다.
스프링 프레임 워크에선 처음부터 페이지를 부분적으로 조각내놓고 타일처럼 조립하는 방식을 사용한다.
그럼 기존의 notice.jsp
라는 공지사항을 출력하는 뷰 페이지를 중복되는 부분을 모두 쪼개서 각각의 파일로 저장해 보자.
전체적인 구조는 아래와 같다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>index</title>
<link href="notice.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="header">...</div>
<div id="visual" class="customer">...</div>
<div id="main">
<div class="top-wrapper clear">
<div id="content">...</div>
<div id="navi">...</div>
</div>
</div>
<div id="footer">...</div>
</body>
</html>
이제 이 하나의 파일을 header.jsp
, visual.jsp
, content.jsp
, navi.jsp
, footer.jsp
로 나누어 보자.
<!-- header.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="header">...</div>
<!-- visual.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="visual" class="customer">...</div>
<!-- navi.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="content">...</div>
<!-- navi.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="navi">...</div>
<!-- footer.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="footer">...</div>
파일이 나뉘어 졌으면 이 5개의 파일을 합쳐서 레이아웃 용도로 써줄 layout.jsp
페이지가 필요하다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>index</title>
<link href="notice.css" type="text/css" rel="stylesheet" />
</head>
<body>
<!-- header -->
<tiles:insertAttribute name="header" />
<!-- visual -->
<tiles:insertAttribute name="visual" />
<div id="main">
<div class="top-wrapper clear">
<!-- content -->
<tiles:insertAttribute name="content" />
<!-- navi -->
<tiles:insertAttribute name="aside" />
</div>
</div>
<!-- footer -->
<tiles:insertAttribute name="footer" />
</body>
</html>
새로운 JSTL 태그가 생겼는데 사용하려면 아래 taglib
태그를 추가하자.
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
name
속서에 설정된 식별자로 xml에 설정되어 있는 조각난 jsp페이지를 찾아옴으로 이름을 잘 기억해 두자.
이제 본격적으로 Spring tiles
을 사용하기 위해 아래 사이트에서 라이브러리를 다운받자.
http://tiles.apache.org/
http://archive.apache.org/dist/tiles/v2.2.2/ 에서
tiles-2.2.2-bin.zip
저장
압축파일을 해제하면 여러개의 jar파일이 나오는데 아래 10개의 jar파일을 /WEB-INF/lib
폴더에 넣도록 하자.
tiles-api-2.2.2.jar
tiles-core-2.2.2.jar
tiles-jsp-2.2.2.jar
tiles-servlet-2.2.2.jar
tiles-template-2.2.2.jar
lib
폴더 안의 4개
commons-beanutils-1.8.0.jar
commons-digester-2.0.jar
jcl-over-slf4j-1.5.8.jar
slf4j-api-1.5.8.jar
lib\optional
폴더 안의
slf4j-jdk14-1.5.8.jar
총 10개 추가
위에서 만든 layout.xml
에 조각난 jsp 페이지들을 합치려면 여러 설정이 필요한데 하나씩 알아보자.
Dispatcher
(프론트 컨트롤러)가 사용하는 기본 viewResolver
부터 타일즈용 viewResolver
로 바꿔주어야 한다.
<!-- dispatcher-servlet.xml -->
...
...
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions" value="/WEB-INF/tiles-defs.xml"></property>
</bean>
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"></property>
</bean>
...
...
tiles-defs.xml
설정 파일을 통해 만들어지는 TilesConfigurer
빈 객체를 생성,
TilesView
풀 클래스명을 viewClass
필드에 문자열로 주입해주고 UrlBasedViewResolver
빈 객체를 생성한다.
위 두 빈 객체 추가를 통해 기본 ViewResolver
객체가 InternalResourceViewResolver
에서 UrlBasedViewResolver
로 바뀌었다.
하지만 만약 타일즈 방식으로 쪼개지지 않은 페이지를 제공하고 싶다면 InternalResourceViewResolver
를 통해 jsp
페이지로 이동시켜야 한다.
(모든 페이지를 쪼갤 순 없으니 InternalResourceViewResolver
도 필요)
아래와 같이 InternalResourceViewResolver
도 빈 객체로 생성해주자.
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="controllers, newlecture" />
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions" value="/WEB-INF/tiles-defs.xml"></property>
</bean>
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"></property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
</beans>
이제 실질적으로 쪼개진 파일들을 layout.jsp
를 통해 합쳐주는 설정이 있는 tiles-defs.xml
설정파일을 알아보자.
기본
tiles-defs.xml
양식은 아래 페이지에서 참고 가능.
http://tiles.apache.org/2.2/framework/tutorial/basic/pages.html
<!-- tiles-defs.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="customer.notice" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/inc/content.jsp" />
</definition>
</tiles-definitions>
<tiles-definitions>
태그가 하나의 요청을 처리하도록 설정하는 태그이다.
요청 이름은 name
속성을 사용하면 customer.notice
라는 요청이 들어오면 template
속성에 설정된 layout.jsp
를 열어
<put-attribute>
태그로 설정된 쪼개진 파일들을 layout.jsp
파일 안에 <tiles:insertAttribute name="..."/>
태그에 맞게 집어넣어 합친다.
<tiles:insertAttribute name="" />
태그의 name속성과 <put-attribute>
태그의 name 속성이 서로 매치되기 때문에 같은 이름으로 설정해주자.
@RequestMapping("notice.htm")
public String notices( @RequestParam(value="pg", defaultValue="1" , required=false) String p_page, String p_field, String p_query , Model model )
throws ClassNotFoundException, SQLException {
int page = 1;
String field = "title";
String query = "%%";
if( p_page != null && !p_page.equals("")) page= Integer.parseInt(p_page);
if( p_field != null && !p_field.equals("")) field= p_field;
if( p_query != null && !p_query.equals("")) query= "%"+p_query+"%";
List<Notice> list = this.noticeDao.getNotices( page , field, query);
model.addAttribute("list", list);
int pageCount = (int)( Math.ceil( (double)this.noticeDao.getCount(field, query) / 10 ));
model.addAttribute("pageCount",pageCount );
// return "notice.jsp";
return "customer.notice";
}
기존에는 notice.jsp
로 요청이 들어와 InternalResourceViewResolver
가 뷰 페이지로 이동시켰지만 이제는 타일즈용 ViewResolver
객체인 UrlBasedViewResolver
가 customer.notice
요청을 받아 tiles-defs.xml
파일에 설정된 대로 처리한다.
이렇게 하나씩 추가하다보면 tiles-defs.xml
파일 내용이 아래와 같이 길어진다…
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="customer.notice" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/notice.jsp" />
</definition>
<definition name="customer.noticeDetail" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/noticeDetail.jsp" />
</definition>
<definition name="customer.noticeReg" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/noticeReg.jsp" />
</definition>
<definition name="customer.noticeReg" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/noticeReg.jsp" />
</definition>
<definition name="customer.noticeEdit" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/noticeEdit.jsp" />
</definition>
</tiles-definitions>
보면 패턴이 있는데 <definition>
태그의 name속성값의 .
값이 바뀌고
맨 마지막 <put-attribute>
태그의 value
속성값의 content
값만 달라진다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="customer.*" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/{1}.jsp" />
</definition>
</tiles-definitions>
<definition>
태그의 name
속성안의 들어가는 *
특수문자는 {index}
를 통해 접근할 수 있다.
그럼 회원가입과 로그인에 해당하는 설정도 추가하자.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="customer.*" template="/customer/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/customer/inc/aside.jsp" />
<put-attribute name="visual" value="/customer/inc/visual.jsp" />
<put-attribute name="content" value="/customer/{1}.jsp" />
</definition>
<definition name="joinsu.*" template="/joinus/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" /><!-- 이름은 상관 없음 -->
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/joinus/inc/aside.jsp" />
<put-attribute name="visual" value="/joinus/inc/visual.jsp" />
<put-attribute name="content" value="/joinus/{1}.jsp" />
</definition>
</tiles-definitions>
여기서도 패턴이 보이는데 customer
와 joinus
만 바뀌면 된다.
위의 2개 <definition>
을 하나로 바꿀 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="*.*" template="/{1}/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" />
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/{1}/inc/aside.jsp" />
<put-attribute name="visual" value="/{1}/inc/visual.jsp" />
<put-attribute name="content" value="/{1}/{2}.jsp" />
</definition>
</tiles-definitions>
지금까지 <tiles:insertAttribute name="..." />
를 통해 타일로 .jsp페이지를 삽입하였는데
<tiles:getAsString name="..." />
로 문자열 값을 가져올 수 도 있다.
<!-- -->
<tiles-definitions>
<definition name="*.*" template="/{1}/inc/layout.jsp">
<put-attribute name="header" value="/inc/header.jsp" />
<put-attribute name="footer" value="/inc/footer.jsp" />
<put-attribute name="aside" value="/{1}/inc/aside.jsp" />
<put-attribute name="visual" value="/{1}/inc/visual.jsp" />
<put-attribute name="content" value="/{1}/{2}.jsp" />
<put-attribute name="css" value="{2}.css" />
<put-attribute name="title" value="Sist 5 class" />
</definition>
</tiles-definitions>
<put-attribute>
태그로 전달할 문자열 값을 설정하고 <tiles:getAsString name="title" />
JSTL 태그를 통해 설정하였던 문자열 값을 가져올 수 있다.
layout에서 개별적으로 사용하는 css파일이나 문서가 있다면 위와같은 방식으로 문자열을 넘겨줄 수 있다.
그럼 아래처럼 tiles-defs.xml
설정으로 받아오는 속성값을 이용해 요청마다 다른 값을 집어넣을 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><tiles:getAsString name="title" /></title>
<link href="<tiles:getAsString name="css" />" type="text/css" rel="stylesheet" />
</head>
...
...
</html>
만약 컨트롤러가 UrlBasedViewResolver
에게 반환한 값이 joinus.login
이라면 <link>
태그 href
속성엔 login.css
가 들어갈 것이고
반환한 값이 joinus.join
이라면 <link>
태그 href
속성엔 join.css
가 들어갈 것이다.