客户管理系统的详细编写流程
一、系统设计
1、需求分析
(系统中包含哪些数据模型、数据模型存在怎样的关系 E-R图、UML(用例图))
2、制作页面Demo
(和真实系统效果一样,给客户确认需求)
3、技术选型(环境搭建)
软件建模工具:IBM RSA、Rational Rose、Jude(日本研发 纯java编写,小巧。在此次编写中使用)
技术选型:DHTML+JSP+Servlet+C3P0+DBUtils+MySQL(MVC模式,DAO模型)+Tomcat6+Windows
4、数据库设计 ----- 新建数据库 新建用户
create table customer(
id varchar(40) primary key,
name varchar(20) not null,
gender varchar(10) not null,
birthday date ,
cellphone varchar(20),
email varchar(40),
preference varchar(100),
type varchar(40) not null,
description varchar(255)
);
创建数据库新用户angle 并利用angle来实现JDBC对数据库的操作
create user angel identified by ‘angel‘; --此句用来创建angle用户 密码用identified设置为angle
grant all on customer.* to angel; --此句用来限定angle账户访问的权限为customer下的一切数据
5、搭建开发环境
(1)创建工程
(2)导入jar包
c3p0-0.9.1.2.jar (因为要用到c3p0技术 )
commons-beanutils-1.8.3.jar commons-logging-1.1.1.jar (利用BeanUtils技术将参数快速封装入javabean中)
commons-dbutils-1.4.jar (数据层快速进行CURD操作)
mysql-connector-java-5.0.8-bin.jar (MySQL数据库驱动)
(3)创建工程包结构
web层:web
业务层:service
数据层:dao
工具类包:utils
bean数据类包:vo
(4)配置文件 c3p0
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="user">angel</property> <property name="password">angel</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///customer</property> <property name="idleConnectionTestPeriod">30</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!-- This app is massive! --> </c3p0-config>
6、编写基本类
JDBCUtils 提供连接池和连接工具类
Customer JavaBean结构和数据库对应
JDBCUtils
package utils; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * 工具类 提供数据库连接池 和数据库连接 * * @author seawind * */ public class JDBCUtils { private static DataSource dataSource = new ComboPooledDataSource(); public static DataSource getDataSource() { return dataSource; } /** * 当DBUtils需要手动控制事务时,调用该方法获得一个连接 * * @return * @throws SQLException */ public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }
Customer类
package vo; import java.sql.Date; /** * javabean实体类 * * @author seawind * */ public class Customer { <span style="white-space:pre"> </span>private String id; <span style="white-space:pre"> </span>private String name; <span style="white-space:pre"> </span>private String gender; <span style="white-space:pre"> </span>private Date birthday; <span style="white-space:pre"> </span>private String cellphone; <span style="white-space:pre"> </span>private String email; <span style="white-space:pre"> </span>private String preference;// 爱好为复选框,不止一个爱好,所以此处会想到用数组,但是若为数组类型,这数据库封 //装不了,所以将此问题在web层进行封装时解决掉。 <span style="white-space:pre"> </span>private String type; <span style="white-space:pre"> </span>private String description; <span style="white-space:pre"> </span>public String getId() { <span style="white-space:pre"> </span>return id; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setId(String id) { <span style="white-space:pre"> </span>this.id = id; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getName() { <span style="white-space:pre"> </span>return name; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setName(String name) { <span style="white-space:pre"> </span>this.name = name; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getGender() { <span style="white-space:pre"> </span>return gender; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setGender(String gender) { <span style="white-space:pre"> </span>this.gender = gender; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public Date getBirthday() { <span style="white-space:pre"> </span>return birthday; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setBirthday(Date birthday) { <span style="white-space:pre"> </span>this.birthday = birthday; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getCellphone() { <span style="white-space:pre"> </span>return cellphone; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setCellphone(String cellphone) { <span style="white-space:pre"> </span>this.cellphone = cellphone; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getEmail() { <span style="white-space:pre"> </span>return email; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setEmail(String email) { <span style="white-space:pre"> </span>this.email = email; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getPreference() { <span style="white-space:pre"> </span>return preference; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setPreference(String preference) { <span style="white-space:pre"> </span>this.preference = preference; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getType() { <span style="white-space:pre"> </span>return type; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setType(String type) { <span style="white-space:pre"> </span>this.type = type; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public String getDescription() { <span style="white-space:pre"> </span>return description; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void setDescription(String description) { <span style="white-space:pre"> </span>this.description = description; <span style="white-space:pre"> </span>} }
因为客户id为customer表的主键,不能重复,所以利用UUID和Hash码来得到不同的主键
编写CustomerUtils类来实现主键的获取
package utils; import java.util.UUID; /** * 客户工具类,提供通用方法 * * @author seawind * */ public class CustomerUtils { public static String generateId() { <span style="color:#ff0000;">String uuid = UUID.randomUUID().toString(); return uuid.hashCode(); </span><span style="color:#33ccff;">//UUID值太长 所以取得其Hash码</span> } }
7、CURD
按照 : 增加 ----- 查询 ---- 删除 ---- 修改 的顺序进行编写
(1)增加数据。
进行增加数据流程的设计分析
首先编写客户端显示页面,要实现对参数的表单提交
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>客户信息增加</title> </head> <body> <h1>客户信息增加</h1> <form action="${pageContext.request.contextPath }/addCustomer" method="post"> <table> <tr> <td><label for="name">客户姓名</label> </td> <td><input type="text" name="name" id="name" /> </td> </tr> <tr> <td><label for="gender">性别</label></td> <td> <input type="radio" name="gender" id="male" value="男"/><label for="male">男</label> <input type="radio" name="gender" id="female" value="女"/><label for="female">女</label> </td> </tr> <tr> <td><label for="birthday">生日</label></td> <td><input type="text" name="birthday" id="birthday" /></td> </tr> <tr> <td><label for="cellphone">手机号码</label></td> <td><input type="text" name="cellphone" id="cellphone" /></td> </tr> <tr> <td><label for="email">邮箱</label></td> <td><input type="text" name="email" id="email" /></td> </tr> <tr> <td><label for="preference">爱好</label></td> <td> <input type="checkbox" name="preference" value="音乐" id="music" /><label for="music">音乐</label> <input type="checkbox" name="preference" value="体育" id="sport" /><label for="sport">体育</label> <input type="checkbox" name="preference" value="读书" id="read" /><label for="read">读书</label> <input type="checkbox" name="preference" value="旅游" id="travel" /><label for="travel">旅游</label> </td> </tr> <tr> <td><label for="type">类型</label></td> <td> <select name="type" id="type"> <option value="vip">VIP</option> <option value="白金用户">白金用户 </option> <option value="普通用户">普通用户 </option> </select> </td> </tr> <tr> <td><label for="description">客户信息</label></td> <td> <textarea rows="5" cols="60" name="description" id="description"></textarea> </td> </tr> <tr> <td><input type="submit" value="添加" /></td> <td><input type="reset" value="重置" /></td> </tr> </table> </form> </body> </html>
然后数据由客户端提交到web层,由AddCustomerServlet来进行javabean封装
建立AddCustomerServlet 将url设置为/addCustomer
package web; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import service.CustomerService; import vo.Customer; public class AddCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { <span style="color:#ff6666;">// 处理乱码 request.setCharacterEncoding("utf-8");</span> // beanutils封装 Customer customer = new Customer(); try { BeanUtils.populate(customer, request.getParameterMap()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } <span style="color:#ff0000;">// 没有完成爱好封装、自己封装 String[] preference = request.getParameterValues("preference"); // 例如:音乐 体育 ------ [音乐,体育] String value = Arrays.toString(preference); value = value.substring(1, value.length() - 1); //去掉集合的中括号 customer.setPreference(value);</span> // 查看封装效果 CustomerService service = new CustomerService(); service.addCustomer(customer); // 跳转index.jsp response.sendRedirect(request.getContextPath() + "/index.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
再由web层把数据传递到业务层,在业务层编写业务逻辑。但由于此案例并无业务逻辑,故在业务层直接调用数据层的增加方法即可
public class CustomerService { /** * 添加客户信息 * * @param customer */ public void addCustomer(Customer customer) { CustomerDAO customerDAO = new CustomerDAO(); customerDAO.inser(customer); } }
再在dao包编写数据库增加操作类
public class CustomerDAO { public void inser(Customer customer) { // 使用DBUtls存入数据库 QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "insert into customer values(?,?,?,?,?,?,?,?,?)"; Object[] param = { CustomerUtils.generateId(), customer.getName(), customer.getGender(), customer.getBirthday(), customer.getCellphone(), customer.getEmail(), customer.getPreference(), customer.getType(), customer.getDescription() }; // 执行sql ----- update try { queryRunner.update(sql, param); } catch (SQLException e) { e.printStackTrace(); } } }
跳转到主页面,编写主页面index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <span style="color:#ff0000;"><h1>欢迎使用客户管理系统</h1> <a href="${pageContext.request.contextPath }/add.jsp">添加客户信息</a> <a href="${pageContext.request.contextPath }/searchCustomer">查询客户信息</a> <a href="${pageContext.request.contextPath }/searchPage">分页查询客户信息</a> </body></span>
<span style="color:#ff6600;"> </span><u><span style="color:#ff6600;"><--上面几句主要注意利用</span><span style="color:#3366ff;">EL表达式获得路径</span><span style="color:#ff6600;">的方法--></span></u> </html>
至此即完成增加用户的操作
(2)查询数据
进行完毕增加操作后,建议进行查询操作。一来查询操作比较简单,二来也可以查看一下增加操作是否成功。
同样首先进行流程设计
首先要编写list.jsp来实现对列表的显示
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>显示所有客户信息</title> </head> <body> <h1>客户信息表</h1> <table border="1"> <tr> <th>客户编号</th> <th>客户姓名</th> <th>性别</th> <th>生日</th> <th>手机号码</th> <th>邮箱</th> <th>爱好</th> <th>类型</th> <th>客户信息</th> </tr> <span style="color:#ff6666;"><c:forEach var="customer" items="${requestScope.customers}"> <tr> <td>${customer.id }</td> <td>${customer.name }</td> <td>${customer.gender }</td> <td>${customer.birthday }</td> <td>${customer.cellphone }</td> <td>${customer.email }</td> <td>${customer.preference }</td> <td>${customer.type }</td> <td>${customer.description }</td> </tr> </c:forEach></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="color:#33ccff;font-family: Arial, Helvetica, sans-serif;"> <--注意上述代码用JSTL技术实现对查询结果的循环输出--></span>
<span style="font-weight: normal;"></table> </body> </html></span>
同样根据流程图我们首先进行web层的SearchCustomerServlet
package web; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import service.CustomerService; import vo.Customer; public class SearchCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 调用Service 查询 CustomerService customerService = new CustomerService(); List<Customer> customers = customerService.searchCustomer(); // 传递结果给jsp request.setAttribute("customers", customers); request.getRequestDispatcher("/list.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
再在业务层中的类CustomerService.java中编写业务层方法
/** * 查询所有用户 */ public List<Customer> searchCustomer() { List<Customer> customers; CustomerDAO customerDAO = new CustomerDAO(); customers = customerDAO.findAll(); return customers; }
数据层CustomerDAO.java中编写查询方法findAll()
// 查询所有客户信息 public List<Customer> findAll() { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "select * from customer"; try { List<Customer> customers = queryRunner.query(sql, <span style="color:#ff0000;">new BeanListHandler<Customer>(Customer.class)</span>); return customers; } catch (SQLException e) { e.printStackTrace(); } return null; }
至此,查询工作做完。
(3)删除数据
对操作做一个流程图
首先,要进行数据的删除,我们需要在前面生成的list页面数据表格中添加一列删除链接,来实现对某条数据的删除。而且,删除属于危险动作,我们需要对删除动作进行一个确认操作提示框。
修改后的list.jsp (红色部分为修改部分)
<span style="font-weight: normal;"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>显示所有客户信息</title> </span><span style="color:#ff0000;font-weight: normal;"><script type="text/javascript"> function confirmDel(e){ //e 是一个事件对象 // 提示用户确认 var isConfirm = window.confirm("是否删除?"); if(!isConfirm){ // 用户取消删除 </span><span style="color:#3366ff;font-weight: normal;">if(e&&e.preventDefault){ // 此时不是IE e.preventDefault(); // 官方DOM提供方法 火狐可以用 }else{ // 此时IE window.event.returnValue=false; }</span><span style="color:#ff0000;font-weight: normal;"> } } </script></span><span style="font-weight: normal;"> </head> <body> <h1>客户信息表</h1> <table border="1"> <tr> <th>客户编号</th> <th>客户姓名</th> <th>性别</th> <th>生日</th> <th>手机号码</th> <th>邮箱</th> <th>爱好</th> <th>类型</th> <th>客户信息</th> </span><span style="color:#ff0000;"><th>删除操作</th></span><span style="font-weight: normal;"> </tr> <c:forEach var="customer" items="${requestScope.customers}"> <tr> <td>${customer.id }</td> <td>${customer.name }</td> <td>${customer.gender }</td> <td>${customer.birthday }</td> <td>${customer.cellphone }</td> <td>${customer.email }</td> <td>${customer.preference }</td> <td>${customer.type }</td> <td>${customer.description }</td> </span><span style="color:#ff0000;"><td><a href=</span><span style="color:#cc33cc;">"delCustomer?id=${customer.id }"</span><span style="color:#ff0000;"> </span><span style="color:#3366ff;">onclick="confirmDel(event);"</span><span style="color:#ff0000;">>删除</a></td> <--上述语句很重要,将所要删除的主键id提交至服务器--></span><span style="font-weight: normal;"> </tr> </c:forEach> </table> </body> </html></span>
然后将所要删除的数据的主键信息封装至javabean中(利用主键来得知要删除哪一个数据)
package web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import service.CustomerService; import vo.Customer; public class DelCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获得删除id 存入javabean Customer customer = new Customer(); customer.setId(request.getParameter("id")); CustomerService customerService = new CustomerService(); customerService.delCustomer(customer); <span style="color:#ff0000;">// 跳转到显示客户信息Servlet(***一定要注意记得此步骤,删除之后会跳查询的servlet) request.getRequestDispatcher("/searchCustomer").forward(request, response); </span> } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
然后将数据传递至业务层,在业务层中增加删除数据的方法
/** * 删除客户信息 * * @param customer */ public void delCustomer(Customer customer) { CustomerDAO customerDAO = new CustomerDAO(); customerDAO.delete(customer); }
然后传递至数据层,在CustomerDAO类中增加删除客户信息的方法
// 删除客户信息 public void delete(Customer customer) { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "delete from customer where id =?"; try { queryRunner.update(sql, customer.getId()); } catch (SQLException e) { e.printStackTrace(); } }
至此,删除操作完成。
(4)修改操作
之所以将修改操作放置最后,是因为相比其他几个操作而言修改操作更为繁琐。
修改操作有两个注意点:1.要进行全字段修改
2.要把所要修改的客户原始信息呈现出来
对于修改操作的流程如图:
要进行修改操作,就如同删除操作,首先要在客户信息显示列表末尾添加修改链接。
所以首先对list.jsp进行进一步修改
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>显示所有客户信息</title> <script type="text/javascript"> function confirmDel(e){ //e 是一个事件对象 // 提示用户确认 var isConfirm = window.confirm("是否删除?"); if(!isConfirm){ // 用户取消删除 if(e&&e.preventDefault){ // 此时不是IE e.preventDefault(); // 官方DOM提供方法 火狐可以用 }else{ // 此时IE window.event.returnValue=false; } } } </script> </head> <body> <h1>客户信息表</h1> <table border="1"> <tr> <th>客户编号</th> <th>客户姓名</th> <th>性别</th> <th>生日</th> <th>手机号码</th> <th>邮箱</th> <th>爱好</th> <th>类型</th> <th>客户信息</th> <th>删除操作</th> <span style="color:#ff0000;"><th>修改操作</th></span> </tr> <c:forEach var="customer" items="${requestScope.customers}"> <tr> <td>${customer.id }</td> <td>${customer.name }</td> <td>${customer.gender }</td> <td>${customer.birthday }</td> <td>${customer.cellphone }</td> <td>${customer.email }</td> <td>${customer.preference }</td> <td>${customer.type }</td> <td>${customer.description }</td> <td><a href="delCustomer?id=${customer.id }" onclick="confirmDel(event);">删除</a></td> <span style="color:#ff0000;"><td><a href="viewCustomer?id=${customer.id }">修改</a></td></span> </tr> </c:forEach> </table> </body> </html>
首先获得所要修改的用户的id,并通过该用户的id来得到该用户的原始信息,再将原始信息回显到update.jsp中由用户进行修改
将来自list.jsp的id信息传递至web层的ViewCustomerServlet
package web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import service.CustomerService; import vo.Customer; public class ViewCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 接收修改数据 编号 String id = request.getParameter("id"); // 调用业务层 查询相应数据 CustomerService customerService = new CustomerService(); Customer customer = customerService.viewCustomer(id); // 传递数据给JSP request.setAttribute("customer", customer); request.getRequestDispatcher("/update.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
将数据传递至业务层 增加通过id查询信息的方法
/** * 通过id查询客户信息 * */ public Customer viewCustomer(String id) { // 传递客户编号 给数据层 CustomerDAO customerDAO = new CustomerDAO(); Customer customer = customerDAO.findById(id); return customer; }
将数据传递至数据层,进行具体的查询方法实现
// 通过客户id 查询客户信息 public Customer findById(String id) { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "select * from customer where id = ?"; try { Customer customer = queryRunner.query(sql, new BeanHandler<Customer>(Customer.class), id); return customer; } catch (SQLException e) { e.printStackTrace(); } return null; }
得到了客户原始数据信息,即回显至update.jsp中,编写update.jsp页面
<span style="font-size:18px; font-weight: normal;"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>客户信息修改</title> </head> <body> <h1>客户信息修改</h1> <!-- 修改数据 和 添加时数据一样吗?多了客户编号 --> <form action="${pageContext.request.contextPath }/updateCustomer" method="post"> <table> <tr> <td>客户编号 </td> <td>${requestScope.customer.id }</span><span style="color:#ff0000;font-size:18px; font-weight: normal;"> </span><span style="font-size:18px; font-weight: normal;"> </span><p><span style="font-size:18px; font-weight: normal;"> <span style="color:#cc33cc;"><input type="hidden" name="id" value="${requestScope.customer.id }" /></span></span><span style="font-size:18px; font-weight: normal; font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-size:18px; font-weight: normal; color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;"><--将id信息隐式保存--></span><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-weight: normal;"><span style="font-size:18px;"> </span><span style="font-size:14px;"></td></span></span></span></p>
<span style="font-weight: normal;"> </tr> <tr> <td><label for="name">客户姓名</label> </td> <td><input type="text" name="name" id="name" value="${requestScope.customer.name }"/> </td> </tr> <tr> <td><label for="gender">性别</label></td> <td> <input type="radio" name="gender" id="male" value="男" <c:if test="${requestScope.customer.gender == '男' }"> checked="checked" </c:if> /><label for="male">男</label> <input type="radio" name="gender" id="female" value="女" <c:if test="${requestScope.customer.gender == '女' }"> checked="checked" </c:if> /><label for="female">女</label> </td> </tr> <tr> <td><label for="birthday">生日</label></td> <td><input type="text" name="birthday" id="birthday" value="${requestScope.customer.birthday }" /></td> </tr> <tr> <td><label for="cellphone">手机号码</label></td> <td><input type="text" name="cellphone" id="cellphone" value="${requestScope.customer.cellphone }"/></td> </tr> <tr> <td><label for="email">邮箱</label></td> <td><input type="text" name="email" id="email" value="${requestScope.customer.email }"/></td> </tr> <tr> <!-- 从请求中customer对象获得 爱好字符串 : 音乐,体育 --> </span><span style="color:#ff0000;"><!-- 如何控制页面多选框 选中 --></span><span style="font-weight: normal;"><span style="color:#ff0000;"> <td><label for="preference">爱好</label></td> <td> <input type="checkbox" name="preference" value="音乐" id="music" </span><span style="color:#6600cc;"><c:if test="${fn:contains(requestScope.customer.preference,'音乐') }"> checked="checked"</span><span style="color:#ff0000;"> </c:if> /><label for="music">音乐</label> <input type="checkbox" name="preference" value="体育" id="sport" </span><span style="color:#6600cc;"><c:if test="${fn:contains(requestScope.customer.preference,'体育') }"> checked="checked"</span><span style="color:#ff0000;"> </c:if> /><label for="sport">体育</label> <input type="checkbox" name="preference" value="读书" id="read" </span><span style="color:#6600cc;"><c:if test="${fn:contains(requestScope.customer.preference,'读书') }"> checked="checked"</span><span style="color:#ff0000;"> </c:if> /><label for="read">读书</label> <input type="checkbox" name="preference" value="旅游" id="travel" </span><span style="color:#6600cc;"><c:if test="${fn:contains(requestScope.customer.preference,'旅游') }"> checked="checked"</span><span style="color:#ff0000;"> </c:if> /><label for="travel">旅游</label></span> </td> </tr> <tr> <td><label for="type">类型</label></td> <td> </span><span style="color:#ff0000;"><!-- 控制选中框选中 checked ,控制下拉框默认值 selected --></span><span style="color: rgb(255, 102, 102); font-weight: normal;"> <select name="type" id="type"> <option value="vip" <c:if test="${requestScope.customer.type == 'vip' }"> selected = "selected" </c:if> >VIP</option> <option value="白金用户" <c:if test="${requestScope.customer.type == '白金用户' }"> selected = "selected" </c:if> >白金用户 </option> <option value="普通用户" <c:if test="${requestScope.customer.type == '普通用户' }"> selected = "selected" </c:if> >普通用户 </option> </select></span><span style="font-weight: normal;"> </td> </tr> <tr> <td><label for="description">客户信息</label></td> <td> <textarea rows="5" cols="60" name="description" id="description" >${requestScope.customer.description }</textarea> </td> </tr> <tr> <td><input type="submit" value="修改" /></td> <td><input type="reset" value="重置" /></td> </tr> </table> </form> </body> </html></span>
在上述页面提交数据之后,将数据在UpdateCustomerServlet中进行封装
<span style="font-weight: normal;">package web; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import service.CustomerService; import vo.Customer; public class UpdateCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 编码设置 request.setCharacterEncoding("utf-8"); // 封装表单信息到javabean Customer customer = new Customer(); try { BeanUtils.populate(customer, request.getParameterMap()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } // 没有完成爱好封装、自己封装 String[] preference = request.getParameterValues("preference"); // 例如:音乐 体育 ------ [音乐,体育] String value = Arrays.toString(preference); value = value.substring(1, value.length() - 1); customer.setPreference(value); // 调用service 修改javabean信息 CustomerService customerService = new CustomerService(); customerService.updateCustomer(customer); </span><span style="color:#ff0000;"><span style="font-weight: normal;">// 跳转到显示客户信息列表 request.getRequestDispatcher("/searchCustomer").forward(request, response); //</span>同样跳转回查询servlet</span><span style="font-weight: normal;"> } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } </span>
将数据传递至业务层,增加修改方法
<span style="font-weight: normal;">/** * 修改客户信息 */ public void updateCustomer(Customer customer) { CustomerDAO customerDAO = new CustomerDAO(); customerDAO.update(customer); } </span>
再由数据层进行具体删除方法实现
// 修改客户信息 public void update(Customer customer) { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "update customer set name=?,birthday=?,gender=?,cellphone=?,email=?,preference=?,type=?,description=? where id=?"; Object[] param = { customer.getName(), customer.getBirthday(), customer.getGender(), customer.getCellphone(), customer.getEmail(), customer.getPreference(), customer.getType(), customer.getDescription(), customer.getId() }; try { queryRunner.update(sql, param); } catch (SQLException e) { e.printStackTrace(); } }
至此数据修改操作完毕
8、分页技术
两种:物理分页、逻辑分页
1)物理分页
依赖数据库语法结构,例如mysql ---- limit Oracle --- rowNum
select * from 表名 limit 开始条数索引,条数 --- 索引从0开始
例如:查询11-20条 select * from customer limit 10,10
使用物理分页 ---- 效率较高
2) 逻辑分页
先查出所有数据,在程序截取需要的数据
使用逻辑分页 --- 效率较低
9、设计分页实现
设计页码格式
|<< << 1,2,3,4,5,6 >> >>|
首页 上一页 1,2,3,4,5,6 下一页 尾页
对客户管理系统进行分页实现
首先进行流程设计分析:
由于客户端页面较为复杂,故先进行后面流程的编写,但要明确需要那些数据来进行传递
currentPage; // 当前页
totalNum; // 总记录条数
totalPageNum; // 总页数
numPerPage = 2; // 每页多少条
List<T> data; //数据集合
首先创建这些数据的封装类
package vo; import java.util.List; /** * 分页类 ,该类定义了分页需要数据 * * @author seawind * */ public class PageData<T> { private int currentPage; // 当前页 private int totalNum; // 总记录条数 private int totalPageNum; // 总页数 private final int numPerPage = 2; // 每页多少条 private List<T> data; public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getTotalNum() { return totalNum; } public void setTotalNum(int totalNum) { this.totalNum = totalNum; } public int getTotalPageNum() { return totalPageNum; } public void setTotalPageNum(int totalPageNum) { this.totalPageNum = totalPageNum; } public List<T> getData() { return data; } public void setData(List<T> data) { this.data = data; } public int getNumPerPage() { return numPerPage; } }
然后在web层进行分页查询的servlet的编写
package web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import service.CustomerService; import vo.Customer; import vo.PageData; /** * 分页查询Serlvet * * @author seawind * */ public class SearchPageCustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获得 页码 --- 当前页 String currentPageStr = request.getParameter("currentPage"); <span style="color:#ff6666;">int currentPage = 1; if (currentPageStr == null) { // 用户没有提交页码 默认页码1 } else { currentPage = Integer.parseInt(currentPageStr); }</span> // 调用业务层 得到分页对象 CustomerService customerService = new CustomerService(); PageData<Customer> pageData = customerService.findByPage(currentPage); // 传递pageData给JSP request.setAttribute("pageData", pageData); request.getRequestDispatcher("/page_list.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
然后传递到业务层 ,编写业务逻辑(调用数据层的实现方法来得到分页后查询到的数据封装对象(当前页,总记录条数,查询到的数据集合))
/** * 分页查询方法 */ public PageData<Customer> findByPage(int currentPage) { CustomerDAO customerDAO = new CustomerDAO(); // 准备PageData需要的所有数据 PageData<Customer> pageData = new PageData<Customer>(); // 1、装入当前页 pageData.setCurrentPage(currentPage); // 2、装入总记录条数 int totalNum = customerDAO.findTotalCount(); pageData.setTotalNum(totalNum); // 3、计算<span style="font-family: Arial, Helvetica, sans-serif;">总记录条数</span> int numPerPage = pageData.getNumPerPage();// 每页多少条 int totalPageNum = (totalNum + numPerPage - 1) / numPerPage; pageData.setTotalPageNum(totalPageNum); // 4、装入分页数据 limit 需要开始页码 、多少页 <span style="color:#ff0000;">int start = (currentPage - 1) * numPerPage; int end = currentPage * numPerPage; List<Customer> customers = customerDAO.findPage(start, numPerPage);</span> pageData.setData(customers); return pageData; }
数据层的具体实现方法:
<span style="font-weight: normal;">// 查询分页数据 public List<Customer> findPage(int start, int len) { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "select * from customer </span><span style="color:#ff0000;font-weight: normal;">limit</span><span style="font-weight: normal;"> ?,?"; //</span><span style="color:#ff0000;">注意limit关键字实现范围查询</span><span style="font-weight: normal;"> Object[] param = { start, len }; try { List<Customer> customers = queryRunner.query(sql, new BeanListHandler<Customer>(Customer.class), param); return customers; } catch (SQLException e) { e.printStackTrace(); } return null; } // 查询总记录数 public int findTotalCount() { QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); String sql = "select <span style="color:#ff0000;">count(*)</span> from customer";//</span><span style="color:#ff0000;">count关键字实现数目统计</span><span style="font-weight: normal;"> long totalCount = 0; try { totalCount = (Long) queryRunner.query(sql, new <span style="color:#ff0000;">ScalarHandler(1)</span>); } catch (SQLException e) { e.printStackTrace(); } return (int) totalCount; } </span>
最后编写客户端分页显示页面page_list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>分页显示客户信息</title> </head> <body> <h1>分页显示数据</h1> <table border="1"> <tr> <th>客户编号</th> <th>客户姓名</th> <th>性别</th> <th>生日</th> <th>手机号码</th> <th>邮箱</th> <th>爱好</th> <th>类型</th> <th>客户信息</th> <th>删除操作</th> <th>修改操作</th> </tr> <c:forEach var="customer" items="${requestScope.pageData.data}"> <tr> <td>${customer.id }</td> <td>${customer.name }</td> <td>${customer.gender }</td> <td>${customer.birthday }</td> <td>${customer.cellphone }</td> <td>${customer.email }</td> <td>${customer.preference }</td> <td>${customer.type }</td> <td>${customer.description }</td> <td><a href="delCustomer?id=${customer.id }">删除</a></td> <td><a href="viewCustomer?id=${customer.id }">修改</a></td> </tr> </c:forEach> <tr> <span style="color:#ff0000;"><td colspan="11" align="right"> <--colspan是对单元格进行合并--> 共有${requestScope.pageData.totalNum } 条记录,共有${requestScope.pageData.totalPageNum } 页 <a href="searchPage?currentPage=1">首页</a> <c:if test="${requestScope.pageData.currentPage!=1}"> <a href="searchPage?currentPage=${requestScope.pageData.currentPage-1}">上一页</a> </c:if> <c:if test="${requestScope.pageData.currentPage==1}"> 上一页 </c:if> <!-- 显示页码 --> <c:set var="start" scope="page" value="${requestScope.pageData.currentPage-5}"></c:set> <c:set var="end" scope="page" value="${requestScope.pageData.currentPage+5}"></c:set> </span><span style="color:#cc66cc;"><c:if test="${requestScope.pageData.currentPage-5<1}"> <%--前面没有5页 --%> <c:set var="start" scope="page" value="1"></c:set> </c:if> <c:if test="${requestScope.pageData.currentPage+5>requestScope.pageData.totalPageNum}"> <%--后面没有5页 --%> <c:set var="end" scope="page" value="${requestScope.pageData.totalPageNum}"></c:set></span><span style="color:#ff0000;"> </c:if> </span><span style="color:#3366ff;"><c:forEach begin="${pageScope.start}" end="${pageScope.end}" step="1" var="i" > <c:if test="${requestScope.pageData.currentPage==i}"> ${i } </c:if> <c:if test="${requestScope.pageData.currentPage!=i}"> <a href="searchPage?currentPage=${i }">${i }</a> </c:if> </c:forEach></span><span style="color:#ff0000;"> <!-- --> <c:if test="${requestScope.pageData.currentPage!=requestScope.pageData.totalPageNum}"> <a href="searchPage?currentPage=${requestScope.pageData.currentPage+1}">下一页</a> </c:if> <c:if test="${requestScope.pageData.currentPage==requestScope.pageData.totalPageNum}"> 下一页 </c:if> <a href="searchPage?currentPage=${requestScope.pageData.totalPageNum }">尾页</a> </td> </tr></span> </table> </body> </html>
彩色部分为页数条目的实现代码,其中实现过程较为复杂,可以慢慢进行分析。
至此分页效果做完。
10、JS表单校验
非空、长度、正则表达式
对即将提交的表单数据进行校验,看是否符合规定格式与内容
对addlist.jsp进行校验功能添加
<span style="font-weight: normal;"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>客户信息增加</title> </span><span style="color: rgb(255, 102, 102); font-weight: normal;"><script type="text/javascript"> function checkForm(){ // 校验表单数据,获得表单数据 document.getElementById // 客户姓名不能为空 var name = document.getElementById("name").value; if(name==""){ alert("客户姓名不能为空!"); return false; } // 判断手机号码长度11位 var cellphone = document.getElementById("cellphone").value; if(cellphone.length != 11){ alert("手机号码必须满足11位!"); return false; } // 判断邮箱符合格式 @itcast.cn结尾 ---- math匹配正则表达式 var email = document.getElementById("email").value; if(</span><span style="color:#ff0000;">email.match("^[a-z0-9][email protected]\\.cn$")==null</span><span style="color: rgb(255, 102, 102); font-weight: normal;">){ alert("邮箱格式不正确!"); return false; } } </script></span><span style="font-weight: normal;"> </head> <body> <h1>客户信息增加</h1> <form action="${pageContext.request.contextPath }/addCustomer" method="post" </span><span style="color:#ff0000;">onsubmit="return checkForm()"</span><span style="font-weight: normal;">> <table> <tr> <td><label for="name">客户姓名</label> </td> <td><input type="text" name="name" id="name" /> </td> </tr> <tr> <td><label for="gender">性别</label></td> <td> <input type="radio" name="gender" id="male" value="男"/><label for="male">男</label> <input type="radio" name="gender" id="female" value="女"/><label for="female">女</label> </td> </tr> <tr> <td><label for="birthday">生日</label></td> <td><input type="text" name="birthday" id="birthday" /></td> </tr> <tr> <td><label for="cellphone">手机号码</label></td> <td><input type="text" name="cellphone" id="cellphone" /></td> </tr> <tr> <td><label for="email">邮箱</label></td> <td><input type="text" name="email" id="email" /></td> </tr> <tr> <td><label for="preference">爱好</label></td> <td> <input type="checkbox" name="preference" value="音乐" id="music" /><label for="music">音乐</label> <input type="checkbox" name="preference" value="体育" id="sport" /><label for="sport">体育</label> <input type="checkbox" name="preference" value="读书" id="read" /><label for="read">读书</label> <input type="checkbox" name="preference" value="旅游" id="travel" /><label for="travel">旅游</label> </td> </tr> <tr> <td><label for="type">类型</label></td> <td> <select name="type" id="type"> <option value="vip">VIP</option> <option value="白金用户">白金用户 </option> <option value="普通用户">普通用户 </option> </select> </td> </tr> <tr> <td><label for="description">客户信息</label></td> <td> <textarea rows="5" cols="60" name="description" id="description"></textarea> </td> </tr> <tr> <td><input type="submit" value="添加" /></td> <td><input type="reset" value="重置" /></td> </tr> </table> </form> </body> </html></span>
彩色部分代码为增添的代码,通过js来对用户名是否为空,手机号码与邮箱是否符合格式进行了校验。
至此,客户管理系统 案例完成。