1.1编写一个实现tag接口的实现类
public class ViewIpTag extends TagSupport {
public int doStartTag() throws JspException {
HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
JspWriter out = this.pageContext.getOut();
String ip = request.getRemoteAddr();
try {
out.write("ip : " + ip);
} catch (IOException e) { /*此标签由viewIp2.jsp调用,如出问题,需要通知其调用者,所以转成一个Java运行时异常抛出,以通知其调用者*/
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
1.2、在tld文件中对标签处理器类进行描述(放在WEB-INF目录下)
<?xml version="1.0" encoding="UTF-8" ?>
<taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>There are my custom tags.</description>
<tlib-version>1.0</tlib-version>
<short-name>Class3g</short-name>
<uri>http://www.class3g.com</uri>
<tag>
<description>show the romete address</description>
<name>viewIP</name>
<tag-class>class3g.web.tag.ViewIpTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
<taglib>元素是标签库描述符的根元素,它包含12个子元素,现在只简单介绍几个
<description>:标签库的一个文本描述。
<tlib-version>:指定标签库的版本。
<short-name>: 为标签定义简短的名字,在taglib指令中可作为首选的前缀名使用。
<uri>:定义一个URI,用于唯一的标识此标签库。
<tag>:用于指定自定义标签的相关信息。<tag>元素有12个子元素,这里只对部分元素做介绍,如下。
1) <description>:为自定义标签提供一个文本描述。
2)<name>:指定标签的名字
3)<tag-class>:指定标签处理类的完整路径
4)<body-content>:指定标签体的格式。格式分为如下4种。
l empty:标识标签没有标签体
l scriptless:表示标签体可以包含EL表达式和JSP的动作元素,但是不能包含JSP的脚本元素。
l JSP:表示标签体可以包含JSP代码。
l tagdependent:表示标签体由标签本身去解析处理。若指定tagdependent,那么在标签体中所写的代码将作为纯文本原封不动的传给标签处理类,而不是将执行的结果传给标签处理类。
1.3、在jsp中导入并使用自定义标签viewIP
<%@ taglib uri="http://www.class3g.com" prefix="class3g" %>
<body>
<class3g:viewIP/>
</body>
1.4使用自定义标签控制页面内容(标签体)是否输出,利用doStartTag()的返回值控制
return this.SKIP_BODY; //忽略标签体
return this.EVAL_BODY_INCLUDE; //执行标签体
1.5控制整个jsp的输出
利用doEndTag()的返回值控制
return this.SKIP_PAGE; //跳过页面标签后余下的jsp代码
return this.EVAL_PAGE; //继续执行余下jsp代码
1.6自定义标签实现内容(标签体)循环输出
利用Tag子接口Iteration中定义的doAfterBody()和返回值EVAL_BODY_AGAIN,SKIP_BODY实现
a) 先覆盖doStartTag()方法,返回EVAL_BODY_INCLUDE
b) 覆盖doAfterBody()
public int doAfterBody() throws JspException { times++; int result = this.EVAL_BODY_AGAIN; if(times>4){ result = this.SKIP_BODY; } return result; } |
2.1 使用自定义标签控制页面内容(标签体)是否输出
public void doTag() throws JspException, IOException { //JspFragment jf = this.getJspBody(); //jf.invoke(null); //等价于jf.invoke(this.getJspContext().getOut()); }
|
2.2 简单标签控制标签后的jsp内容是否执行
public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); jf.invoke(null);
throw new SkipPageException(); } |
2.3 自定义标签实现内容(标签体)循环输出
public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody();
for(int i=0; i<5; i++){ jf.invoke(null); } } |
2.4 自定义标签修改内容(标签体)——大小写转换
public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody();
//为了获取JspFragment中的内容,将其输入一个带缓冲的Writer中,//在获取字符串 StringWriter sw = new StringWriter(); jf.invoke(sw);
String content = sw.toString().toUpperCase();
JspWriter out = this.getJspContext().getOut(); out.write(content); } |
2.5
功能:判断一个YYYY-MM-DD格式的日期修改为下面格式输出
年:YYYY
月:MM
日:DD
@Override
public void doTag() throws JspException, IOException {
JspFragment jf = this.getJspBody();
//jf.invoke(this.getJspContext().getOut());
StringWriter sw = new StringWriter();
jf.invoke(sw);
JspWriter out = this.getJspContext().getOut();
String content = sw.getBuffer().toString();
String shu[] = content.split("-");
String shuzu[]={"年:","月:","日:"};
for(int i=0;i<shu.length;i++){
out.write(shuzu[i]+shu[i]+"</br>");
}
}
3.1、标签案例-开发防盗链标签
目标:要开发的标签
<class3g:referer site="http://localhost:8080" page="/index.jsp"/>
site:受信任站点,只允许次站点的请求
page:正确的链接页面,发现盗链后将其自动转入此页面
步骤
1) 标签处理类
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) this.getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
String referer = request.getHeader("referer");
System.out.println(referer);
if(referer==null||!referer.startsWith(site)){
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
String contextPath = request.getContextPath();
System.out.println(contextPath);
if(page.startsWith(contextPath)){
response.sendRedirect(page);
}else if(page.startsWith("/")){
response.sendRedirect(contextPath+page);
}else{
response.sendRedirect(contextPath+"/"+page);
}
throw new SkipPageException();
}
}
2) 描述文件
<tag>
<description>referer demo</description>
<name>referer</name>
<tag-class>class3g.web.tag.RefererTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>site</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>page</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
<attribute>:该标签用于设置标签的属性
<required>:指定该属性是否必须。默认为false
<rtexprvalue>:指定属性值是否可以在JSP运行时期动态产生
3) 在内容页面使用标签
3.2、标签案例-<c:if>标签
标签功能:
<class3g:if exp="${psw==null }">
user == null <br>
</class3g:if>
<%
session.setAttribute("user","Tom");
%>
<class3g:if exp="${user!=null }">
user != null <br>
</class3g:if>
处理类
public class MyIfTag extends SimpleTagSupport {
private boolean exp;
public void setExp(boolean exp) {
this.exp = exp;
}
public void doTag() throws JspException, IOException {
if(exp){
JspFragment jf = this.getJspBody();
jf.invoke(null);
}
}
}
3.3、标签案例if else 标签
<class3g:choose >
<class3g:when exp="${user!=null }">
aaaaaaaaaa
</class3g:when>
<class3g:otherwise>
bbbbbbbbbbbbbbb
</class3g:otherwise>
</class3g:choose>
处理类:
public class ChooseTag extends SimpleTagSupport {
private boolean invoked;//false:没有子标签被执行 true:某一子标签已被执行
public boolean isInvoked() {
return invoked;
}
public void setInvoked(boolean invoked) {
this.invoked = invoked;
}
@Override
public void doTag() throws JspException, IOException {
this.getJspBody().invoke(null);
}
public class WhenTag extends SimpleTagSupport {
private boolean expr;
public void setExpr(boolean expr) {
this.expr = expr;
}
public void doTag() throws JspException, IOException {
ChooseTag ct = (ChooseTag) this.getParent();
if(ct.isInvoked()!=true && expr){
this.getJspBody().invoke(null);
ct.setInvoked(true);
}
}
}
public class OtherwiseTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
ChooseTag ct = (ChooseTag) this.getParent();
if(ct.isInvoked()==false){
this.getJspBody().invoke(null);
ct.setInvoked(true);
}
}
}
4.1.<br>--------c:out---------<br>
用于将表达式的结果输出到当前的JspWriter对象中。其功能类似于JSP的表达式<%=%>,
或者EL表达式${}.
<c:out value="${user }" default="good morning"></c:out>
<br>
4.2.<br>--------c:set---------<br>
用于设置JSP页面的各种域范围中的变量,或者设置java.util.Map对象或JavaBean对象的属性。
<c:out value="<h1>hello world</h1>" escapeXml="true"/>
<c:out value="<h1>hello world</h1>" escapeXml="false"/>
<br>---------c:set---------<br>
<c:set var="user" value="Tom" scope="session"></c:set>
<c:out value="${user }"/>
<%--
<%
session.setAttribute("user","Tom");
%>
--%>
<br/>
<%
Map map = new HashMap();
request.setAttribute("map",map);
%>
<c:set target="${map }" property="city" value="Baoding"></c:set>
<c:out value="${map.city }"></c:out>
<br>
<%
Person person = new Person();
request.setAttribute("person",person);
%>
<c:set property="name" value="susan" target="${person }"></c:set>
<c:out value="${person.name }"></c:out>
<br>
4.3. <br>-----------c:remove---------<br>
用于移除JSP页面中指定域范围中的变量。
<%
session.setAttribute("date","2011-11-10");
%>
<c:out value="${date }"></c:out>
<br>
<c:remove var="date"/>
<c:out value="${date }">date已经被移除了</c:out>
<br>
4.4. <br>-----------c:catch---------<br>
用于捕获嵌套在标签体内的内容抛出的异常对象,并将异常信息保存到变量中。
<c:catch var="error">
<%=1/0 %>
</c:catch>
输出异常:<c:out value="${error }"/><br/>
异常:<c:out value="${error.message }"/><br/>
堆栈轨迹:<c:out value="${error.stackTrace }"/><br/>
4.5.<br/>-------------c:if----------<br/>
用来做条件判断,功能类似于JSP中的<%if(boolean){}%>
<c:if test="${date == null }" var="result" scope="page">
${result }表达式成立
<c:out value="${result }"></c:out>
</c:if>
4.6. <br/>-------------c:foreach----------<br/>
用于对包含了多个对象的集合进行迭代,重复执行它的标签体,或者重复迭代固定的次数。
<%
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("fff");
list.add("ggg");
list.add("hhh");
request.setAttribute("list",list);
%>
<c:forEach items="${list }" var="curElement" begin="2" end="6" step="2">
<c:out value="${curElement }"></c:out><br/>
</c:forEach>
4.7 <br/>-------------c:forTokens----------<br/>
用来浏览一字符串中所有的成员,其成员是由定义符号(Delimiters)所分隔的。
<c:forTokens items="123456789" delims="1357" var="token">
<c:out value="${token }"/><br/>
</c:forTokens>
4.8 <br/>-------------c:foreach实现表格的颜色间隔显示----------<br/>
<%
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("fff");
list.add("ggg");
list.add("hhh");
request.setAttribute("list",list);
%>
<style type="text/css">
.even{background-color:#ffffcc }
.odd{background-color:#ffcc00 }
tr:hover{background-color: #ffccff}
</style>
<table border="1" width="100">
<c:forEach items="${list }" var="date" varStatus="status">
<tr class="${status.count%2==0?'odd':'even' }">
<td>${date}</td>
</tr>
</c:forEach>
</table>
JSTL fmt:formatNumber日期、 数字、货币格式化
使用<fmt>标签应先导入
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
其uri可在fmt.tld文件下
5.1. 日期格式化
<fmt:formatDate value=“${XXX.date}” pattern=“yyyy-MM-dd HH:mm:ss”/> |
value:要格式化的日期
pattern:日期格式化的格式
5.2 数字格式化
<fmt:formatNumber value="12" type="currency" pattern="$.00"/> -- $12.00 |
5.2.1.java格式化输出:
DecimalFormat df = new DecimalFormat("格式"); String fmt =df.format(double); 符号 意义 0 一个数位 # 一个数位,前导零和追尾零不显示 . 小数点分割位置 , 组分隔符的位置 - 负数前缀 % 用100乘,并显示百分号 其他任何符号 在输出字符串中包括指定符号 |
5.2.2.编程实现固定文本的国际化
ResourceBundle类提供了一个静态方法getBundle,该方法用于装载资源文件,并创建ResourceBundle实例:
Locale currentLocale = Locale.getDefault();
ResourceBundle myResources =
ResourceBundle.getBundle(basename, currentLocale);
• basename为资源包基名(且必须为完整路径)。
代码如下:
<%
ResourceBundle bundler =
ResourceBundle.getBundle("class3g.web.properties.MyProperties",
request.getLocale());
%>
<form>
<%=bundler.getString("username") %><input type="text" name="username" /><br/>
<%=bundler.getString("password") %><input type="text" name="password" /><br/>
<input type="submit" value="<%=bundler.getString("submit") %>" /><br/>
</form>
<!--
<fmt:setBundle basename="class3g.web.properties.MyProperties"/>
-->
<fmt:bundle basename="class3g.web.properties.MyProperties">
<form>
<fmt:message key="username" /><input type="text" name="username" /><br/>
<fmt:message key="password" /> <input type="text" name="password" /><br/>
<input type="submit" value="<fmt:message key="submit" />" /><br/>
</form>
</fmt:bundle>
当前时间的三种表现形式如下:<br><br>
(1):<fmt:formatDate value="<%=new Date() %>" type="date"/><br><br>
(2):<fmt:formatDate value="<%=new Date() %>" type="time"/><br><br>
(3):<fmt:formatDate value="<%=new Date() %>" type="both"/>