JSP高级

一. JSP页面的组成

1.JSP 页面的元素

5.JSP高级 - 图1

Servlet做动态页面响应这种方式有几个问题: 1)有大量的字符串拼接操作,操作复杂。 2)前端工程师修改页面代码困难 为了解决以上问题sun公司给出了:Java Server Page——简称JSP技术 JSP是为了同时满足动态生成网页和简化页面书写的需求诞生的。

2.JSP注释

在JSP文件的编写过程中,共有三种注释方法 HTML的注释,将输出到客户端 JSP注释,不翻译到Java文件中,JSP注释只有在JSP文件中可见 <%— JSP注释 —%> 在Java脚本中注释,将翻译到Java文件中,依然是注释语句 <% //单行注释 %> <% /多行注释 / %>

3.JSP指令

3.1 指令概念

JSP可以通过指令元素而影响容器翻译生成Java类的整体结构。 指令的语法为: <%@ directive attr1=”value1” attr2=”value2” %> 其中,directive为指令名,attr指该指令对应的属性名,一个指令可能有多个属性。 JSP中常用的指令有三个:page、include、taglib,本章主要学习其中的两个:page指令、include指令。taglib指令将在JSTL标签章节学习。

3.2 page指令

page指令是最复杂的一个指令,共有13个属性。page指令作用于整个JSP页面,可以将指令放在JSP页面任何一个位置。

1). page指令属性:import

import属性用来引入JSP文件需要使用的类。 如下代码所示: <%@ page import=”java.util. , java.io.“ %> <%@ page import=”com.test.vo.*” %> 上述代码可以在JSP文件中使用,引入需要使用的类。可以使用逗号同时引入多个包,也可以在一个JSP文件中多次使用import。值得注意的是,import是page指令中唯一一个可以在一个JSP文件中多次出现的属性,其他属性在一个JSP文件中只能出现一次。

2). page指令属性:pageEncoding

pageEncoding属性用来设置JSP文件的页面编码格式。 如下代码所示: <%@ page pageEncoding=”utf-8”%> 上述代码设置当前JSP的页面编码格式是utf-8。

3). page指令属性:session

session属性用来设置JSP页面是否生成session对象。该属性默认值为true,可以设置成false。 如下代码所示: <%@ page session=”false”%> session属性值设置为false后,该JSP翻译生成的类中将没有内置对象session,该JSP不参与会话。

4). page指令属性:errorPage

errorPage属性设置JSP页面的错误页面。当JSP中发生异常或错误却没有被处理时,容器将请求转发到错误页面。 如下代码所示: <%@ page errorPage=”error.jsp”%> 显然,当页面将发生异常,而且并没有对异常进行处理,那么将跳转到错误页面,例如定制的error.jsp

5). page指令属性: isErrorPage

isErrorPage属性默认值是false,可以设置为true。在JSP的错误页面中,将isErrorPage设置为true,则该页面翻译生成的Java类中,将生成exception内置对象。 若在error.jsp中加入代码: <%@ page isErrorPage=”true”%> 上述代码将error.jsp页面设置为错误页面,所以,在error.jsp翻译生成的Java类中的_jspService方法中将生成exception内置对象。 注意:即使一个页面没有设置isErrorPage=“true”,也可以作为错误页面使用,区别在是否有内置对象exception内置对象产生。

3.3 include指令

include指令是JSP中另外一个常用指令,用来静态包含其他页面。所谓静态包含,指的是在翻译期间,把包含的页面也翻译到当前页面的Java文件中,所谓Java源文件就实现“二合一”。 若在main.jsp中编写如下代码: <%@ include file=”copyright.jsp”%> 过程:翻译main.jsp时,会把copyright.jsp文件翻译插入到相应位置。

4.JSP标准动作

4.1 标准动作概念

JSP规范中定义了一系列的标准动作。Web容器按照规范进行了实现,可以解析并执行标准动作。 标准动作使用标准的XML语法:

