使用“纯”Servlet做一个单表的CRUD操作

news2024/11/15 6:53:18

 1. 项目说明

介绍: 这里我们使用 纯粹 的 Servlet 完成单表【对部门的】的增删改查操作。(B/S结构的。)

结构图

在这里插入图片描述

初始的欢迎页面

在这里插入图片描述

部门列表页面

在这里插入图片描述

部门详情

在这里插入图片描述

修改部门

在这里插入图片描述

删除部门:

在这里插入图片描述

新增部门:

在这里插入图片描述

2. 具体对应的功能的代码实现

2.1 准备工作:

  1. 首先我们使用数据库,存储数据,这里我们使用的数据库是 MYSQL 。
  2. 我们需要准备一个名为 dept的数据表,并插入一些数据。
create table dept (
  depton int primary key,
  dname varchar(255),
  loc varchar(255)
);

insert into dept(depton,dname,loc) values(10,'xiaoShouBu','BEIJING');
insert into dept(depton,dname,loc) values(20,'YanFaBu','SHANGHAI');
insert into dept(depton,dname,loc) values(30,'JisShuBu','GUANGZHOU');
insert into dept(depton,dname,loc) values(40,'MeiTiBu','SHENZHEN');
select * from dept;

小技巧: MySQL 在 cmd 命令中,批量执行 sql语句的方法:如下,首先将编写好的 .sql 文件存储起来。如下图所示,

在这里插入图片描述

再打开cmd 进入命令窗口,再进入到Mysql当中,输入如下命令:

source 后接文件路径(要执行的批量的.sql文件)

在这里插入图片描述

当前数据表 dept 的信息内容如下:

在这里插入图片描述

  1. 为该模块导入 MYSQL的 JDBC 的 jar 包。

注意: 因为我们是在 Tomcat 服务器当中部署项目的,所以我们需要在 WEB-INF 的目录下,创建一个名为 lib 的目录文件夹,用来存放相关的 依赖jar 包,注意路径位置不可以修改,目录文件必须为 lib 不然,当你启动的Tocmat 服务器的时候,是无法找到该对应的 依赖jar 包的。具体如下,我们将 Mysql对应的 jdbc jar 包导入其中。

  • 创建一个webapp(给这个webapp添加servlet-api.jar和jsp-api.jar到classpath当中。)
  • 向webapp中添加连接数据库的jar包(mysql驱动)
    • 必须在WEB-INF目录下新建lib目录,然后将mysql的驱动jar包拷贝到这个lib目录下。这个目录名必须叫做lib,全部小写的。

在这里插入图片描述

2.2 模块目录结构

在这里插入图片描述

2.3 工具类 DBUtil

这里因为我们要连接数据库,所以我们编写一个连接Mysql 数据库的 工具类,这里我们名为一个 DBUtil 的工具类。

这里我们通过读取配置jdbc.properties的配置文件的方式,注册相对应的Mysql驱动 。

如下是相关: jdbc.properties 的配置信息

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
user=root
password=123

再编写好相关的:DBUtil 类 ,具体代码的编写内容如下:

package com.RainbowSea.DBUtil;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

/**
 * JDBC工具类
 */
public class DBUtil {

    // 静态变量,在类加载时执行
    // 都是一些从 jdbc.properties 读取到的配置文件的信息
    // 该方法仅仅只会读取 “.properties" 的后缀的文件,注意:默认是从src目录开始的,有子目录需要写明子目录
    private static ResourceBundle bundle = ResourceBundle.getBundle("com/RainbowSea/resources/jdbc");
    private static String driver = bundle.getString("driver"); // 根据properties中的name读取对应的value值
    private static String url = bundle.getString("url");
    private static String user = bundle.getString("user");
    private static String password = bundle.getString("password");


