struts2 自定义标签说明:
A、继承ComponentTagSupport,获取jsp页面中的属性值
B、承Component类是为了从Struts2中的ValueStack中获得相对应的值
C、创建标签库的描述文件
D、web.xml中添加标签库说明
E、JSP页面中添加标签库说明,及使用标签
1、继承ComponentTagSupport类是为了获得JSP页面中用户自定义的标签中设置的属性值,并包装成Component对象
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import com.opensymphony.xwork2.util.ValueStack;
/**
* 自定义超链接标签
* 作用:检测用户是否有操作该标签的权限,如果该用户有操作该标签的权限,在页面显示超链接
* 如果用户没有操作该标签的权限,页面上不输出该标签
* */
public class ATag extends ComponentTagSupport {
private String params;
private String opcode;
private String style;
private String id;
private String clasz;
private String title; //标签属性title
private String onclick ;
private HttpServletRequest req;
private HttpServletResponse res;
@Override
public Component getBean(ValueStack stack, HttpServletRequest req,
HttpServletResponse res) {
this.req = req;
this.res = res;
return new A(stack,req);
}
public void setParams(String params) {
this.params = params;
}
public void setOpcode(String opcode) {
this.opcode = opcode;
}
public void setCalcpid(String calcpid) {
this.calcpid = calcpid;
}
public void setReq(HttpServletRequest req) {
this.req = req;
}
public void setRes(HttpServletResponse res) {
this.res = res;
}
public void setStyle(String style) {
this.style = style;
}
public void setId(String id) {
this.id = id;
}
public void setClasz(String clasz) {
this.clasz = clasz;
}
public void setTitle(String title) {
this.title = title;
}
public void setOnclick(String onclick) {
this.onclick = onclick;
}
@Override
protected void populateParams() {
super.populateParams();
A a = (A)component;
a.setClasz(clasz);
a.setId(id);
a.setOpcode(opcode);
a.setParams(params);
a.setStyle(style);
a.setTitle(title);
a.setOnclick(onclick);
HttpSession session = req.getSession();
AuthBean authBean = (AuthBean)session.getAttribute(Constants.ATTR_AUTHBEAN);
a.setAuthBean(authBean);
}
}
注释:ATag重写的两个方法是:
(1).public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res);
此方法就是获得一个基本类的对象。在基本类里面需要有传入ValueStack的构造函数,如果基本类逻辑里面需要request或者response,那么需要有传入ValueStack stack, HttpServletRequest req, HttpServletResponse res的构造函数;
(2).protected void populateParams()此方法是用来将JSP页面传来的属性值赋给基本类。这里是继承来的,所以首先调用super的相应方法。第一个方法返回的对象就是全局的一个Component对象,populateParams方法里面使用的对象。请看ComponentTagSupport源码:
public abstract class ComponentTagSupport extends StrutsBodyTagSupport {
protected Component component;
public abstract Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res);
public int doEndTag() throws JspException {
component.end(pageContext.getOut(), getBody());
component = null;
return EVAL_PAGE;
}
public int doStartTag() throws JspException {
component = getBean(getStack(), (HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse());
Container container = Dispatcher.getInstance().getContainer();
container.inject(component);
populateParams();
boolean evalBody = component.start(pageContext.getOut());
if (evalBody) {
return component.usesBody() ? EVAL_BODY_BUFFERED : EVAL_BODY_INCLUDE;
} else {
return SKIP_BODY;
}
}
protected void populateParams() {
}
public Component getComponent() {
return component;
}
}
ComponentTagSupport类中声明了全局变量component,doStartTag()方法调用抽象方法getBean()生成component对象,这就是为什么我们要覆写getBean()方法。然后调用了 populateParams()方法,最后调用了component.start。
EVAL_BODY_INCLUDE:把Body读入存在的输出流中,
doStartTag()函数可用 EVAL_PAGE:继续处理页面,
doEndTag()函数可用 SKIP_BODY:忽略对Body的处理,
doStartTag()和doAfterBody()函数可用
SKIP_PAGE:忽略对余下页面的处理,
doEndTag()函数可用
EVAL_BODY_TAG:已经废止,由EVAL_BODY_BUFFERED取代 EVAL_BODY_TAG:申请缓冲区,由setBodyContent()函数得到的BodyContent对象来处理tag的body,如果类实现了BodyTag,那么doStartTag()可用,否则非法。
2、继承Component类是为了从Struts2中的ValueStack中获得相对应的值
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.components.Component;
import com.opensymphony.xwork2.util.ValueStack;
public class A extends Component {
private String params; //参数
private String opcode;
private String style; //标签属性风格
private String id; //标签属性id
private String clasz; //标签属性calss
private String title; //标签属性title
private String onclick ; //标签属性onclick
private AuthBean authBean;
HttpServletRequest req ;
public A(ValueStack stack,HttpServletRequest req) {
super(stack);
this.req = req;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getOpcode() {
return opcode;
}
public void setOpcode(String opcode) {
this.opcode = opcode;
}
public String getClasz() {
return clasz;
}
public void setClasz(String clasz) {
this.clasz = clasz;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getOnclick() {
return onclick;
}
public void setOnclick(String onclick) {
this.onclick = onclick;
}
public void setAuthBean(AuthBean authBean) {
this.authBean = authBean;
}
@Override
public boolean start(Writer writer) {
boolean flag = false;//是否能访问本连接
UserRoleOperate operate = null;
if(authBean != null){
authBean.getOperate();
//省略了业务逻辑
flag= true;
}
if(flag){
//如果有访问权限
StringBuffer href = new StringBuffer();
String contextpath = req.getContextPath();
String url = operate.getUrl();
href.append(contextpath+url);
StringBuffer link = new StringBuffer();
link.append("<A ");
//首先添加action
//判断是否为空,如果为空的话,不写href属性
if(!StringUtils.isBlank(url)){
link.append(" href=\"").append(href);
//添加参数
if(!StringUtils.isBlank(params)){
link.append("?"+params);
}
link.append("\"");
}
//添加标签id属性
if(!StringUtils.isBlank(id)){
link.append(" id=\""+id+"\"");
}
//添加标签style属性
if(!StringUtils.isBlank(style)){
link.append(" style=\""+style+"\"");
}
//添加标签calss属性
if(!StringUtils.isBlank(clasz)){
link.append(" class=\""+clasz+"\"");
}
if(!StringUtils.isBlank(title)){
link.append(" title=\""+title+"\"");
}
if(!StringUtils.isBlank(onclick)){
link.append(" onclick=\""+onclick+"\"");
}
link.append(">");
System.err.println("----------------->"+link);
try {
writer.write(link.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
return super.start(writer);
}
@Override
public boolean end(Writer writer, String body) {
boolean flag = false;//是否能访问本连接
UserRoleOperate operate = null;
if(authBean != null){
if(authBean != null){
authBean.getOperate();
//省略了业务逻辑
flag= true;
}
}
if(flag){
try {
writer.write("</A>");
} catch (IOException e) {
e.printStackTrace();
}
}
return super.end(writer, body);
}
}
自己需要输出的逻辑通过writer输出字符串
这里请注意形式参数body中数据为空,为什么呢?为什么标签体的内容没有获得呢?,如果我们想自己控制body的显示呢?
获取body的方法时,重写Component类中的方法:
/**
* Overwrite to set if body shold be used.
* @return always false for this component.
*/
public boolean usesBody() {
return true;
}
设置返回值true,这时候你就可以获得body的值了,自己控制显示的情况。
3、创建标签库的描述文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>2.2.3</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>layout</short-name>
<uri>/struts-layout-tags</uri>
<display-name>"Struts Tags"</display-name>
<description><![CDATA["To make it easier to access dynamic data;
the Apache Struts framework includes a library of custom tags.
The tags interact with the framework's validation and internationalization features;
to ensure that input is correct and output is localized.
The Struts Tags can be used with JSP FreeMarker or Velocity."]]></description>
<tag>
<name>a</name>
<tag-class>com.fangdo.core.view.ATag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>opcode</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<description><![CDATA[opcode for this link]]></description>
</attribute>
<attribute>
<name>calcpid</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[calc product for this link]]></description>
</attribute>
<attribute>
<name>params</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[params for this link]]></description>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[style for this link]]></description>
</attribute>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[id for this link]]></description>
</attribute>
<attribute>
<name>clasz</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[clasz for this link]]></description>
</attribute>
<attribute>
<name>title</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[title for this link]]></description>
</attribute>
<attribute>
<name>onclick</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[onclick for this link]]></description>
</attribute>
</tag>
</taglib>
4、
web.xml中添加标签库说明
<jsp-config>
<taglib>
<taglib-uri>/struts-layout-tags.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-layout-tags.tld</taglib-location>
</taglib>
</jsp-config>
5、
JSP页面中添加标签库说明,及使用标签
<%String jxc4_param = "id="+ cc.getId()+"&height=450&width=750"; %>
<layout:a opcode="JXC_4" params="<%=jxc4_param %>" clasz="thickbox" title="商户详情">
详情
</layout:a>