自定义标签主要可以按4个步骤进行开发
1、创建标签的处理类(Tag Handler Class) ,此类需要继承TagSupport类,重写其中的doStartTag(),doEndTag()方法。
/**
*
*/
package com.watson.common.taglib;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.JavaScriptUtils;
import org.springframework.web.util.WebUtils;
import com.watson.common.util.ContextUtil;
import com.watson.common.util.LocaleUtil;
import com.watson.common.util.SessionUtil;
/**
* 多国语言标签
* @author watson
* @jsp.tag name="locale" bodycontent="empty"
*/
public class LocaleTag extends TagSupport{
private static final long serialVersionUID = 5123954502753313916L;
protected final Log log = LogFactory.getLog(getClass());
private static boolean isLoad = false;
private String key = null;
private String defaultValue = null;
private String args = null;
private String argTransFlag = null;
private String characterCoding = null;
private Boolean htmlEscape=null;//对html特殊字符进行转义
private Boolean javaScriptEscape=null;//对脚本的特殊字符进行处理
private Integer beginIndex=null;//显示字符串开始位置 。
private Integer endIndex=null;//显示字符串结束位置 。
private String implBean = null;
public LocaleTag(){
super();
init();
}
private void init(){
key=defaultValue=args=argTransFlag=characterCoding=null;
javaScriptEscape=htmlEscape=null;
beginIndex=endIndex=null;
implBean = "localeUtil";
}
@Override
public void release() {
super.release();
init();
}
/**
* 获取args
* @jsp.attribute required="false" rtexprvalue="true"
* @return
*/
public String getArgTransFlag() {
return argTransFlag;
}
/**
* 设置arg翻译,true/false
* @param args
*/
public void setArgTransFlag(String argTransFlag) {
this.argTransFlag = argTransFlag;
}
/**
* 获取args
* @jsp.attribute required="false" rtexprvalue="true"
* @return
*/
public String getArgs() {
return args;
}
/**
* 设置arg,参数以都好分隔符分割
* @param args
*/
public void setArgs(String args) {
this.args = args;
}
/**
* 獲取語言編碼
* @jsp.attribute required="true"
* @return
*/
public String getCharacterCoding() {
return characterCoding;
}
public void setCharacterCoding(String characterCoding) {
this.characterCoding = characterCoding;
}
/**
* 获取键值
* @jsp.attribute required="true" rtexprvalue="true"
* @return
*/
public String getKey() {
return this.key;
}
/**
* 设置默认值
* @return
*/
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public Boolean getHtmlEscape() {
return htmlEscape;
}
public void setHtmlEscape(Boolean htmlEscape) {
this.htmlEscape = htmlEscape;
}
public Boolean getJavaScriptEscape() {
return javaScriptEscape;
}
public void setJavaScriptEscape(Boolean javaScriptEscape) {
this.javaScriptEscape = javaScriptEscape;
}
public Integer getBeginIndex() {
return beginIndex;
}
public void setBeginIndex(Integer beginIndex) {
this.beginIndex = beginIndex;
}
public Integer getEndIndex() {
return endIndex;
}
public void setEndIndex(Integer endIndex) {
this.endIndex = endIndex;
}
public String getImplBean() {
return implBean;
}
public void setImplBean(String implBean) {
this.implBean = implBean;
}
/**
* 设置键值
* @param key
*/
public void setKey(String key) {
try {
this.key = (String) ExpressionEvaluatorManager.evaluate("key", key, String.class, this, pageContext);
} catch (JspException e) {
} catch (NullPointerException e) {
this.key = "";
}
}
public int doStartTag() throws JspException {
LocaleUtil localeUtil = (LocaleUtil) ContextUtil.getSpringBeanByName(pageContext.getServletContext(), implBean);
try {
if (null == characterCoding) {
characterCoding = StringUtils.defaultIfBlank(SessionUtil.getLocaleString((HttpServletRequest) pageContext.getRequest()), Constants.DEFAULT_LOCALE);
}
String characterValue=null;
if (StringUtils.isNotEmpty(key)) {
defaultValue=StringUtils.isNotBlank( defaultValue )?defaultValue:key;
if (StringUtils.isNotEmpty(args)) {
String[] argList = args.split(",");
if ("true".equals(argTransFlag)) {
characterValue = localeUtil.getLocalText(characterCoding, key, defaultValue, this.getTrans(argList));
} else {
characterValue = localeUtil.getLocalText(characterCoding, key, defaultValue, argList);
}
} else {
characterValue = localeUtil.getLocalText(characterCoding, key,defaultValue);
}
}
if (StringUtils.isNotEmpty(characterValue)) {
characterValue = substring(characterValue,beginIndex,endIndex);
if( isHtmlEscape() ){
characterValue=HtmlUtils.htmlEscape(characterValue);
}
if( BooleanUtils.isTrue( javaScriptEscape ) ){
JavaScriptUtils.javaScriptEscape( characterValue );
}
pageContext.getOut().print(characterValue);
}
} catch (IOException e) {
log.error(e.getMessage());
}
// Continue processing this page
return SKIP_BODY;
}
/***
* 转义html特殊字符。
* @return
*/
protected boolean isHtmlEscape() {
Boolean calHtmlEscape=null;
if (this.htmlEscape != null) {
calHtmlEscape=this.htmlEscape;
}else {
calHtmlEscape= WebUtils.getDefaultHtmlEscape( pageContext.getServletContext() );
}
return BooleanUtils.toBoolean( calHtmlEscape );
}
/***
* 截取字符串
* @param input
* @param beginIndex
* @param endIndex
* @return
*/
protected String substring(String input, Integer beginIndex, Integer endIndex) {
if (input == null) input = "";
if(beginIndex==null && endIndex==null)
return input;
if(beginIndex==null && endIndex!=null )
beginIndex=0;
if(beginIndex!=null && endIndex==null )
endIndex=input.length();
if (beginIndex >= input.length()) return "";
if (beginIndex < 0) beginIndex = 0;
if (endIndex < 0 || endIndex > input.length()) endIndex = input.length();
if (endIndex < beginIndex) return "";
if(input.length()>endIndex){
return input.substring(beginIndex, endIndex)+"...";
}else{
return input.substring(beginIndex, endIndex);
}
}
private String[] getTrans(String[] arg) {
LocaleUtil localeUtil = (LocaleUtil) ContextUtil.getSpringBeanByName(pageContext.getServletContext(), implBean);
String[] ret = new String[arg.length];
for (int i = 0; i < arg.length; i++) {
ret[i] = localeUtil.getLocalText(arg[i]);
}
return ret;
}
public int doEndTag() throws JspException {
init();
return EVAL_PAGE;
}
}
2、创建标签库描述文件(Tag Library Descrptor File) *.tld文件
<?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>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>jmoa</short-name>
<uri>http://www.jmoa.com/tags/jmoa</uri>
<tag>
<name>locale</name>
<tag-class>com.watson.common.taglib.LocaleTag</tag-class>
<description><![CDATA[国际化配置参数]]></description>
<attribute>
<name>key</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>defaultValue</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>args</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>argTransFlag</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>characterCoding</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>javaScriptEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>beginIndex</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>endIndex</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>implBean</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3、在web.xml文件中配置元素
<jsp-config>
<taglib>
<taglib-uri>http://www.jmoa.com/tags/jmoa</taglib-uri>
<taglib-location>/WEB-INF/jmoa.tld</taglib-location>
</taglib>
</jsp-config>
4. 在JSP文件中引人标签库
<%@ taglib uri="http://www.jmoa.com/tags/jmoa" prefix="jmoa"%>
注意在开发的过程中可能会遇到一些问题
1.需要导入jsp-api.jar包或者是javaee-api.jar包。但是在tomcat容器中,这两个包是已经存在的,如果将这两个包加入到lib中进行发布,会导致与tomcat中的包冲突,引起jsp解析出现空指针报错。解决此问题的方法是让在两个包只留着开发环境而不需要发布到tomcat中,如果用的是maven构建项目,在引入依赖的时候需要加上包的范围限制
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
或者
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
这两个引入其中一个就可以了。