    static {
        // 注册驱动(注册驱动只需要注册一次,放在静态代码当中,DBUtil类加载的时候执行)
        // "com.mysql.jdbc.Driver"是连接数据库的驱动,不能写死,因为以后可能还会连接Oracle数据库。
        // OCP开闭原则: 对扩展开放,对修改关闭(什么是符合 OCP呢?在进行功能扩展的时候,不需要修改java源代码)
        // Class.forName("com.mysql.jdbc.Driver")

        try {
            Class.forName(driver);  // 加载驱动
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * 获取数据库连接
     * @return Connection
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }


    /**
     * 关闭连接
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        // 注意:分开try,最后使用的资源,优先关闭
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        if(statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }


        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

2.4 功能一: index.html 该项目的欢迎页面如下:

默认在 web 当中,一个全局配置信息当中,会将名为 index.html 的文件,设置为该项目的欢迎页面。相应的具体内容大家可以移步至 🔜🔜🔜 关于Web的欢迎页面的开发设置_ChinaRainbowSea的博客-CSDN博客

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎使用OA系统</title>
</head>
<body>
    <!--注意:对应前端的资源获取基本上都是要加项目名的,并且要"/"开始-->
    <a href="/servlet09/dept/list/">查看部门列表</a>
</body>
</html>

2.5 功能二:部门列表 DeptListServlet

注意:因为我们这里使用的是 纯 Servlet 编写的一个项目,所以在后端想要将相关的 HTML 标签相应到前端浏览器,被浏览器渲染的话,则需要特殊的方法:如下

// 设置将后端的字符串的 html 标签相应到浏览器端执行处理,并设置相应的字符集编码
response.setContentType("text/html;charSet=UTF-8");
PrintWriter writer = response.getWriter();

思路:

  1. DeptListServlet类的doGet方法中连接数据库,查询所有的部门,动态的展示部门列表页面.
  • 分析 html 页面中哪部分是固定死的,哪部分是需要动态展示的。

  • html页面中的内容所有的双引号要替换成单引号,因为out.print("")这里有一个双引号,容易冲突。

  • 现在写完这个功能之后,你会有一种感觉,感觉开发很繁琐,只使用servlet写代码太繁琐了

  1. 我们需要连接数据库,从数据库中获取到数据,显示到前端浏览器当中。
  2. 注意我们这里上面的 index.html 中是通过超链接的方式,跳转到该 部门列表页面的。超链接是 doGet 请求。
package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/**
 * 部门列表
 */
public class DeptListServlet extends HttpServlet {

    /*
    说明:这里使用了doGet,和 goPost 的原因是,我们前端的 DeptSaveServlet 的新增部门,
    的请求是doPost,从 doPost 请求  "转发"出来的同样是 doPost请求的,而 重定向就是doGet请求了,无论是doPost,doGet请求都是
    所以这里为了,处理接受到 DeptSaveServlet 的新增部门的 "转发"请求,写了一个doPost 请求处理
     */


    // 优化,将转发,替换成了 重定向的机制,(重定向的机制)是自发到浏览器前端的地址栏上的,后自发的执行
    // 地址栏上是 doGet 请求的,就不需要 doPost 请求了。
   /* @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response); // 调用本身这里的doGet()请求

    }*/

    /*
        因为我们前端使用的是 <a>超链接,是goGet请求所以,
        前后端的请求保持一致。
         */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 设置前端浏览器显示的格式类型,以及编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        // 获取到该webapp的项目根路径:也就是在Tomcat 当中设置的访问的项目路径
        // 注意的是: getContextPath()获取返回的路径是带有 "/项目名"的,所以不要多写了 / 
        String contextPath = request.getContextPath();


        int i = 0;

        writer.println("     <!DOCTYPE html>");
        writer.println("<html lang='en'>");

        writer.println("<head>");
        writer.println("    <meta charset='UTF-8'>");
        writer.println("   <title>部门列表页面</title>");
        writer.println("</head>");

        writer.println("    <script type = 'text/javascript' >");
        writer.println("            function del(dno) {");
        // 弹出确认框,用户点击确定,返回true,点击取消返回false
        writer.println("        var ok = window.confirm('亲,删了不可恢复哦!');");
        writer.println("        if (ok) {");
        // 发送请求进行删除数据的操作
        // 在js代码当中如何发送请求给服务
        // document.location.href='请求路径
        // document.location = '请求路径'")
        // window.location.href = '请求路径
        // window.location = '请求路径'
        // 注意是根据所传的部门编号删除数据的
        writer.println("             document.location.href = '" + contextPath + "/dept/delete?deptno=' + dno");
        writer.println("          }");
        writer.println("       }");
        writer.println("</script >");

        writer.println("<body>");
        writer.println("    <h1 align='center'>部门列表</h1>");
        writer.println("   <table border='1px' align='center' width='50%'>");
        writer.println("      <tr>");
        writer.println("          <th>序号</th>");
        writer.println("         <th>部门编号</th>");
        writer.println("         <th>部门名称</th>");
        writer.println("     </tr>");

        try {
            // 连接数据库,查询所有部门:
            // 1. 注册驱动,获取连接
            connection = DBUtil.getConnection();
            // 2. 获取操作数据库对象,预编译sql语句
            String sql = "select depton as det,dname,loc from dept"; // 在mysql中测试一下是否正确
            preparedStatement = connection.prepareStatement(sql);

            // 3. 执行sql语句
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String det = resultSet.getString("det");  // 有别名要使用别名
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");

                writer.print("			<tr>");
                writer.print("				<td>" + (++i) + "</td>");
                writer.print("				<td>" + det + "</td>");
                writer.print("				<td>" + dname + "</td>");
                writer.print("				<td>");
                writer.print("					<a href='javascript:void(0)' onclick= 'del(" + det + ")'>删除</a>");
                // 将部门编号传过去,用户数据库查询修改
                writer.print("					<a href='"+contextPath+"/dept/edit?deptno="+det+"'>修改</a>");
                //注意这里的是前端的资源,需要加项目名,但是这里的项目名我们通过 getContestPath()方法动态获取
                // 并且将部门名传过去,再从数据库当中查找出来对应的部门的详细信息:注意: ?(间隔) Http传输协议
                writer.print("					<a href='" + contextPath + "/dept/detail?deptno=" + det + "'>详情</a>");
                writer.print("				</td>");
                writer.print("			</tr>");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {

            // 5. 关闭资源
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        writer.println("</table>");
        writer.println("<hr>");
        // 前端的资源路径访问需要加项目名
        writer.println("<a href='" + contextPath + "/add.html'>新增部门</a>");
        writer.println("</body>");
        writer.println("</html>");

    }
}

2.6 功能三:查看部门详情 DeptDetailServlet

建议:从前端往后端一步一步实现。首先要考虑的是,用户点击的是什么?用户点击的东西在哪里?

一定要先找到用户点的“详情”在哪里。这里我们使用超链接的形式处理

<a href='写一个路径'>详情</a>

详情 是需要连接数据库的,所以这个超链接点击之后也是需要执行一段java代码的。所以要将这个超链接的路径修改一下。

注意:修改路径之后,这个路径是需要加项目名的。"/servlet09/dept/detail"

技巧:

out.print("<a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>");

重点:向服务器提交数据的格式:uri?name=value&name=value&name=value&name=value 。这里的问号,必须是英文的问号。不能中文的问号。

思路:

中文思路(思路来源于:你要做什么?目标:查看部门详细信息。)
第一步:获取部门编号
第二步:根据部门编号查询数据库,获取该部门编号对应的部门信息。
第三步:将部门信息响应到浏览器上。(显示一个详情。)

package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/**
 * 部门详情
 */
public class DeptDetailServlet extends HttpServlet {

    // 前端超连接是 doGet()请求
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 设置前端浏览器格式类型和字符集编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        //中文思路(思路来源于:你要做什么?目标:查看部门详细信息。)
        // 第一步:获取部门编号
        // 第二步:根据部门编号查询数据库,获取该部门编号对应的部门信息。
        // 第三步:将部门信息响应到浏览器上。(显示一个详情。)


        // 1.
        // http://127.0.0.1:8080/servlet09/dept/detail?deptno=40
        String deptno = request.getParameter("deptno");  // 注意是我们前端提交的数据,建议复制name

        try {
            // 2. 连接数据库,根据部门编号查询数据库
            // 1.注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 预编译SQL语句,sql要测试
            String sql = "select dname,loc from dept where depton = ?";  // ? 占位符
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正执行sql语句
            preparedStatement.setString(1, deptno);
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");


                // 注意将 “双引号转换为单引号,因为在Java当中不可以嵌套多个双引号,除非是字符串的拼接
                // 所以使用 '单引号
                writer.println("    <body>");
                writer.println("  <h1>部门详情</h1>");
                writer.println("              部门编号: " + deptno + " <br>");
                writer.println("          部门名称: " + dname + "<br>");
                writer.println("     部门位置: " + loc + "<br>");
                writer.println("  <input type='button' value='后退' onclick='window.history.back()'  />");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 5. 释放资源
            DBUtil.close(connection, preparedStatement, resultSet);
        }


        writer.println("</body>");
        writer.println("</html>");
    }
}

2.7 功能四:删除部门 DeptDelServlet

怎么开始?从哪里开始?从前端页面开始,用户点击删除按钮的时候,应该提示用户是否删除。因为删除这个动作是比较危险的。任何系统在进行删除操作之前,是必须要提示用户的,因为这个删除的动作有可能是用户误操作。(在前端页面上写JS代码,来提示用户是否删除。)

<a href="javascript:void(0)" onclick="del(30)" >删除</a>
<script type="text/javascript">
	function del(dno){
		if(window.confirm("亲,删了不可恢复哦!")){
			document.location.href = "/oa/dept/delete?deptno=" + dno;
		}
	}
</script>

以上的前端程序要写到后端的java代码当中:DeptListServlet类的doGet方法当中,使用out.print()方法,将以上的前端代码输出到浏览器上。

删除成功或者失败的时候的一个处理(这里我们一开始使用的选择的是转发,后面优化使用的是重定向机制。)

删除成功:我们跳转到部门列表当中。DeptListServlet

删除失败:我们跳转到一个失败的页面当中。这里我们将该失败的页面名为: error.html 页面如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>error</title>
</head>
<body>
<h1> 操作失败: </h1>
<a href='/servlet09/dept/list/' onclick="window.history.back()">返回</a>
</body>
</html>

具体的 Servlet 编写如下

package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;


/**
 * 删除部门
 */
public class DeptDelServlet extends HttpServlet {


    /*
    注意前端是超链接的方式:是get请求
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        request.setCharacterEncoding("UTF-8");

        // 思路:
        /*
        根据部门编号删除信息,
        删除成功,跳转回原来的部门列表页面
        删除失败,跳转删除失败的页面
         */

        Connection connection = null;
        PreparedStatement preparedStatement = null;

        // 记录删除数据库的行数
        int count = 0;

        // 获取到前端提交的数据
        String deptno = request.getParameter("deptno");


        // 连接数据库进行删除操作

        try {
            // 1.注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 开启事务(取消自动提交机制),实现可回滚
            connection.setAutoCommit(false);

            // 2. 预编译sql语句,sql测试
            String sql = "delete from dept where depton = ?"; // ? 占位符
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正的执行sql语句
            preparedStatement.setString(1, deptno);
            // 返回影响数据库的行数
            count = preparedStatement.executeUpdate();
            connection.commit();  // 手动提交数据
        } catch (SQLException e) {
            // 遇到异常回滚
            if (connection != null) {
                try {
                    // 事务的回滚
                    connection.rollback();
                } catch (SQLException ex) {
                    throw new RuntimeException(ex);
                }
            }
            throw new RuntimeException(e);
        } finally {
            // 4. 释放资源
            // 因为这里是删除数据,没有查询操作,所以 没有 ResultSet 可以传null
            DBUtil.close(connection, preparedStatement, null);
        }

        if (count == 1) {
            // 删除成功
            // 仍然跳转到部门列表页面
            // 部门列表页面的显示需要执行另外一个Servlet,怎么办,可以使用跳转,不过这里最后是使用重定向
            // 注意:转发是在服务器间的,所以不要加“项目名” 而是 / + web.xml 映射的路径即可
            //request.getRequestDispatcher("/dept/list/").forward(request,response);

            // 优化:使用重定向机制 注意: 重定向是自发到前端的地址栏上的,前端所以需要指明项目名
            // 注意: request.getContextPath() 返回的根路径是,包含了 "/" 的
            response.sendRedirect(request.getContextPath() + "/dept/list/");
        } else {
            // 删除失败
            // web当中的 html资源,这里的 "/" 表示 web 目录
            //request.getRequestDispatcher("/error.html/").forward(request, response);

            // 优化,使用重定向
            response.sendRedirect(request.getContextPath() + "/error.html/");
        }


    }
}

2.8 功能五:新增部门 DeptSaveServlet

思路:

获取到前端 form 表单提交的数据,这里我们 form 表单 中的 metod = post 设置为了 doPost 请求。

再连接数据库,添加一条记录。

添加成功:我们跳转到部门列表当中。DeptListServlet

添加失败:我们跳转到一个失败的页面当中。这里我们将该失败的页面名为: error.html

注意点:

最后保存成功之后,跳转到 /dept/list 的时候,如果你使用的是 转发 机制的话,这里因为你是从 doPost 请求 转发过去的(转发是一次请求,之前是post,之后还是post,因为它是一次请求。),所以对应接收该 doPost 请求的也要是 doPost 方法处理该请求,不然会报 405 错误。

而同时:这时候接收该 转发 的 /dept/list Servlet当中只有一个doGet方法。就会报 405 错误。

怎么解决?两种方案

