5_项目实战MyShop
阅读原文时间:2023年07月09日阅读:3

一. 网上商城

1.1 商城类别

  • B2B

    • 商家对商家
  • B2C

    • 商家对客户
  • C2C

    • 客户对客户
  • O2O

    • 线上线下相结合

1.2 商城常见模块

  • 后台常见功能模块

    • 商品管理

      • 包括后台商品库存管理, 上货, 出货, 编辑管理和商品分类管理, 商品品牌管理等
    • 订单管理

      • 在线订单程序, 使消费者能够顺利的通过WEB在线的方式, 直接生成购买订单
    • 商品促销

      • 一般的购物系统多有商品促销功能, 通过商品促销功能, 能够迅速的促进商城的消费积极性
    • 支付方式

      • 即通过网上钱包, 电子支付卡, 进行网上资金流转换的业务流程, 国内主流支付方式包括: 微信, 支付宝, 网银等, 还有部分网上商城支持货到付款
    • 配送方式

      • 购物系统集成的物流配送方式, 从而方便消费者对物流方式进行在线选择, 如顺丰, EMS, 中通, 圆通, 韵达等
    • 会员模块

      • 在购物系统中, 集成会员注册是吸引会员进行二次购买和提升转换率的方式
  • 前端界面功能模块

    • 模板风格自定义

      • 即通过系统内置的模板引擎, 可以方便的通过后台可视化编辑, 设计出符合自身需求的风格界面
    • 商品多图显示

      • 随着电子商务的发展, 商品图片成为吸引消费者的第一要素, 多图展示即提供前台多张图片的展示, 从而提升消费者的购物欲望
    • 自定义广告模块

      • 内置在系统中的广告模块, 网站管理员能够顺利的通过操作就可以在前端页面中添加各种广告图片
    • 购物车

      • 用户可以把想要购买的商品添加进购物车, 随时增删商品

二. 软件开发流程[重点]

  • 软件开发流程即软件设计思路和方法的一般过程, 包括对软件先进行需求分析, 设计软件的功能和实现的算法和方法, 软件的总体结构设计和模块设计, 编码和调试, 程序联调和测试以及编写, 提交程序等一系列操作以满足客户的需求并且解决客户的问题, 如果有更高需求, 还需要对软件进行维护, 升级处理, 报废处理.

2.1 周期和阶段

从管理的角度, 即从业务和经济的角度来看, 软件的生命周期包括四个主要阶段

  • 起始阶段
  • 细化阶段
  • 构建阶段
  • 移交阶段

2.2 开发流程

  • 需求分析
  • 概要设计
  • 详细设计
  • 编码
  • 测试
  • 软件交付
  • 验收
  • 维护

三. MyShop项目介绍

3.1 开发环境

  • 操作系统

    • Window8.1
  • 数据库平台

    • MySQL5.7
  • 应用服务器

    • tomcat 8.5.54
  • Java开发工具

    • IDEA
  • 框架

  • 项目名称

    • MyShop

3.2 主要功能

  1. 用户模块

    • 用户注册, 登录, 注销
  2. 商品显示模块

    • 分页显示所有商品, 查看单个商品详细信息, 搜索商品
  3. 购物车模块

    • 加入商品到购物车, 修改购物车内商品数据
  4. 地址模块

    • 管理用户收货地址
  5. 订单模块

    • 提交订单前先预览订单, 用户确认后生成正式订单, 用户查看历史订单
  6. 支付模块

    • 完成在线支付功能
  7. 后台模块

四. 数据库设计[重点]

  • 数据库设计是指根据用户的需求, 在某一具体的数据库管理系统上, 设计数据库的结构和建立数据库的过程

4.1 PowerDesigner

  • PowerDesigner是能进行数据库设计的强大的软件, 是一款开发人员常用的数据库建模工具, 使用它可以分别从概念数据模型(Conceptual Data Model)和物理数据模型(Physical Data Model)两个层次对数据库进行设计
4.1.1 概念数据模型CDM
  • 概念数据模型描述的是独立于数据库管理系统(DBMS)的实体定义和实体关系定义
  • 在CDM中用来标识实体的是属性(Attribute)
4.1.2 物理数据模型PDM
  • 物理数据模型是在概念数据模型的基础山针对目标数据库管理系统的具体化
  • PDM的对象: 表(Table) 表中的列(Table Column), 主外键(Primary, Foreign Key), 参照(Reference), 索引(Index), 视图(View)等
  • 在PDM中用来表示实体属性的是列(Column)
4.1.3 CDM和PDM对比
  • CDM概念数据模型: 描述要存储的实体, 属性, 实体关系
  • PDM物理数据模型: 对概念数据库模型进行升级, 将实体转化为具有数据库特性的模型
    • 实体-->表
    • 属性-->列
  • 总结: 类似抽象类和实现的关系
4.1.4 数据库设计步骤
  • 设计CDM模型
  • 生成PDM模型
  • 生成DBMS脚本

4.2 用户模块涉及表

4.2.1 用户表
create table user
(
   u_id                 int not null auto_increment comment '用户实体的主键属性',
   u_name               varchar(20) not null comment '用户账号',
   u_password           varchar(64) not null comment '用户密码',
   u_email              varchar(50) not null comment '用户邮箱',
   u_sex                varchar(4) comment '用户性别',
   u_status             int comment '用户的激活状态0未激活1激活',
   u_code               varchar(64) comment '邮件激活码',
   u_role               int comment '用户0管理员1',
   primary key (u_id)
)
charset = UTF8;
4.2.2 地址表
create table address
(
   a_id                 int not null auto_increment comment '地址实体',
   u_id                 int comment '用户实体的主键属性',
   a_name               varchar(30) comment '地址的收件人',
   a_phone              varchar(14) comment '收件人电话',
   a_detail             varchar(200) comment '收货人详细地址',
   a_state              int comment '0不是默认地址,1是默认地址',
   primary key (a_id)
)
charset = UTF8;

4.3 商品模块涉及表

4.3.1 商品类别表
create table type
(
   t_id                 int not null auto_increment comment '类别的主键id',
   t_name               varchar(20) comment '类别的名称',
   t_info               varchar(200) comment '类别的描述',
   primary key (t_id)
)
charset = UTF8;
4.3.2 商品表
create table product
(
   p_id                 int not null auto_increment comment '商品的唯一主键',
   t_id                 int comment '类别的主键id',
   p_name               varchar(50) comment '商品名称',
   p_time               date comment '商品上市时间',
   p_image              varchar(100) comment '商品图片路径',
   p_price              decimal(12) comment '商品价格',
   p_state              int comment '商品热门指数',
   p_info               varchar(200) comment '商品描述',
   primary key (p_id)
)
charset = UTF8;

4.4 购物车模块涉及表

4.4.1 购物车表
create table cart
(
   c_id                 int not null auto_increment comment '购物车的唯一标识',
   p_id                 int comment '商品的唯一主键',
   u_id                 int comment '用户实体的主键属性',
   c_count              decimal(12) comment '购物车小计',
   c_num                int comment '购物车商品数量',
   primary key (c_id)
)
charset = UTF8;

4.5 订单模块涉及表

4.5.1 订单表
create table orders
(
   o_id                 varchar(64) not null comment '订单编号是字符串类型,但也是唯一标识',
   a_id                 int comment '地址实体',
   u_id                 int comment '用户实体的主键属性',
   o_count              decimal(12) comment '订单总金额',
   o_time               datetime comment '订单的详细时间',
   o_state              int comment '订单状态 0未付款,1付款未发货,,2发货未收货,,3收货待评价,4订单完成,5退货状态',
   o_detail             varchar(200) comment '订单收货地址',
   primary key (o_id)
)
charset = UTF8;
4.5.2 订单详情表
create table item
(
   i_id                 int not null auto_increment comment '订单项的唯一标识',
   o_id                 varchar(64) comment '订单编号是字符串类型,但也是唯一标识',
   p_id                 int comment '商品的唯一主键',
   i_num                int comment '订单项数量',
   i_count              decimal(12) comment '订单项小计',
   primary key (i_id)
)
charset = UTF8;

4.6 后台管理模块

  • 没有新表

4.7 约束

alter table address add constraint FK_u_a_fk foreign key (u_id)
      references user (u_id) on delete restrict on update restrict;

alter table cart add constraint FK_p_c_fk foreign key (p_id)
      references product (p_id) on delete restrict on update restrict;

alter table cart add constraint FK_u_c_fk foreign key (u_id)
      references user (u_id) on delete restrict on update restrict;

alter table item add constraint FK_o_i_fk foreign key (o_id)
      references orders (o_id) on delete restrict on update restrict;

alter table item add constraint FK_p_i_fk foreign key (p_id)
      references product (p_id) on delete restrict on update restrict;

