JSTL1.1 不是JSP2.0规范的一部分!你能访问Servlet和JSP API 不意味着你能访问JSTL!
使用JSTL之前,需要将两个文件("jstl.jar" 和 "standard.jar")放在自己Web应用的WEB-INF/lib目录中。
将Html标记以纯文本显示出来,而不是解释标记渲染页面:<c:out />
1 <c:out value='${pageContent.rawHTML}' escapeXml='false' /> //escapeXml=false,所有的Html标记都会得到计算,而不是作为文本显示 2 <c:out value='${pageContent.currentTip}' escapeXml='true' /> //escapeXml=true,则所有的Html标记都是以纯文本显示出来,escapeXml默认值为true
使用<c:out />标记来输出所有的用户串,可以避免跨网站攻击或跨网站脚本攻击
给<c:out />标记提供一个默认值:
1 <b>Hello <c:out value='${user}' default='guest' />.</b> //当value计算结果为null时,就会输出默认值。这是<c:out />标记的优势,因为EL和JSP表达式当计算结果为null时,只能打印一个空格
实现循环:<c:forEach />
1 <table> 2 <c:forEach var="movie" items="${movieList}"> //将movieList集合中的每一个元素依次赋给变量movie,然后打印到表格中 3 <tr> 4 <td>${movie}</td> 5 </tr> 6 </c:forEach> 7 </table>
可选参数varStatus
1 <table> 2 <c:forEach var="movie" items="${movieList}" varStatus="movieLoopCount" > 3 <tr> 4 <td>Count: ${movieLoopCount.count}</td> //varStatus参数的count属性,打印计数器的当前值 5 <tr> 6 <tr> 7 <td>${movie}</td> 8 </tr> 9 </c:forEach> 10 </table>
<c:forEack />标记还可以进行嵌套:
servlet代码:
1 String[] movies1 = {"Matrix Revolutions", "Kill Bill", "Boondock Saints"}; 2 String[] movies2 = {"Amelie", "Return of the King", "Mean Girls"}; 3 java.util.List movieList = new java.util.List ArrayList(); 4 movieList.add(movies1); 5 movieList.add(movies2); 6 7 request.setAttribute("movieList", movieList);
JSP:
1 <table> 2 <c:forEach var="listElement" items="${movieList}"> //外部循环,将movieList数组列表中的元素(一共2个元素)赋给listElement 3 <c:forEach var="movie" items="${listElement}"> //内部循环,依次获取外部循环的元素listElement,将listElement中的元素赋给movie,打印到表格中 4 <tr> 5 <td>${movie}</td> 6 </tr> 7 </c:forEach> 8 </c:forEach> 9 </table>
使用<c:if />完成条件包含:
同一个页面,注册用户和非注册用户看到的内容不一样。注册用户能添加评论。
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 3 <c:if test="${userType eq 'member'}"> 4 <jsp:include page="inputComments.jsp"/> 5 </c:if>
如果一个if不行,需要else,可以用<c:choose/>标记
1 <c:choose> 2 <c:when test="${userPref == 'performance'}"> 3 Now you can stop even if you <em>do</em> drive insanely fast. 4 </c:when> 5 6 <c:when test="${userPref == 'safety'}"> 7 Our brakes will never lock up, no matter how bad a driver you are. 8 </c:when> 9 10 <c:when test="${userPref == 'maintenance'}"> 11 Lost your tech job? No problem--you won't have to service these brakes for at least three years. 12 </c:when> 13 14 <c:otherwise> 15 Our brakes are the best. 16 </c:otherwise> 17 </c:choose>
<c:set />
<jsp:setProperty>标记只能做一件事情,就是设置bean的性质。
<c:set/>标记可以做得更多。<c:set/>有两个版本:var版本和target版本。两个版本又都有两种形式:有体和没体。
var版本:
1 <c:set var="userLevel" scope="session" value="Cowboy"/> 2 3 <c:set var="Fido" value="${person.dog}"/> 4 5 <c:set var="userLevel" scope="session"> //有体 6 Sheriff, Bartendar, Cowgirl 7 </c:set>
target版本:
1 <c:set target="${PetMap}" property="dogName" value="Clover" /> 2 3 <c:set target="${person}" property="name"> //有体 4 ${foo.name} 5 </c:set>
使用<c:remove/>标记删除一个变量
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <html><body> 3 4 <c:set var="userStatus" scope="request" value="Brilliant" /> 5 6 userStatus: ${userStatus} <br> 7 8 <c:remove var="userStatus" scope="request" /> //scope是可选的,但是如果没有指定scope,就会从所有作用域中删除userStatus属性 9 10 userStatus is now: ${userStatus} 11 12 </body></html>
使用<c:import/>标记包含内容:
之前已经知道了两种:<%@ include file="xx.jsp" %>include指令 <jsp:include page="xx.jsp" />include动作
现在再学一招:<c:import />JSTL标记
1 <c:import url="http://www.wickedlysmart.com/skyler/horse.html" /> //动态:在请求时,将URL属性指定的内容增加到当前页面。它与<jsp:include/>相似,但是更强大、更灵活。
使用<%@ include file="xx.jsp">或者<jsp:include page="xx.jsp" />只能包含当前Web应用之内的页面。但是<c:import />还可以把容器之外的内容包含进来。
还有<c:param/>标记:
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <html><body> 3 4 <c:import url="Header.jsp"> 5 <c:param name="subTitle" value="We take the sting out of SOAP." /> 6 </c:import> 7 8 <br> 9 10 <em>Welcome to our Web Services Support Group.</em><br><br> 11 Contact us at : ${initParam.mainEmail} 12 </body></html>
<c:url/>标记可以满足所有超链接需求:
客户禁用cookie后,容器会自动地完成URL重写。但是如果使用Servlet,还必须对URL编码:
1 //Servlet的URL重写 2 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ 3 response.setContentType("text/html; charset=utf-8"); 4 PrintWriter out = request.getWriter(); 5 HttpSession session = request.getSession(); 6 7 out.println("<html><body>"); 8 out.println("<a href=\"" + response.encodeURL("/BeerTest.do") + "\">click</a>"); //在Java中写Html真的是很麻烦 9 out.println("</body></html>"); 10 }
那如果使用<c:url/>标记呢:
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <html><body> 3 4 This is a hyperlink with URL rewriting enabled. 5 6 <a href="<c:url value='/inputComments.jsp'/>"Click here</a> 7 8 </body></html>
<c:url />标记所做的只是URL重写,URL通常都需要编码:
1 <c:url value="/inputComments.jsp" var="inputURL"> 2 <c:param name="firstName" value="${first}" /> //现在<c:param>标记负责对URL进行编码工作 3 <c:param name="lastName" value="${last}" /> 4 </c:url>
建立自己的错误页面:(errorPage)
让发生的错误对用户更加友好!而不是显示一堆跟踪错误(自己都不想看)
1 <%@ page isErrorPage="true" %> //向容器做出确认,这个是正式的错误页面 2 <html><body> 3 <strong>Bummer.</strong> 4 <img src="images/bummerGuy.jpg" /> 5 </body></html>
1 <%@ page errorPage="errorPage.jsp" %> //告诉容器,出问题了就把请求转发到errorPage.jsp 2 <html><body> 3 About to be bad... 4 <% int x = 10 / 0; %> 5 </body></html>
那么问题来了,要给一个一个的JSP加上<%@ page errorPage="errorPage.jsp" %>也是很麻烦的!
可以使用<error-page>DD标记,为整个Web应用配置错误页面:(<%@ page errorPage="errorPage.jsp" %>优先级高于DD中的<error-page>标记)
在DD(web.xml)中,可以根据<exception-type>或HTTP状态码<error-code>声明错误页面。
1 <error-page> 2 <exception-type>java.lang.Throwable</exception-type> //普通的错误 3 <location>/errorPage.jsp</location> 4 </error-page> 5 6 <error-page> 7 <exception-type>java.lang.ArithmeticException</exception-type> //更加明确的错误 8 <location>/arithmeticError.jsp</location> 9 </error-page> 10 11 <error-page> 12 <error-code>404</error-code> //404错误 13 <location>/notFoundError.jsp</location> //<location>必须以/开头,无论<exception-type>还是<error-code> 14 </error-page>
错误页面得到一个额外的对象:exception:
错误页面实际上就是处理异常的JSP,所以容器为这个页面提供了一个额外的exception对象。exception隐式对象只对错误页面可用(有明确定义的page指令:<%@ page isErrorPage="true" %>)
1 <%@ page isErrorPage="true" %> 2 <html><body> 3 <strong>Bummer.</strong><br> 4 5 You caused a ${pageContext.exception} on the server.<br> //这样会得到更加明确的错误类型,因为调用了exception隐式对象 6 7 <img src="images/bummerGuy.jpg" /> 8 </body></html>
<c:catch />标记 —— 就像try/catch.......
<c:catch />标记,把有风险的标记或表达式包起来。因为倘若不这样,就会抛出异常,默认的错误处理机制就会插手!
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <%@ page errorPage="errorPage.jsp" %> //这是一个正式指定了错误页面,可以使用exception隐式对象 3 <html><body> 4 5 About to do a risky thing: <br /> 6 7 <c:catch> 8 <% int x = 10 / 0; %> //一个可预见的错误 9 </c:catch> 10 11 If you see this, we survived. //因为使用了<c:catch>标记,遇到异常立即跳过,所以我们得救了 12 13 </body></html>
理解TLD:(Tag Library Descriptor,TLD,标记库描述文件)
标记库描述文件TLD,描述了两个主要内容:定制标记和EL函数。
1.TLD,标记库描述文件可以放到WEB-INF的任何子目录中去!
2.在部署描述文件(DD,web.xml)中使用<taglib>元素定义TLD(标记库描述文件)
1 <taglib> 2 <taglib-uri>myTags</taglib-uri> 3 <taglib-location>/WEB-INF/myTags.tld</taglib-location> 4 </taglib>