xiaohuihui
for me

Jsp

2020-10-26 11:31:54
Word count: 3.2k | Reading time: 14min

Jsp

1.什么是Jsp?

Jsp(java server page):java的服务器页面。

jsp的主要作用是代替Servlt程序回传html页面的数据(服务端返回给客户端)。

因为Servlt程序回传html页面数据是非常繁琐的一件事情。开发和维护成本非常高。

2.Jsp的本质

jsp页面本质上是一个Servlet程序。

当我们第一次访问jsp页面的时候。Tomact服务器会帮我们把jsp翻译成为一个java源文件。

我们访问路径:

C:\Users\Lenovo\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_9_0_38_FirstJsp\work\Catalina\localhost\FirstJsp_war_exploded\org\apache\jsp

可以看到生成了一个java源文件

image-20201026162523599

打开文件,我们可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.38
* Generated at: 2020-10-26 08:22:50 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;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_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("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" <p>这是一个Servlet文件</p>\n");
out.write(" </body>\n");
out.write("</html>\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);
}
}
}

它的底层继承了org.apache.jasper.runtime.HttpJspBase的类

我们查看HttpJspBase继承了HttpServlet类,相当于jsp翻译出来的java类,它间接继承了HttpServlet类。所以我们可以得出jsp就是Servlet程序

image-20201026163529230

而其底层也是通过输出流,把html页面数据回传给客户端。

3.Jsp的三种语法

a)Jsp头部的page命令

image-20201026164049303

  • language属性:表示jsp翻译后是什么属性
  • contentType属性:表示jsp返回的数据类型是什么。也是源码中的response.setContentType()参数值
  • pageEncdoing属性:表示当前jsp页面文件本身的字符集。
  • import属性:跟java源代码一样,用于导包,导类。

——————————————-给out输出流使用的两个属性———————————————————–

  • autoFlush属性:设置out输出缓冲区满了之后,是否自动刷新缓冲区。默认是true。
  • buffer属性:设置out缓冲区的大小,默认是8kb。

  • errorPage属性:设置当Jsp页面运行出错,自动跳转的错误页面路径。(这个路径一般以斜杆开头,它表示请求地址为http://ip:port/工程路径/ 映射到代码的Web目录 )
  • isErrorPage属性:设置当前jsp页面是否是错误信息页面。默认是false,如果是true可以获取异常信息。
  • session属性:设置访问当前jsp页面,是否会创建HttpSession对象,默认是true。
  • extends属性:设置jsp翻译出来的java类默认继承谁。

b)jsp中常用脚本

1.声明脚本(不常使用)

声明脚本的格式:<%!声明代码块%>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %><%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2020/10/26
Time: 11:51
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 1.声明类属性--%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>

<%-- 声明static静态代码块--%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
}
%>

<%-- 声明类方法--%>
<%!
public int num(){
return 100;
}
%>

<%-- 生成内部类--%>
<%!
public static class A{
private Integer id = 11;
private String username = "coderYang";
}
%>
</body>
</html>

当运行jsp文件之后我们查看它的源代码:

image-20201026171426122

我们可以发现在java文件中生成了对应的代码。

2.表达式脚本(常用)

表达式脚本格式:<%=表达式%>

表达式脚本的作用:在jsp页面输出数据。

表达式脚本特点:

  • 所有的表达式脚本都会被翻译到_jspService方法中。
  • 所有的表达式脚本都会被翻译成为out.print()输出到页面上。
  • 由于表达式脚本翻译的内容都在_jspService()方法中,所以__jspServcie方法中的对象可以直接使用。
  • 表达式脚本中的表达式不能以分号结尾。
3.代码脚本

代码脚本的格式是:<% java语句 %>

代码脚本的作用是:可以在jsp页面中,编写我们所需要的功能。

代码脚本的特点是:

  1. 代码脚本翻译之后都在_jspService方法中。
  2. 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
  3. 还可以由多个代码脚本块组合完成一个java语句
  4. 代码脚本还可以和表达式脚本一起组合使用,在jsp页面上输出数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %><%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2020/10/26
Time: 11:51
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 1.声明类属性--%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>

<%-- 声明static静态代码块--%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
}
%>

<%-- 声明类方法--%>
<%!
public int num(){
return 100;
}
%>

<%-- 生成内部类--%>
<%!
public static class A{
private Integer id = 11;
private String username = "coderYang";
}
%>


<%-- 一些输出命令--%>
<%=map%>
<%="useranme = "+request.getParameter("username")%>
</body>


<%--代码脚本 if语句--%>
<%
int i = 12;
if(i == 12){
System.out.println("true");
}else{
System.out.println("false");
}
%>

<%--代码脚本---for循环--%>
<%
for (int j =0;j<10;++j){
System.out.println(j);
}
%>


<%-- 翻译后java文件中_jspService方法内的代码都可以写--%>
<%
String username = request.getParameter("username");
System.out.println("username = "+username);
%>


</html>

4.Jsp中的九大内置对象(不用new)

Jsp中的内置对象,是指Tomcat在翻译jsp页面成为Servlet源代码后,内部提供的九大对象,叫内置对象。

image-20201027112224979

request 请求对象

response 响应对象

pageContext jsp的上下文对象(JSP页面容器)

session 会话对象

application 全局对象

config 配置对象(服务器配置信息)

out 输出对象

page 当前JSP页面对象(相当于Java中的this)

