为了巩固开发的流程,咱们再拿一个客户关系管理系统来练手...!javascript
咱们完成的就是下面的项目!php
CREATE TABLE customer (
id VARCHAR(40) PRIMARY KEY,
name VARCHAR(20) NOT NULL,
gender VARCHAR(10) NOT NULL,
birthday DATE,
cellphone VARCHAR(30) NOT NULL,
email VARCHAR(30),
preference VARCHAR(200),
type VARCHAR(20),
description VARCHAR(255)
);
复制代码
开发实体十分简单,对照着数据库的表就好了!html
private String id;
private String name ;
private String gender ;
private Date birthday ;
private String cellphone ;
private String eamil ;
private String preference ;
private String type ;
private String description;
//....各类setter、getter
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
<named-config name="oracle">
<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
<property name="jdbcUrl">jdbc:oracle:thin:@//localhost:1521/事例名...</property>
<property name="user">用户名</property>
<property name="password">密码</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
复制代码
public class Utils2DB {
private static ComboPooledDataSource comboPooledDataSource = null;
static {
//它会自动寻找配置文件,节点为mysql的数据库(默认就是Mysql)
comboPooledDataSource = new ComboPooledDataSource();
}
public static DataSource getDataSource() {
return comboPooledDataSource ;
}
public static Connection connection() {
try {
return comboPooledDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("数据库初始化失败了!");
}
}
}
复制代码
public class WebUtils {
public static String makeId() {
return UUID.randomUUID().toString();
}
}
复制代码
DAO应该提供增长客户和查询用户的功能java
public void addCustomer(Customer customer) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "INSERT INTO customer (id,name, gender, birthday, cellphone, preference, type, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?)";
//获得用户传递进来的数据
String id = customer.getId();
String name = customer.getName();
String gender = customer.getGender();
String cellphone = customer.getCellphone();
String email = customer.getEmail();
String preference = customer.getPreference();
String type = customer.getType();
String description = customer.getDescription();
//对于日期,要转换一下
Date date = customer.getBirthday();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String birthday = simpleDateFormat.format(date);
try {
//向数据库插入数据
queryRunner.update(sql, new Object[]{id, name, gender, birthday, cellphone, email, preference, type, description});
//插入记录成功!
} catch (SQLException e) {
//若是出现了异常,就抛出Dao异常吧(自定义的异常)
e.printStackTrace();
throw new DaoException("添加用户出错了!");
}
}
复制代码
写完一个功能,不要急着去写其余的功能,先测试一下!mysql
@Test
public void add() {
//为了测试的方便,直接使用构造函数了!
Customer customer = new Customer("1", "zhongfucheng", "男", new Date(), "1234", "aa@sina.com", "打代码", "高贵的用户", "我是个好人");
CustomerDao customerDao = new CustomerDao();
customerDao.addCustomer(customer);
}
复制代码
解决的办法,看我另一篇博文:https://zhongfucheng.bitcron.com/post/jie-jue-cuo-wu/mysqlzhong-wen-luan-ma程序员
将全部的客户查询出来就好了!web
//获得全部的用户
public List<Customer> getAll() {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM customer";
try {
List<Customer> customers = (List<Customer>) queryRunner.query(sql, new BeanListHandler(Customer.class));
//若是集合大于个数大于0,就返回集合,不大于0,就返回null
return customers.size() > 0 ? customers : null;
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("获取全部的用户出错了!");
}
}
复制代码
@Test
public void find() {
CustomerDao customerDao = new CustomerDao();
List<Customer> customers = customerDao.getAll();
for (Customer customer : customers) {
System.out.println(customer.getName());
}
}
复制代码
修改用户信息首先要知道用户的信息,在web端,只有id能惟一标识用户,咱们须要经过id,获取用户所有信息(也就是Customer对象)sql
public Customer find(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM customer WHERE id = ?";
try {
Customer customer = (Customer) queryRunner.query(sql, new BeanHandler(Customer.class), new Object[]{id});
return customer;
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("查找用户失败了");
}
}
复制代码
修改用户都是外边传递个对象进来,Dao层取出对象的数据,从而对数据库的数据进行修改!数据库
public void update(Customer customer) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "UPDATE customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? WHERE id = ?";
try {
queryRunner.update(sql, new Object[]{customer.getName(), customer.getGender(), customer.getBirthday(),customer.getCellphone(), customer.getEmail(), customer.getPreference(), customer.getType(), customer.getDescription(), customer.getId()});
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("更新失败");
}
}
复制代码
@Test
public void update() {
CustomerDao customerDao = new CustomerDao();
//咱们已经知道了某id,经过id获取获得用户信息(Customer)
String id = "043f7cce-c6f1-4155-b688-ba386cae1636";
Customer customer = customerDao.find(id);
//修改用户信息
customer.setName("看完博客要点赞");
customerDao.update(customer);
}
复制代码
public void delete(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "DELETE from customer WHERE id = ?";
try {
queryRunner.update(sql, new Object[]{id});
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("删除用户失败了");
}
}
复制代码
@Test
public void delete() {
CustomerDao customerDao = new CustomerDao();
//咱们已经知道了某id,经过id删除数据库中的记录
String id = "043f7cce-c6f1-4155-b688-ba386cae1636";
customerDao.delete(id);
}
复制代码
数据库已经查询不到id为043f7cce-c6f1-4155-b688-ba386cae1636的记录了!编程
public class BusinessService {
CustomerDao customerDao = new CustomerDao();
public List<Customer> getAll() {
return customerDao.getAll();
}
public void addCustomer(Customer customer) {
customerDao.addCustomer(customer);
}
public void deleteCustomer(String id) {
customerDao.delete(id);
}
public void updateCustomer(Customer customer) {
customerDao.update(customer);
}
public Customer findCustomer(String id) {
return customerDao.find(id);
}
}
复制代码
//直接跳转到显示增长用户页面的jsp
request.getRequestDispatcher("/WEB-INF/addCustomer.jsp").forward(request, response);
复制代码
<form action="${pageContext.request.contextPath}/addCustomerController">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="gender" value="female">女
<input type="radio" name="gender" value="male">男
</td>
</tr>
<tr>
<td>生日:</td>
<td>
<select id="year">
<option value="1900">1900</option>
</select>
<select id="month">
<option value="01">01</option>
</select>
<select id="day">
<option value="01">01</option>
</select>
</td>
</tr>
<tr>
<td>电话号码:</td>
<td><input type="text" name="cellphone"></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="checkbox" name="hobbies" value="唱歌">唱歌
<input type="checkbox" name="hobbies" value="跳舞">跳舞
<input type="checkbox" name="hobbies" value="打代码">打代码
</td>
</tr>
<tr>
<td>客户类型</td>
<td>
<input type="radio" name="type" value="VIP">VIP
<input type="radio" name="type" value="普通客户">普通客户
<input type="radio" name="type" value="黑名单客户">黑名单客户
</td>
</tr>
<tr>
<td>描述</td>
<td>
<textarea name="description" cols="30" rows="10"></textarea>
</td>
</tr>
<tr>
<td><input type="submit" value="增添客户"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
复制代码
咱们发现,在日期的下拉框中,只有一个数据(由于咱们在value中只写了一个数据)
要想在下拉框中能够选择不少的数据,那么value的值就不能单单只有一个。固然了,也不可能在JSP页面中写下面的代码
<option value="1900">1900</option>
<option value="1901">1900</option>
<option value="1902">1900</option>
<option value="1903">1900</option>
复制代码
咱们用javaScript生成下拉框的数据就好了!!
function makeYear() {
//获得下拉框的控件
var year = document.getElementById("year");
//要想下拉框有更多的数据,就须要有更多的option控件
//js获取获得年份是getFullYear(),单单的getYear()只是获取两位数
for (var i=1901; i<= new Date().getFullYear(); i++) {
//生成option控件
var option = document.createElement("option");
//option控件的值和文本内容为循环生成的年分!
option.value = i;
option.innerText = i;
//将生成option控件绑定到select控件上
year.appendChild(option);
}
}
复制代码
function makeMonth() {
var month = document.getElementById("month");
for (var i = 2; i <= 12; i++) {
var option = document.createElement("option");
if (i < 10) {
option.value = '0' + i;
option.innerText = '0' + i;
} else {
option.value = i;
option.innerText = i;
}
month.appendChild(option);
}
}
function makeDay() {
var day = document.getElementById("day");
for(var i=2;i<=12;i++)
{
var option = document.createElement("option");
if(i<10)
{
option.value = '0' + i;
option.innerText = '0' + i;
}else{
option.value = i;
option.innerText = i;
}
day.appendChild(option);
}
}
复制代码
在JSP页面中导入javascript文件
注意:javasrcipt文件不能放在WEB-INF下面!!!!不然是获取不到的!!!
<script type="text/javascript" src="${pageContext.request.contextPath}/customer.js" ></script>
复制代码
function pageInit() {
makeYear();
makeMonth();
makeDay();
}
<body onload="pageInit()">
复制代码
表单的数据很是多,毫无疑问,咱们会使用BeanUtils来将数据封装到Bean对象中!
对于表单的数据,仍是有些杂乱的。表单中日期的年月日是分开的,咱们要么在客户端将年月日的数据拼凑起来,要么在服务器端将年月日拼凑起来!同理,客户的喜爱可能不仅仅有一个,但在Customer对象中,喜爱单单用一个String类型来表示的。咱们也要把客户的喜爱拼凑起来。
显然,在客户端用javaScript作拼凑是很是方便的!
function makeBirthday() {
//获取下拉框的数据,把数据拼凑成日期字符串
var year = document.getElementById("year");
var month = document.getElementById("month");
var day = document.getElementById("day");
var birthday = year + "-" + month + "-" + day;
//想要将拼凑完的字符串提交给服务器,用隐藏域就好了
var input = document.createElement("input");
input.type = "hidden";
input.value = birthday;
input.name = "birthday";
//将隐藏域绑定在form下【为了方便,在form中设置id,id名字为form】
document.getElementById("form").appendChild(input);
}
function makePreference() {
//获取喜爱的控件
var hobbies = document.getElementsByName("hobbies");
//定义变量,记住用户选中的选项
var preference = "";
//遍历喜爱的控件,看用户选上了什么!
for (var i = 0; i < hobbies.length; i++) {
if (hobbies[i].checked == true) {
preference += hobbies[i].value + ",";
}
}
//刚才拼凑的时候,最后一个逗号是多余的,咱们要把它去掉
preference = preference.substr(0, preference.length - 1);
//也是用隐藏域将数据带过去给服务器
var input = document.createElement("input");
input.type = "hidden";
input.value = preference;
input.name = "preference";
//将隐藏域绑定到form表单上
document.getElementById("form").appendChild(input);
}
复制代码
function makeForm() {
makeBirthday();
makePreference();
return true;
}
<form action="${pageContext.request.contextPath}/addCustomerController" id="form" onsubmit=" return makeForm()" method="post">
复制代码
public static <T> T request2Bean(HttpServletRequest httpServletRequest, Class<T> aClass) {
try {
//获取Bean的对象
T bean = aClass.newInstance();
//获取表单中全部的名字
Enumeration enumeration = httpServletRequest.getParameterNames();
//遍历表单提交过来的名字
while (enumeration.hasMoreElements()) {
//每一个名字
String name = (String) enumeration.nextElement();
//获取获得值
String value = httpServletRequest.getParameter(name);
//若是用户提交的数据不为空,那么将数据封装到Bean中
if (!value.equals("") && value != null) {
BeanUtils.setProperty(bean, name, value);
}
}
return bean;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("封装数据到Bean中,失败了!");
}
}
复制代码
//将表单的数据弄到Bean对象中
Customer customer = WebUtils.request2Bean(request, Customer.class);
try {
//调用BusinessService层的方法,添加客户
BusinessService businessService = new BusinessService();
businessService.addCustomer(customer);
//若是执行到这里,说明成功了,若是被catch了,说明失败了。
request.setAttribute("message", "添加成功!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "添加失败");
}
request.getRequestDispatcher("/message.jsp").forward(request, response);
复制代码
//跳转到显示客户界面信息的jsp
request.getRequestDispatcher("/WEB-INF/lookCustomer.jsp").forward(request, response);
复制代码
<c:if test="${empty(list)}">
对不起,尚未任何客户的信息!
</c:if>
<c:if test="${!empty(list)}">
<table border="1px">
<tr>
<td>用户名:</td>
<td>密码:</td>
<td>性别:</td>
<td>生日:</td>
<td>电话号码:</td>
<td>邮箱:</td>
<td>类型:</td>
<td>描述:</td>
</tr>
<c:forEach items="${list}" var="customer">
<tr>
<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>
</table>
</c:if>
复制代码
采用分贞技术,让界面更加好看!
index页面:
<frameset rows="25%,*">
<frame src="${pageContext.request.contextPath }/head.jsp" name="head">
<frame src="${pageContext.request.contextPath }/body.jsp" name="body">
</frameset>
复制代码
head页面:
<body style="text-align: center;">
<h1>客户管理系统!</h1>
<a href="${pageContext.request.contextPath}/AddCustomer" target="body">增添客户</a>
<a href="${pageContext.request.contextPath}/LookCustomer" target="body">查看客户</a>
</body>
复制代码
body页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
复制代码
如今问题来了,若是咱们客户信息有很是很是地多,咱们不可能把客户信息所有都挤在同一个页面上,若是咱们这样作的话,网页的长度就会很是的长!
因而乎,咱们就须要用到了分页的技术**,对于分页技术基础的讲解,在我另外一篇博文中有介绍:** https://zhongfucheng.bitcron.com/post/jdbc/jdbcdi-si-pian-shu-ju-ku-lian-jie-chi-dbutilskuang-jia-fen-ye
看完上篇博文,咱们知道,首先要作的就是:明确分页技术中须要用到的4个变量的值!
查询总记录数也就是查询数据库表的记录有多少条,这是关于对数据库数据的操做,因此确定是在dao层作!
public Long getTotalRecord() {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM customer";
try {
//获取查询的结果
Long l = (Long) queryRunner.query(sql, new ScalarHandler());
return l;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("查询总记录数失败了!");
}
}
复制代码
获取分页的数据也是查询数据库的记录,这也是关于对数据库的操做,因此也是在Dao层作的!
/*查询分页数据*/
//获取分页的数据是须要start和end两个变量的【从哪条开始取,取到哪一条】
public List<Customer> getPageData(int start, int end) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM customer LIMIT ?,?";
try {
List<Customer> customers = (List<Customer>) queryRunner.query(sql, new BeanListHandler(Customer.class), new Object[]{start, end});
return customers;
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("获取分页数据失败了!");
}
}
复制代码
如今咱们已经能够知道总记录数了,对于其余3个变量(每页显示记录数【由程序员来指定】,当前是多少页【由用户来指定】,总页数【由总记录数和每页显示记录数来算数来的】)
如今要分析的是,这些变量应该放在哪里呢???所有放在Dao层??所有放在Dao层是能够实现功能的,可是,这样MVC结构就被破坏掉了(Dao层只用来对数据进行CRUD操做,4个变量存在Dao层,是不合理的)
最好的作法是这样的:建立一个实体Page,将分页用到的信息所有封装在Page中实现!Page就表明着分页的数据这样就很是符合面向对象的思想了!
①:建立Page类
//保存着分页的数据
private List<Customer> list;
//总记录数
private long totalRecord;
//每页显示记录数,这里我规定每页显示3条
private int linesize = 3;
//总页数
private int totalPageCount;
//当前显示的页数
private long currentPageCount;
//...各类的setter、getter
复制代码
②:BusinessService应该提供获取分页数据的服务
//既然Page对象表明是分页数据,那么返回Page对象便可!
//web层应该传入想要看哪一页数据的参数!
public Page getPageData(String currentPageCount) {
Page page = new Page();
//获取数据库中有多少条记录,并封装到Page对象中
Long totalRecord = customerDao.getTotalRecord();
page.setTotalRecord(totalRecord);
//算出总页数,并封装到Page对象中
int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
page.setTotalPageCount(totalPagecount);
int start ;
int end = page.getLinesize();
//如今又分两种状况了,若是传递进来的参数是null的,那么说明外界是第一次查询的
if (currentPageCount == null) {
//第一次查询,就应该设置当前页数是第一页
page.setCurrentPageCount(1);
start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());
List<Customer> customers = customerDao.getPageData(start, end);
page.setList(customers);
} else {
//若是不是第一次,就把外界传递进来的页数封装到Page对象中
page.setCurrentPageCount(Long.parseLong(currentPageCount));
start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());
List<Customer> customers = customerDao.getPageData(start, end);
page.setList(customers);
}
return page;
}
复制代码
③:web层调用BusinessService层的功能,获取获得Page对象
//获取用户想要看的页数,若是是第一次,那确定为null
String currentPageCount = request.getParameter("currentPageCount");
//调用BusinessService的方法,获取获得全部客户信息
BusinessService businessService = new BusinessService();
Page page = businessService.getPageData(currentPageCount);
//把客户信息带过去给jsp页面
request.setAttribute("page", page);
//跳转到显示客户界面信息的jsp
request.getRequestDispatcher("/WEB-INF/lookCustomer.jsp").forward(request, response);
复制代码
④:在JSP页面中,使用EL表达式获取到Page对象,从而输出数据
<c:forEach items="${page.list}" var="customer">
<tr>
<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>
复制代码
⑤:在JSP页面中显示页码,同时把码数绑定到超连接去!
<%--提供页数的界面--%>
<c:forEach var="pageNum" begin="1" end="${page.totalPageCount}">
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
${pageNum}
</a>
</c:forEach>
复制代码
通常的分页不只仅只有页码给你,还有上一步和下一步。咱们在JSP页面上也能添加这样的功能,其实这是很是简单的!
<%--若是当前的页码大于1,才显示上一步--%>
<c:if test="${page.currentPageCount>1}">
<%--把传递过去的页码-1就好了--%>
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
上一步
</a>
</c:if>
<%--若是当前的页码小于总页数,才显示下一步--%>
<c:if test="${page.currentPageCount<page.totalPageCount}">
<%--把传递过去的页码-1就好了--%>
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
下一步
</a>
</c:if>
复制代码
当前页数是:[${page.currentPageCount}]
总页数是:${page.totalPageCount}
总记录数是:${page.totalRecord}
复制代码
<input type="text" id="currentPageCount">
<input type="button" value="跳转">
复制代码
咱们如今要作的就是:怎么样才能输入框输入内容,而后点击跳转按钮,将输入框的数据发送到Servlet上,而后实现跳转到某页上功能
明显地,咱们确定要使用JavaScript代码!
<script type="text/javascript">
/*既然写上了JavaScript代码了,就顺便验证输入框输入的数据是否合法吧*/
function goPage() {
/*获取输入框控件*/
var input = document.getElementById("currentPageCount");
/*获取输入框的数据*/
var value = input.value;
if(value==null || value==""){
alert("请输入页码");
return false;
}
if(!value.match("\\d+")){
alert("请输入数字");
return false;
}
if(value<1 || value>${page.totalPageCount}){
alert("请输入合法数据");
return false ;
}
window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
}
</script>
复制代码
为何咱们要记录JSP页面的开始页和结束页呢?通过上面层层地优化,咱们感受不出有什么问题了。那是由于数据量太少!
咱们试着多添加点记录进数据库,再回来看看!
从上面的图咱们能够发现**页数有多少,JSP页面就显示多少!**这明显不合理的,若是有100页也显示100页吗?
咱们作一个规定,一次只能显示10页的数据。那么显示哪10页呢?这又是一个问题了,若是咱们在看第11页的数据,应该显示的是第7到第16页的数据(显示11附近的页数),咱们在看第2页的数据,应该显示第1到第10页的数据。用户想要看的页数是不明确的,咱们显示附近的页数也是不明确的!。咱们应该把用户想要看的页数记录下来,而后根据逻辑判断,显示附近的页数
咱们显示页数的代码是这样的:
很明显,咱们只要控制了begin和end中的数据,就控制显示哪10页了!
①在Page类中多定义两个成员变量
//记录JSP页面开始的页数和结束的页数
private int startPage;
private int endPage;
//Setter,Getter方法
复制代码
②开始页数和结束页数受用户想看的页数影响,在BusinessService的getPageData()加入下面的逻辑
//第一次访问
page.setStartPage(1);
page.setEndPage(10);
//不是第一次访问
if (page.getCurrentPageCount() <= 10) {
page.setStartPage(1);
page.setEndPage(10);
} else {
page.setStartPage((int) (page.getCurrentPageCount() - 4));
page.setEndPage((int) (page.getCurrentPageCount() + 5));
//若是由于加减角标越界了,那么就设置最前10页,或者最后10页
if (page.getStartPage() < 1) {
page.setStartPage(1);
page.setEndPage(10);
}
if (page.getEndPage() > page.getTotalPageCount()) {
page.setEndPage(page.getTotalPageCount());
page.setStartPage(page.getTotalPageCount() - 9);
}
}
复制代码
③:在JSP显示页数时,获取获得开始页和结束页就好了
<%--提供页数的界面--%>
<c:forEach var="pageNum" begin="${page.startPage}" end="${page.endPage}">
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
[${pageNum}]
</a>
</c:forEach>
复制代码
咱们再回头看看BusinessService中获取分页数据的代码:
//既然Page对象表明是分页数据,那么返回Page对象便可!
//web层应该传入想要看哪一页数据的参数!
public Page getPageData(String currentPageCount) {
Page page = new Page();
//获取数据库中有多少条记录,并封装到Page对象中
Long totalRecord = customerDao.getTotalRecord();
page.setTotalRecord(totalRecord);
//算出总页数,并封装到Page对象中
int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
page.setTotalPageCount(totalPagecount);
int start ;
int end = page.getLinesize();
//如今又分两种状况了,若是传递进来的参数是null的,那么说明外界是第一次查询的
if (currentPageCount == null) {
//第一次查询,就应该设置当前页数是第一页
page.setCurrentPageCount(1);
page.setStartPage(1);
page.setEndPage(10);
start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());
List<Customer> customers = customerDao.getPageData(start, end);
page.setList(customers);
} else {
//若是不是第一次,就把外界传递进来的页数封装到Page对象中
page.setCurrentPageCount(Long.parseLong(currentPageCount));
start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());
if (page.getCurrentPageCount() <= 10) {
page.setStartPage(1);
page.setEndPage(10);
} else {
page.setStartPage((int) (page.getCurrentPageCount() - 4));
page.setEndPage((int) (page.getCurrentPageCount() + 5));
//若是由于加减角标越界了,那么就设置最前10页,或者最后10页
if (page.getStartPage() < 1) {
page.setStartPage(1);
page.setEndPage(10);
}
if (page.getEndPage() > page.getTotalPageCount()) {
page.setEndPage(page.getTotalPageCount());
page.setStartPage(page.getTotalPageCount() - 9);
}
}
List<Customer> customers = customerDao.getPageData(start, end);
page.setList(customers);
}
return page;
}
复制代码
太太太太太tm复杂,太太太太tm长了!!!!!咱们BusinessService要作的仅仅是调用Dao层的功能,为web层提供数据,但咱们在方法中使用大量了逻辑判断,并且这些逻辑判断都是属于Page类的!
明确一下:只有获取数据库总记录数是在BusinessService中作的,其余的数据变量都是应该在Page类中完成!
在BusinessService获取了总记录数以后,咱们要对其余变量进行初始化(根据总记录数,用户想要看哪一页的数据),算出其余的数据(JSP记录开始页数、结束页数、总页数等等),最好的办法就是经过Page的构造函数来实现初始化!
public Page getPageData2(String currentPageCount) {
//获取获得总记录数
Long totalPageCount = customerDao.getTotalRecord();
if (currentPageCount == null) {
//若是是第一次,那么就将用户想看的页数设置为1
Page page = new Page(1, totalPageCount);
List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());
page.setList(customers);
return page;
} else {
//若是不是第一次,就将获取获得的页数传递进去
Page page = new Page(Integer.parseInt(currentPageCount), totalPageCount);
List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());
page.setList(customers);
return page;
}
}
复制代码
public Page(int currentPageCount, long totalRecord) {
//将传递进来的currentPageCount初始化
this.currentPageCount = currentPageCount;
//总页数
totalPageCount = (int) (totalRecord % linesize == 0 ? totalRecord / linesize : totalRecord / linesize + 1);
//总记录数
this.totalRecord = totalRecord;
//开始取数据的位置
startIndex = (currentPageCount - 1) * linesize;
//若是当前页小于10,那么开始页为1,结束页为10就好了
if (this.currentPageCount <= 10) {
this.startPage = 1;
this.endPage = 10;
} else {
startPage = this.currentPageCount - 4;
endPage = this.currentPageCount + 5;
//加减后页数越界的状况
if (startPage < 1) {
this.startPage = 1;
this.endPage = 10;
}
if (endPage > totalPageCount) {
this.startPage = this.currentPageCount - 9;
this.endPage = this.totalPageCount;
}
}
}
复制代码
分页的显示页面都是永恒不变的,咱们能够把代码重构成一个jsp,须要用到分页显示页面的地方,就包含进去就好了!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--显示当前页数--%>
当前页数是:[${page.currentPageCount}]
<%--若是当前的页码大于1,才显示上一步--%>
<c:if test="${page.currentPageCount>1}">
<%--把传递过去的页码-1就好了--%>
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
上一步
</a>
</c:if>
<%--提供页数的界面--%>
<c:forEach var="page" begin="${page.startPage}" end="${page.endPage}">
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page}">
[${page}]
</a>
</c:forEach>
<%--若是当前的页码小于总页数,才显示下一步--%>
<c:if test="${page.currentPageCount<page.totalPageCount}">
<%--把传递过去的页码-1就好了--%>
<a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
下一步
</a>
</c:if>
<input type="text" id="currentPageCount">
<input type="button" value="跳转" onclick="goPage()">
总页数是:${page.totalPageCount}
总记录数是:${page.totalRecord}
<script type="text/javascript">
/*既然写上了JavaScript代码了,就顺便验证输入框输入的数据是否合法吧*/
function goPage() {
/*获取输入框控件*/
var input = document.getElementById("currentPageCount");
/*获取输入框的数据*/
var value = input.value;
if(value==null || value==""){
alert("请输入页码");
return false;
}
if(!value.match("\\d+")){
alert("请输入数字");
return false;
}
if(value<1 || value>${page.totalPageCount}){
alert("请输入合法数据");
return false ;
}
window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
}
</script>
复制代码
用须要用到的地方,导入便可!
<jsp:include page="page.jsp"></jsp:include>
复制代码
为了作到更好的通用性,处理分页数据的url应该由Servlet传进去给Page类,让Page类封装起来!要使用的时候,再用Page取出来就好了。
下面写法已经固定了,不够灵活!也就是说,下面的url地址不该该写死的
${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}
复制代码
咱们能够这样作:
String servletName = this.getServletName();
//调用BusinessService的方法,获取获得全部客户信息
BusinessService businessService = new BusinessService();
//把Servlet的url也传递进去
Page page = businessService.getPageData2(currentPageCount, request.getContextPath() + "/" + servletName);
复制代码
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
复制代码
page.setUrl(url);
复制代码
咱们在jsp页面跳转处处理分页数据的Servlet上,就再不用写死了。直接用Page对象中获取出来就好了!
<%--把传递过去的页码-1就好了--%>
<a href="${page.url}?currentPageCount=${page.currentPageCount-1}">
上一步
</a>
复制代码
在查询jsp页面上,增添删除和修改的操做连接!
超连接绑定要删除用户的id,带过去给Controller
<a href="${pageContext.request.contextPath}/DeleteCustomer?id=${customer.id}">删除</a>
复制代码
controller的代码也十分简单:
String id = request.getParameter("id");
//调用BusinessService层的功能,就能够完成删除操做了
BusinessService businessService = new BusinessService();
businessService.deleteCustomer(id);
复制代码
删除客户记录也是一件很是重要的事情,应该提供JavaSrcript代码询问是否要真的删除
在超连接控件上绑定事件!
<a href="${pageContext.request.contextPath}/DeleteCustomer?id=${customer.id}" onclick=" return sureDelete()">删除</a>
复制代码
function sureDelete() {
var b = window.confirm("你肯定要删除吗?");
if(b) {
return true;
}else {
return false;
}
}
复制代码
测试:
修改操做的流程是这样的:点击修改超连接,跳转到该用户的详细信息页面,在详细信息页面中修改数据,再提交修改!【跳转到用户详细信息页面时,用户的id还在的,在提交数据的时候,记得把id也给到服务器,【id是不包含在表单中的,要咱们本身提交过去】!】
<a href="${pageContext.request.contextPath}/UpdateCustomerUI?=${customer.id}">修改</a>
复制代码
String id = request.getParameter("id");
BusinessService businessService = new BusinessService();
//经过id获取获得用户的详细信息
Customer customer = businessService.findCustomer(id);
request.setAttribute("customer", customer);
//跳转到显示用户详细信息的jsp页面上
request.getRequestDispatcher("/WEB-INF/customerInformation").forward(request, response);
复制代码
想要日期可以选择,记得导入JavaScript代码,响应事件!
注意:在显示页面上,必定要把id传递过去给处理表单的Servlet,否则服务器是不知道你要修改哪一条数据的!
<head>
<title>用户详细信息</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/customer.js"> </script>
</head>
<body onload="pageInit()">
<form action="${pageContext.request.contextPath}/updateCustomer?id=${customer.id}" method="post" onsubmit="makeForm()">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input type="text" name="name" value="${customer.name}"></td>
</tr>
<tr>
<td>性别</td>
<td><input type="radio" name="gender" value="male" ${customer.gender=='male'?'checked':''}>男
<input type="radio" name="gender" value="female"${customer.gender=='female'?'checked':''}>女
</td>
</tr>
<tr>
<td>生日</td>
<td>
<select id="year">
<option value="${fn:split(customer.birthday,'-')[0]}">${fn:split(customer.birthday,'-')[0]}</option>
</select>
<select id="month">
<option value="${fn:split(customer.birthday,'-')[1]}">${fn:split(customer.birthday,'-')[1]}</option>
</select>
<select id="day">
<option value="${fn:split(customer.birthday,'-')[2]}">${fn:split(customer.birthday,'-')[2]}</option>
</select>
</td>
</tr>
<tr>
<td>电话号码:</td>
<td><input type="text" name="cellphone" value="${customer.cellphone}"></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="text" name="email"value="${customer.email}"></td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="checkbox" name="hobbies" value="唱歌"${fn:contains(customer.preference, '唱歌')==true?'checked':''}>唱歌
<input type="checkbox" name="hobbies" value="跳舞"${fn:contains(customer.preference, '跳舞')==true?'checked':''}>跳舞
<input type="checkbox" name="hobbies" value="打代码"${fn:contains(customer.preference, '打代码')==true?'checked':''}>打代码
</td>
</tr>
<tr>
<td>客户类型</td>
<td>
<input type="radio" name="type" value="VIP" ${customer.type=='VIP'?'checked':''}>VIP
<input type="radio" name="type" value="普通客户"${customer.type=='普通客户'?'checked':''}>普通客户
<input type="radio" name="type" value="黑名单客户"${customer.type=='黑名单客户'?'checked':''}>黑名单客户
</td>
</tr>
<tr>
<td>描述</td>
<td>
<textarea name="description" cols="30" rows="10">${customer.description}</textarea>
</td>
</tr>
<tr>
<td><input type="submit" value="肯定修改"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
复制代码
效果:
//将数据封装到Bean中
Customer customer = WebUtils.request2Bean(request, Customer.class);
//将id封装到Customer对象中!!!不要忘了id!!!在表单中获取到的数据是没有id的!!!!!记得!!!!
customer.setId(request.getParameter("id"));
//调用Service层的方法,实现修改
BusinessService businessService = new BusinessService();
businessService.updateCustomer(customer);
//修改为功就跳回查看客户界面
request.getRequestDispatcher("/LookCustomer").forward(request, response);
复制代码
若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章的同窗,想要获取更多的Java资源的同窗,能够关注微信公众号:Java3y