Servlet

目录

Servlet概念

Servlet 主要做的工作

创建一个Servlet项目

1.创建一个Maven项目

2.引入依赖

3.创建目录

1) 创建 webapp 目录

2) 创建 web.xml

3) 编写 web.xml

5.打包程序

6.程序部署

7.验证程序

更方便的部署方式-Smart TomCat

安装 Smart Tomcat 插件

1. 菜单 -> 文件 -> Settings

2. 选择 Plugins(插件), 选择 Marketplace, 搜索 "tomcat", 点击 "Install".

3. 安装完毕之后, 会提示 "重启 IDEA“

配置 Smart TomCat 插件

5. 访问页面.

区分IDEA和TomCat之间的关系

常见的访问错误

出现404

出现405

出现500

出现”空白页面“

出现无法访问此网站

小结

Servlet 运行原理

TomCat的定位

详细的交互过程

用户发送请求-封装

通过网络设备,直至抵达目标主机;

服务器接受请求-分用

TomCat的伪代码

TomCat初始化流程

TomCat处理请求流程

Servlet 的 service 方法的实现

Servlet API 详解

HttpServlet

核心方法

处理GET/POST请求

HttpServletRequest

核心方法

HttpServletResponse

核心方法

Cookie 和 Session

Cookie:

Session :会话

网页应用的登录流程

Cookie 和 Session 的区别

核心方法:

HttpServletRequest 类

HttpServletResponse 类

HttpSession 类

Cookie 类

上传文件

核心方法

HttpServletRequest 类方法

Part 类方法


Servlet概念

Servlet 是一种实现动态页面的技术.

是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app

Servlet 主要做的工作

  • 初始化:
    • 允许程序猿注册一个类, 与http中的特定请求关联,在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类中的一些代码.
  • 进入循环(处理请求)
    • 帮助程序猿解析 HTTP 请求, 把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象.
    • 根据请求对象生成一个HttpServletResponse对象(表示响应)
      • 根据请求生成响应,这个过程,就是初始化阶段注册的类里的代码完成(程序员的工作,业务逻辑)
    • 根据HttpServletResponse对象,帮助程序猿构造 HTTP 响应,返回给浏览器

创建一个Servlet项目

1.创建一个Maven项目

使用idea 创建一个maven项目

1.菜单-》文件-》新建项目-》Maven

2.选择存放目录

3.项目创建完毕后,一般右下角会弹出一下对话框,选择enable auto-import

2.引入依赖

Maven 项目创建完毕后, 会自动生成一个 pom.xml 文件.

我们需要在 pom.xml 中引入 Servlet API 依赖的 jar 包

1. 在中央仓库 https://mvnrepository.com/ 中搜索 "servlet", 一般第一个结果就是

2. 选择版本. 一般我们使用 3.1.0 版本

Servlet 的版本要和 Tomcat 匹配.

如果我们使用 Tomcat 8.5, 那么就需要使用 Servlet 3.1.0

可以在 Apache Tomcat® - Which Version Do I Want? 查询版本对应关系

3. 把中央仓库中提供的 xml 复制到项目的 pom.xml 中

修改后的 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>serlet</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    
    //引入包
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            //此标签表示,当前jar包只是在开发阶段使用,不需要打包到最终的发布包中
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

<dependencies>标签内部放置项目依赖的 jar 包. maven 会自动下载依赖到本地

关于 groupId, artifactId, version

这几个东西暂时我们不关注.啥时候需要关注呢?

如果我们要把这个写的代码发布到中央仓库上, 那么就需要设定好这几个 ID 了.

groupId: 表示组织名称

artifactId: 表示项目名称

version: 表示版本号

中央仓库就是按照这三个字段来确定唯一一个包的

红色方框圈出来的部分, 就是这个 jar 包的 groupId, artifactId, version

3.创建目录

当项目创建好了之后, IDEA 会帮我们自动创建出一些目录. 形如

这些目录中:

  • src 表示源代码所在的目录
  • main/java 表示源代码的根目录. 后续创建 .java 文件就放到这个目录中.
  • main/resources 表示项目的一些资源文件所在的目录. 此处暂时不关注.
  • test/java 表示测试代码的根目录. 此处暂时不关注

这些目录还不够, 我们还需要创建一些新的目录/文件

1) 创建 webapp 目录

