[TOC]

0x00 JSP基础

1.介绍

什么是JSP?它有什么用?

简介:Java Server Pager -> 从用户的角度来说就是一个网页(java + html的结合体),而从程序的角度来说最终会翻译成一个类实际就是一个Servlet及(JSP = Servlet)
作用:由于HTML在多数的情况下是显示的静态网页,但是在实际应用场景中常常需要在网页上显示一些动态数据,实际就是采用JSP访问数据库读取数据,然后再呈现给用户端网页上

Tomcat 最后会将 jsp 文件编译后的(.class-字节码文件/.java-类)存放在目录/work/Catalina/localhost/项目名/org/apache/jsp 里面:

1
2
3
//E:\Development\apache-tomcat-9.0.31\work\Catalina\localhost\Web\org\apache\jsp
$ ls
login_jsp.class login_jsp.java

在Eclipse建立的JSP文件默认的编码格式是IISO-8859-1,我们可以从 Windows->penferences->jsp Files 修改编码为UTF-8则后面建立的文件默认格式就是UTF-8了

JavaEE 架构

  • 客户层 (Web 浏览器 、Applet)
  • Web (Severlet、 Jsp)
  • 业务逻辑 (EJB)
  • 数据持久层 (数据库 MySQL , Oracle)


2.基础语法

描述:主要记录学习的JSP的基础指令写法和变量声明定义与使用;

(1) 变量定义和调用

1
2
3
4
5
6
7
8
9
10
11

//全局变量
<%! int a = 99; %>
//局部变量
<% int a = 1024; %>

//调用输出变量
<%=a %>

//JSP代码注释:
<%-- <jsp:forward page="./Demo1/forward.jsp"></jsp:forward> --%>


(2) JSP指令语法格式:
JSP的三大指令:

1
2
3
4
5
<%@ 指令名称 %>

<%@ page %>
<%@ include %>
<%@ taglib %>


page 指令进行设置当前页面的一些信息:
实例解释:

1
2
3
4
5
6
<%@ page %>
<!-- JSP File 文件头部 -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="true" errorPage="error.jsp" %>

<!-- error.jsp 文件头部 -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="true" isErrorPage="true" %>

  • language : 表示JSP文件中使用的JAVA代码
  • contentType : 表示JSP文件显示的类型以及使用什么编码,我们可以在Tomcat的web.xml看到定义的MIME-type;
  • pageEncoding : JSP文件编码格式
  • extends : 用于指定JSP翻译成为JAVA文件后继承的父类是谁(常规默认即可)
  • import : 导入指定包使用其方法;
  • session : 控制jsp页面中是否能够直接使用Session对象(即session.getAttribute(‘’) ),值可选true(默认)或者false,具体区别是翻译的.Java文件在Tomcat的Work目录之中;
  • errorPage : 指定错误的页面值需要给错误的页面路径;
  • isErrorPage : 声明某一个页面到底是不是错误页面,即errorPage指定包含isErrorPage 参数的JSP页面 <%=exception.toString();%>;


include 指令进行包含嵌套另外一个JSP的内容进来,即将另外一个文件读取包含进来(所有的标签元素)
实例解释:

1
2
3
//假如是在A页面上使用 <%@ include file="B.jsp" %>
//从页面上看 , 确实是两个 jsp 的内容组合到一起了。但是从背后翻译成的 java 文件看, 里面做了很多重复的标签输出。 其实就是既输出 A.jsp , 也输出了 B.jsp
<%@ include file="page.jsp" %>


taglib 指令:用于导入标签库 ,多用于引入 JSTL标签库

1
2
<%@ taglib prefix='' url="" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

  • url : 表示标签库路径地址
  • prefix : 标签别名表示别名或者称之为前缀也可以。


(3) 动态标签
描述:在JSP页面进行动态加载的标签;

1
2
3
<jsp:include page=""></jsp:include>
<jsp:forward page=""></jsp:forward>
<jsp:param value="" name=""/>

详细讲解:
jsp:include 动态包含指定页面,将指定页面其中body主体中的运行结果拿到本页面进行显示(即body中的内容文本);

1
2
<h1>这是Error.jsp页面body元素内的内容:</h1>
<jsp:include page="error.jsp"></jsp:include>

