功能分析:
只有一个角色客户,客户可以
--查看图书信息(包括查看图书详细信息,使用条件(例价格区间)查看图书信息,对图书进行翻页)
--把图书加入购物车
--查看购物车
--修改购物车(包括清空购物车,修改购物车单本图书数量,删除单本图书)
--结账(填写用户名和账号信息)
--查看交易记录
总体架构:
MVC 设计模式:
--model:POJO
--controller:Servlet
--view:JSP + EL + JSTL
技术选型:
数据库:Mysql
数据源:C3P0
JDBC 工具:DBUtils
事务解决方案:Filter + ThreadLocal
Ajax 解决方案:jQuery + JavaScript + JSON + google-gson
层之间解耦方案:工厂设计模式
数据表设计:
在 Mysql 数据库中建好这些数据表。
配置好环境
实体类设计:Account(账户表,用于支付),User(客户表,存储客户基本信息),Trade(交易项),TradeItem(交易记录),Book,ShoppingCartItem,ShoppingCart
DAO 层设计:(这里先每个方法手动的获取Connection,在后面操作事务时,再改成获取统一的Connection)
- Dao 接口,定义 Dao 的基本操作,使用BaseDao 实现 Dao 接口。
- BaseDao :使用 DBUtils 工具类提供 Dao 接口的具体实现。
BookDao 接口:用于定义操作 Book 实体类的基本方法。
- BookDaoImpl :使用 BaseDao 中的方法实现 BookDao。
Dao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import java.util.List;
4
5 /**
6 * Dao 接口,定义 Dao 的基本操作,由BaseDao 提供实现。
7 * @param <T>:Dao 实际操作的泛型类型。
8 */
9 public interface Dao<T> {
10
11 /**
12 * 执行 update 操作(insert(但没有返回值)、update、delete)
13 * @param sql:待执行的 SQL 语句。
14 * @param args:填充占位符的可变参数。
15 */
16 void update(String sql, Object...args);
17
18 /**
19 * 执行 insert 操作,返回插入后的记录的ID
20 * @param sql:待执行的 SQL 语句。
21 * @param args:填充占位符的可变参数。
22 * @return:插入新记录的ID。
23 */
24 long insert(String sql, Object...args);
25
26 /**
27 * 执行单条记录的查询,返回与记录对应的类的一个对象。
28 * @param sql:待执行的SQL 语句。
29 * @param args:填充占位符的可变参数。
30 * @return:与记录对应的类的一个对象。
31 */
32 T query(String sql, Object...args);
33
34 /**
35 * 执行多条记录的查询,返回与记录对应的类的一个List。
36 * @param sql:待执行的 SQL 语句。
37 * @param args:填充占位符的可变参数。
38 * @return:与记录对应的类的一个 List。
39 */
40 List<T> queryForList(String sql, Object...args);
41
42 /**
43 * 执行一个属性或值得查询,例如查询某一条记录的一个字段或查询某个统计信息,返回要查询的值。
44 * @param sql:待执行的 SQL 语句。
45 * @param args:填充占位符的可变参数。
46 * @return:返回要查询的一个属性或值。
47 */
48 <E> E getForValue(String sql, Object...args);
49
50 /**
51 * 执行批量根性操作
52 * @param sql:待执行的 SQL 语句。
53 * @param params:填充占位符的可变参数。
54 */
55 void batch(String sql, Object[]...params);
56 }
BookDao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import java.util.Collection;
4 import java.util.List;
5
6 import com.hnust.bookstore.domain.Book;
7 import com.hnust.bookstore.domain.ShoppingCartItem;
8 import com.hnust.bookstore.web.CriteriaBook;
9 import com.hnust.bookstore.web.Page;
10
11 public interface BookDao {
12
13 /**
14 * 根据 bookId 获取指定的 Book 对象
15 * @param bookId
16 * @return
17 */
18 public abstract Book getBook(int bookId);
19
20 /**
21 * 根据传入的CriteriaBook 对象返回对应的 Page 对象。
22 * @param cb
23 * @return
24 */
25 public abstract Page<Book> getPage(CriteriaBook cb);
26
27 /**
28 * 根据传入的 CriteriaBook 对象返回对应的记录个数。
29 * @param cb
30 * @return
31 */
32 public abstract long getTotalBookNumber(CriteriaBook cb);
33
34 /**
35 * 根据传入的 CriteriaBook 和 pageSize 返回当前页对应的 List。
36 * @param cb
37 * @param pageSize
38 * @return
39 */
40 public abstract List<Book> getPageList(CriteriaBook cb, int pageSize);
41
42 /**
43 * 返回指定的 id 的 book 的 storeNumber 字段的值。
44 * @param id
45 * @return
46 */
47 public abstract int getStoreNumber(Integer bookId);
48
49 /**
50 * 根据传入的 ShoppingCartItem 的集合,
51 * 批量更新 books 数据表的 storenumber 和 salesnumber 字段的值
52 * @param items
53 */
54 public abstract void batchUpdateStoreNUmberAndSalesAmount(Collection<ShoppingCartItem> items);
55 }
AccountDao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import com.hnust.bookstore.domain.Account;
4
5 public interface AccountDao {
6
7 /**
8 * 根据传入的 accountId 获取对应的 Account 对象。
9 * @param accountId
10 * @return
11 */
12 public abstract Account get(Integer accountId);
13
14 /**
15 * 根据传入的 accountId、amount 更新指定账户的余额:扣除 amount 指定的钱数。
16 * @param accountId
17 * @param amount
18 */
19 public abstract void updateBalance(Integer accountId, float amount);
20 }
TradeDao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import java.util.Set;
4
5 import com.hnust.bookstore.domain.Trade;
6
7 public interface TradeDao {
8
9 /**
10 * 向数据表中插入 Trade 对象
11 * @param trade
12 */
13 public abstract void insert(Trade trade);
14
15 /**
16 * 根据 userId 获取和其关联的 Trade 的集合
17 * @param userId
18 * @return
19 */
20 public abstract Set<Trade> getTradesWithUserId(Integer userId);
21 }
TradeItemDao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import java.util.Collection;
4 import java.util.Set;
5
6 import com.hnust.bookstore.domain.TradeItem;
7
8 public interface TradeItemDao {
9
10 /**
11 * 批量保存 TradeItem 对象
12 * @param items
13 */
14 public abstract void batchSave(Collection<TradeItem> items);
15
16 /**
17 * 根据 tradeId 获取和其关联的 TradeItem 的集合。
18 * @param tradeId
19 * @return
20 */
21 public abstract Set<TradeItem> getTradeItemsWithTradeId(Integer tradeId);
22 }
UserDao 接口 代码:
1 package com.hnust.bookstore.dao;
2
3 import com.hnust.bookstore.domain.User;
4
5 public interface UserDao {
6
7 /**
8 * 根据用户名获取 User 对象。
9 * @param userName
10 * @return
11 */
12 public abstract User getUser(String userName);
13 }
封装翻页信息的 Page 类:
-pageNo (当前页的页码)
-list (本业需要显示的 list (选购的书籍的集合))
-pageSize (每页显示多少条记录)
-totalItemNumber (总的记录数,用来计算总的页数)
-Page(int) : 构造器,初始化当前页的页码 pageNo,在Servlet 里面对其进行赋值。
-getPageNo():返回当前页的页码,注意:需通过 getTatalPageNumber() 进行校验,因为有可能传入的页码不一定是合法的。
-getList():
-setList():设置当前页需要显示的 List 对象,是在 DAO 对其进行赋值。
-getPageSize():返回当前页显示多少条记录
-getTotalPageNumber():获取总页码数,需计算得出
-setTotalItemNumber():设置总的记录数,是在 DAO 对其进行赋值。
-isHasNext()
-isHasPrev()
-getPrevPage()
-getNextPage()
封装查询条件的 CriteriaBook 类:
-minPrice:价格区间的最小值,默认为 0
-maxPrice:价格区间的最大值,默认为 Integer.MAX_VALUE
-pageNo:当前页的页码
-CriteriaBook()
-CriteriaBook(int, int, int)
-getMinPrice()
-setMinPrice(int)
-getMaxPrice()
-setMaxPrice(int)
-getPageNo()
-setPageNo(int)
-toString()
BaseDao 代码:
1 package com.hnust.bookstore.dao.impl;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.Statement;
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.bookstore.dao.Dao;
15 import com.hnust.bookstore.db.JDBCUtils;
16 import com.hnust.bookstore.utils.ReflectionUtils;
17 import com.hnust.bookstore.web.ConnectionContext;
18 import com.sun.org.apache.regexp.internal.recompile;
19
20 public class BaseDao<T> implements Dao<T> {
21
22 private QueryRunner queryRunner = new QueryRunner();
23
24 private Class<T> clazz;
25
26 public BaseDao(){
27 clazz = ReflectionUtils.getSuperGenericType(getClass());
28 }
29
30 @Override
31 public void update(String sql, Object... args) {
32
33 Connection conn = null;
34
35 try {
36 //获取连接
37 conn = JDBCUtils.getConnection();
38 queryRunner.update(conn, sql, args);
39
40 } catch (Exception e) {
41 e.printStackTrace(); }
42 }finally{
43 JDBCUtils.release(conn);
44 }
45 }
46
47 @Override
48 public long insert(String sql, Object... args) {
49
50 long id = 0;
51 Connection conn = null;
52 PreparedStatement ps = null;
53 ResultSet rs = null;
54
55 try {
56 conn = JDBCUtils.getConnection();
57 ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
58
59 if(args != null){
60 for(int i = 0; i < args.length; i++){
61 ps.setObject(i + 1, args[i]);
62 }
63 }
64 ps.executeUpdate();
65 //获取生成的主键值
66 rs = ps.getGeneratedKeys();
67 if(rs.next()){
68 id = rs.getLong(1);
69 }
70 } catch (Exception e) {
71 e.printStackTrace();
72 }finally{
73 JDBCUtils.release(rs, ps);
74 JDBCUtils.release(conn);
75 }
76 return id;
77 }
78
79 @Override
80 public T query(String sql, Object... args) {
81 Connection conn = null;
82
83 try {
84 conn = JDBCUtils.getConnection();
85 return queryRunner.query(conn, sql, new BeanHandler<>(clazz), args);
86 } catch (Exception e) {
87 e.printStackTrace();
88 }
89 finally{
90 JDBCUtils.release(conn);
91 }
92 return null;
93 }
94
95 @Override
96 public List<T> queryForList(String sql, Object... args) {
97
98 Connection conn = null;
99 try {
100 conn = JDBCUtils.getConnection();
101 return queryRunner.query(conn, sql, new BeanListHandler<>(clazz), args);
102 } catch (Exception e) {
103 e.printStackTrace();
104 }
105 finally{
106 JDBCUtils.release(conn);
107 }
108 return null;
109 }
110
111 @Override
112 public <E> E getForValue(String sql, Object... args) {
113 Connection conn = null;
114
115 try {
116 conn = JDBCUtils.getConnection();
117 return (E) queryRunner.query(conn, sql, new ScalarHandler(), args);
118 } catch (Exception e) {
119 e.printStackTrace();
120 }
121 finally{
122 JDBCUtils.release(conn);
123 }
124 return null;
125 }
126
127 @Override
128 public void batch(String sql, Object[]... params) {
129 Connection conn = null;
130
131 try {
132 conn = JDBCUtils.getConnection();
133 queryRunner.batch(conn, sql, params);
134 } catch (Exception e) {
135 e.printStackTrace();
136 }
137 finally{
138 JDBCUtils.release(conn);
139 }
140 }
141
142 }
最后完成对以上剩余DAO层的实现,BookDaoImpl、AccountDaoImpl、TradeDaoImpl、TradeItemDaoImpl、UserDaoImpl。
明天继续,over。