JavaWeb:基於MVC設計模式的一個小案例(一)

(未經容許,請勿轉載,謝謝。)javascript

本案例的處理過程:html

客戶端發送一個請求給服務器,服務器把這個請求給Servlet,Servlet 獲取請求信息,根據請求信息的狀況去調用 model (在這裏是一個普通的 Java 類),而後把返回結果給 Servlet ,而後Servlet 根據返回結果 轉向一個 JSP,JSP是用來呈現數據的 (這裏用的是Java 代碼),生成一個HTML 頁面顯給客戶。java

使用到的技術:mysql

MVC 設計模式:JSP、Servlet、POJOjquery

數據庫:MySQLweb

鏈接數據庫使用 c3p0 數據庫鏈接池sql

JDBC 工具使用 DBUtils數據庫

頁面上的提示操做使用 jQueryapache

具體實現步驟:設計模式

一、創建數據表

代碼: 

Create table customer(
id int(10) primary key auto_increment,
name varchar(30) not null unique,
address varchar(30),
phone varchar(30)
);

爲 name 字段添加惟一約束:
alter table customers add constraint name_uk unique(name);

二、底層實現

①、加入c3p0 數據源:導入兩個 jar 包(c3p0 和 數據庫驅動),在 src 下新建配置文件:c3p0-config.xml ,修改一下要有鏈接數據庫的基本信息(driverClass、jdbcUrl、user、password)。

c3p0-config.xml 代碼:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <c3p0-config>
 3 
 4   <named-config name="mvcapp"> 
 5   
 6       <!--指定鏈接數據源的基本信息  -->
 7       <property name="driverClass">com.mysql.jdbc.Driver</property>
 8       <property name="jdbcUrl">jdbc:mysql:///javawebdb</property>
 9       <property name="user">root</property>
10       <property name="password">root</property>
11       
12       <!-- 若數據庫中鏈接不足時,一次性向數據庫服務器申請多少個鏈接-->
13     <property name="acquireIncrement">5</property>
14     <!-- 初始化數據庫鏈接池時鏈接的數量-->
15     <property name="initialPoolSize">10</property>
16     <!-- 數據庫鏈接池中的最小的數據庫鏈接數-->
17     <property name="minPoolSize">10</property>
18     <!-- 數據庫鏈接池中的最大的數據庫鏈接數-->
19     <property name="maxPoolSize">50</property>
20     
21     <!-- c3p0 數據庫鏈接池能夠維護的 Statement 的個數-->
22     <property name="maxStatements">20</property> 
23     <!-- 每一個鏈接同時能夠使用的Statement 對象的個數-->
24     <property name="maxStatementsPerConnection">5</property>
25 
26   
27   </named-config>
28 </c3p0-config>

 

②、編寫DAO 工具類、JdbcUtils 工具類和 CustomerDao 接口(如下有具體說明和代碼)

DAO 工具類:封裝了基本的增刪改查的方法,以供子類繼承使用。當前DAO 沒有事務,直接在方法中獲取數據庫鏈接。導入了DBUtils 的 jar 包,整個 DAO 採起 DBUtils 的解決方案。

實現方法:

update(封裝了insert、delete、update)操做:public void update(String sql, Object...args){  }

查詢 返回 T 對應的實體類的對象:public T get(String sql, Object...args){  }

查詢 返回 T 對應的List :public List<T> getForList(String sql, Object...args){  }

查詢 返回一個字段的值: public <E> E getForValue(String sql, Object...args){  }

