Java Web 学习日记(2)
XML
XML 简介
什么是 XML: XML 是可扩展的标记性语言。
作用:
1、用来保存数据,而且这些数据具有自我描述性。
2、可以作为项目或者模块的配置文件。
3、可以作为网络传输数据的格式。
第一个 XML 实例文件
组成部分
1、文档声明
2、元素(标签)
3、xml 属性
4、xml 注释
5、文本区域(CDATA区)
<?xml version="1.0" encoding="utf-8" ?>
<!--
以上内容就是xml文件的声明
version="1.0" version 表示 xml 的版本
encoding="utf-8" encoding 表示 xml 文件本身的编码
-->
<books> <!-- books 表示多个图书信息 -->
<book sn="SN2314234"> <!-- book 表示一个图书信息,sn 属性表示图书序列号 -->
<name>时间简史</name> <!-- name 表示书名 -->
<author>霍金</author> <!-- author 表示作者 -->
<price>75</price> <!-- price 表示价格 -->
</book>
<book sn="SN5435345"> <!-- book 表示一个图书信息,sn 属性表示图书序列号 -->
<name>史记</name> <!-- name 表示书名 -->
<author>司马迁</author> <!-- author 表示作者 -->
<price>15</price> <!-- price 表示价格 -->
</book>
</books>
xml 语法介绍
注释语法和 html 一样 <!-- -->
xml 元素:xml 元素是从开始标签到结束标签的部分。
元素可以包含其他元素,文本或者两者的混合物,元素也可以拥有属性。
xml 元素的命名规则:
-
名称可以包含字母,数字和其他的字符
-
名称不能以数字或者标点符号开始
-
不能包含空格
XML 属性
xml 的标签属性和 html 的标签属性是非常类似的,属性可以提供元素的额外信息。
在标签上可以书写属性:
-
一个标签上可以书写多个属性,每个属性的值必须使用引号引起来
-
所有 xml 元素都需要有关闭标签
-
xml 对大小写敏感
-
xml 文档必须有根元素,根元素就是顶级元素,没有父标签的元素,叫做顶级元素,根元素是没有父标签的顶级元素,且必须唯一。
xml 特殊字符
< : <
: >
文本区域(CDATA 区)
CDATA 格式:
在该区域内的文字不会被解析。
xml 解析技术介绍
xml 是标记型文档,都可以使用 w3c 组织制定的 dom 技术解析。
早期 JDK 为我们提供了两种 xml 解析技术 Dom 和 Sax (已过时)
第三方的解析技术
jdom 在 dom 上进行了封装
dom4j 对 jdom 进行封装
pull 朱勇用在 Android 手机开发中,是在跟 sax 非常类似都是事件解析 xml 文件。
dom4j
由于 dom4j 它不是 sum 公司的技术,所以需要 dom4j 的 jar 包。
package com.an.pojo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.List;
/**
* @author an
* @create 2021-05-09-19:34
*/
public class Dom4jTest {
@Test
public void test1() throws DocumentException {
// 创建一个 SaxReader 输入流,去读取 xml 配置文件,生成 Document 对象
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/books.xml");
System.out.println(document);
}
/**
* 读取 books.xml 文件生成 book 类
*
*/
@Test
public void test2() throws Exception {
// 1、读取 books.xml
SAXReader reader = new SAXReader();
// 在 Junit 中,相对路径从模块名开始算
Document document = reader.read("src/books.xml");
// 2、通过文档对象获取根元素
Element rootElement = document.getRootElement();
System.out.println(rootElement);
// 3、通过根元素获取 book 标签对象
// element 和 elements 都是通过标签名查找子元素
List<Element> books = rootElement.elements("book");
// 4、遍历、处理每个 book 标签转化为 book 对象
for(Element book : books) {
// asXML 把标签对象转化为标签字符串
// System.out.println(book.asXML());
Element nameElement = book.element("name");
// System.out.println(nameElement);
// getText() 可以获取标签内文本内容
String nameText = nameElement.getText();
//直接获取指定标签名的文本内容
String priceText = book.elementText("price");
String authorText = book.elementText("author");
String snValue = book.attributeValue("sn");
System.out.println(new Book(snValue,nameText, BigDecimal.valueOf(Double.parseDouble(priceText)),authorText));
}
}
}
Tomcat
JavaWeb 概念
什么是 JavaWeb ?
JavaWeb 是指,所有通过 Java 语言编写可以通过浏览器访问的程序的总称,叫 JavaWeb。
JavaWeb 是基于请求和相应开发的。
什么是请求?
请求是指客户端给服务器发送数据,叫请求 Request。
什么是相应?
相应是指服务器给客户端回传数据,叫响应Response。
请求和响应是成对出现的。
web 资源的分类
web 资源按照实现的技术和呈现的效果不同,又分为静态资源和动态资源两类。
静态资源:html 页面,css 样式,js,txt,MP4,jpg 等
动态资源:jsp页面,Servlet 程序等
常见的 Web 服务器
Tomcat: 由 Apache 组织提供的一种 web 服务器,提供对 jsp 和 Servlet 的支持,它是一种轻量级的 javaWeb 容器(服务器),也是当前应用最广的 JavaWeb 服务器 (免费)。
Jboss: 是一个遵从 JavaEE 规范的、开源的、纯 Java 的 EJB 服务器,它支持所有的 JavaEE 规范(免费)。
GlassFish: 由 Oracle 公司开发的一款 JavaWeb 服务器,是一款强健的商业服务器,应用少。
WebLogic: 是 Oracle 公司的产品,是目前收费应用最广泛的 Web 服务器,支持 JavaEE 规范。
Resin: CAUCHO 公司的的产品,收费,应用多。
Tomcat 和 Servlet 版本的对应关系
Servlet 从 2.5 版本是现在使用最多的版本 (XML) 3.0 后注解。
Tomcat 使用
a) 安装
找到需要用的 tomcat 版本对应的 zip 压缩包,解压到相应的目录即可。
b) 目录介绍
-
bin 用来存放 tomcat 的可执行程序
-
conf 存放 tomcat 的配置文件
-
lib 存放 tomcat 服务器 jar 包
-
logs 存放 tomcat 服务器运行时输出的日志信息
-
temp 专门用来存放 tomcat 运行时产生的临时数据
-
webapps 存放部署的 web 工程
-
work tomcat 工作时的目录,用来存放 tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session 钝化的目录
c) 启动 tomcat 服务器
找到 tomcat bin/startup.bat 双击启动。
如何测试 tomcat 是否启动成功
打开浏览器,在浏览器中输入以下地址信息:
常见启动失败有,双击 startup.bat 闪退,这个时候基本上是因为没有配置好 javaweb
启动 tomcat 服务器的方式二:
打开命令行,cd 到 tomcat 目录下,敲入启动 catalina run
d) 停止 tomcat
1、点击命令行窗口的关闭按钮
2、把 tomcat 服务器窗口设置为当前窗口,按 ctrl+c
3、找到 tomcat 的 bin 目录下的 shutdown.bat 双击
e) 修改 tomcat 端口号
Mysql 默认的端口: 3306
Tomcat 默认的端口: 8080
找到 tomcat 目录下的 conf 目录,找到 server.xml 配置文件
修改 port 属性,1-65535。
修改后必须重启 tomcat 后才可以生效。
平时上百度: http://www.baidu.com:80
http 协议默认的端口号是 80
f) 如何部署 web 工程到 Tomcat 中
1、只需要把 web 工程的目录拷贝到 webapps 目录下即可
如何访问 tomcat 下的 web 工程 + localhost:8080/book/index.html
2、在 conf/catalina/localhost
中,创建如下的配置文件
<!--
Context 表示一个工程上下文,
path 表示工程的访问路径
docbase 表示工程目录在哪
-->
<Context path="/abc" docBase="E:\IdeaProjects\JavaWeb\out\artifacts\web03_war_exploded" />
g) 在浏览器直接查看本地 html 文件和在浏览器中输入 http://ip:端口号/工程名/ 访问的区别
直接查看:浏览器地址如下 file:///D://xxx.html
使用的协议为 file 协议,告诉浏览器直接读取 file 协议后的路径,解析展示在浏览器上。
如果是在浏览器地址栏中输入访问地址格式如下:http://ip:port/工程名/资源名 所使用的协议是 http 协议,客户端发送请求,服务器收到请求后,读取要访问的文件,然后回传给客户端要的页面的内容。
h) root 工程的访问以及默认的 index.html 页面的访问
当我们在浏览器地址栏中输入访问地址如下:
没有工程名时,默认访问的是 root 工程。
当我们在浏览器中访问地址如下:http://ip:port/工程名/ ,默认访问 index 页面
IDEA 整合 tomcat 服务器
a) 如何创建动态 web 工程
1、
2、
3、输入模块名,点击 finish 完成创建
src 存放自己编写的源代码,web 目录专门用来存放 web 工程的资源文件,比如 html、css 等。
web-inf 目录是一个受服务器保护的目录,浏览器无法直接访问此目录的内容。
web.xml 是整个动态 web 工程的配置部署描述文件,可以在这里配置很多 web 工程的组件,比如:Serlet 程序, Filter 过滤器,Session 组件等等。
lib 用来存放第三方的 jar 包。
如何在 idea 中启动 tomcat 模板
1、建议修改 web 工程对应的 Tomcat 运行实例
2、将要部署的 web 工程添加到 tomcat 实例中
3、可以修改 tomcat 实例启动后默认的访问地址
4、点击运行按钮
5、资源的热部署。。。
Servlet 技术
什么是 Servlet
1、Servlet 是 JavaEE 规范之一,规范就是接口
2、Servlet 是 JavaWeb 三大组件之一,三大组件分别是:Servlet 程序,Filter 过滤器,Listner 监听器
3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并相应数据给客户端。
手动实现 Servlet 程序
1、编写一个类去实现 Servlet 接口
2、实现 service 方法,处理请求,并相应数据
3、到 web.xml 中配置 servlet 程序的访问地址
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 给 Tomcat 配置 servlet 程序 -->
<servlet>
<!-- 给 servlet 程序起一个别名(一般是类名) -->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet-class 是 Servlet 的全类名 -->
<servlet-class>com.an.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 给 Servlet 程序配置访问地址 -->
<servlet-mapping>
<!-- 告诉服务器当前配置的地址给哪个 Servlet 程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置访问地址
/ 斜杠表示地址为 http://ip:port/工程路径
/ hello 表示地址为 http://ip:port/工程地址/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
HelloServlet
package com.an.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* @author an
* @create 2021-05-09-21:53
*/
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service 方法:是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被访问了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
url 地址如何定位到 Servlet 程序去访问
Servlet 生命周期方法
1、执行 Servlet 构造器方法
2、执行 init 初始化方法
第 1、2 步是在第一次访问的时候,创建 Servlet 程序会调用
3、执行 Servlet 方法
第 3 步,每次访问都会调用
4、执行 destroy 销毁方法
第 4 步,在 Web 工程停止的时候调用
package com.an.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* @author an
* @create 2021-05-09-21:53
*/
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1、构造器方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2、init初始化方法");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service 方法:是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3、Service ===> Hello Servlet 被访问了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4、destroy 方法");
}
}
Servlet 请求的分发处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/06_servlet/hello" method="get">
<input type="submit"/>
</form>
</body>
</html>
HelloServlet.java
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3、Service ===> Hello Servlet 被访问了");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
System.out.println(method);
if("GET".equals(method)) {
doGet();
} else if("POST".equals(method)) {
doPost();
}
}
/**
*
* 做 get 请求的操作
*
*/
public void doGet() {
System.out.println("get 请求");
}
public void doPost() {
System.out.println("post 请求");
}
通过继承 HttpServlet 实现 Servlet 程序
一般在实际项目中,都是使用继承 HttpServlet 类的方法来实现 Servlet 程序。
1、编写一个类继承 HttpServlet 类。
2、根据业务需要重写 doGet 或 doPost 方法。
3、到 web.xml 中的配置 Servlet 程序的访问地址。
public class HelloServlet2 extends HttpServlet {
/**
* 处理 get 请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("HelloServlet2 的 doGet 方法");
}
/**
*
* 处理 post 请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("HelloServlet2 的 doPost 方法");
}
}
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>com.an.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
使用 idea 创建 Servlet 程序
Servlet 类的继承体系
ServletConfig 类
ServletConfig 从类名上看是 Servlet 程序的配置信息类。
a) ServletConfig 类的三大作用
1、获取 Servlet 程序的别名 servlet-name 的值
2、获取初始化参数 init-param
<servlet>
<!-- 给 servlet 程序起一个别名(一般是类名) -->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet-class 是 Servlet 的全类名 -->
<servlet-class>com.an.servlet.HelloServlet</servlet-class>
<!-- init-param 是初始化参数 -->
<init-param>
<!-- 是参数名 -->
<param-name>url</param-name>
<!-- 是参数值 -->
<param-value>jdbc:mysql://localhost:3306/test/</param-value>
</init-param>
</servlet>
3、获取 ServletContext 对象
Servlet 和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。
Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象。
ServletContext 类
a) 什么是 ServletContext 类
1、ServletContext 是一个接口,它表示 Servlet 上下文
2、一个 web 工程。只有一个 ServletContext 对象实例
3、ServletContext 对象是一个域对象
域对象,可以像 map 一样存储数据的对象叫做域对象,这里的域指的是存储数据的操作范围。
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put | get | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
b) 四个常用作用
1、获取 web.xml 中配置的上下文参数 context.param
2、获取当前的工程路径,格式: /工程路径
3、获取工程部署后在服务器硬盘上的绝对路径
4、像 Map 一样存储数据
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>com.an.servlet.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>/contextservlet</url-pattern>
</servlet-mapping>
<!-- context-param 是上下文参数, 它属于整个 web 工程 -->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>
public class ContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1、获取 web.xml 中配置的上下文参数 context.param
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println(username);
//
// 2、获取当前的工程路径,格式: /工程路径
System.out.println(context.getContextPath());
// 3、获取工程部署后在服务器硬盘上的绝对路径
System.out.println(context.getRealPath("/"));
// 4、像 Map 一样存储数据
context.setAttribute("key1","value1");
System.out.println(context.getAttribute("key1"));
}
}
HTTP 协议
协议: 双方,或多方,相互约定号,大家都需要遵守的规则叫协议。
HTTP 协议:就是指客户端和服务器之间通信式发送的数据,需要遵守的规则,叫做 HTTP 协议。
HTTP 协议中的数据叫做报文。
客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫做响应。
- GET 请求
1、请求行
(1) 请求的方式
(2) 请求的资源路径(+?+请求的参数)
(3) 请求的协议的版本号
2、请求头
key:value 组成不同的键值对,表示不同的含义
有哪些:
1、form 标签 method=get
2、a 标签
3、link 标签引入 css
4、script 标签引入 js 文件
5、img 标签引入图片
6、iframe 标签引入 html 页面
7、在浏览器地址栏输入地址后敲回车
- POST 请求
1、请求行
2、请求头
空行
3、请求体 === > 发送给服务器的数据
有哪些:
1、form 标签 method=post
- 相应的 HTTP 协议格式
1、相应行
(1) 响应的协议和版本号
(2) 响应状态码
(3) 响应状态描述符
2、响应头
(1) key:value
空行
3、响应体 ->> 回传给客户端的数据
MIME 类型说明
MIME 是 HTTP 协议中数据类型
MIME 的英文全称是 "Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务,MIME 类型的格式是 "大类型/小类型",并与某一种文件的扩展名对应。
HTTPServletRequest 类
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。然后传递到 service 方法中给我们使用,我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
常用方法
方法名 | 用途 |
---|---|
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值的时候使用) |
getMethod() | 获取请求的方式 GET 或 POST |
setAttribute(key,value) | 设置域数据 |
getAttribute(key) | 获取域数据 |
getRequestDispatcher() | 获取请求转发对象 |
获取get请求参数
<form action="http://localhost:8080/06_servlet/hello2" method="get">
用户名: <input type="text" name="username"> <br/>
密码: <input type="password" name="password"> <br/>
<input type="submit"/>
</form>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String u = req.getParameter("username");
String p = req.getParameter("password");
System.out.println(u+" "+p);
}
中文乱码问题
req.setCharacterEncoding("UTF-8"); // 要在获取请求参数之前调用才有效
请求转发
什么是请求转发?
请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作。
package com.an.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-05-23-16:12
*/
public class Servlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求的参数
String username = request.getParameter("username");
System.out.println("在 Servlet1 柜台 1 中查看参数:" + username);
// 使用域数据给材料盖章,并传递到 Servlet2 查看
request.setAttribute("key","柜台1的章");
// 问路, 柜台2怎么走
/*
请求转发必须要以 / 打头,斜杠表示地址为 http://ip:port/工程名/
映射到 IDEA 代码的 web 目录
*/
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
// 走向 servlet2
requestDispatcher.forward(request,response);
}
}
package com.an.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-05-23-16:13
*/
public class Servlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求的参数
String username = request.getParameter("username");
System.out.println("在 Servlet2 柜台 1 中查看参数:" + username);
// 查看柜台1是否盖章
Object key = request.getAttribute("key");
System.out.println("柜台1是否有章"+key);
// 处理自己的业务
System.out.println("servlet2");
}
}
浏览器输入
http://localhost:8080/06_servlet/servlet1?username=an
控制台打印
请求转发特点
1、浏览器地址栏没有变化
2、它们是一次请求
3、它们共享 Request 域中的数据
4、可以转发到 WEB-INF 目录下
base 标签的作用
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是 a 下的 b 下的 c
<a href="../../index.html">跳回首页</a>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是 web 下的 index.html
<a href="a/b/c.html">a/b/c.html</a>
</body>
</html>
添加请求转发
package com.an.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-05-23-16:37
*/
public class ForwardC extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("经过了ForwardC程序");
request.getRequestDispatcher("a/b/c.html").forward(request,response);
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是 web 下的 index.html
<a href="a/b/c.html">a/b/c.html</a>
<a href="http://localhost:8080/06_servlet/forwardc">a/b/c.html</a>
</body>
</html>
会发现第二个链接无法跳转回去。
原因
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<base href="http://localhost:8080/06_servlet/a/b/">
</head>
<body>
这是 a 下的 b 下的 c
<a href="../../index.html">跳回首页</a>
</body>
</html>
web 中 / 斜杠的不同意义
在 web 中 / 斜杠是一种绝对路径
/ 斜杠如果被浏览器解析,得到的地址 http//ip:port
/ 如果被服务器解析,得到的地址是 http//ip:port/工程路径
HttpServletResponse 类的作用
和 HttpServletRequest 类一样,每次请求进来,Tomcat 服务器都会创建一个 Response 对象,传递给 Servlet 程序使用。
我们如果需要设置返回给客户端的信息,都可以通过设置 Response 对象来设置。
两个输出流的作用
字节流 getOutputStream() 常用于下载(传递二进制数据)
字符流 getWriter() 常用于回传字符串(常用)
两个流同时只能使用一个,使用字节流,就不能再使用字符流。
package com.an.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author an
* @create 2021-05-23-19:08
*/
public class ResponseIOServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置服务器字符集
response.setCharacterEncoding("UTF-8");
// 设置浏览器字符集
response.setHeader("Content-Type","text/html;charset=UTF-8");
/*
方式2 : 同时设置服务器和浏览器
response.setContentType("text/html; charset=UTF-8")
*/
// 往客户端回传字符
PrintWriter writer = response.getWriter();
writer.write("<h1>response's content</h1>");
// 回传中文
writer.write("中文");
}
}
请求重定向
请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一个新地址(之前地址可能被废弃),去新的地址访问。
response1
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Response1");
// 设置相应状态码 302 表示重定向
resp.setStatus(302);
// 设置相应体,说明新的地址在哪里
resp.setHeader("Location","http://localhost:8080/06_servlet/response2");
}
}
response2
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("response2's result!");
}
}
请求重定向的特点
1、浏览器地址栏会发生变化
2、两次请求
3、不共享 Request 域中的数据
请求重定向第二种实现方案(推荐使用)
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Response1");
resp.sendRedirect("http://localhost:8080/06_servlet/response2");
}
}
书城项目第二阶段 —— 用户注册和登录
JavaEE 项目的三层架构
分层是为了解耦,解耦就是为了降低代码的耦合度,方便项目后期的维护和升级。
创建数据库和 t_user 用户表
1、先创建书城需要的数据库和表。
CREATE DATABASE book;
USE book;
CREATE TABLE t_user (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(200)
);
INSERT INTO t_user(`username`,`password`,`email`) VALUE('admin','admin','admin@an.com');
SELECT * FROM t_user;
编写数据库表对应的 JavaBean 对象
package com.an.pojo;
/**
* @author an
* @create 2021-06-03-15:34
*/
public class User {
private Integer id;
private String username;
private String password;
private String email;
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public User() {
}
}
JdbcUtils 工具类的编写与调试
导入 jar 包
编写连接配置文件 jdbc.properties
username=an
password=an
url=jdbc:mysql://localhost:3306/book
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
编写获取数据库连接的类
/**
* @author an
* @create 2021-06-03-15:37
*/
public class JdbcUtils {
private static DruidDataSource dataSource;
static {
Properties properties = new Properties();
// 读取 jdbc.properties 属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
// 从流中加载数据
properties.load(inputStream);
// 创建数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
编写测试类
/**
* @author an
* @create 2021-06-03-15:50
*/
public class JdbcUtilsTest {
@Test
public void testJdbcUtils() {
for (int i = 0; i < 100; i++) {
Connection conn = JdbcUtils.getConnection();
System.out.println(conn);
JdbcUtils.close(conn);
}
}
}
编写 BaseDao
package com.an.dao.impl;
import com.an.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @author an
* @create 2021-06-03-15:55
*/
public abstract class BaseDao {
// 使用 DbUtils 操作数据库
private QueryRunner queryRunner = new QueryRunner();
/**
* update() 方法用来执行:Insert/update/delete
* 如果返回 -1 说明执行失败,返回其他的表示影响的函数
*/
public int update(String sql,Object ... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.update(connection,sql,args);
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
}
/**
* 查询返回一个 JavaBean 的 sql 语句
*/
public <T> T queryForOne(Class<T> type,String sql,Object ... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(connection);
}
return null;
}
public <T> List<T> queryForList(Class<T> type, String sql, Object ... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(connection);
}
return null;
}
/**
* 执行返回一行一列的 sql 语句
*/
public Object queryForSingleValue(String sql,Object ... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new ScalarHandler(),args);
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.close(connection);
}
return null;
}
}
编写 UserDao
编写接口
package com.an.dao;
import com.an.pojo.User;
/**
* @author an
* @create 2021-06-03-16:11
*/
public interface UserDao {
/**
* 根据用户名查询用户信息
* @param username
* @return 如果返回 null,说明不存在用户信息
*/
public User queryUserByUsername(String username);
/**
* 根据用户名和密码查询用户
* @param username
* @return 如果返回 null,说明用户名或密码错误
*/
public User queryUserByUsernameAndPassword(String username,String password);
/**
* 保存用户信息
* @param user
* @return
*/
public int saveUser(User user);
}
编写实现类
package com.an.dao.impl;
import com.an.dao.UserDao;
import com.an.pojo.User;
/**
* @author an
* @create 2021-06-03-16:13
*/
public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql = "select `id`,`username`,`password`,`email` from t_user where username = ?";
return queryForOne(User.class,sql,username);
}
@Override
public User queryUserByUsernameAndPassword(String username,String password) {
String sql = "select `id`,`username`,`password`,`email` from t_user where username = ? and password = ?";
return queryForOne(User.class,sql,username,password);
}
@Override
public int saveUser(User user) {
String sql = "insert into t_user(`username`,`password`,`email`) values(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
}
编写测试类
package com.an.test;
import com.an.dao.UserDao;
import com.an.dao.impl.UserDaoImpl;
import com.an.pojo.User;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author an
* @create 2021-06-03-16:27
*/
public class UserDaoTest {
UserDao userDao = new UserDaoImpl();
@Test
public void queryUserByUsername() {
if(userDao.queryUserByUsername("admin")==null)
System.out.println("不存在此用户");
}
@Test
public void queryUserByUsernameAndPassword() {
if(userDao.queryUserByUsernameAndPassword("admin","admin")==null) {
System.out.println("登录失败");
}else {
System.out.println("登录成功");
}
}
@Test
public void saveUser() {
System.out.println(userDao.saveUser(new User(null,"admin2","123456","admin2@qq.com")));
}
}
编写 UserService 和测试
编写接口
package com.an.service;
import com.an.pojo.User;
/**
* @author an
* @create 2021-06-03-16:40
*/
public interface UserService {
/**
* 注册用户
*/
public void registUser(User user);
/**
* 登录
* @param user
* @return
*/
public User login(User user);
/**
* 是否存在用户
* @param username
* @return
*/
public boolean existsUsername(String username);
}
实现类
package com.an.service.impl;
import com.an.dao.UserDao;
import com.an.dao.impl.UserDaoImpl;
import com.an.pojo.User;
import com.an.service.UserService;
/**
* @author an
* @create 2021-06-03-16:43
*/
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void registUser(User user) {
userDao.saveUser(user);
}
@Override
public User login(User user) {
return userDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword());
}
@Override
public boolean existsUsername(String username) {
if(userDao.queryUserByUsername(username)==null) {
// 没有查询到
return false;
}
return true;
}
}
测试
package com.an.test;
import com.an.pojo.User;
import com.an.service.UserService;
import com.an.service.impl.UserServiceImpl;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author an
* @create 2021-06-03-16:47
*/
public class UserServiceTest {
UserService userService = new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"bbj168","66666","bj@qq.com"));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"admin","admin",null)));
}
@Test
public void existsUsername() {
if(userService.existsUsername("admin")) {
System.out.println("用户名已存在");
}else {
System.out.println("用户名可用");
}
}
}
实现用户注册的功能
前端部分
<base>
标签固定相对路径
<!-- 写 base 标签,永远固定相对路径跳转结果 -->
<base href="http://localhost:8080/book/" />
<link type="text/css" rel="stylesheet" href="static/css/style.css">
表单请求地址
<form action="registServlet" method="post">
后端代码
package com.an.web;
import com.an.pojo.User;
import com.an.service.UserService;
import com.an.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-06-03-17:02
*/
public class RegistServlet extends HttpServlet {
private UserService userService= new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
// 2、检查验证码是否正确 === 写死,要求验证码为 6n6np
System.out.println(code);
if("6n6np".equalsIgnoreCase(code)) {
// 3、检查用户名是否可用
if(userService.existsUsername(username)) {
System.out.println("用户名["+username+"]已存在!");
// 不可用
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
} else {
// 可用
// 调用 service 保存到数据库
userService.registUser(new User(null,username,password,email));
// 跳到注册成功页面 regist_success.html
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
}
} else {
System.out.println("验证码错误");
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}
}
}
IDEA 中 Debug 调试的使用
Debug 调试代码,首先需要两个元素:断点+Debug启动服务器
1、断点,只要在代码需要的行的左边单击,就可以添加和取消
2、Debug 启动 Tomcat (运行键旁边的虫子)
用户登录功能的实现
前端部分
<base href="http://localhost:8080/book/" />
<form action="loginServlet" method="post">
后端部分
package com.an.web;
import com.an.pojo.User;
import com.an.service.UserService;
import com.an.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-06-03-18:36
*/
public class LoginServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1、获取请求参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2、调用 xxService.login()
User loginUser = userService.login(new User(null, username, password, null));
if(loginUser==null) {
request.getRequestDispatcher("/pages/user/login.html").forward(request,response);
} else {
request.getRequestDispatcher("/pages/user/login_success.html").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Cookie
什么是 Cookie
Cookie 是服务器通知客户端保存键值对的一项技术
客户端有了 Cookie 后,每次请求都发送给服务器
每个 Cookie 的大小不能超过 4kb
Cookie 的创建
添加资料里的演示中的cookie/session.html
cookie.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cookie</title>
<base href="http://localhost:8080/13_cookie_session/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" width="500" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li>
<li><a href="" target="target">Cookie的获取</a></li>
<li><a href="" target="target">Cookie值的修改</a></li>
<li>Cookie的存活周期</li>
<li>
<ul>
<li><a href="" target="target">Cookie的默认存活时间(会话)</a></li>
<li><a href="" target="target">Cookie立即删除</a></li>
<li><a href="" target="target">Cookie存活3600秒(1小时)</a></li>
</ul>
</li>
<li><a href="" target="target">Cookie的路径设置</a></li>
<li><a href="" target="target">Cookie的用户免登录练习</a></li>
</ul>
</div>
</body>
</html>
BaseServlet
package com.an.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// System.out.println(method);
// 调用目标业务 方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
CookieServlet
package com.an.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author an
* @create 2021-06-06-20:08
*/
public class CookieServlet extends BaseServlet {
protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1 创建 Cookie 对象
Cookie cookie = new Cookie("key1","value1");
//2 通知客户端保存 Cookie
resp.addCookie(cookie);
resp.getWriter().write("Cookie 创建成功");
}
}
处理流程
Cookie 的获取
服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():返回 Cookie 对象的数组。
cookie.html
<li><a href="cookieServlet?action=getCookie" target="target">Cookie的获取</a></li>
cookieServlet
protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
// getName() 返回 Cookie 的 key
resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br />");
}
}
寻找特定键的 Cookie
protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
Cookie iWantCookie = null;
for (Cookie cookie : cookies) {
// getName() 返回 Cookie 的 key
resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br />");
if("key1".equals(cookie.getName())) {
iWantCookie = cookie;
}
}
// 如果不等于 null,说明赋过了值,也就是找到了需要的 cookie
if(iWantCookie != null) {
resp.getWriter().write("找到了需要的cookie");
}
}
也可以封装到查找的工具类
public class CookieUtils {
/**
* 查找指定名称的Cookie对象
* @param name
* @param cookies
* @return
*/
public static Cookie findCookie(String name,Cookie[] cookies) {
if(name == null || cookies == null || cookies.length==0) {
return null;
}
for (Cookie cookie : cookies) {
if(name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
}
Cookie 值的修改
方案1:
1、先创建一个要修改的同名的 Cookie 对象
2、在构造器,同时赋予新的 Cookie 值
3、调用 response.addCookie(Cookie)
protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("key1","newValue1");
// 通知客户端保存修改
resp.addCookie(cookie);
}
方案2:
1、先查找到所需要修改的 Cookie 对象
2、调用 setValue() 方法赋予新的值
3、调用 response.addCookie 方法
Cookie 生命控制
Cookie 生命控制指的是如何管理 Cookie 什么时候删除
setMaxAge()
正数:表示在经过指定的秒数后过期
负数:表示浏览器一关,Cookie 就会被删除(默认是 -1)
0:表示马上删除 Cookie
protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie= new Cookie("defaultLife","defaultLife");
// 设置存活时间
cookie.setMaxAge(-1);
resp.addCookie(cookie);
}
Cookie 的 path 属性
Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器,哪些不发。
path 属性是通过请求的地址来进行有效的过滤。
CookieA path=/工程路径
CookieB path=/工程路径/abc
请求地址如下:
http://ip:port/工程路径/a.html
Cookie A 发送
Cookie B 不发送
protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie= new Cookie("path1","path1");
// getContextPath() 得到工程路劲
cookie.setPath(req.getContextPath()+"/abc"); // 工程路径 + /abc
resp.getWriter().write("创建了一个带有 path 路径的 Cookie");
}
Cookie 应用——免用户名登录
Session 会话
什么是 Session 会话
1、Session 是一个接口(HttpSession)
2、Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术
3、每个客户端都有自己的一个 Session 会话
4、Session 会话中,我们经常用来保存用户登录信息
Session 的创建和获取
如何创建和获取 Session ,它们的 API 是一样的。
request.getSession()
第一次调用:都是创建 Session 会话
之后调用:获取前面创建好的 Session 回去对象
isNew():判断到底是不是刚创建出来的(新的)
true 表示刚创建
false 表示获取之前创建
每个会话都有一个身份号码,也就是 ID 值,而且这个 ID 值是唯一的。
getId() 得到 Session 的会话 id
public class SessionServlet extends BaseServlet {
protected void createGetSession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建和获取 Session 会话对象
HttpSession session = request.getSession();
// 判断当前 Session 对象是否是新创建出来的
boolean isNew = session.isNew();
// 获取 Session 会话的唯一标识
String id = session.getId();
response.getWriter().write("得到的 Session,它的id是"+id+"<br />");
response.getWriter().write("这个 Session 是否是新创建的"+isNew+"<br />");
}
}
Session 域数据的存取
/**
* 往 Session 中保存数据
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void setAttribute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().setAttribute("key1","value1");
}
/**
* 获取 Session 域中的数据
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void getAttribute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object attribute = request.getSession().getAttribute("key1");
response.getWriter().write("从 Session 中获取出 key1 的数据是:"+attribute);
}
Session 生命周期控制
setMaxInactiveInterval() 设置 Session 的超时时间,超过指定的时长,Session 就会被销毁。
getMaxInactiveInterval() 获取 Session 的超时时间
以秒为单位
Session 默认的超时时长
Session 默认的超时时长为 30 min,因为在 tomcat 的 web.xml 中,配置了当前 tomcat 服务器下,超时配置时长为 30 分钟。
如果说,你希望你的 web 工程默认的超时时长为其他时长,可以自己配置。