項(xiàng)目開始時(shí)間:2018年4月8日14:37:47
項(xiàng)目完成時(shí)間:2018年4月9日10:03:30
技術(shù)準(zhǔn)備
這個(gè)項(xiàng)目是自己用于鞏固 J2EE 相關(guān)知識(shí)的練手項(xiàng)目,非常簡(jiǎn)單,但是相關(guān)的功能卻非常實(shí)用,所以在這里分享一下
為了完成這個(gè)項(xiàng)目蒙袍,需要掌握如下技術(shù):
- Java
基礎(chǔ)知識(shí) - 前端:
HTML, CSS, JAVASCRIPT, JQUERY - J2EE:
Tomcat, Servlet, JSP, Filter - 數(shù)據(jù)庫:
MySQL
開發(fā)流程
項(xiàng)目雖然很簡(jiǎn)單,很小,但是為了開發(fā)的有條不紊玩郊,還是按照商業(yè)項(xiàng)目的開發(fā)來完成。
① 需求分析
首先要確定要做哪些功能
- 使用數(shù)據(jù)庫來保存數(shù)據(jù)
- 能增刪改查學(xué)生的信息(學(xué)號(hào)枉阵,名稱译红,年齡,性別兴溜,出生日期)
② 表結(jié)構(gòu)設(shè)計(jì)
根據(jù)需求侦厚,那么只需要一個(gè) student 表就能夠完成功能了。
-
創(chuàng)建數(shù)據(jù)庫:student
將數(shù)據(jù)庫編碼格式設(shè)置為 UTF-8 拙徽,便于存取中文數(shù)據(jù)
DROP DATABASE IF EXISTS student;
CREATE DATABASE student DEFAULT CHARACTER SET utf8;
-
創(chuàng)建學(xué)生表:student
不用學(xué)生學(xué)號(hào)(studentID)作為主鍵的原因是:不方便操作悔橄,例如在更新數(shù)據(jù)的時(shí)候迄沫,同時(shí)也要更改學(xué)號(hào)囱修,那這樣的操作怎么辦呢吠卷?
所以我們加了一個(gè) id 用來唯一表示當(dāng)前數(shù)據(jù)。
CREATE TABLE student(
id int(11) NOT NULL AUTO_INCREMENT,
studentID int(11) NOT NULL UNIQUE,
name varchar(255) NOT NULL,
age int(11) NOT NULL,
sex varchar(255) NOT NULL,
birthday date DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
③ 原型設(shè)計(jì)
就是設(shè)計(jì)界面,在商業(yè)項(xiàng)目中来破,這是很重要的一步篮灼,我們可以解除界面原型,低成本徘禁、高效率的與客戶達(dá)成需求的一致性诅诱。
這個(gè)項(xiàng)目一共就分為兩個(gè)頁面:
-
主頁面:
首頁 -
學(xué)生編輯頁面:
編輯頁面
④ 實(shí)體類的設(shè)計(jì)
實(shí)體類僅僅是對(duì)數(shù)據(jù)庫中表的一一映射,同時(shí)可能還需要兼顧對(duì)業(yè)務(wù)能力的支持晌坤。
- 在 Packge[bean]下創(chuàng)建 Student 類:
package bean;
import java.util.Date;
public class Student {
private int id; // 在數(shù)據(jù)庫中的ID
private int studentID; // 學(xué)號(hào)逢艘,跟ID區(qū)分開為了方便數(shù)據(jù)庫操作
private String name; // 姓名
private int age; // 年齡
private String sex; // 性別
private Date birthday; // 出生日期
// setter 和 getter (為節(jié)約篇幅沒列出來)
}
⑤ DAO 類的設(shè)計(jì)
DAO,即 Date Access Object骤菠,數(shù)據(jù)庫訪問對(duì)象它改,就是對(duì)數(shù)據(jù)庫相關(guān)操作的封裝,讓其他地方看不到 JDBC 的代碼商乎。
首先我們先創(chuàng)建一個(gè)數(shù)據(jù)庫操作的工具類:
- 在 Packge[util]下創(chuàng)建 DBUtil 類:
/**
* 數(shù)據(jù)庫工具類央拖,這個(gè)類的作用是初始化驅(qū)動(dòng),并且提供一個(gè)getConnection用于獲取連接鹉戚。
*/
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtil {
static String ip = "127.0.0.1";
static int port = 3306;
static String database = "student";
static String encoding = "UTF-8";
static String loginName = "root";
static String password = "root";
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
return DriverManager.getConnection(url, loginName, password);
}
public static void main(String[] args) throws SQLException {
System.out.println(getConnection());
}
}
- 寫工具類的好處:
便于統(tǒng)一維護(hù)鲜戒,降低維護(hù)成本
然后是 DAO 類,除了進(jìn)行典型的 ORM 支持功能之外抹凳,也需要提供各種業(yè)務(wù)方法遏餐。
- 在 Packge[dao]下創(chuàng)建 StudentDAO 類:
package dao;
import bean.Student;
import util.DBUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class StudentDAO {
public int getTotal() {
int total = 0;
String sql = "SELECT COUNT(*) FROM student";
try (Connection c = DBUtil.getConnection(); Statement st = c.createStatement()) {
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
total = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return total;
}
public void add(Student student) {
String sql = "INSERT INTO student VALUES(NULL,?,?,?,?,?)";
try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, student.getStudentID());
ps.setString(2, student.getName());
ps.setInt(3, student.getAge());
ps.setString(4, student.getSex());
ps.setDate(5, new java.sql.Date(student.getBirthday().getTime()));
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void delete(int id) {
String sql = "DELETE FROM student WHERE ID = ?";
try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, id);
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void update(Student student) {
String sql = "update student set student_id = ?, name = ?, age = ?, sex = ?, birthday = ? where id = ? ";
try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, student.getStudentID());
ps.setString(2, student.getName());
ps.setInt(3, student.getAge());
ps.setString(4, student.getSex());
ps.setDate(5, new java.sql.Date(student.getBirthday().getTime()));
ps.setInt(6, student.getId());
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
public Student get(int id) {
Student student = new Student();
String sql = "SELECT * FROM student WHERE ID = " + id;
try (Connection c = DBUtil.getConnection(); Statement st = c.createStatement()) {
ResultSet rs = st.executeQuery(sql);
if (rs.next()) {
int student_id = rs.getInt("student_id");
String name = rs.getString("name");
int age = rs.getInt("age");
String sex = rs.getString("sex");
Date birthday = rs.getDate("birthday");
student.setStudentID(student_id);
student.setName(name);
student.setAge(age);
student.setSex(sex);
student.setBirthday(birthday);
student.setId(id);
}
} catch (SQLException e) {
e.printStackTrace();
}
return student;
}
public List<Student> list() {
return list(0, Short.MAX_VALUE);
}
public List<Student> list(int start, int count) {
List<Student> students = new ArrayList<>();
String sql = "SELECT * FROM student ORDER BY student_id desc limit ?,?";
try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, start);
ps.setInt(2, count);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Student student = new Student();
int id = rs.getInt("id");
int studentID = rs.getInt("student_id");
String name = rs.getString("name");
int age = rs.getInt("age");
String sex = rs.getString("sex");
Date birthday = rs.getDate("birthday");
student.setId(id);
student.setStudentID(studentID);
student.setName(name);
student.setAge(age);
student.setSex(sex);
student.setBirthday(birthday);
students.add(student);
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
return students;
}
}
- 該類中,既提供了增刪改查這些基本的 CRUD 操作
1.增加:public void add(Student student)
2.刪除:public void delete(int id)
3.修改:public void update(Student student)
4.查詢所有:public List<Student> list()
- 又提供了一些非 CRUD 方法
1.獲取總數(shù):public int getTotal()
2.根據(jù) id 獲扔住:public Student get(int id)
⑥ 業(yè)務(wù)類介紹
作為 J2EE Web 應(yīng)用失都,一般都會(huì)按照如圖所示的設(shè)計(jì)流程進(jìn)行:
Servlet -> Service(業(yè)務(wù)類) -> DAO -> database
當(dāng)瀏覽器提交請(qǐng)求到 Tomcat Web 服務(wù)器的時(shí)候,對(duì)應(yīng)的 Servlet 的doGet/doPost 方法會(huì)被調(diào)用幸冻,接著在 Servlet 中調(diào)用 Service類粹庞,然后在 Service 類中調(diào)用DAO類,最后在 DAO 中訪問數(shù)據(jù)庫獲取相應(yīng)的數(shù)據(jù)洽损。
單本項(xiàng)目沒有使用 Service 這一層庞溜,原因是在對(duì) DAO 類進(jìn)行開發(fā)中,已經(jīng)提供了很好的支持業(yè)務(wù)的方法碑定,沒有必要再包括上一層 Service 業(yè)務(wù)類流码。
參考鏈接:這里
⑦ 功能開發(fā)
需要按照模塊之間的依賴關(guān)系,順序開發(fā)延刘。
- 首先為項(xiàng)目添加必要的 jar 包:
jstl.jar
mysql-connector-java-5.0.8-bin.jar
servlet-api.jar
standard.jar
這也是 Web 開發(fā)中最基本的 4 個(gè)包
——【1.編寫 Filter】——
由于項(xiàng)目中設(shè)計(jì)表單 POST 方式的提交旅掂,所以我們先來編寫好相關(guān)編碼的過濾器,好支持中文的存取
- 在 Packge[filter] 下編寫 EncodingFilter 類:
package filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 設(shè)置編碼格式為 UTF-8
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
——【2. 編寫 Servlet 】——
按照傳統(tǒng)的方式访娶,我們項(xiàng)目的業(yè)務(wù)為增刪改查,所以對(duì)應(yīng)四個(gè)路徑觉阅,也就是需要編寫四個(gè) Servlet 才可以
- AddServlet:
package servlet;
import bean.Student;
import dao.StudentDAO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/addStudent")
public class AddServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Student student = new Student();
// 直接從表單中獲取數(shù)據(jù)
int studentID = Integer.parseInt(req.getParameter("studentID"));
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));
String sex = req.getParameter("radio");
Date birthday = null;
// String 類型按照 yyyy-MM-dd 的格式轉(zhuǎn)換為 java.util.Date 類
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
birthday = simpleDateFormat.parse(req.getParameter("birthday"));
} catch (ParseException e) {
e.printStackTrace();
}
student.setStudentID(studentID);
student.setName(name);
student.setAge(age);
student.setSex(sex);
student.setBirthday(birthday);
new StudentDAO().add(student);
resp.sendRedirect("/listStudent"); // 這里可以理解為刷新崖疤,重新請(qǐng)求
}
}
- DeleteServlet:
package servlet;
import dao.StudentDAO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/deleteStudent")
public class DeleteServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = Integer.parseInt(req.getParameter("id"));
new StudentDAO().delete(id);
resp.sendRedirect("/listStudent");
}
}
- EditServlet:
package servlet;
import bean.Student;
import dao.StudentDAO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/editStudent")
public class EditServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = Integer.parseInt(req.getParameter("id"));
Student student = new StudentDAO().get(id);
req.setAttribute("student", student);
req.getRequestDispatcher("/editStudent.jsp").forward(req, resp);
}
}
- ListServlet:
package servlet;
import bean.Student;
import dao.StudentDAO;
import util.Page;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/listStudent")
public class ListServlet extends HttpServlet {
private StudentDAO studentDAO = new StudentDAO();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取分頁參數(shù)
int start = 0;
int count = 10;
try {
start = Integer.parseInt(req.getParameter("page.start"));
count = Integer.parseInt(req.getParameter("page.count"));
} catch (Exception e) {
}
Page page = new Page(start, count);
List<Student> students = studentDAO.list(page.getStart(), page.getCount());
int total = studentDAO.getTotal();
page.setTotal(total);
req.setAttribute("students", students);
req.setAttribute("page", page);
req.getRequestDispatcher("/listStudent.jsp").forward(req, resp);
}
}
- UpdateServlet:
package servlet;
import bean.Student;
import dao.StudentDAO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/updateStudent")
public class UpdateServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Student student = new Student();
int id = Integer.parseInt(req.getParameter("id"));
int studentID = Integer.parseInt(req.getParameter("studentID"));
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));
String sex = req.getParameter("radio");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date birthday = null;
try {
birthday = simpleDateFormat.parse(req.getParameter("birthday"));
} catch (ParseException e) {
e.printStackTrace();
}
student.setId(id);
student.setStudentID(studentID);
student.setName(name);
student.setAge(age);
student.setSex(sex);
student.setBirthday(birthday);
new StudentDAO().update(student);
resp.sendRedirect("/listStudent");
}
}
——【3. JSP 的編寫】——
我們把默認(rèn)的 index.jsp 修改成如下代碼:
<%
request.getRequestDispatcher("/listStudent").forward(request, response);
%>
- 引入 JQ 和 Bootstrap
為了簡(jiǎn)化操作秘车,引入了 JQuery 和 Bootstrap - 編寫 listStudent.jsp
其實(shí)主要還是利用 Bootstrap 編寫好整個(gè)頁面,我寫的時(shí)候也是對(duì)照這里寫的
<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<%-- 引入JQ和Bootstrap --%>
<script src="js/jquery/2.0.0/jquery.min.js"></script>
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<link href="css/style.css" rel="stylesheet">
<title>學(xué)生管理頁面 - 首頁</title>
<script>
$(function () {
$("ul.pagination li.disabled a").click(function () {
return false;
});
});
</script>
</head>
<body>
<div class="listDIV">
<table class="table table-striped table-bordered table-hover table-condensed">
<caption>學(xué)生列表 - 共${page.total}人</caption>
<thead>
<tr class="success">
<th>學(xué)號(hào)</th>
<th>姓名</th>
<th>年齡</th>
<th>性別</th>
<th>出生日期</th>
<th>編輯</th>
<th>刪除</th>
</tr>
</thead>
<tbody>
<c:forEach items="${students}" var="s" varStatus="status">
<tr>
<td>${s.studentID}</td>
<td>${s.name}</td>
<td>${s.age}</td>
<td>${s.sex}</td>
<td>${s.birthday}</td>
<td><a href="/editStudent?id=${s.id}"><span class="glyphicon glyphicon-edit"></span> </a></td>
<td><a href="/deleteStudent?id=${s.id}"><span class="glyphicon glyphicon-trash"></span> </a></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<nav class="pageDIV">
<ul class="pagination">
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=0">
<span>?</span>
</a>
</li>
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=${page.start-page.count}">
<span>?</span>
</a>
</li>
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status">
<c:if test="${status.count*page.count-page.start<=30 && status.count*page.count-page.start>=-10}">
<li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>>
<a
href="?page.start=${status.index*page.count}"
<c:if test="${status.index*page.count==page.start}">class="current"</c:if>
>${status.count}</a>
</li>
</c:if>
</c:forEach>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?page.start=${page.start+page.count}">
<span>?</span>
</a>
</li>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?page.start=${page.last}">
<span>?</span>
</a>
</li>
</ul>
</nav>
<div class="addDIV">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">增加學(xué)生</h3>
</div>
<div class="panel-body">
<form method="post" action="/addStudent" role="form">
<table class="addTable">
<tr>
<td>學(xué)號(hào):</td>
<td><input type="text" name="studentID" id="studentID" placeholder="請(qǐng)?jiān)谶@里輸入學(xué)號(hào)"></td>
</tr>
<tr>
<td>姓名:</td>
<td><input type="text" name="name" id="name" placeholder="請(qǐng)?jiān)谶@里輸入名字"></td>
</tr>
<tr>
<td>年齡:</td>
<td><input type="text" name="age" id="age" placeholder="請(qǐng)?jiān)谶@里輸入年齡"></td>
</tr>
<tr>
<td>性別:</td>
<td><input type="radio" class="radio radio-inline" name="radio" value="男"> 男
<input type="radio" class="radio radio-inline" name="radio" value="女"> 女
</td>
</tr>
<tr>
<td>出生日期:</td>
<td><input type="date" name="birthday" id="birthday" placeholder="請(qǐng)?jiān)谶@里輸入出生日期"></td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<button type="submit" class="btn btn-success">提 交</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
- eidtStudent.jsp
編輯表單對(duì)照著首頁的增加表單稍微改一改參數(shù)就好了
<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<%-- 引入JQ和Bootstrap --%>
<script src="js/jquery/2.0.0/jquery.min.js"></script>
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<link href="css/style.css" rel="stylesheet">
<title>學(xué)生管理頁面 - 編輯頁面</title>
</head>
<body>
<div class="editDIV">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">編輯學(xué)生</h3>
</div>
<div class="panel-body">
<form method="post" action="/updateStudent" role="form">
<table class="editTable">
<tr>
<td>學(xué)號(hào):</td>
<td><input type="text" name="studentID" id="studentID" value="${student.studentID}"
placeholder="請(qǐng)?jiān)谶@里輸入學(xué)號(hào)"></td>
</tr>
<tr>
<td>姓名:</td>
<td><input type="text" name="name" id="name" value="${student.name}" placeholder="請(qǐng)?jiān)谶@里輸入名字">
</td>
</tr>
<tr>
<td>年齡:</td>
<td><input type="text" name="age" id="age" value="${student.age}" placeholder="請(qǐng)?jiān)谶@里輸入年齡"></td>
</tr>
<tr>
<td>性別:</td>
<td><input type="radio" class="radio radio-inline" name="radio" value="男"> 男
<input type="radio" class="radio radio-inline" name="radio" value="女"> 女
</td>
</tr>
<tr>
<td>出生日期:</td>
<td><input type="date" name="birthday" id="birthday" value="${student.birthday}"
placeholder="請(qǐng)?jiān)谶@里輸入出生日期"></td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<input type="hidden" name="id" value="${student.id}">
<button type="submit" class="btn btn-success">提 交</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
- style.css 文件:
body {
padding-top: 60px;
}
div.listDIV {
width: 600px;
margin: 0 auto;
}
div.editDIV {
width: 400px;
margin: 0 auto;
}
nav.pageDIV {
text-align: center;
}
div.addDIV {
width: 300px;
margin: 0 auto;
}
table.addTable {
width: 100%;
padding: 5px;
}
table.addTable td {
padding: 5px;
}
table.editTable {
width: 100%;
padding: 5px;
}
table.editTable td {
padding: 5px;
}
——【4. 項(xiàng)目細(xì)節(jié)】——
-
項(xiàng)目的整理結(jié)構(gòu):
分頁功能
- 首頁在 Packge[util] 下創(chuàng)建一個(gè) Page 工具類:
package util;
public class Page {
int start; // 開始數(shù)據(jù)
int count; // 每一頁的數(shù)量
int total; // 總共的數(shù)據(jù)量
public Page(int start, int count) {
super();
this.start = start;
this.count = count;
}
public boolean isHasPreviouse(){
if(start==0)
return false;
return true;
}
public boolean isHasNext(){
if(start==getLast())
return false;
return true;
}
public int getTotalPage(){
int totalPage;
// 假設(shè)總數(shù)是50劫哼,是能夠被5整除的叮趴,那么就有10頁
if (0 == total % count)
totalPage = total /count;
// 假設(shè)總數(shù)是51,不能夠被5整除的权烧,那么就有11頁
else
totalPage = total / count + 1;
if(0==totalPage)
totalPage = 1;
return totalPage;
}
public int getLast(){
int last;
// 假設(shè)總數(shù)是50眯亦,是能夠被5整除的,那么最后一頁的開始就是40
if (0 == total % count)
last = total - count;
// 假設(shè)總數(shù)是51般码,不能夠被5整除的妻率,那么最后一頁的開始就是50
else
last = total - total % count;
last = last<0?0:last;
return last;
}
// 各種 setter 和 getter
}
- totalPage 是計(jì)算得來的數(shù),用來表示頁碼一共的數(shù)量
在首頁顯示的 StudentList 用 page 的參數(shù)來獲劝遄!:
List<Student> students = studentDAO.list(page.getStart(), page.getCount());
并且在 DAO 類中用 LIMIT 關(guān)鍵字:
String sql = "SELECT * FROM student ORDER BY student_id desc limit ?,?";
第一個(gè)參數(shù)為 start宫静,第二個(gè)參數(shù)為 count
這樣就能根據(jù)分頁的信息來獲取到響應(yīng)的數(shù)據(jù)編寫分頁欄:
1.寫好頭和尾
<nav class="pageDIV">
<ul class="pagination">
.....
</ul>
</nav>
2.寫好?
?
這兩個(gè)功能按鈕
使用 <c:if>
標(biāo)簽來增加邊界判斷,如果沒有前面的頁碼了則設(shè)置為disable狀態(tài)
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=0">
<span>?</span>
</a>
</li>
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=${page.start-page.count}">
<span>?</span>
</a>
</li>
再通過 JavaScrip 代碼來完成禁用功能:
<script>
$(function () {
$("ul.pagination li.disabled a").click(function () {
return false;
});
});
</script>
3.完成中間頁碼的編寫
從 0
循環(huán)到 page.totalPage - 1
券时,varStatus
相當(dāng)于是循環(huán)變量
- status.count 是從1開始遍歷
- status.index 是從0開始遍歷
- 要求:顯示當(dāng)前頁碼的前兩個(gè)和后兩個(gè)就可孤里,例如當(dāng)前頁碼為3的時(shí)候,就顯示 1 2 3(當(dāng)前頁) 4 5 的頁碼
-
理解測(cè)試條件:
-10 <= 當(dāng)前頁*每一頁顯示的數(shù)目 - 當(dāng)前頁開始的數(shù)據(jù)編號(hào) <= 30
- 只要理解了這個(gè)判斷條件橘洞,其他的就都好理解了
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status">
<c:if test="${status.count*page.count-page.start<=30 && status.count*page.count-page.start>=-10}">
<li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>>
<a
href="?page.start=${status.index*page.count}"
<c:if test="${status.index*page.count==page.start}">class="current"</c:if>
>${status.count}</a>
</li>
</c:if>
</c:forEach>
4.在 Servlet 中獲取參數(shù)
// 獲取分頁參數(shù)
int start = 0;
int count = 10;
try {
start = Integer.parseInt(req.getParameter("page.start"));
count = Integer.parseInt(req.getParameter("page.count"));
} catch (Exception e) {
}
....
// 共享 page 數(shù)據(jù)
req.setAttribute("page", page);
Date 轉(zhuǎn)換的問題
/**
* Date類型轉(zhuǎn)為指定格式的String類型
*
* @param source
* @param pattern
* @return
*/
public static String DateToString(Date source, String pattern) {
simpleDateFormat = new SimpleDateFormat(pattern);
return simpleDateFormat.format(source);
}
/**
*
* 字符串轉(zhuǎn)換為對(duì)應(yīng)日期
*
* @param source
* @param pattern
* @return
*/
public static Date stringToDate(String source, String pattern) {
simpleDateFormat = new SimpleDateFormat(pattern);
Date date = null;
try {
date = simpleDateFormat.parse(source);
} catch (Exception e) {
}
return date;
}
項(xiàng)目總結(jié)
這一個(gè)項(xiàng)目實(shí)在有些太簡(jiǎn)單了捌袜,可能最需要理解的一個(gè)功能就屬于【分頁功能】了吧
不過還是借助這個(gè)項(xiàng)目,進(jìn)一步鞏固了 J2EE 開發(fā)的相關(guān)知識(shí)炸枣,也對(duì)開發(fā)的流程愈發(fā)熟悉虏等,整個(gè)項(xiàng)目編寫時(shí)間不超過 8 個(gè)小時(shí),對(duì)于我自己來說抛虏,不算快博其,但還算比較順暢的
需要改進(jìn)的地方:
登錄驗(yàn)證
本項(xiàng)目沒有增加登錄驗(yàn)證,可以增加一個(gè)登錄頁面并結(jié)合 session 來完成驗(yàn)證代碼重構(gòu)
本項(xiàng)目?jī)H僅完成的是一個(gè)學(xué)生表的增刪改查迂猴,卻有以下的五個(gè) Servlet :
如果項(xiàng)目大起來慕淡,那可想而知,Servlet 有多臃腫沸毁,維護(hù)成本有多高
- 改進(jìn)方法:用一個(gè) StudentServlet 代替
- 具體做法:使用 Filter + Servlet 完成
① 首先編寫一個(gè)過濾所有地址的 Filter峰髓,并解析地址欄的地址,提取出其中的方法傳遞給 StudentServlet (這個(gè)時(shí)候需要統(tǒng)一的地址息尺,如:
student_list
携兵、student_edit
、student_delete
搂誉、student_update
)
request.setAttribute("method", method);
② 在 Servlet 中獲取 method 方法徐紧,并調(diào)用
// 獲取到對(duì)應(yīng)的方法
String method = (String) request.getAttribute("method");
// 對(duì) method 作判斷,調(diào)用對(duì)應(yīng)的方法
- 沒有對(duì)輸入的數(shù)據(jù)的正確性進(jìn)行驗(yàn)證
這顯然會(huì)導(dǎo)致許多問題,可以通過 js 代碼來完成驗(yàn)證
歡迎轉(zhuǎn)載并级,轉(zhuǎn)載請(qǐng)注明出處拂檩!
簡(jiǎn)書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號(hào):wmyskxz
分享自己的學(xué)習(xí) & 學(xué)習(xí)資料 & 生活
想要交流的朋友也可以加qq群:3382693