Servlet之Request和Response的快速上手

阅读提示:

1、Request和Response概述

  • request:获取请求数据
  • 浏览器会发送HTTP请求到后台服务器[Tomcat]
  • HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
  • 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
  • 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
  • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
  • response:设置响应数据
  • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
  • 把响应数据封装到response对象中
  • 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
  • 浏览器最终解析结果,把内容展示在浏览器给用户浏览
  • 案例
@WebServlet("/demo")
public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用request对象 获取请求数据
        String name = request.getParameter("name"); //用于获取请求参数,如url?name=zhangsan

        //使用response对象 设置响应数据
        response.setHeader("content-type","text/html;charset=utf-8");
        response.getWriter().write(""+name+",欢迎您!");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Post...");
    }
}

2、Request对象

2.1 Request继承体系

类或接口 说明 ServletRequest Java提供的请求对象根接口 ↑ — HttpServletRequest Java提供的针对HTTP协议封装的请求对象接口 ↑ — RequestFacade Tomcat定义的实现类

2.2 Request获取请求数据

2.2.1 获取请求行

  • 请求行示例

    GET /request-demo/req1?name=zhangsan&password=123/ HTTP/2 分别为请求方式、请求资源路径和参数、协议和版本号

  • 获取方法
// 获取请求方式 GET
String getMethod();
// 获取虚拟目录(项目访问路径) /request-demo
String getContextPath();
// 获取URL(统一资源定位符)http://localhost:8080/request-demo/req1
StringBuffer getRequestURL();
// 获取URI(统一资源标识符)/request-demo/req1
String getRequestURI();
// 获取请求参数(GET方式)name=zhangsan&password=123
String getQueryString();

2.2.2 获取请求头

  • 请求头示例

    User-Agent: Mozilla/5.0 Chrome/91.0.4472.106

  • 获取方法
// 获取请求头,参数为对应的键
String getHadder(String name);

2.2.3 获取请求体

  • 请求体用于POST请求方式
  • 获取方法
// 获取字节流,用于二进制数据
ServletInputStream getInputStream();
// 获取字符流,用于纯文本数据
BufferedReader getReader();

2.2.4 获取请求参数的通用方式

  • 存在问题

    BufferedReader getReader();获取文本数据需要手动解析

  • 改进方法
// 获取所有参数Map集合(Map集合的Value元素采用数据,以应对多选等情况)
Map getParameterMap();
// 根据名称获取参数值(数组)
String[] getParameterValues(String name);
// 根据名称获取参数值(单个值)
String getParameter(String name);

2.3 请求参数中文乱码问题

2.3.1 POST请求解决方案

  • 分析原因
  • POST的请求参数是通过 request的 getReader()来获取流中的数据
  • TOMCAT在获取流的时候采用的编码是 ISO-8859-1
  • 在获取参数前设置使用需要的编码
// 设置字符输入流编码,设置字符集和页面保持一致,不区分大小写
request.setCharacterEncoding("UTF-8");

2.3.2 GET请求解决方案

  • 分析原因
  • 字符串用过HTTP由浏览器提交到服务器
  • 服务器不支持中文,会将字符进行URL编码
  • 将URL编码发送到服务器,由服务器进行解码
  • TOMCAT服务器对GET请求获取请求参数的方式是 request.getQueryString(),与POST请求不同
  • TOMCAT默认使用 ISO-8859-1进行URL解码
  • TOMCAT中 getParameter(String name);方法将URL解码采用的编码格式写死,无法修改
  • 在获取参数前设置使用需要的编码
// 浏览器采用UTF-8将字符进行RUL编码
// 服务器采用ISO-8859-1进行URL解码,此时采用编码为ISO-8859-1,出现乱码

// 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
// 将字节数组使用UTF-8重新编码
username = new String(bytes, StandardCharsets.UTF_8);
  • 备注

    Tomcat 8.0以上 解决了GET请求的乱码问题,设置了URL解码的默认方式为UTF-8

  • URL编解码
// 编码
URLEncoder.encode(str,"UTF-8");
// 解码
URLDecoder.decode(s,"ISO-8859-1");

