老杜 JavaWeb 讲解(十四) ——JSP+Servlet改造oa项目

发布时间 2023-07-24 21:35:46作者: 猪无名

(十四)JSP改造oa项目

相关视频:

38-Servlet和JSP改造oa项目

使用Servlet + JSP完成oa项目的改造

  • 使用Servlet处理业务,收集数据。 使用JSP展示数据。

  • 将之前原型中的html文件,全部修改为jsp,然后在jsp文件头部添加page指令(指定contentType防止中文乱码),将所有的JSP直接拷贝到web目录下。

  • 完成所有页面的正常流转。(页面仍然能够正常的跳转。修改超链接的请求路径。)

    • <%=request.getContextPath() %> 在JSP中动态的获取应用的根路径。
  • Servlet中连接数据库,查询所有的部门,遍历结果集。

    • 遍历结果集的过程中,取出部门编号、部门名、位置等信息,封装成java对象。
    • 将java对象存放到List集合中。
    • 将List集合存储到request域当中。
    • 转发forward到jsp。
  • 在JSP中:

    • 从request域当中取出List集合。
    • 遍历List集合,取出每个部门对象。动态生成 tr标签。
  • 思考一个问题:如果我只用JSP这一个技术,能不能开发web应用?

    • 当然可以使用JSP来完成所有的功能。因为JSP就是Servlet,在JSP的<%%>里面写的代码就是在service方法当中的,所以在<%%>当中完全可以编写JDBC代码,连接数据库,查询数据,也可以在这个方法当中编写业务逻辑代码,处理业务,都是可以的,所以使用单独的JSP开发web应用完全没问题。
    • 虽然JSP一个技术就可以完成web应用,但是不建议,还是建议采用servlet + jsp的方式进行开发。这样都能将各自的优点发挥出来。JSP就是做数据展示。Servlet就是做数据的收集。(JSP中编写的Java代码越少越好。)一定要职责分明。
  • JSP文件的扩展名必须是xxx.jsp吗?

    • jsp文件的扩展名是可以配置的。不是固定的。

    • 在CATALINA_HOME/conf/web.xml,在这个文件当中配置jsp文件的扩展名。

      <!-- The mappings for the JSP servlet -->
      <servlet-mapping>
          <servlet-name>jsp</servlet-name>
          <url-pattern>*.jsp</url-pattern>
          <url-pattern>*.jspx</url-pattern>
      </servlet-mapping>
      
    • xxx.jsp文件对于小猫咪来说,只是一个普通的文本文件,web容器会将xxx.jsp文件最终生成java程序,最终调用的是java对象相关的方法,真正执行的时候,和jsp文件就没有关系了。

    • 小窍门:JSP如果看不懂,建议把jsp翻译成java代码,就能看懂了。

  • 包名bean是什么意思?

    • javabean(java的logo是一杯冒着热气的咖啡。javabean被翻译为:咖啡豆)

    • java是一杯咖啡,咖啡又是由一粒一粒的咖啡豆研磨而成。

    • 整个java程序中有很多bean的存在。由很多bean组成。

    • 什么是javabean?实际上javabean你可以理解为符合某种规范的java类,比如:

      有无参数构造方法

      属性私有化
      对外提供公开的set和get方法

      实现java.io.Serializable接口

      重写toString

      重写hashCode+equals

      ... ...

    • javabean其实就是java中的实体类。负责数据的封装。

    • 由于javabean符合javabean规范,具有更强的通用性。

具体代码实现:

工具类

DBUtil.java(简化数据库操作)
package com.zwm.oa.utils;

import java.sql.*;
import java.util.ResourceBundle;

/**
 * @author 猪无名
 * @date 2023/7/14 16 15
 * discription:JDBC的工具类
 */
public class DBUtil {
    //静态变量:在类加载时,执行
    //顺序:自上而下

    //属性资源文件绑定,根据属性配置文件的key获取value。
    private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc");
    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数据库。
            //如果直接写死,后续更改可能要修改java代码,显然违背OCP原则(对扩展开放,对修改关闭)。
            //Class.forName("com.mysql.jdbc.Driver");
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取数据库连接对象
     * @return connection连接对象
     * @throws SQLException
     */
    public static Connection getConnection()  throws SQLException {
        //注册驱动只需要注册一次, 因此放在静态代码块中。
        //获取连接
        Connection connection = DriverManager.getConnection(url, user, password);

        return connection;
    }

