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的外键
第五个是 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";
    }
}



















