前言
只有光头才能变强。
文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y
项目GitHub地址:
https://github.com/ZhongFuCheng3y/BookSystem
用户模块
要登陆后才能购买,因此我们先写购买模块.
设计实体
private String id;private String username;private String password;private String email;private String cellphone;private String address;//各种setter、getter
private String username;
private String password;
private String email;
private String cellphone;
private String address;
//各种setter、getter
设计数据库表
CREATE TABLE user ( id VARCHAR(40) PRIMARY KEY, username VARCHAR(20) NOT NULL, cellphone VARCHAR(20) NOT NULL, address VARCHAR(40) NOT NULL, email VARCHAR(30), password VARCHAR(30) NOT NULL);TABLE user (
id VARCHAR(40) PRIMARY KEY,
username VARCHAR(20) NOT NULL,
cellphone VARCHAR(20) NOT NULL,
address VARCHAR(40) NOT NULL,
email VARCHAR(30),
password VARCHAR(30) NOT NULL
);
编写DAO
/** * 用户的登录注册模块 * 1:登陆 * 2:注册 * 3:根据id查找具体的用户 */public class UserDaoImpl { public void register(User user) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "INSERT INTO user (id,username,cellphone,address,email,password) VALUES(?,?,?,?,?,?)"; try { queryRunner.update(sql, new Object[]{user.getId(),user.getUsername(), user.getCellphone(), user.getAddress(), user.getEmail(), user.getPassword()}); } catch (SQLException e) { throw new RuntimeException(e); } } public User login(String username, String password) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM user WHERE username = ? AND password=?"; try { return (User) queryRunner.query(sql, new Object[]{username, password}, new BeanHandler(User.class)); } catch (SQLException e) { throw new RuntimeException(e); } } public User find(String id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM user WHERE id=?"; try { return (User) queryRunner.query(sql, id, new BeanHandler(User.class)); } catch (SQLException e) { throw new RuntimeException(e); } }}
public class UserDaoImpl {
public void register(User user) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "INSERT INTO user (id,username,cellphone,address,email,password) VALUES(?,?,?,?,?,?)";
try {
queryRunner.update(sql, new Object[]{user.getId(),user.getUsername(), user.getCellphone(), user.getAddress(), user.getEmail(), user.getPassword()});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public User login(String username, String password) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM user WHERE username = ? AND password=?";
try {
return (User) queryRunner.query(sql, new Object[]{username, password}, new BeanHandler(User.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public User find(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM user WHERE id=?";
try {
return (User) queryRunner.query(sql, id, new BeanHandler(User.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
抽取DAO
public interface UserDao { void register(User user); User login(String username, String password); User find(String id);}interface UserDao {
void register(User user);
User login(String username, String password);
User find(String id);
}
编写Service
private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);public void registerUser(User user) { userDao.register(user);}public User loginUser(String username,String password) { return userDao.login(username, password);}public User findUser(String id) { return userDao.find(id);}"zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);
public void registerUser(User user) {
userDao.register(user);
}
public User loginUser(String username,String password) {
return userDao.login(username, password);
}
public User findUser(String id) {
return userDao.find(id);
}
前台样式
<div id="User"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <button name="login">登陆</button> <button name="register">注册</button></div>
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<button name="login">登陆</button>
<button name="register">注册</button>
</div>
#body { position: relative;}#user { position: absolute; margin-top: 130px; margin-left: 1364px;}
position: relative;
}
#user {
position: absolute;
margin-top: 130px;
margin-left: 1364px;
}
实现登陆注册功能
当点击登陆按钮的时候,把数据带过去给Servlet,让Servlet调用BusinessService方法,实现登陆。注册同理…..因此,我们需要用到JavaScript代码
<c:if test="${user==null}" ><div id="User"> 用户名:<input type="text" id="username"> 密码:<input type="password" id="password"> <button name="login" onclick="login()">登陆</button> <button name="register" onclick="register()">注册</button></div></c:if><c:if test="${user!=null}" > <div id="User"> 欢迎您:${user.username} <a href="${pageContext.request.contextPath}/UserServlet?method=Logout">注销</a> </div></c:if>"${user==null}" >
<div id="User">
用户名:<input type="text" id="username">
密码:<input type="password" id="password">
<button name="login" onclick="login()">登陆</button>
<button name="register" onclick="register()">注册</button>
</div>
</c:if>
<c:if test="${user!=null}" >
<div id="User">
欢迎您:${user.username} <a href="${pageContext.request.contextPath}/UserServlet?method=Logout">注销</a>
</div>
</c:if>
<script type="text/javascript"> function login() { //得到输入框的数据 var username = document.getElementById("username").value; var password = document.getElementById("password").value; //跳转到相对应的Servlet上 window.location.href = "${pageContext.request.contextPath}/UserServlet?method=login&username=" + username + "&password=" + password; } function register() { //跳转到注册页面 window.location.href = "${pageContext.request.contextPath}/client/register.jsp"; } </script>
function login() {
//得到输入框的数据
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
//跳转到相对应的Servlet上
window.location.href = "${pageContext.request.contextPath}/UserServlet?method=login&username=" + username + "&password=" + password;
}
function register() {
//跳转到注册页面
window.location.href = "${pageContext.request.contextPath}/client/register.jsp";
}
</script>
String method = request.getParameter("method");BussinessServiceImpl service = new BussinessServiceImpl();if (method.equals("login")) { try { //得到页面传递过来的数据 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = service.loginUser(username, password); request.getSession().setAttribute("user",user); request.getRequestDispatcher("/client/head.jsp").forward(request, response); } catch (Exception e) { request.setAttribute("message", "登陆失败了!"); request.getRequestDispatcher("/message.jsp").forward(request, response); }} else if (method.equals("register")) { try { //得到JSP传递过来的数据,封装成Bean对象 User user = WebUtils.request2Bean(request, User.class); user.setId(WebUtils.makeId()); service.registerUser(user); request.setAttribute("message", "注册成功了!"); } catch (Exception e) { e.printStackTrace(); request.setAttribute("message", "注册失败了!"); } request.getRequestDispatcher("/message.jsp").forward(request, response);} else if (method.equals("Logout")) { //销毁session request.getSession().invalidate(); //回到首页 request.getRequestDispatcher("/client/head.jsp").forward(request, response);}
BussinessServiceImpl service = new BussinessServiceImpl();
if (method.equals("login")) {
try {
//得到页面传递过来的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = service.loginUser(username, password);
request.getSession().setAttribute("user",user);
request.getRequestDispatcher("/client/head.jsp").forward(request, response);
} catch (Exception e) {
request.setAttribute("message", "登陆失败了!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
} else if (method.equals("register")) {
try {
//得到JSP传递过来的数据,封装成Bean对象
User user = WebUtils.request2Bean(request, User.class);
user.setId(WebUtils.makeId());
service.registerUser(user);
request.setAttribute("message", "注册成功了!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "注册失败了!");
}
request.getRequestDispatcher("/message.jsp").forward(request, response);
} else if (method.equals("Logout")) {
//销毁session
request.getSession().invalidate();
//回到首页
request.getRequestDispatcher("/client/head.jsp").forward(request, response);
}
购买模块
在显示图书的时候,顺便添加购买的超链接
<li><a href="#">购买</a></li><a href="#">购买</a></li>
设计购物车实体
如果不清楚为什么这样设计,可参考我之前的博文:http://blog.csdn.net/hon_3y/article/details/56481439#t5
public class Cart { private Map<String, CartItem> map = new HashMap<>(); private double price; //提供把商品添加到购物的功能 public void addBook2Cart(Book book) { //得到对应的购物项 CartItem cartItem = map.get(book.getId()); //如果是null,说明购物车还没有该购物项 if (cartItem == null) { cartItem = new CartItem(); cartItem.setQuantity(1); cartItem.setBook(book); cartItem.setPrice(book.getPrice()); //把购物项加到购物车中 map.put(book.getId(), cartItem); } else { //如果购物车有该购物项了,那么将购物项的数量+1 cartItem.setQuantity(cartItem.getQuantity() + 1); } } //购物车的价钱是购物项价钱的总和 public double getPrice() { double totalPrice = 0; for (Map.Entry<String, CartItem> me : map.entrySet()) { CartItem cartItem = me.getValue(); totalPrice += cartItem.getPrice(); } return totalPrice; } public Map<String, CartItem> getMap() { return map; } public void setMap(Map<String, CartItem> map) { this.map = map; } public void setPrice(double price) { this.price = price; }}class Cart {
private Map<String, CartItem> map = new HashMap<>();
private double price;
//提供把商品添加到购物的功能
public void addBook2Cart(Book book) {
//得到对应的购物项
CartItem cartItem = map.get(book.getId());
//如果是null,说明购物车还没有该购物项
if (cartItem == null) {
cartItem = new CartItem();
cartItem.setQuantity(1);
cartItem.setBook(book);
cartItem.setPrice(book.getPrice());
//把购物项加到购物车中
map.put(book.getId(), cartItem);
} else {
//如果购物车有该购物项了,那么将购物项的数量+1
cartItem.setQuantity(cartItem.getQuantity() + 1);
}
}
//购物车的价钱是购物项价钱的总和
public double getPrice() {
double totalPrice = 0;
for (Map.Entry<String, CartItem> me : map.entrySet()) {
CartItem cartItem = me.getValue();
totalPrice += cartItem.getPrice();
}
return totalPrice;
}
public Map<String, CartItem> getMap() {
return map;
}
public void setMap(Map<String, CartItem> map) {
this.map = map;
}
public void setPrice(double price) {
this.price = price;
}
}
设计购物项实体
public class CartItem { private Book book; private double price; private int quantity; public double getPrice() { return this.book.getPrice() * this.quantity; } public void setPrice(double price) { this.price = price; } public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; }}class CartItem {
private Book book;
private double price;
private int quantity;
public double getPrice() {
return this.book.getPrice() * this.quantity;
}
public void setPrice(double price) {
this.price = price;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
处理用户想要买的书籍Servlet
<li><a href="${pageContext.request.contextPath}/BuyServlet?book_id=${book.id}">购买</a></li><a href="${pageContext.request
.contextPath}/BuyServlet?book_id=${book.id}">购买</a></li>
BussinessServiceImpl service = new BussinessServiceImpl();//先检查该用户是否登陆了。User user = (User) request.getSession().getAttribute("user");if (user == null) { request.setAttribute("message", "您还没登陆,请登陆了再来购买"); request.getRequestDispatcher("/message.jsp").forward(request, response); return ;}//如果登陆了...//得到该用户的购物车Cart cart = (Cart) request.getSession().getAttribute("cart");if (cart == null) { cart = new Cart(); request.getSession().setAttribute("cart", cart);}//得到用户想买的书籍String book_id = request.getParameter("book_id");Book book = service.findBook(book_id);//把书籍添加到购物车中service.buyBook(cart, book);request.setAttribute("message", "该商品已添加到购物车中");request.getRequestDispatcher("/message.jsp").forward(request,response);
//先检查该用户是否登陆了。
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没登陆,请登陆了再来购买");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return ;
}
//如果登陆了...
//得到该用户的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
request.getSession().setAttribute("cart", cart);
}
//得到用户想买的书籍
String book_id = request.getParameter("book_id");
Book book = service.findBook(book_id);
//把书籍添加到购物车中
service.buyBook(cart, book);
request.setAttribute("message", "该商品已添加到购物车中");
request.getRequestDispatcher("/message.jsp").forward(request,response);
提供显示购物车商品的Servlet
//先判断该用户是否登陆了User user = (User) request.getSession().getAttribute("user");if (user == null) { request.setAttribute("message", "您还没有登陆呢!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return;}//如果登陆了.....Cart cart = (Cart) request.getSession().getAttribute("cart");//把该用户的购物车给JSP页面显示request.setAttribute("cart", cart);request.getRequestDispatcher("/client/listCart.jsp").forward(request, response);
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没有登陆呢!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果登陆了.....
Cart cart = (Cart) request.getSession().getAttribute("cart");
//把该用户的购物车给JSP页面显示
request.setAttribute("cart", cart);
request.getRequestDispatcher("/client/listCart.jsp").forward(request, response);
显示购物车的JSP页面
<c:if test="${empty(cart.map)}"> 您还没有购买过任何商品哦!!!</c:if><table border="1px"> <c:if test="${!empty(cart.map)}"> <h1>您购物车下有如下的商品:</h1><br> <tr> <td>书名:</td> <td>作者:</td> <td>数量:</td> <td>价钱:</td> </tr> <c:forEach items="${cart.map}" var="cartItme"> <tr> <td>${cartItme.value.book.name}</td> <td>${cartItme.value.book.author}</td> <td>${cartItme.value.quantity}</td> <td>${cartItme.value.price}</td> </tr> </c:forEach> </c:if></table>"${empty(cart.map)}">
您还没有购买过任何商品哦!!!
</c:if>
<table border="1px">
<c:if test="${!empty(cart.map)}">
<h1>您购物车下有如下的商品:</h1><br>
<tr>
<td>书名:</td>
<td>作者:</td>
<td>数量:</td>
<td>价钱:</td>
</tr>
<c:forEach items="${cart.map}" var="cartItme">
<tr>
<td>${cartItme.value.book.name}</td>
<td>${cartItme.value.book.author}</td>
<td>${cartItme.value.quantity}</td>
<td>${cartItme.value.price}</td>
</tr>
</c:forEach>
</c:if>
</table>
效果:
订单模块
在前台用户界面中,当用户要把购物车付款时,应该提供生成订单的超链接….
设计订单实体
订单应该包含id,收货人信息,下单的时间,订单的总价,订单的状态【有无发货】..而不应该包含商品的信息的。商品的信息用一个专门的”订单项“来表示
一个订单对应多个订单项,这是一对多的关系!
private String id;//下单的时间、日期、状态private Date date;private double price;private boolean state;//一个用户可以有多个订单,把用户记住private String user_id;//一个订单中有多个订单项private Set<OrderItem> items = new HashSet<>();//各种的setter和getter
//下单的时间、日期、状态
private Date date;
private double price;
private boolean state;
//一个用户可以有多个订单,把用户记住
private String user_id;
//一个订单中有多个订单项
private Set<OrderItem> items = new HashSet<>();
//各种的setter和getter
设计订单项实体
private String id;//一本书对应多个订单项,订单项一定是由书组成,记住书private String book_id;private double price;private int quantity;//各种的setter和getter
//一本书对应多个订单项,订单项一定是由书组成,记住书
private String book_id;
private double price;
private int quantity;
//各种的setter和getter
设计数据库表
mysql不能创建名为”order”的表,后边加个s就可以
CREATE TABLE orders ( id VARCHAR(40) PRIMARY KEY, date DATE NOT NULL, user_id VARCHAR(40) NOT NULL, state BOOLEAN, price DOUBLE, CONSTRAINT user_id_FK FOREIGN KEY (user_id) REFERENCES user (id));TABLE orders (
id VARCHAR(40) PRIMARY KEY,
date DATE NOT NULL,
user_id VARCHAR(40) NOT NULL,
state BOOLEAN,
price DOUBLE,
CONSTRAINT user_id_FK FOREIGN KEY (user_id) REFERENCES user (id)
);
CREATE TABLE orderItem ( id VARCHAR(40) PRIMARY KEY, price DOUBLE, quantity INT, order_id VARCHAR(40) , book_id VARCHAR(40) , CONSTRAINT order_id_FK FOREIGN KEY (order_id) REFERENCES orders (id), CONSTRAINT book_id_FK FOREIGN KEY (book_id) REFERENCES book (id));TABLE orderItem (
id VARCHAR(40) PRIMARY KEY,
price DOUBLE,
quantity INT,
order_id VARCHAR(40) ,
book_id VARCHAR(40) ,
CONSTRAINT order_id_FK FOREIGN KEY (order_id) REFERENCES orders (id),
CONSTRAINT book_id_FK FOREIGN KEY (book_id) REFERENCES book (id)
);
设计Dao
public class OrderDaoImpl implements zhongfucheng.dao.OrderDao { @Override public void addOrder(Order order) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql1 = "INSERT INTO orders(id,ordertime,user_id,state,price) VALUES(?,?,?,?,?)"; try { //订单的基本信息 queryRunner.update(sql1, new Object[]{order.getId(), order.getOrdertime(), order.getUser_id(), order.isState(), order.getPrice()}); //订单项的信息 String sql2 = "INSERT INTO orderItem(id,price,quantity,order_id,book_id) VALUES(?,?,?,?,?)"; Set<OrderItem> items = order.getItems(); for (OrderItem item : items) { queryRunner.update(sql2, new Object[]{item.getId(), item.getPrice(), item.getQuantity(), item.getOrder_id(), item.getBook_id()}); } } catch (SQLException e) { throw new RuntimeException(e); } } @Override public Order findOrder(String id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); Order order; try { //找出订单的基本信息 String sql = "SELECT * FROM orders WHERE id=?"; order = (Order) queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{id}); //找出订单的所有订单项 String sql2 = "SELECT * FROM orderItem WHERE order_id=?"; List<OrderItem> list = (List<OrderItem>) queryRunner.query(sql2, new BeanListHandler(OrderItem.class), new Object[]{order.getId()}); System.out.println("这是数据库拿到的list集合:"+list.size()); //将所有订单项装到订单里边 order.getItems().addAll(list); System.out.println("这是数据库拿到的"+order.getItems().size()); //找出该订单是属于哪一个用户的 String sql3 = "SELECT * FROM orders o,user u WHERE o.user_id=u.id AND o.id=? "; User user = (User) queryRunner.query(sql3, new BeanHandler(User.class), new Object[]{order.getId()}); order.setUser_id(user.getId()); return order; } catch (SQLException e) { throw new RuntimeException(e); } } //更新订单的状态 public void updateState(String id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "UPDATE orders SET state=? WHERE id=?"; try { queryRunner.update(sql, new Object[]{true, id}); } catch (SQLException e) { throw new RuntimeException(e); } } //查看已经发货或没发货的订单信息 public List<Order> getAllOrder(boolean state) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM orders WHERE state=? "; try { return (List<Order>) queryRunner.query(sql, new BeanListHandler(Order.class), new Object[]{state}); } catch (SQLException e) { throw new RuntimeException(e); } } //通过用户的id查找用户的订单,可能不止一个 public List<Order> findUserOrder(String user_id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM orders WHERE user_id=? "; try { return List<Order> queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{user_id}); } catch (SQLException e) { throw new RuntimeException(e); } }}class OrderDaoImpl implements zhongfucheng.dao.OrderDao {
@Override
public void addOrder(Order order) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql1 = "INSERT INTO orders(id,ordertime,user_id,state,price) VALUES(?,?,?,?,?)";
try {
//订单的基本信息
queryRunner.update(sql1, new Object[]{order.getId(), order.getOrdertime(), order.getUser_id(), order.isState(), order.getPrice()});
//订单项的信息
String sql2 = "INSERT INTO orderItem(id,price,quantity,order_id,book_id) VALUES(?,?,?,?,?)";
Set<OrderItem> items = order.getItems();
for (OrderItem item : items) {
queryRunner.update(sql2, new Object[]{item.getId(), item.getPrice(), item.getQuantity(), item.getOrder_id(), item.getBook_id()});
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Order findOrder(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
Order order;
try {
//找出订单的基本信息
String sql = "SELECT * FROM orders WHERE id=?";
order = (Order) queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{id});
//找出订单的所有订单项
String sql2 = "SELECT * FROM orderItem WHERE order_id=?";
List<OrderItem> list = (List<OrderItem>) queryRunner.query(sql2, new BeanListHandler(OrderItem.class), new Object[]{order.getId()});
System.out.println("这是数据库拿到的list集合:"+list.size());
//将所有订单项装到订单里边
order.getItems().addAll(list);
System.out.println("这是数据库拿到的"+order.getItems().size());
//找出该订单是属于哪一个用户的
String sql3 = "SELECT * FROM orders o,user u WHERE o.user_id=u.id AND o.id=? ";
User user = (User) queryRunner.query(sql3, new BeanHandler(User.class), new Object[]{order.getId()});
order.setUser_id(user.getId());
return order;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//更新订单的状态
public void updateState(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "UPDATE orders SET state=? WHERE id=?";
try {
queryRunner.update(sql, new Object[]{true, id});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//查看已经发货或没发货的订单信息
public List<Order> getAllOrder(boolean state) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM orders WHERE state=? ";
try {
return (List<Order>) queryRunner.query(sql, new BeanListHandler(Order.class), new Object[]{state});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//通过用户的id查找用户的订单,可能不止一个
public List<Order> findUserOrder(String user_id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM orders WHERE user_id=? ";
try {
return List<Order> queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{user_id});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
二次更新
在编写dao的时候,尤其是Add方法。它是将所有数据都封装到Order对象上,然后取出数据,把数据插入到数据表中
抽取成DAO接口
public interface OrderDao { void addOrder(Order order); Order findOrder(String id); List<Order> getAllOrder(boolean state); void updateState(String user_id); List<Order> findUserOrder(String user_id);}interface OrderDao {
void addOrder(Order order);
Order findOrder(String id);
List<Order> getAllOrder(boolean state);
void updateState(String user_id);
List<Order> findUserOrder(String user_id);
}
BussinessService
private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);public void createOrder(Cart cart, User user) { //订单的基本信息 String order_id = WebUtils.makeId(); Order order = new Order(); order.setId(order_id); order.setPrice(cart.getPrice()); order.setOrdertime(new Date()); order.setState(false); order.setUser_id(user.getId()); //订单项的基本信息 //得到每个购物项,购物项就作为订单项 for (Map.Entry<String, CartItem> me : cart.getMap().entrySet()) { OrderItem orderItem = new OrderItem(); CartItem cartItem = me.getValue(); orderItem.setId(WebUtils.makeId()); orderItem.setPrice(cartItem.getPrice()); orderItem.setBook_id(cartItem.getBook().getId()); orderItem.setQuantity(cartItem.getQuantity()); orderItem.setOrder_id(order_id); order.getItems().add(orderItem); } orderDao.addOrder(order);}public Order findOrder(String user_id) { return orderDao.findOrder(user_id);}public List<Order> getAllOrder(boolean state) { return orderDao.getAllOrder(state);}public void sendOutOrder(String id) { orderDao.updateState(id);}public List<Order> findUserOrder(String user_id) { return orderDao.findUserOrder(user_id);}"zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);
public void createOrder(Cart cart, User user) {
//订单的基本信息
String order_id = WebUtils.makeId();
Order order = new Order();
order.setId(order_id);
order.setPrice(cart.getPrice());
order.setOrdertime(new Date());
order.setState(false);
order.setUser_id(user.getId());
//订单项的基本信息
//得到每个购物项,购物项就作为订单项
for (Map.Entry<String, CartItem> me : cart.getMap().entrySet()) {
OrderItem orderItem = new OrderItem();
CartItem cartItem = me.getValue();
orderItem.setId(WebUtils.makeId());
orderItem.setPrice(cartItem.getPrice());
orderItem.setBook_id(cartItem.getBook().getId());
orderItem.setQuantity(cartItem.getQuantity());
orderItem.setOrder_id(order_id);
order.getItems().add(orderItem);
}
orderDao.addOrder(order);
}
public Order findOrder(String user_id) {
return orderDao.findOrder(user_id);
}
public List<Order> getAllOrder(boolean state) {
return orderDao.getAllOrder(state);
}
public void sendOutOrder(String id) {
orderDao.updateState(id);
}
public List<Order> findUserOrder(String user_id) {
return orderDao.findUserOrder(user_id);
}
生成订单的Servlet
BussinessServiceImpl service = new BussinessServiceImpl(); //检查该用户的购物车是否有商品 Cart cart = (Cart) request.getSession().getAttribute("cart"); if (cart == null) { request.setAttribute("message", "您购物车没有商品,无法生成订单"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } //如果有商品,得到当前用户 User user = (User) request.getSession().getAttribute("user"); service.createOrder(cart, user); request.setAttribute("message", "订单已经生成了,准备好钱来收货把"); request.getRequestDispatcher("/message.jsp").forward(request, response); return;
//检查该用户的购物车是否有商品
Cart cart = (Cart) request.getSession().getAttribute("cart");
if (cart == null) {
request.setAttribute("message", "您购物车没有商品,无法生成订单");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果有商品,得到当前用户
User user = (User) request.getSession().getAttribute("user");
service.createOrder(cart, user);
request.setAttribute("message", "订单已经生成了,准备好钱来收货把");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
用户查询自己的订单Servlet
<a href="${pageContext.request.contextPath}/LookOrder" target="body">查看订单</a></a>
BussinessServiceImpl service = new BussinessServiceImpl();//检查该用户是否登陆了User user = (User) request.getSession().getAttribute("user");if (user == null) { request.setAttribute("message", "您还没登陆,等您登陆了再来看把"); request.getRequestDispatcher("/message.jsp").forward(request, response); return;}//用户登陆了!Order order = service.findUserOrder(user.getId());//交给相对应的JSP 显示request.setAttribute("order", order);request.setAttribute("user",user);request.getRequestDispatcher("/client/listOrder.jsp").forward(request, response);return ;
//检查该用户是否登陆了
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没登陆,等您登陆了再来看把");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//用户登陆了!
Order order = service.findUserOrder(user.getId());
//交给相对应的JSP 显示
request.setAttribute("order", order);
request.setAttribute("user",user);
request.getRequestDispatcher("/client/listOrder.jsp").forward(request, response);
return ;
显示订单数据的JSP
<c:if test="${order==null}"> 您还没有下过任何订单!!</c:if><c:if test="${order!=null}"> <table border="1px"> <tr> <td>下单人:</td> <td>订单时间</td> <td>订单状态</td> <td>订单价钱</td> </tr> <tr> <td>${user.username}</td> <td>${order.ordertime}</td> <td>${order.state==false?"未发货":"已发货"}</td> <td>${order.price}</td> </tr> </table></c:if>"${order==null}">
您还没有下过任何订单!!
</c:if>
<c:if test="${order!=null}">
<table border="1px">
<tr>
<td>下单人:</td>
<td>订单时间</td>
<td>订单状态</td>
<td>订单价钱</td>
</tr>
<tr>
<td>${user.username}</td>
<td>${order.ordertime}</td>
<td>${order.state==false?"未发货":"已发货"}</td>
<td>${order.price}</td>
</tr>
</table>
</c:if>
效果:
后台查询订单的状况Servlet
<a href="${pageContext.request.contextPath}/OrderServlet?state=false" target="body">待处理订单</a><br><a href="${pageContext.request.contextPath}/OrderServlet?state=true" target="body">已发货订单</a><br></a><br>
<a href="${pageContext.request.contextPath}/OrderServlet?state=true" target="body">已发货订单</a><br>
BussinessServiceImpl service = new BussinessServiceImpl();String state = request.getParameter("state");if (state.equals("true")) { List<Order> list = service.getAllOrder(true); request.setAttribute("list",list);} else if (state.equals("false")) { List<Order> list = service.getAllOrder(false); request.setAttribute("list", list);}request.getRequestDispatcher("/background/listOrder.jsp").forward(request, response);
String state = request.getParameter("state");
if (state.equals("true")) {
List<Order> list = service.getAllOrder(true);
request.setAttribute("list",list);
} else if (state.equals("false")) {
List<Order> list = service.getAllOrder(false);
request.setAttribute("list", list);
}
request.getRequestDispatcher("/background/listOrder.jsp").forward(request, response);
显示订单状况的JSP
<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> </tr> <c:forEach items="${list}" var="order"> <tr> <td>${order.user_id}</td> <td>${order.ordertime}</td> <td>${order.state==false?"未发货":"已发货"}</td> <td>${order.price}</td> <td> <a href="${pageContext.request.contextPath}/orderItemServlet?order_id=${order.id}">查看详细信息</a> <a href="#">删除</a> </td> </tr> </c:forEach> </table></c:if>
还没有任何订单哦!
</c:if>
<c:if test="${!empty(list)}">
<table border="1px">
<tr>
<td>下单人:</td>
<td>订单时间</td>
<td>订单状态</td>
<td>订单价钱</td>
<td>操作</td>
</tr>
<c:forEach items="${list}" var="order">
<tr>
<td>${order.user_id}</td>
<td>${order.ordertime}</td>
<td>${order.state==false?"未发货":"已发货"}</td>
<td>${order.price}</td>
<td>
<a href="${pageContext.request.contextPath}/orderItemServlet?order_id=${order.id}">查看详细信息</a>
<a href="#">删除</a>
</td>
</tr>
</c:forEach>
</table>
</c:if>
查看具体订单的详细信息Servlet
BussinessServiceImpl service = new BussinessServiceImpl();//得到用户想要查看详细信息的表单String order_id = request.getParameter("order_id");Order order = service.findOrder(order_id);//将该order对象给相对应的JSP显示request.setAttribute("order", order);request.getRequestDispatcher("/background/listDetail.jsp").forward(request, response);
//得到用户想要查看详细信息的表单
String order_id = request.getParameter("order_id");
Order order = service.findOrder(order_id);
//将该order对象给相对应的JSP显示
request.setAttribute("order", order);
request.getRequestDispatcher("/background/listDetail.jsp").forward(request, response);
查看具体订单的详细信息JSP
<table border="1px"> <tr> <td>书籍的编号</td> <td>价钱</td> <td>数量</td> <td>操作</td> </tr> <c:forEach items="${order.items}" var="item"> <tr> <td>${item.book_id}</td> <td>${item.price}</td> <td>${item.quantity}</td> <td><a href="${pageContext.request.contextPath}/SendOutServlet?id=${order.id}">发货</a></td> </tr> </c:forEach></table>
<tr>
<td>书籍的编号</td>
<td>价钱</td>
<td>数量</td>
<td>操作</td>
</tr>
<c:forEach items="${order.items}" var="item">
<tr>
<td>${item.book_id}</td>
<td>${item.price}</td>
<td>${item.quantity}</td>
<td><a href="${pageContext.request.contextPath}/SendOutServlet?id=${order.id}">发货</a></td>
</tr>
</c:forEach>
</table>
处理发货的Servlet
BussinessServiceImpl service = new BussinessServiceImpl(); String id = request.getParameter("id"); service.sendOutOrder(id); request.setAttribute("message", "已发货!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return;
String id = request.getParameter("id");
service.sendOutOrder(id);
request.setAttribute("message", "已发货!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
效果:
添加权限控制
目前为止,我们已经学习了动态代理技术和注解技术了。于是我们想要为之前的bookStore项目添加权限控制…..
只有用户有权限的时候,后台管理才可以进行相对应的操作…..
实现思路
之前我们做权限管理系统的时候,是根据用户请求的URI来判断该链接是否需要权限的。这次我们使用动态代理的技术和注解来判断:用户调用该方法时,检查该方法是否需要权限…
根据MVC模式,我们在web层都是调用service层来实现功能的。那么我们具体的思路是这样的:
设计实体、数据库表
上次我们做的权限管理系统是引入了角色这个概念的,这次主要为了练习动态代理和注解技术,就以简单为主,不引入角色这个实体。直接是用户和权限之间的关系了。
Privilege实体
public class Privilege { private String id ; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}class Privilege {
private String id ;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
数据库表
CREATE TABLE privilege ( id VARCHAR(40) PRIMARY KEY, name VARCHAR(40));TABLE privilege (
id VARCHAR(40) PRIMARY KEY,
name VARCHAR(40)
);
privilege和user是多对多的关系,于是使用第三方表来维护他们的关系
CREATE TABLE user_privilege ( privilege_id VARCHAR(40), user_id VARCHAR(40), PRIMARY KEY (privilege_id, user_id), CONSTRAINT privilege_id_FK FOREIGN KEY (privilege_id) REFERENCES privilege(id), CONSTRAINT user_id_FK1 FOREIGN KEY (user_id) REFERENCES user(id));TABLE user_privilege (
privilege_id VARCHAR(40),
user_id VARCHAR(40),
PRIMARY KEY (privilege_id, user_id),
CONSTRAINT privilege_id_FK FOREIGN KEY (privilege_id) REFERENCES privilege(id),
CONSTRAINT user_id_FK1 FOREIGN KEY (user_id) REFERENCES user(id)
);
添加测试数据
为了方便,直接添加数据了。就不写详细的DAO了。
编写DAO
后面在动态代理中,我们需要检查该用户是否有权限…那么就必须查找出该用户拥有的哪些权限。再看看用户有没有相对应的权限
//查找用户的所有权限public List<Privilege> findUserPrivilege(String user_id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT p.* FROM privilege p, user_privilege up WHERE p.id = up.privilege_id AND up.user_id = ?"; try { return (List<Privilege>) queryRunner.query(sql, new Object[]{user_id}, new BeanListHandler(Privilege.class)); } catch (SQLException e) { throw new RuntimeException(e); }}
public List<Privilege> findUserPrivilege(String user_id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT p.* FROM privilege p, user_privilege up WHERE p.id = up.privilege_id AND up.user_id = ?";
try {
return (List<Privilege>) queryRunner.query(sql, new Object[]{user_id}, new BeanListHandler(Privilege.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
抽取到接口上
List<Privilege> findUserPrivilege(String user_id);
注解模块
@Retention(RetentionPolicy.RUNTIME)public @interface permission { String value();}
public @interface permission {
String value();
}
@permission("添加分类")/*添加分类*/public void addCategory(Category category) { categoryDao.addCategory(category);}/*查找分类*/public void findCategory(String id) { categoryDao.findCategory(id);}@permission("查找分类")/*查看分类*/public List<Category> getAllCategory() { return categoryDao.getAllCategory();}"添加分类")
/*添加分类*/
public void addCategory(Category category) {
categoryDao.addCategory(category);
}
/*查找分类*/
public void findCategory(String id) {
categoryDao.findCategory(id);
}
@permission("查找分类")
/*查看分类*/
public List<Category> getAllCategory() {
return categoryDao.getAllCategory();
}
抽取Service
把Service的方法抽取成ServiceDao。在Servlet中,也是通过ServiceFactory来得到Service的对象【和DaoFactory是类似的】
CategoryService
@permission("添加分类")/*添加分类*/ void addCategory(Category category);/*查找分类*/void findCategory(String id);@permission("查找分类")/*查看分类*/ List<Category> getAllCategory();"添加分类")
/*添加分类*/ void addCategory(Category category);
/*查找分类*/
void findCategory(String id);
@permission("查找分类")
/*查看分类*/ List<Category> getAllCategory();
ServiceFactory
public class ServiceDaoFactory { private static final ServiceDaoFactory factory = new ServiceDaoFactory(); private ServiceDaoFactory() { } public static ServiceDaoFactory getInstance() { return factory; } //需要判断该用户是否有权限 public <T> T createDao(String className, Class<T> clazz, final User user) { System.out.println("添加分类进来了!"); try { //得到该类的类型 final T t = (T) Class.forName(className).newInstance(); //返回一个动态代理对象出去 return (T) Proxy.newProxyInstance(ServiceDaoFactory.class.getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, PrivilegeException { //判断用户调用的是什么方法 String methodName = method.getName(); System.out.println(methodName); //得到用户调用的真实方法,注意参数!!! Method method1 = t.getClass().getMethod(methodName,method.getParameterTypes()); //查看方法上有没有注解 permission permis = method1.getAnnotation(permission.class); //如果注解为空,那么表示该方法并不需要权限,直接调用方法即可 if (permis == null) { return method.invoke(t, args); } //如果注解不为空,得到注解上的权限 String privilege = permis.value(); //设置权限【后面通过它来判断用户的权限有没有自己】 Privilege p = new Privilege(); p.setName(privilege); //到这里的时候,已经是需要权限了,那么判断用户是否登陆了 if (user == null) { //这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。 throw new PrivilegeException("对不起请先登陆"); } //执行到这里用户已经登陆了,判断用户有没有权限 Method m = t.getClass().getMethod("findUserPrivilege", String.class); List<Privilege> list = (List<Privilege>) m.invoke(t, user.getId()); //看下权限集合中有没有包含方法需要的权限。使用contains方法,在Privilege对象中需要重写hashCode和equals() if (!list.contains(p)) { //这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。 throw new PrivilegeException("您没有权限,请联系管理员!"); } //执行到这里的时候,已经有权限了,所以可以放行了 return method.invoke(t, args); } }); } catch (Exception e) { new RuntimeException(e); } return null; }}class ServiceDaoFactory {
private static final ServiceDaoFactory factory = new ServiceDaoFactory();
private ServiceDaoFactory() {
}
public static ServiceDaoFactory getInstance() {
return factory;
}
//需要判断该用户是否有权限
public <T> T createDao(String className, Class<T> clazz, final User user) {
System.out.println("添加分类进来了!");
try {
//得到该类的类型
final T t = (T) Class.forName(className).newInstance();
//返回一个动态代理对象出去
return (T) Proxy.newProxyInstance(ServiceDaoFactory.class.getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, PrivilegeException {
//判断用户调用的是什么方法
String methodName = method.getName();
System.out.println(methodName);
//得到用户调用的真实方法,注意参数!!!
Method method1 = t.getClass().getMethod(methodName,method.getParameterTypes());
//查看方法上有没有注解
permission permis = method1.getAnnotation(permission.class);
//如果注解为空,那么表示该方法并不需要权限,直接调用方法即可
if (permis == null) {
return method.invoke(t, args);
}
//如果注解不为空,得到注解上的权限
String privilege = permis.value();
//设置权限【后面通过它来判断用户的权限有没有自己】
Privilege p = new Privilege();
p.setName(privilege);
//到这里的时候,已经是需要权限了,那么判断用户是否登陆了
if (user == null) {
//这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。
throw new PrivilegeException("对不起请先登陆");
}
//执行到这里用户已经登陆了,判断用户有没有权限
Method m = t.getClass().getMethod("findUserPrivilege", String.class);
List<Privilege> list = (List<Privilege>) m.invoke(t, user.getId());
//看下权限集合中有没有包含方法需要的权限。使用contains方法,在Privilege对象中需要重写hashCode和equals()
if (!list.contains(p)) {
//这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。
throw new PrivilegeException("您没有权限,请联系管理员!");
}
//执行到这里的时候,已经有权限了,所以可以放行了
return method.invoke(t, args);
}
});
} catch (Exception e) {
new RuntimeException(e);
}
return null;
}
}
PrivilegeExcetption
当用户没有登陆或者没有权限的时候,我们应该给用户一些友好的提示….于是我们自定义了PrivilegeException
public class PrivilegeException extends Exception { public PrivilegeException() { super(); } public PrivilegeException(String message) { super(message); } public PrivilegeException(String message, Throwable cause) { super(message, cause); } public PrivilegeException(Throwable cause) { super(cause); }}class PrivilegeException extends Exception {
public PrivilegeException() {
super();
}
public PrivilegeException(String message) {
super(message);
}
public PrivilegeException(String message, Throwable cause) {
super(message, cause);
}
public PrivilegeException(Throwable cause) {
super(cause);
}
}
我们继承的是Exception,通过方法名抛出去。但是我们是通过代理对象调用方法的,于是sun公司的策略就是把它们转换成运行期异常抛出去。
因此,我们就在Servlet上得到异常,再给出友好的提示。。
效果:
要点总结
该权限控制是十分优雅的,只要我在Service层中添加一个注解…那么当web层调用该方法的时候就需要判断用户有没有该权限….
外界调用Service层的方法是代理调用invoke()方法,我们在invoke()方法可以对其进行增强!
invoke()方法内部就是在查询调用该方法上有没有注解,如果没有注解,就可以直接调用。如果有注解,那么就得到注解的信息,判断该用户有没有权限来访问这个方法
在反射具体方法的时候,必须记得要给出相对应的参数!
在invoke()方法抛出的编译时期异常,java会自动转换成运行期异常进行抛出…
使用contains()方法时,就要重写该对象的hashCode()和equals()
最后
有帮助?在看!转发!乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!