  • 第一种:在/dept/list Servlet中添加doPost方法,然后在doPost方法中调用doGet。
  • 第二种:使用重定向的方式,进行跳转,重定向的机制是改变浏览器的请求路径URL,让浏览器重新发送跳转之后的 URL 地址,该方式是从浏览器地址栏上跳转的,所以是 doGet 请求,就不要编写 doPost 请求了。

具体代码编写如下:

package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;


/**
 * 增加部门数据
 */
public class DeptSaveServlet extends HttpServlet {
    // 前端是注册信息,是post 请求
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        /*
        思路:
         获取到前端的提交的数据,注意 编码设置post 请求
         连接数据库: 进行添加数据
         添加成功: 返回部门列表页面
         添加失败: 返回失败的页面
         */

        request.setCharacterEncoding("UTF-8");

        // 获取到前端的数据,建议 name 使用复制
        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");

        // 连接数据库,添加数据
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 影响数据库的行数
        int count = 0;

        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取操作数据库对象,预编译sql语句,Sql测试
            String sql = "insert into dept(depton,dname,loc) values(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符, 真正执行sql语句,
            // 注意: 占位符的填充是从 1 开始的,基本上数据库相关的起始下标索引都是从 1下标开始的
            preparedStatement.setString(1, deptno);
            preparedStatement.setString(2, dname);
            preparedStatement.setString(3, loc);