在 main 目录下, 和 java 目录并列, 创建一个 webapp 目录 (注意, 不是 webapps).

2) 创建 web.xml

然后在 webapp 目录内部创建一个 WEB-INF 目录, 并创建一个 web.xml 文件

注意单词拼写,严格相同

3) 编写 web.xml

往 web.xml 中拷贝以下代码. 具体细节内容我们暂时不关注

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>

webapp 目录就是未来部署到 Tomcat 中的一个重要的目录. 当前我们可以往 webapp 中放一些静 态资源, 比如 html , css 等.

在这个目录中还有一个重要的文件 web.xml. Tomcat 找到这个文件才能正确处理 webapp 中的动 态资源.

4.编写简单代码

在 java 目录中创建一个类 HelloServlet, 代码如下:

/**
 * @WebServlet() Servlet提供的注解;
 * 功能:将 类 和 HTTP特定请求进行关联
 *      根据HTTP请求的URL的路径进行关联
 *    若收到路径为/hello 的请求,就会调用到HelloServlet的代码
 *    若为GET请求,调用doGet方法
 *    若为POST请求,调用doPost方法
 */
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    /**
     * 重写doGet方法,若不重写,调用父类方法,报错
     * 根据GET请求,生成响应
     * @param req :收到的请求
     *      HttpServletRequest 表示 HTTP 请求.
     *            Tomcat 按照 HTTP 请求的格式把 字符串 格式的请求转成 HttpServletRequest 对象.
     *              后续想获取请求中的信息(方法, url, header, body 等) 都是通过这个对象来获取.
     * @param resp :要构造的响应
     *             HttpServletResponse 表示 HTTP 响应.
     *             代码中把响应对象构造好(构造响应的状态码, header,body 等)
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //干掉父类代码
        //super.doGet(req, resp);

        /**
         * resp.getWriter():获取一个流对象
         * 通过这个流对象就可以写入一些数据, 写入的数据会被构造成一个 HTTP 响应的 body 部分
         * 
         * Tomcat 会把整个响应转成字符串, 通过 socket 写回给浏览器
         */
        //实现hello world,不管请求,直接返回字符串
        resp.getWriter().write("hello world");
    }
}

1.我们的代码不是通过 main 方法作为入口了. main 方法已经被包含在 Tomcat 里, 我们写的代码会 被 Tomcat 在合适的时机调用起来.(方法调用,实例化,有TomCat在合适的时机自主调用)

此时我们写的代码并不是一个完整的程序, 而是 Tomcat 这个程序的一小部分逻辑.

2. 我们随便写个类都能被 Tomcat 调用嘛? 满足啥样条件才能被调用呢?

主要满足三个条件:

  • a) 创建的类需要继承自 HttpServlet
  • b) 这个类需要使用 @WebServlet 注解关联上一个 HTTP 的路径
  • c) 这个类需要实现 doXXX 方法.

当这三个条件都满足之后, Tomcat 就可以找到这个类, 并且在合适的时机进行调用

