业务形容

需要形容

任何一个电商零碎中都有一个商品子系统,而与商品相关联都会有一个品牌信息管理,在以后业务零碎设计中咱们就是要对商品品牌信息的治理进行设计和实现.

业务架构剖析

在品牌(Brand)信息管理中就是要实现对商品品牌信息的增加,批改,查问,删除等业务,如图所示:

业务根本原型设计

基于品牌业务形容,对品牌模块的业务原型进行剖析和设计,如图所示:

我的项目技术架构剖析及设计

在品牌治理模块实现过程,咱们采纳典型的C/S架构进行实现.客户端咱们基于浏览器进行实现,服务端采纳tomcat,数据库应用MySQL.具体应用层基于MVC分层架构进行实现.

我的项目技术栈利用剖析及选型

  • 客户端技术:html,css,javascript,bootstrap
  • 服务端技术:hikaricp,mybatis,spring,springboot,thymeleaf
  • 数据库技术:mysql,sql
  • 开发工具集:jdk1.8,maven3.6.3,idea2020.2

我的项目品牌模块外围API剖析与设计

基于分层架构设计思维,现对品牌API进行设计,如图所示:

数据库及表的剖析与设计

设计并创立数据库

如果数据库已存在,则先删除数据库,代码如下:

drop database if exists dbbrand;

创立新的数据库,代码如下:

create database dbbrand default character set utf8;

设计并创立品牌(Brand)表

关上数据库,语句如下:

use dbbrand;

在dbbrand数据库中创立品牌表.

create table tb_brand(     id bigint primary key auto_increment,     name varchar(100) not null,     remark text,     createdTime datetime not null)engine=InnoDB;

基于SQL脚本执行数据库初始化

将数据库设计脚本写到brand.sql中,而后按如下步骤执行:

关上mysql自带客户端,登录mysql,指令如下:

mysql -uroot -proot

设置客户端编码,指令如下:

set names utf8;

执行sql脚本,指令如下:

source d:/brand.sql

脚本执行胜利当前,在客户端查问数据之前,先执行如下语句:

set names gbk;

我的项目环境初始化

筹备操作

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

创立我的项目Module

关上idea,而后基于设计,创立我的项目module,如图所示:

增加我的项目Module依赖

  • MySQL 驱动
<dependency>   <groupId>mysql</groupId>   <artifactId>mysql-connector-java</artifactId>   <scope>runtime</scope></dependency>
  • Srping Jdbc 提供了HikariCP连接池
<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-jdbc</artifactId></dependency>
  • MyBatis 资源
<dependency>   <groupId>org.mybatis.spring.boot</groupId>   <artifactId>mybatis-spring-boot-starter</artifactId>   <version>2.1.3</version></dependency>
  • Spring Web 依赖 (内置一个tomcat服务)
<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-web</artifactId></dependency>
  • Thymeleaf 依赖 (html模板引擎)
<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

我的项目Module根底配置

关上我的项目Module配置文件application.properties,并增加如下内容:

#spring serverserver.port=80# spring datasourcespring.datasource.url=jdbc:mysql:///dbbrand?serverTimezone=GMT%2B8&characterEncoding=utf8spring.datasource.username=rootspring.datasource.password=root# spring mybatismybatis.mapper-locations=classpath:/mapper/*/*.xml# spring loglogging.level.com.cy=debug#spring thymeleafspring.thymeleaf.cache=falsespring.thymeleaf.prefix=classpath:/templates/spring.thymeleaf.suffix=.html

启动我的项目进行初步环境测试剖析

  • 端口号被占用

  • 数据库连贯谬误

品牌数据的查问及出现

业务形容

将数据库中的品牌信息查问进去,而后在客户端基于html技术进行出现,如图所示:

服务端品牌查问时序设计

基于查问申请,进行拜访时序设计,如图所示:

畛域对象(POJO)设计及实现

设置Brand对象,基于此对象封装从数据库查问到的品牌信息,代码如下:

package com.cy.pj.brand.pojo;import java.util.Date;public class Brand {    private Integer id;    private String name;    private String remark;    private Date createdTime;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    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 "Brand{" +                "id=" + id +                ", name='" + name + ''' +                ", remark='" + remark + ''' +                ", createdTime=" + createdTime +                '}';    }}

数据逻辑对象(DAO)查询方法设计及实现

设计用于拜访Brand数据的数据拜访对象及办法,其关键步骤如下:

第一步:定义BrandDao接口,代码如下:

package com.cy.pj.brand.dao;@Mapperpublic interface BrandDao{}

第二步:在BrandDao中定义品牌查询方法,代码如下:

List<Brand> findBrands(String name);

第三步:基于查询方法定义SQL映射.
在resources目录中创立mapper/brand目录,并在目录中增加BrandMapper.xml文件,要害代码如下:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cy.pj.brand.dao.BrandDao">    <select id="findBrands" resultType="com.cy.pj.brand.pojo.Brand">        select id,name,remark,createdTime        from tb_brand        <if test="name!=null and name!=''">            where name like concat("%",#{name},"%")        </if>    </select></mapper>

其中:concat为mysql中提供的字符串连贯函数.

第四步:对数据层的查询方法进行单元测试,代码如下:

package com.cy.pj.brand.dao;@SpringBootTestspublic class BrandDaoTests{     @Autowired     private BrandDao brandDao;     @Test     void testFindBrands(){        List<Brand> list=brandDao.findBrands("TCL");        for(Brand b:list){           System.out.println(b);        }     }} 

