Sitemesh #4 Sitemesh 팁

web 2007. 8. 24. 05:29

당연하겠지만, 이 글은 그저 간단한 팁이라 생각하면 되겠당.. 더 좋은 방법이 있으면 더욱 많이 생겨나면 좋겠다.

샘플의 특정회사는 당근 가명이다...^^

 

특정 패턴을 빼거나 적용하기

특정 디렉토리에 모든 웹 컴포넌트(jsp, action, html등등)을 하나의 decoration으로 적용이 가능하다. 하지만, 때에 따라서는 그 폴더안에 특정 웹 컴포넌트등은 그 decoration을 적용시키지 않을 수도 있고, 다른 decoration을 적용시킬 수 있다.
즉, context상 같은 디렉토리에 있지만, UI상에서 다르게 decoration이 적용될 수 있는데, 이런 예외상황을 처리할 수 있는 방법을 Sitemesh는 가지고 있다.
exclude 패턴, jsp상에서의 meta 태그, decorator 패턴 지정등을 통해서 여러 패턴으로 지정이 가능하다.

Decoration의 exlclude 패턴 사용하기

특정 패턴의 action 혹은 html, jsp등에 지정된 pattern을 아예 적용하지 않고 싶을 때에 exclude를 사용할 수 있다. 이 때, 주의할 점은 decorators.xml에 exclude 패턴을 사용했다 해서 적용되지 않는다.

decorators.xml
...
<excludes> 
    <pattern>/exclude.gl</pattern> 
    <pattern>/alert.gl</pattern>
</excludes> 
...

그 이유는 sitemesh.xml 에서 exclude할 패턴을 적용할 파일을 지정해야 한다. sitemesh.xml 파일에서 exlcude할 파일 리스트가 적힌 xml파일을 지정한다.
decorator-mapper 태그안에 mapper class를 ConfigDecoratorMapper안에 해당 config파일을 적용했다 하더라도 이는 exclude 파일 리스트와는 무관하다.

<excludes file="/WEB-INF/decorators.xml"/>

다음은 exclude를 적용한 실제 예제이다.

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>

	<excludes file="/WEB-INF/d1.xml"/>
	<decorator-mappers>
		<mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
			<param name="config" value="/WEB-INF/decorators.xml" />
		</mapper>
	</decorator-mappers>
</sitemesh>
d1.xml
<decorators>
    <excludes>
	<pattern>/exclude.gl</pattern> 
         <pattern>/alert.gl</pattern>
    </excludes>