即Servlet编程,三大起手式

  • 继承HttpServlet;
  • 使用@WebServlet("url路径”)注解关联特定请求
  • 实现doXXXX方法(一般为:doGet/doPost)

5.打包程序

使用 maven 进行打包. 打开 maven 窗口 (一般在 IDEA 右侧就可以看到 Maven 窗口, 如果看不到的话,

可以通过 菜单 -> View -> Tool Window -> Maven 打开)

看到SUCCESS字样打包成功

打包成功后, 可以看到在 target 目录下, 生成了一个 jar 包

这样的 jar 包并不是我们需要的, Tomcat 需要识别的是另外一种 war 包格式.

另外这个 jar 包的名字太复杂了, 我们也希望这个名字能更简单一点

war 包和 jar 包的区别

jar 包 :是普通的 java 程序打包的结果. 里面会包含一些 .class 文件.

war 包:是 java web 的程序, 里面除了会包含 .class 文件之外, 还会包含 HTML, CSS, JavaScript, 图 片, 以及其他的 jar 包. 打成 war 包格式才能被 Tomcat 识别

ServletHelloWorld-1.0-SNAPSHOT.jar 的由来

这个名字来源于

相当于把 artifactId 和 version 拼接起来了

通过pom.xml文件设置包名,及类型

通过packing 标签改变包名

表示打包的方式是打一个 war 包

<packaging>war</packaging>

通过 build 标签 设置,内置一个 finalName 标签,

表示打出的 war 包的名字是

<build> 
<finalName>ServletHelloWorld</finalName> 
</build>

6.程序部署

  • 把 war 包拷贝到 Tomcat 的 webapps 目录下
  • 启动 Tomcat , Tomcat 就会自动把 war 包解压缩.

7.验证程序

此时通过浏览器访问 http://127.0.0.1:8080/ServletHelloWorld/hello

即可看到结果

http://127.0.0.1:8080/路径

注意: URL 中的 PATH 分成两个部分, 其中 HelloServlet 为 Context Path, hello 为 Servlet Path

更方便的部署方式-Smart TomCat

安装 Smart Tomcat 插件

1. 菜单 -> 文件 -> Settings

2. 选择 Plugins(插件), 选择 Marketplace, 搜索 "tomcat", 点击 "Install".

注意: 安装过程必须要联网.

3. 安装完毕之后, 会提示 "重启 IDEA“

配置 Smart TomCat 插件

1. 点击右上角的 "Add Configuration

2. 选择左侧的 "Smart Tomcat"

3. 在 Name 这一栏填写一个名字(可以随便写)

在 Tomcat Server 这一栏选择 Tomcat 所在的目录(设置一次以后就不用设置了).

其他的选项不必做出修改

其中 Context Path 默认填写的值是项目名称.

这会影响到后面咱们的访问页面.

4. 点击 OK 之后, 右上角变成了

点击绿色的三角号, IDEA 就会自动进行编译, 部署, 启动 Tomcat 的过程

此时 Tomcat 日志就会输出在 IDEA 的控制台中, 可以看到现在就不再乱码了

5. 访问页面.

在浏览器中使用 http://127.0.0.1:8080/ServletHelloWorld/hello 访问页面.

注意路径的对应关系

部署方式

使用 Smart Tomcat 部署的时候, 我们发现 Tomcat 的 webapps 内部并没有被拷贝一个 war 包, 也没有看到解压缩的内容.

会发现给当前项目创建了一个单独的目录,把当前正在运行的Tomcat,搞一个副本,来运行当前正在编辑的代码

区分IDEA和TomCat之间的关系

IDEA 和 TomCat 之间是独立的两个进程,通过Smart Tomcat插件

让idea进程 调用 tomcat进程;

常见的访问错误

出现404

404表示用户访问的资源不存在,大概率是URL路径写的不正确

正确路径:https://127.0.0.1:8080/ServletHellowworld/hello

  • context path
    • 少写了context path

  • Servlet path
    • 少写了Servlet path

  • WebServlet()注解路径
    • WebServlet 注解中路径 同url中不匹配

  • web.xml写错了

出现405

405表示对应http请求方法没有实现

  • 没有实现对应的http请求方法

请求为GET,提供的实现却是POST就会引发405

  • 重写的实现方法,没有”干掉“父类方法

出现500

往往是Servlet代码抛出异常引起

比较好处理,日志或页面上就会明确提示除异常的调用栈等详细信息

实际开发中异常调用栈直接显示在页面上十分危险

出现”空白页面“

响应数据的body中没有提供数据

错误实例:

修改代码, 去掉 resp.getWritter().write() 操作

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
        System.out.println("hello");
    }
}

抓包观察,响应body中的内容就是空数据

出现无法访问此网站

一般为Tomcat 启动失败

  • Servlet Path出错

应该写作 "/hello", Tomcat 在启动的时候已经提示了相关的错误.

Tomcat 启动的日志里面报错信息可能比较多, 需要耐心观察, 找到关键的提示.

小结

熟悉 HTTP 协议能够让我们调试问题事半功倍.

  • 4xx 的状态码表示路径不存在, 往往需要检查 URL 是否正确, 和代码中设定的 Context Path 以及 Servlet Path 是否一致.
  • 5xx 的状态码表示服务器出现错误, 往往需要观察页面提示的内容和 Tomcat 自身的日志, 观察是否 存在报错.
  • 出现连接失败往往意味着 Tomcat 没有正确启动, 也需要观察 Tomcat 的自身日志是否有错误提示.
  • 空白页面这种情况则需要我们使用抓包工具来分析 HTTP 请求响应的具体交互过程.

Servlet 运行原理

TomCat的定位

浏览器发送http请求

当TomCat拿到请求后,对请求进行解析,返回一个HttpServletRequest对象,调用Servlet类,执行程序员写好的代码

详细的交互过程

用户发送请求-封装

应用层:用户在浏览器输入一个URL,浏览器就会构造出一个HTTP请求,通过HTTP协议封装,若url中ip地址位域名,通过DNS协议转换为对应IP地址;

传输层:基于TCP协议,封装数据,包括源端口号,目的端口号

网络层:基于IP协议,封装数据,包括源IP地址,目的IP地址

数据链路层:基于以太网帧,封装数据,通过ARP转换目的MAC包括源MAC地址,目的MAC地址

物理成:传输数据

通过网络设备,直至抵达目标主机;

详细过程可复习网路部分笔记

服务器接受请求-分用

1.接受数据

服务器从下到上分用解析数据

数据链路层:解析数据,检查MAC地址

网路层:解析数据,检查IP地址

传输层:解析数据,锁定目的端口

应用层:解析数据,TomCat通过Socket读取请求,按照HTTP请求格式解析,创建HTTPServletRequest对象,

根据 请求中的 Context Path 确定一个 webapp, 再通过 Servlet Path 确定一个具体的 类.

再根据当前请 求的方法 (GET/POST/...), 决定调用这个类的 doGet 或者 doPost 等方法.

此时我们的代码中的 doGet / doPost 方法的第一个参数 HttpServletRequest 就包含了这个 HTTP 请求的详细信息.

2.根据请求计算响应:

根据我们的代码,给HttpServletReponse对象设置属性

3.返回响应:

对应的请求方法执行结束后,TomCat自动将HttpServletResponse对象,转换为符合HTTP协议的字符串,通过Socket发送响应

通过网络协议,逐层封装数据,通过物理层发送数据

通过网络设备,传输至目标主机

目标主机,逐层分用解析,还原为HTTP响应,交由浏览器处理

TomCat的伪代码

TomCat初始化流程

  • Tomcat 的代码中内置了 main 方法. 当我们启动 Tomcat 的时候, 就是从 Tomcat 的 main 方法开 始执行的.
  • 被 @WebServlet 注解修饰的类会在 Tomcat 启动的时候就被获取到, 并集中管理.
  • Tomcat 通过 反射 这样的语法机制来创建被 @WebServlet 注解修饰的类的实例.
  • 这些实例被创建完了之后, 会调用其中的 init 方法进行初始化. (这个方法是 HttpServlet 自带的, 我们自己写的类可以重写 init,在初始化阶段进行其他工作)
  • 这些实例被销毁之前, 会调用其中的 destory 方法进行收尾工作. (这个方法是 HttpServlet 自带的, 我们自己写的类可以重写 destory)

destroy()有坑,不一定执行得到,若直接kill掉tomcat进程,此时destroy就不会执行

  • Tomcat 内部也是通过 Socket API 进行网络通信.
  • Tomcat 为了能同时相应多个 HTTP 请求, 采取了多线程的方式实现. 因此 Servlet 是运行在 多线程 环境 下的

TomCat处理请求流程

  • Tomcat 从 Socket 中读到的 HTTP 请求是一个字符串, 然后会按照 HTTP 协议的格式解析成一个 HttpServletRequest 对象.(根据协议解析为HttpServletRequest对象)
  • Tomcat 会根据 URL 中的 path 判定这个请求是请求一个静态资源还是动态资源.
    • 如果是静态资源, 直接找到对应的文件把文件的内容通过 Socket 返回.
    • 如果是动态资源, 才会执行到 Servlet 的相关 逻辑.
  • Tomcat 会根据 URL 中的 Context Path 和 Servlet Path 确定要调用哪个 Servlet 实例的 service 方 法.
  • 通过 service 方法, 就会进一步调用到我们之前写的 doGet 或者 doPos

Servlet 的 service 方法的实现

  • Servlet 的 service 方法内部会根据当前请求的方法, 决定调用其中的某个 doXXX 方法.
  • 在调用 doXXX 方法的时候, 就会触发 多态 机制, 从而执行到我们自己写的子类中的 doXXX 方法

Servlet API 详解

HttpServlet

我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法

核心方法

方法名称

调用时机

init

在 HttpServlet 实例化之后被调用一次

destory

