JavaWeb:网上书店的案例
功能分析:
只有一个角色客户,客户可以
–查看图书信息(包括查看图书详细信息,使用条件(例价格区间)查看图书信息,对图书进行翻页)
–把图书加入购物车
–查看购物车
–修改购物车(包括清空购物车,修改购物车单本图书数量,删除单本图书)
–结账(填写用户名和账号信息)
–查看交易记录
总体架构:
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。