最近在做j2ee的项目,需要封装很多标签,发现直接从BodyTagSupport继承的话,无法获取valuestack,也无法借用struts的国际化解决方案。所以需要扩展struts的标签。
看了网上很多的扩展方法,觉得只能做为参考或示例,但却一点也不实用。索性自已用ComponentTagSupport来做个封装。
下面是关于ComponentTagSupport的一些介绍:
package com.jdgm.platform.common.tag;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import com.jdgm.framework.utils.BeanUtils;
import com.jdgm.framework.utils.ResourceUtil;
import com.jdgm.framework.utils.Utils;
import com.jdgm.platform.ConstantsPF;
import com.jdgm.platform.components.log.LogUtil;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
/**
*
* struts的标签扩展从这里继承
* 相比于从BodyTagSupport扩展,具有以下优势:
* 1)国际化的解决:CommonStrutsTag的子类可以享有和struts自带标签一样的国际化解决方案
* 2)值栈:CommonStrutsTag的子类,可以获取valuestack的实例,也可以通过类属性
* 来做与action对应属性的双向绑定,即值提交与值填充<具体参见属性valueproperty的说明>
*
* @author zhangpf
*
*/
public abstract class CommonStrutsTag extends ComponentTagSupport {
/**
* 网站的URL地址,系统赋值。
*/
protected String ctx;
protected String id;
protected String templateFile;
protected String showdiv;
public String getShowdiv() {
return showdiv;
}
public void setShowdiv(String showdiv) {
this.showdiv = showdiv;
}
/**
* 所有属性列表
*/
protected List propertys = new ArrayList();
{
propertys.add("ctx");
propertys.add("id");
propertys.add("showdiv");
}
/**
* 需要在字类中特殊处理的属性集合
*/
protected List specproperty = new ArrayList();
/**
* URL相关的属性
*/
protected List urlproperty = new ArrayList();
/**
* 需要从valuestack中取值的相关的属性
* 比如:控件具有一属性:titlefield,值为"model.title"
* 对应的控件源码为:< input name="%{titlefield}" />
* 这样的话,就完成了与action中属性model.title的单向绑定,即提交表单时
* input的值会自动填充到action中的对应属性。但是却无法做到把action中属性的值
* 反向填充到input控件。若想做到这一点,可修改控件源码为:
* < input name="%{titlefield}" value="%{title}"/>
* 同时,在tag子类中,再定义一属性title,并把添加到valueproperty中,
* 然后在init()中,为title赋值为:"model.title",这样就完成了action属性值与input控件的反向绑定
* 即通过action地址打开jsp页面时,若action中model.title不为空,则会把该属性的值自动赋给控件
*/
protected List valueproperty = new ArrayList();
@Override
public Component getBean(ValueStack arg0, HttpServletRequest arg1,
HttpServletResponse arg2) {
init();
CommonStrutsComponent cmp=new CommonStrutsComponent(arg0);
return cmp;
}
@Override
protected void populateParams() {
super.populateParams();
CommonStrutsComponent cmp=(CommonStrutsComponent)component;
cmp.setHtmlContent(toHTML());
}
/**
* 该方法用于在构建标签前,对标签内的各属性做预处理用的
* 主要方便子类扩展
*/
protected void init(){
}
final protected String toHTML() {
ctx=ConstantsPF.URL_WEBSITE;
try {
StringBuilder string = new StringBuilder(IOUtils.toString(
CommonTag.class.getResourceAsStream(templateFile), "UTF-8"));
for (String pro : propertys) {
if(specproperty.contains(pro)
||valueproperty.contains(pro)
||urlproperty.contains(pro))
continue;
String regex = "%{" + pro + "}";
while (string.indexOf(regex) != -1) {
int index = string.indexOf(regex);
String provalue = String.valueOf( PropertyUtils.getProperty(this,pro));
if (StringUtils.isNotBlank(provalue)) {
string.replace(index, index + regex.length(),provalue);
} else {
provalue = "";
string.replace(index, index + regex.length(), provalue);
}
}
}
dealUrlProperty(string);
dealValueProperty(string);
dealSpecProperty(string);
return string.toString();
} catch (Exception e) {
LogUtil.error("生成控件失败", e);
}
return "";
}
/**
* url 相关的处理
* @param string
* @throws Exception
*/
protected void dealUrlProperty(StringBuilder string)throws Exception
{
for (String pro : urlproperty) {
String regex = "%{" + pro + "}";
while (string.indexOf(regex) != -1) {
int index = string.indexOf(regex);
String provalue = String.valueOf( PropertyUtils.getProperty(this,pro));
if (StringUtils.isNotBlank(provalue)) {
provalue = ctx + provalue;
string.replace(index, index + regex.length(),provalue);
} else {
provalue = "";
string.replace(index, index + regex.length(), provalue);
}
}
}
}
/**
* 需要从valuestack中取值的相关的属性
*/
protected void dealValueProperty(StringBuilder string) throws Exception
{
for (String pro : valueproperty) {
String regex = "%{" + pro + "}";
while (string.indexOf(regex) != -1) {
int index = string.indexOf(regex);
String field = String.valueOf(PropertyUtils.getProperty(this,pro));
if (StringUtils.isNotBlank(field)) {
String fieldValue=this.getStack().findString(field);
if(fieldValue==null)
fieldValue="";
string.replace(index, index + regex.length(),fieldValue);
}
else {
string.replace(index, index + regex.length(), "");
}
}
}
}
/**
* 处理特殊属性,主要用于子类扩展
*/
protected void dealSpecProperty(StringBuilder string) throws Exception{
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCtx() {
return ctx;
}
public void setCtx(String ctx1) {
ctx = ctx1;
}
}
class CommonStrutsComponent extends Component {
private String htmlContent;
public String getHtmlContent() {
return htmlContent;
}
public void setHtmlContent(String htmlContent) {
this.htmlContent = htmlContent;
}
public CommonStrutsComponent(ValueStack stack) {
super(stack);
}
public boolean start(Writer writer) {
boolean result = super.start(writer);
try
{
writer.write(htmlContent);
}
catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
}
对于上面的CommonStrutsTag的类使用,下面给了一个简单例子,看了后,你会觉得因为CommonStrutsTag,再写自定义标签的时候,非常简单,秒秒中的事。哈哈
DemoTag.java
package com.jdgm.platform.common.tag;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import com.jdgm.framework.utils.BeanUtils;
import com.jdgm.framework.utils.ResourceUtil;
import com.jdgm.framework.utils.Utils;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
/**
*
* tab页控件
* @author zhangpf
*
*/
public class DemoTag extends CommonStrutsTag {
{
templateFile="demotag.txt";
}
{
propertys.add("field");
valueproperty.add("value");
}
private String field;
private String value;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
demotag.txt: