这是菜狗学习Servlet的一些笔记
什么是Servlet?
Servlet就是一种技术,用于开发动态Web
Servlet是一种接口
Servlet就是一种实现了Servlet接口的Java程序
如果你想开发一个动态Web,你需要:1. 编写一个类,实现Servlet接口;2. 将这个类部署到Web服务器中
Hello Servlet
构建Maven父子项目
首先构建一个普通的Maven项目,删除src目录,称其为主工程
在主工程里新建模块,称其为子工程
例如构建主工程为Root_Servlet,子工程为Servlet_01,这二者的pom.xml中会加入父子关系的描述,如下:
父项目<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>Root_Servlet</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>Servlet_01</module> </modules> <properties> <maven.compiler.source>15</maven.compiler.source> <maven.compiler.target>15</maven.compiler.target> </properties> </project>
子项目
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root_Servlet</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>Servlet_01</artifactId> <properties> <maven.compiler.source>15</maven.compiler.source> <maven.compiler.target>15</maven.compiler.target> </properties> </project>
另外,子项目可以使用父项目的Maven依赖,而父项目则不能使用子项目的
然后同样的,我们把子项目中web.xml的内容换成与Tomcat的webapps里web.xml一致的,并删除冗余部分
写一段代码
接着在java目录下新建一个java文件(或者先新建一个软件包再新建一个java文件),然后令你的类继承HttpServlet接口,注意:这里继承时需要先通过Maven导入包(如果本地仓库没有,可以去Maven仓库找),而通过Maven导包时配置的是子项目的pom.xml文件,如果不想重复导入,可以把相关的依赖剪切到父项目的pom.xml下
这些完成后需要重写方法,现阶段需要掌握的只有doGet和doPost方法,因此只重写这两个
因为这两个方法通常没什么不同,所以我们习惯在一个方法里调用另一个,然后所有代码就写在另一个方法里面
简单写两句://响应流 PrintWriter writer = resp.getWriter(); //输出 writer.println("Hello Servlet!");
编写Servlet映射
- 注册Servlet
在web.xml中添加<servlet>标签,在此标签下添加<servlet-name>标签(一般自动添加),在这个标签下写Servlet的名字,比如hello
然后在<servlet>下添加<servlet-class>,在这个标签下写Java类的包名+简单类名 - 编写Servlet的请求路径
在web.xml中添加<servlet-mapping>标签,其下自动生成两个标签,<servlet-name>和<url-pattern>,即名字(与<servlet>的<servlet-name>相同)和请求路径
完成后如图
Tomcat,启动!
添加Tomcat配置,启动程序
出现报错500
我麻了
重新来
经过亿系列试错,找到了解决方法:
tomcat10 带来的报错:jakarta.servlet.ServletException: 类com.kang.servlet.HelloServlet不是Servlet
原来是Tomcat10的锅(包名改了)
修改之后pom.xml文件依赖长这样
导入的包长这样
(是的,为了解决这个错误我重新下了IDEA专业版,社区版完全就是****)
启动成功✿ヽ(°▽°)ノ✿
自定义404界面
原理:指定固有映射路径的优先级最高
同样的,新建一个error类
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* <p>
* 创建日期:2021-04-16 21:43
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class Error404 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("<h1>404 NOT FOUND</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
接着去web.xml注册Servlet和编写访问路径,要想达到404的效果,需要用到通配符*
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>Error404</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
式中/*
表示任意路径(包括空),但其优先级低于已编写的其他访问路径
通配符*还可用于指定后缀
例如改一下Error404的servlet-mapping:
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>Erroe404</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>*.error</url-pattern>
</servlet-mapping>
通过全局唯一的ServletContext获取不同Servlet的信息
ServletContext:
WEB容器在启动时,它会为每个Web应用程序都创建一个对应d的ServletContext,它代表当前Web应用。并且它被所有客户端共享。
ServletContext对象可以通过ServletConfig.getServletContext()方法获得对ServletContext对象的引用,也可以通过this.getServletContext()方法获得其对象的引用。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。公共聊天室就会用到它。
当web应用关闭、Tomcat关闭或者Web应用reload的时候,ServletContext对象会被销毁
(引用自博客Servlet——ServletContext 对象)
例子:在一个Servlet中写入username信息,让另一个Servlet读取
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* <p>
* 创建日期:2021-04-17 09:13
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class Hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter writer = resp.getWriter();
writer.print("Hello");
//得到ServletContext
ServletContext servletContext = this.getServletContext();
//添加指定的属性,并为其赋指定的值,如果已有该属性,则修改之
servletContext.setAttribute("Username", "Hoppinging");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 创建日期:2021-04-18 08:31
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username = (String) servletContext.getAttribute("Username");
//设置编码格式
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("Username:" + username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
记得配置web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>Hello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getUsername</servlet-name>
<servlet-class>GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getUsername</servlet-name>
<url-pattern>/gu</url-pattern>
</servlet-mapping>
</web-app>
来看效果:
第一次请求:很明显,获取到了个寂寞
这是因为还没写入属性
这就hello一下
重新获取
转发与重定向
简单的理解:转发url不会发生变化,请求只能转发到相同Web应用的项目资源,不可以跨应用或者服务器;重定向url会发生变化,可以跨Web应用和服务器来重新定位资源,但是不可以直接重定向到WEB-INF中的资源
具体的理解:
图片来自博客转发与重定向
转发
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 创建日期:2021-04-18 10:08
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class ServletDispatcher extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//转发的请求路径设为/hello
servletContext.getRequestDispatcher("/hello").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
配置xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>ServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/dispatcher</url-pattern>
</servlet-mapping>
效果
重定向
简单的一句话
resp.sendRedirect("/XXXX/XXX");
显然XXXX是服务器部署路径,比如完整请求路径为
http://localhost:8081/Servlet_01_war/random
,则XXXX就是Servlet_01_war,XXX就是random
完整代码Demo如下
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 创建日期:2021-04-26 16:49
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class Redirect extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.sendRedirect("/Servlet_01_war/random");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
}
注册web.xml
<servlet>
<servlet-name>random</servlet-name>
<servlet-class>Demo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>random</servlet-name>
<url-pattern>/random</url-pattern>
</servlet-mapping>
通过ServletContext获取资源文件
一般的,先在resources目录下新建一个资源文件,比如info.properties
写一些键值对
注意,放在resources目录下的资源文件默认会导出,但在java下的不会,这时需要在pom中添加配置
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
接着写获取资源的类
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* <p>
* 创建日期:2021-04-18 13:54
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class GetProperties extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext
ServletContext servletContext = this.getServletContext();
//通过target中的info.properties的路径获取资源文件并转换成输入流,注意,用到的路径是以/WEB-INF开头的
InputStream resourceStream = servletContext.getResourceAsStream("/WEB-INF/classes/info.properties");
//new一个资源对象
Properties properties = new Properties();
//加载输入流到对象
properties.load(resourceStream);
//输出
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("用户名:" + properties.getProperty("username") + "密码:" + properties.getProperty("password"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
添加web.xml
<servlet>
<servlet-name>getProperties</servlet-name>
<servlet-class>GetProperties</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getProperties</servlet-name>
<url-pattern>/prop</url-pattern>
</servlet-mapping>
效果:
通过HttpServletResponse下载文件
步骤:
- 确定文件的下载路径(一般为绝对路径);
- 确定文件名;
- 编写文件头(让浏览器支持下载);
- 获取输入流;
- 创建缓冲区;
- 创建输出流;
- 将输入流写入缓冲区,用输出流输出到客户端。
如下所示
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
/**
* <p>
* 创建日期:2021-04-17 09:13
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class Download extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 确定文件的下载路径;
String path = this.getServletContext().getRealPath("/WEB-INF/classes/233.jpg");
// 2. 确定文件名;
String filename = path.substring(path.lastIndexOf("/") + 1);
// 3. 编写文件头(让浏览器支持下载)
resp.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename,"UTF-8"));
// 4. 获取文件输入流
FileInputStream inputStream = new FileInputStream(filename);
// 5. 创建缓冲区
int len;
byte[] buffer = new byte[1024];
// 6. 创建响应输出流
ServletOutputStream outputStream = resp.getOutputStream();
// 7. 将输入流写入缓冲区,用输出流输出到客户端
while((len = inputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
不用要忘了配置web.xml
<servlet>
<servlet-name>download</servlet-name>
<servlet-class>Download</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>download</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
然后启动Tomcat
按回车
没错下载是成功了,但是还需要解决的问题是:
- 没有下载的提示框
- 不支持迅雷下载
通过HttpServletRequest获取前客户端的信息和请求转发
1. 获取前端传参
比如一个这样的前端:
<%--
Created by IntelliJ IDEA.
User: hoppi
Date: 2021/4/27
Time: 16:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<div style="text-align: center">
<form action="${pageContext.request.contextPath}/login" method="post">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
hobbies:
<input type="checkbox" name="hobbies" value="Game"> Games
<input type="checkbox" name="hobbies" value="Sleep"> Sleep
<input type="checkbox" name="hobbies" value="Eating"> Eating
<input type="checkbox" name="hobbies" value="Bilibili"> Bilibili
<br>
<input type="submit">
</form>
</div>
</body>
</html>
显然,它传递了6个参数,而要读取这些参数,需要用到
HttpServletRequest
的方法比如getParameter
和getParameterValues
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
/**
* <p>
* 创建日期:2021-04-27 16:09
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobbies");
System.out.println("============================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("============================");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2. 请求转发的衔接
通常的,比如上面那个login前端,当login完成后,想要跳转到另一个界面告诉客户login成功了,这时候就需要用到请求转发
在doGet方法中加上一句req.getRequestDispatcher("/success.jsp").forward(req, resp);
,其中"success.jsp"
是另一个界面,就像这样:
<%--
Created by IntelliJ IDEA.
User: hoppi
Date: 2021/4/27
Time: 16:22
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Success</title>
</head>
<body>
<h1>
Login success!
</h1>
</body>
</html>
配置web.xml之后就可以运行了:
Cookies
什么是Cookies
Cookies,可以简单理解为服务器给你发的凭证,当你重新登陆一个网站时,如果你持有该网站的Cookies,就会被网站识别(大概,如果这个网站有这种功能的话),Cookies具有持续时间,当你的某网站的Cookies过期之后,再次登陆需要重新验证。
大多数需要登录的网站在用户验证成功之后都会设置一个 cookie,只要这个 cookie 存在这个用户,他就可以就可以自由浏览这个网站的任意页面
简单的Cookies应用Demo
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* <p>
* 创建日期:2021-04-29 17:14
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class cookiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//防止中文乱码
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
Cookie[] cookies = req.getCookies();
boolean cookie_exist = false;
for (Cookie cookie : cookies) {
if(cookie.getName().equals("LoginTime")){
writer.write("Your last login time was:");
long loginTime = Long.parseLong(cookie.getValue());
Date date = new Date(loginTime);
writer.write(date.toLocaleString());
cookie_exist = true;
break;
}
}
if (!cookie_exist){
writer.write("Welcome to here for the first time!");
}
//向客户端发送Cookies
Cookie cookie = new Cookie("LoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>cookies</servlet-name>
<servlet-class>cookiesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cookies</servlet-name>
<url-pattern>/cookies</url-pattern>
</servlet-mapping>
效果:
Session
Session,意为会话
来一个简单的SessionDemo
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
/**
* <p>
* 创建日期:2021-05-01 19:44
*
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//防止乱码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
//为session置入属性
session.setAttribute("name", "Hoppinging");
//获取session的Id
String sessionId = session.getId();
//显示
resp.getWriter().write("session的Id为:" + sessionId);
//事实上,这里还有一步默认进行,建立一个cookie,JSESSIONID=sessionId
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>setSession</servlet-name>
<servlet-class>SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>setSession</servlet-name>
<url-pattern>/session</url-pattern>
</servlet-mapping>
略微修改一下,可以显示session中包含的属性。在显示的时候加一句
resp.getWriter().write((String) session.getAttribute("name"));
,显示名为"name"的Attribute值,当然最好加一个换行符,否则name会和sessionId连在一起_(:з」∠)_
观察得,两次请求的SessionId是不同的,这是因为session是存在于服务器中的,重启服务器会清除session
Session属性的移除与Session的注销
移除指定名称的属性:
removeAttribute(String var1)
注销session:invalidate()
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
/**
* <p>
* 创建日期:2021-05-02 17:05
* Session属性的移除与Session的注销
* @author Hoppinging
* @version 1.1
* @since 1.0
*/
public class SessionInvalidateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//防止乱码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
//移除session的指定属性
session.removeAttribute("name");
//获取session的Id
String sessionId = session.getId();
//显示
resp.getWriter().write("session的Id为:" + sessionId);
resp.getWriter().write("<br>" + session.getAttribute("name") + "<br>");
//注销session
session.invalidate();
//第二次显示
resp.getWriter().write("session的Id为:" + sessionId);
resp.getWriter().write("<br>" + session.getAttribute("name") + "<br>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
ps:这里<br>起到换行的作用,因为servlet中\n
无法起到换行的作用
web.xml:
<servlet>
<servlet-name>invalidateSession</servlet-name>
<servlet-class>SessionInvalidateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>invalidateSession</servlet-name>
<url-pattern>/invalidate</url-pattern>
</servlet-mapping>
点击刷新
session的id在刷新前后不一致,这说明session确实是被清掉了
另外,第一次显示时name为null,第二次显示直接就没有了,这是因为第一次getAttribute找到的name值为null,toString之后是字符串null
,第二次是因为invalidate完session就失效了,虽然会生成一个新的session,但getAttribute指向的对象还是原来那个session,故会导致NullPointerException
,所以就输出了个寂寞,然后根据某大佬的研究
(U•ェ•*U狗头保命)
Session的自动注销
当然,上面的那种是手动注销
自动注销是在web.xml中编辑<session-config>的<session-timeout>属性,单位是分钟
<!--设置session的默认失效时间-->
<session-config>
<!--十五分钟过期-->
<session-timeout>15</session-timeout>
</session-config>