SiteMesh를 사용하여 웹 페이지에 레이아웃을 적용하기 위해서는 다음의 두 가지를 필요로 한다.
SiteMesh 설정 1, web.xml
SiteMesh를 설정하기 위해서는 먼저 SiteMesh가 제공하는 PageFilter(서블릿 필터)를 설정해주어야 한다. 아래 코는 설정 예이다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>
com.opensymphony.module.sitemesh.filter.PageFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
위 코드는 / 로 들어오는 모든 요청에 대해서 PageFilter를 적용한다고 설정하였다. PageFilter는 요청 URL과 매칭되는 데코레이터를 검색한 뒤, 데코레이터가 발견될 경우 결과 HTML에 매칭되는 데코레이터를 적용한다. 따라서, 데코레이터가 적용되어야 하는 URL의 경우 반드시 PageFilter에 매핑시켜주어야 한다.
SiteMesh 설정 2, decorators.xml 작성
web.xml 파일에 PageFilter 매핑을 설정한 다음에는, 실제 데코레이터에 대한 정보를 담고 있는 decorators.xml 파일을 작성해주어야 한다. decorators.xml 파일은 데코레이터에 대한 설정 정보를 담게 된다.
decorators.xml 파일은 다음과 같은 형태로 데코레이터 목록을 기술한다.
<decorators defaultdir="/decorators">
<decorator name="submenu" page="submenu_decorator.jsp">
<pattern>/sub/*</pattern>
</decorator>
<decorator name="main" page="main_decorator.jsp">
<pattern>/*</pattern>
</decorator>
</decorators>
위 코드에서 <decorators> 태그의 defaultdir 속성은 데코레이터 JSP가 위치할 경로를 의미한다. 이 경로는 웹 어플리케이션 콘텍스트 내에서의 경로를 의미한다.
<decorator> 태그는 한 개의 데코레이터를 설정한다. <decorator> 태그의 두 속성은 다음과 같다.
- name - 데코레이터의 이름
- page - 데코레이터로 사용될 JSP 페이지
<pattern> 태그는 데코레이터를 적용할 패턴을 의미한다. 이 패턴은 서블릿 매핑에서의 패턴과 비슷하다. 예를 들어, /sub/submain1.jsp 나 /sub/menu/submenu1.jsp 로 요청이 들어올 경우 'submenu' 데코레이터가 적용되며, 그 외 /main.jsp나 /another/another1.jsp와 같이 /sub/* 에 포함되지 않는 요청의 경우는 'main' 데코레이터가 적용된다.
만약 정확하게 일치하는 <pattern> 값이 존재할 경우 해당 데코레이터를 사용한다. 예를 들어, 아래의 설정을 보자.
<decorator name="submenu" page="submenu_decorator.jsp">
<pattern>/sub/*</pattern>
</decorator>
<decorator name="submain" page="submain_decorator.jsp">
<pattern>/sub/submain1.jsp</pattern>
</decorator>
이 경우 /sub/submain1.jsp는 submenu 데코레이터와 submain 데코레이터에 모두 매핑되지만, 좀더 정확하게 일치하는 submain 데코레이터가 사용된다.
한 개의 <decorator> 태그는 0개 이상의 <pattern> 태그를 포함할 수 있다.
서블릿 매핑 시 주의 사항
서블릿 매핑을 사용할 경우 <pattern> 값은 서블릿의 경로를 따른다. 예를 들어, 다음과 같이 서블릿 매핑을 설정했다고 하자.
<servlet-mapping>
<servlet-name>content</servlet-name>
<url-pattern>/catalog/*</url-pattern>
</servlet-mapping>
이 경우, 지정한 서블릿 매핑에 해당되는 요청에 데코레이터를 적용하고자 한다면, 다음과 같이decorators.xml의 <pattern> 태그의 값으로 서블릿 경로명을 지정해주어야 한다.
<decorator name="catalog" page="catalog_decorator.jsp">
<pattern>/catalog</pattern>
</decorator>
만약 서블릿 경로명이 아닌 /catalog/* 를 <pattern> 태그의 값으로 지정할 경우 해당 데코레이터가 적용되지 않는다.
데코레이터 작성
SiteMesh의 데코레이터는 JSP 페이지로서, SiteMesh가 제공하는 커스텀 태그를 사용하여 결과 HTML 페이지를 데코레이션하게 된다. 아래 코드는 간단하게 작성해본 SiteMesh의 데코레이터 코드이다.
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
<html>
<head>
<title><decorator:title default="테크리포트" /></title>
<decorator:head />
</head>
<body>
<div>헤더</div>
<hr/>
<decorator:body />
<hr/>
<div>푸터</div>
</body>
</html>
위 코드에서 눈여겨 볼 부분은 decorator로 시작하는 커스텀 태그이다. 사용자의 요청을 처리한 결과 페이지는 데코레이터에 전달되는데, 이때 커스텀 태그를 사용하여 전달된 페이지의 내용을 사용할 수 있게 된다. 예를 들어, <decorator:title> 커스텀 태그는 전달된 페이지의 <title> 태그의 값을 구하게 된다. 사용가능한 커스텀 태그는 다음과 같다.
<decorator:head />
HTML의 <head> 태그의 내용을 삽입한다.
<decorator:body />
<body> 태그의 내용을 삽입한다.
<body> 태그에 명시된 프로퍼티의 값을 데코레이터 JSP에 삽입하고 싶다면 다음과 같이 <decorator:getProperty> 커스텀 태그를 사용하면 된다.
<body onload="<decorator:getProperty property="body.onload" />">
…
<decorator:body />
…
</body>
<decorator:title [ default="..." ] />
<title> 태그에 명시된 타이틀을 삽입한다. 만약 <title> 태그의 값이 발견되지 않을 경우 default 속성에 명시한 값을 삽입한다.
<decorator:getProperty property="." [default="."] [writeEntireProperty="." ]/>
원본 HTML 페이지의 프로퍼티를 삽입한다. 이때 사용가능한 프로퍼티는 다음과 같이 생성된다.
- HTML Tag:
<html> 태그의 모든 속성이 프로퍼티로 추가된다.
- TITLE Tag:
<title> 태그의 내용이 'title' 프로퍼티로 추가된다.
- META Tags:
이름과 내용을 갖는 모든 <meta> 태그는 'meta.이름' 프로퍼티로 추가된다.
- BODY Tag:
모든 <body> 태그의 속성이 'body.속성이름' 프로퍼티로 추가된다.
<decorator:getProperty> 커스텀 태그에서 사용가능한 속성은 다음과 같다.
- property (필수) - 삽입할 프로퍼티의 이름(키)
- default (선택) - 프로퍼티가 존재하지 않을 경우 삽입할 값
- writeEntireProperty (선택) - 프로퍼티의 이름 및 이름 앞의 공백을 함께 삽입할 지의 여부를 지정한다. 허용되는 값은 'true', 'yes', 또는 '1' 이다.
예를 들어, 원본 페이지에서 다음과 같이 <body> 태그를 작성했다고 하자.
<body onload="document.someform.somefield.focus();">
그리고 데코레이터 JSP에서 다음과 같이 <decorator:getProperty> 커스텀 태그를 사용했다고 하자.
<body bgcolor="White" <decorator:getProperty property="body.onload"
writeEntireProperty="true" />>
이 경우 최종적으로 생성되는 코드는 다음과 같다.
<body bgcolor="White" onload="document.someform.somefield.focus();">