2.4 Request 请求转发

  • 请求转发是一种在服务器内部的跳转方式
  • 实现请求转发
  • 接收资源A请求,执行其对应Servlet方法
  • 资源A中要跳转到资源B
  • 将请求转发到资源B
  • 执行资源BServlet方法
// 在资源A中
req.getRequestDispatcher("资源B路径").forward(req,resp);
  • 请求转发资源间共享数据:使用Request对象

    将该需要共享的数据(有需要时封装为对象)放在Request域中,可在转发后进行获取

// 以(k, v)存储数据到request域中
void setAttribute(String name,Object o);
// 根据key获取value
Object getAttribute(String name);
// 根据key删除该键值对
void removeAttribute(String name);
  • 请求转发的特点
  • 浏览器地址栏的路径不发生变化
  • 只能转发到当前服务器内部资源
  • 一次请求,可以在转发的资源间使用request共享数据

3、Response对象

3.1 Response继承体系

类或接口 说明 ServletResponse Java提供的响应对象根接口 ↑ — HttpServletResponse Java提供的针对HTTP协议封装的响应对象 ↑ — ResponseFacade Tomcat定义的实现类

3.2 Response设置响应数据功能介绍

  • 设置响应行

    HTTP/2 200 OK

// 设置响应状态码
void setStatus(int sc);
  • 设置响应头

    Content-Type:text/html

// 设置响应头键值对
void setHeader(String name,String value);
  • 设置响应体

    HTML代码等,通过字符、字节输出流的方式网浏览器写

// 获取字符输出流
PrintWriter getWriter();
// 获取字节输出流
ServletOutputStream getOutputStream();

3.3 Response请求重定向

  • 重定向:一种资源跳转的方式,区别于转发
  • 浏览器发送发送请求到服务器,其中资源A接收到请求
  • 资源A无法处理,但知道资源B资源可以处理,对浏览器做出响应,告知状态和处理方法
    • 响应状态码: 302
    • 响应头给出资源位置: location:xxx
  • 浏览器接收到响应状态码 302
  • 浏览器重新发送请求到请求头中 location对应的地址寻找到资源B
  • 资源B接收请求后,进行处理,返回结果到服务器
  • 重定向实现方式
/*
// 设置响应状态码和响应头
resp.setStatus(302);
resp.setHeader("location","项目虚拟目录(项目访问路径)+资源B的访问路径");
*/

// 设置重定向
resp.sendRedirect("虚拟目录(项目访问路径)+资源B的访问路径");
  • 重定向的特点(区别于请求转发)
  • 浏览器地址栏路径发生变化
  • 可以重定向到任意资源位置,不局限于服务器内部
  • 两次请求之间,不能在多个资源使用Request域共享数据

3.4 路径问题

  • 关于虚拟目录(明确路径被谁使用)
  • 浏览器使用:需要加虚拟目录(项目访问路径) — 如重定向
  • 服务器使用:无需虚拟目录 — 如请求转发
  • 举例
  • 需要加虚拟目录
    • resp.sendRedirect("路径")
  • 不需要虚拟目录
    • req.getRequestDispatcher("路径");
  • 动态获取虚拟目录

            org.apache.toncat.maven
            tomcat-maven-plugin
            2.2

// 动态获取虚拟目录
String contextPath = request.getContextPath();

3.5 Response相应字符数据

字符输出流不需要关闭,其由Response对象获取,会随Response对象的回收而回收

  • 返回简单字符串 aaa
// 通过Response对象获取字符输出流
PrintWriter writer = response.getWriter();
// 写数据
writer.write("aaa");
  • 返回HTML代码,切能被解析