在 HttpServlet 实例不再使用的时候调用一次

service

收到 HTTP 请求的时候调用

doGet

收到 GET 请求的时候调用(由 service 方法调用)

doPost

收到 POST 请求的时候调用(由 service 方法调用)

doPut/doDelete/doOptions/...

收到其他请求的时候调用(由 service 方法调用)

实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service .

处理GET/POST请求

  • 创建Servlet 类继承HttpServlet

  • 重写doXXXX(doGet/doPost)方法
@WebServlet("/method")
public class MethodServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //必须在添加body之前设置,否则无用
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("GET 响应");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("POST 响应");
    }
}

点击发送请求,可能会发现乱码(控制台)

编码方式不统一;

我们使用UTF-8,浏览器通常随windows系统使用GBK编码

我们可以在header中加入Content-Type,在其中注明编码格式

  • 测试,创建请求(通过前端ajax创建)

一个 Servlet 程序中可以同时部署静态文件. 静态文件就放到 webapp 目录中即可.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MethodServlet</title>
</head>
<body>
    <button onclick="sendGet()">发送GET请求</button>
    <button onclick="sendPost()">发送POST请求</button>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
        function sendGet(){
            $.ajax({
                type: "get",
                url: "method",
                success: function(data, status){
                    console.log(data);
                }
            })
        }
        function sendPost(){
            $.ajax({
                type: "post",
                url: "method",
                data: "request body",
                success: function(data, status){
                    console.log(data);
                }
            })
        }
    </script>
</body>
</html>

HttpServletRequest

当 Tomcat 通过 Socket API 读取 HTTP 请求(字符串), 并且按照 HTTP 协议的格式把字符串解析成HttpServletRequest 对象

HTTP请求报文:

首行:(方法 url 版本号) url:path,query string

header:键值对

空行:

body:

核心方法

方法

描述

String getProtocol()

返回请求协议的名称和版本。

String getMethod()

返回请求的 HTTP 方法的名称,

例如,GET、POST 或 PUT。

String getRequestURI()

从协议名称直到 HTTP 请求的第一行的查询字符串中,

返回该请求的 URL 的一部分。

URL:Location,资源位置;URI:Identify,资源表示符;使用场景类似

String getContextPath()

返回指示请求上下文的请求 URI 部分。

String getQueryString()

返回包含在路径后的请求 URL 中的查询字符串。

得到完整query string

Enumeration getParameterNames()

返回一个 String 对象的枚举,

包含在该请求中包含的参数的名称。

String getParameter(String name)

以字符串形式返回请求参数的值,

或者如果参数不存在则返回null。

String[] getParameterValues(String name)

返回一个字符串对象的数组,

包含所有给定的请求参数的值,

如果参数不存在则返回 null。

这几个方法,不光可以操作query string 还可以操作 x-www-form-urlencoded格式的body数据

允许多个键值对,键相同

Enumeration getHeaderNames()

返回一个枚举,

包含在该请求中包含的所有的头名。

String getHeader(String name)

以字符串形式返回指定的请求头的值。

String getCharacterEncoding()

返回请求主体中使用的字符编码的名称。

String getContentType()

返回请求主体的 MIME 类型,

如果不知道类型则返回 null。

int getContentLength()

以字节为单位返回请求主体的长度,

并提供输入流,

或者如果长度未知则返回 -1。

InputStream getInputStream()

用于读取请求的 body 内容.

返回一个 InputStream 对象

通过这些方法可以获取到一个请求中的各个方面的信息.

注意: 请求对象是服务器收到的内容, 不应该修改.

因此上面的方法也都只是 "读" 方法, 而不是 "写" 方法

HttpServletResponse

  • Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到 HttpServletResponse 对象中.
  • Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过 Socket 写回给浏览器

核心方法

方法

描述

void setStatus(int sc)

为该响应设置状态码。

void setHeader(String name,String value)

设置一个带有给定的名称和值的 header.

如果 name 已经存在,

则覆盖旧的值.

void addHeader(String name, String value)

添加一个带有给定的名称和值的 header.

如果 name 已经存在,

不覆盖旧的值,

并列添加新的键值对

对于http响应来说,header中的key并不是要求唯一的,有些key可以重复出现。

典型的就是 Set-Cookie 属性

void setContentType(String type)

设置被发送到客户端的响应的内容类型。

