JSP技术
2012年04月11日


1、include动作指令和jsp:include标签的使用

特别注意其路径的书写方式。我相信有90%的程序员都会忽略一个细节:
以include动作指令为例,写法有二
<%@ include file="/WEB-INF/views/common/taglibs.jsp"%>
<%@ include file="../common/taglibs.jsp"%>
第一种是绝对路径,第二种是相对路径。这两种写法都正确。

再看看html标签中的写法,以css文件的引入为例:
<link href="../resources/css/reset.css" rel="stylesheet" type="text/css" /> 正确
<link href="/resources/css/reset.css" rel="stylesheet" type="text/css" /> 错误
<link href="/project/resources/css/reset.css" rel="stylesheet" type="text/css" /> 正确
<link href="http://localhost:8080/project/resources/css/reset.css" rel="stylesheet" type="text/css" /> 正确
<link href="<%=request.getContextPath()%>/resources/css/reset.css" rel="stylesheet" type="text/css" /> 正确
<link href="<c:url value='/resources/css/reset.css' />" rel="stylesheet" type="text/css"  /> 正确

其中,第二种用法是错误的,相对的,第三种用法才正确。

但是,我们再看看下面的几种写法:
<%@ include file="http://localhost:8080/project/WEB-INF/views/common/taglibs.jsp"%>
<%@ include file="/project/WEB-INF/views/common/taglibs.jsp"%>
<%@ include file="<%=request.getContextPath()%>/WEB-INF/views/common/taglibs.jsp"%>
<%@ include file="<c:url value='/WEB-INF/views/common/taglibs.jsp' />"%>

思考……………………

然后,再看看上面include的写法,谁能告诉我上面几种写法的正误

总结:
我们知道大部分情况下写在页面(不管静态还是动态)里并输出到IE中的路径都是由IE来解析的,以“/”开头的绝对路径 这个“/”代表的是服务器的根目录:比如访问URL为 http://localhost:8080/项目名/templates/template.jsp
那么“/”代表的就是 "http://localhost:8080/" 而并不带有项目名信息。

而<jsp:include>引入页面的过程,是在服务器运行向IE输出数据的过程中由JAVA程序调用执行,路径也当然由JAVA程序来解析,此时以"/"开头的绝对路径中的“/” 代表的已经是本项目的根目录了。
比如 URL为 http://localhost:8080/项目名/templates/template.jsp
那么“/”代表的就是 "http://localhost:8080/项目名/"。已经带有了项目名信息。

同时,也不用像引入JS CSS文件那样在路径前加上 <%=request.getContextPath()%> 来解决项目名本身修改的问题了。只需一个“/”就什么也不用管了。 


问题:怎么获取List的某个值?
答:用EL表达式,[]括号,${aList[i]}
${alist.get(0)}


JSTL 实现if-else的方法:
<c:choose>
 <c:when test="${task.status==0 }">
  IIII IF
 </c:when>
 <c:otherwise >
  EEEE ESLE
 </c:otherwise >
</c:choose>

JSTL和struts标签循环遍历数字的方法:
<c:forEach begin="0" end="9" var="i">${i}</c:forEach>
<s:iterator value="new int[10]" status="i">
 <s:property value="#i.index"/>
</s:iterator>

<s:bean name="org.apache.struts2.util.Counter" id="counter">  
 <s:param name="first" value="1" />  
 <s:param name="last" value="%{#number}" />  
 <s:iterator>  
 <option value="<s:property value="current-1"/>" <s:if test="current-1==begin">selected</s:if> ><s:property value="current-1"/></option>
 </s:iterator>  
</s:bean>


页面查找List中元素的方法:
 var refundReason = "<s:property value="refundConfig.refundReason" />";
  var reasonArray = refundReason.split(",");
  $.each(reasonArray, function(index, value){
   var id = "#"+value;
         $(id).attr("checked","checked");
  });

<input name="refundReason" type="checkbox"id='<s:property value="#reason.key"/>

     
<s:if test="#reason.key in refundReasonSet">checked</s:if>
<s:if test="#reason.key in refundReasonList">checked</s:if>
<s:if test="refundReasonList.contains(#reason.key)">checked</s:if>
<s:if test="refundReasonSet.contains(#reason.key)">checked</s:if>

