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"/>