其中action_name表示标准动作的名字,attribute1和attribute2是标准动作的若干个属性。本节将学习常用的3种标准动作,forward、include、param

4.2 标准动作 :forward

forward动作:在JSP页面中进行请求转发。 如下代码所示:

上述代码将把请求转发到success.jsp页面,类似在Servlet中调用RequestDispatcher的forward方法进行请求转发。

4.3 标准动作 :include

include动作:在JSP页面中,进行动态包含。 如下代码所示:

上述代码是动态包含,即在运行期访问被包含的页面,并将响应结果同包含页面的响应结果合并,生成最终响应。类似在Servlet中调用RequestDispatcher的include方法进行包含。 因为是动态包含,所以可以在包含时传递请求参数。 如下代码所示:

comName将作为请求参数,被传递给top.jsp页面。 include标准动作与include指令的区别: 1.静态包含 include指令 动态包含 include标准动作

2.静态包含 <%@ include file=”top.jsp” %> 动态包含

3.include指令的属性是file,实现静态包含,发生在翻译阶段,将包含的jsp文件翻译进去 include标准动作的属性是page,实现动态包含,发生在请求阶段,将包含的jsp文件直接翻译成java文件

4.4 标准动作 :param

param动作往往作为子动作使用,为forward和include动作传递参数。 如下代码所示:


上述代码使用param为forward和include动作传递参数,参数将被作为请求参数传递。

二.EL表达式&EL的内置对象

EL全称:Expression Language 语法:${ 表达式} 作用:代替jsp中脚本表达式的功能,简化对java代码的操作。

1. EL使用 - 获取作用域的值

获得四个容器(pagerequestsessionservletContext :域对象)的数据

1.1 ScopeServlet中

@WebServlet(name = “ScopeServlet” , urlPatterns = “/scope”) public class ScopeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //请求域传值
  3. request.setAttribute("name", "李四");
  4. //获得会话
  5. HttpSession session = request.getSession();
  6. session.setAttribute("name", "张三");
  7. //获得上下文
  8. ServletContext sc = request.getServletContext();
  9. sc.setAttribute("name" , "王二");
  10. //跳转页面
  11. request.getRequestDispatcher("scope.jsp").forward(request, response);
  12. }

}

1.2 scope.jsp中

<% pageContext.setAttribute(“name”, “赵六”); %>

  1. 当前页作用域:${pageScope.name} <br>
  2. 请求作用域:${requestScope.name} <br>
  3. 会话作用域:${sessionScope.name} <br>
  4. 上下文作用域:${applicationScope.name} <br>
  5. <br>
  6. ${name}
  7. ${aaa}

1.3 效果

5.JSP高级 - 图2 注意:获取属性时,若使用表达式的话,指定的key不存在,表达式会得到null;而使用EL表达式取出的时候指定的key不存在,页面上什么都没有。

2. EL使用 - 解析复杂数据

复杂数据:数组,集合(List Map),自定义对象(Person User Animal) 案例:EL使用 - 解析复杂数据 <%@ page contentType=”text/html;charset=UTF-8” language=”java” import=”java.util. , com.igeek.javaee.entity.User” %>

<%— EL获取复杂数据 —%> <% //测试数组 int[] arr = {666,1888,2333,1024,999}; pageContext.setAttribute(“arr”, arr); %> 可以通过下标获取数据:${arr[0]}
<% //测试集合 List list = new ArrayList(); list.add(“白米饭”); list.add(“咸菜”); list.add(“紫菜汤”); pageContext.setAttribute(“list”, list); Map map = new HashMap(); map.put(“sj1”, “诺基亚”); map.put(“sj2”, “黑莓”); map.put(“sj3”, “摩托罗拉”); map.put(“sj4”, “大哥大”); map.put(“aa.bb.cc”, “波导手机中的战斗机”); pageContext.setAttribute(“map”, map); %> 可以通过下标获取数据:${list[0]}
通过map的key获取数据: ${map.sj1} ${map[“aa.bb.cc”]}
<%— EL获取自定义对象 —%> <% User u = new User(); u.setName(“李四”); u.setAge(18); pageContext.setAttribute(“u”, u); %> 通过相同的属性名称获取数据: ${u} ${u.name} ${u.age} <%— 所有可以使用点的地方,都可以使用[ ]获取数据 —%> ${u[“age”]}