            // 返回影响数据库的行数
            count = preparedStatement.executeUpdate();

            // 5.释放资源
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }

        // 保存成功,返回部门列表页面
        if (count == 1) {
            // 这里应该使用,重定向
            // 这里用的转发,是服务器内部的,不要加项目名
            //request.getRequestDispatcher("/dept/list/").forward(request, response);

            // 重定向
            response.sendRedirect(request.getContextPath() + "/dept/list/");
        } else {
            // 保存失败
            // web当中的 html资源,这里的 "/" 表示 web 目录
            //request.getRequestDispatcher("/error.html").forward(request, response);

            response.sendRedirect(request.getContextPath() + "/error.html");
        }


    }
}

2.9 功能六:跳转到修改部门的页面 DepEditServlet

思路:
获取到提交的过来的 部门编号
根据部门编号修改信息,注意:部门编号是唯一的不要被修改了
连接数据库,查询到相关信息显示到浏览器页面当中,方便用户修改

具体的代码编写如下

package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/**
 * 跳转到修改部门的页面
 */
public class DepEditServlet extends HttpServlet {
    // 超链接是 doGet()请求

    // http://127.0.0.1:8080/servlet09/dept/edit?deptno=10
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();

        writer.println("     <!DOCTYPE html>");
        writer.println("<html lang='en'>");