void setCharacterEncoding(String charset)

设置被发送到客户端的响应的字符编码(MIME 字符集)

例如,UTF-8。

void sendRedirect(String location)

使用指定的重定向位置 URL

发送临时重定向响应到客户端。

PrintWriter getWriter()

用于往 body 中写入文本格式数据.

OutputStream getOutputStream()

用于往 body 中写入二进制格式数据

Cookie 和 Session

Cookie:

是HTTP协议中的一个字段,同时是浏览器在客户端保存数码的一种方式;

Cookie从哪来?

  • 服务器产生,通过HTTP响应的Set-Cookie 字段 来进行设置,返回给浏览器

Cookie怎么存?

  • 在浏览器这边存储,浏览器会根据域名/地址,分别存储Cookie

Cookie 到哪去?

  • 会在下次请求中,自动添加到 请求中,发给服务器

Cookie 存的是什么?

  • 字符串;键值对结构的字符串;

Session :会话

服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系.

Session 本质就是 hash表;key就是SesionId,value 就是程序员自定义的数据(可以存储用户身份信息)

Cookie 和 Session 之间要相互配合

网页应用的登录流程

  • 浏览器:发送登录请求,包含用户名和密码;
  • 服务器:接收请求,拿到用户名和密码,在数据库中查找,根据用户名查找,查验用户名和密码的正确性;匹配则登录成功,失败登录失败;
    • 登录成功,服务器根据这次登录,生成会话信息,放到session中;
    • 设置Set-Cookie:将SessionId放入,返回给浏览器;
  • 浏览器:拿到SetCookie的值,并保存本地,浏览器根据域名,保存一份SessionId,之后发出请求,Cookie自动添加;
  • 服务器:拿到请求,根据Cookie中的SessionId,响应请求

Cookie 和 Session 的区别

  • Cookie 是客户端的机制. Session 是服务器端的机制.
  • Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合.
    • 完全可以用 Cookie 来保存一些数据在客户端.
      • 这些数据不一定是用户身份信息, 也不一定是 token / sessionId
    • Session 中的 token / sessionId 也不需要非得通过 Cookie / Set-Cookie 传递

核心方法:

HttpServletRequest 类

方法

描述

HttpSession getSession()

在服务器中获取会话.

参数如果为 true,

则当不存在会话时新建会话;

根据请求中SessionId获取当前的session;

  • 若session不存在,就创建;
  • 创建一个HttpSession对象,作为value;
  • 创建一个sessionId作为key
  • 将vaule key 插入hash中,将session通过SetCookie返回浏览器

参数如果为 false,

则当不存在会话时返回 null

Cookie[] getCookies()

返回一个数组,

包含客户端发送该请求的所有的 Cookie 对象.

会自动把Cookie 中的格式解析成键值对.

HttpServletResponse 类

方法

描述

void addCookie(Cookie cookie)

把指定的 cookie 添加到响应中

HttpSession 类

一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息

方法

描述

Object getAttribute(String name)

该方法返回在该 session 会话中具有指定名称的对象,

如果没有指定名称的对象,则返回 null.

void setAttribute(String name, Object value)

该方法使用指定的名称绑定一个对象到该 session 会话

boolean isNew()

判定当前是否是新创建出的会话

Cookie 类

每个 Cookie 对象就是一个键值对

方法

描述

String getName()

该方法返回 cookie 的名称。

名称在创建后不能改变。

(这个值是 SetCooke 字段设置给浏览器的)

String getValue()

该方法获取与 cookie 关联的值

void setValue(String newValue)

该方法设置与 cookie 关联的值。

  • HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie对象.
  • 通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对.
  • 通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对

上传文件

上传文件在Servlet中的支持

核心方法

HttpServletRequest 类方法

方法

描述

Part getPart(String name)

获取请求中给定 name 的文件

Collection getParts()

获取所有的文件

前端,选择文件上传,一次可以选择多个文件,每个文件就是一个Part

每个文件都有自己的 name(input 标签中 name属性)

在服务器中通过 这个name 找到对应的 Part(part中包含文件内容)

Part 类方法

方法

描述

String getSubmittedFileName()

获取提交的文件名

String getContentType()

获取提交的文件类型

long getSize()

获取文件的大小

void write(String path)

把提交的文件数据写入磁盘文件

最难不过坚持!

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值