效果: 5.JSP高级 - 图3

3. EL使用 - 执行运算

3.1 支持算术运算符

      • / %

3.2 支持逻辑运算符

5.JSP高级 - 图4

3.3 支持比较运算符

5.JSP高级 - 图5

代码: <%— 演示El执行运算 —%> <% int x = 3; int y = 4; //String y = “4g”; pageContext.setAttribute(“x”, x); pageContext.setAttribute(“y”, y); %>

<%— 使用EL表达式获取数据,最终都是讲数据转换成字符串,根据字符串,格式化数字,在进行计算 —%> ${x+y } ${x-y } ${x*y } ${x/y } ${x%y }


<% boolean flag = true; boolean info = false; pageContext.setAttribute(“flag”, flag); pageContext.setAttribute(“info”, info); %>

${flag && info}

${!info}

${flag || info}


${x < y } ${x <= y} ${x > y } ${x >= y } ${x == y } ${x != y } 效果: 5.JSP高级 - 图6

注意:当算术运算的时候,如果字符串内容不能解析成数据,则报数字格式化异常。数字格式化错误:EL取出来的数据无法转换成数字 5.JSP高级 - 图7

3.4 empty运算符:检查对象是否为null或“空”

对于自定义对象,检查是否为null 对于集合检查,是否为空(集合存在,但是没有数据) 代码: <%
User user = new User();
user.setName(“张三”);
pageContext.setAttribute(“user”, user); %>

${empty user} 效果: false

3.5 ${ user!=null ? user.name : “”} 三元运算

代码: <%
User user = new User();
user.setName(“张三”);
pageContext.setAttribute(“user”, user); %>

${user!=null ? user.name : “” } 效果: 张三

4. EL的11个内置对象使用

EL表达式它也有自己的内置(直接使用)对象可以直接在EL表达式中使用

4.1 从不同的容器中取值

pageScope

requestScope

sessionScope

applicationScope

代码: <% pageContext.setAttribute(“name”,”a”); //只在当前页面

  1. request.setAttribute("name","b"); //一次请求中,可以请求转发
  2. session.setAttribute("name","c"); //会话超时之前都存在,只要浏览器不关闭
  3. application.setAttribute("name","d"); //服务器重启或关闭前都存在,只要服务器不关闭
  4. %>
  5. EL表达式取name:
  6. ${pageScope.name }
  7. ${requestScope.name }
  8. ${sessionScope.name }
  9. ${applicationScope.name }

4.2 获取用户提交的请求参数param/paramValues

获取单个值: param
获取某个key对应的多个value值(例如获取页面中checkbox): paramValues

代码: ${param.username} ${paramValues.hobby[0]}

测试: http://localhost:8888/javaee/testInnerObj.jsp?username=lisi&hobby=football&hobby=basketball

4.3 获取请求头中的信息 header/headerValues

获取请求头中的单个值: header
代码: ${header} 结果: 5.JSP高级 - 图8

某个请求头中的多个value值: headerValues
代码: ${headerValues.cookie[0]} 结果: 5.JSP高级 - 图9

4.4 cookie内置对象

代码: <%— ${cookie}获取了cookie数组,获取所有的cookie数据。 —%> ${cookie}

<%— 若要获取数组中的指定cookie,使用点名称的方式获取 —%> ${cookie.JSESSIONID.name }
${cookie.JSESSIONID.value}
${cookie.nameCookie.name}
${cookie.nameCookie.value}
效果: 5.JSP高级 - 图10

4.5 pageContext内置对象

它和JSP内置对象pageContext功能一致,可以使用pageContext,获取request对象,调用request对象的方法。 代码: ${pageContext.request.contextPath}