    /**
     *释放资源
     * @param connection     连接对象
     * @param statement      数据库操作对象
     * @param resultSet      结果集对象
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet){
        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);
            }
        }

    }

}

Dept.java(javaBean 用来封装数据 )
package com.zwm.oa.bean;

import java.util.Objects;

/**
 * @author 猪无名
 * @date 2023/7/24 16 44
 * discription:一个普通的java类,这个Java类可以封装零散的数据。代表一个部门。
 */
public class Dept {
    private String deptno;
    private String dname;
    private String loc;

    public String getDeptno() {
        return deptno;
    }

    public void setDeptno(String deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    public Dept(String deptno, String dname, String loc) {
        this.deptno = deptno;
        this.dname = dname;
        this.loc = loc;
    }
    public Dept() {
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno='" + deptno + '\'' +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dept dept = (Dept) o;
        return Objects.equals(deptno, dept.deptno) && Objects.equals(dname, dept.dname) && Objects.equals(loc, dept.loc);
    }

    @Override
    public int hashCode() {
        return Objects.hash(deptno, dname, loc);
    }
}

Servlet

DeptServlet.java

package com.zwm.oa.web.action;

import com.zwm.oa.bean.Dept;
import com.zwm.oa.utils.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
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.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 猪无名
 * @date 2023/7/23 19 02
 * discription:
 */
@WebServlet({ "/dept/list","/dept/delete","/dept/detail","/dept/save","/dept/modify"})
public class DeptServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String servletPath = request.getServletPath();
        if("/dept/list".equals(servletPath)){
            doList(request,response);
        }else if("/dept/delete".equals(servletPath)){
            doDel(request,response);
        }else if("/dept/detail".equals(servletPath)){
            doDetail(request,response);
        }else if("/dept/save".equals(servletPath)){
            doSave(request,response);
        }else if("/dept/modify".equals(servletPath)){
            doModify(request,response);
        }
    }


    private void doModify(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        String deptno = request.getParameter("deptno");
        String deptname = request.getParameter("deptname");
        String loc = request.getParameter("loc");
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "UPDATE dept SET dname = ?, loc = ? WHERE deptno = ?";
            ps=conn.prepareStatement(sql);
            ps.setString(1,deptname);
            ps.setString(2,loc);
            ps.setString(3,deptno);
            //执行SQL语句
            //返回值代表影响了数据库当中多少条数据。
            int rowsAffected = ps.executeUpdate();

            if (rowsAffected > 0) {
                System.out.println("更改成功");
                response.sendRedirect(request.getContextPath()+"/dept/list");
            } else {
                System.out.println("无匹配数据");
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //释放资源
            DBUtil.close(conn,ps,rs);
        }
    }

    //数据添加
    private void doSave(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        String deptno = request.getParameter("deptno");
        String deptname = request.getParameter("deptname");
        String loc = request.getParameter("loc");

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "INSERT INTO dept (deptno, dname, loc) VALUES (?, ?, ?)";
            ps=conn.prepareStatement(sql);
            ps.setString(1,deptno);
            ps.setString(2,deptname);
            ps.setString(3,loc);
            //执行SQL语句
            //返回值代表影响了数据库当中多少条数据。
            int rowsAffected = ps.executeUpdate();
            if (rowsAffected > 0) {
                System.out.println(rowsAffected + " 行已插入数据");
                response.sendRedirect(request.getContextPath()+"/dept/list");
            } else {
                System.out.println("未插入任何数据");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //释放资源
            DBUtil.close(conn,ps,rs);
        }
    }

    //根据部门编号获取部门信息
    private void doDetail(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取部门编号
        String deptno = request.getParameter("deptno");
        //根据部门编号获取部门信息,将部门信息封装在bean中。
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        Dept dept = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "select dname,loc from dept where deptno = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, deptno);

            //这个结果集中只有一条数据,不需要循环。
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");

                //创建豆子,封装对象。
                dept = new Dept(deptno, dname, loc);

            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        request.setAttribute("dept", dept);

        request.getRequestDispatcher("/"+request.getParameter("tag")+".jsp").forward(request,response);

    }


    //执行删除
    private void doDel(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{

        String deptno = request.getParameter("deptno");
        //System.out.println(deptno);

        //连接数据库,查询所有的部门信息。
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            //获取连接
            connection = DBUtil.getConnection();
            String sql = "DELETE FROM dept WHERE deptno = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,deptno);

            int rowsAffected = preparedStatement.executeUpdate();

            if (rowsAffected > 0) {
                System.out.println("删除成功");
                // 删除完成后重定向回原来的页面
                response.sendRedirect(request.getContextPath()+"/dept/list");
            } else {
                System.out.println("删除失败");
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,preparedStatement, null);
        }

    }



