一 JSP基础
1什么是JSP
Java Server Pages,它和servle技术一样,是Java中用于开发动态web资源的技术。
JSP相当于Java + Html
JSP的最大的特点在于,写JSP就像在写html。相比html而言,html只能为用户提供静态数据,而JSP技术允许在页面中嵌套java代码,为用户提供动态数据。相比Servlet而言,Servlet很难对数据进行排版,而JSP除了可以用java代码产生动态数据的同时,也很容易对数据进行排版。
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把Servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
原因在于,程序的数据通常要美化后再输出,让JSP既用java代码产生动态数据,又做美化会导致页面难以维护;让Servlet既产生数据,又在里面嵌套Html代码美化数据,同样也会导致程序可读性差,难以维护。
因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,Servlet只负责响应请求产生数据,并把数据通过转发技术带给JSP,数据的显示JSP来做。
2 JSP执行过程
JSP本质上就是Servlet
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
注意:第一次访问JSP文件时,会在tomcat的work目录下生成对应的java文件,然后编译为字节码文件,执行JSP时,其实就是执行对应的class文件,并执行其中的相关方法
二 JSP语法
1 JSP脚本
在 JSP 中,可以使用脚本写入 Java 代码
基本语法:
<%
Java语句
%>
注意:JSP脚本中只能出现java代码,不能出现其它模板元素(html相关标签), JSP引擎在翻译JSP页面中,会将JSP脚本中的Java代码将被原封不动地放到Servlet的_jspService方法中。
JSP脚本片断中的Java代码必须严格遵循Java语法
<!-- jsp脚本,脚本中声明的变量放在_jspService方法中 -->
<%
// 相当于局部变量
int num = 10;
String name = "zhangsan";
System.out.println(name);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(date);
System.out.println(dateStr);
%>
单个脚本中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如:
<%
for (int i=1; i<5; i++)
{
%>
<H1>hahahaha</H1>
<%
}
%>
<%
for(int i = 1; i <= 6; i++){
response.getWriter().write("<h" + i + ">标题" + i + "<h" + i + "/>");
}
%>
<%
for(int i = 1; i <= 6; i++){
%>
<h<%=i %>>标题<%=i %></h<%=i %>>
<%
}
%>
2 JSP表达式
JSP 表达式可以把变量或者表达式输出到网页上
<%=java的表达式 %>
JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.write(…) 将数据输给客户端。
注意:JSP脚本表达式中的变量或表达式后面不能有分号(;)。
<!-- jsp表达式 -->
<!-- 相当于out.print(name.length() ); -->
<%=name %>
<%=name.length() %>
当前时间:<%= new java.util.Date() %>
3 JSP声明
JSP 声明语句用于声明变量、方法
<%!
定义变量、方法等
%>
JSP声明中的java代码被翻译到_jspService方法的外面,即成为成员变量/成员方法。
<!-- jsp声明 -->
<%!
//相当于成员变量
private int aaa = 10;
//定义了一个方法
public int add(int a, int b){
return a + b;
}
int sum = add(10, 12);
//System.out.println(sum);
%>
4 JSP注释
<%-- 注释的内容 --%>
三 EL表达式
EL:Expression Language
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的域中检索java对象、获取数据。
使用EL表达式获取数据语法:
${标识符}
1 获取数据
1)从指定域中获取数据
<body>
<%
application.setAttribute("name", "application_zhangsan");
pageContext.setAttribute("name", "page_zhangsan");
request.setAttribute("name", "req_zhangsan");
session.setAttribute("name", "session_zhangsan");
//request.getAttribute("name");
Dog dog = new Dog("fugui", 4);
request.setAttribute("d", dog);
List<Dog> list = new ArrayList<Dog>();
for(int i = 0; i < 3; i++){
Dog d = new Dog("wangcai" + i, i + 3);
list.add(d);
}
request.setAttribute("dogList", list);
Map<String, Object> map = new HashMap<String, Object>();
map.put("height", 130);
map.put("dog", dog);
request.setAttribute("map", map);
%>
<!-- 本例中,name表示域对象中的key值 -->
<!-- el表达式, 从域对象中获取数据,并且在页面上展示数据 -->
<!-- 如果向多个域对象中写了相同的key值,获取数据的顺序 pageContext、request、session、application -->
${name } <br />
<!-- 指定从哪个域对象汇总获取数据
requestScope等属于el的内置对象
-->
${requestScope.name } <br />
${sessionScope.name } <br />
${applicationScope.name } <br />
</body>
2)获取对象属性
${d }<br />
<!-- 获取对象中的属性,直接使用属性名,不要调用get方法 -->
${d.name }<br />
${d.age }<br />
3)获取集合中值
<!-- 根据下标获取列表中数据 -->
${dogList[2].name } <br />
<!-- 获取map对象中数据 -->
${map["height"] }<br />
${map.height }<br />
2 表达式运算
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算
算数运算符:
说明 | ||
---|---|---|
+ | 加 | ${5+2} ,结果7 |
- | 减 | ${5-2},结果3 |
* | 乘 | ${5*2},结果10 |
/ 或 div | 除 | ${10 / 3},结果3.3333... |
% 或 mod | 求余 | ${10 % 3},结果 1 |
关系运算符:
说明 | ||
---|---|---|
== 或 eq | 等于 | ${6 == 6} 或 ${6 eq 6} ${"A"="a"} 或 $ |
!= 或 ne | 不等于 | ${6 != 6} 或 ${6 ne 6} ${“A"!=“a”} 或 $ |
< 或 lt | 小于 | ${3 < 8} 或 ${3 lt 8} ${"A"<"a"} 或 $ |
> 或 gt | 大于 | ${3 > 8} 或 ${3 gt 8} ${"A" > "a"} 或 $ |
<= 或 le | 小于等于 | ${3<=8} 或 ${3 le 8} ${"A"<="a"} 或 $ |
>= 或 ge | 大于等于 | ${3>=8} 或 ${3 ge 8} ${"A" >= "a"} 或 $ |
逻辑运算符
说明 | ||
---|---|---|
&& 或 and | 与 | ${2>1 && 3<4 } 或 $ |
|| 或 or | 或 | ${2 < 1 || 3 > 4} 或 $ |
! 或 not | 非 | ${!(2 > 4)} 或 $ |
3 内置对象
EL 表达式定义了一些内置(隐式)对象,利用这些隐式对象,开发人员可以获得对web中常用对象的引用,从而获得这些对象中的数据
隐含对象名称 | 描 述 |
---|---|
pageContext | 对应于JSP页面中的pageContext对象 |
pageScope | 代表page域中用于保存属性的对象 |
requestScope | 代表request域中用于保存属性的对象 |
sessionScope | 代表session域中用于保存属性的对象 |
applicationScope | 代表application域中用于保存属性的对象 |
param | 表示一个保存了所有请求参数的对象 |
paramValues | 表示一个保存了所有请求参数的对象,它对于某个请求参数,返回的是一个string[] |
header | 表示一个保存了所有http请求头字段的对象 |
headerValues | 同上,返回string[]数组。注意:如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”] |
cookie | 表示一个保存了所有cookie的对象 |
initParam | 表示一个保存了所有web应用初始化参数的对象 |
<!-- 内置对象 -->
<!-- 获取web应用的路径 -->
${pageContext.request.contextPath }<br />
<!-- http://localhost:8080/day38_jsp/01el.jsp?id=10&name=zhagnsan -->
${param["id"] }<br />
${param.id }<br />
<!-- 获取cookie对象 -->
${cookie["JSESSIONID"] }<br />
${cookie["JSESSIONID"].value }<br />
${cookie.JSESSIONID }<br />
四 jstl标签
JSTL(JSP Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。主要包括:
核心标签(c:) JSTL函数(fn:) 格式化标签(fmt:) 数据库标签 XML标签
1 核心标签库
标签 | 说明 |
---|---|
<c:out> | 将表达式的结果输出到页面中,类似于 <%= ...%> |
<c:set> | 在指定范围内设置变量或属性值 |
<c:if> | 类似于 Java if 语句,用于条件判断 |
<c:choose> | 类似于 Java switch 关键字,为 <c:when>和<c:otherwise> 的父标签 |
<c:when> | <c:choose> 的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose> 的子标签,当所有的 <c:when> 标签判断为 false 时被执行 |
<c:forEach> | 类似于 Java for,用于迭代集合中的信息 |
2 使用步骤
1)添加依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
2)通过tablib指令在jsp中导入相关的标签库
语法:
<%@ taglib uri="tagliburl" prefix="tagPre" %>
其中,uri 指定自定义标签库的存放位置;prefix 指定标签库的前缀
<!-- 引入核心标签库,前缀必须使用"c" -->
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3)核心标签库语法
<body>
<!-- 设置值
var 变量名
value 对应的值
-->
<c:set var="name" value="haha" ></c:set>
${name }
<!-- 输出值
default 表示默认值 -->
<c:out value="${name1 }" default="aa"></c:out>
<c:set var="sex" value="女"></c:set>
<!-- 单条件判断
类似java中 if(){}
test 判断条件,可以通过el表达式设置,在{}里面写判断逻辑
-->
<c:if test="${sex == '男' }">
<input type="radio" value="男" checked="checked" />男
<input type="radio" value="女" />女
</c:if>
<c:if test="${sex == '女' }">
<input type="radio" value="男" />男
<input type="radio" value="女" checked="checked" />女
</c:if>
<c:set value="50" var="score"></c:set>
<!-- 多条件判断 -->
<c:choose>
<c:when test="${score > 80 && score <= 100 }">
学霸
</c:when>
<c:when test="${score >= 60 && score <= 80 }">
中规中矩
</c:when>
<c:when test="${score > 0 && score < 60 }">
渣渣
</c:when>
<c:otherwise>
分数错误
</c:otherwise>
</c:choose>
<%
List<User> list = new ArrayList<User>();
for(int i = 0; i < 3; i++){
User d = new User();
d.setName("wangwu" + i);
d.setAge(20);
list.add(d);
}
request.setAttribute("userList", list);
%>
<!-- 循环遍历
items 要遍历的集合
var 遍历的元素的变量名
varStatus 变量的状态
count 序号 1, 2, 3, 4.。。
index 索引、下标
first 是否第一个元素
last 是否最后一个元素
-->
<table border="1" width="200">
<tr>
<td>name</td>
<td>age</td>
<td></td>
</tr>
<c:forEach items="${userList }" var="user" varStatus="vs">
<tr>
<td>${user.name }</td>
<td>${user.age }</td>
<td>${vs.count }/${vs.index }/${vs.first }/${vs.last }</td>
</tr>
</c:forEach>
</table>
</body>
附录
JSP三大指令
JSP的指令并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
1 include指令
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的相对路径。file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前文件。
注意: 被引入的文件必须遵循JSP语法。 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容。 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(pageEncoding和导包除外)。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
session="false"
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<!-- 静态包含 引入需要包含的文件,将多个文件合并成一个文件,转换为一份java代码 -->
<%@include file="head.jsp" %>
</head>
<body>
include用法
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<link type="text/css" href="css/index.css"></link>
<script type="text/javascript" src="js/common.js"></script>
<script type="text/javascript" src="js/common2.js"></script>
2 page指令
用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
page指令的完整语法:
<%@ page
[ language="java" ]
[ import="{package.class | package.*}, ..." ]
[ session="true | false" ]
[ buffer="none | 8kb | sizekb" ]
[ autoFlush="true | false" ]
[ isThreadSafe="true | false" ]
[ info="text" ]
[ errorPage="relative_url" ]
[ isErrorPage="true | false" ]
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]
[ pageEncoding="characterSet | ISO-8859-1" ]
[ isELIgnored="true | false" ]
属 性 | 取 值 | 说 明 | 举 例 |
---|---|---|---|
buffer | none、缓冲区大小(默认值为 8kb) | 指定输出流是否有缓冲区 | <%@ page buffer="16kb" %> |
autoFlush | true(默认值)、false | 指定缓冲区是否自动清除 | <%@ page autoFlush="true" %> |
contentType | text/html; charset = ISO-8859-1、 text/xml;charset = UTF-8 等 | 指定 MIME 类型和字符编码 | <%@ page contentType="text/html;charset=UTF-8" %> |
errorpage | 页面路径 | 指定当前 JSP 页面发生异常时,需要重定向的错误页面 | <%@ page errorpage="myerrorpage.jsp" %> 注意:myerrorpage.jsp 的 isErrorpage 值必须为 true |
isErrorpage | true、false(默认值) | 指定当前页面为错误页面 | <%@ page isErrorpage="true" %> |
extends | 包名.类名 | 指定当前页面继承的父类,一般很少使用 | <%@ page extends="mypackage.SampleClass"%> |
import | 类名、接口名、包名 | 导入类、接口、包,类似于 Java 的 import 关键字 | <%@ page import = " java.util.Date" %> <%@ page import="java.io., java.lang."%> |
info | 页面的描述信息 | 定义 JSP 页面的描述信息,可以使用 getServletInfo() 方法获取 | <%@ page info="helloworld"%> |
isThreadSafe | true(默认值)、false | 是否允许多线程使用 | <%@ page isThreadSafe="false" %> |
language | 脚本语言 | 指定页面中使用的脚本语言 | <%@ page language= "java" %> |
session | true(默认值)、false | 指定页面是否使用 session | <%@ page session="false" %> |
isELIgnored | true(默认值)、false | 指定页面是否忽略 JSP 中的 EL表达式 | <%@ page isELIgnored="false" %> |
3 taglib指令
通过该 指令可以在JSP页面中声明并引入标签库
语法:
<%@ taglib uri="tagliburl" prefix="tagPre" %>
其中,uri 指定自定义标签库的存放位置;prefix 指定标签库的前缀
内置对象
1 九大内置对象
JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。
对 象 | 类型 | 说 明 |
---|---|---|
request | javax.servlet.http.HttpServletRequest | |
response | javax.servlet.http.HttpServletResponse | |
out | javax.servlet.jsp.JspWriter | 输出内容到 HTML 中 |
session | javax.servlet.http.HttpSession | |
application | javax.servlet.ServletContext | |
config | javax.servlet.ServletConfig | |
pageContext | javax.servlet.jsp.PageContext | 可用于获取 page、request、application 和 session 的属性 |
page | javax.servlet.jsp.HttpJspPage | 类似于 Java 类的 this 关键字,表示当前 JSP 页面 |
exception | java.lang.Throwable | 该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。 |
2 pageContext
pageContext对象是JSP技术中最重要的一个对象,它代表当前JSP页面的运行环境,这个对象不仅封装了对其它8大对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如包含和跳转其它资源、检索其它域对象中的属性等
<%
//可以获取其他内置对象
pageContext.getRequest();
pageContext.getResponse();
pageContext.getServletContext();
pageContext.getSession();
pageContext.getServletConfig();
pageContext.getException();
pageContext.getOut();
pageContext.getPage();
%>
<%
//pageContext 域对象
//pageContext.setAttribute("msg", "page_msg");
//第三个参数,指定向哪个域中设置数据
//四个域对象
pageContext.setAttribute("msg", "page_msg", PageContext.PAGE_SCOPE);
pageContext.setAttribute("msg", "request_msg", PageContext.REQUEST_SCOPE);
pageContext.setAttribute("msg", "session_msg", PageContext.SESSION_SCOPE);
pageContext.setAttribute("msg", "application_msg", PageContext.APPLICATION_SCOPE);
%>
3 四个域对象
域对象 | 作用范围 |
---|---|
pageContext | 该作用域中的属性只在当前 JSP 页面有效,跳转页面后失效。 |
request | 该作用域中的属性只在当前请求范围内有效,转发时可以共享request对象中数据,重定向后失效 |
session | 该作用域中的属性只在当前会话范围内有效。当session过期;或者没有设置JSESSIONID的有效期,而关闭网页,都会引起失效。 |
application | 该作用域中的属性在整个应用范围内有效,服务器重启后失效。 |
<%
System.out.println(pageContext.getAttribute("msg"));
System.out.println(request.getAttribute("msg"));
System.out.println(session.getAttribute("msg"));
System.out.println(application.getAttribute("msg"));
//从域中查找属性
//pageContext->reqeust->session->application
System.out.println(pageContext.findAttribute("msg"));
%>
内置动作标签 理解
动作 | 说明 |
---|---|
jsp:include | 页面被请求时引入一个文件 |
jsp:userBean | 实例化JavaBean对象 |
jsp:setProperty | 设置 JavaBean 的属性 |
jsp:getProperty | 获取 JavaBean 的属性 |
jsp:forward | 将请求转发到另一个页面 |
jsp:plugin | 根据浏览器类型替换成 <object> 或者 <embed>标签 |
jsp:element | 定义动态 XML 元素 |
jsp:attribute | 设置动态 XML 元素的属性 |
jsp:body | 设置动态 XML 元素的内容 |
1 <jsp:useBean> 的语法
<jsp:useBean id = "name" class = "package.class" scope= "page | request | session | application" />
其中:id表示 创建的对象名称,class 对象的类名(包名+类名)
<!-- 创建对象 ,将对象自动放到域对象中
class 包名+类名
-->
<jsp:useBean id="user" class="com.qianfeng.entity.User" ></jsp:useBean>
${user }
2 <jsp:setProperty> 的语法
<jsp:setProperty name = "beanName" property = "attributeName" value = "attributeValue"/>
其中:name 表示对象的名称,property 属性名,value 表示属性对应的值
<!-- 给对象的属性设置值
name 对象的名称
property 对象汇总数据的名称
value 对应的值
-->
<jsp:setProperty name="user" property="name" value="zhangsan"/>
${user.name }
3 <jsp:getProperty> 的语法
<jsp:getProperty name = "beanName" property = "attributeName">
<!-- 获取对象中属性的值 -->
<jsp:getProperty property="name" name="user"/>
4 <jsp:forward> 的语法
<jsp:forward page="url"/>
比如
<!-- 实现转发 -->
<%-- <jsp:forward page="01el.jsp"></jsp:forward> --%>
<!-- WEB-INF 目录下的资源不能直接访问
通过如下的方式可以实现访问操作
-->
<jsp:forward page="WEB-INF/index.jsp"></jsp:forward>