4.6 initParam内置对象

通过initParam获取的项目的全局配置参数 配置:


wx
无锡极客营


wh
武汉极客营
代码: ${initParam} ${initParam.wx} ${initParam.wh} 效果: 5.JSP高级 - 图11

三.JSTL的核心标签库使用

Sun公司,推出了一套java标签的标准,根据这个标准,自己制作了一套标签,给所有的Java程序员使用,这个标签就是JSTL。 JSTL的介绍: 5.JSP高级 - 图12

1. 准备工作

1.1 导入相关jstl的jar包

1.2 使用核心标签库,引入标签库到jsp页面中

<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core“ %> prefix 表示的是标签的小名 ; uri 表示的是引入那个标签库

1.3 常见库

core:jstl的核心标签库,使用最多(必须掌握) fmt:格式化的标签(对页面显示数据,格式化,现在都交给前端去做) functions:jstl中提供对字符串操作的函数库(建议,在数据显示在页面之前,在后台程序中,先格式化好字符串,然后直接显示,不再页面做处理,如果有前端,交给前端处理(javascript 解析json格式数据)) sql:jstl提供的在jsp页面上书写sql,操作数据库,目前已经不再(不允许)使用(jsp开发模式二(MVC),这个开发模式不允许,在页面操作数据库) xml:jstl操作xml文件的。目前已经不再使用(页面传递数据,页面解析数据,json格式字符串。)

2. c:if 标签

作用: 相当于java代码中if语句 。 使用c:if 标签,在JSP页面上可以完成if判断。 注意: 在JSTL核心标签库中没有c:else , 只有if( ){ }结构,没有 if( ){ }else{ }结构 写法:

条件成立的时候,执行标签中的内容 API截图: 5.JSP高级 - 图13 test属性:判断是否执行标签内的内容(true则执行标签中的内容,false则不执行)。

var属性:用来保存test属性的结果(使用var属性给他取个名字),这个结果可以保存到指定的容器中。(如果没有指定容器,默认存入page容器中)

scope属性:指定保存数据的容器。 案例: <%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core“ %>

<%— scope=”session” 设置var中的数据flag保存在会话容器中,值为test的值—%>

测试if标签,EL表达式方式

pageScope:${pageScope.flag }
requestScope:${requestScope.flag }
sessionScope:${sessionScope.flag }
applicationScope:${applicationScope.flag }
效果: 5.JSP高级 - 图14

3. c:choose / c:when / c:otherwise 标签

c:choose c:when c:otherwise 相当于:if( ){ }else if( ){ } else if( ){ } …… else{ }。 c:choose标签它必须与c:when和c:otherwise 标签一起使用,它表示哪些c:when和c:otherwise 是在一组的。 使用c:choose,c:when和c:otherwise 三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。 c:when ,c:otherwise 属于同一级别标签,同时是c:choose的子标签。 代码: <%— 演示choose when otherwise 标签 —%> <%

  1. int num = 4;
  2. pageContext.setAttribute("num", num);
  3. int flag = 1;
  4. pageContext.setAttribute("flag", flag);

%>

  1. <c:when test="${num==1 }">星期一</c:when>
  2. <c:when test="${num==2 }">星期二</c:when>
  3. <c:when test="${num==3 }">星期三</c:when>
  4. <c:when test="${num==4 }">星期四</c:when>
  5. <c:when test="${num==5 }">星期五</c:when>
  6. <c:when test="${num==6 }">星期六</c:when>
  7. <c:when test="${num==7 }">星期日</c:when>
  8. <c:when test="${flag==1 }">白天</c:when>
  9. <c:when test="${flag==2 }">黑夜</c:when>
  10. <c:otherwise>参数不合法</c:otherwise>

效果:星期四

异常:使用when otherwise标签的时候,一定要写在choose标签内,不然报错 5.JSP高级 - 图15 异常:一组choose中有多个otherwise,就出现异常。 5.JSP高级 - 图16 异常:choose标签中不要写java代码 5.JSP高级 - 图17

