JavaWeb03
一、JSP
1、第一个JSP程序及原理
再WEB-INF目录外新建一个hello.jsp文件,里面没有任何内容即可
启动服务器后访问http://localhost:8080/xmm/hello.jsp
实际上执行的是hello_jsp.java编译后的hello_jsp.class文件
由Tomcat服务器将jsp文件翻译生成java文件,再编译
hello_jsp这个类实际上是一个Servlet类,其生命周期和Servlet相同
hello_jsp继承HttpJspBase类,HttpJspBase继承HttpServlet
Servlet和jsp的职责不同,Servlet主要收集数据并处理业务,jsp主要展示数据
// 借助JSP,我们无需再手动实现以下过程
out.println("<html>");
...
out.println("</html>");
(3)JSP是一套规范
JSP规范是JavaEE的13个规范之一
所有的Web服务器实现了这套规范
根据这套规范将jsp文件翻译成相应的Java文件
2、JSP的基础语法
(1)在jsp文件中直接写文字
会被直接翻译到Servlet类的Service方法的out.write() 方法里
(2)page指令
设置响应的内容类型,可以解决响应时的中文乱码问题
直接在jsp文件中写 <%@page contentType = "text/html;charset=UTF-8" %>
(3)在jsp中写Java代码
用<% Java代码; %> 的格式编写,中间的Java代码会被翻译到service方法体中
在这里写Java代码等同于在service方法体中写
这里的Java代码如果有编译错误,仍然可以翻译生成java文件,但无法编译生成class文件
在同一个jsp文件中,可以出现多个<% %>
也可以用 <%! Java代码; %> 的格式,会被翻译到Hello_jsp类体中(很少用,线程不安全)
(4)在jsp中向浏览器输出一个Java变量
out是jsp的九大内置对象之一,可以直接用(在service方法内部)
<% String name = "bob"; out.write("name = " + name);
%>也可以:
<%= 100 + 200 %>
<%= name %>
会被翻译到service方法内:
out.print( 100 + 200 );
out.print( name );
(5)jsp的注释格式
<%-- 注释内容 --%> 是专业的jsp注释,不会被翻译到Java源代码中
<!-- HTML --> 是HTML的注释,会被当成普通文本进行翻译,out.write("<!-- HTML -->");
(6)JSP文件的扩展名
可以在CATALINA_HOME/conf/web.xml文件中进行配置,不一定是Xxx.jsp
JSP文件对Tomcat来说只是一个文本文件
3、JSP和Servlet配合使用
(1)分工
Servlet连接数据库,获取数据,处理业务逻辑
JSP负责数据展示
(2)操作步骤
在Servlet中连接数据库并查询数据,封装成Java的实体类对象
将这些对象放入一个集合中,将这个集合存入request请求域对象
在Servlet中进行转发,到JSP
在JSP中获取这个集合并进行数据的动态展示
<%-- 数据的动态展示(仍待优化的版本) --%>
<%List<Dept> deptList = (List<Dept>)request.getAttribute("depts");int i = 0;for (Dept dept: deptList) {
%>
<tr><td><%=++i%></td><td><%=dept.getDeptNum()%></td><td><%=dept.getName()%></td>
</tr>
<%}
%>
4、JSP的指令
(1)作用
指导JSP的翻译引擎将jsp文件翻译成Java文件
(2)分类
include指令:在JSP中完成静态包含(现在很少用)
taglib指令:引入标签库,在学习JSTL标签库时会涉及到
page指令:目前重点学习
(3)指令的使用语法
<%@指令名 属性名=属性值 属性名=属性值%>
(4)page指令的常见属性
session属性:为true则表示启用session对象,没有该对象则创建;为false则无法使用该对象
contentType属性:设置响应的内容类型,也可以设置字符集
pageEncoding属性:设置响应的字符集
import属性:导入Java包
errorPage属性:当前页面出异常后的跳转到的错误页面的路径
isErrorPage属性:为true则启用exception对象,在错误页面中使用,用exception对象输出报错信息
5、JSP的九大内置对象
(1)四个作用域对象
页面作用域:jakarta.servlet.jsp.PageContext pageContext
请求作用域:jakarta.servlet.http.HttpServletRequest request
会话作用域:jakarta.servlet.http.HttpSession session
应用作用域:jakarta.servlet.ServletContext application
作用域范围的大小:pageContext < request < session < application
使用原则:尽可能使用小的域
(2)异常对象
java.lang.Throwable exception
(3)配置对象
jakarta.servlet.ServletConfig config
(4)this对象(当前servlet对象)
java.lang.Object page
(5)响应和输出对象
输出对象:jakarta.servlet.jsp.JspWriter out
响应对象:jakarta.servlet.http.HttpServletResponse response
二、Session机制
1、简介
B/S架构的会话机制,属于B/S架构的一部分,使用其他语言开发也有Session机制
用户打开浏览器,进行一系列操作,最后关闭浏览器,整个过程称为一次会话
一个会话中可以有多次请求
会话在服务器端对应一个Java对象session(包名为jakarta.servlet.http.HttpSession)
2、session对象
(1)作用
session对象的主要作用:保存会话信息和状态
Http协议是无状态协议,每次请求结束后,浏览器和服务器连接会断开,以减轻服务器压力
因此需要session会话域对象来保存会话状态(比如登录状态等)
session对象也有setAttribute和getAttribute方法
request请求域对象的域太小,ServletContext应用域对象的域太大
(2)获取session对象
// 从服务器端获取当前的session对象
// 如果没有则新建一个
HttpSession session = request.getSession();// 如果传入一个false,就算没有获取到也不会新建
HttpSession session = request.getSession(false);
当一段时间内,某个会话里没有请求,则会销毁这个session对象(超时机制)
也可以手动销毁,当用户退出时点击安全退出,发送请求通知服务器销毁session对象
注意:直接关闭浏览器时,服务器不知道浏览器关闭
JSP也是一个Servlet,JSP翻译后的Java程序会创建一个session对象
如果不想让它创建,使用<%page session="false"%>,写上之后session对象无法使用
3、Session机制的实现原理
Web容器中有一个session列表,类似于Map集合
键是sessionId,值是session对象
第一次请求:服务器创建session对象并发送Id给浏览器,浏览器将sessionId存在缓存中
后续请求:浏览器将sessionId携带在请求中,服务器据此找到相应的session对象
关闭浏览器后,缓存中的sessionId会被清除,一段时间后session对象被服务器销毁
JSESSIONID=xxxx,以Cookie的形式存储在浏览器的缓存中
如果Cookie被禁用,代表浏览器拒收sessionId,此时可以使用URL重写机制
4、用Session机制实现登录功能
@WebServlet("/user/login")
public class LoginServlet extends HttpServlet {@overrideprotected void doLogin(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {boolean loginSucceed = false;// 这里写登录的业务逻辑 ......if (loginSucceed) {HttpSession session = request.getSession();session.setAttribute("username", username); } }@overrideprotected void doExit(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {HttpSession session = request.getSession(false);if (session != null) {// 手动删除session对象session.invalidate();response.sendRedirect(request.getContextPath()); }}
}@WebServlet("/dept/*")
public class DeptServlet extends HttpServlet {@overridepublic void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 这里最好传入false,无需新建HttpSession session = request.getSession(false);if (session != null && session.getAttribute("username") != null) {// 执行业务逻辑 ...... } else {// 访问Web应用的根路径,重定向到欢迎页面response.sendRedirect(request.getContextPath()); }}
}
三、Cookie
1、与session的关联
每个session对象有Id,如JSESSIONID=41C481F0224664BDB28E95081D23D5B8
这个键值对就是一个cookie对象
对于session关联的cookie来说,这个cookie被保存在浏览器的运行内存中
只要浏览器不关闭,再发送请求时,会自动将浏览器运行内存中的cookie携带到服务器端
例如Cookie: JSESSIONID=41C481F0224664BDB28E95081D23D5B8
服务器根据41C481F0224664BDB28E95081D23D5B8这个值来找到session对象
2、与session对比
二者都是为了保存会话的状态
cookie将会话的状态保存在浏览器客户端(cookie数据存储在浏览器,可以在内存或磁盘)
session将会话状态保存在服务器端(session对象存储在服务器)
cookie和session机制都是Http协议的一部分
案例:在未登录时将商品添加到购物车,将商品编号添加到cookie,将cookie保存到硬盘
3、格式
任何一个cookie都是由name和value组成的,name和value都是字符串
4、在Java中使用cookie
(1)Cookie类简介
JavaEE提供了一个Cookie类来专门表示cookie数据
jakarta.servlet.http.Cookie
这个类只有有参构造方法,需要传入name和value
(2)将cookie数据返回给浏览器
response.addCookie(cookie);
(3)Cookie的有效时间
// 设置cookie的有效时间,以秒为单位
// 如果大于零,会存储到硬盘
// 如果等于零,会删除所有同名的cookie
// 如果小于零,等同于不设置
// 如果不设置有效时间,默认保存在浏览器的运行内存中
public void setMaxAge(int empiry);
(4)Cookie的path
每个cookie会关联一个路径path
当浏览器发送请求的路径是path或其子路径时,会自动携带cookie数据给服务器
通过cookie.setPath() 方法可以手动设置path
(5)服务器获取cookie数据
使用request对象的getCookies方法,返回值是数组
Cookie[ ] cookies = request.getCookies();
如果浏览器没有携带cookie,返回null,而不是长度为零的数组