Java Standard Tag Library是apache的一个开源标签组件。http://tomcat.apache.org/taglibs/standard/
JSTL | 标签名称 | 标签配置文件 | 描述 |
---|---|---|---|
核心标签库 | c | c.tld | 定义了属性管理、迭代、判断、输出 |
SQL标签库 | sql | sql.tld | 定义了数据库查询操作 |
XML标签库 | xml | x.tld | 定义了操作XML数据 |
函数标签库 | fn | fn.tld | 提供了一些常用的操作函数,例如:字符串函数 |
I18N格式标签库 | fmt | fmt.tld | 格式化数据 |
标签的开发需要*.tld
文件和所有的标签支持类,这些tld文件可以直接从jar
包中拷贝出来,存放到项目的WEB-INF目录。
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="/WEB-INF/c.tld"%>
<html>
<head>
<title>hello_jstl.jsptitle>
head>
<body>
<c:out value="这是第一个JSTL">c:out>
body>
html>
如果觉得直接在jsp页面中使用标签的绝对路径不太方便,我们也可以在web.xml
中进行以下的配置:
<jsp-config>
<taglib>
<taglib-uri>http://127.0.0.1/javaweb/jstl/coretaglib-uri>
<taglib-location>/WEB-INF/c.tldtaglib-location>
taglib>
<taglib>
<taglib-uri>http://127.0.0.1/javaweb/jstl/fmttaglib-uri>
<taglib-location>/WEB-INF/fmt.tldtaglib-location>
taglib>
<taglib>
<taglib-uri>http://127.0.0.1/javaweb/jstl/fntaglib-uri>
<taglib-location>/WEB-INF/fn.tldtaglib-location>
taglib>
<taglib>
<taglib-uri>http://127.0.0.1/javaweb/jstl/sqltaglib-uri>
<taglib-location>/WEB-INF/sql.tldtaglib-location>
taglib>
<taglib>
<taglib-uri>http://127.0.0.1/javaweb/jstl/xtaglib-uri>
<taglib-location>/WEB-INF/x.tldtaglib-location>
taglib>
jsp-config>
在jsp页面中通过映射的uri进行使用:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%--@ taglib prefix="c" uri="/WEB-INF/c.tld"--%>
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<html>
<head>
<title>hello_jstl.jsptitle>
head>
<body>
<c:out value="这是第一个JSTL">c:out>
body>
html>
该标签主要用于输出内容。语法:
<c:out value="要打印的内容" [escapeXml="[true|false]"] [default="默认值"]>c:out>
<c:out value="要打印的内容" [escapeXml="[true|false]"]>默认值c:out>
例如:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<%
pageContext.setAttribute("info", "慕课网");
%>
属性存在,默认进行了转义:<c:out value="${info }">c:out><br />
属性存在,设置转义为false:<c:out value="${info }" escapeXml="false">c:out><br />
属性不存在,默认值:<c:out value="${ref }" default="属性不存在,这是默认值">c:out><br />
属性不存在,默认值:<c:out value="${ref }">属性不存在,这是默认值,通过标签体给出c:out><br />
将属性保存在4种属性范围之内。语法:
<c:set var="属性名称" value="属性内容" [scope="[page|request|session|application]"]/>
<c:set var="属性名称" [scope="[page|request|session|application]"]>属性内容c:set>
<c:set value="属性内容" target="属性名称" property="属性名称" />
<c:set target="属性名称" property="属性名称" >属性内容c:set>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:set var="info" value="Hello World!" scope="request">c:set><br />
通过c:set设置内容,通过c:out输出内容:<c:out value="${info }">c:out>
<%
SimpleBean bean = new SimpleBean();
request.setAttribute("simple", bean);
%>
<c:set value="怒发冲冠凭栏" target="${simple }" property="content">c:set>
javabean的属性:${simple.content }
删除指定范围之内的属性,功能与removeAttribute()
方法类似,语法:
<c:remove var="属性名" [scope="[page|request|session|application]"]/>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:set var="info" value="hello world!" scope="request">c:set>
属性内容:${info }<br />
<c:remove var="info" scope="request"/>
属性删除后:${info }<br />
处理异常,语法:
<c:catch [var="保存异常信息的属性名称"]>
有可能发生异常的语句
c:catch>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:catch var="errmsg">
<%
int result = 10 / 0;
%>
c:catch>
<h2>异常信息:${errmsg }h2>
主要在程序中进行判断,功能和if语句类似。语法:
<c:if test="判断条件" var="存储判断结果" [scope="[page|request|session|application]"] />
<c:if test="判断条件" var="存储判断结果" [scope="[page|request|session|application]"] >
满足条件时执行的语句
c:if>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:if test="${param.ref=='admin' }" scope="page" var="res1">
欢迎${param.ref }光临<br />
c:if>
<c:if test="${10<30 }" scope="page" var="res2">
10比30小<br />
c:if>
第一个c:if的判断结果:${res1 }<br />
第二个c:if的判断结果:${res2 }
注意:c:choose
标签只能作为c:when
和c:otherwise
的父标签出现。语法:
<c:choose>
标签体内容(<c:when>、<c:otherwise>)
c:choose>
<c:when test="判断条件">
满足条件时执行的语句
c:when>
<c:otherwise>
当所有<c:when>不满足时执行本标签体的内容
c:otherwise>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:set var="num" value="10">c:set>
<c:choose>
<c:when test="${num==0 }">
<c:out value="num等于0">c:out>
c:when>
<c:when test="${num>0 }">
<c:out value="num是正数">c:out>
c:when>
<c:otherwise>
<c:out value="num是负数">c:out>
c:otherwise>
c:choose>
循环控制,主要用于迭代输出,和Iterator接口类似,语法:
<c:forEach [var="每一个对象的属性名称"] items="集合" [varStatus="保存相关成员信息"] [begin="集合的开始输出位置"] [end="集合的结束输出位置"] [step=""每次增长的步进值]>
具体的操作代码
c:forEach>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<%
String[] info = {"Think in java","Head First Java","java7高级编程","Git权威指南"};
pageContext.setAttribute("ref", info);
List all = new ArrayList();
all.add("诛仙");
all.add("轩辕剑");
all.add("魔剑");
all.add("赤霄剑");
pageContext.setAttribute("all", all);
Map map = new HashMap();
map.put("001", "张小凡");
map.put("002", "陆雪琪");
map.put("003", "碧瑶");
pageContext.setAttribute("map", map);
%>
<h2>输出全部h2>
<c:forEach items="${ref }" var="mem" >
${mem },
c:forEach>
<h2>部分输出(间隔为2)h2>
<c:forEach items="${ref }" var="mem" step="2">
${mem },
c:forEach>
<h2>输出前3个h2>
<c:forEach items="${ref }" var="mem" begin="0" end="2">
${mem },
c:forEach>
<hr />
<c:forEach items="${all }" var="res">
${res },
c:forEach>
<hr />
<c:forEach items="${map }" var="m">
${m.key }-->${m.value }<br />
c:forEach>
该标签也是用于输出的。它更像是String
类中的split
方法和循环输出的一种集合,标签的语法如下:
<c:forTokens items="输出的字符串" delims="字符串分隔符" [var="存放每一个字符串变量"] [varStatus="存放当前对象的相关信息"] [begin="输出位置"] [end="结束位置"] [step="输出步长"]>
标签体内容
c:forTokens>
例
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<%
String info = "www.hello.com.cn";
pageContext.setAttribute("ref", info);
%>
拆分结果:<br />
<c:forTokens items="${ref }" delims="." var="con">
${con }、
c:forTokens>
<br /> 拆分结果:<br />
<c:forTokens items="1;2;3;4;5;6;7;8" delims=";" var="con">
${con }、
c:forTokens>
将其他页面的内容包含起来一起显示,和
标签的功能类似,但是与
标签不同的是:
可以包含外部项目的页面,语法:
<c:import url="包含地址的url" [context="上下文路径"] [var="保存内容的属性名称"] [scope=["page|request|session|application"]] [charEncoding="字符集"] [varReader="以Reader方式"]>
标签体内容
[<c:param name="参数名称" value="参数内容" />]
c:import>
例(包含百度的页面):
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core" %>
<c:import url="http://www.baidu.com" charEncoding="utf-8">c:import>
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
name参数:${param.name}<br />
url参数:${param.url}<br />
c_import_param.jsp
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<c:import url="param.jsp" charEncoding="utf-8">
<c:param name="name" value="JSON">c:param>
<c:param name="url" value="www.io.cn">c:param>
c:import>
该标签可以直接产生一个URL地址,语法:
<c:url value="操作的url" [context="上下文路径"] [var="保存的属性名称"] [scope="[page|request|session|aplication]"] />
<c:url value="操作的url" [context="上下文路径"] [var="保存的属性名称"] [scope="[page|request|session|aplication]"]>
<c:param name="参数名" value="参数值">c:param>
c:url>
基于这个语法,我们可以在自己的页面中调用百度搜索。
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<c:url value="http://www.baidu.com/s" var="urlinfo">
<c:param name="ie" value="utf-8">c:param>
<c:param name="wd" value="关键字">c:param>
c:url>
<a href="${urlinfo }">调用百度搜索a>
进行客户端跳转,相当于response.sendRedect(String url)
。语法:
<c:redirect url="跳转地址" context="上下文路径" />
<c:redirect url="跳转地址" context="上下文路径">
<c:param name="参数名" value="参数值">c:param>
c:redirect>
例:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<c:redirect url="param.jsp">
<c:param name="name" value="Tom">c:param>
<c:param name="url" value="baidu.com">c:param>
c:redirect>
设定用户所在区域。语法:
<fmt:setLocale value="区域编码" [variant="浏览器"] [scope="[page|request|session|application]"]/>
例:以不同的语言显示日期信息;
<%@ taglib prefix="fmt" uri="http://127.0.0.1/javaweb/jstl/fmt"%>
<%
pageContext.setAttribute("date", new Date());
%>
中文日期显示:<fmt:setLocale value="zh_CN"/><fmt:formatDate value="${date }"/><br />
英文日期显示:<fmt:setLocale value="en_US"/><fmt:formatDate value="${date }"/><br />
设置请求的编码,相当于request.setCharacterEncoding()
,语法:
<fmt:requestEncoding value="字符集"/>
在国际化程序中最重要的部分就是资源文件的读取,在JSTL中提供了4个标签用于资源文件的读取和操作。
、
、
、
。
所有的资源文件都是以*.properties
为后缀的,所有的内容按照“key=value”的格式进行编写。在web中,资源文件要保存在/WEB-INF/classes目录中(因为它在classpath中)。
属性文件/WEB-INF/classes/Message.properties
name=Tom
info=\u6B22\u8FCE{0}\u5149\u4E34
上面的info中有中文,进行了转码操作({0}表示占位符)。
绑定需要读取的资源文件名称。语法:
<fmt:bundle basename="资源文件名称(不要后缀)" [prefix="前置标记"]>
标签体内容
fmt:bundle>
当通过
指定好了资源文件名称后,就可以使用
标签按照key读取value,语法:
<fmt:message key="资源文件的key" [bundle="资源文件名称"] [var="存储内容的属性名称"] [scope="[page|request|session|application]"] />
<fmt:message key="资源文件的key" [bundle="资源文件名称"] [var="存储内容的属性名称"] [scope="[page|request|session|application]"]>
<fmt:param value="设置占位符内容" />
fmt:message>
例:输出属性文件中的内容,并用动态文本替换占位符。
<%@ taglib prefix="fmt" uri="http://127.0.0.1/javaweb/jstl/fmt"%>
<fmt:bundle basename="Message">
<fmt:message key="name" var="nameref"/>
fmt:bundle>
姓名:${nameref }<br />
<fmt:bundle basename="Message">
<fmt:message key="info" var="inforef">
<fmt:param>杰克fmt:param>
fmt:message>
fmt:bundle>
信息:${inforef }
在进行资源文件的读取的时候也可以通过
标签设置一个默认的读取资源名称,这样每次使用
进行信息的读取的时候,直接通过bunle设置读取的资源的属性即可。语法:
<fmt:setBundle basename="资源文件名称" [var="保存资源文件的内容的变量"] [scope="[page|request|session|application]"]/>
例:
<%@ taglib prefix="fmt" uri="http://127.0.0.1/javaweb/jstl/fmt"%>
<fmt:setBundle basename="Message" var="msg"/>
<fmt:message key="name" var="nameref" bundle="${msg}"/>
<fmt:message key="info" var="inforef" bundle="${msg}">
<fmt:param>杰克逊fmt:param>
fmt:message>
姓名:${nameref }<br />
信息:${inforef }
fmt:formatNumber
格式化数字,fmt:parseNumber
反格式化数字。
例(格式化和反格式化数字):
<%@ taglib prefix="fmt" uri="http://127.0.0.1/javaweb/jstl/fmt"%>
<fmt:formatNumber value="351569.3256" maxFractionDigits="3" groupingUsed="true" var="num1">fmt:formatNumber>
<fmt:formatNumber value="351569.3256" pattern="##.###E0" var="num2">fmt:formatNumber>
格式化数字:${num1 }<br />
科学计数法:${num2 }<br />
<hr />
<fmt:parseNumber value="2,256,123.528925" var="num3">fmt:parseNumber>
<fmt:parseNumber value="1.496E12" pattern="#.###E0" var="num4">fmt:parseNumber>
<fmt:parseNumber value="3.5%" pattern="00%" var="num5">fmt:parseNumber>
反格式化数字:${num3 }<br />
反科学计数法:${num4 }<br />
反百分比:${num5 }<br />
<%@ taglib prefix="fmt" uri="http://127.0.0.1/javaweb/jstl/fmt"%>
<%
pageContext.setAttribute("dateref", new Date());
%>
<fmt:formatDate value="${dateref }" type="both" dateStyle="default" timeStyle="default" var="date"/>
default显示日期时间:${date }<br />
<fmt:formatDate value="${dateref }" type="both" dateStyle="short" timeStyle="short" var="date"/>
short显示日期时间:${date }<br />
<fmt:formatDate value="${dateref }" type="both" dateStyle="long" timeStyle="long" var="date"/>
long显示日期时间:${date }<br />
<fmt:formatDate value="${dateref }" type="both" dateStyle="full" timeStyle="full" var="date"/>
full显示日期时间:${date }<br />
<fmt:formatDate value="${dateref }" type="both" pattern="Gyyyy年MM月dd日 HH:mm:ss.SSS EE z Z" var="date"/>
自定义格式显示日期时间:${date }<br />
<hr />
<fmt:parseDate value="公元2015年05月04日 21:08:59.425 星期一 CST +0800" type="both" pattern="Gyyyy年MM月dd日 HH:mm:ss.SSS EE z Z" var="date">fmt:parseDate>
字符串变为日期:${date }<br />
<fmt:parseDate value="2015年5月4日 星期一 下午09时12分03秒 CST" type="both" dateStyle="full" timeStyle="full" var="date">fmt:parseDate>
字符串变为日期:${date }<br />
<fmt:timeZone value="GMT+8">
<fmt:formatDate value="${dateref }" type="both" timeStyle="full" dateStyle="full" var="date1"/>
fmt:timeZone>
<fmt:timeZone value="GMT-10">
<fmt:formatDate value="${dateref }" type="both" timeStyle="full" dateStyle="full" var="date2"/>
fmt:timeZone>
<fmt:timeZone value="GMT">
<fmt:formatDate value="${dateref }" type="both" timeStyle="full" dateStyle="full" var="date3"/>
fmt:timeZone>
北京时间:${date1 }<br />
夏威夷时间:${date2 }<br />
格林尼治时间:${date3 }<br />
JSTL标签本省的功能非常强大,基本上所有的功能都包含了。但是从MVC设计模式上来讲:在JSP页面中直接操作SQL语句纯粹属于业余人士。
WebRoot/META-INF/context.xml中已经配置了一个Tomcat数据源(名称为jdbc/mldn):
<Context>
<Resource name="jdbc/mldn"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="mysqladmin"
driverClassName="org.gjt.mm.mysql.Driver"
url="jdbc:mysql://localhost:3306/mldn?characterEncoding=utf8"/>
Context>
<%@ taglib prefix="sql" uri="http://127.0.0.1/javaweb/jstl/sql"%>
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<sql:setDataSource dataSource="jdbc/mldn" var="mldnds"/>
<sql:query var="result" dataSource="${mldnds }" maxRows="2" startRow="2">
SELECT empno,ename,job,hiredate,sal FROM emp
sql:query>
一共有${result.rowCount }条记录!<br />
<table border="1">
<tr>
<th>雇员编号th>
<th>雇员姓名th>
<th>雇员职位th>
<th>雇佣日期th>
<th>雇员工资th>
tr>
<c:forEach items="${result.rows }" var="row">
<tr>
<td>${row.empno}td>
<td>${row.ename}td>
<td>${row.job}td>
<td>${row.hiredate}td>
<td>${row.sal}td>
tr>
c:forEach>
table>
可以向数据库中插入记录或者删除记录。
<%@ taglib prefix="sql" uri="http://127.0.0.1/javaweb/jstl/sql"%>
<sql:setDataSource dataSource="jdbc/mldn" var="mldnds"/>
<sql:update var="result" dataSource="${mldnds }">
INSERT emp VALUES(1111,'岳飞','usecase','2015-02-02',5523.3 )
sql:update>
<sql:update var="result" dataSource="${mldnds }">
DELETE FROM emp WHERE empno=1111
sql:update>
使用预处理的方式(SQL语句中可以使用?进行占位符)完成数据库的CRUD操作。
<%@ taglib prefix="sql" uri="http://127.0.0.1/javaweb/jstl/sql"%>
<sql:setDataSource dataSource="jdbc/mldn" var="mldnds"/>
<sql:update var="result" dataSource="${mldnds }">
UPDATE emp SET ename=?,job=?,hiredate=?,sal=? WHERE empno=?
<sql:param value="明月"/>
<sql:param value="分析师"/>
<sql:param value="1999-09-09"/>
<sql:param value="2500.6"/>
<sql:param value="1000"/>
sql:update>
<%@ taglib prefix="sql" uri="http://127.0.0.1/javaweb/jstl/sql"%>
<sql:setDataSource dataSource="jdbc/mldn" var="mldnds"/>
<sql:transaction isolation="serializable" dataSource="${mldnds }">
<sql:update>
INSERT emp VALUES(1111,'碧瑶','魔教','1993-07-19',8888.88)
sql:update>
sql:transaction>
XPath简介
在xml文档中能够准确找到某一个节点元素,可以通过XPath找到一个XML文档中定义的节点内容或者属性。
XPath路径标记
路径标记 | 描述 |
---|---|
根元素 | / |
父元素 | ../ |
任何路径下的节点 | // |
属性 | @属性名称 |
通配符 | * |
例如有以下的xml文件:
<bookstore>
<book id="1">
<name>冰与火之歌name>
<author>乔治马丁author>
<year>2014year>
<price>89price>
book>
bookstore>
完成xml文件的解析。语法:
<x:parse [doc="xml文件"] [var="保存名称"] [scope="[page|request|session|application]"] [varDom="DOM解析后的xml对象"] [scopeDom="varDom范围"] [systemId="xml文件的URI"] />
<x:parse [var="保存名称"] [scope="[page|request|session|application]"] [varDom="DOM解析后的xml对象"] [scopeDom="varDom范围"] [systemId="xml文件的URI"] >
要解析的xml文件
x:parse>
完成xml文档的输出,输出时要通过xpath进行指定。
<x:out select="XPath路径" [escapeXml="[true|false]" />
例:将以上的xml文档的内容输出:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<%@ taglib prefix="x" uri="http://127.0.0.1/javaweb/jstl/x"%>
<c:import url="books.xml" charEncoding="utf-8" var="books">c:import>
<x:parse doc="${books }" var="booksXml">x:parse>
书名:<x:out select="$booksXml/bookstore/book/name"/>
编号:<x:out select="$booksXml/bookstore/book/@id"/>
作者:<x:out select="$booksXml/bookstore/book/author"/>
年份:<x:out select="$booksXml/bookstore/book/year"/>
价格:<x:out select="$booksXml/bookstore/book/price"/>
将从xml文件中读取出来的内容保存到指定的属性范围之中。语法:
<x:set select="XPath路径" var="属性保存名称" [scope="[page|request|session|application]"] />
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<%@ taglib prefix="x" uri="http://127.0.0.1/javaweb/jstl/x"%>
<c:import url="books.xml" charEncoding="utf-8" var="books">c:import>
<x:parse doc="${books }" var="booksXml">x:parse>
<x:set var="nameXml" select="$booksXml/bookstore/book" scope="page"/>
书名:<x:out select="$nameXml/name"/>
判断Xpath指定内容是否符合判断条件。语法:
<x:if select="XPath路径" var="存放判断结果" [scope="[page|request|session|application]"] />
<x:if select="XPath路径" var="存放判断结果" [scope="[page|request|session|application]"] >
条件满足时输出
x:if>
例如,判断xml文档中是否有某个属性:
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<%@ taglib prefix="x" uri="http://127.0.0.1/javaweb/jstl/x"%>
<c:import url="books.xml" charEncoding="utf-8" var="books">c:import>
<x:parse doc="${books }" var="booksXml">x:parse>
<x:if select="$booksXml//book/@id='1'">
存在编号为1的书
x:if>
除了判断是否存在某个属性还可以判断是否存在特定的元素内容。
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<%@ taglib prefix="x" uri="http://127.0.0.1/javaweb/jstl/x"%>
<c:import url="books.xml" charEncoding="utf-8" var="books">c:import>
<x:parse doc="${books }" var="booksXml">x:parse>
<x:choose>
<x:when select="$booksXml//book/@id='1'">
存在编号为1的书
x:when>
<x:otherwise>
不存在编号为1的书
x:otherwise>
x:choose>
完成xml文件的迭代输出。语法:
<x:forEach select="XPath路径" [var="保存结果"] [varStatus="保存变量信息"] [begin="开始位置"] [end="结束位置"] [step="步长"]>
标签体内容
x:forEach>
例:迭代输出以下xml文件的内容:
<bookstore>
<book id="1">
<name>冰与火之歌name>
<year>2014year>
<price>89price>
book>
<book id="2">
<name>安徒生童话name>
<year>2004year>
<price>29price>
book>
<book id="3">
<name>名侦探柯南name>
<year>2044year>
<price>75price>
book>
bookstore>
<%@ taglib prefix="c" uri="http://127.0.0.1/javaweb/jstl/core"%>
<%@ taglib prefix="x" uri="http://127.0.0.1/javaweb/jstl/x"%>
<c:import url="books.xml" charEncoding="utf-8" var="books">c:import>
<x:parse doc="${books }" var="booksXml">x:parse>
<x:forEach select="$booksXml//book" var="book">
编号:<x:out select="@id"/><br />
书名:<x:out select="name"/><br />
年份:<x:out select="year"/><br />
价格:<x:out select="price"/><br />
<hr />
x:forEach>
正经的开发中xml文件的解析应该放在后台进行。
函数标签库的使用和其他的标准标签库不同(不是采用的类似于xml文件的输出),而是采用类似于表达式语言的输出。
其实函数标签库就是对String
类的包装。例:
<%@ taglib prefix="fn" uri="http://127.0.0.1/javaweb/jstl/fn"%>
<%
pageContext.setAttribute("info", "Hello java,Hello Tom");
%>
字符串:${info}<br />
<hr />
字符串中是否存在java:${fn:contains(info,"java") }<br />
字符串中是否存在JAVA(忽略大小写):${fn:containsIgnoreCase(info,"JAVA") }<br />
字符串是否以Hello开否:${fn:startsWith(info,"Hello") }<br />
字符串是否以Tom开否:${fn:endsWith(info,"Tom") }<br />
java的位置:${fn:indexOf(info,"java") }<br />
<hr />
替换:${fn:replace(info,"Hello","yes") }<br />
截取:${fn:substring(info,0,10) }<br />
拆分:${fn:split(info," ")[0] }<br />
AJAX技术的核心操作对象。该对象的属性:
属性 | 描述 |
---|---|
onreadystatechange | 指定当readState状态改变时使用的操作,一般用于指定具体的回调函数 |
readyState | 返回当前的请求状态(只读) |
responseBody | 将回应信息正文以unsigned byte数组的形式返回(只读) |
responseStream | 以Ado Stream对象的形式返回响应信息(只读) |
responseText | 接收以普通文本返回的数据(只读) |
responseXML | 接收以XML文档形式回应的数据(只读) |
status | 返回当前请求的http状态码(只读) |
statusText | 返回当前请求的响应行状态(只读) |
readyState取值(5种)
XMLHttpRequest对象的方法
方法 | 描述 |
---|---|
abort() | 取消当前所发出的请求 |
getAllResponseHeaders() | 取得所有的Http头信息 |
getResponseHeader() | 取得一个特定的Http头信息 |
open() | 创建一个Http请求,并制定请求模式(get或者post) |
send() | 将创建的请求发送到服务器端,并接受回应信息 |
setRequestHeader() | 设置一个特定请求的Http头信息 |
接受异步请求的页面ajax_receive_content.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax_receive_contenttitle>
<script>
var xmlHttp;
// 创建AJAX
function createXMLHttp () {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); // FF,Chrome
}else{
xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); // IE
}
}
function showMsg(){
createXMLHttp(); // 创建XHR
xmlHttp.open("post","content.html"); // 创建Http请求(指定请求方式和请求的url)
xmlHttp.onreadystatechange = showMsgCallBack; // 设置操作的回调函数
xmlHttp.send(null); // 将请求发送到Server接收回应信息
}
// 回调函数
function showMsgCallBack(){
/* 响应完成,并且Http状态码为200 */
if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
var text = xmlHttp.responseText; // 响应的是普通文本(还可以是xml)
document.getElementById('msg').innerHTML = text;
}
}
script>
head>
<body>
<input type="button" onClick="showMsg()" value="调用AJAX显示内容" />
<span id="msg">span>
body>
html>
content.html
Hello AJAX
AJAX必须在服务器端使用,content.html
中存在的内容要通过AJAX异步返回到调用处。
在进行用户注册的时候必须保障用户的用户名是唯一的,用户输入用户名之后(文本框失去焦点触发ajax)就可以利用ajax来进行验证用户的id是否合法。
reg.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxtitle>
<script>
var xmlHttp;
var flag = false; // 表单是否提交
function createXMLHttp () {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); // FF,Chrome
}else{
xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); // IE
}
}
function checkUsername(username){
createXMLHttp(); // 创建XHR
xmlHttp.open("post", "CheckServlet?username=" + username);
xmlHttp.onreadystatechange = checkUsernameCallback;
xmlHttp.send(null);
document.getElementById('msg').innerHTML = '正在提交验证。。。'; // 网速慢的时候会显示这句话
}
function checkUsernameCallback(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var text = xmlHttp.responseText;
if(text=="true"){
document.getElementById('msg').innerHTML = '用户名已存在!';
flag = false;
}else{
document.getElementById('msg').innerHTML = '此用户名有效!';
flag = true;
}
}
}
/* 当用户名重复的时候不提交表单 */
function checkForm(){
return flag;
}
script>
head>
<body>
<form method="post" onsubmit="return checkForm()">
用户名:<input type="text" name="username" onblur="checkUsername(this.value)" /><span id='msg'>span><br />
密码:<input type="text" name="password" /><br />
<input type="submit" value="提交" />
<input type="reset" value="重置" />
form>
body>
html>
检验用户名是否重复的Servlet
public class CheckServlet extends HttpServlet {
// 数据库驱动程序和数据库URL、用户名、密码的字符串常量
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html");
String username = request.getParameter("username");
PrintWriter out = response.getWriter();
try {
Class.forName(DB_DRIVER);
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
String sql = "SELECT COUNT(username) FROM user WHERE username = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
if (rs.getInt(1)>0) { // 用户名已存在
out.print("true");
}else {
out.print("false");
}
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
假设有以下的allarea.xml
:
<allarea>
<area>
<id>1id>
<title>北京title>
area>
<area>
<id>2id>
<title>天津title>
area>
<area>
<id>3id>
<title>南京title>
area>
allarea>
页面加载的时候将xml文档中的数据异步加载到页面。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax_receive_contenttitle>
<script>
var xmlHttp;
// 创建AJAX
function createXMLHttp () {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); // FF,Chrome
}else{
xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); // IE
}
}
function getCity(){
createXMLHttp();
xmlHttp.open("post", "allarea.xml");
xmlHttp.onreadystatechange = getCityCallback;
xmlHttp.send(null);
}
function getCityCallback(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var allarea = xmlHttp.responseXML.getElementsByTagName('area'); // 取得所有的area节点
var select = document.getElementById("city") ; // 取得下拉列表框
//select.lenght = 1; // 每次选择一个
//select.options[0].selected = true; // 第1个为选中状态
/* 遍历每一个area节点 */
for(var i = 0;i < allarea.length; i++){
var area = allarea[i]; // 取得每一个area节点
var id = area.getElementsByTagName('id')[0].textContent; // 取得xml中的id和title
var title = area.getElementsByTagName('title')[0].firstChild.nodeValue;
var option = document.createElement('option'); // 创建一个选项
option.setAttribute("value",id); // 选项添加属性和文本节点
option.appendChild(document.createTextNode(title));
select.appendChild(option); // 将选项作为列表框的子节点追加在末尾
}
}
}
script>
head>
<body onload="getCity()">
<form action="" method="post">
请选择喜欢的城市:
<select name="city" id="city">
<option value="0">-- 请选择喜欢的城市 --option>
select>
form>
body>
html>
通过Servlet在内存中生成DOM Tree,页面加载的时候异步加载内存中的XML文档在页面输出。
XHR提交的Servlet:CityServlet
public class CityServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/xml;charset=utf-8");
PrintWriter out = response.getWriter();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 文档向内存中输出
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.newDocument();
String[] data = {"北京","天津","上海","广州","武汉","香港","南京"};
Element allarea = doc.createElement("allarea"); // 创建根元素
for (int i = 0; i < data.length; i++) {
Element area = doc.createElement("area");
Element id = doc.createElement("id");
Element title = doc.createElement("title");
id.appendChild(doc.createTextNode(i + 1 + ""));
title.appendChild(doc.createTextNode(data[i]));
area.appendChild(id);
area.appendChild(title);
allarea.appendChild(area);
}
doc.appendChild(allarea);
// 输出
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.ENCODING, "gbk"); // 这里设置为utf-8会乱码
tf.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(baos);
tf.transform(source, result);
System.out.println(baos);
out.println(baos);
out.close();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
}
异步加载的页面:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax_receive_contenttitle>
<script>
var xmlHttp;
// 创建AJAX
function createXMLHttp () {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); // FF,Chrome
}else{
xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); // IE
}
}
function getCity(){
createXMLHttp();
xmlHttp.open("post", "CityServlet");
xmlHttp.onreadystatechange = getCityCallback;
xmlHttp.send(null);
}
function getCityCallback(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var allarea = xmlHttp.responseXML.getElementsByTagName('area'); // 取得所有的area节点
var select = document.getElementById("city") ; // 取得下拉列表框
//select.lenght = 1; // 每次选择一个
//select.options[0].selected = true; // 第1个为选中状态
/* 遍历每一个area节点 */
for(var i = 0;i < allarea.length; i++){
var area = allarea[i]; // 取得每一个area节点
var id = area.getElementsByTagName('id')[0].textContent; // 取得xml中的id和title
var title = area.getElementsByTagName('title')[0].firstChild.nodeValue;
var option = document.createElement('option'); // 创建一个选项
option.setAttribute("value",id); // 选项添加属性和文本节点
option.appendChild(document.createTextNode(title));
select.appendChild(option); // 将选项作为列表框的子节点追加在末尾
}
}
}
script>
head>
<body onload="getCity()">
<form action="" method="post">
请选择喜欢的城市:
<select name="city" id="city">
<option value="0">-- 请选择喜欢的城市 --option>
select>
form>
body>
html>
在以上的代码中我们可以发现前台的代码仅仅更改了一个XHR的请求的URL就可以实现动态加载XML文件。通过XML实现了网站的前端和后台的分离。