4. c:set和c:out标签

4.1 c:set

作用:它可以给某个容器中保存数据,或者去修改某个对象的属性值。相当于代替了pageContext.setAttribute。 API截图: 5.JSP高级 - 图18 var:声明了一个变量空间,用来存储数据(value属性的值)的

value:要保存的数据

scope:指定保存在那个容器中

target:指定要修改的对象

property:指定要修改的属性

代码: <%— 演示set标签 —%>

${sessionScope.path}



<%— 演示修改数据 —%> <% pageContext.setAttribute(“user”, new User()); %>

<%— target=”${user}” 指定要修改的对象 property=”name” 指定要修改的属性 —%> ${user}

${user}
效果: 5.JSP高级 - 图19

异常原因: 修改对象属性的时候不能修改它所在的容器。var 属性和scope属性必须一起使用。 5.JSP高级 - 图20

异常原因:target属性和property属性是要一起使用的,如果修改的数据不是对象的属性,那么就会报错 5.JSP高级 - 图21

4.2 c:out

作用:它可以把数据输出到页面上,相当于JSP的内置对象out API截图: 5.JSP高级 - 图22 代码: <%— 演示out标签 —%> <% pageContext.setAttribute(“str”, null); %>

<%— default设置没有数据的时候,默认输出 —%>

<%— escapeXml=”true” 让浏览器不解析其中的html—%>

效果: 5.JSP高级 - 图23

5. c:forEach标签

c:forEach 循环的标签。 实现 java中for循环的功能。 API截图: 5.JSP高级 - 图24 varStatus:保存了当前循环过程中的信息

1 public java.lang.Integer getBegin() 返回为标签设置的begin属性的值,如果没有设置begin属性则返回null

2 public int getCount() 返回当前已循环迭代的次数

3 public java.lang.Object getCurrent() 返回当前迭代到的元素对象

4 public java.lang.Integer getEnd() 返回为标签设置的end属性的值,如果没有设置end属性则返回null

5 public int getIndex() 返回当前迭代的索引号

6 public java.lang.Integer getStep() 返回为标签设置的step属性的值,如果没有设置step属性则返回null

7 public boolean isFirst() 返回当前是否是第一次迭代操作

8 public boolean isLast() 返回当前是否是最后一次迭代操作

5.1 foreach不循环对象(集合、数组)的情况下,单单控制循环的次数。

代码: <%— 演示foreach标签 —%> <%— c:forEach控制迭代 begin起始值 end终止值 step步长,控制循环 var用来设置当前迭代到的元素,保存在page容器中的数据的名称
varStatus保存了循环过程中状态信息 —%>

${sta.index} <%— 当前迭代的索引号 —%> ${sta.count} <%— 当前已经迭代的次数 —%> ${sta.first} <%— 返回当前是否是第一次迭代操作 —%> ${sta.last} <%— 返回当前是否是最后一次迭代操作 —%> ${info}
<%— 用来设置当前迭代到的元素,保存在page容器中的数据的名称 —%>
效果: 5.JSP高级 - 图25

5.2 foreach循环对象的情况下(数组,集合:list和map)

代码: <%— 演示foreach,循环对象 —%> <% int[] arr = {666,23333,886,9527,82}; pageContext.setAttribute(“arr”, arr); %>

<%— var=”num” :保存的是数组中的元素 —%>

${num}



<% List list = new ArrayList(); list.add(“跑男”); list.add(“欢乐喜剧人”); list.add(“极限挑战”); list.add(“笑傲江湖”); list.add(“爸爸去哪儿”);

pageContext.setAttribute(“list”, list); %>

${name}



<% Map map = new TreeMap(); map.put(“addr1”, “东京”); map.put(“addr2”, “马尔代夫”); map.put(“addr3”, “巴黎”); map.put(“addr4”, “东南亚”);

pageContext.setAttribute(“map”, map); %>

${entry.key} ${entry.value} 效果: 5.JSP高级 - 图26