Servlet简介
- Servlet就是sun公司开发动态web的一门技术
- Sun在这些APi中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Serlet接口
- 把开发好java类部署到web服务器中。
把实现了Servlet接口的Java程序叫做,Servlet
HelloServlet
Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServled
HelloServlet
- 构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就题Maven主工程;
在pom.xml里面放依赖
https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope> 可以删掉
</dependency>
</dependencies>
JavaServer Page jsp依赖
https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api/2.3.3
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
关于Maven父子工程的理解;
父项目中会有<modules>
<module>
servlet-01
</module>
</modules>
子项目会有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的java子项目可以直接使用
son extends father
Maven环境优化
- 修改web.xml为最新的 ```
<?xml version=”1.0” encoding=”UTF-8”?>
1. 将maven的结构搭建完整
.![image.png](https://cdn.nlark.com/yuque/0/2021/png/2211273/1611654510796-598e1542-8d90-4693-b533-e0095bd03926.png#align=left&display=inline&height=144&margin=%5Bobject%20Object%5D&name=image.png&originHeight=190&originWidth=346&size=7353&status=done&style=none&width=263)
4. 编写一个Servlet程序
1. 编写一个普通类
1. 实现Servlet接口,这里我们直接继承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); //响应流
writer.print("Hello,Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5. 编写Servlet的映射<br />为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需<br />要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6. 配置Tomcat<br />注意:配置项目发布的路径就可以了<br />![](https://cdn.nlark.com/yuque/0/2021/png/2211273/1611652053932-480ee1be-11f6-4ed0-85af-2410aae69b96.png#align=left&display=inline&height=356&margin=%5Bobject%20Object%5D&originHeight=356&originWidth=512&size=0&status=done&style=none&width=512)<br />![](https://cdn.nlark.com/yuque/0/2021/png/2211273/1611652053971-0265de5d-741e-4614-a85a-c2eff81dae91.png#align=left&display=inline&height=120&margin=%5Bobject%20Object%5D&originHeight=120&originWidth=554&size=0&status=done&style=none&width=554)
6. 启动测试,OK!<br />![](https://cdn.nlark.com/yuque/0/2021/png/2211273/1611652054058-584d3e8e-0364-4b5e-a115-929d421ea296.png#align=left&display=inline&height=306&margin=%5Bobject%20Object%5D&originHeight=306&originWidth=642&size=0&status=done&style=none&width=642)
<a name="pM5eE"></a>
## Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:<br />![](https://cdn.nlark.com/yuque/0/2021/png/2211273/1611652054012-8f21fa69-f48c-48bf-aa05-9b10412a6955.png#align=left&display=inline&height=783&margin=%5Bobject%20Object%5D&originHeight=783&originWidth=1058&size=0&status=done&style=none&width=1058)
<a name="hjTWj"></a>
## Mapping问题
1. 一个Servlet可以指定一个映射路径<br />.
2. 一个servlet可以指定多个映射路径
3. 一个servlet可以指定通用映射路径
4. 默认请求路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5. 指定一些后缀或者前缀等等…
6. 优先级问题<br />指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<a name="3BVu2"></a>
# ServletConfig
<a name="DMlax"></a>
## ServletConfig对象有什么用?
通过此对象可以**读取web.xml中**配置的**初始化参数**。
<a name="PXVXw"></a>
## 🙄why?
**能够让你的程序更加灵活**【更换需求,更改配置文件web.xml即可,程序代码不用改】
<a name="Flmvo"></a>
## 获取web.xml文件配置的参数信息
- 为Demo1这个Servlet配置一个参数,参数名是name,值是zhongfucheng
```xml
<servlet>
<servlet-name>Demo1</servlet-name>
<servlet-class>zhongfucheng.web.Demo1</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>zhongfucheng</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>/Demo1</url-pattern>
</servlet-mapping>
在Servlet中获取ServletConfig对象,通过ServletConfig对象获取在web.xml文件配置的参数 ```java public class servletConfig extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletConfig对象
ServletConfig servletConfig = this.getServletConfig();
//根据配置的名字获取值
String name = servletConfig.getInitParameter("name");
System.out.println(name);
} }
<a name="ServletContext"></a>
# ServletContext
<a name="ciijZ"></a>
## 共享数据
- 在一个Servlet中,可以在另一个Servlet中拿到,实现了Servlet之间的通信
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1281683/1598019995087-0c7b4fb8-bbe1-4285-9c61-a0c243e330ef.png#align=left&display=inline&height=239&margin=%5Bobject%20Object%5D&name=image.png&originHeight=320&originWidth=714&size=24381&status=done&style=none&width=534)
```java
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Hello");
//this.getInitParameter() 初始化参数
//this.getServletConfig() Servlet配置
//this.getServletContext() Servlet上下文
ServletContext context1 = this.getServletContext();
//将一个数据保存到 ServletContext中,名字为:username,值为username
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
String username = "shilin.z";
context1.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context2 = this.getServletContext();
String username = (String) context2.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().print("s1传输的内容: " + username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>edu.cqupt.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>edu.cqupt.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
测试结果:
先 http://localhost:8080/s2/hello, 不然输出为null
获取初始化参数
<!-- 配置一些web应用的初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://local:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>getp</servlet-name>
<servlet-class>edu.cqupt.servlet.Servlet03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getp</servlet-name>
<url-pattern>/getp</url-pattern>
</servlet-mapping>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
请求转发(不是重定向)
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入了Servlet04");
ServletContext context = this.getServletContext();
//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getp"); //转发的请求路径
//requestDispatcher.forward(req,resp); //调用forward实现请求转发
context.getRequestDispatcher("/getp").forward(req,resp);
}
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>edu.cqupt.servlet.Servlet04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
测试结果:
读取资源文件
- Properties类
- 在java目录下新建properties
- 在resources目录下新建properties
- 发现:都被打包到了同一路径下:classes,我们俗称路径为classpath
需要在本项目的pom.xml中配置resources
<!-- 在bulid中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
需要一个文件流:
Servlet05.java
public class Servlet05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获得文件流
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user + ":" + pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
db.properties
username=root
password=123456
web.xml
<servlet>
<servlet-name>sd5</servlet-name>
<servlet-class>edu.cqupt.servlet.Servlet05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd5</servlet-name>
<url-pattern>/sd5</url-pattern>
</servlet-mapping>
HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,一个代表响应的HttpServletResponse对象;
- 如果要获取客户端请求过来的参数:找HttpServletRequset对象
如果要给客户端响应一些信息: 找HttpServletResponse对象
简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
响应的状态码
HttpServletResponse定义了很多状态码的常量(具体可以查看Servlet的API),当需要向客户端发送响应状态码时,可以使用这些常量,避免了直接写数字,常见的状态码对应的常量:
int SC_CONTINUE = 100;
int SC_OK = 200;
int SC_MULTIPLE_CHOICES = 300;
int SC_NOT_FOUND = 404;
int SC_INTERNAL_SERVER_ERROR = 500;
.....
常见应用
向浏览器输出消息
使用PrintWriter流输出中文注意问题:
在获取PrintWriter输出流之前首先使用
response.setCharacterEncoding(charset)
设置字符以什么样的编码输出到浏览器- 如:
response.setCharacterEncoding("UTF-8");
设置将字符以”UTF-8”编码输出到客户端浏览器,然后再使用response.getWriter();
获取PrintWriter输出流,这两个步骤不能颠倒 ```java response.setCharacterEncoding(“UTF-8”);//设置将字符以”UTF-8”编码输出到客户端浏览器 /**
- PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding(“UTF-8”);之后
- 否则response.setCharacterEncoding(“UTF-8”)这行代码的设置将无效,浏览器显示的时候还是乱码 */ PrintWriter out = response.getWriter();//获取PrintWriter输出流 ```
- 然后再使用
response.setHeader("content-type", "text/html;charset=字符编码");
设置响应头,控制浏览器以指定的字符编码编码进行显示,例如:
```java /**//通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
- 多学一招:使用HTML语言里面的标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为 *response.getWriter().write(““);
等同于response.setHeader(“content-type”, “text/html;charset=UTF-8”); */ response.getWriter().write(““); ```
下载文件
- 获取下载文件的路径
- 下载的文件名
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端 ```java package com.dyq.servlet;
import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder;
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.要获取下载文件的路径 // target/classes/段.jpg String realPath = “C:\Users\DYQ\IdeaProjects\javaweb-02-servlet\response\target\classes\段.jpg”; System.out.println(“下载文件的路径”+realPath); //2.下载文件名是啥? String fileName = realPath.substring(realPath.lastIndexOf(“\“) + 1); //“\“是转义 //3.设置想办法让浏览器能够支持下在我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码 resp.setHeader(“Content-Disposition”,”attachment;filename=”+ URLEncoder.encode(fileName,”utf-8”)); //4.获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5.创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; //6.获取OutputStream对象 ServletOutputStream out = resp.getOutputStream(); //7.将FileOutputStream流写入到buffer缓冲区 使用OutputStream将缓冲区中的数据输出到客户端 while (in.read(buffer)>0){ out.write(buffer,0,len); } in.close(); out.close(); }
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1281683/1598064943480-8bf05768-d1c9-41b9-a0f3-54641c1902f8.png#align=left&display=inline&height=498&margin=%5Bobject%20Object%5D&name=image.png&originHeight=995&originWidth=934&size=60658&status=done&style=none&width=467)
<a name="DKCF2"></a>
### 验证码功能
**验证怎么来的?**
- 前端实现
- 后端实现,需要用到 java 的图片类,生成一个图片
```java
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 如何让浏览器3秒自动刷新一次;
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_3BYTE_BGR);
//得到图片
Graphics2D g = (Graphics2D)image.getGraphics();
// 设置图片的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.blue);
g.setFont(new Font("宋体",Font.BOLD,20));
g.drawString(makeNum(),0,20);
// 告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires", -1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 把图片写给浏览器
boolean write = ImageIO.write(image, "jpg",resp.getOutputStream());
}
//生产随机数
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7 - num.length() ; i++) { //保证生成的随机数只有7位
sb.append("0"); //不足7位用0填充
}
num = sb.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>img</servlet-name>
<servlet-class>edu.cqupt.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>img</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1281683/1598104251154-19554502-a91d-4590-8178-5447323d9028.png#align=left&display=inline&height=242&margin=%5Bobject%20Object%5D&name=image.png&originHeight=630&originWidth=1162&size=35334&status=done&style=none&width=446)
实现重定向
B一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫重定向。
常见场景:
- 用户登录:登录成功,跳转到另外的页面。 ```java public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setHeader(“Location”, “/s3/img”); // resp.setStatus(302); resp.sendRedirect(“/s3/img”); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<a name="J83bq"></a>
## 🧐面试题:请求和重定向的区别?
- 相同点
- 页面都会跳转
- 不同点
- 请求转发,url地址不会发生变化 307
- 重定向,url地址会发生变化 302
```java
public class RequestTestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入这个请求了----");
// 处理请求
String username = req.getParameter("username");
String pwd = req.getParameter("password");
System.out.println(username + ":" + pwd);
// 重定向一定要注意,路径问题,否则就会404
resp.sendRedirect("/s3/home.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1> Success ! </h1>
</body>
</html>
HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
常用方法
getRequestURL方法返回客户端发出请求时的完整URL。
getRequestURI方法返回请求行中的资源名部分。
getQueryString 方法返回请求行中的参数部分。
getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
getRemoteAddr方法返回发出请求的客户机的IP地址。
getRemoteHost方法返回发出请求的客户机的完整主机名。
getRemotePort方法返回客户机所使用的网络端口号。
getLocalAddr方法返回WEB服务器的IP地址。
getLocalName方法返回WEB服务器的主机名。
🙄获得客户机请求参数(客户端提交的数据)
- getParameter(String)方法(常用)
getParameterValues(String name)方法(常用)
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
//获取前端传递参数
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("---------------");
//重定向
// resp.sendRedirect("/s4/success.jsp");
//通过请求转发
System.out.println(req.getContextPath());
//这里的/代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
更多
Cookie、Session
会话
会话:用户打开一个浏览器,点击了很多web资源,访问多个web资源,关闭浏览器,这个过程就叫做会话。
有状态会话:客户端访问服务器,下次在访问服务器,服务器知晓客户端曾今访问过。
一个网站怎么证明用户访问过?
客户端 服务器
- 服务端给客户端一个cookie,客户端下次访问带上cookie就可以了
- 服务器通过session登记客户端访问过,下次客户端再次访问,服务器匹配客户端
保存会话的两种技术
cookie(发票)
- 客户端技术(响应、请求)
session(登记)
- 服务器技术:利用这个技术,可以保存用户的会话信息,我们可以把信息或者数据放在Session中
常见场景:
- 网站登录过后,下次不用登录,第二次访问直接就进去。
cookie
- 从请求中拿到cookie
服务器响应给客户端cookie
// 保存用户上一次访问的时间
public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 服务器告诉你 ,你访问的时间,把这个时间封装成一个信件,下次访问的时候,需要带上信件
req.setCharacterEncoding("gbk");
resp.setCharacterEncoding("gbk");
PrintWriter out = resp.getWriter();
// 服务器端从客户端获取
Cookie[] cookies = req.getCookies(); // cookie可能存在多个
// 判断cookie是否存在
if(cookies!=null){
//如果存在
out.write("你上次访问的时间是:");
for (int i = 0; i <cookies.length ; i++) {
Cookie cookie = cookies[i];
// 获取cookie的名字
if(cookie.getName().equals("lastLoginTime")){
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
System.out.println(cookie.getName());
}
}else{
out.write("这是您第一次访问本网站。");
}
//服务器给客户端响应一个Cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
🍋Session(重点)
什么是Session:
服务器给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后,整个网站都可以访问!
- 场景:保存用户的信息,保存购物车信息,在整个网站中经常会使用的数据,我们将它保存在session中
Session和Cookie的区别:**
- Cookie是把用户的数据写给用户得浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建
使用Session
public class SessionDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决乱码问题
resp.setHeader("content-type","text/html; charset=utf-8");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//得到session
HttpSession session = req.getSession();
//获取Session的ID
String sessionId = session.getId();
//判断session是否为新创建的
if(session.isNew()){
resp.getWriter().write("session 创建成功。session ID:" + sessionId );
}else{
resp.getWriter().write("已经在服务器中存在了。session ID:" + sessionId );
}
// Session创建的时候做了什么事情
//Cookie cookie = new Cookie("JSESSIONID",sessionId);
//resp.addCookie(cookie);
//给Session中存字符串
session.setAttribute("name","shilin.z");
String name = (String) session.getAttribute("name");
System.out.println(name);
//给Session中存用户信息
session.setAttribute("name",new Person("shilin.z",20));
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
//手动注销Session: 刷新,会重新生成sessionID
//session.removeAttribute("name");
//session.invalidate();
//自动注销:在xml中配置
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!-- 设置Session 默认的失效时间,以分钟为单位-->
<session-config>
<!-- 1分钟后失效 -->
<session-timeout>1</session-timeout>
</session-config>