15-基于Spring,MyBatis,SpringBoot,Vue技术实现购物券系统的增删改查操作。

15-基于Spring,MyBatis,SpringBoot,Vue技术实现购物券系统的增删改查操作。

springboot

发布于 10月19日

业务描述

基于Spring,MyBatis,SpringBoot,VUE技术实现购物券的增删改查操作。

项目环境初始化

准备工作

1. MySQL(5.7)
2. JDK (1.8)
3. Maven (3.6.3)
4. IDEA(2020.2)

数据库初始化

打开mysql控制台,然后按如下步骤执行dbretail.sql文件。
第一步:登录mysql。

mysql –uroot –proot

第二步:设置控制台编码方式。

set names utf8;

第三步:执行dbretail.sql文件(切记不要打开文件复制到mysql客户端运行)。

source d:/dbretail.sql

其中dbvoucher.sql文件内容如下:

drop database if exists dbretail;
create database dbretail default character set utf8;
use dbretail;
CREATE TABLE tb_voucher(
     `id`  INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
     `deno` DECIMAL(10,2) UNSIGNED NOT NULL COMMENT '面值',
     `requirement` DECIMAL(10,2) UNSIGNED NOT NULL COMMENT '订单多少钱可以使用',
     `startTime`  DATETIME  COMMENT '起始日期',
     `endTime`  DATETIME  COMMENT '截至日期',
     `maxNum` INT COMMENT '代金卷发放最大数量',
     `remark` varchar(200) COMMENT '备注',
    `createdTime`  DATETIME  COMMENT '创建日期'
) COMMENT='购物券表';
insert into tb_voucher values (null,100,1000,'2020/05/07','2020/06/07',200,'Remark',now());
insert into tb_voucher values (null,80,800,'2020/05/07','2020/06/07',300,'Remark',now());
insert into tb_voucher values (null,50,500,'2020/05/07','2020/06/07',400,'Remark',now());
insert into tb_voucher values (null,30,300,'2020/05/07','2020/06/07',500,'Remark',now());
insert into tb_voucher values (null,10,100,'2020/05/07','2020/06/07',600,'Remark',now());

创建项目并添加依赖

基于IDEA创建

第一步:创建Empty项目并设置基本信息(假如Empty项目已经存在则无需创建)

image.png

image.png

第二步:基于start.spring.io 创建项目Module,并设置基本信息。

image.png

image.png

第三步:创建项目module时指定项目核心依赖

image.png

第四步:继续完成module的创建并分析其结构

image.png

项目配置文件内容初始化

#server
server.port=80
#spring datasource
spring.datasource.url=jdbc:mysql:///dbvoucher?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml

#spring logging
logging.level.com.cy.retail=debug 

项目API架构设计

其API架构设计,如图所示:

image.png

商品查询业务实现

业务描述

从数据库查询购物卷信息,并将购物卷信息呈现在页面上,如图所示:

image.png

业务时序分析

查询所有购物券信息,其业务时序分析,如图所示:
image.png

Pojo类定义

定义Voucher对象,用于封装从数据库查询到的购物券信息。

