在 Struts 2 中自定义支持 OGNL 的标签

来源:互联网 发布:google tensorflow应用 编辑:程序博客网 时间:2024/06/03 11:42

原文链接http://blog.psjay.com/posts/customize-tags-which-supporting-ognl-in-struts-2/


最近在用 Struts 2 练习着做一个 Toy Project 。为了使试图层代码保持整洁,需要在 JSP 页面中使用自定义标签。自定义 JSP 标签的方法在这篇教程中已经说得很清楚了,但是由于这样自定义的标签只支持 EL 表达式而不支持 OGNL,所以在使用了 Struts 2 的项目中发挥不出太多用处,特别是当需要将 Action 中的值传给标签作为其属性时。当然,有一些办法使得可以用 JSTL 访问到 Action 的值,但为了保持编码的统一风格,不在页面上同时出现两种表达式语言,我还是决定使自定义标签支持 OGNL 。

使自定义 JSP 标签支持 OGNL 的方法也很简单,只需要做三件事情就可以办到:

  • 创建一个 Component 类,继承自 org.apache.struts2.components.Component,这个类封装了标签的逻辑;

  • 创建一个 Tag 类,继承自 org.apache.struts2.views.jsp.ComponentTagSupport,这个类提供 JSP 支持并且向 Component 类传递参数;

  • 创建一个 tld 文件,放在 Web 项目的 WEB-INF 或其子目录下,定义了自定义标签的格式。

自定义 Component 类

也许你会产生疑问,为什么 Struts 2 要把标签的逻辑分离出来,封装在一个 Component 类中而不直接写在 Tag 类中呢?这是因为 Struts 2 支持多种试图,例如 JSP,Freemarker,Velocity。不同视图的标签的自定义方法是不同的,为了提高代码的复用性,Struts 2 把标签的逻辑分离了出来。

以万能的 HelloWorld 为例子,写一个简单的 Component:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
package com.psjay.tag.component;import java.io.IOException;import java.io.Writer;import org.apache.struts2.components.Component;import com.opensymphony.xwork2.util.ValueStack;public class HelloWorldComponent extends Component {    private String name;    public HelloWorldComponent(ValueStack stack) {        super(stack);    }    @Override    public boolean start(Writer writer) {        try {            writer.write(name);        } catch (IOException e) {            e.printStackTrace();        }        return true;    }    @Override    public boolean end(Writer writer, String body) {        try {            writer.write("tag end");        } catch (IOException e) {            e.printStackTrace();        }        return super.end(writer, body);    }    // setter and getter    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

这个类的关键就是 start 和 end 方法。这两个方法分别在标签的开始和结束处被调用,而 start 的返回值决定了标签体是否输出。这个类有一个 name 属性,它对应着从页面上通过标签属性传回来的值,当然,要按照国际管理给这个属性加上 setter 和 getter。请注意这个类的构造函数,它有一个 ValueStack 参数,说明了在这个类中其实是可以访问到 Action 的 ValueStack 的。调用 getStack() 方法就返回 Action 的 ValueStack,然后你就可以通过 ValueStack 的 findValue 方法来提供 ONGL 支持了。

自定义 Tag 类

完成了逻辑部分的 Component ,就需要开始创建 Tag 类了。接着上面的例子,创建一个 HelloWorldTag:

123456789101112131415161718192021222324252627282930313233343536
package com.psjay.tag;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts2.components.Component;import org.apache.struts2.views.jsp.ComponentTagSupport;import com.psjay.tag.component.HelloWorldComponent;import com.opensymphony.xwork2.util.ValueStack;public class HelloWorldTag extends ComponentTagSupport {    private static final long serialVersionUID = 7767836903901043944L;    private String name;    @Override    public Component getBean(ValueStack stack, HttpServletRequest req,            HttpServletResponse res) {        return new HelloWorldComponent(stack);    }    @Override    protected void populateParams() {        HelloWorldComponent component = (HelloWorldComponent)getComponent();        component.setName(name);    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

同样的,需要为这个类声明相应的属性和对应的 setter 和 getter。然后重写 getBean 方法,返回一个新创建的 HelloWorldComponent。populateParams 方法就是为 component 传递参数的方法了,这个例子只是简单的将 Tag 的 name 属性直接赋值给了 Component 的 name 属性。

定义 tld

tld 描述了标签的语法,具体的格式本文不赘述,本文开头部分链接到的教程里已经有了详细的说明,这里只给出代码:

1234567891011121314151617
<?xml version="1.0" encoding="UTF-8"?><taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version> <short-name>mytaglib</short-name> <uri>/mytaglib</uri> <tag>  <name>HelloWorld</name>  <tag-class>com.psjay.tag.HelloWorldTag</tag-class>  <body-content>JSP</body-content>  <attribute>   <name>name</name>   <required>true</required>   <rtexprvalue>false</rtexprvalue>  </attribute> </tag></taglib>

将这个 tld 文件放在 Web 目录下的 WEB-INF 或其子目录下即可。

使用自定义的标签

到这里,就已经完成了定义标签的所有工作,使用方法也很简单:

1234
<%@taglib prefix="my" uri="/mytaglib" %><my:HelloWorld name="psjay">    this is the tag body</my:HelloWorld>

使用浏览器打开这个 JSP 页面,页面就会输出

psjay this is the tag body tag end

 2011-10-23 Sun  Code, Java












0 0
原创粉丝点击