SSH实战 · 唯唯乐购项目(上)

时间:2023-03-08 22:02:17
前台需求分析
一:用户模块
  1. 注册
  • 前台JS校验
  • 使用AJAX完成对用户名(邮箱)的异步校验
  • 后台Struts2校验
  • 验证码
  • 发送激活邮件
  • 将用户信息存入到数据库
  • 激活
    • 点击激活邮件中的链接完成激活
      • 根据激活码,查询数据库中是否有该用户;
      • 如果有则激活,否则不激活;
  • 登录
    • 输入用户名、密码、验证码(前台,后台数据校验)
    • 用户名、密码都正确同时用户状态必须是激活状态
  • 退出
    • 销毁session。
    二:一级分类模块
    1. 查询一级分类
    • 将一级分类存入session中(每个页面都一样的数据)
  • 查询某个一级分类
    • 查询所有一级分类,同时查询到该一级分类下的所有二级分类
    • 查询该分类下所有的商品,带分页显示
    三:商品模块
    1. 查询热门商品
    • 查询热门商品:限制查10个
  • 查询最新商品
    • 查询最新商品:限制查10个
  • 查询某个分类商品
    • 根据分类的ID进行查询商品
  • 查询某个二级分类商品
    • 根据二级分类的ID进行查询商品
  • 查询某个商品信息
    • 根据商品ID进行查询商品
    四:购物模块
    1. 添加到购物车
    • 将商品添加到购物车
  • 从购物车中移除商品
    • 将商品从购物车中移除
  • 清空购物车
    • 将所有的商品信息从购物车中移除
    五:订单模块
    1. 生成订单
    • 将购物车中的信息存入到数据库(生成订单)
      • 清空购物车
  • 为订单付款
    • 在线支付功能
    • 修改订单状态
    • 修改订单信息(收货地址,联系方式,收货人等)
  • 查询我的订单
    • 根据用户ID查询订单
  • 查询某个订单详情
    • 根据订单ID查询订单
    后台需求分析
    一:用户模块
    1. 添加用户     ·   后台只添加管理员用户
    2. 删除用户
    3. 查询用户
    4. 修改用户
    二:一级分类
    1. 添加一级分类
    2. 删除一级分类
    • 级联删除一级分类下的所有二级分类
  • 修改一级分类
    • 级联修改一级分类下的所有二级分类
  • 查询一级分类
    • 分页查询
    三:二级分类
    1. 添加二级分类
    • 选择所属的一级分类进行添加
  • 删除二级分类
    • 删除二级分类下的所有商品
  • 修改二级分类
  • 查询二级分类
    • 分页查询
    五:商品模块
    1. 添加商品
    • 选择商品所属二级分类进行添加
    • 上传商品图片
  • 修改商品
    • 修改商品二级分类
    • 修改商品图片
  • 删除商品
  • 查询商品
    • 商品查询(带分页)
    六:订单模块
    1. 查询订单
    • 查询所有订单(带分页)
      • 异步加载所有订单
    页面设计
    完成前台静态页面的设计。
    数据库设计
    原则:至少一个模块一张表。
    用户表:
      • 用户ID
      • 用户名
      • 密码
      • 真实姓名
      • 邮箱
      • 细致
      • 电话
      • 用户状态:0--激活;1--未激活
      • 激活码
      sql语句:
      CREATE TABLE `user` (
        `uid` int(11) NOT NULL AUTO_INCREMENT,
        `username` varchar(255) DEFAULT NULL,
        `password` varchar(255) DEFAULT NULL,
        `name` varchar(255) DEFAULT NULL,
        `email` varchar(255) DEFAULT NULL,
        `phone` varchar(255) DEFAULT NULL,
        `addrress` varchar(255) DEFAULT NULL,
        `state` int(11) DEFAULT NULL,
        `code` varchar(64) DEFAULT NULL,
        PRIMARY KEY (`uid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
       一级分类表:
        • 一级分类ID
        • 一级分类名称
      CREATE TABLE `category` (
        `cid` int(11) NOT NULL AUTO_INCREMENT,
        `cname` varchar(255) DEFAULT NULL,
        PRIMARY KEY (`cid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
      二级分类表:
        • 二级分类ID
        • 二级分类名称
        • 一级分类ID(外键指向一级分类主键ID)
      CREATE TABLE `categorysecond` (
        `csid` int(11) NOT NULL AUTO_INCREMENT,
        `csname` varchar(255) DEFAULT NULL,
        `cid` int(11) DEFAULT NULL,
        PRIMARY KEY (`csid`),
        KEY `FK936FCAF21DB1FD15` (`cid`),
        CONSTRAINT `FK936FCAF21DB1FD15` FOREIGN KEY (`cid`) REFERENCES `category` (`cid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8;
      商品表:
        • 商品ID
        • 商品名称
        • 商品商城价格
        • 商品描述
        • 商品市场价格
        • 商品描述
        • 商品图片(路径)
        • 二级分类ID(外键指向二级分类主键ID )
      CREATE TABLE `product` (
        `pid` int(11) NOT NULL AUTO_INCREMENT,
        `pname` varchar(255) DEFAULT NULL,
        `market_price` double DEFAULT NULL,
        `shop_price` double DEFAULT NULL,
        `image` varchar(255) DEFAULT NULL,
        `pdesc` varchar(255) DEFAULT NULL,
        `is_hot` int(11) DEFAULT NULL,
        `pdate` datetime DEFAULT NULL,
        `csid` int(11) DEFAULT NULL,
        PRIMARY KEY (`pid`),
        KEY `FKED8DCCEFB9B74E02` (`csid`),
        CONSTRAINT `FKED8DCCEFB9B74E02` FOREIGN KEY (`csid`) REFERENCES `categorysecond` (`csid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=86 DEFAULT CHARSET=utf8;
      订单表:
        • 订单ID
        • 订单时间
        • 订单金额
        • 订单状态
        • 订单地址
        • 订单电话
        • 订单收货人
        • 用户ID(外键指向用户表的主键ID)
      CREATE TABLE `orders` (
        `oid` int(11) NOT NULL AUTO_INCREMENT,
        `total` double DEFAULT NULL,
        `ordertime` datetime DEFAULT NULL,
        `state` int(11) DEFAULT NULL,
        `name` varchar(20) DEFAULT NULL,
        `phone` varchar(20) DEFAULT NULL,
        `addr` varchar(50) DEFAULT NULL,
        `uid` int(11) DEFAULT NULL,
        PRIMARY KEY (`oid`),
        KEY `FKC3DF62E5AA3D9C7` (`uid`),
        CONSTRAINT `FKC3DF62E5AA3D9C7` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=9004 DEFAULT CHARSET=utf8;
      订单项表:(需要参与业务逻辑中)
        • 主键ID
        • 商品ID(指向)
        • 订单ID()
        • 数量
        • 小计
      CREATE TABLE `orderitem` (
        `itemid` int(11) NOT NULL AUTO_INCREMENT,
        `count` int(11) DEFAULT NULL,
        `subtotal` double DEFAULT NULL,
        `pid` int(11) DEFAULT NULL,
        `oid` int(11) DEFAULT NULL,
        PRIMARY KEY (`itemid`),
        KEY `FKE8B2AB6166C01961` (`oid`),
        KEY `FKE8B2AB6171DB7AE4` (`pid`),
        KEY `FKE8B2AB6140ACF87A` (`oid`),
        CONSTRAINT `FKE8B2AB6140ACF87A` FOREIGN KEY (`oid`) REFERENCES `orders` (`oid`),
        CONSTRAINT `FKE8B2AB6171DB7AE4` FOREIGN KEY (`pid`) REFERENCES `product` (`pid`)
      ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
      后台用户表:
        • 用户名
        • 密码
      表关系分析图
      其中 : 订单项表是商品表和订单表之间多对多关系产生的中间表。
      SSH实战  ·  唯唯乐购项目(上)
       编码实现
      一:SSH整合
      1. 参考之前得SSH项目实战  ·  项目环境搭建——http://www.cnblogs.com/panweiwei/p/6212609.html。

        2. 引入前端页面 ---- 页面都放到WebRoot/WEB-INF下。

        • 引入静态页面
          • 将HTML静态页面都复制到WebRoot/WEB-INF/jsp目录下.
          • 将JS、CSS文件分别复制到WebRoot/js、WebRoot/css目录下.

        3. 访问首页

        • 创建包的格式:
        * cn.itcast.shop.index
        * action
        * cn.itcast.shop.user
        * action
        * service
        * dao
        * vo
          • 编写Action
            • IndexAction
          • 改造jsp和文件路径
            • 将html静态页面改为jsp页面文件
            • 将jsp中的css、js、图片路径改为绝对路径(${pageContext.request.contextPath} )
          • 配置Action
            • 配置applicationContext.xml
         <!-- 首页访问的Action 注意:千万不要忘记scope-->
         <bean id="indexAction" class="cn.itcast.shop.index.action.IndexAction" scope="prototype"></bean>
            • 配置struts.xml
         <!-- 配置首页访问的Action -->
         <action name="index" class="indexAction">
             <result name="index">/WEB-INF/jsp/index.jsp</result>
         </action>
        用户模块:注册
        一:改装页面 
        1. 将页面中能共用的菜单、头部区域提出来(新建一个head.jsp)
        2. 在原来网页的头部处将head.jsp包入就好:
                  <@% include file="head.jsp" %>
        二:跳转到注册界面
        1. 点击注册链接进行跳转(添加到一个Action中,从Action中完成页面转向)
        • 修改注册的访问路径
                                 ${pageContext.request.contextPath}/user_registePage.action
          • 编写Action
          • 配置applicationContext.xml
        <!-- 用户模块的Action -->
        <bean id="userAction" class="cn.itcast.shop.user.action.UserAction" scope="prototype"></bean>
          • 配置struts.xml
             <!-- 配置用户模块的Action -->
             <action name="user_*" class="userAction" method="{1}">
                 <result name="registPage">/WEB-INF/jsp/regist.jsp</result>
             </action>
          • 修改register.jsp页面:
            • 替换css、图片的路径
                             ./css 替换成 ${pageContext.request.contextPath}/css
                            ./images 替换成 ${pageContext.request.contextPath}/images
            • 包含head.jsp。当然了,原页面中相应的内容删掉
        <@% include file="head.jsp" %>
        1. 用户注册校验
               2.1 前台校验:页面中凡是涉及到提交表单的都要进行验证。
          • 统一字段名的name、id(与数据库表中字段、实体类中的字段对应);
          • 加 JS。
          • AJAX异步校验:验证数据库中是否已存在输入的用户名
            • 事件触发:onblur
            • 编写AJAX代码:向action中提交:传递username参数
            • 编写antion:

        *  接收username:模型驱动接收

        *  编写实体类:User;

        *  映射文件:User.hbm.xml;

        *  将实体类与映射文件配置到spring中。

            • 编写DAO

        *  继承HibernateDaoSupport;

                  • 在配置中注入sessionFactory
            • 编写Service

        *  注入UserDao;

                  *  配置事务管理;

               2.2 后台数据校验
          • 在Action所在包下创建一个校验的xml
            • 创建一个与Action类名-validation.xml(只针对register方法进行校验)
            • UserAction-user_regist-validation.xml
          <!DOCTYPE validators PUBLIC
                  "-//Apache Struts//XWork Validator 1.0.3//EN"
                  "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> 
          <validators>
         <!-- 校验用户名 -->
         <field name="username">
             <field-validator type="requiredstring">
                 <message>用户名不能为空!</message>
             </field-validator>
         </field>
         <!-- 校验用户名 -->
         <field name="password">
             <field-validator type="requiredstring">
                 <message>密码不能为空!</message>
             </field-validator>
         </field>
         <!-- 校验邮箱 -->
         <field name="email">
             <field-validator type="email">
                 <message>邮箱格式不正确!</message>
             </field-validator>
         </field>
           </validators>
          • 在struts.xml中配置INPUT逻辑视图
                 <!-- 配置用户模块的Action -->
                  <action name="user_*" class="userAction" method="{1}">
                      <result name="registPage">/WEB-INF/jsp/register.jsp</result>
                      <result name="input">/WEB-INF/jsp/register.jsp</result>
                  </action>
          • 在register.jsp页面先引入struts标签
                       <%@ taglib uri="/struts-tags" prefix="s"%>
          • 在相应的位置回显错误提示信息。如密码验证提示如下:
          <span><s:fielderror fieldName="password"/></span>
        1. 用户注册
          • 将数据保存到数据库
            • 完善user对象
                             *  用户状态默认为0(未激活状态);
                             *  激活码采用工具类(UUID)生成(32位激活码);
          • 发送激活邮件
            • 电子邮箱:邮件服务器上的一块空间;
            • SSH实战  ·  唯唯乐购项目(上)

              邮件服务器:类比于web服务器(tomcat),有相应的服务器软件;

            • 邮件协议:大公司发送和接收服务器分开,也可以都用一个服务器。
                                   SMTP:简单的邮件发送协议;
                                   POP3:接收邮件的一个协议;
            • 邮件发送的全过程:理论上需要联网,但是通过搭建在本地的服务器,可以在本地进行邮件的发送。
            • 搭建邮箱服务器:
              • 安装邮箱服务器(易邮邮箱服务器,就按默认的安装在C盘)
              • 修改域名:工具-->服务器设置-->单域名改为:shop.com
              • 注册几个内部账号:账号-->新建账号。密码设为55555
              • 注册一个商城官方账号:service    密码:55555
            • 安装邮件客户端软件(可以接发邮件):避免了网页版session的过期离线问题。
              • 流行的有软件有:outlook(微软收费)、foxmail(免费,选用foxmail)
              • 配置
                                      * 配置发送邮件服务器:localhost
                                      * 配置接收邮件服务器:localhost
            • 编码实现邮件发送
        1. 用户激活
        • 在邮箱客户端中点击激活链接:
          • 根据链接中传递的激活码进行查询
                                 * 如果用户不为空:修改用户状态:0  -->  1,向前台传递激活成功消息。
                                 * 如果用户为空:激活码失效或被篡改,向前台传递激活失败消息。
        1. 用户登录
        • 登录页面跳转链接
          • 将html编写为login.jsp,并更换引用路径以及菜单头文件
          • 修改页面上的登录链接为${pageContext.request.contextPath}/user_loginPage.action
          • 编写Action中的方法
          • struts.xml中配置页面转向
        • 登录功能实现
          • 添加login.jsp中的表单action
          • 接收用户输入的用户名、密码——模型驱动会自动接收;
          • 调用userService,进行查询——参数:用户名、密码、用户状态。
          • 登录成功:跳转到首页,并将用户信息显示在首页。
          • 登录失败:跳转回登录页面,并将错误信息显示在登录页面。
      1. 用户退出
        • 给链接加action的路径,点击退出链接
          • 销毁session
        //销毁session
        ServletActionContext.getRequest().getSession().invalidate();
            • 页面跳转
        1. 验证码
          • 在com.weiwei.shopping.user下编写单独的验证码Action类;
          • 在spring、struts配置文件中完成配置;
                       applicationContext.xml 中:
                <!-- 配置验证码Action -->
                <bean id="checkImgAction" class="com.weiwei.shopping.user.action.CheckImgAction" scope="prototype"></bean>
                       struts.xml 中:
                    <!-- 验证码Action -->
                    <action name="checkImg" class="checkImgAction"></action>
            • 页面中需要的位置显示验证码
                    <img id="rightcode" class="captchaImage" src="${pageContext.request.contextPath}/checkImg.action" title="点击更换验证码" onclick="ChangeCodeImg()" />
            • 编写JS,点击刷新验证码
          /*点击更换验证码图片*/
          function ChangeCodeImg(){
               /*取到验证码图片*/
               var codeImg = document.getElementById("rightcode");
               /*由于浏览器的缓存,所以需要加上时间戳*/
               codeImg.src = "${pageContext.request.contextPath}/checkImg.action?" + new Date().getTime();
          }
            • 提交到action,在action中进行比较,表单输入的与session中的验证码不相等则相应请求不提交。
          /*判断验证码,验证码正确则提交,否则不提交*/
          //从session中获取正确的验证码
          String rightcode = (String) ServletActionContext.getRequest().getSession().getAttribute("checkcode");
          //与表单提交的验证码比较
          if(!formcode.equalsIgnoreCase(rightcode)){
                //不相等
                this.addActionError("验证码输入错误!");
                return "loginPage";
          }
          User existUser = userService.checkLogin(user);
          if(existUser == null){
                //登录失败
                this.addActionError("查无此人,登录失败!");
                return "login";
          else{
                //登录成功
                //将用户的信息存到session中,在进行页面的跳转
                ServletActionContext.getRequest().getSession().setAttribute("existUser", existUser);
                this.addActionMessage("登录成功!");
                return "loginPage";
          }