        writer.println("<head>");
        writer.println("    <meta charset='UTF-8'>");
        writer.println("   <title>部门列表页面</title>");
        writer.println("</head>");
        writer.println("<body>");
        writer.println("    <h1>修改部门</h1>");


        writer.println("   <form action='"+request.getContextPath()+"/dept/modify' method='post'>");



        /*
        思路:
        获取到提交的过来的 部门编号
        根据部门编号修改信息,注意:部门编号是唯一的不要被修改了
        连接数据库,查询到相关信息显示到浏览器页面当中,方便用户修改
         */

        String deptno = request.getParameter("deptno");

        // 连接数据库
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取到操作数据库对象,预编译SQL语句,sql测试
            String sql = "select dname,loc from dept where depton = ?";

            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正执行sql语句
            preparedStatement.setString(1, deptno);
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String dname = resultSet.getString("dname");  // 查询使用的别名,要用别名
                String loc = resultSet.getString("loc");

                // <!-- readonly 表示只读,不可修改的作用
                writer.println("      部门编号: <input type='text' name='deptno' value='" + deptno + "' readonly /><br>");
                writer.println("     部门名称: <input type='text' name='dname' value=" + dname + " /><br>");
                writer.println("    部门位置: <input type='text' name='loc' value=" + loc + " /><br>");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 5.释放资源,最后使用的优先关闭(因为如果是关闭优先使用的话,再最后面使用的可能需要前面的资源,才能执行)
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        writer.println(" <input type='submit' value='修改' />");
        writer.println(" </form>");
        writer.println("</body>");
        writer.println("</html>");


    }
}