第五步:测试过程中的BUG剖析?

  • BindingException,如图所示:

  • ExecutorException,如图所示:

业务逻辑对象(Service)查询方法设计及实现

业务逻辑对象负责模块的具体业务解决,例如参数校验,事务管制,权限管制,日志记录等.

第一步:定义业务接口

package com.cy.pj.brand.service;public interface BrandService{} 

第二步:在BrandService接口中增加品牌查询方法

List<Brand> findBrands(String name);

第三步:定义BrandService接口实现类BrandServiceImpl.

package com.cy.pj.brand.service.impl;@Servicepublic class BrandServiceImpl implements BrandService{     private static final Logger log=     LoggerFactory.getLogger(BrandServiceImpl.class);          @Autowired     private BrandDao brandDao;     public List<Brand> findBrands(String name){            long t1=System.currentTimeMillis();            List<Brand> list=brandDao.findBrands(name);            long t2=System.currentTimeMillis();            log.info("findBrands->time->{}",(t2-t1));            return list;     }} 

第三步:定义BrandService接口办法的单元测试类,并业务进行测试剖析

package com.cy.pj.brand.service;@SpringBootTestpublic class BrandServiceTests{    @Autowired    private BrandService brandService;    @Test    void testFindBrands(){        List<Brand> list=brandService.findBrands();        for(Brand b:list){            System.out.println(b);        }    }}

第四步:测试过程中的Bug剖析?

  • NoSuchBeanDefinition,如图所示:

  • NullPointerException,如图所示:

管制逻辑对象(Controller)中删除办法设计及实现

在管制层对象中定义解决删除申请的办法,具体代码如下:

@GetMapping("/brand/doDeleteById/{id}")public String doDeleteById(@PathVariable Integer id,Model model){      brandService.deleteById(id);      List<Brand> list=brandService.findBrands();      model.addAttribute("list",list);      return "brand/brand";} 

客户端删除按钮事件定义及解决

在tbody的tr中增加一列,代码如下:

<td> <button type="button" th:onclick="doDeleteById([[${brand.id}]])">delete</button></td>

定义javascript函数,解决删除事件,代码如下:

function doDeleteById(id){    //给出提示信息 if(!confirm("您确认删除吗"))return;//confirm为浏览器中window对象的函数 //执行删除业务 location.href=`http://localhost/brand/doDeleteById/${id}ss`;}

品牌模块增加业务剖析及实现

业务形容

在列表页面上,设计增加按钮,当点击增加按钮时,跳转到增加页面,而后在增加页面上数据品牌信息,点击Save按钮就数据提交到服务端进行保留.

增加时序剖析及设计

数据逻辑对象(Dao)中办法设计及实现

第一步:在BrandDao中增加用于保留品牌信息的办法,代码如下:

int insertBrand(Brand brand);

第二步:在BrandMapper中增加品牌保留操作对应的sql映射,代码如下:

<insert id="insertBrand">     insert into tb_brand      (name,remark,createdTime)     values     (#{name},#{remark},now())</insert>

业务逻辑对象(Service)中办法设计及实现

第一步:在BrandService业务接口中中定义用于保留品牌信息的办法,代码如下:

int saveBrand(Brand brand);

第二步:在BrandServiceImpl业务实现类中增加保留品牌信息的具体实现,代码如下:

public int saveBrand(Brand brand){    int rows=brandService.saveBrand(brand);    return rows;}

管制逻辑对象(Controller)中办法设计及实现

第一步:在BrandController中增加用于解决申请增加页面的办法,代码如下:

@GetMapping("/brand/doAddUI")public String doAddUI(){    return "brand/brand-add";}

第二步:在BrandController增加用于解决增加品牌信息页面的办法,代码如下:

@PostMapping("/brand/doSaveBrand")public String doSaveBrand(Brand brand,Model model){    System.out.println("save.brand="+brand);    brandService.saveBrand(brand);    List<Brand> list=brandService.findBrands(null);    model.addAttribute("list",list);    return "brand/brand";}

客户端操作设计及实现

第一步:设计品牌增加页面brand-add.html,代码如下

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title>    <link rel="stylesheet" href="/bootstrap/css/bootstrap.css"></head><body>   <div class="container">       <h1>The Brand Add Page</h1>       <form th:action="@{/brand/doSaveBrand}" method="post">           <div class="form-group">               <label for="nameId">Name</label>               <input type="text" class="form-control" name="name" id="nameId" placeholder="Brand Name">           </div>           <div class="form-group">               <label for="remarkId">Remark</label>               <textarea class="form-control" rows="5" cols="100" name="remark" id="remarkId">               </textarea>           </div>           <button type="submit" class="btn btn-default">Submit</button>       </form>   </div></body></html>

第二步:在品牌列表brand.html页面,设计增加按钮,代码如下:

<button type="button" onclick="doAddUI()" class="btn btn-primary btn-sm">Add Brand</button>

第三步:点击增加按钮时,加载品牌增加页面,事件处理函数如下:

function doAddUI(){    location.href="/brand/doAddUI";}

第四步:在品牌增加页面输出品牌信息,间接将数据提交到服务端执行保留操作

启动服务进行拜访测试剖析

品牌模块批改业务剖析及实现

总结(Summary)