// 通过Response对象获取字符输出流
PrintWriter writer = response.getWriter();
// 设置响应头content-type,让浏览器以HTML格式进行解析
response.setHeader("content-type","text/html");
// 写HTML代码
writer.write("aaa");
  • 返回中文字符串,设置编码格式为UTF-8(通过Response获取的字符输出流默认编码为 ISO-8859-1
// 通过Response对象获取字符输出流
PrintWriter writer = response.getWriter();
// 设置响应头content-yupe,使用HTML格式解析,并注明字符集
// response.setHeader("content-type","text/html;cahrset=utf-8");
response.setContentType("text/html;cahrset=utf-8");
// 写HTML代码
writer.write("你好");
// writer.write("你好");

3.6 Response相应字节数据

  • 返回字节数据使用方法
// 通过Response对象获取字节输出流
ServletOutputStream outputStream = resp.getOutputStream();
// 通过字节输出流写数据
outputStream.write(字节数据);
  • 示例
// 读取文件
FileInputStream fis = new FileInputStream("d://demo.jpg");
// 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
// 完成流的copy
byte[] buff = new byte[1024];
int len = 0;
while ((len = fis.read(buff))!= -1){
    os.write(buff, 0, len);
}

fis.close();
  • 使用工具类改进示例

            commons-io
            commons-io
            2.6

// 读取文件
FileInputStream fis = new FileInputStream("d://demo.jpg");
// 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
// 完成流的copy
// byte[] buff = new byte[1024];
// int len = 0;
// while ((len = fis.read(buff))!= -1){
//     os.write(buff, 0, len);
// }
IOUtils.copy(fis, os);

fis.close();

4、用户注册登录案例

4.1用户登录和注册案例

4.1.1 需求分析

  • 登录
  • 用户填写用户名密码,提交到LoginServlet
  • 在LoginServlet中使用MyBatis查询数据库,验证用户名密码是否正确
  • 如果正确响应登录成功,否则响应登录失败
  • 注册
  • 用户填写用户名密码,提交到RegisterServlet
  • 在LoginServlet中使用MyBatis查询数据库,验证用户名是否存在
  • 若不存在则向数据库中插入新的用户数据,否则响应注册失败

4.1.2 环境准备

  • 依赖导入

  4.0.0

  priv.dandelion
  day09RequestResponse
  1.0-SNAPSHOT
  war

      org.mybatis
      mybatis
      3.5.5

      mysql
      mysql-connector-java
      5.1.34

      junit
      junit
      4.11

      org.slf4j
      slf4j-api
      1.7.20

      ch.qos.logback
      logback-classic
      1.2.3

      ch.qos.logback
      logback-core
      1.2.3

      javax.servlet
      javax.servlet-api
      3.1.0
      provided

      commons-io
      commons-io
      2.6

        org.apache.tomcat.maven
        tomcat7-maven-plugin
        2.2

  • 页面

    注:代码中虚拟目录位置需要进行替换

  • 登录

    login

        LOGIN IN
         Username:

         Password:

            没有账号?点击注册

  • 注册

    欢迎注册

        欢迎注册
        已有帐号? 登录

                用户名

                    用户名不太受欢迎

                密码

                    密码格式有误

  • 数据库和实体类
  • User表
-- 创建用户表
CREATE TABLE tb_user(
    id int primary key auto_increment,
    username varchar(20) unique,
    password varchar(32)
);

-- 添加数据
INSERT INTO tb_user(username,password) values('zhangsan','123'),('lisi','234');

SELECT * FROM tb_user;

  • 实体类
package priv.dandelion.entity;

public class User {
    private Integer id;
    private String username;
    private String password;

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public User() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

  • MyBatis
  • 核心配置文件

    注:代码中数据库名称需要进行替换


  • UserMapper.xml映射文件

    先完成接口,再由MyBatisX插件生成,或手动再resources目录下创建


  • UserMapper接口
public interface UserMapper {

    // 查询已存在用户数量,防止重复注册
    @Select("select * from tb_user where username = #{username} limit 0, 1")
    public User selectByUsername(@Param("username") String username);

    // 查询用户信息
    @Select("select * from tb_user where username = #{username} and password = #{password} limit 0, 1")
    public User selectAll(@Param("username") String username, @Param("password") String password);

    @Insert("insert into tb_user(username, password) VALUES (#{username}, #{password})")
    public void insertUser(@Param("username") String username, @Param("password") String password);
}

4.1.3 代码实现

注:实现流程

  1. 接收用户名和密码
  2. 解决Request中文乱码
  3. 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
  4. 将字节数组使用UTF-8重新编码
  5. 调用MyBatis完成查询
  6. 加载MyBatis核心配置文件,获取SqlSessionFactory
  7. 获取Session对象,设置自动提交事务
  8. 获取UserMapper
  9. 执行SQL
  10. 处理结果并返回数据
  11. 设置response编码并获取字符输出流
  12. 处理结果(注册时需要额外判断用户是否已经存在)
  13. 释放资源

  14. 登录Servlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("开始进行登录判断");

        // 接收用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 解决Request中文乱码
        // 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
        // 将字节数组使用UTF-8重新编码
        username = new String(bytes, StandardCharsets.UTF_8);

        // 调用MyBatis完成查询
        // 加载MyBatis核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取Session对象,设置自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 获取UserMapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 执行SQL
        User user = userMapper.selectAll(username, password);

        // 设置response编码并获取字符输出流
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();

        // 处理结果
        if (user != null) {
            // 登录成功
            writer.write("login success" + user.getUsername() + "欢迎您");
        } else {
            // 登录失败
            writer.write("login fail 用户" + user.getUsername() + "不存在");
        }
        // 释放资源
        sqlSession.close();
        System.out.println("login end");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
  • 注册Servlet
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("register start");
        // 接收用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 解决Request中文乱码
        // 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
        // 将字节数组使用UTF-8重新编码
        username = new String(bytes, StandardCharsets.UTF_8);

        // 调用MyBatis完成查询
        // 加载MyBatis核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取Session对象,设置自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 获取UserMapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 执行SQL,处理结果
        User user = userMapper.selectByUsername(username);

        // 设置response编码并获取字符输出流
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();

        // 查重
        if (user == null){
            userMapper.insertUser(username, password);
            // 注册成功
            writer.write("register success 成功");
        } else {
            System.out.println(user.getUsername());
            // 注册失败
            writer.write("用户名已被占用");
        }

        // 释放资源
        sqlSession.close();
        System.out.println("register end");

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

4.2 SQLSessionFactory工具抽取:改进登录案例

  • 案例存在问题
  • SqlSessionFactory创建部分存在代码冗余
  • SqlSessionFactory内置连接池,多次创建资源消耗较大
  • 改进方案
  • 使用工具类解决代码重复问题
  • 使用静态代码块实现仅创建一次 SqlSessionFactory
  • 代码实现
  • 工具类
public class SqlSessionFactoryUtils {

    // 提升作用域,用于返回值
    private static SqlSessionFactory sqlSessionFactory;

    // 静态代码块会随着类的加载自动执行且只执行一次
    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    // 返回工厂对象
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

}
  • 改进后代码(以 LoginServlet为例)
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("开始进行登录判断");

        // 接收用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 解决Request中文乱码
        // 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
        // 将字节数组使用UTF-8重新编码
        username = new String(bytes, StandardCharsets.UTF_8);

        // 调用MyBatis完成查询
        // 加载MyBatis核心配置文件,获取SqlSessionFactory,已通过工具类进行改进
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        // 获取Session对象,设置自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 获取UserMapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 执行SQL
        User user = userMapper.selectAll(username, password);

        // 设置response编码并获取字符输出流
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();

        // 处理结果
        if (user != null) {
            // 登录成功
            writer.write("login success" + user.getUsername() + "欢迎您");
        } else {
            // 登录失败
            writer.write("login fail 用户" + user.getUsername() + "不存在");
        }
        // 释放资源
        sqlSession.close();
        System.out.println("login end");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

Original: https://www.cnblogs.com/dandelion-000-blog/p/16738687.html
Author: Dandelion_000
Title: Servlet之Request和Response的快速上手

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714225/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Goroutines (一)

    Goroutines CSP communicating sequential processes Go 语言中,每一个并发执行单元叫做一个goroutine,语法上仅需要在一个普…

    技术杂谈 2023年7月11日
    058
  • nodejs中使用websockets

    websockets介绍 websockets这个新协议为客户端提供了一个更快、更有效的通信线路。像HTTP一样,websockets运行在TCP连接之上,但是它们更快,因为我们不…

    技术杂谈 2023年5月31日
    0100
  • 抽象类和接口

    Loading Tips: 除非必须使用,否则不要用接口 和 抽象类(大多时候,常规类就可以解决问题) 在合理的范围内尽可能抽象,相比于抽象类,我们 更倾向于接口的使用 poste…

    技术杂谈 2023年7月25日
    075
  • 深入源码理解Spring整合MyBatis原理

    写在前面 聊一聊MyBatis的核心概念、Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的。(结合右侧目录了解吧) MyBatis相关核心概念粗略…

    技术杂谈 2023年7月25日
    083
  • eslint 报错-Missing space before value for key ‘xxx’

    es-lint报错 原因:对象值前没有加空格 解决: 本文来自博客园,作者:King-DA,转载请注明原文链接:https://www.cnblogs.com/qingmuchua…

    技术杂谈 2023年6月1日
    080
  • Kubernetes: Kubesphere 和 Rancher

    Kubesphere 和 Rancher 如何做抉择? – 掘金https://juejin.cn/post/7030740701260316702 (40条消息) k…

    技术杂谈 2023年6月1日
    053
  • 使用freemarker对模板进行渲染

    public class FreemarkerUtilsTest extends TestCase {public void generateStringTest(){Map&lt…

    技术杂谈 2023年6月1日
    092
  • 轻量级多级菜单控制框架程序(C语言)

    1、前言 作为嵌入式软件开发,可能经常会使用命令行或者显示屏等设备实现人机交互的功能,功能中通常情况都包含 UI 菜单设计;很多开发人员都会有自己的菜单框架模块,防止重复造轮子,网…

    技术杂谈 2023年7月25日
    061
  • Redis篇:事务和lua脚本的使用

    现在多数秒杀,抽奖,抢红包等大并发高流量的功能一般都是基于 redis 实现,然而在选择 redis 的时候,我们也要了解 redis 如何保证服务正确运行的原理 前言 redis…

    技术杂谈 2023年7月25日
    073
  • SpringBoot集成JWT(极简版)

    SpringBoot集成JWT(极简版) 在WebConfig配置类中设置接口统一前缀 import org.springframework.context.annotation….

    技术杂谈 2023年7月11日
    075
  • (三)underscore.js框架Objects类API学习

    _.keys(object)Retrieve all the names of the object‘s properties. _.keys({one: 1, two…

    技术杂谈 2023年5月31日
    097
  • oracle 11g RAC public/virtual/SACN/private IP we need to know

    Before starting the installation, you must have at least two interfaces configured on each…

    技术杂谈 2023年6月1日
    094
  • 基于zookeeper集群的云平台-配置中心的功能设计

    最近准备找工作面试,就研究了下基于zookeeper集群的配置中心。 下面是自己设想的关于开源的基于zookeeper集群的云平台-配置中心的功能设计。大家觉得哪里有问题,请提出宝…

    技术杂谈 2023年7月11日
    072
  • 2-3树/红黑树

    2-3树 为了维护2-3树绝对平衡的性质,插入结点时就要符合一下逻辑: 添加结点不能添加到空位置,除非此时整个树为空。 如果按照二分搜索树的方式插入元素,如果插入位置为空,此时和最…

    技术杂谈 2023年7月24日
    094
  • 面向对象ooDay7

    .精华笔记:1)成员内部类: 应用率不高1.1)类中套类,外面的称为外部类,里面的称为内部类1.2)内部类通常只服务于外部类,对外不具备可见性1.3)内部类对象通常在外部类中创建1…

    技术杂谈 2023年7月11日
    052
  • quartz框架(六)-ThreadPool

    本篇博文,博主将介绍Quartz框架中ThreadPool线程池相关的内容。线程池顾名思义,就是一个可以帮助我们来进行线程资源管理的对象。在web开发中,常见的就有数据库连接池,h…

    技术杂谈 2023年7月24日
    079
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球