이글은 webwork,sitemesh를 기반으로 한 프레임워크에 적합한 내용입니다. 그리고, 이 글은 모든 내용이 다 맞지 않습니다.
한글 자료가 거의 전무하여 적어 놓게 되었습니다. 회사이름은 밝히기 않기 위해. 대충 가명썼습니다..
소개
SiteMesh는 web-page layout이고, decoration(장식) 프레임웍이고, 일관된 look/fee, navagation, layout scheme를 필요로 하는 많은 페이지로 구성된 큰 사이트를 만드는것을 도와주는 web-application 통합 프레임웍이다. 일관성있는 요소들때문에 조직화하고, 변화와 수정에 탁월해야 한다. Sitemesh,는 웹 서버에 요구된 정적/동적 요청을 가로채어 요청된 페이지 자원을 파싱하여 설정된 속성과 렌더링할 데이터를 컨텐츠로부터 읽어들여 원래의 페이지에 decoration과 수정을 가해 최종 페이지를 생성한다.
대부분의 HTML 문서는 다음과 같은 decorator 패턴 양식을 가지고 있다.
- meta tags (keywords, description, author)
- stylesheet (CSS)
- header
- navigation
- footer
- copyright notice
naviation과 layout 스킴만 정하면 나머지는 공통부분으로 따로 정리할 수 있도록 도와주는 프레임웍이 Sitemesh 이다.
Figure 1. Normal Page Rendering
Figure 2. SiteMesh Page Rendering
간단히 맛보기
기본적인 jsp 코드는 다음과 같다.
<html> <head> <title>Simple Document</title> </head> <body> Hello World! <br /> <%= 1+1 %> </body> </html>
위의 코드의 템플릿으로 만들어지는 페이지를 데코레이션을 사용하여 jsp 페이지를 동적으로 승화시킬 수 있다.
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title> My Site - <decorator:title default="Welcome!" /> </title> <decorator:head /> </head> <body> <h1><decorator:title default="Welcome!" /></h1> <p><decorator:body /></p> </body> </html>
첫번째 라인에 sitemesh 태그라이브러리가 소개되고, <decorator:title> 엘리먼트는 장식될 페이지의 <title> 엘리먼트의 텍스트를 가져와 삽입한다. <decorator:body> 엘리멘트는 페이지의 본문을 장식한다.
Sitemesh에 모든 패턴에 사용할 decorator를 WEB-INF/decorators.xml파일에 설정한다.
<decorators> <decorator name="mydecorator" page="/decorator.jsp"> <pattern>/*</pattern> </decorator> <decorators>
이런 식으로 밑의 파일처럼 특정 디렉토리 또는 패턴에 따라 다양하게 decoration이 가능하다.
<decorators defaultdir="/decorators"> <decorator name="default" page="default.jsp"> <pattern>/*</pattern> </decorator> <decorator name="anotherdecorator" page="decorator2.jsp"> <pattern>/subdir/*</pattern> </decorator> <decorator name="htmldecorator" page="html.jsp"> <pattern>*.html</pattern> <pattern>*.htm</pattern> </decorator> <decorator name="none"> <!-- These files will not get decorated. --> <pattern>/anotherdir/*</pattern> </decorator> </decorators>
환경 설정
cvs서버로부터 test_project프로젝트를 update하고, 그 기반에서 동작하는 것을 기준으로 한다.
- sitemesh.jar가 [web-app home directory]/WEB-INF/lib에 위치해 있는지 확인한다. (sitemesh 2.1.1 gl 버젼의 jar파일이 저장되어 있음을 확인할 수 있을 것이다.)
- [web-app home directory]/WEB-INF/web.xml의 <web-app> 태그안에 다음의 내용이 추가되어야 한다. webwork-cleanup - sitemesh - webwork 의 순서대로 등록해야 한다.
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app 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" version="2.4"> .....fileter의 webwork-cleanup 정의 ..... <filter> <filter-name>sitemesh</filter-name> <filter-class> com.opensymphony.module.sitemesh.filter.PageFilter </filter-class> <init-param> <param-name>pageEncoding</param-name> <param-value>MS949</param-value> </init-param> </filter> .....fileter의 sitemesh 정의 ..... .....filter-mapping의 webwork-cleanup 정의 ..... <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping> .....filter-mapping의 sitemesh 정의 .....
- [web-app home directory]/WEB-INF/sitemesh.xml 파일이 생성해야 한다. 필수 파일은 아니지만, 있어야 원하는 패턴을 지정할 수 있다.
sitemesh.xml
<sitemesh> <page-parsers> <parser default="true" class="com.opensymphony.module.sitemesh.parser.DefaultPageParser" /> <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" /> </page-parsers> <decorator-mappers> <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper"> <param name="property.1" value="meta.decorator" /> <param name="property.2" value="decorator" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper"> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper"> <param name="match.MSIE" value="ie" /> <param name="match.Mozilla [" value="ns" /> <param name="match.Opera" value="opera" /> <param name="match.Lynx" value="lynx" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper"> <param name="decorator" value="printable" /> <param name="parameter.name" value="printable" /> <param name="parameter.value" value="true" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper"> <param name="decorator" value="robot" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper"> <param name="decorator.parameter" value="decorator" /> <param name="parameter.name" value="confirm" /> <param name="parameter.value" value="true" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper"> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper"> <param name="config" value="/WEB-INF/decorators.xml" /> </mapper> </decorator-mappers> </sitemesh>
- [web-app home directory]/WEB-INF/decorators.xml 파일이 생성되어야 한다.
decorators.xml
<decorators> <decorator name="defaultHeader" page="defaultHeader.jsp"/> <decorator name="defaultFooter" page="defaultFooter.jsp"/> <decorator name="default" page="default.jsp"> <pattern>/*</pattern> </decorator> </decorators>
헤더와 풋터 jsp를 지정한다.그리고, 디폴트 페이지를 모든페이지에 지정한다.
- [web-app home directory]/WEB-INF/decorators 디렉토리에 템플릿으로 쓰일 default.jsp, defaultHeader.jsp, defaultFooter.jsp 파일을 생성한다.
default.jsp
<%@ page language="java" pageEncoding="MS949" %> <%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %> <%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> <head> <meta http-equiv=Cache-Control content=No-Cache> <meta http-equiv=Pragma content=No-Cache> <meta http-equiv="expires" content="0"> <META HTTP-EQUIV="imagetoolbar" CONTENT="no"> <meta http-equiv="Content-type" content="text/html; charset=euc-kr"> <title><decorator:title default="퍼블 테스트" /></title> </head> <body bgcolor=ffffff bottommargin=0 topmargin=0 marginheight=0> <!-- TOP Menu --> <page:applyDecorator name="defaultHeader"/> <!-- //TOP Menu 영역 --> xxxx <decorator:body/> xxxx <!-- footer --> <page:applyDecorator name="defaultFooter"/> <!-- //footer 영역 --> </html>
defaultHeader.jsp<%@ page language="java" pageEncoding="MS949" %> <!--head start--> Header<br> <!--head end-->
defaultFooter.jsp<%@ page language="java" pageEncoding="MS949" %> <!--Footer start--> <br> Footer <Br> <!--Footer end-->
- 하나의 액션 HelloWorld.java를 생성한다.
HelloWorld
import com.google.common.actions.GoogleBaseAction; public class HelloWorld extends GoogleBaseAction { public String execute() throws Exception { return SUCCESS; } }
- [web-app home directory]/hello.jsp 코드를 작성한다.
hello.jsp
<%@ page language="java" pageEncoding="MS949" %> <%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %> <%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> Hello World
- 결과
Web browser
Header xxxx Hello World xxxx Footer
Sitemesh의 설정 파일 설명
decorators.xml
decorators.xml 은 여러 decorator의 정의와 특정 decorator가 적용될 페이지의 리스트가 설정되어 있다. decorator의 순서에 따라 적용되어 진다.
<?xml version="1.0" encoding="ISO-8859-1"?> <decorators defaultdir="/decorators"> <!-- Any urls that are excluded will never be decorated by Sitemesh --> <excludes> <pattern>/exclude.jsp</pattern> <pattern>/exclude/*</pattern> </excludes> <!-- decorator 태그안에 page의 경로는 web-app/decorators/main.jsp가 된다.--> <decorator name="main" page="main.jsp"> <pattern>/*</pattern> </decorator> <decorator name="panel" page="panel.jsp"/> <decorator name="printable" page="printable.jsp"/> <decorator name="black" page="black.jsp"/> <decorator name="nopanelsource" page="nopanelsource.jsp"/> <decorator name="badpanelsource" page="badpanelsource.jsp"/> <decorator name="velocity" page="velocity.vm"> <pattern>/velocity.html</pattern> </decorator> <decorator name="freemarker" page="freemarker.ftl"> <pattern>/freemarker.html</pattern> </decorator> <decorator name="test" page="test.jsp"> <pattern>/agent.jsp</pattern> </decorator> </decorators>
- decorators
<decorators> 엘리먼트는 decorator들의 리스트를 정의하고 있다. <decorators defaultdir="/decorators">의 defaultdir="/decorators" attribute은 기본적으로 decorator page들이 위치하고 있는 경로를 나타낸다. - excludes
<excludes> 엘리먼트는 decorator가 적용되지 않아야 할 패턴의 리스트이다.
decorator name="main"의 main decorator는 모든 패턴의 리소스에 적용되며 main.jsp를 decorator page로 사용한다는 뜻이다.
panel, printable, black, nonpanelsource, badpanelsource는 모두 패턴을 지정하지 않았고, freemaker, velocity는 특정페이지를 적용했다. - pattern
<pattern> 엘리먼트는 decorator가 적용될 Request URI를 지정한다. 패턴이 적용되는 순서가 다르다. Request URI를 보고 다음의 순서대로 해당 decorator page를 찾게된다.
- 정확하게 단어가 맞는 패턴 (Exact word)
- 'abc*'나 'abc?'와 같은 컴플렉스 패턴 (Complext)
- '/', '*', '/*'와 같은 디폴트 패턴 (Default)
적절한 패턴이 설정되지 않은 decorator는 다른 decorator 내에서 <page:applyDecorator/>를 통해 포함할 때 사용되거나 decorator mapper(sitemesh.xml)에서 특정 decorator를 지정할 때 사용된다.
sitemesh.xml
sitemesh.xml은 decorator mapper 리스트가 설정되어 있다. 만일 Sitemesh가 해당 경로에서 설정 파일을 찾는데 실패하면sitemesh.jar 에 패키징 되어 있는 sitemesh-default.xml 파일로 대체된다.
<sitemesh> <property name="decorators-file" value="/WEB-INF/decorators.xml" /> <page-parsers> <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" /> </page-parsers> <excludes file="${decorators-file}" /> <decorator-mappers> <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper"> <param name="property.1" value="meta.decorator" /> <param name="property.2" value="decorator" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper"> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper"> <param name="match.MSIE" value="ie" /> <param name="match.Mozilla [" value="ns" /> <param name="match.Opera" value="opera" /> <param name="match.Lynx" value="lynx" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper"> <param name="decorator" value="printable" /> <param name="parameter.name" value="printable" /> <param name="parameter.value" value="true" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper"> <param name="decorator" value="robot" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper"> <param name="decorator.parameter" value="decorator" /> <param name="parameter.name" value="confirm" /> <param name="parameter.value" value="true" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper"> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper"> <param name="config" value="${decorators-file}" /> </mapper> </decorator-mappers> </sitemesh>
- page parsers
<page-parsers> 엘리먼트는 content-type에 따라 적용할 파서를 정의한다. SiteMesh는 현재 text/html을 파싱할 때 사용되는 FastPage Parser만 구현되어 있다. 나머지에 대해서는 디폴트로 DefaultPageParser가 사용가능하다.<page-parsers> <parser default="true" class="com.opensymphony.module.sitemesh.parser.DefaultPageParser" /> <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" /> </page-parsers>
- decorator mapper
decorator mapper는 Sitemesh에게 장식에 사용될 적합한 decorator를 설정해주는 역할을 한다. <decorator-mapper> 엘리먼트는 decorator mapper들을 정의한다. decorator mapper 추상 클래스는 링크드 리스트로 정의되어 있고, 적혀진 순서에 따라 decorator 체인으로 만들어진다.<decorator-mappers> <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper"> <param name="property.1" value="meta.decorator" /> <param name="property.2" value="decorator" /> </mapper> </decorator-mappers> ....
- excludes
특정 웹 페이지(jsp)들을 모아 decoration이 적용되지 않도록 하는 설정파일을 지정한다.<excludes file="/WEB-INF/decorators.xml"/>
- property
변수화하여 쉽게 사용할 수 있도록 한다.<property name="decorators-file" value="/WEB-INF/decorators.xml" /> ... <excludes file="${decorators-file}" /> ... <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper"> <param name="config" value="${decorators-file}" /> </mapper>
ConfigDecoratorMapper는 decorator 파일들을 config로 지정할 수 있음을 의미하며, 여러 개의 config 파일을 포함할 수 있다.
Decorator를 이용한 일관성있는 Look
jsp와 이미 기존에 쓰이고 있는 CGI script가 사용할 수 있도록 도와줌으로서, 일관성있는 look을 제공한다.
Flow Diagram
web.xml에서 정의된 필터, 즉 PageFiletr에 의해 Sitemesh가 사용되어진다.
페이지를 Page 객체에 파싱한 후 DecoratorMapper에 의해서 Decorator를 판단한다. 그래서 sitemesh.xml 파일에 DecoratorMapper 선언된 순서대로 decorator를 사용하고 mapper에서 결국 decorator를 얻지 못하면 본래 모습으로 보여준다. 주요 DecoratorMapper는 /WEB-INF/decorators.xml에서 decorator와 mapping을읽어들이는 ConfigDecoratorMapper 이다.
SiteMesh 구조와 흐름
- request 단계
모든 request는 PageFilter에서 가로채어진다. PageFilter는 Context 초기화 시점에 decorator.xml에 정의된 <exclude> 태그에 따라 요청된 request의 url-pattern에 따라 장식을 수행할지 여부를 결정한다. - paring 단계
PageFilter는 요청된 자원에 대한 웹 어플리케이션의 수행결과를 do(request, respose) 메소드를 호출하여 받아낸다. 응답 파라미터에는 ServletResponse가 아닌 HttpServletResponseWrapper를 상속받아 확장한 PageResponseWrapper 객체를 사용한다.
따라서 페이지 아웃풋은 writer로 보내지 않고 content-type에 따라 선택된 파서가 PageResponseWrapper에서 캡처된 page 아웃풋 데이터를 파싱한다. 현재는 반환 page의 content-type이 text/html일 경우만 FastPageParser가 작동한다. - decorator 선정 단계
적합한 decorator를 결정한다. 이 과정은 mapper 클래스의 getDecorator()에 의해서 이뤄진다. 처음 decorator 선정을 시도한 mapper 클래스가 적합한 decorator를 얻어낸다면 리턴하고, 아니면 decorator 체인상의 상위 링크의 getDecorator() 메소들르 호출하게 된다. 정확한 decorator가 결정될 때까지 반복된다. - decorator 단계
decorator를 얻오고, decorator로부터 decorator page를 구해 올 수 있다면, PageFilter는 applyDecorator()내에서 decorator 페이지에 대한 요청을 생성하고, decorator page는 FastPageParser에 의해 파싱된 결과 page의 적절한 부분들을 커스텀 태그를 통해 가져와 출력 페이지를 작성한다.
참조
http://today.java.net/pub/a/today/2004/03/11/sitemesh.html
마소의 sitemesh 기사
'web' 카테고리의 다른 글
Sitemesh #4 Sitemesh 팁 (0) | 2007.08.24 |
---|---|
Sitemesh #3 Site Mesh 매뉴얼 (Tag Reference & DecoratorMapper & Freemarker) (0) | 2007.08.24 |
Sitemesh #1 Tiles에서 Sitemesh로 변환하기 (0) | 2007.08.24 |
multi-part/form-data (0) | 2007.08.23 |
html 4.0의 select-optgroup (0) | 2007.08.23 |