1.JSP及作用
[!note]
JSP(Java Server Pages)是一种用于创建动态Web页面的技术,它是在Java语言的基础上开发的。JSP允许开发人员将Java代码嵌入HTML页面中,以实现动态内容生成。JSP页面在服务器端被解析和执行,最终生成HTML页面发送给客户端浏览器。
[!tip]
JSP的主要作用包括:
- 动态生成网页内容:通过在JSP页面中嵌入Java代码,可以根据不同的条件生成不同的HTML内容,使得网页可以根据用户的需求动态展示不同的信息。
- 简化Web应用开发:JSP提供了一种将Java代码与HTML页面结合的方式,使得开发人员可以更方便地编写和维护动态Web应用程序。
- 支持Java EE平台:JSP是Java EE平台的一部分,可以与其他Java EE技术(如Servlet、JDBC等)结合使用,实现更复杂的Web应用程序开发。
- 可重用性:JSP页面可以通过包含其他JSP页面或Java类来实现代码的重用,提高了开发效率和代码的可维护性。
2.JSP的本质
[!important]
JSP的本质是Servlet程序
[!warning]
JSP(JavaServer Pages)的本质是一种在服务器端执行的Java技术,它允许开发人员将静态的HTML页面与动态的Java代码结合在一起,以生成动态的Web内容。当客户端请求一个包含JSP的网页时,服务器会先解析JSP页面,将其中的Java代码编译成Servlet,并执行这些Servlet代码,最终生成HTML页面返回给客户端浏览器。
因此,尽管在JSP页面中可以直接编写HTML和嵌入Java代码,但实际上,服务器在处理JSP时会将其转换为Servlet,并在服务器端执行。这样做的好处是能够在服务器端动态生成HTML内容,从而实现更丰富、更灵活的Web应用程序。
[!caution]
在JSP页面被第一次请求时,容器(如Tomcat)会将其翻译成一个Servlet源文件。这个Servlet源文件会被编译成Java字节码,并且在服务器上执行。这个编译和执行过程被称为JSP的"编译"。
在JSP被编译为Servlet时,生成的Servlet会继承自
HttpJspBase
类,而HttpJspBase
类则间接继承自HttpServlet
类。HttpJspBase
类提供了JSP生命周期管理、JSP页面执行过程中需要的一些方法实现等功能。通过继承HttpServlet
,JSP生成的Servlet获得了处理HTTP请求的能力。总之,JSP页面编译后生成的Servlet会继承自
HttpJspBase
类,而HttpJspBase
类则继承自HttpServlet
,这样JSP页面就能够被服务器正确地处理HTTP请求了。
jsp页面编译成java代码
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.41
* Generated at: 2024-04-15 14:28:40 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp.pages;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class jsp01_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("<h1>什么是jsp、jsp的作用</h1>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
3.JSP语法
SP头部的page指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
[!note]
在JSP页面中,可以使用
<%@ page %>
指令来设置页面的一些属性和配置信息。这个指令通常出现在JSP页面的头部,用于指定一些与整个页面相关的属性
属性 | 描述 | 示例 |
---|---|---|
language | 指定脚本语言 | language="java" |
contentType | 指定响应的内容类型和字符编码 | contentType="text/html; charset=UTF-8" |
import | 导入 Java 类或包 | import="java.util.*, java.io.*" |
extends | 指定生成的 Servlet 类的父类 | extends="javax.servlet.jsp.HttpJspBase" |
session | 指定是否使用会话 | session="false" |
autoFlush (out输出流使用) | 指定是否自动刷新缓冲区 | autoFlush="false" |
buffer(out输出流使用) | 指定输出缓冲区的大小(单位为 KB) | buffer="16kb" |
isThreadSafe | 指定是否线程安全 | isThreadSafe="false" |
info | 指定 JSP 页面的描述信息 | info="This is a JSP page" |
errorPage | 指定错误处理页面的 URL | errorPage="error.jsp" |
isErrorPage | 指定当前页面是否是错误处理页面 | isErrorPage="true" |
JSP中的常用脚本
1.声明脚本
[!note]
在JSP中,声明脚本(declaration)用
<%! %>
标签包裹,允许在JSP页面中定义Java代码,包括成员变量、方法和初始化代码块等。这些声明的内容会被放置在生成的Servlet类的类体中,因此可以在整个JSP页面的任何位置使用。声明脚本中定义的成员变量和方法属于Servlet的实例,因此是线程安全的,每个请求都会创建一个新的实例。
[!tip]
在 JSP 页面中,声明脚本一般被放置在页面的头部,通常在任何 HTML 或 JSP 元素之前。这样做有助于保持页面的整洁和可读性。声明脚本可以用来定义类的属性、方法以及其他初始化代码块等,因此放置在页面的开头是比较常见的做法。
<%--
Created by IntelliJ IDEA.
User: ZJM
Date: 2024/4/15
Time: 22:54
To change this template use File | Settings | File Templates.
--%>
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- **声明脚本** --%>
<%--1.声明类属性--%>
<%!
private String message = "Hello, World!";
private Integer id;
private String name;
private static Map<String, Object> map;
%>
<%--2.声明静态代码块--%>
<%!
static {
System.out.println("Static block executed");
// 在这里可以执行一些初始化静态变量的操作
map = new HashMap<>();
map.put("username", "zjm");
}
%>
<%--3.声明方法--%>
<%!
// 声明一个方法,用于计算两个整数的和
public int calculateSum(int a, int b) {
return a + b;
}
%>
<%--4.声明内部类--%>
<%!
// 声明一个内部类
public class InnerClass {
private String message;
public InnerClass(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
%>
<html>
<head>
<title>声明脚本</title>
</head>
<body>
<%--可以放在任何位置--%>
<%!
// 声明一个静态方法,用于计算两个整数的和
public static int add(int a, int b) {
return a + b;
}
%>
</body>
</html>
2.表达式脚本
[!note]
在 JSP(JavaServer Pages)中,表达式脚本(Expression Script)是一种用于在页面上输出动态内容的简洁方式。表达式脚本使用
<%= %>
标记,并且其中可以包含任何有效的 Java 表达式,例如变量、方法调用、算术运算等。当 JSP 引擎处理页面时,表达式脚本会被解析并执行,并将结果输出到生成的 HTML 页面中。例如,假设有一个名为
username
的 Java 变量,你可以在 JSP 页面中使用表达式脚本来输出它的值:<p>Welcome, <%= username %>!</p>
在这个例子中,
<%= username %>
将会被替换为username
变量的值,这样用户就会看到一个欢迎消息,其中包含他们的用户名。表达式脚本通常用于在页面中嵌入动态数据,例如显示用户信息、计算结果等。需要注意的是,表达式脚本不适合用于控制结构或复杂的业务逻辑,对于这些情况,更适合使用声明脚本或脚本片段。
3.代码脚本
[!note]
用于编写任意的 Java 代码。脚本片段使用
<% %>
标记。你可以在脚本片段中编写任何有效的 Java 代码,包括变量声明、条件语句、循环等。例如:<% String name = "John"; out.println("Hello, " + name + "!"); %>
[!tip]
任意 Java 代码:脚本片段中可以包含任何有效的 Java 代码,包括变量声明、条件语句、循环、方法调用等。
灵活性:脚本片段提供了最大的灵活性,可以在其中编写各种逻辑和操作,以满足不同的需求。
直接执行:脚本片段中的代码会在 JSP 页面被处理时直接执行,因此可以用于处理页面上的动态逻辑、数据处理等任务。
与静态内容混合:脚本片段可以与静态内容和其他类型的脚本元素混合使用,使得在页面中嵌入 Java 代码变得更加灵活和方便。
适用于复杂逻辑:脚本片段通常用于处理较复杂的业务逻辑、控制结构等,以及需要动态生成内容的情况。
JSP中的三种注释
在 JSP(JavaServer Pages)中,有三种类型的注释,它们分别是 HTML 注释、JSP 注释和 Java 注释。
-
HTML 注释:
HTML 注释是在生成的 HTML 页面中可见的注释。它们使用
<!-- -->
标记,与普通 HTML 注释相同。HTML 注释中的内容不会被浏览器显示,但会在页面的源代码中存在。例如:<!-- 这是一个 HTML 注释 -->
-
JSP 注释:
JSP 注释是在 JSP 页面的源代码中可见的注释。它们使用
<%-- --%>
标记,不会被发送到客户端,也不会在生成的 HTML 页面中显示。例如:<%-- 这是一个 JSP 注释 --%>
-
Java 注释:
Java 注释是在 Java 代码中使用的注释,包括单行注释
//
和多行注释/* */
。在 JSP 页面中,Java 注释可以用来注释掉 Java 代码块,但不会影响页面的渲染和呈现。例如:<% // 这是一个单行 Java 注释 %> <% /* 这是一个多行 Java 注释 */ %>
4.JSP九大内置对象
内置对象 | 类型 | 描述 |
---|---|---|
request | HttpServletRequest | 代表客户端的 HTTP 请求,可以获取客户端提交的数据。 |
response | HttpServletResponse | 代表发送给客户端的 HTTP 响应,可以设置响应的内容和属性。 |
session | HttpSession | 代表客户端的会话,可以在多个请求之间存储和获取数据,以及跟踪用户的状态。 |
application | ServletContext | 代表整个 Web 应用程序的上下文,可以在整个应用程序中共享数据。 |
out | JspWriter | 代表响应输出流,可以向客户端输出内容。 |
config | ServletConfig | 代表当前 JSP 页面的配置信息,可以获取初始化参数和其他配置信息。 |
page | Object | 代表当前 JSP 页面的实例,可以调用当前页面的方法和属性。 |
pageContext | PageContext | 代表当前页面的上下文,可以获取其他内置对象。 |
exception | Throwable | 代表发生在当前页面中的异常,如果页面出现异常,可以使用该对象来处理异常。 |
5.JSP四大域对象
[!tip]
域对象:可以像Map一样存储数据
域对象 | 类型 | 描述 | 生命周期 |
---|---|---|---|
page 域 | javax.servlet.jsp.PageContext | 数据仅在当前 JSP 页面中可见和有效。 | 页面开始时创建,页面结束时销毁。 |
request 域 | javax.servlet.http.HttpServletRequest | 数据在一次 HTTP 请求过程中可见和有效。 | 请求开始时创建,请求结束时销毁。 |
session 域 | javax.servlet.http.HttpSession | 数据在用户会话期间可见和有效。 | 用户会话开始时创建,会话结束时销毁。 |
application 域 | javax.servlet.ServletContext | 数据在整个 Web 应用程序中可见和有效。 | Web 应用程序启动时创建,应用程序关闭时销毁。 |
在 JSP 中,四个域对象的使用优先顺序为:
- Page 域
- Request 域
- Session 域
- Application 域
6.JSP的out和response区别
[!tip]
jsp页面一般使用out
out.write()//输出整型会出问
建议使用out.print()
7.常用标签
静态包含
[!note]
<%@include file="/include/footer.jsp"%>静态包含 地址中的第一个斜杆/ 表示为http://ip:prot/工程路径/ 映射到代码的web目录 静态包含的特点: 1.静态包含不会翻译被包含的jsp页面 2.静态包含其实就是把被包含的jsp页面的代码拷贝到包含的位置执行输出
动态包含
[!note]
<jsp:include page=“/include/footer.jsp”></jsp:include>动态包含
动态包含可以像静态包含一样,把被包含的jsp页面的代码拷贝到包含的位置执行输出动态包含的特点:
1.动态包含会把包含的jsp页面也翻译成java代码
2.动态包含底层代码使用java代码调用被包含的jsp页面执行输出
3.动态包含还可以传递参数<jsp:include page="/include/footer.jsp"> <%--动态包含传递参数--%> <jsp:param name="username" value="zjm"/> <jsp:param name="password" value="zjm_password"/> </jsp:include>
请求转发标签
[!note]
<%-- <jsp:forward page="/include/main.jsp"></jsp:forward> 请求转发标签 page属性设置转发路径 --%> <jsp:forward page="/include/main.jsp"></jsp:forward>
8.请求转发的使用
@WebServlet("/search")
public class SearchServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Student> studentList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
studentList.add(new Student(i + 1, "name" + i, 18 + i, "phone" + i));
}
req.setAttribute("studentList", studentList);
//获取请求调度器对象
RequestDispatcher dispatcher = req.getRequestDispatcher("/pages/jsp10.jsp");
//转发
dispatcher.forward(req, resp);
}
}
<%
List<Student> studentList = (List<Student>) request.getAttribute("studentList");
%>