Skip to content

一 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

image-20230329185713476

每个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
<% 
Java语句
%>

注意:JSP脚本中只能出现java代码,不能出现其它模板元素(html相关标签), JSP引擎在翻译JSP页面中,会将JSP脚本中的Java代码将被原封不动地放到Servlet的_jspService方法中。

JSP脚本片断中的Java代码必须严格遵循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语句,例如:

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
<%=java的表达式 %>

JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.write(…) 将数据输给客户端。

注意:JSP脚本表达式中的变量或表达式后面不能有分号(;)。

java
<!-- jsp表达式 -->
<!--  相当于out.print(name.length() ); -->
<%=name %>
<%=name.length() %>
当前时间:<%= new java.util.Date() %>

3 JSP声明

JSP 声明语句用于声明变量、方法

java
<%! 
定义变量、方法等
%>

JSP声明中的java代码被翻译到_jspService方法的外面,即成为成员变量/成员方法。

java
<!-- 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注释

java
<%--  注释的内容  --%>

三 EL表达式

EL:Expression Language

EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的域中检索java对象、获取数据。

使用EL表达式获取数据语法:

java
${标识符}

1 获取数据

1)从指定域中获取数据

java
<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)获取对象属性

java
${d }<br />
<!-- 获取对象中的属性,直接使用属性名,不要调用get方法 -->
${d.name }<br />
${d.age }<br />

3)获取集合中值

java
<!-- 根据下标获取列表中数据 -->
${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应用初始化参数的对象
java
<!-- 内置对象 -->
<!-- 获取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)添加依赖

shell
<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

2)通过tablib指令在jsp中导入相关的标签库

语法:

java
<%@ taglib uri="tagliburl" prefix="tagPre" %>

其中,uri 指定自定义标签库的存放位置;prefix 指定标签库的前缀

java
<!-- 引入核心标签库,前缀必须使用"c" -->
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

3)核心标签库语法

java
<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 序号 1234.。。
		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指令的基本语法格式:

shell
<%@ 指令 属性名="值" %>

1 include指令

include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。

语法:

shell
<%@ include file="relativeURL"%>

其中的file属性用于指定被引入文件的相对路径。file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前文件。

注意: 被引入的文件必须遵循JSP语法。 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容。 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(pageEncoding和导包除外)。

java
<%@ 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>
java
<%@ 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指令的完整语法:

java
<%@ 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" ]
属 性取 值说 明举 例
buffernone、缓冲区大小(默认值为 8kb)指定输出流是否有缓冲区<%@ page buffer="16kb" %>
autoFlushtrue(默认值)、false指定缓冲区是否自动清除<%@ page autoFlush="true" %>
contentTypetext/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
isErrorpagetrue、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"%>
isThreadSafetrue(默认值)、false是否允许多线程使用<%@ page isThreadSafe="false" %>
language脚本语言指定页面中使用的脚本语言<%@ page language= "java" %>
sessiontrue(默认值)、false指定页面是否使用 session<%@ page session="false" %>
isELIgnoredtrue(默认值)、false指定页面是否忽略 JSP 中的 EL表达式<%@ page isELIgnored="false" %>

3 taglib指令

通过该 指令可以在JSP页面中声明并引入标签库

语法:

shell
<%@ taglib uri="tagliburl" prefix="tagPre" %>

其中,uri 指定自定义标签库的存放位置;prefix 指定标签库的前缀

内置对象

1 九大内置对象

JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。

对 象类型说 明
requestjavax.servlet.http.HttpServletRequest
responsejavax.servlet.http.HttpServletResponse
outjavax.servlet.jsp.JspWriter输出内容到 HTML 中
sessionjavax.servlet.http.HttpSession
applicationjavax.servlet.ServletContext
configjavax.servlet.ServletConfig
pageContextjavax.servlet.jsp.PageContext可用于获取 page、request、application 和 session 的属性
pagejavax.servlet.jsp.HttpJspPage类似于 Java 类的 this 关键字,表示当前 JSP 页面
exceptionjava.lang.Throwable该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。

2 pageContext

pageContext对象是JSP技术中最重要的一个对象,它代表当前JSP页面的运行环境,这个对象不仅封装了对其它8大对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如包含和跳转其它资源、检索其它域对象中的属性等

java
<%
	//可以获取其他内置对象
	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该作用域中的属性在整个应用范围内有效,服务器重启后失效。
java
<%
	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> 的语法

java
<jsp:useBean id = "name" class = "package.class" scope= "page | request | session | application" />

其中:id表示 创建的对象名称,class 对象的类名(包名+类名)

java
<!-- 创建对象   ,将对象自动放到域对象中
	class  包名+类名
-->
<jsp:useBean id="user" class="com.qianfeng.entity.User" ></jsp:useBean>

${user }

2 <jsp:setProperty> 的语法

java
<jsp:setProperty name = "beanName" property = "attributeName" value = "attributeValue"/>

其中:name 表示对象的名称,property 属性名,value 表示属性对应的值

java
<!-- 给对象的属性设置值   
	name 对象的名称
	property 对象汇总数据的名称
	value 对应的值
 -->
<jsp:setProperty name="user" property="name"  value="zhangsan"/>

${user.name }

3 <jsp:getProperty> 的语法

java
<jsp:getProperty name = "beanName" property = "attributeName">
java
<!-- 获取对象中属性的值 -->
<jsp:getProperty property="name" name="user"/>

4 <jsp:forward> 的语法

java
<jsp:forward page="url"/>

比如

java
<!-- 实现转发 -->
<%-- <jsp:forward page="01el.jsp"></jsp:forward> --%>

<!-- WEB-INF 目录下的资源不能直接访问 
	通过如下的方式可以实现访问操作
-->
<jsp:forward page="WEB-INF/index.jsp"></jsp:forward>