DAO.java 代碼:

  1 package com.hnust.mvcapp.dao;
  2 
  3 import java.lang.reflect.ParameterizedType;
  4 import java.lang.reflect.Type;
  5 import java.sql.Connection;
  6 import java.sql.SQLException;
  7 import java.util.List;
  8 
  9 import org.apache.commons.dbutils.QueryRunner;
 10 import org.apache.commons.dbutils.handlers.BeanHandler;
 11 import org.apache.commons.dbutils.handlers.BeanListHandler;
 12 import org.apache.commons.dbutils.handlers.ScalarHandler;
 13 
 14 import com.hnust.mvcapp.utils.JdbcUtils;
 15 
 16 /**
 17  * 封裝了基本的增刪改查的方法,以供子類繼承使用。
 18  * 當前DAO 直接在方法中獲取數據庫鏈接。
 19  * 整個DAO 採起DBUtils 解決方案。
 20  * @author User
 21  *
 22  * @param <T> 當前 DAO 處理的實體類的類型是什麼
 23  */
 24 public class Dao<T> {
 25 
 26     private QueryRunner queryRunner = new QueryRunner();
 27     
 28     private Class<T> clazz;
 29     
 30     /**
 31      * 須要肯定 clazz
 32      */
 33     public Dao(){
 34         //由獲得子類的 Class獲得父類 帶泛型的那個類型。
 35         Type superClass = getClass().getGenericSuperclass();
 36         //先判斷是否是那個類型
 37         if(superClass instanceof ParameterizedType){
 38             //是的話,強轉一下
 39             ParameterizedType parameterizedType = (ParameterizedType) superClass;
 40             //獲取真正的泛型的參數
 41             Type[] typeArgs = parameterizedType.getActualTypeArguments();
 42             if(typeArgs != null && typeArgs.length >0){
 43                 if(typeArgs[0] instanceof Class){
 44                     clazz = (Class<T>) typeArgs[0];
 45                 }
 46             }
 47         }
 48     }
 49     
 50     
 51     /**
 52      * 查詢,返回某一個字段的值
 53      */
 54     public <E> E getForValue(String sql, Object...args){
 55         Connection connection = null;
 56         try {
 57             connection = JdbcUtils.getConnection();
 58             return (E) queryRunner.query(connection, sql, new ScalarHandler(), args);
 59         } catch (SQLException e) {
 60             e.printStackTrace();
 61         }finally{
 62             JdbcUtils.releaseConnection(connection);
 63         }
 64         return null;
 65     }
 66     
 67     /**
 68      * 查詢,返回T 所對應的 List
 69      */
 70     public List<T> getForList(String sql, Object...args){
 71         Connection connection = null;
 72         try {
 73             connection = JdbcUtils.getConnection();
 74             return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
 75         } catch (SQLException e) {
 76             e.printStackTrace();
 77         }finally{
 78             JdbcUtils.releaseConnection(connection);
 79         }
 80         return null;
 81     }
 82     
 83     /**
 84      * 查詢,返回一個T 的實體類對象
 85      */
 86     public T get(String sql, Object...args){
 87         Connection connection = null;
 88         
 89         try {
 90             connection = JdbcUtils.getConnection();
 91             return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
 92         } catch (SQLException e) {
 93             e.printStackTrace();
 94         }finally{
 95             JdbcUtils.releaseConnection(connection);
 96         }
 97         return null;
 98     }
 99     
100     /**
101      * 通用的 insert 、delete、update 方法
102      */
103     public void update(String sql, Object...args){
104         Connection connection = null;
105         try {
106             connection = JdbcUtils.getConnection();
107             queryRunner.update(connection, sql, args);
108         } catch (Exception e) {
109             e.printStackTrace();
110         }finally{
111             JdbcUtils.releaseConnection(connection);
112         }
113     }
114 }

 

JdbcUtils 工具類:JDBC 操做的工具類。

實現方法:

返回數據源的一個 Connection 對象:public static Connection getConnection(){  }

釋放 Connection 的鏈接:public static void releaseConnection(Connection connection){  }

注意:數據源的初始化必定要放在靜態代碼塊中,數據源被建立一次就夠了。寫完一個能夠用單元測試檢驗如下。

JdbcUtils.java 代碼:

 1 package com.hnust.mvcapp.utils;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import javax.sql.DataSource;
 7 
 8 import com.mchange.v2.c3p0.ComboPooledDataSource;
 9 
10 /**
11  * JDBC 操做的工具類
12  * @author User
13  *
14  */
15 public class JdbcUtils {
16 
17     /**
18      * 釋放鏈接
19      */
20     public static void releaseConnection(Connection connection){
21         
22         try {
23             if(connection != null){
24                 connection.close();
25             }
26         } catch (Exception e) {
27             e.printStackTrace();
28         }
29     }
30     
31     private static DataSource dataSource = null;
32     static{
33         dataSource = new ComboPooledDataSource("mvcapp"); //傳入的是 configName
34     }
35     /**
36      * 獲取鏈接
37      * @throws SQLException 
38      */
39     public static Connection getConnection() throws SQLException{
40         
41         return dataSource.getConnection();
42     }
43 }

 

CustomerDao 接口:

實現的方法:

模糊查詢 返回知足條件的List :public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc);

查詢 返回List:public List<Customer> getAll();