package com.cy.retail.voucher.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.util.Date;
/**购物卷*/
public class Voucher implements Serializable {
    private static final long serialVersionUID = -8863293149012534747L;
    private Integer id;
    /**面值*/
 private Integer deno;
    /**条件(多少钱可以使用)*/
 private Integer requirement;
    /**起始时间*/
 @JsonFormat(pattern = "yyyy/MM/dd HH:mm")
    private Date startTime;
    /**结束时间*/
 @JsonFormat(pattern = "yyyy/MM/dd HH:mm")
    private Date endTime;
    /**代金卷发放最大数量*/
 private Integer maxNum;
    /**备注*/
 private String remark;
    /**创建时间*/
 private Date createdTime;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getDeno() {
        return deno;
    }
    public void setDeno(Integer deno) {
        this.deno = deno;
    }
    public Integer getRequirement() {
        return requirement;
    }
    public void setRequirement(Integer requirement) {
        this.requirement = requirement;
    }
    public Date getStartTime() {
        return startTime;
    }
    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }
    public Date getEndTime() {
        return endTime;
    }
    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }
    public Integer getMaxNum() {
        return maxNum;
    }
    public void setMaxNum(Integer maxNum) {
        this.maxNum = maxNum;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public Date getCreatedTime() {
        return createdTime;
    }
    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }
    @Override
 public String toString() {
        return "Voucher{" +
                "id=" + id +
                ", deno=" + deno +
                ", requirement=" + requirement +
                ", startTime=" + startTime +
                ", endTime=" + endTime +
                ", maxNum=" + maxNum +
                ", remark='" + remark + ''' +
                ", createdTime=" + createdTime +
                '}';
    }
}

Dao接口方法及映射定义

在GoodsDao接口中定义商品查询方法以及SQL映射,基于此方法及SQL映射获取所有商品信息。代码如下:

package com.cy.retail.voucher.dao;
import com.cy.retail.voucher.pojo.Voucher;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface VoucherDao {

    @Select("select count(*) from tb_voucher")
    int getRowCount();
    @Select("select * from tb_voucher order by createdTime desc limit #{startIndex},#{pageSize}")
    List findPageObjects(Integer startIndex, Integer pageSize);
} 

编写单元测试类进行测试分析:

package com.cy.retail.voucher.dao;
import com.cy.retail.voucher.pojo.Voucher;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class VoucherDaoTests {
    @Autowired
    private VoucherDao voucherDao;
    @Test
    void testGetRowCount(){
        int rowCount=voucherDao.getRowCount();
        System.out.println("rowCount="+rowCount);
    }
    @Test
    void testFindPageObjects(){
        List list=voucherDao.findPageObjects(0,3);
        list.forEach(item-> System.out.println(item));
    }
}

Service接口方法定义及实现

业务逻辑层分页逻辑封装对象定义,代码如下:

package com.cy.retail.common.pojo;
import java.io.Serializable;
import java.util.List;
public class PageObject implements Serializable {
    /**总记录数*/
 private Integer rowCount;
    /**当前页记录*/
 private List records;
    /**总页数(计算出来)*/
 private Integer pageCount;
    /**当前页码值*/
 private Integer pageCurrent;
    /**页面大小(每页最多显示多少条记录)*/
 private Integer pageSize;
    public PageObject(Integer rowCount, List records, Integer pageCurrent, Integer pageSize) {
        this.rowCount = rowCount;
        this.records = records;
        this.pageCurrent = pageCurrent;
        this.pageSize = pageSize;
        this.pageCount=rowCount/pageSize;
        if(this.rowCount%this.pageSize!=0)this.pageCount++;
    }
    public Integer getRowCount() {
        return rowCount;
    }
    public void setRowCount(Integer rowCount) {
        this.rowCount = rowCount;
    }
    public List getRecords() {
        return records;
    }
    public void setRecords(List records) {
        this.records = records;
    }
    public Integer getPageCount() {
        return pageCount;
    }
    public void setPageCount(Integer pageCount) {
        this.pageCount = pageCount;
    }
    public Integer getPageCurrent() {
        return pageCurrent;
    }
    public void setPageCurrent(Integer pageCurrent) {
        this.pageCurrent = pageCurrent;
    }
    public Integer getPageSize() {
        return pageSize;
    }
    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }
    @Override
 public String toString() {
        return "PageObject{" +
                "rowCount=" + rowCount +
                ", records=" + records +
                ", pageCount=" + pageCount +
                ", pageCurrent=" + pageCurrent +
                ", pageSize=" + pageSize +
                '}';
    }
}

VoucherService接口及查询方法定义

package com.cy.retail.voucher.service;
import com.cy.retail.common.pojo.PageObject;
import com.cy.retail.voucher.pojo.Voucher;
public interface VoucherService {
    /**
 * 分页查询Voucher信息
 * @param pageCurrent
 * @param pageSize
 * @return
 */ PageObject findPageObjects(Integer pageCurrent,Integer pageSize);
}

VoucherService接口实现类VoucherServiceImpl定义及方法实现

package com.cy.retail.voucher.service.impl;
import com.cy.retail.common.pojo.PageObject;
import com.cy.retail.voucher.dao.VoucherDao;
import com.cy.retail.voucher.pojo.Voucher;
import com.cy.retail.voucher.service.VoucherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class VoucherServiceImpl implements VoucherService {
    @Autowired
 private VoucherDao voucherDao;
    @Override
 public int deleteById(Integer id) {
        return voucherDao.deleteById(id);
    }
    @Override
 public PageObject findPageObjects(Integer pageCurrent, Integer pageSize) {
        int rowCount=voucherDao.getRowCount();
        int startIndex=(pageCurrent-1)*pageSize;
        List records=voucherDao.findPageObjects(startIndex,pageSize);
        return new PageObject<>(rowCount,records,pageCurrent,pageSize);
    }
}

编写单元测试类进行测试分析

package com.cy.retail.voucher.service;
import com.cy.retail.common.pojo.PageObject;
import com.cy.retail.voucher.dao.VoucherDao;
import com.cy.retail.voucher.pojo.Voucher;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class VoucherServiceTests {
    @Autowired
 private VoucherService voucherService;
    @Test
 void testFindPageObjects(){
        PageObject pageObject=
        voucherService.findPageObjects(1,3);
        System.out.println(pageObject);
    }
}

Controller对象方法定义及实现

控制逻辑层响应数据标准对象设计及实现,代码如下:

package com.cy.retail.common.pojo;
import java.io.Serializable;
public class ResponseResult implements Serializable {
    private static final long serialVersionUID = -4971076199594828397L;
    /**状态:1 ok,0 error*/
 private Integer state=1;
    /**状态信息*/
 private String message="ok";
    /**业务层返回的正确响应数据*/
 private Object data;
    public ResponseResult(){}
    public ResponseResult(String message){ //new JsonResult("update ok");
 this.message=message;
    }
    public ResponseResult(Object data){
        this.data=data;
    }
    public ResponseResult(Throwable e){
        this.state=0;
        this.message=e.getMessage();
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
}

定义VoucherController类,并添加doFindPageObjects方法,代码如下:

ackage com.cy.retail.voucher.controller;
import com.cy.retail.common.pojo.PageObject;
import com.cy.retail.common.pojo.ResponseResult;
import com.cy.retail.voucher.service.VoucherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class VoucherController {
    @Autowired
 private VoucherService voucherService;
    @GetMapping("/voucher/doFindPageObjects/{pageCurrent}/{pageSize}")
    public ResponseResult doFindPageObjects(@PathVariable Integer pageCurrent,@PathVariable Integer pageSize){
        return new ResponseResult(voucherService.findPageObjects(pageCurrent,pageSize));
    }
}

控制层统一异常处理类设计及实现,关键代码如下:

package com.cy.retail.common.web;
import com.cy.retail.common.pojo.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log= LoggerFactory.getLogger(GlobalExceptionHandler.class);
    @ExceptionHandler(RuntimeException.class)
    public ResponseResult doHandleRuntimeException(RuntimeException e){
        e.printStackTrace();//控制台输出
 log.error("exception msg {}"+e.getMessage());
        return new ResponseResult(e);
    }
}

Voucher页面设计及实现

在static目录中添加voucher.html页面,代码如下:




    
    Title
    


The Voucher Page

序号 面值 可用条件 起始日期 截止日期 数量 操作
{{i+1}} {{v.deno}} {{v.requirement}} {{v.startTime}} {{v.endTime}} {{v.maxNum}}

启动服务器进行访问测试分析

首先,启动tomcat,然后在打开浏览器,在地址栏输入访问地址,获取服务端数据并进行呈现,如图所示:
image.png

购物券删除业务实现

业务描述

从数据库查询购物券信息后,点击页面上删除按钮,基于id删除当前行记录,如图所示:

image.png

业务时序分析

在购物券呈现页面,用户执行删除操作,其删除时序如图所示:

image.png

Dao接口方法及映射定义

在VoucherDao接口中定义删除方法以及SQL映射,代码如下:

 @Delete("delete from tb_voucher where id=#{id}")

 int deleteById(Integer id);

Service接口方法定义及实现

在VoucherService接口中添加删除方法,代码如下:

int deleteById(Integer id);

在VoucherService的实现类VoucherServiceImpl中添加deleteById方法实现。代码如下。

@Override
    public int deleteById(Integer id) {
        int rows=voucherDao.deleteById(id);

        return rows;
    }

Controller对象方法定义及实现

在VoucherController中的添加doDeleteById方法,代码如下:

 @DeleteMapping("/voucher/doDeleteById/{id}")
public ResponseResult doDeleteById(@PathVariable Integer id){
    voucherService.deleteById(id);
    return new ResponseResult(id);
} 

说明:Restful 风格为一种软件架构编码风格,定义了一种url的格式,其url语法为/a/b/{c}/{d},在这样的语法结构中{}为一个变量表达式。假如我们希望在方法参数中获取rest url中变量表达式的值,可以使用@PathVariable注解对参数进行描述。

Voucher页面上删除按钮事件处理

在voucher.html页面中添加删除事件,代码如下:

在vue的methods对象中添加删除方法,代码如下:

doDeleteById(id){
    let url=`voucher/doDeleteById/${id}`;
    axios.delete(url).then(function(result){
        alert(result.data.message);
        this.vm.doFindPageObjects();
    })
}

启动tomcat服务器进行访问测试分析

启动tomcat,然后在打开浏览器,在地址栏输入访问地址,获取服务端数据并进行呈现,接下来点击页面上的删除按钮进行测试。

购物券添加业务设计实现

业务描述

在购物券页面中设计添加表单,然后点击表单中的Save 按钮时将表单数据异步提交到服务端进行保存,如图所示:

image.png

业务时序设计及分析

在购物券页面,输入购物券信息,然后提交到服务端进行保存,其时序分析如图所示:

DAO接口方法设计及实现

在VoucherDao中添加用于保存商品信息的接口方法,代码如下:

int insertObject(Voucher entity);

在VoucherMapper文件中添加insertObject方法对应的SQL映射,代码如下:




    
        insert into tb_voucher
        (deno,requirement,startTime,endTime,maxNum,remark,createdTime)
        values
        (#{deno},#{requirement},#{startTime},#{endTime},#{maxNum},#{remark},now())
    

Service接口方法设计及实现

在VoucherService接口中添加业务方法,用于实现购物券信息添加,代码如下:

int saveObject(Voucher entity);

在VoucherSerivceImpl类中添加接口方法实现,代码如下:

@Override
public int saveObject(Voucher entity) {
    return voucherDao.insertObject(entity);
} 

Controller类中方法设计及实现

在VoucherController类中添加用于处理添加请求的方法,代码如下:

@PostMapping("/voucher/doSaveObject")
public ResponseResult doSaveObject(@RequestBody Voucher entity){
    System.out.println(entity);
    voucherService.saveObject(entity);
    return new ResponseResult("save ok");
}

购物券页面表单元素设计及事件处理

在voucher.html页面代码中设计添加表单,代码如下:

在Vue对象的Data区添加属性数据,代码如下:

deno:"",
requirement:"",
startTime:"",
endTime:"",
maxNum:"",
remark:"",

在Vue对象中的Methods区,添加保存按钮事件处理函数,代码如下:
doSaveOrUpdate(){

 let url="voucher/doSaveObject";
    let params={"id":this.id,"deno":this.deno,"requirement":this.requirement,"startTime":this.startTime,"endTime":this.endTime,"maxNum":this.maxNum,"remark":this.remark};
    console.log(params);
    axios.post(url,params).then(function(result){
        alert(result.data.message);
        this.vm.doFindPageObjects();
        this.vm.id="";
        this.vm.deno="";
        this.vm.requirement="";
        this.vm.startTime="";
        this.vm.endTime="";
        this.vm.maxNum="";
        this.vm.remark="";
    })
}

购物券修改业务设计实现

业务描述

在购物券页面中设计修改按钮,并在点击修改按钮时候基于id查询购物券信息,然后呈现在表单中,如图所示:

image.png

业务时序设计及分析

基于用户更新设计其执行时序。

Dao接口方法设计及实现

在VoucherDao中添加基于id查询和更新的方法,代码如下:

@Select("select * from tb_voucher where id=#{id}")
Voucher findById(Integer id);
int updateObject(Voucher entity);

将updateObject方法的SQL映射添加到映射文件(建议SQL内容比较多的写到映射文件),代码如下:


    update tb_voucher
    set
     deno=#{deno},
     requirement=#{requirement},
     startTime=#{startTime},
     endTime=#{endTime},
     maxNum=#{maxNum},
     remark=#{remark}
    where id=#{id}

Service接口方法设计及实现

在VoucherService中添加基于id查询和更新的方法,代码如下:

Voucher findById(Integer id);
int updateObject(Voucher entity);

在VoucherServiceImpl类中添加基于id查询和更新的方法,代码如下:

@Override
public Voucher findById(Integer id) {
    return voucherDao.findById(id);
}
@Override
public int updateObject(Voucher entity) {
    return voucherDao.updateObject(entity);
}

Controller类中方法设计及实现

在VoucherController类中添加处理基于id的查询请求方法和更新购物券信息的方法,代码如下:

@GetMapping("/voucher/doFindById/{id}")
public ResponseResult doFindById(@PathVariable Integer id){
    Voucher voucher=voucherService.findById(id);
    return new ResponseResult(voucher);
}
@PostMapping("/voucher/doUpdateObject")
public ResponseResult doUpdateObject(@RequestBody Voucher entity){
    voucherService.updateObject(entity);
    return new ResponseResult("update ok");
}

Voucher页面中更新设计设计及实现

在voucher页面设计中,在vue对象中的methods区添加基于id的查询请求方法,代码如下:

doFindById(id){
    let url=`voucher/doFindById/${id}`;
    axios.get(url).then(function(result){
        console.log(result.data);
        this.vm.id=result.data.data.id;
        this.vm.deno=result.data.data.deno;
        this.vm.requirement=result.data.data.requirement;
        this.vm.startTime=result.data.data.startTime;
        this.vm.endTime=result.data.data.endTime;
        this.vm.maxNum=result.data.data.maxNum;
        this.vm.remark=result.data.data.remark;
    })
}

在voucher页面设计中,在vue对象中的methods区修改doSaveOrUpdate方法,代码如下:

doSaveOrUpdate(){
    let url=this.id?"voucher/doUpdateObject":"voucher/doSaveObject";
    let params={"id":this.id,"deno":this.deno,"requirement":this.requirement,"startTime":this.startTime,"endTime":this.endTime,"maxNum":this.maxNum,"remark":this.remark};
    console.log(params);
    axios.post(url,params).then(function(result){
        alert(result.data.message);
        this.vm.doFindPageObjects();
        this.vm.id="";
        this.vm.deno="";
        this.vm.requirement="";
        this.vm.startTime="";
        this.vm.endTime="";
        this.vm.maxNum="";
        this.vm.remark="";
    })
} 

启动服务器进行访问测试分析

你可能感兴趣的:(java)