实际运行编译的java源码:D:\apache-tomcat-7.0.100\work\Catalina\localhost\JspDemo\org\apache\jsp\jsp_005faction_jsp.java

1
2
// 在 public void _jspService 方法里面
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "./Demo1/include.jsp", out, false);

补充知识:

  • 1.jsp:include 与 include 指令有何区别?

    答:我们上面看到jsp:include编译后可以看见java文件,前者是先解析该include.jsp后再执行拿取里面的内容,而include指令是直接将文件进行包含输出;


jsp:forward 进行请求转发到指定页面,URL还是原URL不变化;
补充:如果想关心到底底层是如何走的,可以去看jsp翻译成的那个java文件,里面有具体的翻译后的代码,再配合servlet源代码,即可找到最终的答案,就是:请求转发

1
2
<h2>请求转发到/Demo1/forward.jsp页面</h2>
<jsp:forward page="./Demo1/forward.jsp"></jsp:forward>

实际运行编译的java源码:D:\apache-tomcat-7.0.100\work\Catalina\localhost\JspDemo\org\apache\jsp\jsp_005faction_jsp.java

1
2
3
4
5
6
7
if (true) {
_jspx_page_context.forward("./Demo1/forward.jsp");
return;
}
//实际调用类和方法
javax.servlet.jsp.PageContext _jspx_page_context = null;
request.getRquestsDispatcher("./Demo1/forward.jsp").forward(request,response);


jsp:param 在进行包含页面或者进行请求转发设置时带的请求参数与值;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// jsp_action.jsp
<h3>请求转发携带指定参数到/Demo1/forward.jsp页面</h3>
<jsp:forward page="./Demo1/forward.jsp">
<jsp:param value="WeiyiGeek" name="name"/>
<jsp:param value="18" name="age"/>
<jsp:param value="Computer" name="Love"/> <%-- 注意这里如果是中文会在输出时候乱码,在后面的课程之中进行改进 --%>
</jsp:forward>


// /Demo1/forward.jsp
<h1>Forward.jsp?<%=request.getQueryString() %></h1>
<p>显示转发请求的参数:</p>
Name:<%=request.getParameter("name") %>
<br>
Age:<%=request.getParameter("age") %>
<br>
喜好:<%=new String(request.getParameter("Love").getBytes("ISO-8859-1"),"UTF-8") %>

实际运行编译的java源码:D:\apache-tomcat-7.0.100\work\Catalina\localhost\JspDemo\org\apache\jsp\jsp_005faction_jsp.java

1
2
3
4
5
6
7
8
9
10
11
if (true) {
_jspx_page_context.forward("./Demo1/forward.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("name", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("WeiyiGeek", request.getCharacterEncoding()) + "&" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("age", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("18", request.getCharacterEncoding()));
return;
}

//执行结果:
Forward.jsp?name=WeiyiGeek&age=18&Love=Computer
显示转发请求的参数:
Name:WeiyiGeek
Age:18
喜好:Computer


3.内置对象

描述:我们在JSP页面中无需进行创建以及手动导包,就直接在jsp页面中使用这些对象。

(1)内置对象说明
九大内置对象:

1
2
3
4
5
6
7
8
9
10
11
12
page [Object]  //实际就是该jsp翻译成为Java类的实例对象;
exception [Throwable] //需要在page指令中加上isErrorPage的页面上显示使用
config [Servlet]

out [JspWriter]
response [HttpServletResponse]

//#后四个是作用域对象
pageContext [PageContext]
request [HttpServletRequest]
session [HttpSession]
application [ServletContext]


实际案例jsp_inner.java与java文件对照:

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>内部对象</title>
</head>
<body>

<h1>九大内置对象</h1>
<%=page.toString() %>
<br>
<%--=exception.toString() --%>
<%=config.toString() %>
<br>
<% out.write("\n 其次输出jspWriter 对象输出 <br>"); %>
<br>
<% response.getWriter().write("\n 首先输出 Response 对象输出 <br>"); %>

<h2>内置作用域对象设置</h2>
<% pageContext.setAttribute("name", "pageContext"); %>
<% request.setAttribute("name", "request"); %>
<% session.setAttribute("name", "session"); %>
<% application.setAttribute("name", "application"); %>

<hr>
<p>四大内置作用域对象输出</p>
<%=pageContext.getAttribute("name") %>
<%=request.getAttribute("name") %>
<%=session.getAttribute("name") %>
<%=application.getAttribute("name") %>
</body>
</html>


<!--
Tomcat 封装后的 isp_005finner_jsp.java 文件
内置对象定义的原型
-->
final java.lang.Object page = this; //该JSP翻译成.java的实例对象this
final javax.servlet.ServletConfig config;
final javax.servlet.http.HttpServletRequest request
java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
javax.servlet.jsp.JspWriter out = null;

<!-- 内置对象的作用域 -->
final javax.servlet.http.HttpServletResponse response
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;

执行效果:

WeiyiGeek.内置对象

WeiyiGeek.内置对象


注意事项及其补充:

  • 1.response与out内置对象的输出比较,我们从上面可以看出虽然response.getWrite.write()放在了out.Write()后面但是在输出的时候任然输出在前;
    1
    2
    3
    4
    5
    6
    //我们可以翻看Servlet源码进行查看或者工程封装的jsp java文件中查看
    out.write("\n 其次输出jspWriter 对象输出 <br>");
    out.write("\r\n");
    out.write("<br>\r\n");
    out.write("\r\n");
    response.getWriter().write("\n 首先输出 Response 对象输出 <br>");
    WeiyiGeek.response与out内置对象的输出

    WeiyiGeek.response与out内置对象的输出


2) 四个作用域对象

