SiteMesh是一个轻量级的web应用框架,实现了Decorator模式。它的目标是将多个页面都将引用的jsp页面通过配置加载到相应的jsp文件中。
在我们的项目中,每个jsp都需要添加两个top和bottom的jsp来完成某些功能。最笨的方法当然就是在每个页面上hard code这些功能的相关代码,但是这样的做法实在是不满足DRY的原则。clean code需要我们最大程度的复用我们的代码,减少代码冗余。
SiteMesh提供了这样的解决方案:使用decorator模式来动态的给每个jsp页面添加额外的职责。使用了Decorator模式后每个页面就可以专注于解决本页面要解决的问题,而不需要关心那些全局上需要每个页面完成的功能模块了。
SiteMesh的工作原理十分简单:使用一个filter对每个发送到服务器的请求进行过滤;对照配置文件确认该请求的目标jsp是否满足decorator的条件(是否需要被decorate);对需要decorate的页面,使用配置文件中指定的装饰规则把指定的文件(如header,footer等)与目标页面组合起来,把结果返回给客户端。
详细的做法是:
1.引入SiteMesh的引用
<dependency> <groupId>opensymphony</groupId> <artifactId>sitemesh</artifactId> <version>2.4.2</version> </dependency>
2.在web.xml文件中配置filter
<filter> <filter-name>sitemesh</filer-name> <filter-class>com.opensymphony.sitemesh.webspp.SiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>*.jsp</url-pattern> <dispatcher>FORWARD</dispatcher> </filter-mapping>
这样的配置代表我希望对所有的jsp都进行decorate
3.编写decorators.xml
<decorators defaultdir="/path/to/decorators/file"> <excludes> <pattern>/exclude/specific/kind/of/files/in/this/folder</pattern> </excludes> <decorator name="myDecorator" page="FileNameOfTheDecorateRule"> <pattern>*.jsp</pattern> </decorator> </decorators>
excludes节点定义了哪些在decorator目录下,但是我又不想其被装饰的文件。
4.编写定义decorate rules的jsp模板
这里的decorate rules就是在decorators.xml文件中定义的“myDecorator”,其中详细定义了对目标文件的装饰规则。包括:用什么文件对目标文件进行装饰,在目标文件的哪个位置进行装饰等等。它一般是一个jsp文件,或者说是一个模板。在这个模板中写入需要decorate的详细内容,格式规范与普通jsp相同,但是有两个重要的标签:
<decorator:head/> <decorator:body/>
当对目标页面进行装饰的时候,遇到<decorator:head/>就插入目标文件的<head>部分,遇到<decorator:body/>就插入目标文件的<body>部分。
这样,根据目标文件的不同,就动态的生成了具有相同附加职责的不同的页面。