添加:poublic void save(Customer customer);

修改時要根據id 的查詢顯示:public Customer get(Inreger id);

刪除(根據 id):public void delete(Integer id);

查詢 和這個名字同樣的 記錄數(根據 name):public long getCountWithName(String name);

CustomerDao.java 代碼:

 1 package com.hnust.mvcapp.dao;
 2 
 3 import java.util.List;
 4 
 5 import com.hnuct.mvcapp.entity.Customer;
 6 
 7 public interface CustomerDao {
 8     
 9     /**
10      * 模糊查詢 返回知足條件的List
11      * @param cc :封裝了查詢條件
12      * @return
13      */
14     public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc);
15 
16     /**
17      * 查詢 返回 List
18      */
19     public List<Customer> getAll();
20     
21     /**
22      * 增長
23      */
24     public void save(Customer customer);
25     
26     /**
27      * 修改 更新時候的查詢(根據id)顯示
28      */
29     public Customer get(Integer id);
30     
31     /**
32      * 刪除
33      */
34     public void delete(Integer id);
35     
36     /**
37      * 返回和name 相同的記錄數
38      */
39     public long getCountWithName(String name);
40 }

 

實體類 Customer:

Customer.java 代碼:

 

 1 package com.hnuct.mvcapp.entity;
 2 
 3 public class Customer {
 4 
 5     private Integer id;
 6     private String name;
 7     private String address;
 8     private String phone;
 9     public Integer getId() {
10         return id;
11     }
12     public void setId(Integer id) {
13         this.id = id;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public String getAddress() {
22         return address;
23     }
24     public void setAddress(String address) {
25         this.address = address;
26     }
27     public String getPhone() {
28         return phone;
29     }
30     public void setPhone(String phone) {
31         this.phone = phone;
32     }
33     public Customer(Integer id, String name, String address, String phone) {
34         super();
35         this.id = id;
36         this.name = name;
37         this.address = address;
38         this.phone = phone;
39     }
40     public Customer() {
41         super();
42     }
43     
44     @Override
45     public String toString() {
46         return "Customers [id=" + id + ", name=" + name + ", address="
47                 + address + ", phone=" + phone + "]";
48     }
49     
50     
51 }

 

Dao 接口的實現:

CustomerDaoJdbcImpl.java 代碼:

 1 package com.hnuct.mvcapp.dao.impl;
 2 
 3 import java.util.List;
 4 
 5 import com.hnuct.mvcapp.entity.Customer;
 6 import com.hnust.mvcapp.dao.CriteriaCustomer;
 7 import com.hnust.mvcapp.dao.CustomerDao;
 8 import com.hnust.mvcapp.dao.Dao;
 9 
10 public class CustomerDaoJdbcImpl extends Dao<Customer> implements CustomerDao{
11 
12     @Override
13     public List<Customer> getAll() {
14         String sql = "select * from customer";
15         return getForList(sql);
16     }
17 
18     @Override
19     public void save(Customer customer) {
20         String sql = "insert into customer(name,address,phone) values (?,?,?)";
21         update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
22     }
23 
24     @Override
25     public Customer get(Integer id) {
26         String sql = "select * from customer where id = ?";
27         return get(sql, id);
28     }
29 
30     @Override
31     public void delete(Integer id) {
32         String sql = "delete from customer where id = ? ";
33         update(sql, id);
34     }
35 
36     @Override
37     public long getCountWithName(String name) {
38         String sql = "select count(id) from customer where name = ?";
39         return getForValue(sql, name);
40     }
41 
42     @Override
43     public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {
44         String sql = "SELECT id,name,address,phone FROM customer WHERE name LIKE ? AND "
45                 + "address LIKE ? AND phone LIKE ?";
46         //注意:修改了 CriteriaCustomer 的 getter 方法,使其返回的字符串中有 "%%",
47         //若返回值爲 null 則返回 "%%" ,若不爲 null, 則返回 "% " + 字段自己的值 + " %"
48         return getForList(sql, cc.getName(), cc.getAddress(), cc.getPhone());
49     }
50 
51 }

ps:注意由於查詢條件不少時候 和 實體類 並不相同,因此要作成一個單獨的類,這裏是 CriteriaCustomer 類,其中裏面的getter 方法作了修改,是爲了正確的填充佔位符。

CriteriaCustomer.java 代碼:

 1 package com.hnust.mvcapp.dao;
 2 
 3 public class CriteriaCustomer {
 4 
 5     private String name;
 6     private String address;
 7     private String phone;
 8     public String getName() {
 9         if(name == null)
10             name = "%%";
11         else
12             name = "%" + name + "%";
13         return name;
14     }
15     public void setName(String name) {
16         this.name = name;
17     }
18     public String getAddress() {
19         if(address == null)
20             address = "%%";
21         else 
22             address = "%" + address + "%";
23         return address;
24     }
25     public void setAddress(String address) {
26         this.address = address;
27     }
28     public String getPhone() {
29         if(phone == null)
30             phone = "%%";
31         else 
32             phone = "%" + phone + "%";
33         return phone;
34     }
35     public void setPhone(String phone) {
36         this.phone = phone;
37     }
38     
39     
40     
41     public CriteriaCustomer() {
42         super();
43     }
44     public CriteriaCustomer(String name, String address, String phone) {
45         super();
46         this.name = name;
47         this.address = address;
48         this.phone = phone;
49     }
50     
51     
52 }

 

三、Servlet 的實現:獲取請求信息的參數,根據請求信息調用 DAO 的對應的方法。

先寫了一個 test.jsp 頁面 放了三個超連接。

test.jsp 代碼:

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 7 <title>Insert title here</title>
 8 </head>
 9 <body>
10         <%-- 
11         <a href="customerServlet?method=add">add</a>
12         <br><br>
13         <a href="customerServlet?method=query">query</a>
14         <br><br>    
15         <a href="customerServlet?method=delete">delete</a>
16         --%>
17         
18         <a href="addCustomer.do">add</a>
19         <br><br>
20         <a href="query.do">query</a>
21         <br><br>
22         <a href="delete.do">delete</a>
23         <br><br>
24         
25         
26         
27 </body>
28 </html>

注意你的 web.xml 裏的 url-pattern:<url-pattern>*.do</url-pattern>

 

而後 建立了CustomerServlet :去響應服務器的請求,調用對應的model,返回結果(我這裏暫時實現了 模糊查詢和 刪除的功能)。

CustomerServlet.java 代碼:

  1 package com.hnust.mvcapp.servlet;
  2 
  3 import java.io.IOException;
  4 import java.lang.reflect.InvocationTargetException;
  5 import java.lang.reflect.Method;
  6 import java.util.List;
  7 
  8 import javax.servlet.ServletException;
  9 import javax.servlet.http.HttpServlet;
 10 import javax.servlet.http.HttpServletRequest;
 11 import javax.servlet.http.HttpServletResponse;
 12 
 13 import com.hnuct.mvcapp.dao.impl.CustomerDaoJdbcImpl;
 14 import com.hnuct.mvcapp.entity.Customer;
 15 import com.hnust.mvcapp.dao.CriteriaCustomer;
 16 import com.hnust.mvcapp.dao.CustomerDao;
 17 
 18 
 19 public class CustomerServlet extends HttpServlet {
 20     private static final long serialVersionUID = 1L;
 21 
 22     private CustomerDao customerDao = new CustomerDaoJdbcImpl();
 23     
 24     protected void doGet(HttpServletRequest request, HttpServletResponse response) 
 25             throws ServletException, IOException {
 26         
 27             this.doPost(request, response);
 28     }
 29     
 30     @Override
 31     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 32             throws ServletException, IOException {
 33         
 34         //一、獲取servletPath
 35         String servletPath = req.getServletPath();
 36         //System.out.println(servletPath);  //獲得的是  /addCustomer.do
 37         
 38         //二、去除 / 和 .do ,獲得 addCustomer 這樣的字符串
 39         String methodName = servletPath.substring(1);
 40         methodName = methodName.substring(0, methodName.length() - 3);
 41         //System.out.println(methodName);  // 獲得的是 addCustomer
 42         
 43         try {
 44             //三、利用反射,根據獲取的 方法名,獲取對應的方法。
 45             Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
 46                                                     HttpServletResponse.class);
 47             //四、利用反射調用對應的方法    
 48             method.invoke(this, req, resp);
 49             
 50         } catch (Exception e) {
 51             e.printStackTrace();
 52             //能夠有一些響應
 53             resp.sendRedirect("error.jsp");
 54         }
 55         
 56     }
 57 
 58     private void delete(HttpServletRequest request, HttpServletResponse response) 
 59             throws ServletException, IOException {
 60         //一、獲取 id
 61         String idStr = request.getParameter("id");
 62         int id = 0;
 63         //爲了不輸入的 id 是不 合法的。 idStr 不能轉爲 int 類型。若不能轉,則 id 爲0,沒法執行任何的操做。
 64         try {
 65             id = Integer.parseInt(idStr);
 66             //二、調用 CustomerDAO 的 delete 方法
 67             customerDao.delete(id);
 68             //三、頁面的重定向
 69             response.sendRedirect("query.do");
 70         } catch (Exception e) {
 71             e.printStackTrace();
 72         }
 73     }
 74 
 75     private void query(HttpServletRequest request, HttpServletResponse response) 
 76             throws ServletException, IOException {
 77         //一、獲取模糊查詢的請求參數
 78         String name = request.getParameter("name");
 79         String address = request.getParameter("address");
 80         String phone = request.getParameter("phone");
 81         
 82         //二、把請求參數封裝爲 CriteriaCustomer 對象
 83         CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
 84         
 85         //三、再調用CustomerDao 的 getForListWithCriteriaCustomer() 方法
 86         List<Customer> customers = customerDao.getForListWithCriteriaCustomer(cc);
 87          
 88         //調用CustomerDao 的 getAll() 方法 查詢。
 89         //List<Customer> customers = customerDao.getAll();
 90         
 91         //四、把查詢到的結果集放入 request 中
 92         request.setAttribute("customers", customers);
 93         //五、請求的轉發
 94         request.getRequestDispatcher("/index.jsp").forward(request, response);
 95         
 96     }
 97 
 98     private void addCustomer(HttpServletRequest request, HttpServletResponse response) 
 99             throws ServletException, IOException {
100 
101         System.out.println("add");
102     }
103 
104 }

 

