Using Servlets and JSP to Refactor an OA Project
Servlets handle business logic and data collection, while JSP is used for data presentation. The original HTML files are converted to JSP, adding a page directive at the top to set the content type and avoid charset issues. All JSPs are placed directly under the web directory. Navigation between pages is maintained by updating hyperlinks to use <%=request.getContextPath()%> to dynamically fetch the application's root path.
In the Servlet, a database connection is established to query all departments. The result set is iterated to extract department number, name, and location, which are then encapsulated into Java objects. These objects are stored in a List, which is placed into the request scope and forwarded to the JSP page.
In the JSP, the List is retrieved from the request scope and itertaed to generate table rows dynamically.
Can a web application be developed using only JSP?
Yes, JSP alone is sufficient because JSP is ultimately a Servlet. The code within <% %> is executed inside the service method, so JDBC code for database operations and business logic can be written there. However, it is recommended to use Servlets and JSP together to leverage their strengths: Servlets for data collection and JSP for data presentation. The amount of Java code in JSP should be minimized to maintain clear separation of responsibilities.
Is the extension of JSP files fixed to .jsp?
No, it is configurable. The mapping for JSP file extensions is defined in CATALINA_HOME/conf/web.xml:
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
The JSP file is just a plain text file for the server. The web container translates it into a Java program and executes the corresponding Java object methods. At runtime, the original JSP file is no longer involved. If you find JSP syntax confusing, studying the translated Java code can be helpful.
What does the package name 'bean' mean?
JavaBean refers to a Java class that follows certain conventions:
- A no-argument constructor
- Private fields with public getter and setter methods
- Implements
java.io.Serializable- Overrides
toString(),hashCode(), andequals()
A JavaBean is essentially an entity class used for data encapsulation. Adhering to the JavaBean specification improves reusability and consistency.
Implemantation Details
Utility Class
DBUtil.java – Simplifying Database Operations
package com.zwm.oa.utils;
import java.sql.*;
import java.util.ResourceBundle;
/**
* JDBC utility class.
*/
public class DBUtil {
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 {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
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 – Data Encapsulation Bean
package com.zwm.oa.bean;
import java.util.Objects;
/**
* Represents a department entity.
*/
public class Dept {
private String deptno;
private String dname;
private String loc;
public Dept() {}
public Dept(String deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
// Getters and setters
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; }
@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 – Handling All Department Requests
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.*;
import java.util.ArrayList;
import java.util.List;
@WebServlet({"/dept/list", "/dept/delete", "/dept/detail", "/dept/save", "/dept/modify"})
public class DeptServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = req.getServletPath();
switch (path) {
case "/dept/list" -> doList(req, resp);
case "/dept/delete" -> doDelete(req, resp);
case "/dept/detail" -> doDetail(req, resp);
case "/dept/save" -> doSave(req, resp);
case "/dept/modify" -> doModify(req, resp);
}
}
private void doList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Dept> deptList = new ArrayList<>();
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT deptno, dname, loc FROM dept");
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
Dept dept = new Dept(rs.getString("deptno"), rs.getString("dname"), rs.getString("loc"));
deptList.add(dept);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
req.setAttribute("deptList", deptList);
req.getRequestDispatcher("/list.jsp").forward(req, resp);
}
private void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String deptno = req.getParameter("deptno");
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement("DELETE FROM dept WHERE deptno = ?")) {
ps.setString(1, deptno);
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
resp.sendRedirect(req.getContextPath() + "/dept/list");
}
private void doDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String deptno = req.getParameter("deptno");
Dept dept = null;
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT dname, loc FROM dept WHERE deptno = ?")) {
ps.setString(1, deptno);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
dept = new Dept(deptno, rs.getString("dname"), rs.getString("loc"));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
req.setAttribute("dept", dept);
String target = req.getParameter("tag");
req.getRequestDispatcher("/" + target + ".jsp").forward(req, resp);
}
private void doSave(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String deptno = req.getParameter("deptno");
String dname = req.getParameter("deptname");
String loc = req.getParameter("loc");
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement("INSERT INTO dept(deptno, dname, loc) VALUES (?, ?, ?)")) {
ps.setString(1, deptno);
ps.setString(2, dname);
ps.setString(3, loc);
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
resp.sendRedirect(req.getContextPath() + "/dept/list");
}
private void doModify(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String deptno = req.getParameter("deptno");
String dname = req.getParameter("deptname");
String loc = req.getParameter("loc");
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement("UPDATE dept SET dname = ?, loc = ? WHERE deptno = ?")) {
ps.setString(1, dname);
ps.setString(2, loc);
ps.setString(3, deptno);
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
resp.sendRedirect(req.getContextPath() + "/dept/list");
}
}
JSP Pages
list.jsp – Department List Page
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Department List</title>
</head>
<body>
<script>
function confirmDelete(dno) {
if (window.confirm("Delete this department? This action cannot be undone.")) {
document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + dno;
}
}
</script>
<h1 align="center">Department List</h1>
<hr>
| \# | Number | Name | Location | Actions |
|---|---|---|---|---|
<dept> deptList = (List<dept>) request.getAttribute("deptList"); int index = 0; for (Dept dept : deptList) { index++; %> | <%=index%> | <%=dept.getDeptno()%> | <%=dept.getDname()%> | <%=dept.getLoc()%> | [Delete](#) [Edit](<%=request.getContextPath()%>/dept/detail?tag=edit&deptno=<%=dept.getDeptno()%>) [Detail](<%=request.getContextPath()%>/dept/detail?tag=detail&deptno=<%=dept.getDeptno()%>) |
<% } %> </dept></dept>
<hr>
<a href="<%=request.getContextPath()%>/add.jsp">Add Department</a>
</body>
</html>
detail.jsp – Department Details
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Dept dept = (Dept) request.getAttribute("dept");
%>
<html>
<head>
<title>Department Detail</title>
</head>
<body>
<h1>Department Detail</h1>
<hr>
Number: <%=dept.getDeptno()%><br>
Name: <%=dept.getDname()%><br>
Location: <%=dept.getLoc()%><br>
<input type="button" value="Back" onclick="window.history.back()"/>
</body>
</html>
edit.jsp – Edit Department Form
<%@ page import="com.zwm.oa.bean.Dept" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Dept dept = (Dept) request.getAttribute("dept");
%>
<html>
<head>
<title>Edit Department</title>
</head>
<body>
<h1>Edit Department</h1>
<hr>
<form action="<%=request.getContextPath()%>/dept/modify" method="post">
Number: <input type="text" name="deptno" value="<%=dept.getDeptno()%>" readonly/><br>
Name: <input type="text" name="deptname" value="<%=dept.getDname()%>"/><br>
Location: <input type="text" name="loc" value="<%=dept.getLoc()%>"/><br>
<input type="submit" value="Update"/>
</form>
</body>
</html>
add.jsp – Add Department Form
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Add Department</title>
</head>
<body>
<h1>Add Department</h1>
<hr>
<form action="<%=request.getContextPath()%>/dept/save" method="post">
Number: <input type="text" name="deptno"/><br>
Name: <input type="text" name="deptname"/><br>
Location: <input type="text" name="loc"/><br>
<input type="submit" value="Save"/>
</form>
</body>
</html>