使用纯Servlet做一个单表的CRUD操作
开发前的准备
第一步:准备一张部门表
sql脚本
- DOS命令窗口默认编码是GBK , 导入中文会出现乱码 , 需要在执行SQL语句前执行 set names utf-8
- mysql -uroot -p123456 --default-character-set=utf-8
- 将SQL脚本保存为 UTF-8的形式
drop table if exists dept;
create table dept(
deptno int primary key,
dname varchar(255),
loc varchar(255)
);
insert into dept(deptno, dname, loc) values(10, 'XiaoShouBu', 'BEIJING');
insert into dept(deptno, dname, loc) values(20, 'YanFaBu', 'SHANGHAI');
insert into dept(deptno, dname, loc) values(30, 'JiShuBu', 'GUANGZHOU');
insert into dept(deptno, dname, loc) values(40, 'MeiTiBu', 'SHENZHEN');
commit;
select * from dept;
第二步:准备一套HTML页面(项目原型) , 将HTML页面中的链接都能够跑通(实现页面的相互流转)
- 欢迎页面:index.html
- 列表页面:list.html(以列表页面为核心,展开其他操作)
- 新增页面:add.html
- 修改页面:edit.html
- 详情页面:detail.html
第三步:分析系统包括哪些功能 , 只要这个操作连接了数据库,就表示一个独立的功能
- 查看部门列表
- 新增部门
- 删除部门
- 查看部门详细信息
- 跳转到修改页面(动态的从数据库中获取信息并显示)
- 修改部门
第四步:在IDEA当中搭建开发环境
- 创建一个webapp(给这个webapp添加servlet-api.jar和jsp-api.jar到classpath当中)
- 向webapp中添加连接数据库的jar包(mysql驱动)
- 必须在WEB-INF目录下新建lib目录,然后将mysql的驱动jar包拷贝到这个lib目录下。这个目录名必须叫做lib,全部小写的
- 将所有HTML页面拷贝到web目录下。
准备JDBC的工具类
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bjpowernode
user=root
password=root
public class DBUtil {
// 静态变量:在类加载时执行。并且是有顺序的。自上而下的顺序。
// 属性资源文件绑定
private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc");
// 根据属性配置文件key获取value
private static String driver = bundle.getString("driver");
private static String url = bundle.getString("url");
private static String user = bundle.getString("user");
private static String password = bundle.getString("password");
static {
// 注册驱动(注册驱动只需要注册一次,放在静态代码块当中。DBUtil类加载的时候执行。)
try {
// "com.mysql.jdbc.Driver" 是连接数据库的驱动,不能写死。因为以后可能还会连接Oracle数据库。
// 如果连接oracle数据库的时候,还需要修改java代码,显然违背了OCP开闭原则。
// OCP开闭原则:对扩展开放,对修改关闭。(什么是符合OCP呢?在进行功能扩展的时候,不需要修改java源代码。)
//Class.forName("com.mysql.jdbc.Driver");
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return conn 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
// 获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/**
* 释放资源
* @param conn 连接对象
* @param ps 数据库操作对象
* @param rs 结果集对象
*/
public static void close(Connection conn, Statement ps, ResultSet rs){
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
在web应用中完成资源的跳转
在一个web应用中通过两种方式,可以完成资源的跳转
- 第一种方式:转发
- 第二种方式:重定向
跳转的下一个资源必须是一个Servlet吗?
- 不一定,跳转的资源只要是服务器内部合法的资源即可。包括:Servlet、JSP、HTML…
开发准备
一个JavaBean的规范
- 有无参数的构造方法 , 属性私有化 , 实现java.io.Serializable接口
- 对外提供setter和getter方法 , 重写toString() , 重写hashCode + equals
public class User implements Serializable {
private String id;
private String name;
public User() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id) && Objects.equals(name, user.name);
}
// 对外提供setter和getter方法 , 重写toString() , 重写hashCode + equals
}
AServlet
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建一个用户对象
User user = new User();
user.setId("111111");
user.setName("杰克");
// 将用户对象存储到请求域当中
request.setAttribute("userObj", user);
// 转发(服务器自己完成内部资源的跳转,不需要添加项目名)
// 浏览器一共发送了一次请求: http://localhost:8080/servlet10/a
// request.getRequestDispatcher("/b").forward(request, response);
// 重定向(浏览器需要重新发起请求 , 需要添加项目名)
// response对象将这个路径:"/servlet10/b"响应给浏览器了。浏览器又自发的向服务器发送了一次全新的请求
// 所以浏览器一共发送了两次请求:最终浏览器地址栏上显示的地址当然是最后那一次请求的地址。所以重定向会导致浏览器地址栏上的地址发生改变。
// 第一次请求:http://localhost:8080/servlet10/a
// 第二次请求:http://localhost:8080/servlet10/b
response.sendRedirect(request.getContextPath() + "/b");
}
}
BServlet
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 从请求域当中取出存储的数据
Object userObj = request.getAttribute("userObj");
// 输出到浏览器
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("请求域当中的用户对象:" + userObj);
}
}
转发(发送了一次请求)
在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终请求结束之后,浏览器地址栏上的地址还是这个
- AServlet转发到BServlet,再转发到CServlet,再转发到DServlet,不管转发了多少次,都在同一个request当中。这是因为调用forward方法的时候,会将当前的request和response对象传递给下一个Servlet。
// 获取请求转发器对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list");
// 调用请求转发器对象的forward方法完成转发
dispatcher.forward(request, response);
// 合并一行代码
request.getRequestDispatcher("/dept/list").forward(request, response);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dq787atl-1673499606725)(D:\笔记\老杜javaweb文档\转发.png)]
重定向(发送了多次请求)
在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终在浏览器地址栏上显示的地址是:http://localhost:8080/servlet10/b
// 以下这一行代码会将请求路径“/oa/dept/list”发送给浏览器 , 然后浏览器会自发的向服务器发送一次全新的请求:/oa/dept/list
response.sendRedirect("/oa/dept/list");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nzzSOxie-1673499606727)(D:\笔记\老杜javaweb文档\重定向.png)]
两种跳转方式的区别
转发的请求路径不需要添加项目名 :因为转发是由WEB服务器内部来控制的。
- A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。
- 我没钱了,找张三借钱,其实张三没有钱,但是张三够义气,张三自己找李四借了钱,然后张三把这个钱给了我,我不知道这个钱是李四的,杜老师只求了一个人。我以为这个钱就是张三的。
重定向的请求路径需要添加项目名:因为浏览器会根据服务器响应的路径重新发起一个请求(浏览器是在地址栏上发起的get请求)
- 我没钱了,找张三借钱,张三没有钱,张三有一个好哥们,叫李四,李四是个富二代,于是张三将李四的家庭住址告诉了杜老师,我按照这个地址去找到李四,然后从李四那里借了钱。在这个过程中,我求了两个人。并且我知道最终这个钱是李四借给俺的。
应用场景
什么时候使用转发,什么时候使用重定向?
- 如果在上一个Servlet当中向request域当中绑定了数据,希望从下一个Servlet当中把request域里面的数据取出来,使用转发机制。
- 剩下所有的请求均使用重定向。(重定向使用较多)
转发存在浏览器的刷新问题
Student.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生</title>
</head>
<body>
<form action="/servlet10/save" method="get">
学生编号<input type="text" name="no"><br>
学生姓名<input type="text" name="name"><br>
<input type="submit" value="保存">
</form>
</body>
</html>
StudentSaveServlet
- 当使用转发跳转到 success.html 页面并刷新页面时 , 数据库中也会插入数据 , 因为地址栏上的请求还是之前的那个请求没变
- 当使用重定向跳转到 success.html 页面并刷新页面时 , 数据库中不会插入数据 , 因为地址栏上的请求变成了最后一次的请求
public class StudentSaveServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 保存学生信息到数据库
request.setCharacterEncoding("UTF-8");
String no = request.getParameter("no");
String name = request.getParameter("name");
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "insert into t_student(no,name) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, no);
ps.setString(2, name);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}
// 保存成功之后跳转到成功页面
if (count == 1) {
// 转发
//request.getRequestDispatcher("/success.html").forward(request, response);
// 重定向
response.sendRedirect(request.getContextPath() + "/success.html");
}else{
}
}
}
实现系统功能
我们应该怎么去实现一个功能呢?
- 你可以从后端往前端一步一步写。也可以从前端一步一步往后端写。都可以。但是千万要记住不要想起来什么写什么。
- 你写代码的过程最好是程序的执行过程。也就是说:程序执行到哪里,你就写哪里。这样一个顺序流下来之后,基本上不会出现什么错误、意外。
假设从前端开始,那么一定是从用户点击按钮那里开始的。考虑用户点击的是什么?用户点击的东西在哪里?
实现查看部门列表功能
第一:先修改前端页面的超链接,因为用户先点击的就是这个超链接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LcgaiN9n-1673499606727)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1673499373292.png)]
欢迎页面:index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎使用OA系统</title>
</head>
<body>
<!--前端超链接发送请求的时候,请求路径以“/”开始,并且要带着项目名-->
<a href="/oa/dept/list">查看部门列表</a>
</body>
</html>
第二:编写web.xml文件
<servlet>
<servlet-name>list</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptListServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>list</servlet-name>
<!--web.xml文件中的这个路径也是以“/”开始的,但是不需要加项目名-->
<url-pattern>/dept/list</url-pattern>
</servlet-mapping>
第三:编写DeptListServlet类继承HttpServlet类。然后重写doGet方法。
- 在DeptListServlet类的doGet方法中连接数据库,查询所有的部门,动态的展示部门列表页面.
- 分析list.html页面中哪部分是固定死的,哪部分是需要动态展示的。
- list.html页面中的内容所有的双引号要替换成单引号,因为out.print(“”)这里有一个双引号,容易冲突。 (可以利用文本工具查找替换)
- 多行编辑 , 按住Alt键 , 鼠标往下托就行
DeptListServlet
- 现在写完这个功能之后,你会有一种感觉,感觉开发很繁琐,只使用servlet写代码太繁琐了。
public class DeptListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取应用的根路径
String contextPath = request.getContextPath();
// 设置响应的内容类型以及字符集。防止中文乱码问题。
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 使用多行编辑功能 , 按住Alt键 , 鼠标往下托就行
out.print("<!DOCTYPE html>");
out.print("<html>");
out.print(" <head>");
out.print(" <meta charset='utf-8'>");
out.print(" <title>部门列表页面</title>");
out.print("<script type='text/javascript'>");
out.print(" function del(dno){");
out.print(" if(window.confirm('亲,删了不可恢复哦!')){");
out.print(" document.location.href = '"+contextPath+"/dept/delete?deptno=' + dno");
out.print(" }");
out.print(" }");
out.print("</script>");
out.print(" </head>");
out.print(" <body>");
out.print(" <h1 align='center'>部门列表</h1>");
out.print(" <hr >");
out.print(" <table border='1px' align='center' width='50%'>");
out.print(" <tr>");
out.print(" <th>序号</th>");
out.print(" <th>部门编号</th>");
out.print(" <th>部门名称</th>");
out.print(" <th>操作</th>");
out.print(" </tr>");
/*上面一部分是死的*/
// 动态的连接数据库,查询所有的部门
//...................
/*下面一部分是死的*/
out.print(" </table>");
out.print(" <hr >");
out.print(" <a href='"+contextPath+"/add.html'>新增部门</a>");
out.print(" </body>");
out.print("</html>");
}
}
动态的连接数据库,查询所有的部门的代码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 获取连接
conn = DBUtil.getConnection();
// 获取预编译的数据库操作对象
String sql = "select deptno as a,dname,loc from dept";
ps = conn.prepareStatement(sql);
// 执行SQL语句
rs = ps.executeQuery();
// 处理结果集
// i 表示序号
int i = 0;
while(rs.next()){
String deptno = rs.getString("a");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
out.print(" <tr>");
out.print(" <td>"+(++i)+"</td>");
out.print(" <td>"+deptno+"</td>");
out.print(" <td>"+dname+"</td>");
out.print(" <td>");
out.print(" <a href='javascript:void(0)' οnclick='del("+deptno+")'>删除</a>");
out.print(" <a href='"+contextPath+"/dept/edit?deptno="+deptno+"'>修改</a>");
out.print(" <a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>");
out.print(" </td>");
out.print(" </tr>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
DBUtil.close(conn, ps, rs);
}
实现查看部门详情功能
先找到用户点的“详情”的按钮在哪里。在后端的java程序 DeptListServlet 动态的响应的内容中
- 用户点击详情按钮的超链接后是需要执行一段java代码连接数据库的。
将详情按钮的超链接路径修改一下
- 这个路径是需要加项目名的。并且需要携带你想要查看的部门编号 , 这样才能连接数据库查询部门信息
- 向服务器提交数据的格式:uri?name=value&name=value&name=value&name=value , 这里的问号,必须是英文的问号。不能中文的问号。
// i 表示序号
int i = 0;
while(rs.next()){
String deptno = rs.getString("a");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
out.print(" <tr>");
out.print(" <td>"+(++i)+"</td>");
out.print(" <td>"+deptno+"</td>");
out.print(" <td>"+dname+"</td>");
out.print(" <td>");
out.print(" <a href='javascript:void(0)' οnclick='del("+deptno+")'>删除</a>");
out.print(" <a href='"+contextPath+"/dept/edit?deptno="+deptno+"'>修改</a>");
out.print(" <a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>");
out.print(" </td>");
out.print(" </tr>");
}
编写一个类:DeptDetailServlet继承HttpServlet,重写doGet方法。
- 在doGet方法当中:连接数据库,根据部门编号查询该部门的信息。动态展示部门详情页。
web.xml文件
<servlet>
<servlet-name>detail</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptDetailServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>detail</servlet-name>
<url-pattern>/dept/detail</url-pattern>
</servlet-mapping>
DeptDetailServlet
- 第一步:获取部门编号
- 第二步:根据部门编号查询数据库,获取该部门编号对应的部门信息。
- 第三步:将部门信息响应到浏览器上。(显示一个详情。)
public class DeptDetailServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<!DOCTYPE html>");
out.print("<html>");
out.print(" <head>");
out.print(" <meta charset='utf-8'>");
out.print(" <title>部门详情</title>");
out.print(" </head>");
out.print(" <body>");
out.print(" <h1>部门详情</h1>");
out.print(" <hr >");
/*上面一部分是死的*/
// 连接数据库,根据部门编号查询该部门的信息。动态展示部门详情页。
//...................
/*下面一部分是死的*/
out.print(" <input type='button' value='后退' οnclick='window.history.back()'/>");
out.print(" </body>");
out.print("</html>");
}
}
连接数据库,根据部门编号查询该部门的信息。动态展示部门详情页的代码。
// 通过请求参数获取部门编号 , /oa/dept/detail?deptno=30
// 虽然是提交的30,但是服务器获取的是"30"这个字符串。Mysql底层自动会把"30"转换成300
String deptno = request.getParameter("fdsafdsas");
// 连接数据库,根据部门编号查询部门信息。
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
String sql = "select dname,loc from dept where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, deptno);
rs = ps.executeQuery();
// 这个结果集一定只有一条记录。
if(rs.next()){
String dname = rs.getString("dname");
String loc = rs.getString("loc");
out.print("部门编号:"+deptno+" <br>");
out.print("部门名称:"+dname+"<br>");
out.print("部门位置:"+loc+"<br>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}
实现删除部门功能
从前端页面开始,用户点击删除按钮的时候,应该提示用户是否删除。因为删除这个动作是比较危险的 , 有可能是用户误操作。
-
我希望设置给超链接设置一个点击事件 , 点击超链接后会执行事件函数 不进行页面的跳转, 在事件函数中发起请求实现删除部门的功能
-
将JS代码写到后端的java程序的DeptListServlet类的doGet方法当中,使用out.print()方法,将以上的前端代码输出到浏览器上。
<!--deptno需要连接数据库获取-->
<!--href设置为javascript:void(0)表示仍然保留超链接的样子 , 但是点此超链接后不进行页面的跳转-->
<a href='javascript:void(0)' onclick='del("+deptno+")'>删除</a>")
<script type="text/javascript">
function del(dno){
// 弹出确认框 , 用户点击确定会返回true , 点击取消会返回false
if(window.confirm("亲,删了不可恢复哦!")){
//document.location = "请求路径"
//document也可以替换成window
document.location.href = "/oa/dept/delete?deptno=" + dno;
}
}
</script>
编写DeptDelServlet继承HttpServlet,重写doGet方法。根据部门编号,删除部门。
web.xml文件
<servlet>
<servlet-name>delete</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptDelServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>delete</servlet-name>
<url-pattern>/dept/delete</url-pattern>
</servlet-mapping>
DeptDelServlet
public class DeptDelServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取部门编号 , 删除部门。
String deptno = request.getParameter("deptno");
// 连接数据库删除数据
Connection conn = null;
PreparedStatement ps = null;
// count判断判断删除成功了还是失败了
int count = 0;
try {
conn = DBUtil.getConnection();
// 开启事务(自动提交机制关闭)
conn.setAutoCommit(false);
String sql = "delete from dept where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, deptno);
// 返回值是:影响了数据库表当中多少条记录。
count = ps.executeUpdate();
// 事务提交
conn.commit();
} catch (SQLException e) {
// 遇到异常要回滚
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}
// 判断删除成功了还是失败了..........
}
}
删除成功或者失败的时候的一个处理 , 因为不需要共享数据 , 所以我们使用重定向机制。
// 无论删除成功还是失败都需要跳转到部门列表页面 , 但是显示部门列表页面需要执行另一个Servlet。
if (count == 1) { //删除成功
response.sendRedirect(request.getContextPath() + "/dept/list");
}else{ // 删除失败
response.sendRedirect(request.getContextPath() + "/error.html");
}
error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>error</title>
</head>
<body>
<h1>操作失败,<a href="javascript:void(0)" onclick="window.history.back()">返回</a></h1>
</body>
</html>
实现新增部门功能
DeptListServlet , 跳转到新增部门的HTML页面
public class DeptListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*上面一部分是死的*/
// 动态的连接数据库,查询所有的部门
//...................
/*下面一部分是死的*/
out.print(" </table>");
out.print(" <hr >");
out.print(" <a href='"+contextPath+"/add.html'>新增部门</a>");
out.print(" </body>");
out.print("</html>");
}
}
add.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>新增部门</title>
</head>
<body>
<h1>新增部门</h1>
<hr >
<form action="/oa/dept/save" method="post">
部门编号<input type="text" name="deptno"/><br>
部门名称<input type="text" name="dname"/><br>
部门位置<input type="text" name="loc"/><br>
<input type="submit" value="保存"/><br>
</form>
</body>
</html>
编写DeptSaveServlet继承HttpServlet,重写doPost方法 , 连接数据库保存新增的部门信息
<!--保存部门-->
<servlet>
<servlet-name>save</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptSaveServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>save</servlet-name>
<url-pattern>/dept/save</url-pattern>
</servlet-mapping>
public class DeptSaveServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取部门的信息
// 注意乱码问题(Tomcat10不会出现这个问题)
request.setCharacterEncoding("UTF-8");
String deptno = request.getParameter("deptno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
// 连接数据库执行insert语句
Connection conn = null;
PreparedStatement ps = null;
// 判断保存成功还是失败
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "insert into dept(deptno, dname, loc) values(?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, deptno);
ps.setString(2, dname);
ps.setString(3, loc);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}
// 判断保存成功还是失败 , 保存成功跳转到列表页面.................
}
}
新增部门添加成功之后的处理
- 转发到 /dept/list 会出现405错误 , 转发是一次请求,保存新增部门信息用的是form表单发起post请求。后端处理时会执行 DeptListServlet 的 doPost方法
- 重定向到 /oa/ /dept/list , 浏览器会在地址栏上发起一次全新的请求,这个请求是get请求 , 不需要在DeptListServlet中添加doPost方法
if (count == 1) {
// 使用转发
//request.getRequestDispatcher("/dept/list").forward(request, response);
// 这里最好使用重定向(浏览器会发一次全新的请求)浏览器在地址栏上发送请求,这个请求是get请求。
response.sendRedirect(request.getContextPath() + "/dept/list");
}else{
// 保存失败跳转到错误页面
//request.getRequestDispatcher("/error.html").forward(request, response);
// 这里也建议使用重定向。
response.sendRedirect(request.getContextPath() + "/error.html");
}
使用转发时需要在DeptListServlet中添加doPost方法,然后在doPost方法中调用doGet方法
public class DeptListServlet extends HttpServlet {
// 处理post请求
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 连接数据库 , 动态展示部门列表页面
}
实现部门修改功能
将修改按钮的超链接路径修改一下
- 这个路径是需要加项目名的。并且需要携带你想要查看的部门编号 , 这样才能连接数据库查询部门信息 , 动态的输出部门信息
// i 表示序号
int i = 0;
while(rs.next()){
String deptno = rs.getString("a");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
out.print(" <tr>");
out.print(" <td>"+(++i)+"</td>");
out.print(" <td>"+deptno+"</td>");
out.print(" <td>"+dname+"</td>");
out.print(" <td>");
out.print(" <a href='javascript:void(0)' οnclick='del("+deptno+")'>删除</a>");
out.print(" <a href='"+contextPath+"/dept/edit?deptno="+deptno+"'>修改</a>");
out.print(" <a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>");
out.print(" </td>");
out.print(" </tr>");
}
DeptEditServlet 实现点击每个部门对应的修改按钮后 , 会跳转到当前部门对应的修改页面(部门编号是只读的)
<!--跳转到修改页面-->
<servlet>
<servlet-name>edit</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptEditServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>edit</servlet-name>
<url-pattern>/dept/edit</url-pattern>
</servlet-mapping>
public class DeptEditServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取应用的根路径。
String contextPath = request.getContextPath();
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<!DOCTYPE html>");
out.print("<html>");
out.print(" <head>");
out.print(" <meta charset='utf-8'>");
out.print(" <title>修改部门</title>");
out.print(" </head>");
out.print(" <body>");
out.print(" <h1>修改部门</h1>");
out.print(" <hr >");
out.print(" <form action='"+contextPath+"/dept/modify' method='post'>");
//上面一部分是死的
// 连接数据库,动态输出部门的信息.....
。
//下面一部分是死的
out.print(" <input type='submit' value='修改'/><br>");
out.print(" </form>");
out.print(" </body>");
out.print("</html>");
}
}
根据部门编号 , 连接数据库,动态输出部门的信息
// 获取部门编号
String deptno = request.getParameter("deptno");
// 连接数据库,根据部门编号查询部门的信息。
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
String sql = "select dname, loc as location from dept where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, deptno);
rs = ps.executeQuery();
// 这个结果集中只有一条记录。
if(rs.next()){
String dname = rs.getString("dname");
String location = rs.getString("location"); // 参数"location"是sql语句查询结果列的列名。
out.print(" 部门编号<input type='text' name='deptno' value='"+deptno+"' readonly /><br>");
out.print(" 部门名称<input type='text' name='dname' value='"+dname+"'/><br>");
out.print(" 部门位置<input type='text' name='loc' value='"+location+"'/><br>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}
DeptModifyServlet 实现点击表单中的修改按钮后 , 连接数据库完成部门信息的更新
<!--修改部门-->
<servlet>
<servlet-name>modify</servlet-name>
<servlet-class>com.bjpowernode.oa.web.action.DeptModifyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>modify</servlet-name>
<url-pattern>/dept/modify</url-pattern>
<!--<url-pattern>/dept/test/abc</url-pattern>-->
</servlet-mapping>
public class DeptModifyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解决请求体的中文乱码问题。
request.setCharacterEncoding("UTF-8");
// 获取表单中的数据
String deptno = request.getParameter("deptno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
// 连接数据库执行更新语句
Connection conn = null;
PreparedStatement ps = null;
// 判断更新成功或者失败
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "update dept set dname = ?, loc = ? where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, dname);
ps.setString(2, loc);
ps.setString(3, deptno);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}
//更新部门信息成功或者失败的一个处理.....
}
}
更新部门信息成功或者失败的一个处理
if (count == 1) { // 更新成功
// 跳转到部门列表页面(部门列表页面是通过Java程序动态生成的,所以还需要再次执行另一个Servlet)
//request.getRequestDispatcher("/dept/list").forward(request, response);
response.sendRedirect(request.getContextPath() + "/dept/list");
}else{ // 更新失败
//request.getRequestDispatcher("/error.html").forward(request, response);
response.sendRedirect(request.getContextPath() + "/error.html");
}