四、返回結果 的 JSP 頁面:獲取返回結果,遍歷顯示。

index.jsp 代碼:

 1 <%@page import="com.hnuct.mvcapp.entity.Customer"%>
 2 <%@page import="java.util.List"%>
 3 <%@ page language="java" contentType="text/html; charset=UTF-8"
 4     pageEncoding="UTF-8"%>
 5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 6 <html>
 7 <head>
 8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 9 <title>Insert title here</title>
10 <script type="text/javascript" src="Scripts/jquery-1.7.2.js"></script>
11 <script type="text/javascript">
12         $(function(){
13             $(".delete").click(function(){
14                 var content = $(this).parent().parent().find("td:eq(1)").text();
15                 var flag = confirm("肯定要刪除 " + content + " 的信息嗎?");
16                 return flag;
17             });
18         })
19 </script>
20 </head>
21 <body>
22         <form action="query.do" method="post">
23                 <table>
24                     <tr>
25                         <td>name:</td>
26                         <td><input type="text" name="name"/></td>
27                     </tr>
28                     <tr>
29                         <td>address:</td>
30                         <td><input type="text" name="address"/></td>
31                     </tr>
32                     <tr>
33                         <td>phone:</td>
34                         <td><input type="text" name="phone"/></td>
35                     
36                     <tr>
37                         <td><input type="submit" value="Query"/></td>
38                         <td><a href="">Add new Customer</a></td>
39                     </tr>
40                 </table>
41         </form>
42         <br><br>
43         
44         <%
45             List<Customer> customers = (List<Customer>) request.getAttribute("customers");
46             if(customers != null && customers.size() > 0){
47         %>
48         <hr>
49         <br><br>
50         <table border="1" cellpadding="10" cellspacing="0">
51             <tr>
52                 <th>ID</th>
53                 <th>NAME</th>
54                 <th>ADDRESS</th>
55                 <th>PHONE</th>
56                 <th>UPDATE/DELETE</th>
57             </tr>
58             <% for(Customer cust : customers){
59             
60             %>
61             <tr>
62                 <td><%= cust.getId() %></td>
63                 <td><%= cust.getName() %></td>
64                 <td><%= cust.getAddress() %></td>
65                 <td><%= cust.getPhone() %></td>
66                 <td>
67                     <a href="">Update</a>
68                     <a href="delete.do?id=<%=cust.getId() %>" class="delete">Delete</a>
69                 </td>
70             </tr>
71             <%
72                 }
73             %>
74         </table>
75         <%
76             }
77         %>
78 </body>
79 </html> 

 

最後結果:

點擊query

能夠實現模糊查詢,和刪除的功能。

 這是今天的學習內容。

相關文章
相關標籤/搜索