2.10 功能七:修改部门 DeptSaveServlet

思路:

获取到前端的提交的数据,注意 编码设置post 请求
连接数据库: 进行添加数据
添加成功: 返回部门列表页面
添加失败: 返回失败的页面

具体的代码编写如下:

package com.RainbowSea.servlet;

import com.RainbowSea.DBUtil.DBUtil;
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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;


/**
 * 增加部门数据
 */
public class DeptSaveServlet extends HttpServlet {
    // 前端是注册信息,是post 请求
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        /*
        思路:
         获取到前端的提交的数据,注意 编码设置post 请求
         连接数据库: 进行添加数据
         添加成功: 返回部门列表页面
         添加失败: 返回失败的页面
         */

        request.setCharacterEncoding("UTF-8");

        // 获取到前端的数据,建议 name 使用复制
        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");

        // 连接数据库,添加数据
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 影响数据库的行数
        int count = 0;

        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取操作数据库对象,预编译sql语句,Sql测试
            String sql = "insert into dept(depton,dname,loc) values(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符, 真正执行sql语句,
            // 注意: 占位符的填充是从 1 开始的,基本上数据库相关的起始下标索引都是从 1下标开始的
            preparedStatement.setString(1, deptno);
            preparedStatement.setString(2, dname);
            preparedStatement.setString(3, loc);

            // 返回影响数据库的行数
            count = preparedStatement.executeUpdate();

            // 5.释放资源
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }

        // 保存成功,返回部门列表页面
        if (count == 1) {
            // 这里应该使用,重定向
            // 这里用的转发,是服务器内部的,不要加项目名
            //request.getRequestDispatcher("/dept/list/").forward(request, response);

            // 重定向
            response.sendRedirect(request.getContextPath() + "/dept/list/");
        } else {
            // 保存失败
            // web当中的 html资源,这里的 "/" 表示 web 目录
            //request.getRequestDispatcher("/error.html").forward(request, response);

            response.sendRedirect(request.getContextPath() + "/error.html");
        }


    }
}

3. 最后的 web.xml 配置信息

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">


    <!--     查看部门列表-->
    <servlet>
        <!--        注意: 两个name值要保持一致-->
        <servlet-name>list</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DeptListServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <!--        注意是: / 开始-->
        <url-pattern>/dept/list/</url-pattern>
    </servlet-mapping>


    <!--    部门详情-->
    <servlet>
        <servlet-name>detail</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DeptDetailServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>detail</servlet-name>
        <url-pattern>/dept/detail</url-pattern>
    </servlet-mapping>


    <!--    删除部门-->
    <servlet>
        <servlet-name>delete</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DeptDelServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>delete</servlet-name>
        <!--        / 开始-->
        <url-pattern>/dept/delete</url-pattern>
    </servlet-mapping>

    <!--    新增部门-->
    <servlet>
        <servlet-name>save</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DeptSaveServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>save</servlet-name>
        <url-pattern>/dept/save</url-pattern>
    </servlet-mapping>

    <!--    跳转到修改部门-->
    <servlet>
        <!--        两个 name 保持一致-->
        <servlet-name>edit</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DepEditServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>edit</servlet-name>
        <!--        "/" 开始-->
        <url-pattern>/dept/edit</url-pattern>
    </servlet-mapping>


    <!--    修改部门信息-->
    <servlet>
        <servlet-name>modify</servlet-name>
        <servlet-class>com.RainbowSea.servlet.DeptModifyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>modify</servlet-name>
        <url-pattern>/dept/modify</url-pattern>
    </servlet-mapping>