alter table orders add constraint FK_a_o_fk foreign key (a_id)
      references address (a_id) on delete restrict on update restrict;

alter table orders add constraint FK_u_o_fk foreign key (u_id)
      references user (u_id) on delete restrict on update restrict;

alter table product add constraint FK_t_p_fk foreign key (t_id)
      references type (t_id) on delete restrict on update restrict;

4.8 导入.sql文件

导入外部sql文件到mysql数据库中的某张表中

  • 方法一:

    • Windows+R打开控制台输入: mysql -uroot -p 数据库名 < .sql文件路径,Enter后输入密码等待一会儿即可
  • 方法二:

    • Windows+R打开控制台输入: mysql -uroot -p, Enter后输入密码进入数据库
    • use 数据库名;
    • source后面输入外部sql文件路径,Enter

五. 项目搭建和准备工作

  • 创建项目
  • 导入工具类
  • 导入jar包
  • 导入配置文件
  • 导入页面

5.1 创建BaseServlet[重点]

  • 作用: 简化和优化Servlet的创建和数量

  • 实现思路: 使一个Servlet对应多个方法! 每个方法都实现一个业务逻辑!

  • BaseServlet的实现

5.1.1 BaseServlet
package com.dz.controller;

import com.dz.utils.Constants;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * description: BaseServlet用于集中处理方法的调用!
 *              返回值的处理!
 *              以及默认页对应方法!
 */

@WebServlet(name = "BaseServlet")
public class BaseServlet extends HttpServlet {
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取请求参数(标识符)
        String methodStr = req.getParameter(Constants.TAG);

        //2. 如果method没有获取到值,就跳转到首页(标识符异常处理)
        if (methodStr == null || methodStr.equals("")) {
            methodStr = Constants.INDEX;
        }

        //3. 反射调用对应的业务逻辑方法
        //3.1 获取类的class对象,
        Class<? extends BaseServlet> aClass = this.getClass();
        try {
            //3.2 获取方法
            /*
            参数1: 方法名
            参数2...: 方法参数的类型
             */
            Method method = aClass.getMethod(methodStr, HttpServletRequest.class, HttpServletResponse.class);
            //3.3 执行方法
            /*
            参数1: 要执行方法的对象
            参数2...:执行方法传入具体的参数
            返回值: 执行方法的返回值!如果方法为void,返回值为null
             */
            Object result = method.invoke(this, req, resp);
            //4. 集中处理返回值响应(根据返回值约定的表示符判断)
            if (result != null) {
                //转发 重定向 返回字符串
                String str = (String) result;
                String path = str.substring(str.indexOf(Constants.FLAG) + 1);
                if (str.startsWith(Constants.FORWARD)) {
                    //转发
                    req.getRequestDispatcher(path).forward(req,resp);
                }else if (str.startsWith(Constants.REDIRECT)) {
                    //重定向
                    //重写url防止用户禁用cookie
                    String newPath = resp.encodeRedirectURL(path);
                    resp.sendRedirect(newPath);
                }else {
                    //输出字符串
                    resp.getWriter().println(str);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            req.getSession().setAttribute("masg","程序异常, 请稍后再试!");
            resp.sendRedirect("/message.jsp");
        }
    }

    /*
    当method中没有值时,为其赋默认值index,我们将index方法提取到BaseServlet中
    没有值就默认跳转index首页
     */
    public String index(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        return Constants.FORWARD + "/index.jsp";
    }

}

六. 项目代码

6.1 Controller

6.1.1 用户模块
package com.dz.controller;

import com.dz.entity.User;
import com.dz.service.UserService;
import com.dz.service.impl.UserServiceImpl;
import com.dz.utils.Base64Utils;
import com.dz.utils.Constants;
import com.dz.utils.MD5Utils;
import com.dz.utils.RandomUtils;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * description: 用户模块的Controller
 */

@WebServlet("/user")
public class UserController extends BaseServlet {

    /**
     * 检测用户名
     */
    public String check(HttpServletRequest request, HttpServletResponse response) {
        String result = Constants.HAS_USER;
        //1. 获取用户名
        String username = request.getParameter("username");

        if (username != null) {
            //2. 调用业务逻辑判断用户名是否存在
            UserServiceImpl userService = new UserServiceImpl();
            boolean b = userService.checkedUser(username);

            //3. 响应字符串 1 存在 0 不存在
            if (b) {
                //用户存在.返回"1",不能注册
                return Constants.HAS_USER;
            }else {
                //不存在,返回0,可以注册
                return Constants.NOT_HAS_USER;
            }
        }
        return result;
    }

    /**
     * 注册
     */
    public String register(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取用户信息
        Map<String,String[]> parameterMap = request.getParameterMap();
        User user = new User();
        try {
            //BeanUtils.populate( Object bean, Map properties )
            //这个方法会遍历map<key, value>中的key,如果bean中有这个属性,就把这个key对应的value值赋给bean的属性
            BeanUtils.populate(user,parameterMap);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //2. 完善用户信息
        //已经赋值的: 用户id(自动生成) 用户名 密码 邮箱 性别
        //没有赋值的: 账号状态 账号类型 激活码
        user.setUstatus(Constants.USER_NOT_ACTIVE);//0 未激活 1 激活
        user.setUrole(Constants.ROLE_CUSTOMER);//0 普通用户 1 管理员
        user.setCode(RandomUtils.createActive());
        //需要处理的属性: 密码 MD5进行加密处理
        user.setUpassword(MD5Utils.md5(user.getUpassword()));

        //3. 调用用户的业务逻辑进行注册
        UserService userService = new UserServiceImpl();
        int row = userService.registerUser(user);
        if (row != 1) {//注册失败
            request.setAttribute("registerMsg","注册失败!");
            return Constants.FORWARD + "/register.jsp";
        }else {
            HttpSession session = request.getSession();
            session.setAttribute("user",user);
            session.setAttribute("registerMsg","您已注册成功,可以登陆啦!");
            return Constants.REDIRECT + "/registerSuccess.jsp";
        }
    }

    /**
     * 激活用户账号
     */
    public String active(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取激活码
        //已经转成base64格式
        String c = request.getParameter("c");
        //base64解码
        String code = Base64Utils.decode(c);
        //2. 调用业务逻辑进行激活
        UserService userService = new UserServiceImpl();
        int row = userService.activeUser(code);

        //3. 响应
        if (row == Constants.ACTIVE_FAIL) {
            request.setAttribute("msg","激活失败!请重新操作!");
        }else if (row == Constants.ACTIVE_SUCCESS) {
            request.setAttribute("msg","恭喜您激活成功!可以登陆啦!");
        }else {
            request.setAttribute("msg","您已经激活过了哦!不用再次激活!");
        }
        return Constants.FORWARD + "/message.jsp";
    }

    /**
     * 登陆
     * 1. 获取前端提交的账号, 密码, 验证码
     * 2. 对比验证码 成功--->对比账号密码
     * 3. 对比账号密码
     *      失败: 回到登陆页面 进行提示
     *      成功: 未激活 登陆界面进行提示
     *            已激活 跳转至程序的首页 将用户放进session共享域
     * 4. 判断是否勾选自动登陆
     *      没有勾选: 清空cookie,返回响应
     *      勾选: 保存cookie, 返回响应
     */
    public String login(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取请求参数(用户名, 密码, 验证码)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String code = request.getParameter("code");//用户输入的验证码
        String auto = request.getParameter("auto");//自动登陆

        //正确的验证码 从Session中提取
        HttpSession session = request.getSession();
        String codes = (String) session.getAttribute("codes");
        //2. 判断验证码是否正确
        if (code == null || !code.equalsIgnoreCase(codes)) {
            request.setAttribute("msg","验证码输入错误!");
            return Constants.FORWARD + "/login.jsp";
        }
        //3. 调用业务逻辑判断账号密码
        UserService userService = new UserServiceImpl();
        User user = userService.login(username, password);

        //4. 响应
        //user 等于null证明账号密码错误,无法登陆
        //user 不为null, 但user的状态是未激活,无法登陆
        if (user == null) {
            request.setAttribute("msg","登陆失败!");
            return Constants.FORWARD + "/login.jsp";
        }
        if (user.getUstatus().equals(Constants.USER_NOT_ACTIVE)) {
            request.setAttribute("msg","账号未激活!!");
            return Constants.FORWARD + "/login.jsp";
        }
        session.setAttribute("loginUser",user);

        //判断是否勾选自动登陆
        if (auto == null) {
            //没有勾选
            //将本地浏览器存储的自动登陆cookie 清空
            Cookie cookie = new Cookie(Constants.AUTO_NAME,"");//清空
            cookie.setPath("/");
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }else {
            //勾选自动登陆,cookie存储在用户本地浏览器两周
            String content = username + Constants.FLAG + password;
            content = Base64Utils.encode(content);
            Cookie cookie = new Cookie(Constants.AUTO_NAME,content);
            cookie.setPath("/");
            cookie.setMaxAge(14*24*60*60);
            response.addCookie(cookie);
        }

        return Constants.REDIRECT + "/index.jsp";

    }

    /**
     * 注销!
     * 1. 清空数据(session和cookie)!
     * 2. 跳转到登陆界面!
     */
    public String logout(HttpServletRequest request, HttpServletResponse response) {

        //1. 清空session中的用户数据
        HttpSession session = request.getSession();
        session.removeAttribute("loginUser");

        //2. 清空和覆盖cookie存储的自动登陆信息
        Cookie cookie = new Cookie(Constants.AUTO_NAME,"");//清空autoUser

        cookie.setPath("/");
        cookie.setMaxAge(0);
        response.addCookie(cookie);

        //3. 转发到登陆界面
        request.setAttribute("msg","注销成功!");

        return Constants.FORWARD + "/login.jsp";
    }
}
6.2.1 地址模块
package com.dz.controller;

import com.dz.entity.Address;
import com.dz.entity.User;
import com.dz.service.AddressService;
import com.dz.service.impl.AddressServiceImpl;
import com.dz.utils.Constants;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

/**
 * description: 地址模块的Controller
 */

@WebServlet("/address")
public class AddressController extends BaseServlet{
    private AddressService addressService = new AddressServiceImpl();

