SiteMesh教程及官方文档翻译


SiteMesh SiteMesh SiteMesh SiteMesh 教程及SiteMesh SiteMesh SiteMesh SiteMesh 官方文档翻译 目录 SiteMesh 教程...................................................................................................................1 使用SiteMesh 简化网页布局..........................................................................................9 Sitemesh 对于性能的影响实验报告............................................................................. 15 1. 目的............................................................................................................................15 2. 环境............................................................................................................................16 3. 过程............................................................................................................................16 4. 结果............................................................................................................................16 5. 结论............................................................................................................................19 SiteMesh 官方文档翻译(含Freemarker 但不包括 velocity 部分)............................... 19 Advanced SiteMesh 官方文档中文版...........................................................................29 Spring MVC 整合sitemesh, freemarker 支持完全 REST 方式.....................................40 SiteMesh 教程 2009-05-20 14:01:32 标签: 简介: sitemesh 应用 Decorator 模式,用 filter 截取 request 和response,把页面组件 head,content,banner 结合为一个完整的视图。通常我们都是用 include 标签在每个 jsp 页面中 来不断的包含各种 header, stylesheet, scripts and footer,现在,在 sitemesh 的帮助下, 我们可以开心的删掉他们了。如下图,你想轻松的达到复合视图模式,那末看完本文吧。 一、在 WEB-INF/web.xml 中copy 以下filter 的定义: sitemesh com.opensymphony.module.sitemesh.filter.PageFilter sitemesh /* 二、copy 所需sitemesh-2.3.jar 到WEB-INF\lib 下。(这里可以下载 http://www.opensymphony.com/sitemesh/) 三、 建立WEB-INF/decorators.xml 描述各装饰器页面。 * 上面配置文件指定了装饰器页面所在的路径,并指定了一个名为 main 的装饰器,该装饰器默 认装饰 web 应用根路径下的所有页面。 四、 建立装饰器页面 /decorators/main.jsp • <%@ page contentType="text/html; charset=GBK"%> <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> <decorator:title default="装饰器页面..."/> sitemesh 的例子

chen56@msn.com 五、建立一个的被装饰页面 /index.jsp(内容页面) • <%@pagecontentType="text/html;charset=GBK"%> AgentTest

本页只有一句,就是本句.

最后访问 index.jsp,将生成如下页面: 而且,所有的页面也会如同 index.jsp 一样,被sitemesh 的filter 使用装饰模式修改成如 上图般模样,却不用再使用 include 标签。 装饰器 decorator 概念 为了建立可复用的 web 应用程序,一个通用的方法是建立一个分层系统,如同下面一个普通 的web 应用: •••• 前端:JSP和Servlets,或jakarta 的velocity 。。。 •••• 控制层框架 Controller :(Struts/Webwork) •••• 业务逻辑 Business :主要业务逻辑 •••• 持久化框架 :hibernate/jdo 可糟糕的是前端的页面逻辑很难被复用,当你在每一个页面中用数之不尽的 include 来复用 公共的 header, stylesheet, scripts,footer 时,一个问题出现了-重复的代码,每个页面必 须用 copy 来复用页面结构,而当你需要创意性的改变页面结构时,灾难就爱上了你。 sitemesh 通过 filter 截取 request 和response,并给原始的页面加入一定的装饰(可能为 header,footer...),然后把结果返回给客户端,并且被装饰的原始页面并不知道 sitemesh 的装 饰,这也就达到了脱耦的目的。 据说即将新出台的 Portlet 规范会帮助我们标准的实现比这些更多更 cool 的想法,但可怜 的我还不懂它到底是一个什末东东,有兴趣的人可以研究 jetspeed,或 JSR(Java Specification Request) 168,但我想 sitemesh 如此简单,我们不妨 先用着。 让我们看看怎样配置环境 除了要 copy 到WEB-INF/lib 中的 sitemesh.jar 外,还有 2个文件要建立到 WEB-INF/: •••• sitemesh.xml (可选) •••• decorators.xml sitemesh.xml 可以设置 2种信息: Page Parsers :负责读取 stream 的数据到一个 Page 对象中以被 SiteMesh 解析和操作。(不太 常用,默认即可) Decorator Mappers : 不同的装饰器种类,我发现 2种比较有用都列在下面。一种通用的 mapper, 可以指定装饰器的配置文件名,另一种可打印的装饰器,可以允许你当用 http://localhost/aaa/a.html?printable=true 方式访问时给出原始页面以供打印(免得把 header,footer 等的花哨的图片也搭上) (但一般不用建立它,默认设置足够了: com/opensymphony/module/sitemesh/factory/sitemesh-default.xml): 范例: decorators.xml :定义构成复合视图的所有页面构件的描述(主要结构页面, header,footer...),如下例: * •••• defaultdir: 包含装饰器页面的目录 •••• page : 页面文件名 •••• name : 别名 •••• role : 角色,用于安全 •••• webapp : 可以另外指定此文件存放目录 •••• Patterns : 匹配的路径,可以用*,那些被访问的页面需要被装饰。 最重要的是写出装饰器本身(也就是那些要复用页面,和结构页面)。 其实,重要的工作就是制作装饰器页面本身(也就是包含结构和规则的页面),然后把他们描 述到 decorators.xml 中。 让我们来先看一看最简单的用法:其实最常用也最简单的用法就是我们的 hello 例子,面对 如此众多的技术,我想只要达到功能点到为止即可,没必要去研究太深(除非您有更深的需求)。 <%@pagecontentType="text/html;charset=GBK"%> <%@taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> <decorator:titledefault="装饰器页面..." /> sitemesh的例子

chen56@msn.com 我们在装饰器页面只用了 2个标签: : 把请求的原始页面的 title 内容插 入到中间。 : 把请求的原始页面的 body 内的全部内容插入到相应位置。 然后我们在 decorator.xml 中加入以下描述即可: * 这样,请求的所有页面都会被重新处理,并按照 main.jsp 的格式重新展现在你面前。 让我们看看更多的用法。(抄袭sitemesh 文档) 以下列着全部标签: Decorator Tags Page Tags 被用于建立装饰器页面. 被用于从原始内容页面访问装饰器. 插入原始页面(被包装页面)的head 标签中的内容(不包括 head 标签本身)。 插入原始页面(被包装页面)的body 标签中的内容。 插入原始页面(被包装页面)的title 标签中的内容,还可以添加一个缺省值。 例: /decorator/main.jsp 中 (装饰器页面): <decorator:title default="却省 title-hello" /> - 附加标题 /aaa.jsp 中 (原始页面):aaa 页面 访问/aaa.jsp 的结果:aaa 页面 - 附加标题 在标签处插入原始页面(被包装页面)的原有的标签的属性中的内容,还可以添加一个缺省值。 sitemesh 文档中的例子很好理解: The decorator: > The undecorated page: The decorated page: 注意,writeEntireProperty="true"会在插入内容前加入一个空格。 象jsp 页面中的标签一样,可以使用被包装为一个 Page 对象的页面。 (懒的用) 例:可用 :<%=page.getTitle()%>达到 的访问结果。 ... ... 应用包装器到指定的页面上,一般用于被包装页面中主动应用包装器。这个标签有点不好理解 , 我们来看一个例子: 包装器页面 /decorators/panel.jsp:

...

并且在 decorators.xml 中有 一个公共页面,即将被 panel 包装:/public/date.jsp: ... <%=new java.util.Date()%> ... 被包装页面 /page.jsp : page 的应用 ..... chen_p@neusoft.com 最后会是什末结果呢?除了/page.jsp 会被默认的包装页面包装上 header,footer 外,page.jsp 页面中还内嵌了 date.jsp 页面,并且此 date.jsp 页面还会被 panel.jsp 包装为一个 title 加 body 的有 2段的页面,第 1段是 date.jsp 的title,第 2段是 date.jsp 的body 内容。 另外,page:applyDecorator 中包含的 page:param 标签所声明的属性值还可以在包装页面中用 decorator:getProperty 标签访问到。 可打印的界面装饰 前面说过有 1种可打印的装饰器,可以允许你当用 http://localhost/aaa/a.html?printable=true 方式访问时,应用其他的装饰器(自己指定), 给出原始页面以供打印(免得把 header,footer 等的花哨的图片也搭上)。 让我们来看一看怎样实现他: 1.首先在 WEB-INFO/sitemesh.xml 中设置: 这样就可以通过?printable=true 来使用名为 printable 的装饰器,而不是用原来的装饰器。 2.在WEB-INFO/decorators.xml 中定义相应的 printable 装饰器 3.最后编写 printable 装饰器/decorators/printable.jsp <%@ taglib uri="sitemesh-decorator" prefix="decorator" %> <decorator:title />

(printable version)

这样就可以让一个原始页面通过?printable=true 开关来切换不同的装饰器页面。 中文问题 由于 sitemesh 内部所使用的缺省字符集为 iso-8859-1,直接使用会产生乱码,我们可以通过以 下方法纠正之: •••• 方法1:可以在您所用的 application server 的配置文件中找一找,有没有设置 encoding 或charset 的项目,然后设成 gbk 或gb2312 即可 •••• 方法2:这也是我们一直使用的方法。 1.在每一个 jsp 页里设置: <%@ page contentType="text/html; charset=gbk"%> 来 告诉server 你所要求的字符集。 2.在每个 jsp 页的head 中定义: 来告诉浏览器你所用的字符集。 总结:使用 sitemesh 最通常的途径: 1.配置好环境, 2.在WEB-INFO/decroators.xml 中描述你将建立的包装器。 3.开发在 decroators.xml 中描述的包装器,最好存放在/_decorators 目录下 4.ok ,可以看看辛勤的成果了 :) 使用 SiteMesh 简化网页布局 在公司项目使用了 Appfuse ,其带有 SiteMesh 对于网页布局简化让我感觉很好用,本 文旨在对对 Sitemesh 的基本原理和在项目中使用 Sitemesh 的实现流程、使用技巧的介绍。 1. 基本原理 SiteMesh 是以 Servlet 2.3 API 为基础(没记错的话 tomcat 支持最新版本 servlet2.5)。 它包含一个引擎,用来解析输出的网页或者网页片段,决定是否需要应用装饰器以及合并合适 的装饰器。 SiteMesh 与应用内容无关,适用的内容格式包括 : 1 Html 2 JSP 3 Servlet 4 XSL 5 甚至 CGI 2. 实现流程 1) 当为 Servlet 容器指定一个 Http 请求时, SiteMesh 截取请求,使用一个 Servlet Filter ,然后捕捉 Html 结果。 2) 然后这个 Html 被解析,并且任何相关的内容都被提取到一个 Page 对象中。 3) 询问 DecoratorMapper 来确定那一个装饰器需要被应用。 4) Servlet 向包含装饰器的 JSP 发送请求。 5 )装饰器生成带有从 page 对象中获得的内容的 Html 布局。 大致流程如下图: Sitemesh 这样的好处是: 1 所有具体业务页面的开发者无需考虑该页面将处在最终输出页面的那个位置。 2 无需 include 一大堆页面, 3 以后如果系统整体改版,那么只需要改写装饰器页面及重新配置装饰规则即可完成 4 方便快捷,可维护性极好。 3. 在项目中使用 Sitemesh 1. 将 sitemesh_[version].jar 包加到 WEB-INF\lib 下 2. 在 web.xml 中增加 1 < filter > 2 < filter - name > sitemesh 3 < filter - class > com.opensymphony.module.sitemesh.filter.PageFilte r 4 5 6 7 < filter - mapping > 8 < filter - name > sitemesh 9 < url - pattern > /* 10 表示对系统中所有 url 请求均使用 sitemesh Filter 进行拦截。 3. 在 WEB-INF 下配置 sitemesh.xml 和 decorator.xml 配置文件。 Sitemesh.xml 1 < sitemesh > 2 < property name = " decorators-file " value = "/WEB-INF/decorato rs.xml "/> 3 < excludes file = " ${decorators-file} "/> 4 5 < page - parsers > 6 < parser default = " true " class ="com.opensymphony.module.site mesh.parser.HTMLPageParser" /> 7 9 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 在 sitemesh.xml 中配置了两个 DecoratorMapperDecoratorMapperDecoratorMapperDecoratorMapper : 1 PrintableDecoratorMapper 2 ConfigDecoratorMapper PrintableDecoratorMapperPrintableDecoratorMapperPrintableDecoratorMapperPrintableDecoratorMapper 是供打印专用,在 url 后加上 printable=true 即会使 用 decorator.xml 中指定的 printable 装饰器来对页面进行装饰,一般来说打印页面是只需 要打印本页面的内容,其余的如头、脚、导航栏、左右菜单等是不需要打印的,通过装饰器可以 轻松实现打印页面的过滤。 Decorator.xml 1 < decorators defaultdir = "/decorators " > 2 < excludes > 3 < pattern >/ demos /* 4 /resources/* 5 /test* 6 /FCKeditor/* 7 8 9 10 11 12 13 *login* 14 15 16 17 /* 18 19 20 4. 创建一个装饰器 JSP 页面,我建议所有装饰器页面放到 decorators 目录,并且以 dec[ 功能 ].jsp 作为命名方式,如 1 decPrintable.jsp 2 decDefault.jsp 下面是一个装饰器的代码: 1 3 4 <%-- Include common set of tag library declarations for each layout --%> 5 <% @ include file = "/common/taglibs.jsp "%> 6 7 < html xmlns = " http://www.w3.org/1999/xhtml " xml:lang = " en " > 8 < head > 9 < decorator:head /> 10 11 < body 12 < decorator:getProperty property = " body.id " writeEntirePropert y = " true "/> 13 < decorator:getProperty property = " body.onload " writeEntireProp erty = " true "/> 14 < decorator:getProperty property = " body.onunload " writeEntirePr operty = " true "/> 15 > 16 <% @ include file = "/common/header.jsp "%> 17 < h1 >< decorator:getProperty property = " page.heading "/> 18 <% @ include file = "/common/messages.jsp "%> 19 < decorator:body /> 20 < jsp:include page = "/common/footer.jsp "/> 21 22 注意其 标签,如 : ,这些标签将被装饰的 pagepagepagepage 页面的相应内容作为属性传入。 Page 页面的相关内容将放在 decorator 标签所指定的位置。 1 Title :标题 2 Head :头部,一般是公共的 js 、 css 及 meta 3 Body :被装饰的 page 的主体内容 5 、 Sitemesh 通过 : 1 在 sitemesh.xml 中配置 DecoratorMapper 配置映射器 2 在 decorator.xml 中配置装饰器文件及其匹配方式 当有页面需要输出到客户端时,将根据这些配置选择相应的装饰器来进行装饰,将装饰结果 返回给客户界面。 4. 参考资料 关于 Sitemesh 的 api 及详细使用说明可以参看其官方网站 Sitemesh 对于性能的影响实验报告 时间:2009-07-15 11:11 来源:未知 作者:YODA CSDNIEQQ 百度 我挖 Google POCO Yahoo 新浪 365Key 天极 和讯 博拉 Live 奇客 鲜果 收客 饭否 叽歪 挖客 核心提示:1. 目的 Sitemesh 是一个很好的页面渲染框架,基本上我现在所在项目都是适用 sitemesh 做页面框架和 整合渲染的,给页面部分的工作带来了很大的便利性。 在sitemesh 的文档中,对于 sitemesh 的工作原理给出了一个 图示,根据这个图可以看出,sitemesh 是通过组合适 1. 目的 Sitemesh 是一个很好的页面渲染框架,基本上我现在所在项目都是适用 sitemesh 做页面框架和整合渲染的,给页面 部分的工作带来了很大的便利性。 在sitemesh 的文档中,对于 sitemesh 的工作原理给出了一个图示,根据这个图可以看出,sitemesh 是通过组合适用 filter 和标签将被渲染页面的内容抽取出来,再整合到一个统一的框架页面中去。曾经有一段时间测试环境 的 Websphere 服务器频繁出现内存溢出的问题,在跟踪内存溢出问题时,发现 sitemesh 组件使用 StringBuffer 对象进行 大量内存申请的动作。这就需要检测 sitemesh 具体是如何来分析页面的,我的猜测就是将被渲染的页面中的最终 HTML 代码展出到一个大的字符串,然后根据关键标签来进行分析和内容抽取,然后再整合到框架页面中。先不管 sitemesh 是用什么方式来分析、抽取和整合的,他对于内存的影响是比较明显的,所以,本实验的目的就是比较使用 sitemesh 和不使用 sitemesh 时,运行期性能是否存在差异。 2. 环境 本实验使用到的环境如下: ·OS: Windows XP Professional SP2 ·HW: Intel Core 2 Duo T7300 2.0GHz, 2GB RAM · Web Server: Resin 3.2.1 · Sitemesh: 2.3 · Test Tool: Load Runner 8.0 ·JDK: Java HotSpot(TM) Client VM 1.5.0_09-b03 · Analysis Tool: IBM Pattern Modeling and Analysis Tool for Java Garbage Collector 2.5 3. 过程 1. 使用 ant example 创建 sitemesh 自带的 example web 应用 2. 在sitemesh example 应用中加入一个 JSP 页面data.jsp,该页面中包含一个 43 行7列的静态表格,表格部分的 HTML 源码约 17KB 3. 同样制作上述数据的非 sitemesh 处理页面 data_nosm.jsp,在 sitemesh 的配置文件 decorators.xml 中将 data_nosm.jsp 添加到排除列表 4. 以展开包的方式部署 sitemesh example 应用到 resin 服务器 5. 设置resin 的JVM 参数为:-Xms64m -Xmx256m -XX:MaxPermSize=256m -Xss1m -verbose:gc -Xloggc:C:/apps/resin-3.2.1/gc.log -XX:+PrintGCDetails 6. 在Load Runner 中制作 2个压力测试脚本,一个用来请求 data.jsp,一个用来请求 data_nosm.jsp 7. 在Load Runner 中设计压力测试场景:10 个用户,持续请求 5分钟,每个用户的每轮请求中包含 10 次对于页面的 请求 8. 重新启动 resin 服务器,进行 data.jsp 的压力测试。测试完成之后,收集 Load Runner 的数据以及 GC 的数据 9. 重新启动 resin 服务器,进行 data_nosm.jsp 的压力测试。测试完成之后,收集 Load Runner 的数据以及 GC 的数据 10. 数据汇总及处理 4. 结果 根据测试的结果,整理 GC 部分和压力测试部分的数据如下: 使用 sitemesh 未使用 sitemesh GC 次数 6,746 74 Full GC 次数 1 1 GC 消耗 0.02 0.00 GC 暂停(秒) 7.00 0.00 最大持久代(字节) 8,388,608.00 8,388,608.00 平均持久代(字节) 6,036,328.00 6,205,085.00 最大旧生代(字节) 61,983,744.00 59,024,384.00 平均旧生代(字节) 42,583,685.00 31,929,903.00 最大新生代(字节) 61,983,744.00 59,024,384.00 平均新生代(字节) 4,426,710.00 4,610,566.00 请求次数 137,344.00 198,188.00 平均每秒请求 454.78 658.43 页面平均响应时间(秒) 0.042 0.029 上表的数据制作成图表如下(为了便于图表显示,部分数据进行了放大): 在上表中,GC 消耗和 GC 暂停考量指标中,未使用 sitemesh 的情况下显示为 0,是因为所用的分析工具 IBM Pattern Modeling and Analysis Tool for Java Garbage Collector 2.5 的显示精度不足导致,实际的并非是真正的 0,而应该是一个 很小的数值。 从数据上看,使用 sitemesh 和不使用 sitemesh 对于虚拟机堆内存的使用差异不太大,但是在 GC 次数上的差异很大。 从GC 日志的详细信息可以看出,在使用 sitemesh 时,发生次要 GC(Minor GC)的频率非常的高,可以推断在运行 时期产生了大量的短生命周期的对象,然后又迅速的被释放,GC 在新生代就已经完成了。主要GC(Major GC, Full GC) 在使用 sitemesh 和不使用的情况下,均发生了 1次,而且这 1次主要 GC 也是在 resin 启动中发生的,不是应用在进 行压力测试时发生的。由于使用 sitemesh 时的GC 次数远远大于不使用 sitemesh,所以在整个测试过程中,GC 上消 耗的时间也是差异非常大的。 从压力测试的探测可以看出,不使用 sitemesh 时完成的请求数是使用 sitemesh 时的144.3%。同时页面响应时间也仅 为使用 sitemesh 时的 69.0%。 sitemesh 的问题及解决 资料引用:http://www.devdao.com/Article/349850.htm 再说 sitemesh 的问题,同样是做 openfans 网摘功能出现的。做好了 IE 插件,有 fans 反馈说弹出页面太大,这也 难怪,用了 sitemesh , head 和 footer 都在页面上,想缩小页面,肯定得把 head 和 footer 都去掉,做个干净点 的。既然用了 sitemesh 肯定是希望最方便的搞定这个,而不用动任何逻辑(包括页面逻辑)。这个好办,文档里有 说,通过在 sitemesh.XML 中增加 Word-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM:#cccccc 1px solid; BACKGROUND-COLOR:#eeeeee"> < 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 "/> 就能搞定,这样只需要使用参数如 saveSnippet.Html?decorator=simple&confirm=true ,就能让它使用指定的 decorator 。然后做一个去掉 head 和 footer 只保留必要的 js 和 CSS 引用的 simple.jsp 页面,同时在 decorator.xml 中配 < decorator name = " simple " page = " simple.jsp " > 就应该可以搞定。 但怎么测,就是不使用这个 simple decorator 。没办法,只好跟进 sitemesh 源码中去调试,进入 ParameterDecoratorMapper 类,它继承了 AbstractDecoratorMapper 类,然后有一个 init 方法一个 getDecorator 方 法。各打一个断点, init 方法在 tomcat 启动就会执行,也正常初始化了, getDecorator 方法却始终不调用,一时 想不出办法。看到篇文章说不自己写 sitemesh.xml 而使用自带的 com/opensymphony/module/sitemesh/factory/sitemesh-default.xml 也可以,于是备份并删除我写的 sitemesh.xml ,居 然成功了。为什么我写的就不行呢?差别一是我的简化了很多,只有 < mapper class ="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper" > < param name ="config" value ="${decorators-file}" /> 和刚加的 ParameterDecoratorMapper ,二就是顺序,我的 ParameterDecoratorMapper 放在了 ConfigDecoratorMapper 后面, 会不会是顺序原因呢,调换一下,果然成功了。问题是解决了,原理呢?再花点时间跟一下代码了解下原理,原来使 用了 Factory ,它会调用各个配置的 Mapper 的 init 方法,并放入 map 中,然后到时选择一个 Mapper ,如果符 合条件就使用,否则继续往下找。这里就有了顺序的问题,因为我在 decorator.xml 中使用了 /*.html ,这样如果 ConfigDecoratorMapper 放在前面,他就先找这个 Mapper , 一 看 saveSnippet.html?decorator=simple&confirm=true ,符合 pattern 啊,就使用它了,另一个 ParameterDecoratorMapper 根本得不到机会,所以也进不了它的 getDecorator 方法。换了顺序就是它先进去,所以执行,其它的 url 也是先找 它,但不匹配,就又交给 ConfigDecoratorMapper 了。呵呵,问题也解决了,对 sitemesh 的认识又进了一步。进入 讨论组讨论。 资料引用:http://www.devdao.com/Article/349850.htm 5. 结论 从上述测试数据来分析,使用sitemesh 对于系统性能是有较大的影响的,主要表现在 GC 的次数会显著增多。建议在 大压力、页面内容大的系统中,慎重选择 sitemesh,并且使用之前对其带来的性能影响进行一个较为合理、全面的评 估。 SiteMesh 官方文档翻译(含Freemarker 但不包括 velocity 部分) 安装配置 1. 创建普通的 web 项目或直接使用 sitemesh-blank.war 2. 将sitemesh-2.4.1.jar 拷贝到[web-app]/WEB-INF/lib 下 3. 创建sitemesh 的配置文件:[web-app]/WEB-INF/decorators.xml, 顶级标签为: 4. (可选的): 创建文件[web-app]/WEB-INF/sitemesh.xml, 包含以下内容: 5. 在[web-app]/WEB-INF/web.xml 中的标签内增加下面内容将 sitemesh 加入到应 用中 sitemesh com.opensymphony.sitemesh.webapp.SiteMeshFilter sitemesh /* 字符集 1. 默认编码: iso8859-1 2. 设置服务器解析后台页面的编码: <%@ page contentType=”text/html; charset=utf-8”%> 3. 告知浏览器解析界面的编码: 4. 设置sitemesh 的装饰器解析时使用的编码 …… 构造装饰器 1. 兼容的一些装饰漆: 1.1. meta tags(关键字, 描述, 作者) 1.2. stylesheet(CSS 样式表) 1.3. header(头部) 1.4. navigation(导航) 1.5. footer(底部) 1.6. copyright notice(版权声明) 2. 首先, 需要定义各种导航/布局, 比如: 是否需要一个默认的装饰器(一个对所有页面适用 的标准装饰器)? 是否在首页有特定的布局? 文档中是否需要头部? 网站是否需要打印版? 3. 下面是一个 web 应用程序的示例结构, sitemesh 不是必须的. /decorators: 包含所有的装饰器文件的目录 /includes: 将要被其他文件包含的所有文件 /images: 包含所有的图片 /styles: 包含所有的样式表 /scripts: 包含所有的脚本文件 4. 良好的习惯: 4.1. 将整个应用都使用的样式表都放入同一个页面定义, 并按照下面方式引入: <% String userAgent = request.getHeader("User-Agent"); if (userAgent != null && userAgent.indexOf("MSIE") == -1) { out.print(""); } else { out.print(""); } %> 4.2. 在你的装饰器中使用 includes(比如: includes/navigation.jsp) 4.3. 不要尝试使用绝对路径(/), 用<%=request.getContextPate() %>去代替, 这会使得应用在 发生变迁的时候变得非常容易. 4.4. 使你的装饰器兼容多浏览器(比如IE, Mozilla, Opera…)将会大大提高整个应用的兼容性 4.5. 使用frame (框架)的时候要特别小心, 因为装饰器可能不支持 frame 5. 第一个装饰器: 最基本的, 你仅仅需要知道可以使用的一些装饰器标签, title, head, body 这三个标签可能是经常使用的. 1: <%-- 2: % 这个主装饰器应用于所有的页面. 3: %它包含标准的缓存, 样式表, 头部, 底部和版权声明. 4: --%> 5: <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> 6: <%@ include file="/includes/cache.jsp" %> 7: 8: 9: 10: <decorator:title default="INTRANET" /> 11: 12: <%@ include file="/includes/style.jsp" %> 13: 14: 15: 16: <%@ include file="/includes/header.jsp"%> 17: 18: 19: 20: 21: 22: 23: 26: 27: 32: 33: 34:
23: 24: <%@ include file="/includes/navigation.jsp" %> 25: 28:
29: 30:
31:
35:
36: <%@ include file="/includes/footer.jsp" %> 37: <%@ include file="/includes/copyright.jsp" %> 38: 39: 40: 第1-4 行: 对装饰器的解释, 这种方式不同于一般的马上进行装饰器的工作. 第5行: 引入标签库, 这对所有要使用内部装饰器的页面都是必须的 第6行: 设置通知浏览器缓存页面的响应头, 如果你的应用是经常变动的, 省略这里 第10 行: 如果请求页面没有 title, 默认title 将使用”INTRANET” 第15 行: 页面在加载的时候状态条的消息 第30 行: 整个请求页面的 body 放入docBody. 将导航和 body 进行了划分. 6. 现在用你喜欢的编辑器打开 WEB-INF/decorators.xml 让sitemesh 知道你有了一个装饰器 (通过映射): /* 7. 现在部署你的 web 应用, 访问欢迎界面, main 装饰器就会被应用上. freemarker 支持 1. sitemesh2.0.2 之后开始支持 freemarker <#include "/includes/decorators/header.dec">

${title}

${head}
${title}
${body} <#include "/includes/decorators/footer.dec">2. 安装freemarker 支持 2.1. 拷贝freemarker.jar 到[web-app]/WEB-INF/lib 下 2.2. 在web.xml 中增加下面内容: sitemesh-freemarker com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet TemplatePath / default_encoding ISO-8859-1 1 sitemesh-freemarker *.dec 2.3. 修改decorators.xml 中要使用 freemarker 的decorator 的page 指向一个后缀为 dec 的文 件. 3. FreemarkerDecoratorServlet 向contex 对象中放入了一些东西可以在模板中使用 3.1. 基础属性: 3.1.1. 所有的 request, request 参数, session, servlet context 属性变量${Session[“user”]} 3.1.2. 创建变量: <#assign ww=JspTaglibs[“/WEB-INF/webwork.tld”]> 使用创建的变量去加 载jsp taglibs: <@ww.property value=”myVar”/> 3.2. sitemesh 的context 属性: 3.2.1. base: request.getContextPath() 3.2.2. title: 解析页面标题 3.2.3. head: 解析页面头部 3.2.4. body: 解析页面体 3.2.5. page: 内部页面对象 装饰器映射 1. 当一个页面被解析的时候, 它会被映射成为一个装饰器, 这个映射就扮演了链接 DecoratorMappers 的角色. 2. 对于每一个请求, 整个过程的第一个 mapper 要求知道使用哪个装饰器, 如果知道使用哪 个装饰器, 传递一个页面对象和 HttpServletRequest, 返回一个装饰器对象, 否则返回 null. 如果返回了 null, 下一个 mapper 继续查询, 重复这个过程直到没有 mapper 或返回了一个合 法的装饰器, 如果没有 mapper 返回装饰器, 页面将不会被装饰以原始的状态返回. 3. 这种mapper 的链式协同使用了责任链设计模式. 4. mapper: 4.1. 通过请求页面路径确定装饰器 4.2. 基于时间, 地域, 浏览器使用不同的装饰器 4.3. 为搜索引擎机器人使用简单的装饰器 4.4. 基于URL 参数, 请求属性或 meta 标签切换装饰器 4.5. 使用用户自定义装饰器基于用户配置. 5. DecoratorMapper 的主实现是从/WEB-INF/decorators.xml 读取装饰器映射的 ConfigDecoratorMapper, 它根据配置的 url pattern 使用合适的装饰器 6. DecoratorMappers 书写很简单, 在发布包中包含了一些示例说明它的写法以及灵活性, 它 们是: 6.1. AgentDecoratorMapper: 6.2. ConfigDecoratorMapper 6.3. CookieDecoratorMapper: 基于cookie 值映射 6.4. EnvEntryDecoratorMapper: 6.5. FileDecoratorMapper: 6.6. FrameSetDecoratorMapper: 6.7. InlineDecoratorMapper 6.8. LanguageDecoratorMapper 6.9. PageDecoratorMapper 6.10. ParameterDecoratorMapper 6.11. SessionDecoratorMapper 6.12. PrintableDecoratorMapper 6.13. RobotDecoratorMapper 标签 1. sitemesh 有两个标签库 2. 装饰器标签: 这类标签用于创建页面装饰器, 一个装饰器通常是通过标签插入一些占位 符然后用原始页面中的数据填充以构建一个 HTML 布局(或者其他合适的原始页面类型). 2.1. : 没有属性. 向页面中插入原始页面标签内部的内容, 但不会 包含标签自身. 2.2. : 没有属性. 插入原始页面中的内容, 但不包括标签自身. 2.2.1. 注意: body 内容的 onload 和onunload 事件(和其他的 body 属性)可以通过获取属性的 的标签得到并包含在装饰器中. 2.2.2. 例如: ”/> 2.3. : 插入原始页面的中的内容, 但不包括标签自身, 如果原始页面没有 title 标签, 那么使用 default 指定的字符串. 2.4. <decorator:getProperty property=””[default=””][writeEntireProperty=””]/>: 插入原始 页面中某个属性的值. 2.4.1. property: 指定要获取的属性名称. 下面对常见的用法解释中所有的标签是指原始页 面 2.4.1.1. <html />标签的属性: 直接使用名称获取. 比如: <html template=”funky”/> 则有 template=funky 2.4.1.2. 某个标签内部的内容: 用标签名获取 title=My Funky Page 2.4.1.3. 普通标签的属性: 标签名.属性名获取 body.bgcolor=green 2.4.1.4. meta 标签的值: meta.名称, 比如: <meta name=”author” content=”Bob”/> 就可 以使用 meta.author 获取到 Bob 2.4.2. default: 如果没有找到指定的属性值的默认值 2.4.3. writeEntireProperty: 前置一个空格并且包含属性名称的完全形式 2.4.3.1. 可以接受的值: true, yes, 1, 默认是不使用这种方式的 2.4.3.2. 以<body <decorator:getProperty property=”body.onload”/>>为例, 假设body.onload 属性值为 window.alert();: 2.4.3.2.1. 不设置此属性: <body window.alert();>, 也就是说不使用 writeEntireProperty 就需要 手动设置属性的名称在模板页中. 2.4.3.2.2. 设置此属性: <body onload=”window.alert();”/> 2.5. <decorator:usePage id=””/>: 将page 对象暴露成为一个装饰器 jsp 中的变量. 2.5.1. id: page 对象的名称 2.5.2. 示例: <decorator:usePage id="myPage" /> <% if ( myPage.getIntProperty("rating") == 10 ){%> <b>10 out of 10!</b> <% }%> 2.5.3. 注意: 这里引入的 page 对象, 实际上就是前面一直说的原始页面, 也就是我们的 url 所请求的页面. 3. page 标签: 用于在当前页面中装饰内联的或外部的内容. 3.1. <page:applyDecorator name=””[page=”” title=””]> </page:applyDecorator>: 装饰器的 包含. 3.1.1. name: decorators.xml 中配置的装饰器的名字. 3.1.2. page: 对于要应用的装饰器要使用的页面对象 3.1.3. title: 和page 一起才有效, 是重写 page 指定的页面对象的 title 3.2. <page:param name=””></page:param>: 在<page:applyDecorator />内部为请求的页面指 定参数. Advanced SiteMesh 官方文档中文版 2009-01-05 00:45 假设你打算结合多种技术来构建一个企业级 web 站点。比如,你准备采用 J2EE 技术往你的 web 站点里添加新内容,而这个系统的其他部分是用 CGI 或者微软的 IIS Server 搭建的。 在这种情况下,怎样让你的应用系统从外观和感受(look and feel)上保持一致 呢?一种办案就是采用 J2EE 技术全部重写,然后选用一种框架,比如 Struts-Tiles,但这种办案的开发成本太高,不太现实。另一种可选方案是在你 的应用系统的各个部分采用相同的 Look and Feel。但这种方案会使维护站点变 成噩梦,因为每当一个应用系统里面的 Look and Feel 需要改变的时候,你就需 要让系统里的其他 web 应用保持同样的改变。 大多数用于解决这种商务需求的可用框架都有一个共同的缺点,他们不是平台相 关就是框架相关。当你决定采用 Tiles 作为 struts 修饰器的时候,需要创建 tiles 定义文件 tiles-defs.xml,然后在 struts-config.xml 里面声明 forwards,引用这些 tiles 以修饰原始的 JSP。 最简单的一种可能的解决方案是,全部采用纯 html 方式来生成你的 web 应用, 每一个 html 页面都不需要知道自己将会被如何修饰,而是在外部采用某种机制 来选择合适的修饰器修饰它们。这就是 SiteMesh 的功能。 SiteMesh 是基于 Java、J2EE 和XML 的开源框架,依赖于从 Servlet 2.3 版本里 引入的新功能——过滤器(Filters) 安装和设置 按照以往的经验,学习任何新技术或新框架最好的办法,就是使用它来创建一个 简单的应用程序。所以,我们将使用 SiteMesh 来创建一个简单的 Struts 应用程 序。我们的应用程序包括三个页面: •一个登录页面 •一个帮助页面,包括页头和页脚 •一个主页面,包括页头、页脚和页边菜单 下面是创建这个简单 web 应用程序的步骤: 1.SiteMesh 基于过滤器,所以我们需要把 SiteMesh 过滤器通知给我们的 web 应用程序。在 web.xml 文件里加入如下几行: <filter> <filter-name>sitemesh</filter-name> <filter-class> com.opensymphony.module.sitemesh.filter.PageFilter </filter-class> <init-param> <param-name>debug.pagewriter</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 这几行是告诉 web 容器,所有对 web 应用的请求都会经由 PageFilter“过滤” 一下。PageFilter 是sitemesh-2.1.jar 里的一个类,你可以从 http://www.opensymphony.com/sitemesh/download.html 下载该 jar 包。 2.在 WEB-INF 目录下生成一个 decorators.xml 文件,内容如下: <decorators defaultdir="/decorators"> <!— 给需要页边菜单的页面配置页边菜单修饰器 --> <decorator name="sidemenu" page="sidemenu.jsp"> <pattern>/home.jsp</pattern> </decorator> <!— 给需要页头和页脚的页面配置页头页脚修饰器 --> <decorator name="headerfooter" page="headerfooter.jsp"> <pattern>/help.jsp</pattern> </decorator> </decorators> decorators.xml 文件用来在你的应用程序里定义修饰器(decorators)。在这个 文件里,每个<decorator>元素定义一个修饰器,name 指定修饰器名,page 指定 修饰器所使用的 JSP 页面。<pattern>子元素指定这些修饰器如何应用到实际的 页面上去。 在我们的示例 web 应用里,定义了两个修饰器:追加页头和页脚的 headerfooter.jsp 和追加页边菜单的 sidemenu.jsp。我们想修饰 help 页面追加 页头和页脚,所以我们追加了一个/help.jsp 路径子元素给 headerfooter.jsp 修饰器。 3.在 WebContent/decorators 目录下创建 headerfooter.jsp: <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title> My Site - <decorator:title default="Welcome!" />

SiteMesh Corporation

SiteMesh copyright
一个 SiteMesh 修饰器其实就是一个使用 SiteMesh 自定义标签的 JSP 页面。在我 们的 web 应用里,当用户请求 help 页面的时候,SiteMesh 会拦截这个请求,然 后再把它发送给 web 应用。而当应用返回响应的时候,SiteMesh 会结合 headerfooter.jsp 文件解析这个响应,遇到就插入响应文件 的,遇到就插入响应文件的。最后,被 headerfooter.jsp 修饰过的文件会被返回给客户端。 4.在 WebContent 目录下创建 help.jsp: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> Help Page Help Page 这是一个在 web 应用里很常见的 help 页面。 5.在浏览器里请求 help.jsp 页面,测试 SiteMesh 安装是否正常。浏览器将会 返回一个包含页头和页脚的 help 页面。 SiteMesh 架构 SiteMesh 架构基于 PageFilter——一个 Servlet 过滤器。容器接收到页面请求 时,会把请求传递给 PageFilter,PageFilter 收集应用程序的响应细节,生成 自定义的响应对象,然后连同请求一起传递给 web 应用程序。web 应用程序把响 应资源写入到自定义响应对象里,再返回给 PageFilter。 1.解析阶段 当控制返回给 PageFilter 的时候,它会检查 web 应用生成响应的内容类型 (content type),然后基于响应类型,生成不同的解析器来解析响应。比如,如 果应用返回 text/html 类型的内容,SiteMesh 会生成一个 FastPageParser 实例, 并把 web 应用生成的页面传递给它。FastPageParser 会解析这个页面,提取出 这个页面的 header、footer、title 等内容。 2.修饰阶段 解析结束后,SiteMesh 开始修饰页面。这一阶段分成两部分: a.决定如何修饰 SiteMesh 有一个概念,叫做修饰器映射,实现这个概念的接口是 DecoratorMapper(有init()和getDecorator()方法)。映射器在 sitemesh.xml 里声明。在sitemesh.xml 文件里,每一个映射器都是它上一个映射器的父映射。 当SiteMesh 需要一个修饰器来修饰页面的时候,会在 sitemesh.xml 里查找映射 器,生成找到的第一个映射器的实例并调用 getDecorator()方法,在这个方法 里尝试查找针对那个页面的修饰器。如果找到了就返回;否则,调用父映射器的 getDecorator()方法,反复进行这个过程,直到找到正确的修饰器。 b.应用修饰 找到修饰器后,SiteMesh 会把请求分发给它。修饰器 JSP 页面会访问在前阶段 里解析出来的页面信息。使用各种 SiteMesh 自定义标签来提取页面信息不同的 部分(比如 header、footer 和title)并把它们插入到输出文件合适的位置上去。 你可以在 sitemesh.xml 文件里自定义使用哪个页面解析器来解析指定的内容类 型或者使用哪种修饰器映射方案,比如: 在这个列表里,指定了用于定义修饰器的 文件。定义了 SiteMesh 可以处理的内容类型。每一个 子元素指定哪一个解析器解析哪一种特定的内容类型。在我们的示例 sitemesh.xml 文件里,我们告诉 SiteMesh 使用 FastPageParser 解析 text/html 类型的内容。默认地,SiteMesh 只可以处理 HTML,但我们可以创建自己的解析 器来处理其他的内容类型。 子元素定义了映射方案,SiteMesh 使用这个映射方案来查 找修饰指定页面的修饰器。你可以使用子元素来配置每一个映射器。 SiteMesh 会把这些配置信息包装成 java.util.Properties 对象传递给映射器的 init()方法。 区域相关的修饰器 在我们的示例 sitemesh.xml 文件里,有下面几行标签: 当查找一个应用于页面的修饰器时,SiteMesh 会首先读取请求头部的 Accept-Language 信息。如果匹配 en 区域,SiteMesh 会在修饰器 JSP 文件名末 尾追加-en。在我们的例子里,如果请求定义了修饰器 headerfooter.jsp 的 help.jsp 页面,并且使用的是区域是英国,SiteMesh 会首先查找并应用 headerfooter-en.jsp 修饰器,如果找不到再去应用 headerfooter.jsp。 浏览器相关的修饰器 可以使用 AgentDecoratorMapper 来保证浏览器的兼容性: 这意味着当 SiteMesh 查找一个修饰器来修饰页面的时候,会首先提取出请求头 部的 User-Agent 信息。如果是 IE,就加上-ie 到修饰器的文件名末尾,并查找 和应用这个修饰器。如果找不到这样的修饰器,则继续应用 headerfooter.jsp。 高级 SiteMesh SiteMesh 提供映射器,让每一个页面参与到寻找自己修饰器的过程中去。 PrintableDecoratorMapper 大多数的 web 站点都提供了一个获得可打印版本页面的功能。所谓可打印版本, 一般是指去除了页头、页尾和页边菜单,并使用了另一套样式表的页面。在 SiteMesh 里,我们可以使用 PrintableDecoratorMapper 来提供这个功能。要使 用这个映射器,需要在 sitemesh.xml 里追加如下几行: 传递给 PrintableDecoratorMapper 的三个配置参数会被包装成 java.util.Properties 对象传递给 init()方法。 •decorator 用来生成可打印版本页面的修饰器名。 •parameter.name 用来通知 SiteMesh 我们需要一个可打印版本的请求参数名。比如在我们的例子 里,通过在查询字符串里追加 printable=true 参数传递 •parameter.value 设置可打印参数为何值时 SiteMesh 提供可打印版本的页面。 PageDecoratorMapper 页面可以通过定义 META 属性来重载指定修饰自己的修饰器名。 要使用这个映射器,需要在 sitemesh.xml 文件里加入如下几行: PageDecoratorMapper 可以获取一个参数列表。在我们的例子里,提供了一个参 数名,指定了通过 META 属性来取得修饰器名。所以如果我们希望使用 test 修饰 器来修饰页面,则在该页头部加入: PageDecoratorMapper 提供了一种静态的方法来让页面选择自己想要使用的修 饰器。另外,页面还可以通过使用 ParameterDecoratorMapper 在运行时指定要 使用的修饰器。 ParameterDecoratorMapper 要使用 ParameterDecoratorMapper,在 sitemesh.xml 里追加如下几行: 三个参数的意义分别如下: •decorator.parameter 指定修饰器所使用的请求参数名。 •parameter.name 确定使用请求修饰器的确认参数名。 •parameter.value 确定使用请求修饰器的确认参数值。 比如,如果你想使用test 修饰器来修饰 help.jsp,可以像下面这样访问 help.jsp help.jsp?decorator=test&confirm=true 除了以上这些映射器以外,SiteMesh 还提供了更多有用的映射器,比如: •FrameSetDecoratorMapper 当页面是 Frame 的时候使用。 •CookieDecoratorMapper 可以通过 cookie 来指定想要使用的修饰器。 •RobotDecoratorMapper 当请求者被确人为 robot 的时候使用指定的修饰器。你可以手动的在请求头部追 加robot 关键字,或者通过修饰器来做。 Velocity 和 Freemarker 修饰器 SiteMesh 并没有限制你只能修饰 JSP 页面。你可以自由的选择想要修饰的对象, 比如 Velocity 或者 Freemarker。Velocity 和Freemarker 是一种可被用于生成 web 页面的模板语言。这些语言比 JSP 更加的简单易用,但在可编程性方面不如 JSP 灵活。 SiteMesh 通过两个 servlet 支持这两种模板语言,这两个 servlet 也被定义在 SiteMesh.jar 文件里。我们可以像这样在 web.xml 里声明这两个 servlet: sitemesh-velocity com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet sitemesh-freemarker com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServle t TemplatePath / default_encoding ISO-8859-1 sitemesh-velocity *.vm sitemesh-freemarker *.dec 当然,我们还需要在 lib 文件夹里引入 freemarker.jar、velocity-dep.jar 和 velocity-tools-view.jar。这些 jar 文件已经包含在 SiteMesh 的发布包里了。 下面让我们修改第一个示例应用,使用 Velocity 和Freemarker 修饰器来取代 JSP。在我们第一个示例应用里定义了两个修饰器:headerfooter 和sidemenu。 下面我们创建一个 headerfooter.dec: My Site - $Advanced SiteMesh ${head}
SiteMesh Corporation
${body}
SiteMesh copyright
在这个页面里,我们使用 Freemarker 模板来请求 header、footer 和title,而 不是使用 JSP 自定义标签,但页面布局是一样的。当容器接收到一个.dec 扩展 名的页面请求时,会把这个请求传递给 FreemarkerDecoratorServlet,后者将 会调用 FreemarkerDecorator 修饰生成的 HTML 页面。我们使用$Advanced SiteMesh 模板来访问应用生成的 web 页面的 title,${head}访问 head,${body} 访问 body。Freemarker 提供了非常丰富的模板,想深入研究的话可以参考 http://www.javaworld.com/jw-01-2001/jw-0119-freemarker.html。 相似的,在decorators 目录下创建 sidemenu.vm 文件,这是 Velocity 修饰器文 件: My Site - $title $head
SiteMesh Header
Sidemenu $body
SiteMesh Footer
使用$title 模板取代,使用$head 和$body Velocity 模板 来取代相应的 JSP 自定义标签。 结论 基于过滤器的 SiteMesh 是一个非常灵活和简单易用的修饰器框架。但它还是存 在着一些问题。首先,从Servlet 2.3 版本才开始支持过滤器,所以一些早期版 本的应用服务器无法支持 SiteMesh。在使用 SiteMesh 之前请先检查一下您想使 用的应用服务器是否支持过滤器。 另外,过滤器只有在使用浏览器请求一个页面的时候才能生效。所以,如果你通 过浏览器访问 home.jsp,它将被修饰,但如果你使用 Servlet 的 RequestDispatcher.include()或者 forward()来控制 home.jsp,修饰器就不起 作用了。但是不用担心,从Servlet 2.4 版本开始,你可以配置过滤器适用的环 境,包括 forward 和include 的情况下都可以使用了。 Spring MVC 整合 sitemesh, freemarker 支持完全 REST方式 文章分类::::Java Java Java Java 编程 使用Spring MVCREST 方式,希望使用如下的 URL: /users/1 /users Java 代码 1. public class FreemarkerDispatcherServlet extends DispatcherServlet { 2. public static final long serialVersionUID = -2440216393145762479L; 3. 4. private static final UrlPathHelper urlPathHelper = new UrlPathHelper(); 5. 6. private FreemarkerDecoratorServlet servlet = new FreemarkerDecoratorServlet(); 7. 8. @Override 9. protected void initFrameworkServlet() throws ServletException { 10. servlet.init(getServletConfig()); 11. } 12. 13. @Override 14. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 15. String path = urlPathHelper.getRequestUri(request); 16. 17. System.out.println(path); 18. if (StringUtils.startsWith(path, "/WEB-INF/decorators/")){ 19. servlet.doGet(request, response); 20. } else { 21. super.doService(request, response); 22. } 23. } 24. } web.xml 中的配置: Xml 代码 1. 2. dispatcher 3. freemarker.ext.servlet.FreemarkerDispatcherServlet 4. 5. TemplatePath 6. / 7. 8. 9. default_encoding 10. UTF-8 11. 12. 1 13. 14. 15. 16. 17. default 18. *.css 19. 20. 21. default 22. *.gif 23. 24. 25. default 26. *.jpg 27. 28. 29. default 30. *.js 31. 32. 33. dispatcher 34. / 35.
还剩41页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

thawice

贡献于2013-05-18

下载需要 6 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf