问题
将员工管理的所有操作请求处理合并到一个Servlet中,实现请求的分发。
方案
使用后缀匹配模式,将以do结尾的请求都提交到ActionServlet中,分析do前的操作请求种类,分发到不同的分支执行相应的动作。同时将JDBC以dao和实体的形式来实现,减少分之内的重复代码。
项目结构如下:
步骤
step1: 新建Employee类
新建与t_emp表对应的实体类,属性与表字段一一对应,添加get/set方法及构造函数和toString方法。
package entity;
public class Employee {
private int id;
private String name;
private double salary;
private int age;
@Override //@Override是伪代码,表示重写
public String toString(){
return id+" "+name+" "+salary+" "+age;
}
public Employee(){ //无参构造函数
super(); //调用父类的构造方法
}
public Employee(int id,String name,double salary,int age){//有参构造函数
super();
this.id=id;
this.name=name;
this.salary=salary;
this.age=age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
step2: 新建DBUtil公共类
用于实现数据库的连接和断开的工具类。
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//JDBC管理连接的工具类,可以获取连接和关闭连接
public class DBUtil {
//获取连接对象
public static Connection getConnection() throws Exception{
Connection conn = null;
try {
//1、加载MySQL的JDBC的驱动
Class.forName("com.mysql.jdbc.Driver");
//2、取得连接的URL,能访问MySQL数据库的用户名和密码
String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "123456";
//3、创建与MySQL数据库的连接类的实例
conn=DriverManager.getConnection(url,username,password);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return conn;
}
//关闭连接对象
public static void close(Connection conn) throws Exception{
if(conn!=null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
throw e;
}
}
}
}
step 3: 新建EmployeeDAO类
建立针对Employee实体的数据操作类dao。
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.html.HTMLDocument.HTMLReader.ParagraphAction;
import entity.Employee;
//Employee的数据操作对象,负责Employee的增删改查
public class EmployeeDAO {
//查询所有员工
public List<Employee> findAll() throws Exception{
List<Employee> emps=new ArrayList<Employee>();
Connection conn=null;
PreparedStatement stmt=null;
ResultSet rs=null;
try {
conn=DBUtil.getConnection();
stmt=conn.prepareStatement("select * from t_emp");
rs=stmt.executeQuery();
while(rs.next()){
Employee emp=new Employee(
rs.getInt("id"),
rs.getString("name"),
rs.getDouble("salary"),
rs.getInt("age")
);
emps.add(emp);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil.close(conn);
}
return emps;
}
//删除员工信息
public void delete(int id) throws Exception{
Connection conn=null;
PreparedStatement stmt=null;
try {
conn=DBUtil.getConnection();
stmt=conn.prepareStatement("delete from t_emp where id=?");
stmt.setInt(1, id);
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil.close(conn);
}
}
//增加员工信息
public void save(Employee emp) throws Exception{
Connection conn=null;
PreparedStatement stmt=null;
try {
conn=DBUtil.getConnection();
stmt=conn.prepareStatement("insert into t_emp(name,salary,age)" +
"values(?,?,?)");
stmt.setString(1, emp.getName());
stmt.setDouble(2, emp.getSalary());
stmt.setInt(3, emp.getAge());
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil.close(conn);
}
}
//根据id 查询员工信息
public Employee findById(int id) throws Exception{
Employee emp=null;
Connection conn=null;
PreparedStatement stmt=null;
ResultSet rs=null;
try {
conn=DBUtil.getConnection();
stmt=conn.prepareStatement("select * from t_emp where id=?");
stmt.setInt(1, id);
rs=stmt.executeQuery();
while(rs.next()){
emp= new Employee(
rs.getInt("id"),
rs.getString("name"),
rs.getDouble("salary"),
rs.getInt("age")
);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return emp;
}
//修改员工信息
public void modify(Employee emp) throws Exception{
Connection conn=null;
PreparedStatement stmt=null;
try {
conn=DBUtil.getConnection();
stmt=conn.prepareStatement("update t_emp set name=?,salary=?,age=? " + //age=?后要加空格
"where id=?");
stmt.setString(1, emp.getName());
stmt.setDouble(2, emp.getSalary());
System.out.println(emp.getSalary());
stmt.setInt(3, emp.getAge());
stmt.setInt(4, emp.getId());
System.out.println(emp.getId());
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil.close(conn);
}
}
}
Step 4:新建ActionServlet类
创建用于进行动作分发的ActionServlet类,通过getRequestURI获取请求资源路径,分析do前面的动作种类,执行不同的分支。(Servlet处理部分)
package emp;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.EmployeeDAO;
import entity.Employee;
public class ActionServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException{
//保证正确读取Post提交来的中文
request.setCharacterEncoding("utf-8");
//保证正确输出中文
response.setContentType("text/html;charset=utf-8");
//获取输出流对象,并输出信息
PrintWriter out=response.getWriter();
//获取请求资源路径
String uri=request.getRequestURI();
//获取请求资源路径中除应用名之外的部分
String action=uri.substring(uri.lastIndexOf("/")+1, //获取*.do的*部分内容
uri.lastIndexOf("."));
if(action.equals("list")){
try {
EmployeeDAO dao=new EmployeeDAO();
List<Employee> emps = dao.findAll();
out.println("<table>");
out.println("<tr><caption>员工信息列表</caption></tr>"); //定义表格标题
out.println("<tr><td>编号</td><td>姓名</td><td>薪水</td>"+
"<td>年龄</td><td> 操作</td></tr>");
for(Employee emp:emps){
out.println("<tr>");
out.println("<td>"+emp.getId()+"</td>");
out.println("<td>"+emp.getName()+"</td>");
out.println("<td>"+emp.getSalary()+"</td>");
out.println("<td>"+emp.getAge()+"</td>");
out.println("<td><a href='delete.do?id="+emp.getId()+"' "+
"onclick=\"return confirm('是否确定删除"+emp.getName()+"');\">删除</a>");
out.println("<a href='load.do?id="+emp.getId()+"'>修改</a></td>");
out.println("</tr>");
}
out.println("</table>");
out.println("<a href='addEmp.html'>增加新员工</a>");
} catch (Exception e) {
e.printStackTrace();
out.print("系统繁忙");
}
}else if(action.equals("add")){
String name= request.getParameter("name");
double salary = Double.valueOf(request.getParameter("salary"));
int age = Integer.valueOf(request.getParameter("age"));
try {
Employee emp=new Employee();
emp.setName(name);
emp.setSalary(salary);
emp.setAge(age);
EmployeeDAO dao=new EmployeeDAO();
dao.save(emp);
response.sendRedirect("list.do");
} catch (Exception e) {
e.printStackTrace();
out.print("系统繁忙");
}
}else if(action.equals("modify")){
int id=Integer.valueOf(request.getParameter("id"));
String name= request.getParameter("name");
double salary = Double.valueOf(request.getParameter("salary"));
int age = Integer.valueOf(request.getParameter("age"));
try {
Employee emp=new Employee();
emp.setName(name);
emp.setSalary(salary);
emp.setAge(age);
emp.setId(id); //保持类的完整性
EmployeeDAO dao=new EmployeeDAO();
dao.modify(emp);
response.sendRedirect("list.do");
} catch (Exception e) {
e.printStackTrace();
out.print("系统繁忙");
}
}else if(action.equals("delete")){
int id=Integer.valueOf(request.getParameter("id"));
try{
EmployeeDAO dao=new EmployeeDAO();
dao.delete(id);
response.sendRedirect("list.do");
} catch (Exception e) {
e.printStackTrace();
out.print("系统繁忙");
}
}else if(action.equals("load")){
int id=Integer.valueOf(request.getParameter("id"));
try{
EmployeeDAO dao=new EmployeeDAO();
Employee emp = dao.findById(id);
out.println("<form action='modify.do' method='post'>");//输出表单
out.println("编号:"+ id + "<br>");
out.println("<input type='hidden' name='id' value='"+emp.getId()+"'/><br>");
out.println("姓名:<input name='name' value='"+emp.getName()+"'/><br>");
out.println("薪水:<input name='salary' value='"+emp.getSalary()+"'/><br>");
out.println("年龄:<input name='age' value='"+emp.getAge()+"'/><br>");
out.println("<input type='submit' value='修改'/>");
out.println("</form>");
out.println("</body></html>");
//response.sendRedirect("list.do");
} catch (Exception e) {
e.printStackTrace();
out.print("系统繁忙");
}
}
}
}
Step 5: 新建addEmp.html
新建用于完成增加员工的表单页面。
<body style="font-size:24px">
<form action="add.do" method="post">
<fieldset>
<legend>添加员工</legend>
姓名:<input name="name"/><br>
薪水:<input name="salary"/><br>
年龄:<input name="age"/><br>
<input type="submit" value="添加">
</fieldset>
</form>
</body>
Step 6: 修改web.xml
使用后缀匹配模式配置ActionServlet的映射原则。
<!-- 合并员工管理多请求 -->
<servlet>
<servlet-name>actionServlet</servlet-name>
<servlet-class>emp.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>actionServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
===================
到此,项目就搭建成功了。实现的也是增删改查功能,与之前不同的是,这里采用后缀匹配模式,即*.do,实现了单一控制器(Servlet)管理员工信息。表面来看是在web.xml配置中少写了很多、,实际上也精简了很多代码,有分层管理代码的思路,看起来更清晰。