exception 异常对象

5.Jsp四种范围对象

pageContext (PageContextImpl类) 当前页面有效(页面跳转后无效)

request (HttpServletRequest类) 同一次请求有效(请求转发后有效,重定向后无效)

session (HttpSession类) 同一次会话有效(打开浏览器访问服务器,直到关闭浏览器)

application (ServletContext类) 全局有效(只要web工程不停止,数据都在)

域对象是可以像Map一样存储数据的对象。四个域对象功能一样。不同的是它们对数据的存储范围。

虽然四个域对象都可以存储数据,在使用它们上是有优先顺序的。

四个域对象在使用的时候,优先顺序分别是:

从小到大:pageContext ====>>> request =====>> session =========> application

以上四个对象公有的方法:

Object getAttribute(String name):根据属性名,获得属性值

void setAttribute(String name,Object obj):设置属性值

void removeAttribute(String name):根据属性名,删除对象

pageContext:当前页面有效(页面跳转后无效)

request:同一次请求有效(请求转发后有效,重定向后无效)

session:同一次会话有效(无论怎么跳转都有效;关闭/切换浏览器后无效;从登录到退出之间 全部有效)

application:全局变量;整个项目运行期间 都有效 (切换浏览器,仍然有效);关闭服务、其他项目 无效

如果想要多个项目共享,重启后仍然有效:JNDI

以上范围对象,尽量使用最小的范围。因为对象的范围越大,造成的性能损耗越大。

scope.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2020/10/27
Time: 11:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>scope.jsp页面</h1>
<%
//往四个域中分别保存数据
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
pageContext的域中是否有值:<%=pageContext.getAttribute("key")%><br>
request的域中是否有值:<%=request.getAttribute("key")%><br>
session的域中是否有值:<%=session.getAttribute("key")%><br>
application的域中是否有值:<%=application.getAttribute("key")%><br>

<%
request.getRequestDispatcher("/scope2.jsp").forward(request,response);
%>
</body>
</html>

scope2.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2020/10/27
Time: 11:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>scope2页面</h1>
pageContext的域中是否有值:<%=pageContext.getAttribute("key")%><br>
request的域中是否有值:<%=request.getAttribute("key")%><br>
session的域中是否有值:<%=session.getAttribute("key")%><br>
application的域中是否有值:<%=application.getAttribute("key")%><br>
</body>
</html>

当我们访问scope.jsp的时候,就会发现被请求转发(请求转发是一次请求)到scpoe2.jsp,此时pageContext的域是无值的。

image-20201028102955959

当我们访问scope2.jsp的时候,我们可以发现request域中的值也为null,因为request只在一次请求内有效。

image-20201028103136286

我们把项目重新部署之后:

image-20201028103428323

6.jsp中的out和response.getWriter输出的区别

response表示响应,用于返回给客户端内容。

out也是给用户输出使用的。

image-20201028104626139

由于jsp翻译之后,底层源代码都是使用out来输出,所以一般情况下。我们在jsp页面中统一使用out来进行输出。避免打乱页面输出内容的顺序。

out.write() 输出字符串没有问题

out.print() 输出任意数据都没有问题(都统一转化位字符串后调用write输出)

image-20201028143453859

write()方法的底层:将传进来的数字转化为char类型的字符。

所以write()方法只适合输出字符串。

所以在Jsp页面中,统一使用out.print()来进行输出。

7.Jsp的常用标签

1)静态包含

语法:<%@ include file = ""%>

地址中第一个斜杆/表示为http://ip:port/工程路径/

file属性指定你要包含的jsp路径。

2)动态包含

语法:<%jsp:include page=""%></jsp:include>

动态包含会把包含的jsp页面翻译成java代码:

JspRuntimeLibrary.include(request,response,”/include/footer.jsp”,out,false);

image-20201028151640460

3)jsp标签-转发

语法:<jsp:forward page=""></jsp:froward>

功能是请求转发,page属性是请求转发的路径。

跟Servlet的请求转发功能是一样的。

8.EL表达式

什么是EL表达式

EL表达式的全称是:Expression Language。是表达式语言。

Author: 小灰灰

Link: http://xhh460.github.io/2020/10/26/Jsp/

Copyright: All articles in this blog are licensed.

< PreviousPost
Java设计模式
NextPost >
Servlet
CATALOG
  1. 1. Jsp
    1. 1.0.1. 1.什么是Jsp?
    2. 1.0.2. 2.Jsp的本质
    3. 1.0.3. 3.Jsp的三种语法
      1. 1.0.3.1. a)Jsp头部的page命令
      2. 1.0.3.2. b)jsp中常用脚本
        1. 1.0.3.2.1. 1.声明脚本(不常使用)
        2. 1.0.3.2.2. 2.表达式脚本(常用)
        3. 1.0.3.2.3. 3.代码脚本
    4. 1.0.4. 4.Jsp中的九大内置对象(不用new)
    5. 1.0.5. 5.Jsp四种范围对象
    6. 1.0.6. 6.jsp中的out和response.getWriter输出的区别
    7. 1.0.7. 7.Jsp的常用标签
      1. 1.0.7.1. 1)静态包含
      2. 1.0.7.2. 2)动态包含
      3. 1.0.7.3. 3)jsp标签-转发
    8. 1.0.8. 8.EL表达式
      1. 1.0.8.1. 什么是EL表达式