</web-app>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/834950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么马斯克和奥特曼都想重振加密货币?

1、前言 加密货币已经死了吗&#xff1f;这个问题的答案取决于谁来回答。一个加密爱好者会给你一百个不同的理由来解释为什么加密货币没有死。特斯拉CEO埃隆马斯克和OpenAI CEO 山姆奥特曼都对加密货币及其在塑造未来世界中的潜在作用有着浓厚的兴趣。 在过去很长一段时间里&…

Ubuntu18.04 安装opencv 4.8.0教程

1. 安装准备 安装前需要下载一些必须的依赖项。 不同版本opencv依赖会有不同&#xff0c;具体见官网opencv安装 sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-…

视频汇聚平台EasyCVR视频广场侧边栏支持拖拽

为了提升用户体验以及让平台的操作更加符合用户使用习惯&#xff0c;我们在EasyCVR v3.3版本中&#xff0c;支持面包屑侧边栏的广场视频、分组列表、收藏这三个模块拖拽排序&#xff0c;并且该操作在视频广场、视频调阅、电子地图、录像回放等页面均能支持。 TSINGSEE青犀视频…

InfluxDB2如何求增量数据

需求 项目中需要接入电表设备&#xff0c;求用电量。 按天和设备统计用电量 按天统计用电量 统计总用电量 存在的问题 difference 函数可以求增量&#xff0c;但是以上计算均存在一个问题&#xff0c;比如xx设备有8.1号和8.2号的数据&#xff0c;我统计每天的用电量&#xf…

单篇笔记曝光248万+,素颜、寸头…小红书女性种草新趋势分析!

最近&#xff0c;小红书上刮起一阵素颜、寸头&#xff0c;拒绝美丽绑架的风潮&#xff0c;他们称之为“脱美役”&#xff0c;即脱离美丽枷锁&#xff0c;做自己&#xff0c;接纳原本的自己。这是女性觉醒的又一阵风&#xff0c;品牌要如何跟上这波种草新趋势呢&#xff1f; 单篇…

Swish for MacBook触控板窗口管理软件

Swish可以帮助您使用触控板&#xff0c;轻松对mac窗口进行管理&#xff0c;只需提前设置好预定的设置即可&#xff0c;非常方便&#xff01; 几乎所有的窗口管理工具用的都是快捷键或者鼠标拖移的方式来管理窗口&#xff0c;Swish 却另辟蹊径&#xff0c;为窗口管理引入了手势…

c语言——计算两个数值的最小公倍数

//计算两个数值的最小公倍数 //列如&#xff1a;4和6的最小公倍数是12. #include<stdio.h> int main() {int a,b,temp,i;printf("Input a&b:");scanf("%d,%d",&a,&b);if(a<b){tempa;ab;btemp;}for(ia;i>0;i)if(i%a0&&i%b0…

物联网|按键实验---学习I/O的输入及中断的编程|函数说明的格式|如何使用CMSIS的延时|读取通过外部中断实现按键捕获代码的实现及分析-学习笔记(14)

文章目录 通过外部中断实现按键捕获代码的实现及分析Tip1:函数说明的格式Tip2:如何使用CMSIS的延时GetTick函数原型stm32f407_intr_handle.c解析中断处理函数&#xff1a;void EXTI4_IRQHandler 调试流程软件模拟调试 两种代码的比较课后作业: 通过外部中断实现按键捕获代码的实…

【雕爷学编程】MicroPython动手做(39)——机器视觉之图像基础3

