0x00 标签使用
1.需求
Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写。而且struts2的主题、模板都提供了很好的扩展性,实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。
使用struts2的标签的jsp页面,需要头声明:<%@ taglib uri ="/struts-tags" prefix ="s" %>
用struts2开发的人员使用标签,会加速开发进程。
2.样例使用
首先,建立一个ok.jsp的文件,里面使用和标签实现一个链接的编写。
ok.jsp页面如下:
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<s:url>
标签生成了一个变量名为url的链接字符串。然后使用<s:a>
标签通过OGNL语句%{#url}
获取该链接。
效果如下:
0x01 Struts2标签工作原理
1.配置
Struts2-core核心jar包里面定义了各个标签的属性以及处理类等内容。文件名为:META-INF/struts-tags.tld
。
在里面可以找到标签的定义如下:
1 | <tag> |
其中包含了对标签的定义,<tag-class>org.apache.struts2.views.jsp.URLTag</tag-class>
说明了标签的具体实现类为org.apache.struts2.views.jsp.URLTag
。
另外定义了标签的各个属性。比如action,anchor等~
现在来查看下org.apache.struts2.views.jsp.URLTag
类,
1 | public class URLTag extends ContextBeanTag { |
看到该类继承了ContextBeanTag类,里面含有许多公用的属性,而URLTag定义了自己特有的属性,action,value,escapeAmp等,与配置文件相呼应。这里用到了Struts2程序中的一种组件模式, public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res)
。这里返回一个URL类的组件。而该URL组件实际上执行了自身标签特有的工作。
2.工作流程
标签的实现原理,实际上是继承了http servlet中可扩展的BodyTagSupport类。然后会依次执行以下方法:
1 | doStartTag() |
根据上面分析,可以知道URL标签是依靠URLTag类实现的。我们找到了它继承的超类ComponentTagSupport
组件,有doStartTag方法:
1 | public int doStartTag() throws JspException { |
这里主要做了两件事:
(1)通过getBean()方法获取具体的组件Bean,这里是URL组件。然后将组件插入XWork容器中进行维护。
(2)对获取的URL组件中属性赋值。 紧接着执行component.start(pageContext.getOut());
在这里看是执行URL组件的start方法。
1 | public boolean start(Writer writer) { |
对于具体的组件,会有自己特定自定义执行的过程,URL组件是执行渲染URL前的准备工作。 最后执行doEndTag()方法:
1 | public int doEndTag() throws JspException { |
也是主要执行组件的自定义方法end(),在这个方法中,真正有对标签的渲染内容。
1 | public boolean end(Writer writer, String body) { |
关键流程就是以上说明的方式,接着就在doStartTag方法开始对标签流程进行单步调试。
0x02 工作流程调试
在StartTag()方法中下断点,可以清楚的看到取出URL组件并对其属性赋值的过程。 然后在准备工作做完之后,我们跳过中间过程,并且直接进入到URL的end()方法中实现渲染的过程。
urlRenderer.renderUrl(writer, urlProvider);
该方法就开始对<s:url var="url" action="hello" includeParams="all"/>
这句标签语句进行url链接生成。具体实现可以追踪到urlComponent.determineActionURL
方法: 然后进入DefaultUrlHelper类,使用buildUrl方法,生成链接。生成的URL方法如下:
生成了链接URL字符串后,将生成的result放入page上下文和request Servlet上下文中。
然后我们就顺利的将处理好的URL放入request中,然后供标签调用。同样进入到了doStartTag()流程。
最后进入到了Anchor组件的end()方法。并使用FreemarkerTemplateEngine渲染引擎的renderTemplate(),通过定义的模板(默认.ftl文件)页面的渲染操作。