<!-- s:if test="refundConfig.refundReason.indexOf(#reason.key)>=0">checked</s:if -->


JSTL格式化时间:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatDate value="${task.createTime}" pattern="yyyy-MM-dd HH:mm:ss"/>



二、JSP基础

1、语法

变量声明<%!……%>

       注意:在JSP内定义函数时,要放在<%!……%>内,否则可能会出错。

JSP Scriptlets语法<%……%>

服务器端注释<%--……--%>

 

2JSP指令元素<%@……%>

1page指令

常用属性language,contenType,import,extends,session,info,isErrorPage等。

例如<%@ page language="java" contenType="text/html;charset=gb2312" %>

2include指令

语法格式为<%@ include file="地址" %>,这种包含属于编译前包含。

3taglib指令

声明自定义标签,语法格式为<%@ taglib uri="URI" prefix="tagPrefix" %>例如

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

3JSP动作元素(单标签或者配对的标签)

1<jsp:include>动作元素

语法为:<jsp:include page="URL" flush="true|false">

可以包含txthtmljsp文件,与include指令元素不同的是,对于静态文件它是编译后在包含,所以txt文件中的jsp代码执行不了。

 

2<jsp:forward>

用法例如:<jsp:forward page="text.jsp"></jsp:forward>属于服务器端跳转。

 

3<jsp:param>

用法为:<jsp:param name="" value=""/>通常配合跳转的jsp:forward和包含进文件的jsp:include一起使用。

 

4<jsp:plugin><jsp:params><jsp:fallback>

配合使用。plugin用于向JSP中插入Java插件,比如Applet。相当于HTML4.0版本中的<object>标签。

 

5.JSP内置对象

包括out, response, pageContext, page, request, session, application, config, exception等。

 

1)设置与读取属性,属性的范围

范围分为:page, request, session, application,分别是当前页面有效(任何跳转都无效),本次请求有效(服务器端跳转仍有效),本次登录有效(只要不关闭浏览器断开了连接),服务器端不重启永久有效。

设置属性的方法为pageContext.setAttribute("name","value")request, session, application类似。

读取属性的方法类似。

 

2)获取客户端传来的参数(用request对象)

例如

request.getParameter(String name) //获取指定name的值

request.getParameterNames() //获取所有name的名称

request.getParameterValues(String name) //获取指定name的多个值

request.getParameterMap() //获得所有数据,封装在Map对象中

Map中存放了成对的name-values值,例如

<%

Map umap= request.getParameterMap();

String[] strUsername= (String[])umap.get("username");

%>


此外,还有getIntHeader(String name), getRequestedSessionId()等等。

 

3response对象

用于给客户端传送信息。例如添加新的Cookie或者跳转等。

例如,实现页面跳转:response.sendRedirect("DirectPage.jsp");

实现自动刷新:response.addIntHeader("自动刷新",10);

实现自动跳转刷新:response.setHeader("自动刷新","10;URL=http://www.");

 

4out对象

out对象常用的方法有println(), close(), clear(),getBufferSize(),  getRemaining()等。

 

5session对象

用于设置与获得session信息。例如:getId(), setMaxInactiveInterval()设置生命周期, isNew(), invalidate()清空。

 

6application对象

用于获取与设置服务器端Servlet的相关信息,例如getSerInfo(), getRealPath()等。

 

7pageContext对象

用法很多,session, request, application的对象它都可以读,例如getRequest()

例如,读取session范围name属性:pageContext.getAttribute("name", pageContext.SESSION_SCOPE);

 

8page对象

通过page对象可以调用Servlet类中定义的方法,例如:

String info=((javax.servlet.jsp.HttpJspPage)page).getServletInfo();

 

9config对象

该对象允许访问ServletJSP引擎的初始化参数。例如getServletMame()


10exception对象

例如:

exception.getMessage(),

exception.printStackTrace(new java.io.PrintWriter(out))


7JSP中调用JavaBean

<jsp:useBean id="" scope="" class=""></jsp:useBean>

例如一个JavaBean内容如下:

package com.zollty.ch07;
public class UserBean {
       private String username;
       public String getUsername() { return username; }
       public void setUsername(String username) { //自定义的get方法
              this.username= username;
       }
}


JSP中调用的方法为

<jsp:useBean id="user" scope="page" class="com.zollty.ch07.UserBean">