0.对应的类型是 PageContext . 该对象是四个作用域之一, 一般使用该对象来存取值 以及 获取其他八个内置对象(但是由于其他内置对象都可以直接使用,所以该作用一般比较少用了)

  • 存取值:setAttribute 和 getAttribute
  • 注意:该对象所存的值只能在该页面上取出来,也就是说它的作用域值能是当前页面。

1.request:该对象是 HttpServletRequest 的实例, 在这里的使用手法与java 代码中的使用手法是一样的。 该对象是四个作用域之一 , 通常在 jsp 页面用来存取值 和 跳转。

  • 跳转:request.getRequestDispatcher(“”).forward(request, response);
  • 存取值:使用的方法是 setAttribute 和 getAttribute .
    注意:该对象的作用域 ,仅限于一次请求中。当服务器对该请求做出响应后,就无法在其他的地方获取里面存的值了。

2.Session: 默认情况下jsp 翻译成 java 文件后,会在里面的方法调用 request.getSession().那么咱们可以直接在 jsp 里面使用 session 对象, 我们一般使用这个对象来存取值。

  • 在顶部的 page 指令里面有一个属性叫做 session=”true” 默认即是 true, 如果是 true 那么就会创建 session 对象。如果 session 属性 的值 是 false , 那么我们在 jsp 页面上,将无法使用 session 对象。因为翻译成的 java 类中,根本没有创建这个对象。
  • 存取值其实就是setAttribute 和 getAttribute 而已。
  • 注意:该对象存的值是在一次会话后(多次请求和响应)内有效。

3.application:该对象是 ServletContext 类的实例, 可以做ServletContext的事情。 但是一般在jsp页面里面,我们使用该对象,多数情况都是来进行存值和取值。

  • 我们使用该对象最多的两个方法是: setAttribute(”name” ,”weiyigeek.top”)和 getAttribute(“name”);
  • 注意:该对象的作用域是最大的,直到服务器停止。也就是说在A.jsp页面中使用该对象存值, 在任何一个jsp页面上,都可以取值。


四个作用域的区别

  • pageContext 【PageContext】

    作用域仅限于当前的页面否则返回NULL,还可以获取到其他八个内置对象。

补充:

1
${pageContext.request.contextPath}  #Web项目根路径(即项目上下文路径)

  • request 【HttpServletRequest】

    作用域仅限于一次请求, 只要服务器对该请求做出了响应,转发是可以获取请求的参数值,而重定向不得到重定向网页前的参数返回为NULL

  • session 【HttpSession】

    作用域限于一次会话(多次请求与响应) 当中,如果在每有设置该Sesssion属性前访问打印该属性值的页面则返回NULL;

  • application 【ServletContext】

    整个工程都可以访问, 服务器关闭后就不能访问了。


