文章目录
1 JSP介绍
JSP(JavaServer Pages)是一种用于开发动态Web应用程序的Java技术。它允许开发人员将Java代码嵌入到HTML页面中,以生成动态内容。JSP的主要特点包括:
-
简化Web开发:JSP允许开发人员将Java代码嵌套在HTML中,使得生成动态内容变得更加直观和容易。这样开发人员可以将Java代码和HTML页面组合在一起,而不需要编写大量的Java代码来生成HTML。
-
基于标签:JSP使用一系列自定义标签(JSP标签库)来简化常见的Web开发任务,如表单处理、数据库访问、会话管理等。这些标签允许开发人员以更高层次的抽象方式来处理Web应用程序的功能。
-
与Servlet集成:JSP是建立在Servlet技术之上的,它与Servlet紧密集成。事实上,JSP页面在首次访问时会被编译成Servlet,并在Servlet容器中运行。这意味着JSP可以与Java Servlet无缝协作,结合了Servlet的强大功能。
-
动态内容生成:JSP允许生成动态内容,例如从数据库检索数据、处理表单提交、动态生成HTML等。开发人员可以在JSP页面中嵌入Java代码片段,这些代码片段在页面被访问时会执行,生成动态内容。
-
可重用组件:JSP支持自定义标签库和标签文件,这使得开发人员能够创建可重用的自定义组件,从而提高了代码的可维护性和可扩展性。
-
MVC模式:JSP通常与Servlet一起用于实现MVC(Model-View-Controller)模式,其中JSP充当视图(View)的角色,而Servlet充当控制器(Controller)的角色,负责处理业务逻辑。
-
与Java EE整合:JSP是Java EE(Java Platform, Enterprise Edition)规范的一部分,因此可以轻松地集成到Java EE应用程序中,使用Java EE的各种功能和API。
示例JSP页面:
<!DOCTYPE html>
<html>
<head>
<title>Simple JSP Example</title>
</head>
<body>
<h1>Welcome to JSP!</h1>
<%
String name = "John";
out.println("Hello, " + name);
%>
</body>
</html>
在上面的示例中,JSP页面包含了HTML和嵌入的Java代码片段,用于生成动态内容。JSP页面在客户端请求时被服务器解析和执行,并生成HTML响应发送给客户端。
2 JSP中嵌套java代码
首先需要引入依赖:
然后可以通过使用以下方式在JSP页面中嵌入Java代码:
-
脚本元素
<% %>
:可以使用脚本元素来包裹Java代码块,如下所示:<% // Java代码块 String name = "kong"; out.println("Hello, " + name); %>
out.println
用于将输出发送到响应中。 -
表达式
<%= %>
:可以使用表达式来在HTML中输出Java表达式的结果,如下所示:<p>Current time: <%= new java.util.Date() %></p>
<%= %>
包裹的表达式会在页面上显示java.util.Date
的当前时间。 -
指令
<%! %>
:可以使用指令元素来定义在JSP页面中的类成员变量和方法,如下所示:<%! private String name = "Hello, kong"; public String getName() { return name ; } %>
<%! %>
包裹的代码定义了一个私有成员变量和一个公共方法,
虽然在JSP中嵌入Java代码是可行的,但最好将JSP用于视图层,将业务逻辑尽量放在Servlet或其他Java组件中,以便实现MVC(Model-View-Controller)模式的良好分离。
3 JSP的工作原理
JSP 的工作原理是将 Java 代码嵌入到 HTML 页面中,然后在服务器端动态生成 HTML 响应,以供客户端浏览器显示。以下是 JSP 的工作原理的基本步骤:
-
编写JSP文件:创建一个以
.jsp
扩展名结尾的文件,其中包含 HTML 代码和嵌入的 Java 代码片段。这个文件可以包含静态 HTML 内容,也可以包含 JSP 标签和 EL 表达式等。 -
JSP编译:当Web应用程序部署到Servlet容器(如Tomcat)时,容器会将JSP文件编译成一个对应的Servlet。这个编译过程会生成Java代码,该代码包含在Servlet的
service
方法中。 -
请求处理:当客户端浏览器发送HTTP请求访问JSP页面时,Servlet容器接收到请求并决定哪个Servlet来处理这个请求。对于JSP页面,它将选择与该JSP文件对应的Servlet。
-
Servlet执行:Servlet执行阶段开始,Servlet的
service
方法被调用。在service
方法中,包含在JSP中的Java代码片段被执行。这些代码片段可以访问请求参数、会话信息、数据库等数据源,并生成动态内容。 -
HTML生成:Servlet执行Java代码片段后,生成的HTML内容与JSP文件中的静态HTML内容合并。生成的HTML响应被发送回客户端浏览器。
-
客户端响应:客户端浏览器接收到HTML响应,将其渲染并显示给用户。
例:当浏览器访问http://localhost:8080/jsp-demo/index.jsp
。服务器发现后缀为.jsp,则会根据路径找到 index.jsp
文件,把它翻译成index_jsp.java
文件,然后对这个java文件进行编译,产生一个index_jsp.class
文件,将class文件加载运行。
将JSP翻译成java文件:它是将JSP中的所有的HTML代码通过流进行输出,也就是说最终翻译成class,被虚拟机加载,它本质是servlet,它就会往回响应,响应回去就是把JSP中的HTML代码以流的方式写回浏览器,所以在JSP中展示出了HTML代码。
4 JSP的内置对象
JSP提供了一些内置对象,这些对象在JSP页面中可以直接访问,用于执行不同的任务和访问不同的信息。这些内置对象是预定义的,无需显式创建,它们包括:
-
request
request 对象代表了客户端发送的HTTP请求。可以使用它来获取请求参数、HTTP头、会话信息等。 -
response
response 对象代表了服务器发送回客户端的HTTP响应。可以使用它来设置响应头、写响应内容等。 -
out
out 对象是一个输出流,用于将文本发送回客户端浏览器。可以使用out.print()来将文本输出到HTML响应中。 -
session
session 对象代表了用户的会话,可以用来存储和检索会话数据。通常用于跨不同请求存储用户状态信息。 -
application
application 对象代表了整个Web应用程序的上下文,允许在不同的会话之间共享数据。通常用于存储全局配置信息、共享资源等。例如,通过application.setAttribute("name", value)
可以设置应用程序范围的属性。 -
config
config 对象包含了关于当前JSP页面的配置信息。可以用来获取初始化参数等。例如,通过config.getInitParameter("paramName")
可以获取初始化参数的值。 -
pageContext
pageContext 对象提供了对上述所有内置对象的访问,以及其他一些功能。它是一个页面级别的上下文对象。 -
page
page 对象代表当前JSP页面的实例。通常用于调用页面级别的方法。 -
exception
exception 对象包含了在页面执行期间抛出的异常信息,可以用于处理异常情况。
只有在包含 isErrorPage=“true” 的页面中才可以被使用。
5 JSP的指令
JSP 提供了一些指令用于在 JSP 页面中设置一些重要的配置和行为。这些指令以<%@
开头,通常位于JSP页面的顶部。以下是常见的JSP指令:
- page 指令:
<%@ page %>
指令用于设置页面级别的配置和属性,它可以包括如下选项:
- import:用于导入Java类或包。
- contentType:设置响应的内容类型(MIME类型)和字符编码。
- language:指定在JSP页面中使用的脚本语言,默认为Java。
- extends:指定生成的Servlet类继承的父类。
- session:指示是否支持会话,可以是
true
或false
。 - buffer:设置输出缓冲区的大小。
- autoFlush:指定是否自动刷新输出缓冲区。
示例:
<%@ page language="java" contentType="text/html; charset=UTF-8" import="java.util.*" %>
-
include 指令:
<%@ include %>
指令用于将其他文件(通常是JSP片段或静态HTML文件)包含到当前JSP页面中,可以用于实现页面的模块化。示例:
<%@ include file="hello.jsp" %>
-
taglib 指令:
<%@ taglib %>
指令用于导入自定义标签库,以便在JSP页面中使用自定义标签。示例:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
6 JSP的作用域
6.1 介绍
在 JSP 中,作用域是用于在不同部分(例如不同Servlet、JSP页面和标签)之间存储和共享数据的一种机制。JSP提供了四种不同的作用域,用于在Web应用程序的不同组件之间传递数据:
- Page Scope(页面作用域):pageContext
- 页面作用域是最短的作用域,它仅在当前JSP页面中有效。
- 数据存储在页面作用域中后,只能在同一JSP页面的不同部分(如脚本块、标签之间)共享。
- 页面作用域的生命周期仅限于当前请求的处理过程。
- Request Scope(请求作用域):request
- 请求作用域在一次HTTP请求中有效,可以在同一个请求的不同Servlet、JSP页面和标签之间共享数据。
- 数据存储在请求作用域中后,只能在当前请求处理过程中的不同组件之间共享。
- 请求作用域通常用于在请求处理期间传递数据。
- Session Scope(会话作用域):session
- 会话作用域在用户的整个会话期间(从登录到退出)有效,可以在不同的HTTP请求之间共享数据。
- 数据存储在会话作用域中后,可以在同一用户的不同请求之间共享,通常用于保存用户的登录状态和其他会话相关的数据。
- 会话作用域可以在多个不同的HTTP请求之间传递数据。
- Application Scope(应用程序作用域):application
- 应用程序作用域在整个Web应用程序的生命周期中有效,可以在不同用户的不同会话中共享数据。
- 数据存储在应用程序作用域中后,可以在整个Web应用程序的不同部分共享,通常用于存储全局配置信息、共享资源等。
- 应用程序作用域通常用于在不同用户之间传递数据,但要小心避免并发访问问题。
6.2 案例
a.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>a</title>
</head>
<body>
<h5>a.jsp存储上下文数据</h5>
<%
pageContext.setAttribute("pkey","pageContext");
request.setAttribute("rkey","request");
session.setAttribute("skey","session");
application.setAttribute("akey","application");
//转发
request.getRequestDispatcher("/b.jsp").forward(request, response);
%>
</body>
</html>
b.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>b</title>
</head>
<body>
<h5>b.jsp取上下文数据</h5>
<%
out.print(pageContext.getAttribute("pkey")+"<br>");
out.print(request.getAttribute("rkey")+"<br>");
out.print(session.getAttribute("skey")+"<br>");
out.print(application.getAttribute("akey")+"<br>");
%>
</body>
</html>
c.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c</title>
</head>
<body>
<h5>c.jsp取上下文数据</h5>
<%
out.print(pageContext.getAttribute("pkey")+"<br>");
out.print(request.getAttribute("rkey")+"<br>");
out.print(session.getAttribute("skey")+"<br>");
out.print(application.getAttribute("akey")+"<br>");
%>
</body>
</html>
启动tomcat服务器,地址栏输入http://localhost:8080/jsp-demo/a.jsp,页面结果:
由于发生了转发,b.jsp页面获取不到 pageContext.getAttribute,结果为null
地址栏输入http://localhost:8080/jsp-demo/a.jsp,页面结果:
由于不是同一个页面,pageContext.getAttribute 结果为 null
由于不是同一次HTTP请求,request.getAttribute 结果为 null
7 EL表达式
EL(Expression Language,表达式语言)是一种用于在Java Web应用程序中访问和操作数据的简洁和强大的表达式语言。EL最初是为JavaServer Pages(JSP)而设计的,但它也可以在其他Java Web框架中使用。EL的主要用途是在JSP页面中嵌入动态数据,以及在JavaBean和其他Java组件中处理数据。
7.1 EL表达式语法
${内容}
7.2 EL基础操作符
7.3 常见的EL特性和用法
-
访问JavaBean属性:EL允许在JSP页面中轻松地访问JavaBean的属性,而无需编写繁琐的Java代码。例如,
${user.name}
可以用来获取user
对象的name
属性的值。 -
执行算术和逻辑运算:EL支持算术运算(+、-、*、/等)和逻辑运算(&&、||、!等),允许在JSP页面中进行简单的计算和条件判断。
-
访问集合元素:可以使用EL来访问数组、List、Map等集合类型的元素。例如,
${items[0]}
可以用来获取数组或List中的第一个元素。 -
调用方法:EL支持调用JavaBean中的方法。例如,
${user.getName()}
可以用来调用user
对象的getName
方法。 -
条件运算:EL允许使用条件运算符(?:)进行条件判断和选择。例如,
${score >= 60 ? 'Pass' : 'Fail'}
可以根据分数输出不同的文本。 -
空值处理:EL引入了安全导航操作符(
?.
),允许在访问属性或方法时避免空指针异常。例如,${user?.name}
如果user
为空,不会引发空指针异常,而是返回null
。 -
内置对象:EL提供了一些内置对象,如
pageScope
、requestScope
、sessionScope
和applicationScope
,可以用于访问不同作用域中的属性。 -
函数:EL支持自定义函数,可以在JSP页面中调用。开发人员可以编写自己的自定义函数,并在JSP中使用
${prefix:functionName(...)}
的语法来调用。
示例:
<%@ page import="com.kdx.demo.entity.User" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>b</title>
</head>
<body>
<h5>b.jsp取上下文数据</h5>
<%
out.print(pageContext.getAttribute("pkey")+"<br>");
out.print(request.getAttribute("rkey")+"<br>");
out.print(session.getAttribute("skey")+"<br>");
out.print(application.getAttribute("akey")+"<br>");
%>
<hr>
<h5>el表达式取上下文数据</h5>
${pageScope.pkey}<br>
${requestScope.rkey}<br>
${sessionScope.skey}<br>
${applicationScope.akey}
<%
pageContext.setAttribute("key", "page scope value");
request.setAttribute("key", "request scope value");
session.setAttribute("key", "session scope value");
application.setAttribute("key", "application scope value");
pageContext.setAttribute("num", 100);
%>
<h5>el表达式不写作用域访问则依次从page->request->session->application中获取数据</h5>
${key}
<h5>el表达式运算符</h5>
${key == 'page scope value'}
${num+1}
<h5>el表达式访问对象属性</h5>
<%
User user = new User();
user.setUsername("kong");
user.setAge(18);
pageContext.setAttribute("user",user);
%>
${user.username}<br>
${user.age}<br>
<h5>el表达式访问集合</h5>
<%
List<User> list = new ArrayList<>();
list.add(new User("kong",18));
pageContext.setAttribute("list",list);
%>
${list[0].username}<br>
${list[0].age}<br>
<h5>el表达式访问地址栏参数</h5>
${param.name}<br><%--访问name参数,如果为空不显示--%>
<%=request.getParameter("name")%><br>
<h5>el表达式访问context path</h5>
${pageContext.request.contextPath}
<%@ include file="c.jsp"%>
</body>
</html>
当表达式没有指定变量或者对象的范围时,容器依次从 pageContext、request、session、application
中查找该变量或对象。
可以通过隐含对象获得指定作用域的值:
- pageScope对象,用于获取当前页面的属性值
- requestScope对象,用于获取请求范围的属性值
- sessionScope对象,用于获取会话范围的属性值
- applicationScope对象,用于获取程序范围的属性值
语法:
${requestScope.key}
8 JSTL
8.1 介绍
JSTL(JavaServer Pages Standard Tag Library)是一组标准的自定义标签,用于在JSP页面中简化和增强动态Web应用程序的开发。JSTL提供了一些常见任务的标准标签,如循环、条件判断、格式化、国际化等,以减少在JSP页面中嵌入Java代码的需求,从而提高代码的可读性和可维护性。
8.2 JSTL语法格式
- 将 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下
- 在JSP页面中引入
<%@ taglib prefix=”页面使用的名称” uri=”功能范围的路径”%>
8.3 核心标签
引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:out>:用于输出内容到页面,自动进行HTML转义。
<c:out value="${userKey.username}"></c:out>
<c:set>:用于设置变量。
<c:set var="n36" value="${requestScope.userKey.username.substring(3, 6)}" scope="page"></c:set>
${n36}
<c:if>:条件判断标签,用于执行条件语句。
<c:if test="true">
is true <br>
</c:if>
<c:choose>:选择标签,类似于Java中的switch语句。
<c:choose>
<c:when test="${1 == 2}">
1 == 2;
</c:when>
<c:when test="${3 == 2}">
2 == 2;
</c:when>
<c:otherwise>
otherwise
</c:otherwise>
</c:choose>
<c:forEach>:循环标签,用于迭代集合。
<c:forEach begin="1" end="10" var="i">
${i}
</c:forEach>
<c:redirect>:用于执行重定向。
<c:redirect url="/index.jsp"></c:redirect>
<c:remove>:用于删除变量。
<c:import>:导入标签,用于包含其他页面的内容。
<c:url>:用于创建URL,可用于处理相对路径和URL重写。
<c:param>:用于添加URL参数。
8.4 格式化标签
fmt:formatDate:用于日期格式化。
<fmt:formatDate value="${date}" pattern="yyyy年MM月dd日 HH:mm:ss.SSS" var="fdate" scope="page"></fmt:formatDate>
fmt:formatNumber:用于数字格式化
<fmt:formatNumber value="${moneyKey}" pattern="#,###.##" var="fmoney" scope="page"></fmt:formatNumber>
fmt:parseDate :用于将指定字符串转化为日期类型
<fmt:parseDate value="${now }" pattern="yyyy-MM-dd" var="today"/>