自定义标签,JSTL标签,web国际化
一、自定义标签
自定义标签主要用于移除Jsp页面中的java代码。
使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:
1:编写一个实现Tag接口的Java类(标签处理器类)。
2:编写标签库描述符(tld)文件,在tld文件中把标签处理器类进行描述。
1自定义标签的开发步骤
1:编写一个类,直接或间接地实现javax.servlet.jsp.tagext.SimpleTag。一般继承javax.servlet.jsp.tagext.SimpleTagSupport。
2:在WEB-INF目录下建立一个扩展名是tld的xml文件。
tld的属性直接拷贝一般,在 E:\apache-tomcat-7.0.55\webapps\examples 下搜索tld文件直接拷贝属性:
然后在自己tld中写配置文件
3:使用:在jsp中通过taglib指令引入标签库
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <!-- uri 为tld中的URI prefix为tld的shortname -->
4 <%@ taglib uri="http://www.baidu.com/jsp/tags" prefix="wsj" %>
5
6 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
7 <html>
8 <head>
9 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
10 <title>Insert title here</title>
11 </head>
12 <body>
13 您的IP是:
14 <wsj:ShowRemoteIp/>
15 </body>
16 </html>
运行后就是自己IP地址:
2标签的执行过程和原理
JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。
1、public void setPageContext(PageContext pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。
2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。
3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。
4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。
5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。
3标签的扩展功能
- a、控制标签的主体内容是否显示。
demo1类
1 package jsptagdemo;
2
3 import java.io.IOException;
4
5 import javax.servlet.jsp.JspException;
6 import javax.servlet.jsp.JspWriter;
7 import javax.servlet.jsp.PageContext;
8 import javax.servlet.jsp.tagext.JspFragment;
9 import javax.servlet.jsp.tagext.SimpleTagSupport;
10
11 public class demo1 extends SimpleTagSupport {
12 private boolean test; //基本类型自动转换 Boolean.parser(String s)
13
14 //标签属性对应这个
15 public void setTest(boolean test) {
16 this.test = test;
17 }
18
19 @Override
20 public void doTag() throws JspException, IOException {
21 //true显示 false默认不处理不显示
22 if(test){
23 //把主体内容用输出流输出即可
24 // PageContext pc = (PageContext) getJspContext();
25 // JspWriter out = pc.getOut();//得到输出流
26 // JspFragment jf = getJspBody(); //得到封装了主体内容的jsp片段
27 // jf.invoke(out);
28
29 getJspBody().invoke(null); //等同于上面代码 看API
30 }
31 }
32 }
tld文件配置
jsp代码
1 <%@page import="java.util.ArrayList"%>
2 <%@page import="java.util.List"%>
3 <%@ page language="java" contentType="text/html; charset=UTF-8"
4 pageEncoding="UTF-8"%>
5
6 <%@ taglib uri="http://www.baidu.com/jsp/tags" prefix="wsj" %>
7 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
8 <html>
9 <head>
10 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
11 <title>控制标签的主体内容是否显示</title>
12 </head>
13 <body>
14 <%
15 List list = new ArrayList();
16 list.add("haha");
17 list.add("haha2");
18 pageContext.setAttribute("list", list);
19 %>
20
21 <wsj:demo1 test="${empty list}">
22 空
23 </wsj:demo1>
24
25 <wsj:demo1 test="${!empty list}">
26 不空
27 </wsj:demo1>
28 </body>
29 </html>
运行结果有数据:
- b、控制结束标签后的内容是否执行。
jsp代码
tld配置
- c、控制主体内容重复执行(相当于demo1)
jsp代码
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <%@ taglib uri="http://www.baidu.com/jsp/tags" prefix="wsj" %>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5 <html>
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <title>Insert title here</title>
9 </head>
10 <body>
11 <wsj:demo3 count="3">
12 <hr/>
13 </wsj:demo3>
14 </body>
15 </html>
demo3代码
1 package jsptagdemo;
2
3 import java.io.IOException;
4
5 import javax.servlet.jsp.JspException;
6 import javax.servlet.jsp.tagext.SimpleTagSupport;
7
8 public class demo3 extends SimpleTagSupport {
9 private int count;
10
11 public void setCount(int count) {
12 this.count = count;
13 }
14
15 @Override
16 public void doTag() throws JspException, IOException {
17 for(int i=0; i<count;i++){
18 getJspBody().invoke(null);
19 }
20 }
21 }
- d、改变主体内容后输出
java代码
1 package jsptagdemo;
2
3 import java.io.IOException;
4 import java.io.StringWriter;
5
6 import javax.servlet.jsp.JspContext;
7 import javax.servlet.jsp.JspException;
8 import javax.servlet.jsp.JspWriter;
9 import javax.servlet.jsp.tagext.JspFragment;
10 import javax.servlet.jsp.tagext.SimpleTagSupport;
11 /**
12 * 改变主体内容后输出 大小写转换
13 * @author Angus
14 *
15 */
16 public class dmeo4 extends SimpleTagSupport {
17 @Override
18 public void doTag() throws JspException, IOException {
19 StringWriter sw = new StringWriter();//带有缓存的内存输出流
20 //必须先取到主体内容:abcde
21 JspFragment jf = getJspBody();
22 jf.invoke(sw);
23
24
25 String s = sw.getBuffer().toString();//取到了abcdefg
26
27 JspContext jc = getJspContext();
28 JspWriter out = jc.getOut();
29 out.write(s.toUpperCase());
30
31
32 }
33 }
二、JSTL中的核心标签
Core库中的常用标签:
if choose when otherwise forEach
Core用的少的标签:
1 <%@page import="com.itheima.domain.Student"%>
2 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5 <html>
6 <head>
7 <title>Core用的少的标签</title>
8
9 <meta http-equiv="pragma" content="no-cache">
10 <meta http-equiv="cache-control" content="no-cache">
11 <meta http-equiv="expires" content="0">
12 <!--
13 <link rel="stylesheet" type="text/css" href="styles.css">
14 -->
15
16 </head>
17
18 <body>
19 <br/>---------c:out输出内容到页面上----------<br/>
20 <c:out value="abc"></c:out>
21 <%
22 pageContext.setAttribute("data1","abcdef");
23 %>
24 <c:out value="${data1}"></c:out>
25 <%
26 pageContext.setAttribute("data2","<hr/>");
27 %>
28 <c:out value="${data2}" escapeXml="true"></c:out>
29 <c:out value="${data3}" default="木有"></c:out>
30 <br/>---------c:set存放数据到域对象中;设置JavaBean的属性;设置Map的key和value值----------<br/>
31 <c:set value="pp" var="p"></c:set><!-- pageContext.setAttribute("p","pp") -->
32 ${pageScope.p}<br/>
33 <c:set value="rp" var="p" scope="request"></c:set><!-- request.setAttribute("p","rp") -->
34 ${requestScope.p}<br/>
35 <c:set value="sp" var="p" scope="session"></c:set><!-- session.setAttribute("p","sp") -->
36 ${sessionScope.p}<br/>
37 <c:set value="ap" var="p" scope="application"></c:set><!-- application.setAttribute("p","ap") -->
38 ${applicationScope.p}<br/>
39 <hr/>
40 <%
41 pageContext.setAttribute("s", new Student());
42 %>
43 ${s.name}<br/>
44 <c:set property="name" target="${s}" value="杨彬彬"></c:set><!-- s.setName("杨彬彬") -->
45 ${s.name}
46 <hr/>
47 <%
48 pageContext.setAttribute("map", new HashMap());
49 %>
50 <c:set property="k1" value="vvv1" target="${map}"></c:set>
51 ${map.k1}
52 <hr/>
53 <br/>---------c:remove从域范围中删除属性----------<br/>
54
55 <c:remove var="p" scope="request"/>
56 page:${pageScope.p}<br/>
57 request:${requestScope.p}<br/>
58 session:${sessionScope.p}<br/>
59 application:${applicationScope.p}<br/>
60
61 <hr/>
62
63 <c:remove var="p"/><!-- 四个域范围中的所有p删除掉 -->
64 page:${pageScope.p}<br/>
65 request:${requestScope.p}<br/>
66 session:${sessionScope.p}<br/>
67 application:${applicationScope.p}<br/>
68 <br/>---------c:catch抓异常----------<br/>
69 <c:catch var="e">
70 ${s.sex}
71 </c:catch>
72 ${e.message}
73 <hr/>
74 <br/>---------c:import包含。可以包含任何页面----------<br/>
75 <c:import url="http://www.baidu.com"></c:import>
76 </body>
77 </html>
Core的常用标签:必须掌握
1 <%@page import="com.itheima.domain.Student"%>
2 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5 <html>
6 <head>
7 <title>Core的常用标签:必须掌握</title>
8
9 <meta http-equiv="pragma" content="no-cache">
10 <meta http-equiv="cache-control" content="no-cache">
11 <meta http-equiv="expires" content="0">
12 <!--
13 <link rel="stylesheet" type="text/css" href="styles.css">
14 -->
15
16 </head>
17
18 <body>
19 <br/>-------c:if模拟java的if语句------------<br/>
20 <c:if test="true">
21 ok
22 </c:if>
23 <br/>-------c:choose c:when c:otherwise 模拟switch的功能------------<br/>
24 <%pageContext.setAttribute("grade", "D"); %>
25 <c:choose>
26 <c:when test="${grade=='A' }">优秀</c:when>
27 <c:when test="${grade=='B' }">良好</c:when>
28 <c:when test="${grade=='C' }">合格</c:when>
29 <c:otherwise>尚需努力</c:otherwise>
30 </c:choose>
31 <br/>-------c:forEach循环------------<br/>
32 <%
33 List<Student> stus = new ArrayList<Student>();
34 stus.add(new Student("杨彬彬","male","石家庄",24));
35 stus.add(new Student("邓冰","female","重庆",25));
36 stus.add(new Student("陈冠希","male","香港",30));
37 stus.add(new Student("阿娇","male","石家庄",24));
38 stus.add(new Student("张柏芝","female","石家庄",24));
39 pageContext.setAttribute("stus", stus);
40 %>
41 <table border="1">
42 <tr>
43 <th>序号</th>
44 <th>第一个</th>
45 <th>最后一个</th>
46 <th>姓名</th>
47 <th>性别</th>
48 <th>地址</th>
49 <th>年龄</th>
50 </tr>
51 <!--
52 属性:varStatus:取值为一个字符串,引用一个对象。
53 这个对象他记录了当前元素的一些基本信息。
54 int getIndex():索引号。从0开始
55 int getCount():计数。从1开始
56 boolean isLast():是否是最有一个元素
57 boolean isFirst():是否是第一个元素
58 -->
59 <c:forEach items="${stus}" var="s" varStatus="vs">
60 <tr bgcolor="${vs.index%2==0?'#c3f3c3':'#f3c3f3'}">
61 <td>${vs.count}</td>
62 <td>${vs.first}</td>
63 <td>${vs.last}</td>
64 <td>${s.name}</td>
65 <td>${s.gender=='male'?'男性':'女性'}</td>
66 <td>${s.city}</td>
67 <td>${s.age}</td>
68 </tr>
69 </c:forEach>
70 </table>
71 <hr/>
72 <%
73 pageContext.setAttribute("strs", new String[]{"a","b","c","d","e","f"});
74 %>
75 <c:forEach items="${strs}" var="s" begin="1" end="5" step="2">${s}</c:forEach>
76 <hr/>
77 <c:forEach begin="1" end="100" var="s">${s} </c:forEach>
78 <br/>-------c:url 自动URL重写 c:param 中文的URL编码------------<br/>
79 <c:url value="/01.jsp" var="u1">
80 <c:param name="username" value="wzhting"></c:param>
81 <c:param name="password" value="123"></c:param>
82 <c:param name="city" value="济南"></c:param>
83 </c:url>
84 <a href="${u1}">猛戳这里</a>
85 </body>
86 </html>
三、国际化(了解)
软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。
国际化又称为 i18n:internationalization
1、固定文本的国际化
把文本写在不同的properties文件中。
一个消息资源包由多个properties文件组成的,但这些文件有着以下的约定:
- 基本文件名一致:msg_zh_CN.properties msg_en_US.properties (ISO)
- 文件中有着相同的key,但是value不同
测试
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <%
6 //得到来访者的语言信息
7 Locale locale = request.getLocale();//Accpet-Language
8 ResourceBundle rb = ResourceBundle.getBundle("com.itheima.resources.msg",locale);
9 %>
10 <head>
11 <title><%=rb.getString("jsp.login.title") %></title>
12
13 <meta http-equiv="pragma" content="no-cache">
14 <meta http-equiv="cache-control" content="no-cache">
15 <meta http-equiv="expires" content="0">
16 <!--
17 <link rel="stylesheet" type="text/css" href="styles.css">
18 -->
19
20 </head>
21
22 <body>
23 <form action="">
24 <%=rb.getString("jsp.login.username") %>:<input/><br/>
25 <%=rb.getString("jsp.login.password") %>:<input/><br/>
26 <input type="submit" value="<%=rb.getString("jsp.login.submit") %>"/>
27 </form>
28 </body>
29 </html>
单元测试
1 package com.itheima;
2
3 import java.util.Locale;
4 import java.util.ResourceBundle;
5
6 import org.junit.Test;
7
8 public class I18nTextDemo {
9 //按照本地(中国)的默认区域信息获取内容
10 @Test
11 public void test1(){
12 ResourceBundle rb = ResourceBundle.getBundle("resources.msg");
13 System.out.println(rb.getString("hello"));
14 }
15 //按照指定的区域信息获取内容
16 @Test
17 public void test2(){
18 ResourceBundle rb = ResourceBundle.getBundle("resources.msg",Locale.US);
19 System.out.println(rb.getString("hello"));
20 }
21 }
2、日期时间的格式化
- 存数据:form—->JavaBean。用户输入的都是String类型—–>JavaBean:其他类型.parser(String)
- 显示数据:JavaBean—–>JSP页面上。显示的都是String类型.其他类型——>String类型.String format(Object)
、
1 package com.wsj;
2
3 import java.text.DateFormat;
4 import java.text.ParseException;
5 import java.util.Date;
6 import java.util.Locale;
7
8 import org.junit.Test;
9
10 public class DateFormatDemo {
11 //FULL: Monday, November 17, 2014 4:47:28 PM CST
12
13 /*内置的样式。自由指定样式请使用SimpleDateFormat:yyyy-MM-dd
14 FULL: 2014年11月17日 星期一 下午04时44分12秒 CST
15 LONG: 2014年11月17日 下午04时45分44秒
16 MEDIUM:2014-11-17 16:46:12
17 DEFAULT:2014-11-17 16:46:12
18 SHORT: 14-11-17 下午4:46
19 */
20
21 @Test
22 public void test1(){
23 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
24 Date now = new Date();
25 String s = df.format(now);
26 System.out.println(s);
27 }
28 @Test
29 public void test2() throws ParseException{
30 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
31 String s = "Monday, November 17, 2014 4:47:28 PM CST";
32 Date d = df.parse(s);//不符合格式
33 System.out.println(d);
34 }
35 }
3、货币的格式化
1 package com.wsj;
2
3 import java.text.NumberFormat;
4 import java.text.ParseException;
5 import java.util.Locale;
6
7 import org.junit.Test;
8
9 public class NumberFormatDemo {
10 @Test
11 public void test1() throws ParseException{
12 int money = 10000000;
13 NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);
14 String s = nf.format(money);
15 System.out.println(s);
16
17 String s1 = "$10,000,000.00";
18 Number n = nf.parse(s1);
19 System.out.println(n);
20 }
21 }
4批量国际化
1 package com.wsj;
2
3 import java.text.DateFormat;
4 import java.text.MessageFormat;
5 import java.text.NumberFormat;
6 import java.util.Calendar;
7 import java.util.Date;
8 import java.util.Locale;
9
10 import org.junit.Test;
11
12 public class MessageFormatDemo {
13 //批量国际化:出现很多区域敏感信息
14 @Test
15 public void test2(){
16 Locale l = Locale.US;
17 //发生的时间//发生的日期
18 Calendar c = Calendar.getInstance();
19 c.set(1998, 6, 3, 12, 30, 00);
20 Date d = c.getTime();
21
22 int money = 1000000;
23
24 String pattern = "At {0,time,medium} on {1,date,long }, a hurricance destroyed 99 houses and caused {2,number,currency} of damage";
25 MessageFormat mf = new MessageFormat(pattern, l);
26 String s = mf.format(new Object[]{d,d,money});
27 System.out.println(s);
28 }
29 //批量国际化:出现很多区域敏感信息
30 @Test
31 public void test1(){
32 Locale l = Locale.US;
33 //发生的时间//发生的日期
34 Calendar c = Calendar.getInstance();
35 c.set(1998, 6, 3, 12, 30, 00);
36 Date d = c.getTime();
37
38 int money = 1000000;
39
40
41 DateFormat df1 = DateFormat.getTimeInstance(DateFormat.DEFAULT,l);
42 String time = df1.format(d);//12:30 pm
43
44 DateFormat df2 = DateFormat.getDateInstance(DateFormat.LONG , l);
45 String date = df2.format(d);//jul 3,1998
46
47 NumberFormat nf = NumberFormat.getCurrencyInstance(l);
48 String smoney = nf.format(money);
49
50
51 String s = "At "+time+" on "+date+", a hurricance destroyed 99 houses and caused "+smoney+" of damage";
52 System.out.println(s);
53 }
54 }
JSTL中的国际化标签
引入:
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <fmt:setLocale value="${pageContext.request.locale}"/>
6 <fmt:setBundle basename="com.itheima.resources.msg" var="msg"/>
7 <head>
8 <title>
9 <fmt:message bundle="${msg}" key="jsp.login.title"/>
10 </title>
11
12 <meta http-equiv="pragma" content="no-cache">
13 <meta http-equiv="cache-control" content="no-cache">
14 <meta http-equiv="expires" content="0">
15 <!--
16 <link rel="stylesheet" type="text/css" href="styles.css">
17 -->
18
19 </head>
20
21 <body>
22 <form action="">
23 <fmt:message bundle="${msg}" key="jsp.login.username"/>:<input/><br/>
24 <fmt:message bundle="${msg}" key="jsp.login.password"/>:<input/><br/>
25 <input type="submit" value="<fmt:message bundle="${msg}" key="jsp.login.submit"/>"/>
26 </form>
27 日期:<hr/>
28 <%
29 pageContext.setAttribute("now", new Date());
30 %>
31 date1:${now}<br/>
32 <fmt:formatDate value="${now}"/><br/>
33 <fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="short"/><br/>
34 <fmt:formatDate value="${now}" type="time"/><br/>
35 <fmt:formatDate value="${now}" pattern="yyyy年MM月dd日"/><br/>
36 </body>
37 </html>