JSP
2023年11月15日大约 10 分钟约 2028 字
服务器渲染技术-JSP[会使用]
介绍

JSP 全称是 Java Server Pages,Java 的服务器页面
JSP 这门技术的最大的特点在于,写 JSP 就像在写 HTML
● 相比 html 而言,html 只能为用户提供静态数据,而 JSP 技术允许在页面中嵌套 java 代码,为用户提供动态数据
● 相比 Servlet 而言,Servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产 生动态数据的同时,也很容易对数据进行排版。
- jsp 技术基于 Servlet, 你可以理解成 JSP 就是对 Servlet 的包装.
- 会使用 JSP 的程序员, 再使用 thymeleaf 是非常容易的事情, 几乎是无缝接轨。
入门
<%@ page import="java.io.PrintWriter" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp简单求和计算器</title>
</head>
<body>
<h1>jsp简单求和计算器</h1>
<%
//1. 在jsp的该标签中,可以写java代码
int i = 10;
int j = 20;
int res = i + j;
//2. jsp中内置对象,可以直接使用,比如 out
// 格式化快捷键 ctrl + alt + l
out.print(i + " + " + j + " = " + res);
%>
</body>
</html>
运行原理
- jsp 页面本质是一个 Servlet 程序,其性能是和 java 关联的,只是长得丑。
- 第 1 次访问 jsp 页面的时候。Tomcat 服务器会把 jsp 页面解析成为一个 java 源文件。并且对它进行编译成为.class 字节码程序。 看下 Cal.jsp 对应的 cal_jsp.java 和cal_jsp.class 文件
- 分析下 cal_jsp.java 的源码,可以看出本质就是 Servlet。(要看到源码和分析类图,需要加入 jasper.jar 这个包[在tomcat/lib 下拷贝])
(1)sum.jsp -> sum_jsp.jsp
(2)sum_jsp 继承 HttpJspBase
(3)HttpJspBase 继承了 HttpServlet
(4)结论 sum.jsp本质就是servlet
(5)因为sum_jsp 类还继承 HttpJspBase 所以就有更强的功能
常用page指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
- language 表示 jsp 翻译后是什么语言文件, 只支持 java
- contentType 表示 jsp 返回的数据类型,对应源码中 response.setContentType()参数值
- pageEncoding 属性 表示当前 jsp 页面文件本身的字符集
- import 属性 跟 java 源代码中一样。用于导包,导类
JSP常用三种脚本
声明脚本基本语法
声明脚本的格式是: <%! 声明 java 代码 %>
作用:定义 jsp 的需要属性、方法、静态代码块和内部类等
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp声明脚本</title>
</head>
<body>
<h1>jsp声明脚本</h1>
<%!
//这里我们可以声明该jsp需要使用的属性,方法,静态代码块,内部类
//也就是给 statement.jsp 对应的 statement_jsp 类定义成员
//1. 属性
private String name = "jack";
private int age;
private static String company;
//2. 方法
public String getName(){
return name;
}
//3. 静态代码块
static{
company = "阿里巴巴";
}
%>
</body>
</html>
表达式脚本基本语法
- 表达式脚本的格式是:<%=表达式%>
- 表达式脚本的作用是:在 jsp 页面上输出数据
- 表达式脚本中的表达式不能以分号结束
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>表达式脚本的使用</title>
</head>
<body>
<h1>个人信息</h1>
<%
String name = "lzw";
String email = request.getParameter("email");
%>
用户名:<%=name%><br>
工作是:<%="java工程师"%><br>
年龄:<%=request.getParameter("age")%><br>
邮箱:<%=email%><br>
</body>
</html>
代码脚本基本语法
- 代码脚本的语法是:<% java 代码%>
- 代码脚本的作用是:可以在 jsp 页面中,编写我们需要的功能(使用 java )
- 可以由多个代码脚本块组合完成一个完整的 java 语句。
- 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据
package com.lzw.entity;
public class Monster {
private Integer id;
private String name;
private String skill;
public Monster(Integer id, String name, String skill) {
this.id = id;
this.name = name;
this.skill = skill;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.lzw.entity.Monster" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>演示代码脚本</title>
</head>
<body>
<h1>演示代码脚本</h1>
<%
//创建 ArrayList,放入两个monster
ArrayList<Monster> monsterLists = new ArrayList<>();
monsterLists.add(new Monster(1, "牛魔王", "芭蕉扇"));
monsterLists.add(new Monster(2, "蜘蛛精", "吐口水"));
%>
<table bgcolor="#bfa" border="1px" width="300px">
<tr>
<th>id</th>
<th>名字</th>
<th>技能</th>
</tr>
<%
for (int i = 0; i < monsterLists.size(); i++) {
//先取出monster对象
Monster monster = monsterLists.get(i);
%>
<tr>
<td><%=monster.getId()%></td>
<td><%=monster.getName()%></td>
<td><%=monster.getSkill()%></td>
</tr>
<%
}
%>
</table>
</body>
</html>
JSP内置对象
介绍
1、JSP 内置对象(已经创建好的对象, 直接使用 inbuild),是指 Tomcat 在翻译 jsp 页面成为Servlet 后,内部提供的九大对象,叫内置对象 2、内置对象,可以直接使用,不需要手动定义
九大内置对象
- out 向客户端输出数据,out.println("");
- request 客户端的 http 请求
- response 响应对象
- session 会话对象
- application 对应 ServletContext
- pageContext jsp 页面的上下文,是一个域对象,可以 setAttribue(),作用范围只是本页面
- exception 异常对象 , getMessage()
- page 代表 jsp 这个实例本身
- config 对应 ServletConfig

package com.lzw.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class HiServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HiServlet 被调用");
PrintWriter writer = response.getWriter();
writer.println("haha");
request.getParameter("age");
response.setContentType("text/html;charset=utf-8");
HttpSession session = request.getSession();
session.setAttribute("job","java工程师");
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("count",666);
ServletConfig servletConfig = getServletConfig();
servletConfig.getInitParameter("pwd");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp内置对象</title>
</head>
<body>
<h1>jsp内置对象</h1>
<%
//jsp的内置对象
//out 类型是 JspWriter 父类就是 Writer.
out.println("jsp out");
//request是HttpServletRequest
request.getParameter("age");
//response就是 HttpServletResponse
//response.sendRedirect("http://www.baidu.com");
//session 就是 HttpSession
session.setAttribute("job", "PHP工程师");
//application类型就是ServletContext
application.setAttribute("name", "老韩老师");
//pageContext 可以存放数据(属性), 但是该数据只能在本页面使用
pageContext.setAttribute("age", 100);
//exception 异常对象 使用比较少
//page 内置对象,类似 this
out.println("page=" + page);
//config 内置对象的类型就是ServletConfig
String pwd = config.getInitParameter("pwd");
%>
</body>
age: <%=pageContext.getAttribute("age")%>
</html>
JSP域对象
JSP四大域对象
- pageContext (域对象,存放的数据只能在当前页面使用)

- request (域对象,存放的数据在一次 request 请求有效)

- session(域对象,存放的数据在一次会话有效)

- application(域对象,存放的数据在整个 web 应用运行期间有效, 范围更大)


应用实例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>scope文件</title>
</head>
<body>
<%
//在不同的域对象中,放入数据
//1. 因为四个域对象,是不同的对象,因此name(key) 相同时,并不会冲突
pageContext.setAttribute("k1","pageContext 数据(k1)");
request.setAttribute("k1","request 数据(k1)");
session.setAttribute("k1","session 数据(k1)");
application.setAttribute("k1","application 数据(k1)");
//做一个请求转发的操作
//路径
// request.getRequestDispatcher("/scope2.jsp").forward(request, response);
//做一个重定向
String contextPath = request.getContextPath();
response.sendRedirect(contextPath + "/scope2.jsp");
// response.sendRedirect("/jsp/scope2.jsp");
%>
<h1>四个域对象,在本页面获取数据的情况</h1>
pageContext-k1:<%=pageContext.getAttribute("k1")%><br>
request-k1:<%=request.getAttribute("k1")%><br>
session-k1:<%=session.getAttribute("k1")%><br>
application-k1:<%=application.getAttribute("k1")%><br>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>scope2.jsp</title>
</head>
<body>
<h1>scope2页面获取数据的情况</h1>
pageContext-k1:<%=pageContext.getAttribute("k1")%><br>
request-k1:<%=request.getAttribute("k1")%><br>
session-k1:<%=session.getAttribute("k1")%><br>
application-k1:<%=application.getAttribute("k1")%><br>
</body>
</html>
注意事项和细节
- 域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存储范围
- 从存储范围(作用域范围看) pageContext < request < session < application
JSP请求转发标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>aa.jsp</title>
</head>
<body>
<%--
1. jsp提供了很多标签,但是因为jsp不是重点,老韩就讲一个常用forward
2. jsp:forward 本质就是 等价 request.getRequestDispatcher("/bb.jsp").for...
--%>
<jsp:forward page="bb.jsp"></jsp:forward>
</body>
</html>