    public String getAddress(HttpServletRequest request, HttpServletResponse response) {
        //1. 判断用户是否登陆
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("loginUser");
        if (user == null) {//如未登录
            session.setAttribute("msg","请先登陆哦!");
            return Constants.REDIRECT + "/login.jsp";
        }
        int uid = user.getUid();
        List<Address> addressList = addressService.findAddressByUid(uid);

        request.setAttribute("addressList",addressList);

        return Constants.FORWARD + "/self_info.jsp";
    }
    public String add(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException {

        //1. 获取请求参数
        Map<String, String[]> map = request.getParameterMap();
        Address address = new Address();
        BeanUtils.populate(address, map);
        //2. 调用业务逻辑添加地址
        int row = addressService.addAddress(address);
        //3. 转发到展示的方法
        if (row != 1) {
            return Constants.FORWARD + "/index.jsp";
        }
        return Constants.FORWARD + "/address?method=getAddress";
    }

    public String delete(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException {

        //1. 获取请求参数
        String aid = request.getParameter("aid");
        //2. 调用业务逻辑添加地址
        int row = addressService.deleteAddress(aid);
        //3. 转发到展示的方法
        if (row != 1) {
            return Constants.FORWARD + "/index.jsp";
        }
        return Constants.FORWARD + "/address?method=getAddress";
    }

    public String setDefault(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException {

        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("loginUser");
        if (user == null) {//如未登录
            session.setAttribute("msg","请先登陆哦!");
            return Constants.REDIRECT + "/login.jsp";
        }
        int uid = user.getUid();
        //1. 获取请求参数
        String aid = request.getParameter("aid");
        //2. 调用业务逻辑添加地址
        int row = addressService.defaultAddr(aid, uid);
        //3. 转发到展示的方法
        if (row != Constants.DEFAULT_ADDRESS) {
            return Constants.FORWARD + "/index.jsp";
        }
        return Constants.FORWARD + "/address?method=getAddress";
    }

    public String update(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException {

        //1. 获取请求参数
        Map<String, String[]> map = request.getParameterMap();
        Address address = new Address();
        BeanUtils.populate(address, map);
        //2. 调用业务逻辑添加地址
        int row = addressService.updateAddress(address);
        //3. 转发到展示的方法
        if (row != 1) {
            return Constants.FORWARD + "/index.jsp";
        }
        return Constants.FORWARD + "/address?method=getAddress";
    }

}
6.3.1 商品类别模块
package com.dz.controller;

import com.dz.entity.Type;
import com.dz.service.TypeService;
import com.dz.service.impl.TypeServiceImpl;
import com.google.gson.Gson;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * description: 商品类别模块的Controller
 */

@WebServlet("/type")
public class TypeController extends BaseServlet{

    public String findAll(HttpServletRequest request, HttpServletResponse response) {

        TypeService typeService = new TypeServiceImpl();
        List<Type> typeList = typeService.findAll();

        Gson gson = new Gson();

        return gson.toJson(typeList);//转为json并返回
    }
}
6.4.1 商品模块
package com.dz.controller;

import com.dz.entity.PageBean;
import com.dz.entity.Product;
import com.dz.service.ProductService;
import com.dz.service.impl.ProductServiceImpl;
import com.dz.utils.Constants;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * description: 商品模块的Controller
 */

@WebServlet("/product")
public class ProductController extends BaseServlet{

    public String show(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取请求参数 tid(类别id)
        String tid = request.getParameter("tid");
        //从前端获取当前页数和页容量
        int pageSize = 8;

        String currentPage = request.getParameter("currentPage");
        int page = 1;
        if (currentPage != null) {
            page = Integer.parseInt(currentPage);
        }

        //2. 调用业务逻辑得到前端需要展示的PageBean
        ProductService productService = new ProductServiceImpl();
        PageBean<Product> pageBean = productService.findPage(tid, page, pageSize);

        //3. 响应即可
        request.setAttribute("pageBean",pageBean);

        return Constants.FORWARD + "/goodsList.jsp";
    }

    public String detail(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取请求参数
        String pid = request.getParameter("pid");

        //2. 调用业务逻辑
        ProductService productService = new ProductServiceImpl();
        Product product = productService.findProductByPid(pid);
        //3. 响应
        request.setAttribute("product",product);

        return Constants.FORWARD + "/goodsDetail.jsp";
    }

}
6.5.1 购物车模块
package com.dz.controller;

import com.dz.entity.Cart;
import com.dz.entity.User;
import com.dz.service.CartService;
import com.dz.service.impl.CartServiceImpl;
import com.dz.utils.Constants;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * description: 购物车模块的Controller
 */

@WebServlet("/cart")
public class CartController extends BaseServlet {
    private CartService cartService = new CartServiceImpl();

    //加入购物车
    public String addCart(HttpServletRequest request, HttpServletResponse response) {
        //1. 判断用户是否登陆
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("loginUser");
        if (user == null) {//如未登录
            session.setAttribute("msg","添加购物车前请先登陆哦!");
            return Constants.REDIRECT + "/login.jsp";
        }
        //不为空,登陆状态
        //2. 获取用户id和商品id
        int uid = user.getUid();
        String pid = request.getParameter("pid");
        int row = cartService.addCart(uid, pid);
        if (row != 1) {
            //2. 结果不为1则添加失败
            return Constants.REDIRECT + "/login.jsp";
        }
        return Constants.FORWARD + "/cartSuccess.jsp";
    }

    //展示购物车
    public String show(HttpServletRequest request, HttpServletResponse response) {
        //1. 判断用户是否登陆
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("loginUser");
        if (user == null) {//如未登录
            session.setAttribute("msg","添加购物车前请先登陆哦!");
            return Constants.REDIRECT + "/login.jsp";
        }
        //2. 获取参数
        int uid = user.getUid();
        //3. 调用业务逻辑
        List<Cart> cartList = cartService.findAll(uid);
        request.setAttribute("cartList",cartList);

        return Constants.FORWARD + "/cart.jsp";
    }

    //购物车内商品删除
    public String delete(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取cid
        String cid = request.getParameter("cid");
        //2. 调用业务逻辑
        int row = cartService.deleteCart(cid);
        if (row != 1) {
            return Constants.FORWARD + "/index.jsp";
        }

        return Constants.FORWARD + "/cart?method=show";
    }

    //购物车商品加减
    public String update(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取cid
        String cid = request.getParameter("cid");
        String cnum = request.getParameter("cnum");
        String pprice = request.getParameter("pprice");
        //2. 调用业务逻辑
        int row = cartService.updateCart(cid, cnum, pprice);
        if (row != 1) {
            return Constants.FORWARD + "/index.jsp";
        }

        return Constants.FORWARD + "/cart?method=show";
    }

    public String clear(HttpServletRequest request, HttpServletResponse response) {
        //1. 获取uid
        String uid = request.getParameter("uid");
        //2. 调用业务逻辑
        int row = cartService.clearCart(uid);

        return Constants.FORWARD + "/cart?method=show";
    }
}
6.6.1 订单模块
package com.dz.controller;

import com.dz.entity.Address;
import com.dz.entity.Cart;
import com.dz.entity.Orders;
import com.dz.entity.User;
import com.dz.service.AddressService;
import com.dz.service.CartService;
import com.dz.service.OrderService;
import com.dz.service.impl.AddressServiceImpl;
import com.dz.service.impl.CartServiceImpl;
import com.dz.service.impl.OrderServiceImpl;
import com.dz.utils.Constants;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * description: 订单模块的Controller
 */

@WebServlet("/order")
public class OrderController extends BaseServlet {
    private OrderService orderService = new OrderServiceImpl();
    private AddressService addressService = new AddressServiceImpl();
    private CartService cartService = new CartServiceImpl();

    //进入订单页面
    public String preview(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取参数
        String uid = request.getParameter("uid");
        //2. 调用业务逻辑
        //获取地址列表
        List<Address> addressList = addressService.findAddressByUid(Integer.parseInt(uid));
        //获取购物车列表
        List<Cart> cartList = cartService.findAll(Integer.parseInt(uid));

        //3. 放入共享域
        request.setAttribute("addressList",addressList);
        request.setAttribute("cartList",cartList);

        //4. 跳转到订单页面
        return Constants.FORWARD + "order.jsp";
    }

    //提交订单
    public String create(HttpServletRequest request, HttpServletResponse response) {

        //1. 获取请求参数
        String uid = request.getParameter("uid");
        String sum = request.getParameter("sum");
        String aid = request.getParameter("aid");

        //2. 调用业务逻辑结构
        orderService.createOrder(uid, sum, aid);

        return Constants.FORWARD + "order?method=show";
    }

    public String show(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("loginUser");
        if (user == null) {//如未登录
            session.setAttribute("msg","请先登陆哦!");
            return Constants.REDIRECT + "/login.jsp";
        }
        int uid = user.getUid();

        List<Orders> orderList = orderService.showOrders(uid);
        request.setAttribute("orderList",orderList);

        return Constants.FORWARD + "/orderList.jsp";
    }

    public String detail(HttpServletRequest request, HttpServletResponse response) {
        String oid = request.getParameter("oid");

        Orders orderDetails = orderService.showDetails(oid);
        request.setAttribute("orderDetails",orderDetails);

        return Constants.FORWARD + "/orderDetail.jsp";
    }
}
6.7.1 验证码
package com.dz.controller;

import cn.dsna.util.images.ValidateCode;

import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * description: 生成验证码的Controller
 */

@WebServlet("/code")
public class CodeController extends BaseServlet{

    public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //1. 生成验证码对象
        ValidateCode validateCode = new ValidateCode(100,35,4,20);
        //2. 将验证码放入session
        String codes = validateCode.getCode();
        request.getSession().setAttribute("codes",codes);
        //3. 向页面写回验证码
        ServletOutputStream outputStream = response.getOutputStream();
        validateCode.write(outputStream);

    }
}

6.2 Service

6.2.1 UserServiceImpl
package com.dz.service.impl;

import com.dz.dao.UserDao;
import com.dz.dao.impl.UserDaoImpl;
import com.dz.entity.User;
import com.dz.service.UserService;
import com.dz.utils.Constants;
import com.dz.utils.DbUtils;
import com.dz.utils.EmailUtils;
import com.dz.utils.MD5Utils;

/**
 * description: 用户模块 业务逻辑实现类
 */

public class UserServiceImpl implements UserService {

    // 创建Dao访问对象
    private UserDao userDao = new UserDaoImpl();

    @Override
    public boolean checkedUser(String username) {
        User user = null;
        //1. 查找用户名
        try {
            DbUtils.begin();
            user = userDao.selectUserByUN(username);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        //2. 判断用户名是否存在
        //true 存在 false 不存在
        return user != null;
    }

    @Override
    public int registerUser(User user) {
        int row = 0;
        try {
            DbUtils.begin();
            //1. 将用户信息保存到数据库
            row = userDao.insertUser(user);
            //2. 发送一封邮件
            EmailUtils.sendEmail(user);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int activeUser(String code) {
        int row = Constants.ACTIVE_FAIL;
        try {
            DbUtils.begin();
            //1. 根据激活码查找用户
            User user = userDao.selectUserByCode(code);
            if (user != null) {//用户不为空,找到用户
                //2. 判断用户是否激活
                if (user.getUstatus().equals(Constants.USER_ACTIVE)) {
                    row =  Constants.ACTIVE_ALREADY;//如用户已激活则返回2(已激活状态)
                }else {
                    //3. 进行激活操作
                    row = userDao.updateStatusByUid(user.getUid());
                }
            }
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public User login(String username, String password) {
        User user = null;
        try {
            DbUtils.begin();
            //1. 需要将密码用MD5处理
            String md5password = MD5Utils.md5(password);
            //2. 根据用户名查找用户
            User temp = userDao.selectUserByUN(username);
            if (temp != null) {
                if (temp.getUpassword().equals(md5password)) {
                    user = temp;
                }
            }
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return user;
    }
}
6.2.2 AddressServiceImpl
package com.dz.service.impl;

import com.dz.dao.AddressDao;
import com.dz.dao.impl.AddressDaoImpl;
import com.dz.entity.Address;
import com.dz.service.AddressService;
import com.dz.utils.Constants;
import com.dz.utils.DbUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * description: 地址模块 业务逻辑实现类
 */

public class AddressServiceImpl implements AddressService {
    private AddressDao addressDao = new AddressDaoImpl();

    @Override
    public List<Address> findAddressByUid(int uid) {
        List<Address> addressList = new ArrayList<>();
        try {
            DbUtils.begin();
            addressList = addressDao.selectAddressByUid(uid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }

        return addressList;
    }

    @Override
    public int addAddress(Address address) {
        int row = 0;
        try {
            DbUtils.begin();
            row = addressDao.insertAddress(address);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int deleteAddress(String aid) {
        int row = 0;
        try {
            DbUtils.begin();
            row = addressDao.delAddress(aid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int defaultAddr(String aid, int uid) {
        int row = Constants.COMMON_ADDRESS;
        try {
            DbUtils.begin();
            //1. 将aid的状态改为1
            int row1 = addressDao.setDefaultByAid(aid);
            //2. 将非aid的状态改为0
            int row2 = addressDao.setCommonByAid(aid, uid);
            if (row1 == Constants.DEFAULT_ADDRESS && row2 == Constants.DEFAULT_ADDRESS) {
                row = Constants.DEFAULT_ADDRESS;
            }
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int updateAddress(Address address) {
        int row = 0;
        try {
            DbUtils.begin();
            row = addressDao.uptAddressByAid(address);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }
}
6.2.3 TypeServiceImpl
package com.dz.service.impl;

import com.dz.dao.TypeDao;
import com.dz.dao.impl.TypeDaoImpl;
import com.dz.entity.Type;
import com.dz.service.TypeService;
import com.dz.utils.DbUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * description: 商品类别模块 业务逻辑实现类
 */

public class TypeServiceImpl implements TypeService {
    private TypeDao typeDao = new TypeDaoImpl();

    @Override
    public List<Type> findAll() {
        List<Type> typeList = new ArrayList<>();
        try {
            DbUtils.begin();
            List<Type> temp = typeDao.selectAll();
            if (temp != null) {
                typeList = temp;
            }
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return typeList;
    }
}
6.2.4 ProductServiceImpl
package com.dz.service.impl;

import com.dz.dao.ProductDao;
import com.dz.dao.impl.ProductDaoImpl;
import com.dz.entity.PageBean;
import com.dz.entity.Product;
import com.dz.service.ProductService;
import com.dz.utils.DbUtils;

import java.util.List;

/**
 * description: 商品模块 业务逻辑实现类
 */

public class ProductServiceImpl implements ProductService {
    private ProductDao productDao = new ProductDaoImpl();

    @Override
    public PageBean<Product> findPage(String tid, int page, int pageSize) {
        PageBean<Product> pageBean = null;
        try {
            DbUtils.begin();
            long counts = productDao.selectCountByTid(tid);
            List<Product> list = productDao.selectProductByPage(page, pageSize, tid);
            pageBean = new PageBean<Product>(list, page, pageSize,counts);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return pageBean;
    }

    @Override
    public Product findProductByPid(String pid) {
        Product product = null;
        try {
            DbUtils.begin();
            product = productDao.selectProductByPid(pid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return product;
    }
}
6.2.5 CartServiceImpl
package com.dz.service.impl;

import com.dz.dao.CartDao;
import com.dz.dao.ProductDao;
import com.dz.dao.impl.CartDaoImpl;
import com.dz.dao.impl.ProductDaoImpl;
import com.dz.entity.Cart;
import com.dz.entity.Product;
import com.dz.service.CartService;
import com.dz.utils.DbUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * description: 购物车模块 业务逻辑实现类
 */

public class CartServiceImpl implements CartService {
    private CartDao cartDao = new CartDaoImpl();

    @Override
    public int addCart(int uid, String pid) {

        int row = 0;
        try {
            DbUtils.begin();
            //1. 判断购物车中是否存在此商品
            Cart cart = cartDao.hasThisProduct(uid, pid);
            if (cart != null) {
                //2. 购物车中已存在此商品, 则修改数量和小计
                cart.setCnum(cart.getCnum() + 1);
                row = cartDao.updateCart(cart);
            }else {
                //3. 若购物车不存在此商品则添加
                //根据商品id查询此商品
                ProductDao productDao = new ProductDaoImpl();
                Product product = productDao.selectProductByPid(pid);
                //为购物车对象赋值
                cart = new Cart();
                cart.setPid(Integer.parseInt(pid));
                cart.setUid(uid);
                cart.setProduct(product);
                cart.setCnum(1);
                //加入购物车
                row = cartDao.insertCart(cart);
            }
            DbUtils.commit();
        } catch (NumberFormatException e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public List<Cart> findAll(int uid) {
        List<Cart> cartList = new ArrayList<>();

        try {
            DbUtils.begin();
            cartList =  cartDao.selectCartByUid(uid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return cartList;
    }

    @Override
    public int deleteCart(String cid) {
        int row = 0;
        try {
            DbUtils.begin();
            row = cartDao.deleteCartByCid(cid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int updateCart(String cid, String cnum, String pprice) {
        int row = 0;
        try {
            DbUtils.begin();
            row = cartDao.updateCartByCid(cid, cnum, pprice);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }

    @Override
    public int clearCart(String uid) {
        int row = 0;
        try {
            DbUtils.begin();
            row = cartDao.clearCartByUid(uid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return row;
    }
}
6.2.6 OrderServiceImpl
package com.dz.service.impl;

import com.dz.dao.AddressDao;
import com.dz.dao.CartDao;
import com.dz.dao.OrderDao;
import com.dz.dao.impl.OrderDaoImpl;
import com.dz.dao.impl.AddressDaoImpl;
import com.dz.dao.impl.CartDaoImpl;
import com.dz.entity.Address;
import com.dz.entity.Cart;
import com.dz.entity.Item;
import com.dz.entity.Orders;
import com.dz.service.OrderService;
import com.dz.utils.DbUtils;
import com.dz.utils.RandomUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * description: 订单模块 业务逻辑实现类
 */

public class OrderServiceImpl implements OrderService {
    private OrderDao orderDao = new OrderDaoImpl();

    @Override
    public void createOrder(String uid, String sum, String aid) {
        try {
            DbUtils.begin();
            //1. 创建一个订单对象进行保存
            Orders orders = new Orders();
            String orderId = RandomUtils.createOrderId();//使用随机数工具类得到订单id
            AddressDao addressDao = new AddressDaoImpl();
            Address address = addressDao.selectAddressByAid(aid);//获取到aid对应的地址对象

            BigDecimal sumBig = new BigDecimal(sum);//总钱数要转为BigDecimal
            orders.setOid(orderId);
            orders.setAid(Integer.parseInt(aid));
            orders.setUid(Integer.parseInt(uid));
            orders.setOtime(new Date());
            orders.setOcount(sumBig);
            orders.setOstate(0);
            orders.setOdetail(address.getAdetail());

            //2. 保存订单
            orderDao.insetOrders(orders);
            //3. 将购物车转成订单项
            CartDao cartDao = new CartDaoImpl();
            //获取到购物车集合
            List<Cart> cartList = cartDao.selectCartByUid(Integer.parseInt(uid));
            //创建订单集合
            List<Item> itemList = new ArrayList<>();
            for (Cart cart : cartList) {//遍历购物车集合
                Item item = new Item();//创建订单项对象
                //为订单项对象赋值
                item.setOid(orderId);
                item.setPid(cart.getPid());
                item.setInum(cart.getCnum());
                item.setIcount(cart.getCcount());
                //加入订单项集合
                itemList.add(item);
            }
            //4. 保存订单对应的订单项
            orderDao.insertItems(itemList);
            //5. 清空购物车
            cartDao.clearCartByUid(uid);
            DbUtils.commit();
        } catch (NumberFormatException e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
    }

    @Override
    public List<Orders> showOrders(int uid) {
        List<Orders> orderList = new ArrayList<>();
        try {
            DbUtils.begin();
            orderList = orderDao.selectOrderByUid(uid);
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }

        return orderList;
    }

    @Override
    public Orders showDetails(String oid) {
        //1. 通过oid查询订单和订单地址信息
        //订单和地址
        Orders orders = orderDao.selectOrdersByOid(oid);
        //2. 通过oid查询对应的订单项和商品信息
        //订单项和商品
        List<Item> itemList = orderDao.selectItemsByOid(oid);
        //3. 订单项集合设置给订单对象
        orders.setItems(itemList);

        return orders;
    }
}

6.3 Dao

6.3.1 UserDaoImpl
package com.dz.dao.impl;

import com.dz.dao.UserDao;
import com.dz.entity.User;
import com.dz.utils.Constants;
import com.dz.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import java.sql.SQLException;

/**
 * description: 用户模块 数据访问实现类
 */

public class UserDaoImpl implements UserDao {
    // 创建一个queryRunner对象
    private QueryRunner queryRunner = new QueryRunner();

    @Override
    public User selectUserByUN(String username) {
        User user = null;
        //1. 编写SQL语句
        String sql = "select u_id as uid, u_name as username, u_password as upassword" +
                    ", u_email as email, u_sex as usex, u_status as ustatus, u_code as code" +
                    ", u_role as urole from user where u_name = ?";
        try {
            //2. 执行SQL语句
            user = queryRunner.query(DbUtils.getConnection(),sql, new BeanHandler<User>(User.class), username);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //3. 返回查询到的结果
        return user;
    }

    @Override
    public int insertUser(User user) {
        int row = 0;
        //1. 编写SQL语句
        String sql = "insert into user(u_name, u_password, u_email, u_sex, u_status, u_code, u_role) values(?,?,?,?,?,?,?)";

        try {
            //2. 执行SQL语句
            row = queryRunner.update(DbUtils.getConnection(), sql, user.getUsername(), user.getUpassword(),
                        user.getEmail(), user.getUsex(), user.getUstatus(), user.getCode(), user.getUrole());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //3. 返回受影响行数
        return row;
    }

    @Override
    public User selectUserByCode(String code) {
        User user = null;
        //1. 编写SQL语句
        String sql = "select u_id as uid, u_name as username, u_password as upassword" +
                ", u_email as email, u_sex as usex, u_status as ustatus, u_code as code" +
                ", u_role as urole from user where u_code = ?";
        try {
            //2. 执行SQL语句
            user = queryRunner.query(DbUtils.getConnection(),sql, new BeanHandler<User>(User.class), code);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //3. 返回查询到的结果
        return user;
    }

    @Override
    public int updateStatusByUid(int uid) {
        int row = 0;
        //1. 编写SQL语句
        String sql = "update user set u_status = ? where u_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, Constants.USER_ACTIVE, uid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }
}
6.3.2 AddressDaoImpl
package com.dz.dao.impl;

import com.dz.dao.AddressDao;
import com.dz.entity.Address;
import com.dz.utils.Constants;
import com.dz.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * description: 地址模块 数据访问实现类
 */

public class AddressDaoImpl implements AddressDao {
    private QueryRunner queryRunner = new QueryRunner();

    @Override
    public List<Address> selectAddressByUid(int uid) {
        List<Address> addressList = new ArrayList<>();
        String sql = "select a_id as aid, u_id as uid, a_name as aname, a_phone as aphone," +
                " a_detail as adetail,a_state as astate from address where u_id = ? order by astate desc ";
        try {
            addressList = queryRunner.query(DbUtils.getConnection(), sql, new BeanListHandler<Address>(Address.class), uid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return addressList;
    }

    @Override
    public int insertAddress(Address address) {
        int row = 0;
        String sql = "insert into address(u_id,a_name,a_phone,a_detail,a_state) values(?,?,?,?,?)";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, address.getUid(), address.getAname(), address.getAphone(), address.getAdetail(), address.getAstate());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    @Override
    public int delAddress(String aid) {
        int row = 0;
        String sql = "delete from address where a_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, aid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    @Override
    public int setDefaultByAid(String aid) {

        int row = 0;
        String sql = "update address set a_state = ? where a_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, Constants.DEFAULT_ADDRESS, aid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    @Override
    public int setCommonByAid(String aid, int uid) {
        int row = 0;
        String sql = "update address set a_state = ? where a_id != ? and u_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, Constants.COMMON_ADDRESS, aid, uid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    @Override
    public int uptAddressByAid(Address address) {
        int row = 0;
        String sql = "update address set a_name = ?, a_phone = ?, a_detail = ?, a_state = ? where a_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, address.getAname(), address.getAphone(), address.getAdetail(), address.getAstate(), address.getAid());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    @Override
    public Address selectAddressByAid(String aid) {
        Address address = null;
        String sql = "select a_detail as adetail from address where a_id = ? ";

        try {
            address = queryRunner.query(DbUtils.getConnection(), sql, new BeanHandler<Address>(Address.class), aid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return address;
    }
}
6.3.3 TypeDaoImpl
package com.dz.dao.impl;

import com.dz.dao.TypeDao;
import com.dz.entity.Type;
import com.dz.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * description: 商品类别模块 数据访问实现类
 */

public class TypeDaoImpl implements TypeDao {
    private QueryRunner queryRunner = new QueryRunner();
    @Override
    public List<Type> selectAll() {
        List<Type> typeList = new ArrayList<>();
        String sql = "select t_id as tid, t_name as tname, t_info as tinfo from type limit 5";
        try {
            typeList = queryRunner.query(DbUtils.getConnection(), sql, new BeanListHandler<Type>(Type.class));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return typeList;
    }
}
6.3.4 ProductDaoImpl
package com.dz.dao.impl;

import com.dz.dao.ProductDao;
import com.dz.entity.Product;
import com.dz.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * description: 商品模块 数据访问实现类
 */

public class ProductDaoImpl implements ProductDao {

    private QueryRunner queryRunner = new QueryRunner();

    @Override
    public long selectCountByTid(String tid) {
        long counts = 0;
        String sql = "select count(*) from product where t_id = ?";
        try {
            Object result = queryRunner.query(DbUtils.getConnection(), sql, new ScalarHandler(), tid);
            counts = (long) result;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return counts;
    }

    @Override
    public List<Product> selectProductByPage(int page, int pageSize, String tid) {
        List<Product> productList = new ArrayList<>();
        String sql = "select p_id as pid, t_id as tid, p_name as pname, p_time as ptime" +
                ", p_image as pimage, p_price as pprice, p_state as pstate, p_info as pinfo" +
                " from product where t_id = ? limit ?,?";
        try {
            productList = queryRunner.query(DbUtils.getConnection(), sql, new BeanListHandler<Product>(Product.class), tid, (page-1)*pageSize, pageSize);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return productList;
    }

    @Override
    public Product selectProductByPid(String pid) {
        Product product = null;
        String sql = "select p_id as pid, t_id as tid, p_name as pname, p_time as ptime" +
                ", p_image as pimage, p_price as pprice, p_state as pstate, p_info as pinfo" +
                " from product where p_id = ?";
        try {
            product = queryRunner.query(DbUtils.getConnection(), sql, new BeanHandler<Product>(Product.class), pid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return product;
    }
}
6.3.5 CartDaoImpl
package com.dz.dao.impl;

import com.dz.dao.CartDao;
import com.dz.entity.Cart;
import com.dz.entity.Product;
import com.dz.utils.DbUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * description: 购物车模块 数据访问实现类
 */

public class CartDaoImpl implements CartDao {
    private QueryRunner queryRunner = new QueryRunner();

    //查询购物车中是否有此商品
    @Override
    public Cart hasThisProduct(int uid, String pid) {
        Cart cart = null;
        //连接查询,多表查询
        String sql = "select product.p_id as pid, t_id as tid, p_name as pname, p_time as ptime, " +
                "p_image as pimage, p_price as pprice, p_state as pstate, p_info as pinfo, " +
                "c_id as cid, cart.p_id as pid, u_id as uid, c_count as ccount, c_num as cnum " +
                "from product inner join cart on product.p_id = cart.p_id where cart.u_id = ? and cart.p_id = ?";
        try {
            //存入Map集合
            Map<String, Object> map = queryRunner.query(DbUtils.getConnection(), sql, new MapHandler(), uid, pid);
            if (map != null) {
                cart = new Cart();
                Product product = new Product();
                //BeanUtils.populate( Object bean, Map properties )
                //这个方法会遍历map<key, value>中的key,如果bean中有这个属性,就把这个key对应的value值赋给bean的属性
                BeanUtils.populate(cart,map);
                BeanUtils.populate(product,map);
                cart.setProduct(product);
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException throwables) {
            throwables.printStackTrace();
        }

        return cart;
    }

    //更新购物车(如购物车内已有此商品,更新即可)
    @Override
    public int updateCart(Cart cart) {
        int row = 0;
        String sql = "update cart set c_num = ?,c_count = ? where c_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, cart.getCnum(), cart.getCcount(), cart.getCid());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    //添加购物车
    @Override
    public int insertCart(Cart cart) {
        int row = 0;
        String sql = "insert into cart(p_id,u_id,c_count,c_num) values(?,?,?,?)";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, cart.getPid(), cart.getUid(), cart.getCcount(), cart.getCnum());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    //查询用户所有的购物车(一个用户有多个购物车,每个商品对应一个购物车)
    @Override
    public List<Cart> selectCartByUid(int uid) {
        List<Cart> cartList = new ArrayList<>();
        //连接查询,多表查询,查询cart需要关联到商品表
        String sql = "select product.p_id as pid, t_id as tid, p_name as pname, p_time as ptime, " +
                "p_image as pimage, p_price as pprice, p_state as pstate, p_info as pinfo, " +
                "c_id as cid, cart.p_id as pid, u_id as uid, c_count as ccount, c_num as cnum " +
                "from product inner join cart on product.p_id = cart.p_id where cart.u_id = ?";
        try {
            List<Map<String, Object>> mapList = queryRunner.query(DbUtils.getConnection(), sql, new MapListHandler(), uid);
            if (mapList != null) {
                for (Map<String, Object> map : mapList) {
                    //cart + product
                    Cart cart = new Cart();
                    Product product = new Product();

                    BeanUtils.populate(cart, map);
                    BeanUtils.populate(product, map);

                    cart.setProduct(product);
                    cartList.add(cart);
                }
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException throwables) {
            throwables.printStackTrace();
        }

        return cartList;
    }

    //删除用户一个购物车中的商品(不是清空购物车,用户还有其他购物车,存着其他商品)
    @Override
    public int deleteCartByCid(String cid) {
        int row = 0;
        String sql = "delete from cart where c_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, cid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    //修改某一个购物车中的商品数据(数量,小计),实现购物车内商品加减操作
    @Override
    public int updateCartByCid(String cid, String cnum, String pprice) {
        BigDecimal cnumBig = new BigDecimal(cnum);
        BigDecimal ppriceBig = new BigDecimal(pprice);
        BigDecimal ccount = cnumBig.multiply(ppriceBig);
        int row = 0;
        String sql = "update cart set c_num = ?, c_count = ? where c_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, cnum, ccount, cid );
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

    //清空所有的购物车
    @Override
    public int clearCartByUid(String uid) {
        int row = 0;
        String sql = "delete from cart where u_id = ?";
        try {
            row = queryRunner.update(DbUtils.getConnection(), sql, uid);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return row;
    }

}
6.3.6 OrderDaoImpl
package com.dz.dao.impl;

import com.dz.dao.OrderDao;
import com.dz.entity.Address;
import com.dz.entity.Item;
import com.dz.entity.Orders;
import com.dz.entity.Product;
import com.dz.utils.DbUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * description: 订单模块 数据访问实现类
 */

public class OrderDaoImpl implements OrderDao {
    private QueryRunner queryRunner = new QueryRunner();

    @Override
    public void insetOrders(Orders orders) {
        String sql = "insert into orders(o_id,a_id,u_id,o_count,o_time,o_state,o_detail) values(?,?,?,?,?,?,?)";
        try {
            queryRunner.update(DbUtils.getConnection(), sql, orders.getOid(), orders.getAid(), orders.getUid(),
                    orders.getOcount(), orders.getOtime(), orders.getOstate(), orders.getOdetail());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public void insertItems(List<Item> itemList) {
        Object [][] params = new Object[itemList.size()][];
        String sql = "insert into item(o_id,p_id,i_num,i_count) values(?,?,?,?)";

        for (int i = 0; i < itemList.size(); i++) {
            Item item = itemList.get(i);
            params[i] = new Object[]{item.getOid(), item.getPid(), item.getInum(), item.getIcount()};
        }
        try {
            queryRunner.batch(DbUtils.getConnection(), sql, params);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public List<Orders> selectOrderByUid(int uid) {

        List<Orders> orderList = new ArrayList<>();
        String sql = "select o_id as oid, o.a_id as aid, o.u_id as uid, o_count as ocount, o_time as otime," +
                "o_state as ostate, o_detail as odetail, a.a_id as aid, a.u_id as uid, a_name as aname, " +
                "a_phone as aphone, a_detail as adetail, a_state as astate from orders o inner join " +
                "address a on o.a_id = a.a_id where o.u_id = ?";
        try {
            List<Map<String, Object>> mapList = queryRunner.query(DbUtils.getConnection(), sql, new MapListHandler(), uid);
            if (mapList != null) {
                for (Map<String, Object> map : mapList) {
                    Orders orders = new Orders();
                    Address address = new Address();

                    BeanUtils.populate(orders, map);
                    BeanUtils.populate(address, map);

                    orders.setAddress(address);
                    orderList.add(orders);
                }
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException throwables) {
            throwables.printStackTrace();
        }

        return orderList;
    }

    @Override
    public Orders selectOrdersByOid(String oid) {
        Orders order = null;
        String sql = "select o_id as oid, o.a_id as aid, o.u_id as uid, o_count as ocount, o_time as otime," +
                "o_state as ostate, o_detail as odetail, a.a_id as aid, a.u_id as uid, a_name as aname, " +
                "a_phone as aphone, a_detail as adetail, a_state as astate from orders o inner join " +
                "address a on o.a_id = a.a_id where o_id = ?";
        try {
            Map<String, Object> map = queryRunner.query(DbUtils.getConnection(), sql, new MapHandler(), oid);
            if (map != null) {
                order = new Orders();
                Address address = new Address();

                BeanUtils.populate(order, map);
                BeanUtils.populate(address, map);

                order.setAddress(address);
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException throwables) {
            throwables.printStackTrace();
        }

        return order;
    }

    @Override
    public List<Item> selectItemsByOid(String oid) {
        List<Item> itemList = new ArrayList<>();
        String sql = "select p.p_id as pid, t_id as tid, p_name as pname, p_time as ptime" +
                ", p_image as pimage, p_price as pprice, p_state as pstate, p_info as pinfo," +
                "i_id as iid, o_id as oid, i.p_id as pid, i_num as inum, i_count as icount " +
                "from product p inner join item i on p.p_id = i.p_id where o_id = ?";

        try {
            List<Map<String, Object>> mapList = queryRunner.query(DbUtils.getConnection(), sql, new MapListHandler(), oid);
            if (mapList != null) {
                for (Map<String, Object> map : mapList) {
                    Item item = new Item();
                    Product product = new Product();

                    BeanUtils.populate(item, map);
                    BeanUtils.populate(product, map);

                    item.setProduct(product);
                    itemList.add(item);
                }
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException throwables) {
            throwables.printStackTrace();
        }

        return itemList;
    }
}

6.4 Filter

6.4.1 AutoFilter
package com.dz.filter;

import com.dz.entity.User;
import com.dz.service.impl.UserServiceImpl;
import com.dz.utils.Base64Utils;
import com.dz.utils.Constants;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * description: 自动登陆过滤器
 */

@WebFilter("/login.jsp") //默认情况下, 过滤器只过滤正常请求和重定向
public class AutoFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        Cookie[] cookies =request.getCookies();

        if (cookies != null) {
            //本地存储了cookie
            String content = null;//用来存储用户名和密码

            for (Cookie cookie : cookies) {
                //如果找到存储 自动登陆cookie 的名字就读取里面存储的账号密码
                if (cookie.getName().equals(Constants.AUTO_NAME)) {
                    content = cookie.getValue();
                }
            }

            if (content != null) {
                //读取到了 自动登陆cookie 存储的用户名和密码
                //base64解码
                content = Base64Utils.decode(content);
                //从:处切割,分成用户名和密码
                String[] split = content.split(Constants.FLAG);
                String username = split[0];
                String password = split[1];

                //调用业务逻辑进行登陆, 如果可以登陆证明用户名和密码正确
                UserServiceImpl userService = new UserServiceImpl();
                User user = userService.login(username, password);
                if (user != null) {
                    //可以自动登陆
                    HttpSession session = request.getSession();
                    session.setAttribute("loginUser",user);
                    response.sendRedirect(request.getContextPath() + "/index.jsp");
                }else {
                    filterChain.doFilter(servletRequest,servletResponse);
                }

            }else {
                //没有读取到, 放行
                filterChain.doFilter(servletRequest,servletResponse);
            }
        }else {
            //本地没有存储cookie,放行即可
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}
6.4.2 EncodingFilter
package com.dz.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * description: 处理乱码问题
 */

@WebFilter(filterName = "EncodingFilter",value = "/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

6.5 Utils

6.5.1 Constants
package com.dz.utils;

/**
 * description: 项目的常量类
 */

public class Constants {

    /**
     * 定义BaseServlet中涉及的常量
     */

    public static final String TAG = "method";

    public static final String FORWARD = "forward:";

    public static final String REDIRECT = "redirect:";

    public static final String FLAG = ":";

    public static final String INDEX = "index";

    /**
     * 定义用户模块涉及的常量
     */

    public static final String HAS_USER = "1";

    public static final String NOT_HAS_USER = "0";

    public static final String USER_ACTIVE = "1";

    public static final String USER_NOT_ACTIVE = "0";

    public static final int ROLE_ADMIN = 1;

    public static final int ROLE_CUSTOMER = 0;

    /**
     * 用户模块账号激活结果
     */

    public static final int ACTIVE_SUCCESS = 1;

    public static final int ACTIVE_FAIL = 0;

    public static final int ACTIVE_ALREADY = 2;

    /**
     * 自动登陆cookie名
     */

    public static final String AUTO_NAME = "autoUser";

    /**
     * 地址模块 1 默认地址 0 普通地址
     */

    public static final int DEFAULT_ADDRESS = 1;

    public static final int COMMON_ADDRESS = 0;

}
6.5.2 DbUtils
package com.dz.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * belongsProject: MyShop
 */

public class DbUtils {
    private static DruidDataSource ds;
    private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();

    static {
        Properties properties = new Properties();
        InputStream inputStream = DbUtils.class.getResourceAsStream("/database.properties");
        try {
            properties.load(inputStream);
            ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection conn = THREAD_LOCAL.get();
        try {
            if (conn == null) {
                conn = ds.getConnection();
                THREAD_LOCAL.set(conn);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    public static void begin() {
        Connection conn = null;
        try {
            conn = getConnection();
            conn.setAutoCommit(false);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public static void commit() {
        Connection conn = null;
        try {
            conn = getConnection();
            conn.commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            closeAll(conn,null,null);
        }
    }

    public static void rollback() {
        Connection conn = null;
        try {
            conn = getConnection();
            conn.rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            closeAll(conn,null,null);
        }
    }

    public static void closeAll(Connection conn, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (conn != null) {
                conn.close();
                THREAD_LOCAL.remove();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

}
6.5.3 RandomUtils
package com.dz.utils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;

//生成邮箱验证 激活码 使用的随机数
public class RandomUtils {
    //当前时间 + 随机数
    public static String createActive(){

        return getTime()+Integer.toHexString(new Random().nextInt(900)+100);
    }
    public static String getTime(){
        return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(Calendar.getInstance().getTime());
    }
    //生成订单编号
    public static String createOrderId(){
        return getTime();
    }
}
6.5.4 Base64Utils
package com.dz.utils;

import java.util.Base64;

//base64 加密 解密 激活邮件的时候 为 邮箱地址 code验证码 进行加密
//当 回传回来后 进行 code 的解密
public class Base64Utils {
    //加密
    public static String encode(String msg){
        return Base64.getEncoder().encodeToString(msg.getBytes());
    }
    //解密
    public static String decode(String msg){
        return new String(Base64.getDecoder().decode(msg));
    }
}
6.5.5 EmailUtils
package com.dz.utils;

import com.dz.entity.User;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Properties;

/*
 * 1.首先需要获取发送邮件的Session对象
 *     Session session = Session.getDefaultInstance(Properties prop)
 * 2.使用session对象 获取待发送的邮件信息
 *  MimeMessage mime = new MimeMessage(session)
 * 3.设置发件人 收件人 标题 邮件内容 附件 发送时间等等
 * 4.利用Transport 发送邮件
 * */
public class EmailUtils {
    public static void sendEmail(User user){
        //发送方
        String myAccount = "dzjava137@163.com";
        //授权码
        String myPass = "IDKINWUVBANSGGVJ";
        //发件人 邮箱的 SMTP 服务器地址
        String SMTPHost = "smtp.163.com";
        //组成 properties
        Properties prop = new Properties();
        prop.setProperty("mail.transport.protocol", "smtp");//设置协议类型
        prop.setProperty("mail.smtp.host", SMTPHost);//定义发件人的邮箱服务器地址
        prop.setProperty("mail.smtp.auth", "true");//设置请求验证
        //1.Session对象 创建会话 用于和邮箱服务器进行交互
        Session session = Session.getDefaultInstance(prop);
        //设置debug模式 可以查看详细发送信息 可略
        //session.setDebug(true);

        //2.创建方法 用来组成一封完整的邮件
        //参数 session(参数配置), myAccount 发送方 , user.getEmail() 接收方
        MimeMessage message = createMsg(session,myAccount,user);
        //4.利用Transport 发送邮件
        try {
            Transport tran = session.getTransport();
            //连接服务器 确认发送方 是否授权
            tran.connect(myAccount, myPass);
            //发送邮件 将message 对象 传给 Transport 对象 将邮件发送出去
            //参数1 要发的内容 参数2 要给哪些人发
            //message.getAllRecipients() 获取到所有的收件人 | 抄送 | 密送
            tran.sendMessage(message, message.getAllRecipients());
            //关闭连接
            tran.close();
        } catch (MessagingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private static MimeMessage createMsg(Session session, String myAccount, User user) {
        //使用session对象 获取待发送的邮件信息
        MimeMessage message = new MimeMessage(session);
        //3.设置发件人 收件人 标题 邮件内容 附件 发送时间等等
        try {
            //3.1发件人 from
            message.setFrom(new InternetAddress(myAccount, "小米", "utf-8"));
            //3.2收件人 to 支持可以添加多个收件人 | 抄送 | 密送 如果想要发送给多个人 可以重复下面代码多次
            /*
             * MimeMessage.RecipientType.TO 发送
             * MimeMessage.RecipientType.CC 抄送
             * MimeMessage.RecipientType.BCC 密送
             * */
            message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(user.getEmail(), user.getUsername(), "utf-8"));
            //3.3生成邮件主题
            message.setSubject("MyShop商城账号激活邮件","utf-8");
            String ip = Inet4Address.getLocalHost().getHostAddress();
            String url = "http://"+ip+":8080/user?method=active&c="+ Base64Utils.encode(user.getCode());
            //设置邮件正文 setContent 可以使用html标签
            message.setContent(user.getUsername()+",你好<br>欢迎注册myshop商城! 请点击链接进行激活:<a href='"+url+"'>点击此处</a>","text/html;charset=utf-8");
            //设置邮件的发送时间 是立即发送
            message.setSentDate(new Date());
            //保存设置
            message.saveChanges();
        } catch (UnsupportedEncodingException | MessagingException | UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return message;
    }
}
6.5.6 MD5Utils
package com.dz.utils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

//MD5 生成器
public class MD5Utils {
    public static String md5(String password){
        //生成一个md5加密器
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            //计算MD5 的值
            md.update(password.getBytes());
            //BigInteger 将8位的字符串 转成16位的字符串 得到的字符串形式是哈希码值
            //BigInteger(参数1,参数2) 参数1 是 1为正数 0为0 -1为负数
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}
6.5.7 PaymentUtil
package com.dz.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class PaymentUtil {

    private static String encodingCharset = "UTF-8";

    /**
     * 生成hmac方法
     *
     * @param p0_Cmd 业务类型
     * @param p1_MerId 商户编号
     * @param p2_Order 商户订单号
     * @param p3_Amt 支付金额
     * @param p4_Cur 交易币种
     * @param p5_Pid 商品名称
     * @param p6_Pcat 商品种类
     * @param p7_Pdesc 商品描述
     * @param p8_Url 商户接收支付成功数据的地址
     * @param p9_SAF 送货地址
     * @param pa_MP 商户扩展信息
     * @param pd_FrpId 银行编码
     * @param pr_NeedResponse 应答机制
     * @param keyValue 商户密钥
     * @return
     */
    public static String buildHmac(String p0_Cmd,String p1_MerId,
            String p2_Order, String p3_Amt, String p4_Cur,String p5_Pid, String p6_Pcat,
            String p7_Pdesc,String p8_Url, String p9_SAF,String pa_MP,String pd_FrpId,
            String pr_NeedResponse,String keyValue) {
        StringBuilder sValue = new StringBuilder();
        // 业务类型
        sValue.append(p0_Cmd);
        // 商户编号
        sValue.append(p1_MerId);
        // 商户订单号
        sValue.append(p2_Order);
        // 支付金额
        sValue.append(p3_Amt);
        // 交易币种
        sValue.append(p4_Cur);
        // 商品名称
        sValue.append(p5_Pid);
        // 商品种类
        sValue.append(p6_Pcat);
        // 商品描述
        sValue.append(p7_Pdesc);
        // 商户接收支付成功数据的地址
        sValue.append(p8_Url);
        // 送货地址
        sValue.append(p9_SAF);
        // 商户扩展信息
        sValue.append(pa_MP);
        // 银行编码
        sValue.append(pd_FrpId);
        // 应答机制
        sValue.append(pr_NeedResponse);

        return PaymentUtil.hmacSign(sValue.toString(), keyValue);
    }

    /**
     * 返回校验hmac方法
     *
     * @param hmac 支付网关发来的加密验证码
     * @param p1_MerId 商户编号
     * @param r0_Cmd 业务类型
     * @param r1_Code 支付结果
     * @param r2_TrxId 易宝支付交易流水号
     * @param r3_Amt 支付金额
     * @param r4_Cur 交易币种
     * @param r5_Pid 商品名称
     * @param r6_Order 商户订单号
     * @param r7_Uid 易宝支付会员ID
     * @param r8_MP 商户扩展信息
     * @param r9_BType 交易结果返回类型
     * @param keyValue 密钥
     * @return
     */
    public static boolean verifyCallback(String hmac, String p1_MerId,
            String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt,
            String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid,
            String r8_MP, String r9_BType, String keyValue) {
        StringBuilder sValue = new StringBuilder();
        // 商户编号
        sValue.append(p1_MerId);
        // 业务类型
        sValue.append(r0_Cmd);
        // 支付结果
        sValue.append(r1_Code);
        // 易宝支付交易流水号
        sValue.append(r2_TrxId);
        // 支付金额
        sValue.append(r3_Amt);
        // 交易币种
        sValue.append(r4_Cur);
        // 商品名称
        sValue.append(r5_Pid);
        // 商户订单号
        sValue.append(r6_Order);
        // 易宝支付会员ID
        sValue.append(r7_Uid);
        // 商户扩展信息
        sValue.append(r8_MP);
        // 交易结果返回类型
        sValue.append(r9_BType);
        String sNewString = PaymentUtil.hmacSign(sValue.toString(), keyValue);
        return sNewString.equals(hmac);
    }

    /**
     * @param aValue
     * @param aKey
     * @return
     */
    public static String hmacSign(String aValue, String aKey) {
        byte k_ipad[] = new byte[64];
        byte k_opad[] = new byte[64];
        byte keyb[];
        byte value[];
        try {
            keyb = aKey.getBytes(encodingCharset);
            value = aValue.getBytes(encodingCharset);
        } catch (UnsupportedEncodingException e) {
            keyb = aKey.getBytes();
            value = aValue.getBytes();
        }

        Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
        Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
        for (int i = 0; i < keyb.length; i++) {
            k_ipad[i] = (byte) (keyb[i] ^ 0x36);
            k_opad[i] = (byte) (keyb[i] ^ 0x5c);
        }

        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {

            return null;
        }
        md.update(k_ipad);
        md.update(value);
        byte dg[] = md.digest();
        md.reset();
        md.update(k_opad);
        md.update(dg, 0, 16);
        dg = md.digest();
        return toHex(dg);
    }

    public static String toHex(byte input[]) {
        if (input == null)
            return null;
        StringBuffer output = new StringBuffer(input.length * 2);
        for (int i = 0; i < input.length; i++) {
            int current = input[i] & 0xff;
            if (current < 16)
                output.append("0");
            output.append(Integer.toString(current, 16));
        }

        return output.toString();
    }

    /**
     *
     * @param args
     * @param key
     * @return
     */
    public static String getHmac(String[] args, String key) {
        if (args == null || args.length == 0) {
            return (null);
        }
        StringBuffer str = new StringBuffer();
        for (int i = 0; i < args.length; i++) {
            str.append(args[i]);
        }
        return (hmacSign(str.toString(), key));
    }

    /**
     * @param aValue
     * @return
     */
    public static String digest(String aValue) {
        aValue = aValue.trim();
        byte value[];
        try {
            value = aValue.getBytes(encodingCharset);
        } catch (UnsupportedEncodingException e) {
            value = aValue.getBytes();
        }
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
        return toHex(md.digest(value));

    }

//    public static void main(String[] args) {
//        System.out.println(hmacSign("AnnulCard1000043252120080620160450.0http://localhost/SZXpro/callback.asp杩?4564868265473632445648682654736324511","8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t"));
//    }
}
6.5.8 StrUtils
package com.dz.utils;
//字符串工具类 判定字符串是否为空
public class StrUtils {
    public static boolean empty(String msg){
        return msg!=null && msg.length()>0;
    }
    public static boolean empty(String...msg){
        boolean res = true;
        for(String s:msg){
            res = (s!=null && s.length()>0);
            if(!res){
                break;
            }
        }
        return res;
    }
}