Servlet_day2 (上)|Servlet 整合 JDBC|请求转发 forward|Request 作用域

📖前言

上一节我们学习了 Servlet 基础开发、获取请求参数。 真实业务开发不会把 JDBC 数据库代码直接写死在 Servlet 类里面,需要做分层拆分;同时业务经常需要 Servlet 之间跳转、传递数据,就需要学习请求转发 与request 作用域。

一、Servlet 整合 JDBC ------ 分层开发实战

核心思想:各司其职,把代码进行分层解耦,提高项目可维护性。 传统写法:在 Servlet 中直接写 JDBC 连接、SQL、处理结果。 ❌弊端:Servlet 代码臃肿,业务逻辑、数据库操作全部混在一起,后期修改维护非常麻烦。

整体分层结构

  1. 数据库层:建表
  2. 实体类 Entity:和数据库表一一对应,封装表数据
  3. DAO 层:数据访问层,接口 + 实现类,专门负责数据库 CRUD
  4. Service 层:业务层,接口 + 实现类,处理业务逻辑,调用 DAO
  5. Servlet 层:控制器,接收浏览器请求,调用 Service,处理跳转与数据展示

开发完整步骤

1. 环境准备
  1. 将数据库驱动 jar 包(ojdbc.jar / mysql‑connector‑java.jar)复制到项目 WEB‑INF/lib
  2. 导入jdbc.properties配置文件
  3. 导入之前写好的JDBCUtil工具类,用于获取连接、关闭资源
2. 编码步骤
  1. 创建数据库表,设计字段
  2. 封装实体类(Entity):一张表对应一个实体类,私有属性、get/set、无参构造、toString
  3. 编写 DAO 层:DAO 接口 + DAO 实现类,完成数据库增删改查

✨写完 DAO 之后,建议写 JUnit 单元测试,验证数据库操作是否正常!

  1. 编写 Service 层:Service 接口 + Service 实现类,调用 DAO 完成业务逻辑

✨写完 Service 同样建议单元测试,确保业务逻辑没问题

  1. 编写 Servlet 控制器
    • 继承HttpServlet
    • 重写 service 方法
    • 设置响应编码
    • 调用 Service 获取业务数据
    • 将数据交给页面 / 另一个 Servlet 展示
    • 在web.xml中配置 servlet 注册与 url‑pattern 映射

💡分层带来的业务优势 把业务调用、数据展示进行拆分:

  • ServletA:只负责接收请求,执行业务逻辑
  • ServletB:专门负责数据展示渲染页面

好处:前端页面可以随时替换。例如:春节一套页面、端午节一套页面、国庆节一套页面;业务逻辑代码完全不用改动,只更换展示 Servlet 即可。

衍生两个必须解决的核心问题:

  1. 如何从一个 Servlet 跳转到另外一个 Servlet?👉请求转发 forward
  2. Servlet 之间跳转,如何传递数据?👉request 作用域

二、请求转发 forward

2.1 什么是请求转发

请求转发(forward)属于服务器内部跳转机制。 将多个 Servlet 串联起来形成工作流,一次请求内部,从 AServlet 跳转到 BServlet,多个 Servlet 协同完成一整套业务。

整个跳转动作全部发生在 Tomcat 服务器内部,浏览器完全感知不到跳转过程。

2.2 请求转发核心 API

复制代码
//获取请求转发器,参数:目标跳转的Servlet访问路径,路径必须以 / 开头
RequestDispatcher dispatcher = request.getRequestDispatcher("/showAllServlet");
//执行转发
dispatcher.forward(request,response);

简化链式写法(开发常用)

复制代码
request.getRequestDispatcher("/showAllServlet").forward(request,response);

2.3 请求转发五大核心特点【重点,面试常考】

  1. ✅浏览器地址栏 URL 不会发生变化。跳转是服务器内部行为,浏览器只发起了 1 次请求。
  2. ✅转发的多个 Servlet 属于同一次 HTTP 请求,共用同一个 request、response 对象。
  3. ✅只有转发链路上最后一个 Servlet 可以向客户端输出响应结果;前面 Servlet 不要做输出。
  4. ✅可以借助request作用域在转发的 Servlet 之间传递数据。
  5. ❌不能转发到项目以外的资源,只能转发当前 web 项目内部的 Servlet、html。

⚠️易错坑点: 转发之前,如果前面的 Servlet 已经调用out.write()输出数据,会抛出异常。 业务逻辑 Servlet 只做处理、存数据,不要输出页面;页面渲染交给目标 Servlet 完成。

简单流程演示

  1. 客户端浏览器发送请求访问 AServlet
  2. AServlet 在服务器内部转发跳转到 BServlet
  3. BServlet 负责输出网页返回给浏览器
  4. 浏览器地址栏依旧显示访问 AServlet 的地址

三、request 作用域

3.1 什么是 request 作用域

request对象本身自带一块存储空间,叫做request 作用域。