MixPY——让爱(AI)触手可及 MixPY布局 主控芯片&#xff1a;K210&#xff08;64位双核带硬件FPU和卷积加速器的 RISC-V CPU&#xff09; 显示屏&#xff1a;LCD_2.8寸 320*240分辨率&#xff0c;支持电阻触摸 摄像头&#xff1a;OV2640&#xff0c;200W像素 扬声器&#…

使用 PowerShell 来揪出端口罪魁祸首

问题&#xff1a; 在调试 Node.js 程序时经常出现端口被占用的情况是很常见的。为了找到具体是哪个进程占用了 3000 端口&#xff0c;我们可以借助一些工具来查找。下面将展示一种方法&#xff1a;使用 PowerShell 。 方法&#xff1a;使用 PowerShell 打开 PowerShell 终端…

TypeScript 类型断言

TypeScript 类型断言 简单来说类型断言就是 使用as关键词 强行指定获取到的结果类型 应用场景 // 类型断言: 强行指定获取到的结果类型// 应用场景// 页面上有一个 id 为 link 的 a 标签// 我们知道它是 a 标签// 但是 TS 不知道 // document.getElementById 的返回值是 HTMLE…

【JAVA BASE API】介绍Java基础API语法,包括JAVA8之后的时间日期等

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; Java | 从跨平台到跨行业 开发工具&#xff1a;IntelliJ IDEA JAVA BASE API Object 类clone 对象克隆toString() 转换字符串equals(Object obj) 地址比较 Objects 类Objects.equals(Object obj1, Object obj2) 非空比较…

react ant add/change created_at

1.引入ant的 Table import { Table, Space, Button, message } from antd; 2.获得接口的数据的时候增加上创建时间 const response await axios.get(${Config.BASE_URL}/api/v1/calculation_plans?token${getToken()});if (response.data.message ok) {const data respon…

Matlab的信号频谱分析——FFT变换

Matlab的信号频谱分析——FFT变换 Matlab的信号频谱分析 FFT是离散傅立叶变换的快速算法&#xff0c;可以将一个时域信号变换到频域。 有些信号在时域上是很难看出什么特征的。但是如果变换到频域之后&#xff0c;就很容易看出特征了。 这就是很多信号分析采用FFT变换的原因…

灵遨底盘驱动安装

文章目录 ROS Packages灵遨科技ROS包的安装安装ROS依赖包导入lingao_ros包到工作空间工作空间的环境source &#xff08;可选&#xff09; 通讯接口设置ROS Package 基本用法使用测试 ROS Packages lingao_base: 灵遨底盘驱动软件包&#xff0c;用于ROS的底盘通讯收发 lingao_…

C++初阶引用

目录 引用引用的特性使用输出型参数作返回值小总结引用的权限引用和指针 引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如周树人&#xff0c;在外…

毕马威加入IBM量子网络,已搭建完成通信行业量子电路!

​ 毕马威全球量子中心主管Bent Dalager&#xff08;图片来源&#xff1a;网络&#xff09; 随着全球企业技术的持续转型&#xff0c;量子计算在开发创新解决方案上越来越重要。为此&#xff0c;毕马威(KPMG)公司加入了IBM量子网络&#xff0c;旨在利用量子计算解决当今最复杂的…

为什么list.sort()比Stream().sorted()更快?

真的更好吗&#xff1f; 先简单写个demo List<Integer> userList new ArrayList<>();Random rand new Random();for (int i 0; i < 10000 ; i) {userList.add(rand.nextInt(1000));}List<Integer> userList2 new ArrayList<>();userList2.add…

Python爬虫遇到重定向问题解决办法汇总

在进行Python爬虫任务时&#xff0c;遇到重定向问题是常见的问题之一。重定向是指在发送请求时&#xff0c;服务器会返回一个新的URL&#xff0c;将请求重新定向到该URL。为了帮助您解决这个问题&#xff0c;本文将提供一些实用的解决办法&#xff0c;并给出相关的代码示例&…

java linq多字段排序时间比较

public static void main(String[] args) {//100万条数据List<CrmInvestSaleUserCount> waitAssignUserList new ArrayList<>();for (int i 0; i < 1000000; i) {waitAssignUserList.add(new CrmInvestSaleUserCount().setSales_username("test" i…