2.JSP 进阶

1.EL表达式

什么是EL表达式?它有什么作用?

答:全称是 Expression Language , 作用是为了简化咱们的 jsp 中的 java 代码
答:获取4个内置对象(域)中的数据,或自定义对象中的数据,或数组、集合容器中的数据。可以完成非常简单的运行技术,但它不能完成复杂的循环、复杂的判断等功能。

EL表达式写法格式:

1
2
3
4
5
6
7
${ 表达式}

//常用的EL表达式基础(可以查看文档)
${ a [ - + * / ] b } //算术运算符表达式
${ a [> < == >= <= != | gt lt ] b } //条件运算符
${ empty u } //判断是否为空
${ u.name } //常用属性取值

注意事项:

  • 1.它与JSP文件变量的调用输出不一致需要学习其语法,并且不想在写 <% %> jsp代码时候会提醒;
  • 2.EL表达式查找变量的顺序先从page->request->session->application等四大作用域一个一个查找key并输出其值(先查到先输出);


(1)EL表达式取出变量
描述:EL表达式可以简化JSP代码输出内置对象定义的变量值,可以输出变量、数组、集合、MAP、等变量中的值;

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
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.HashMap"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式</title>
</head>
<body>

<p>1) 采用EL表达式输出变量属性的值</p>
<%
int a = 1024;
String b = "Java Program";
pageContext.setAttribute("a",a);
pageContext.setAttribute("b",b);
%>

${a}
${b}

<hr>

<p>2) 采用EL表达式输出内置4大域对象定义的属性</p>
<%
pageContext.setAttribute("name", "pageContext");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>

${pageScope.name}
${requestScope.name}
${sessionScope.name}
${ applicationScope.name }

<hr>

<p>3) 采用EL表达式输出数组内容</p>
<%
String[] name = {"WeiyiGeek","Weiyi","Weiye"};
pageContext.setAttribute("arrayName", name);
%>

${arrayName[0]} ,${ arrayName[1] },${ arrayName[2] }

<hr>

<p>4) 采用EL表达式输出数组集合 ArrayList 内容</p>
<%
ArrayList al = new ArrayList();
al.add("abc");
al.add("def");
al.add("1024");
pageContext.setAttribute("al", al);
%>

${al[0]},${al[1]},${al[2]}

<hr>


<p>5) 采用EL表达式输出数组集合 Map 内容</p>
<%
Map map = new HashMap();
map.put("a","map集合需要导包");
map.put("b","WeiyiGeek");
map.put("c.d",1024); //特殊部分
pageContext.setAttribute("map", map);
%>

${map.a},${map.b},${map["c.d"]}

<hr>

<p>6)获取javabean之自定义对象的数据(需要采用page指令导包)</p>
<%--
Person person=new Person();
person.setName("taoshihan");
pageContext.setAttribute("person",person);
--%>
取值的方式:${person.name}

</body>
</html>

执行结果:

WeiyiGeek.EL表达式

WeiyiGeek.EL表达式


1.EL内置对象

描述:下面显示了11个内置对象;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#常用
- pageContext
- initParam #全局初始化参数

#作用域相关对象
- pageScope
- requestScope
- sessionScope
- Application

# 头信息相关对象
- header
- headerValues

#请求参数相关
- param
- params

# cookies信息相关
- cookie

基础示例:

1
2
3
4
5
6
7
8
9
<p>1) 获取URL请求参数 </p>
方式1: <%=request.getParameter("name") %>
<br>
方式2: ${param.name}


<p>2) 获取请求的Cookies的key和值 </p>
<% response.addCookie(new Cookie("name","weiyigek")); %>
${cookie.name.name} 值: ${cookie.name.value}

执行结果:http://127.0.0.1:8080/JspDemo/el_inner.jsp?name=WeiyiGeek

1
2
3
4
5
6
1) 获取URL请求参数
方式1: WeiyiGeek
方式2: WeiyiGeek

2) 获取请求的Cookies
获取Cookie的:name值:weiyigek