</jsp:useBean> //user相当于new的一个UserBean类实例

<%

       user.setUsername("Zollty"); //用自定义的方法设置参数值

       out.println(user.getUsername());

%>


也可以用动作元素标签来设置数据的值,达到和自定义函数setUsername("Zollt

y")一样的效果(范围都要受到<jsp:useBean>的影响),例如有一个表单,里面有uname这一项:

<form action="Test3.jsp" method="post">

<input type="text" name="uname"><br>

<input type="submit" value="提交">

</form>

Test3.jsp里面通过

<jsp:setProperty name="user" property="*" />

就可以将user实例中的所有数据元素值自动匹配form表单中的属性值。再通过user.getUsername()或者<jsp:getProperty name="user" property="username" />就可以获取了。

上面的property="*"是特例,一般写作:

<jsp:setProperty name="user" property="username" param="uname" />

其中property对应的是UserBean类中的数据,而param指的是form表单中的参数(此处是input标签中name的值)。相当于把param的值赋给property,而且这个赋值只在page范围内有效,也就是说仅本页内可以取得这个值,任何跳转了页面这个值就不存在了。其实pagerequest等四个范围的值是独立存在的,要访问也必须指定范围。

PS:这里form表单中提交的数据类型要和Bean中的数据的类型一样。


移除JavaBean,例如要移除page范围内的JavaBean,则在JavaScripts里面写

<%

       pageContext.removeAttribute("user");

%>

注意到虽然是调用“移除属性”的方法,但是"user"并不是属性,它与JSP内置对象的pageContext.setAttribute("name","value")有些区别:"user"是自定义的类UserBean的实例,而"name"只是一个普通的名字,是一个字符串。


PS:英文AttributeProperty都是属性的意思,但在JSPAttribute可以是一个类或普通变量,而Property是指一个类的数据成员。


注意:JSP是放在Web工程ch01下的WebRoot目录下,和META-INFWEB-INF在同一级目录,而JavaBean是放在ch01下的src文件夹下的com.zollty包中,在其他地方中引用只需要引入class="com.zollty.UserBean"即可。


8EL表达式

EL运算符:有()[]、!(not)*/+-<<===&&||${A?B:C}


EL内置对象(EL存取器(也称为导航)),用于获取某些值。例如

${pageScope.user.username},等价于${pageScope.user["username"]}

接收用户参数(从表单post过来的),例如:

${param.username}

${paramValues.interest[0]} ${param.interest[1]}

这个paramparamValues相当于前面讲的request.getParameter()request.getParameterValues()


同理EL存取器还可以获得JavaBeanMap、数组、对象中的值。复杂对象的写法类似于:${sessionScope.shoppingCart[0].price},例如

<%

       HashMap userInfo= new HashMap();

       userInfo.put("username","zollty");

       session.setAttribute("userInfo",userInfo);

%>

然后就可以调用${userInfo.username}

再例如:

<%

       //下面定义一个对象数组

       ArrayList<Person> persons= new ArrayList<Person>();

       //实例化两个Person对象

       Person p1=new Person("Zollty",23,"");

       Person p2=new Person("Duby2",20,"");

       //p1p2装入对象数组中

       persons.add(p1);

       perssons.add(p2);

       session.setAttribute("persons",persons);

%>

然后就可以访问${sessionScope.persons[0].name}


PS:设置Cookie

<%

       Cookie c=new Cookie("username","zollty");

       response.addCookie(c);

%>


其他

${cookie.username.value}

${header["host"]}将显示localhost:8080

${initParam.username},其中usernameweb.xml中设置:

<context-param>

       <param-name>username</param-name>

       <param-value>Zollty</param-value>

</contextparam>

利用下面等方法获取getpost方式传递的信息:

${pageContent.request.queryString}

${pageContent.request.requestURL}

${pageContent.request.contextPath}


9JSTL

1. JSTL核心标签

<c:set>设置变量

         <c:set var=”varName” value=”varValue” [scope=”page|request|session|application”]>
                   default value
         </c:set>


<c:remove>移除变量

<c:remove var=”varName” [scope=”page|request|session|application”] />


<c:out>输出

<c: out value=”object” [escapeXml=”true|false”] >defalut value</c:out>

escapeXml默认为ture,是将<>'"&转换成(<)&lt;(>)&gt;

(')&#039;(")&#034;(&)&amp;输出。


<c:if>

<c:if test=”checkCondition” var=”varName” scope=”page|request|session|application”>
         body content
</c:if>

test的表达式为ture时会执行body content。判断结果turefalse存放到var中。


<c:choose><c:when><c:otherwise>相当于if else

       <c:set var=”num” scope=”page” value=”admin”/>

         <c:choose>

                   <c:when test=”${num==’guest’}”>

                            <c:out value=”guest”/>

               </c:when>

                   <c:when test=”${num==’admin’}”>

                            <c:out value=”admin”/>

               </c:when>

                   <c:otherwise>

                            <c:out value=”other”/>

               </c:otherwise>

         </c:choose>


<c:forEach>遍历或循环

<c:forEach items=”collection” var=”varName” [varstatue=”varStatusName”] [begin=”begin”] [end=”end”] [step=”step”]>

         Body content

</c:forEach>

items指被迭代的对象成员,var指当前指到的成员,begin/end设定起始和结束的位置,step为步长,varstatue存储迭代的状态信息,含indexcountfirstlast四个方法,例如

<c:forEach var=”ItemName” items=”${Items}” begin=”3” end=”4” step=”1” varStatus=”s”>

         &nbsp;<c:out value=”${ItemName}” />的四种属性:<br>

         &nbsp;所在位置即索引: <c:out value=”${s.index}” /> <br>

         &nbsp;总共已迭代的次数: <c:out value=”${s.count}”/><br>

         &nbsp;是否为第一个位置: <c:out value=”${s.first}” /><br>

         &nbsp;是否为最后一个位置: <c:out value=”${s.last}”/>

</c:forEach>


<c:forTokens>分割字符串

例如:

<c:forTokens var=”token” items=”bleu,rouge|vert,jaune|blanc,rouge” delims=”|,”>

         &nbsp;&nbsp;<c:out value=”${token}”/>

</c:forTokens>

delims属性是自定义的分隔符,items为要分割的字符串,还有其他熟悉和forEach差不多。


<c:import>引入静态文件,比<jsp:import>功能更强

<c:import url=”url” [context=”context”] [var=”varName”] [scope=”page|request|session|application”] [varReader=”varReader”] [charEncodion=”charEncoding”]>

         Body content

</c:import>


<c:redirect>跳转页面,和<jsp:redirect>一样

<c:param>

         <c:redirect url=”url” [context=”context”]>

                   <c:param name=”paramName” value=”value”/>

         </c:redirect>


<c:url>URL赋值给一个变量,便于重复调用

<c:url value=”value” [context=”context”] [var=”varName”] [scope=”page|request|session|application”] >

                   <c:param name=”paramName” value=”value” />

</c:url>


2.数据库标签

<sql:setDataSource>

<sql:update>

<sql:query>

<sql:param>

<sql:dateParam>

<sql:transaction>

3.I18N格式化标签库

<fmt:formatNumber>

<fmt:parseNumber>

<fmt:formatDate>

<fmt:parseDate>

<fmt:setTimeZone>

<fmt:timeZone>


<fmt:setLocale>设置本地化环境(语言+地区)

<fmt:setLocale value=”…locale value…” [variant=”…variant value…”] [scope=”page|request|session|application”] />

例如<fmt:setLocal value="zh_CN">

<fmt:requestEncoding>

<fmt:setBundle>

<fmt:message>

<fmt:param>

<fmt:bundle>

4.XML标签库

首先导入xalan.jarserializer.jarWeb站点中的WEB-INF/lib目录下,如果在多个站点中都要使用就放到TOMCAT安装目录下的lib中。

<x:parse>

<x:out>

<x:set>

<x:if>

<x:choose>

<x:forEach>


JSP国际化

 

src目录下建立ApplicationResources.properties文件,内容如下:

title=\u7528\u6237\u6CE8\u518C

welcome=\u6B22\u8FCE\u767B\u5F55\uFF01

再建一些形如ApplicationResources_cn.properties的文件,cn代表中国,例如de则代表德国

 

jsp中引入:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

再设置:

<fmt:setBundle basename="ApplicationResources" scope="session"/>

就可实现本地化了,例如打印上面文件中的title的内容:

<fmt:message key="title"></fmt:message>

改变浏览器的语言环境即可显示不同国家的效果。