因为请求转发多个 Servlet 属于同一次请求,所以存放在 request 作用域的数据,可以在转发链路中的各个 Servlet 之间共享。
⏱生命周期:浏览器发起请求创建 request 对象;请求处理完毕,响应返回浏览器,request 对象就被销毁,里面存放的数据全部失效。

3.2 request 作用域核心 API

表格

方法 作用说明
request.setAttribute(String name,Object value) 存数据:向 request 域存入键值对,value 可以是任意对象(字符串、实体对象、List 集合)
Object request.getAttribute(String name) 取数据:根据 key 取出域中保存的数据,返回 Object,需要强制类型转换
request.removeAttribute(String name) 删除数据:移除作用域中指定 key 的数据

代码示例

AServlet(业务处理,存入数据,转发)

复制代码
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.调用service查询账户集合数据
    AccountService accountService = new AccountServiceImpl();
    List<Account> list = accountService.queryAll();

    //2.把查询到的集合存入request作用域
    request.setAttribute("accountList",list);

    //3.请求转发跳转到展示数据的BServlet
    request.getRequestDispatcher("/showServlet").forward(request,response);
}

BServlet(接收转发,取出数据,展示页面)

复制代码
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/html");
    response.setCharacterEncoding("GBK");
    PrintWriter out = response.getWriter();

    //从request作用域取出数据,Object强转成List集合
    List<Account> list = (List<Account>) request.getAttribute("accountList");

    //遍历集合输出网页表格
    out.println("<table border='1'>");
    for(Account acc : list){
        out.println("<tr>");
        out.println("<td>"+acc.getId()+"</td>");
        out.println("<td>"+acc.getName()+"</td>");
        out.println("</tr>");
    }
    out.println("</table>");
}

执行流程图解文字说明

  1. 浏览器请求 AServlet;Tomcat 创建本次请求的request对象。
  2. AServlet 执行业务查询,调用setAttribute(),把 List 集合存入 request 域。
  3. 执行 forward 转发,服务器内部跳转到 BServlet;还是同一个 request 对象。
  4. BServlet 调用getAttribute()取出集合,渲染 HTML 表格输出页面。
  5. 响应返回浏览器,本次请求结束,request 对象销毁,域内数据全部清空。

💡重要提醒: getAttribute(key)返回 Object,如果 key 不存在,返回null,一定要做判空,避免空指针异常。

✍课堂练习

使用 请求转发 + request 作用域,重构查询全部账户案例:

  1. QueryAllServlet:接收请求,调用 Service 查询全部账户数据,存入 request 域,转发给ShowServlet。
  2. ShowServlet:从 request 域取出账户集合,输出 HTML 表格展示数据。

📝知识点小结

  1. Servlet 整合 JDBC 要分层:实体类→DAO→Service→Servlet,各司其职,提高可维护性;DAO、Service 建议单元测试。
  2. 请求转发 forward:服务器内部跳转,地址栏不变,属于同一次请求,只能转发本项目资源。
  3. request 作用域:同一次请求内共享数据;setAttribute()存,getAttribute()取;请求结束,域对象销毁。
  4. 转发业务规范:源 Servlet 负责业务逻辑、存域对象,不要输出页面;目标 Servlet 负责页面渲染输出。

📢 以上为本篇 Servlet 学习笔记,若有更好的建议,欢迎评论区商讨交流,欢迎各位大佬指正、补充不同实现思路。

💡拓展思考:转发是服务器内部跳转,那如果想要浏览器地址栏发生变化,该用什么方式?下一节会学习重定向 redirect,对比转发与重定向的区别。

相关推荐
螺蛳粉 螺蛳粉7 小时前
CDH第四篇:CDH 元数据库实战:MySQL 5.7.22 二进制安装 + 三库三账号授权全记录
hive·mysql5.7·centos7·元数据·cdh·oozie·数据库部署
chunyublog14 小时前
FinalShell 远程连接 Hadoop 三节点集群教程
大数据·hadoop·分布式
爱吃火鸡面呀15 小时前
MySQL、ClickHouse、Doris、Hive、Spark SQL、Flink SQL 选型对比:优点、缺点与面试话术
hive·mysql·clickhouse
ha_lydms2 天前
AnalyticDB MySQL 技术架构
大数据·hadoop·mysql·adb·spark·dataworks·1024程序员节
螺蛳粉 螺蛳粉4 天前
大数据第四篇:事故复盘:移走 HBase 里 27 个 hadoop-2.10.2 jar 后,HMaster 半小时后“自杀“了【jar 事故复盘】
jvm·hadoop·hbase·异常处理·大数据运维·踩坑记录·事故复盘
鬼手点金4 天前
单轮对话:最简单的 API 调用
java·服务器·前端·javascript·react.js·servlet·tomcat
Francek Chen4 天前
【大数据处理与分析】数据仓库Hive:08 Impala
数据仓库·hive·hadoop·数据分析·impala
ha_lydms5 天前
Window Functions(窗口函数)
大数据·数据仓库·hadoop·spark·数据处理·dataworks·maxcompute
步行cgn6 天前
Servlet 中的三个域对象
servlet