</decorators>
decorators.xml
<decorators defaultdir="/WEB-INF/decorators">
    <decorator name="indexLayout" page="indexLayout.jsp">
        <pattern>/index.gl</pattern>
    </decorator>
 
    <decorator name="defaultHeader" page="defaultHeader.jsp"/>
    <decorator name="defaultFooter" page="defaultFooter.jsp"/>


    <decorator name="default" page="default.jsp">
        <pattern>/*</pattern>
    </decorator>
</decorators>

decorator 설정 파일에서 null decorator 지정

위의 예처럼 exclude 패턴를 사용하여 지정된 패턴에서 일부 파일을 예외화할 수 있다. 또한 이 방법 외엔 다른 방법이 있다. decorator를 null로 지정하여 decoration이 적용안되게 할 수 있다. 또는 다른 특정 decoration을 지정할 수 있다.

decorators.xml
<decorator name="null">
    <pattern>/test.gl</pattern>
</decorator>

jsp, html파일에 meta 태그 사용

decorators.xml에 특정 decorator을 지정하였지만 해당 패턴에 속하지 않았지만, jsp의 파일에 decorator를 지정하여 사용이 가능하다. 이를 위해서는 sitemesh.xml에서 반드시 PageDecoratorMap 클래스가 decorator mapper로 바인딩되어야 한다. (순서는 com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper 보다는 상위에서 정의해야 한다. 그 이유에 대해서는 자세한 내용은 다음장에서 언급한다.)

siemesh.xml
<mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
    <param name="property.1" value="meta.decorator" />
    <param name="property.2" value="decorator" />
</mapper>

decorators 설정파일에서 tv라고 하는 decorator와 아무 decoration도 적용되지 않는 null decorator를 적용한다.

decorators.xml
<decorator name="tv" page="tv.jsp">
</decorator>

<decorator name="null">
</decorator>

google.jsp파일에서 tv라고 하는 decorator를 지하여, tv.jsp의 decorator page를 UI에서 쓸 수 있도록 할 수 있다.

google.jsp
<meta name="decorator" content="tv" />
<%@ page language="java" pageEncoding="MS949" %>
<html>
<head>
<title> Google Test</title>
</head>
<body onload="http://~~~">
google6
</body>
</html>

만약, 아무 decoration도 적용하지 않겠다면, 다음의 코드를 jsp 상단에 지정하면 된다.

<meta name="decorator" content="null" />

Decorator 체인

sitemesh.xml에서 정의된 mapper들의 순서가 chain으로 연결되어 있다. 순서에 유의를 해야 하는데, 순서에 따라서 완젼 다른 결과가 나올 수 있다. 왜 순서에 주의해야 하는지를 예제를 통해서 알아본다.

sitemesh.xml은 PageDecoratorMapper와 ConfigDecoratorMapper를 가지고 있다.

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>

	<!-- <excludes file="/WEB-INF/d1.xml"/>  -->

	<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.ConfigDecoratorMapper">
			<param name="config" value="/WEB-INF/decorators.xml" />
		</mapper>
	</decorator-mappers>
</sitemesh>

decorators.xml은 여러 decorator를 가지고 있다.

decorators.xml
<decorators defaultdir="/WEB-INF/decorators">
    <decorator name="defaultHeader" page="defaultHeader.jsp"/>
    <decorator name="defaultFooter" page="defaultFooter.jsp"/>

    <decorator name="default" page="default.jsp">
        <pattern>/*</pattern>
    </decorator>
    
    <decorator name="tv" page="tv.jsp">
    </decorator>

    <decorator name="null">
    </decorator>
</decorators>

위에서 사용된 google.jsp를 사용한다.

google.jsp
<meta name="decorator" content="tv" />
<%@ page language="java" pageEncoding="MS949" %>
<html>
<head>
<title> Google Test</title>
</head>
<body onload="http://~~~">
google6
</body>
</html>

실행을 해보면, tv decorator가 적용된 결과값이 나온다. (당연하다.)

Header
tv앞 google6 tv뒤 
Footer

만약 sitemesh.xml에서 PageDecoratorMapper, ConfigDecoratorMapper의 연결자 순서를 바꾸어 본다.

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>

	<!-- <excludes file="/WEB-INF/d1.xml"/>  -->

	<decorator-mappers>
		<mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
			<param name="config" value="/WEB-INF/decorators.xml" />
		</mapper>

		<mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
			<param name="property.1" value="meta.decorator" />
			<param name="property.2" value="decorator" />
		</mapper>
	</decorator-mappers>
</sitemesh>

결과는?? tv decorator가 적용되지 않는다. 기본 디폴트 decorator로 적용된다.
그 이유는 ConfigDecoratorMapper에서 처리되어 default decorator로 decoration된다.

<decorator name="default" page="default.jsp">
        <pattern>/*</pattern>
    </decorator>

즉, decoration mapper는 chain으로 구성되어 있고 (사실은 Filter Chain이다. ) 순서에 맞게 서비스를 처리하고 바로 리턴하도록 되어 있다는 점이다. 이 내용은 Site Mesh 매뉴얼 1(소개) 맨 마지막에서 언급되었으니, 참조하면 된다.

decoraotr page에서 특정 필드 추가하기

property 값을 두번 지정할 수 없다. 따로 따로 나눠서 decorator:getProperty를 사용한다.

아래의 예는 <decorator:getProperty/> 태그의 property 속성을 나란히 적어놓았다. 이 예제는 syntax 문제를 일으키기 때문에 동작이 되지 않아 에러를 web browser를 통해 볼 것이다.

X, layout.jsp
<body onload="<decorator:getProperty property="body.onload" property="body.bottommargin" writeEntireProperty="true" />" bgcolor=ffffff topmargin=0 marginheight=0>

아래의 예는 각각 따로 <decorator:getProperty/> 태그를 중복해서 사용한 것이다. 제대로 동작되는지 확인할 수 있다.

O, layout.jsp
<body onload="<decorator:getProperty property="body.onload" writeEntireProperty="true" />"  
body.bottommargin="<decorator:getProperty property="body.bottommargin"  writeEntireProperty="true" />"  
         bgcolor=ffffff topmargin=0 marginheight=0>

웹 페이지는 그저 onload와, bottommargin만 지정하면 해당 atribute가 적용되는지 알 수 있을 것이다.

<body onload="alert('1');" bottommargin=5>

Action과 Decoration

Action에 특정 decorator page를 지정한 상태에서 그 Action 에 여러 Request Parameter가 붙었을 때, 그 Action의 decorator page로 보여진다??

특정 Action에 decorator를 지정하고, Action의 디폴트 메소드외 다른 메소드를 호출하면, 또는 리쿼스트 파라미터가 여럿이 적용이 될까?

밑의 decorators.xml 파일의 예를 보자. google Action은 decorator page를 default.jsp로 가지고 있다. google.gl을 요청하면 default.jsp가decoration이 되어 xwork.xml에서 지정한 jsp파일을 보여줄 것이다.

decoratos.xml
<decorator name="default" page="default.jsp">
    <pattern>/google.gl</pattern>
    <pattern>/google.jsp</pattern>
</decorator>

만약 google Action에 parameter를 추가하거나, Action의 특정 메소드를 특정 메소드를 호출한다면, 적용이 안될 수 있도 있을 법하다. '*' 패턴을 추가하지 않기 때문에 아리까리할 수 있다.

/google.gl?m=register

결과는 해당 패턴에 적용된다는 것이다. Action 이름을 리쿼스트 파라미터로 받으면 파라미터가 얼마나 붙든지 간단하게 정의된 Action기반 Sitemesh 설정파일로 쉽게 처리할 수 있다.

Action의 결과(jsp)중 특정 결과 jsp만 다른 decorator를 줄 수 있다?? - 1번째 얘기

결론부터 말하면, 불행히도 이 방법을 시도했지만, 환경설정 파일만 수정해서는 할 수 없다.

다음의 예를 들어본다. 밑의 예에서 google Action의 결과중 유일하게 적용안되는 것이 있다. 바로 save.jsp 이다. 강조하지만, Sitemesh는 Request URL을 기준으로 되어 있어 dispatch할 경우 여전히 google.gl으로 남기 때문에 save.jsp에 대해서는 bean decorator가 적용되지 않는다.
하지만, redirection이 된 edit.jsp는 패턴이 제외된 채로 적용된다. 그러나 URL이 바뀌는 불상사는 감수해야 한다.

xwork.xml
<action name="google" class="com.google.publ.test.action.GoogleAction">
    <result name="register">/googleRegister.jsp</result>
    <result name="edit" type="redirect">/edit.jsp</result>
    <result name="save">/save.jsp</result>
</action>
decoratos.xml
<excludes>
    <pattern>/edit.jsp</pattern>
</excludes>

<decorator name="default" page="default.jsp">
    <pattern>/google.gl</pattern>
</decorator>

<decorator name="bean" page="beanLayout.jsp">
    <pattern>/save.jsp</pattern>
</decorator>

Action의 결과(jsp)중 특정 결과 jsp만 다른 decorator를 줄 수 있다?? - 2번째 얘기

제목을 보고 짐작했겠지만, 하나의 Action에서 나온 결과에 대해서 다른 decorator를 쓸 수 있는 방법은 존재한다. 바로 내용이 들어가는 jsp안에 특정 decorator를 설정하는 것이다.

밑의 예를 보자. 바로 google Action이 success인 경우 google.jsp로 dispatch되는데, google.jsp안에 있는 메타 태그에 지정된 content의 decoration 타입에 맞춰 브라우져에 나타나게 된다.

google.jsp
<META name="decorator" content="tv">
....
decorators.jsp
<decorator name="default" page="default.jsp">
   <pattern>/google.gl</pattern>
</decorator>

<decorator name="tv" page="tv.jsp">
</decorator>
xwork.xml
<action name="google" class="com.google.publ.test.action.GoogleAction">
    <result name="success">/google.jsp</result>
    <result name="register">/googleRegister.jsp</result>
</action>

이렇게 사용할 수 이유는 바로 sitemesh.xml 파일의 설정과 관련이 있다. sitemesh.xml 에서 ConfigDecoratorMapper보다 PageDecoratorMapper를 먼저 설정하기 때문이다.

sitemesh.xml
...
<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.ConfigDecoratorMapper">
	<param name="config" value="/WEB-INF/decorators.xml" />
</mapper>
..

decorator가 적용되는 순서

decorators.xml에 decorator 태그가 지정된 순서대로 decorator가 적용된다.

예를 들어보자. google.gl이라는 action이 호출될 때, 정확하게 URL과 동일한 이름을 패턴으로 갖는 tv decorator가 적용된다.

decorators.xml
<decorators defaultdir="/WEB-INF/decorators">

    <decorator name="defaultHeader" page="defaultHeader.jsp"/>
    <decorator name="defaultFooter" page="defaultFooter.jsp"/>
    <decorator name="leftMenu" page="leftMenuLayout.jsp"/>

    <decorator name="tv" page="tv.jsp">
	    <pattern>/google.gl</pattern>
    </decorator>

    <decorator name="default" page="default.jsp">
	    <pattern>/*.gl</pattern>
    </decorator>

    <decorator name="null">
    </decorator>

</decorators>

pattern이 적용되는 순서

패턴이 적용되는 순서가 다르다. Request URI를 보고 패턴이 지정된 것중에서 다음의 순서대로 해당 decorator page를 찾게된다.

  1. 정확하게 단어가 맞는 패턴 (Exact word)
  2. 'abc*'나 'abc?'와 같은 컴플렉스 패턴 (Complext)
  3. '/', '*', '/*'와 같은 디폴트 패턴 (Default)

tiles의 getAsString(또는 tiles에서 put을 이용하여 atrribute을 지정) 을 어떻게 변경시키냐?

webwork를 보면, <action> 태그 밑에 <param> 태그를 사용할 수 있다. static parameter interceptor를 이용하여 action에 필드를 넘길 수 있다. 이 때, action은 setter 메소드와 클래스 필드만을 적으면 된다.
자세한 내용은 webwork를 참조하라.

action을 기반하는 jsp중, jsp파일들이 서로 다른 Layout 템플릿을 쓰는 경우

어쩔 때는 rightmenu를 쓰고, 어쩔 때는 rightmenu를 안 쓰는 경우.

  • redirect 하기.
  • 해당 jsp파일에서 meta 태그를 이용하여 특정 decorator를 사용하게 함.
Posted by '김용환'
,