0.把之前的系统的Myssm部分封装为包
新建空的工件jar包
创建相同的文件夹,导入相应文件要从out里面导入字节码文件
全部设置完后点构建工件,然后点刚刚我们设置的这个工件,然后从src下的out文件相应的位置就能找到这个jar包,用于其他项目的开发了
1.熟悉业务需求
1. 需求分析
2. 数据库设计
1) 实体分析
- 图书 Book
- 用户 User
- 订单 OrderBean
- 订单详情 OrderItem
- 购物车项 CartItem
2) 实体属性分析
- 图书 : 书名、作者、价格、销量、库存、封面、状态
- 用户 : 用户名、密码、邮箱
- 订单 : 订单编号、订单日期、订单金额、订单数量、订单状态、用户
- 订单详情 : 图书、数量、所属订单
- 购物车项 : 图书、数量、所属用户
2.准备工作
新建module并把前端页面粘贴进去,我们不要像之前一样放到web下面,放到web-inf下面,因为放web下别人可以随便访问。静态资源还放web下
建立数据库和表
CREATE DATABASE bookdb CHAR SET utf8;
USE bookdb ;
CREATE TABLE `t_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bookImg` varchar(200) NOT NULL,
`bookName` varchar(20) DEFAULT NULL,
`price` double(10,2) DEFAULT NULL,
`author` varchar(20) DEFAULT NULL,
`saleCount` int(11) DEFAULT NULL,
`bookCount` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
/*Data for the table `t_book` */
insert into `t_book`(`id`,`bookImg`,`bookName`,`price`,`author`,`saleCount`,`bookCount`) values (1,'cyuyanrumenjingdian.jpg','C语言入门经典',99.00,'亚历山大',8,197),(2,'santi.jpg','三体',48.95,'周杰伦',18,892),(3,'ailuntulingzhuan.jpg','艾伦图灵传',50.00,'刘若英',12,143),(4,'bainiangudu.jpg','百年孤独',40.00,'王力宏',3,98),(5,'biancheng.jpg','边城',30.00,'刘德华',2,99),(6,'jieyouzahuodian.jpg','解忧杂货店',27.00,'东野圭吾',5,100),(7,'zhongguozhexueshi.jpg','中国哲学史',45.00,'冯友兰',3,100),(8,'huranqiri.jpg','忽然七日',19.00,'劳伦',50,200),(9,'sudongpozhuan.jpg','苏东坡传',20.00,'林语堂',50,300),(10,'fusang.jpg','扶桑',20.00,'严歌岑',10,89),(11,'geihaizideshi.jpg','给孩子的诗',23.00,'北岛',5,99);
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(20) NOT NULL,
`pwd` varchar(32) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`role` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uname` (`uname`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
/*Data for the table `t_user` */
insert into `t_user`(`id`,`uname`,`pwd`,`email`,`role`) values (1,'lina','ok','lina@sina.com.cn',0),(2,'kate','ok','hello_kate@126.com',1),(3,'鸠摩智','ok','jiujiu@126.com',0),(4,'宝2021','ok','bao2021@sohu.com.cn',0),(5,'宝2022','123','bao2022@sohu.com.cn',0);
/*Table structure for table `t_cart_item` */
CREATE TABLE `t_cart_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book` int(11) DEFAULT NULL,
`buyCount` int(11) DEFAULT NULL,
`userBean` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_cart_book` (`book`),
KEY `FK_cart_user` (`userBean`),
CONSTRAINT `FK_cart_book` FOREIGN KEY (`book`) REFERENCES `t_book` (`id`),
CONSTRAINT `FK_cart_user` FOREIGN KEY (`userBean`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
/*Data for the table `t_cart_item` */
insert into `t_cart_item`(`id`,`book`,`buyCount`,`userBean`) values (9,1,1,2),(10,5,1,1),(11,1,2,1),(12,2,13,1),(13,3,2,1),(14,4,1,1),(15,6,1,1),(16,7,1,1),(17,8,1,1),(18,9,1,1),(19,10,1,1),(20,11,4,1);
/*Table structure for table `t_order` */
CREATE TABLE `t_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orderNo` varchar(128) NOT NULL,
`orderDate` datetime DEFAULT NULL,
`orderUser` int(11) DEFAULT NULL,
`orderMoney` double(10,2) DEFAULT NULL,
`orderStatus` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `orderNo` (`orderNo`),
KEY `FK_order_user` (`orderUser`),
CONSTRAINT `FK_order_user` FOREIGN KEY (`orderUser`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
/*Data for the table `t_order` */
insert into `t_order`(`id`,`orderNo`,`orderDate`,`orderUser`,`orderMoney`,`orderStatus`) values (4,'5eaab6146dc54e0482fdb8b6120c229b_20211025112519','2021-10-25 11:25:20',1,506.90,0),(5,'f5a22aac925d42eabc6b49c45a3eb74f_20211025113004','2021-10-25 11:30:04',1,48.95,0),(6,'8a245df4359e4224b531cf121c4acab3_20211025113019','2021-10-25 11:30:20',1,0.00,0),(7,'b521cd49ab2943f0bbc0630c95978f1c_20211025113039','2021-10-25 11:30:40',1,48.95,0),(8,'d4f366a82cd4491c9899b181753804b4_20211025113151','2021-10-25 11:31:52',1,48.95,0),(9,'8f5869a839f4483e947bd2c3163f3c23_20211025113159','2021-10-25 11:31:59',1,48.95,0),(10,'c5fcd95dbe7f49669f96b4ad6444ae6b_20211025120531','2021-10-25 12:05:32',1,147.95,0),(11,'6240ec3e5ac04e3583e1beb75a9e94ec_20211025120542','2021-10-25 12:05:42',1,147.95,0);
/*Table structure for table `t_order_item` */
CREATE TABLE `t_order_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book` int(11) DEFAULT NULL,
`buyCount` int(11) DEFAULT NULL,
`orderBean` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_detail_book` (`book`),
KEY `FK_detail_order` (`orderBean`),
CONSTRAINT `FK_detail_book` FOREIGN KEY (`book`) REFERENCES `t_book` (`id`),
CONSTRAINT `FK_detail_order` FOREIGN KEY (`orderBean`) REFERENCES `t_order` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
/*Data for the table `t_order_item` */
insert into `t_order_item`(`id`,`book`,`buyCount`,`orderBean`) values (6,1,1,4),(7,2,2,4),(8,10,1,4),(9,3,5,4),(10,4,1,4),(11,2,1,5),(12,2,1,7),(13,2,1,8),(14,2,1,9),(15,1,1,10),(16,2,1,10),(17,1,1,11),(18,2,1,11);
数据库一共五个表,第一个是 t_user(用户表)主键id(多次作为别的表的外键)
第二个是 t_book(图书表)
这里老师说最好加个状态的列
第三个是 t_cart_item(购物车项表)t_user的主键 id 为它 userBean 的外键, book的主键 id 为它 book 的外键
第四个是 t_oreder(订单表)t_user的主键 id 为它 orderUser 的外键
第五个是 t_oreder_item(订单项表)(一个订单包括多个订单项,类似一个购物车包含多个购物车项)t_user的主键 id 为它 orderBean的外键,t_book的主键id为它book的外键
然后开始写pojo类,同时记得把druid数据库连接池的配置文件和applicationcontext.xml书写Bean的配置文件复制到src下。这里page还是需要保留的,方便我们能保证一些访问不绕开Thymeleaf或者说Servlet
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE beans [
<!ELEMENT beans (bean*)>
<!ELEMENT bean (property*)>
<!ELEMENT property (#PCDATA)>
<!ATTLIST bean id ID #REQUIRED>
<!ATTLIST bean class CDATA #IMPLIED>
<!ATTLIST property name CDATA #IMPLIED>
<!ATTLIST property ref IDREF #IMPLIED>
]>
<beans>
<bean id="page" class="com.fanxy.myssm.myspringmvc.PageController"/>
</beans>
这里就省略构造函数和get set方法,实际是需要写的,还把一些业务上的1对多,多对一写了,并且参照我们上个项目,有对应关系的写对方类的类型属性,同时都写上带id的构造函数,以备我们改造的新的BaseDAO能直接通过反射生成对方带id的成员变量。也别忘了写空参构造函数(JavaBean基本结构,方便调用反射生成实例)
public class User {
private Integer id;
private String uname;
private String pwd;
private String email;
private Integer role;
}
//我们应该给购物车项写一个Cart购物车类,存放一个人的购物车的购物车项的集合
public class CartItem {
private Integer id;
private Book book;
private Integer buyCount;
private User userBean;
}
public class Book {
private Integer id;
private String bookImg;
private String bookName;
private Double price;
private String author;
private Integer saleCount;
private Integer bookCount;
private Integer bookStatus = 0;
}
public class OrderItem {
private Integer id;
private Book book; // M : 1
private Integer Count;
private OrderBean orderBean; // M : 1
}
public class OrderBean {
private Integer id;
private String orderNo;
private LocalDateTime orderDate;
private User orderUser;
private Double orderMoney;
private Integer orderStatus;
private List<OrderItem> orderItemList; // 1 : M
}
也别忘了把Bean的配置文件参数和Thymeleaf的上下文参数配置复制到web.xml文件,这次我们把前端页面都放在了WEB-INF下,我们干脆把index.html也放进去,然后Thymeleaf配置的前缀我们就改成现在的目录前缀,不再是以前的一个 /
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 在上下文参数中配置视图前缀和视图后缀 -->
<context-param>
<param-name>view-prefix</param-name>
<param-value>/WEB-INF/pages/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>applicationContext.xml</param-value>
</context-param>
</web-app>
根据我们现在的登录页面的位置,我们的tomcat根据PageController的启动和渲染,我们是要经过Thymeleaf,故前缀的一部分其实Thymeleaf的配置帮我们写了,我们直接写user/login即可
接着我们还是延续我们之前系统的思路,先去写登录页面的前端,引入Thymeleaf格式,把src能改的先改了,然后表单的action我们应该从静态页面改成/user.do,将来写UserController,其次我们表单的method写post,当然老规矩,既然是表单我们的到时候写发送逻辑的时候要遵守我们的DispatcherServlet,需要写一个隐藏域的input,name="operate",value="login",意味着将来要写用户的login方法。同时表单的登录部分的账号和密码部分的name要写的和数据库对应(uname,pwd)
很明显,下一步登录需要UserController,写它之前先写DAO层和Service层相应的结构,让我们优先完成登录模块,记得把Bean的配置写到xml里面。
<beans>
<bean id="page" class="com.fanxy.myssm.myspringmvc.PageController"/>
<!-- DAO -->
<bean id="userDAO" class="com.fanxy.dao.impl.UserDAOImpl"/>
<!-- Service -->
<bean id="userService" class="com.fanxy.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
<!-- Controller -->
<bean id="user" class="com.fanxy.controller.UserController">
<property name="userService" ref="userService"/>
</bean>
</beans>
这里先让Controller输出一下查到的用户,看看是否这部分有bug。
public interface UserDAO {
public User getUser(String uname, String pwd);
}
public class UserDAOImpl extends BaseDao implements UserDAO {
@Override
public User getUser(String uname, String pwd) {
String sql = "SELECT * FROM t_user WHERE uname = ? AND pwd = ?;";
try {
List<User> users = executeQuery(User.class, sql, uname, pwd);
if (users.size() > 0) {
return users.get(0);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("UserDAO.getUser出错了");
}
return null;
}
}
public interface UserService {
public User login(String uname, String pwd);
}
public class UserServiceImpl implements UserService {
private UserDAO userDAO = null;
@Override
public User login(String uname, String pwd) {
return userDAO.getUser(uname, pwd);
}
}
public class UserController {
private UserService userService = null;
public String login(String uname, String pwd, HttpSession session){
User user = userService.login(uname, pwd);
System.out.println(user);
return "index";
}
}
经过调试发现前面无bug,下面我们要思考我们的index页面,需要显示图书列表,这些图书的信息来自数据库。所以显然我们需要写BookService层和DAO层,让我们的登录方法返回的页面是具有图书信息的,放入session作用域。
这里我们按苹果系统我们是关键字查询,还带分页,逻辑在页面处判断,需要加入参数,通过Limit分页,查询靠LIKE关键字, 这里如果我们想按价格最大值最小值是可以通过输入这两个参数,然后通过BETEEN AND这种方法查询,然后分页逻辑也一样,这里就先不做了,直接全部查询了。当然别忘了注册Bean。
public interface BookDAO {
public List<Book> getBookList();
}
public class BookDAOImpl extends BaseDao implements BookDAO {
@Override
public List<Book> getBookList() {
String sql = "SELECT * FROM t_book;";
try {
return executeQuery(Book.class, sql);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("BookDAOImpl.getBookList出错了");
}
}
}
public interface BookService {
public List<Book> getBookList();
}
public class BookServiceImpl implements BookService {
private BookDAO bookDAO = null;
@Override
public List<Book> getBookList() {
return bookDAO.getBookList();
}
}
这里我们不想让登录方法还同时把图书列表的功能给聚合,我们后台还有管理员,还有图书的管理操作,显然根据高内聚低耦合的思路,我们应该把图书管理的部分专门写Controller去负责。这里我们的redirect没有写operate=index是因为我们之前写这个模块的时候,operate为空默认赋值index了。
public class UserController {
private UserService userService = null;
public String login(String uname, String pwd, HttpSession session){
User user = userService.login(uname, pwd);
if(user != null){
session.setAttribute("currUser", user);
return "redirect:book.do";
}
return "user/login";
}
}