    /**
     * 连接数据库,查询所有的部门信息,将部门信息收集好,然后跳转到JSP进行页面展示。
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void doList(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        //连接数据库,查询所有的部门信息。
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        List<Dept> depts = new ArrayList<>();

        try {
            //获取连接
            connection = DBUtil.getConnection();
            //执行查询语句
            String sql = "select deptno,dname,loc from dept";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();

            // 遍历结果集
            while (resultSet.next()){
                String deptno = resultSet.getString("deptno");
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");

                //从一个servlet跳转到另一个jsp,就相当于从一个servlet跳转到另一个servlet。
                //此时使用请求域来保存数据。
                //另外,因为查询的数据比较零散,所以可以使用一个java类来封装这些数据。
                Dept dept = new Dept(deptno,dname,loc);

                //将部门对象放在List集合中。
                depts.add(dept);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,preparedStatement,resultSet);
        }

        //将一个集合放在请求域中。
        request.setAttribute("deptList",depts);

        //进行转发(不需要项目名)
        request.getRequestDispatcher("/list.jsp").forward(request,response);

    }
}

JSP

list.jsp
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
	<head>
		<meta charset="utf-8">
		<title>部门列表页面</title>
	</head>
	<body>
		<script>
			function del(dno){
				if(window.confirm("亲,删了不可恢复哦!")){
					document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + dno;
				}
			}
		</script>
		
		<h1 align="center">部门列表</h1>
		<hr>
		<table border="1px" align="center" width="50%">
			<tr>
				<th>编号</th>
				<th>名称</th>
				<th>位置</th>
				<th>操作</th>
			</tr>

            <%--这里返回的是一个Object,但我们已经知道返回的是List集合,所有可以进行强制转换。--%>
			<%
				List<Dept> deptList = (List<Dept>)request.getAttribute("deptList");
				int i = 0;
				for (Dept dept : deptList) {
					//System.out.println(dept);
			%>

			<tr>
				<td><%=++i%></td>
				<td><%=dept.getDeptno()%></td>
				<td><%=dept.getLoc()%></td>
				<td>
					<a href= "#" onclick="del(<%=dept.getDeptno()%>)" >删除</a>
					<a href="<%=request.getContextPath()%>/dept/detail?tag=edit&deptno=<%=dept.getDeptno()%>">修改</a>
					<a href="<%=request.getContextPath()%>/dept/detail?tag=detail&deptno=<%=dept.getDeptno()%>">详情</a>
				</td>
			</tr>

			<%
				}
			%>

		</table>
		
		<hr>
		<a href="<%=request.getContextPath()%>/add.jsp">新增部门</a>
	</body>
</html>
detail.jsp
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%
	Dept dept = (Dept)request.getAttribute("dept");
%>
<html>
	<head>
		<meta charset="utf-8">
		<title>部门详情</title>
	</head>
	<body>
		<h1>部门详情</h1>
		<hr>
		部门编号:<%=dept.getDeptno()%>			<br>
		部门名称:<%=dept.getDname()%>			<br>
		部门位置:<%=dept.getLoc()%>		        <br>

		<input type="button" value="后退" onclick="window.history.back()"/>
		
	</body>
</html>
edit.jsp
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
	Dept dept = (Dept)request.getAttribute("dept");
%>

<html>
	<head>
		<meta charset="utf-8">
		<title>修改部门</title>
	</head>
	<body>
		<h1>修改部门</h1>
		<hr>
		<form action="<%=request.getContextPath()%>/dept/modify" method="post">
			部门编号:<input type="text" name="deptno" value="<%=dept.getDeptno()%>" readonly/><br>
			部门名称:<input type="text" name="deptname" value="<%=dept.getDname()%>"/><br>
			部门位置:<input type="text" name="loc" value="<%=dept.getLoc()%>"/><br>
			<input type="submit" value="修改"/><br>
		</form>
	</body>
</html>
add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
	<head>
		<meta charset="utf-8">
		<title>新增部门</title>
	</head>
	<body>
		<h1>新增部门</h1>
		<hr>
		<form action="<%=request.getContextPath()%>/dept/save" method="post">
			部门编号:<input type="text" name="deptno"/><br>
			部门名称:<input type="text" name="deptname"/><br>
			部门位置:<input type="text" name="loc"/><br>
			<input type="submit" value="保存"/><br>
			
			
		</form>
	</body>
</html>