07-SpringBoot+MyBatis+Spring 技術整合實現商品品牌模塊的CRUD操做

業務描述

需求描述

任何一個電商系統中都有一個商品子系統,而與商品相關聯都會有一個品牌信息管理,在當前業務系統設計中咱們就是要對商品品牌信息的管理進行設計和實現.javascript

業務架構分析

在品牌(Brand)信息管理中就是要實現對商品品牌信息的添加,修改,查詢,刪除等業務,如圖所示:
image.pngcss

業務基本原型設計

基於品牌業務描述,對品牌模塊的業務原型進行分析和設計,如圖所示:html

  • 品牌列表頁面

image.png

  • 品牌編輯頁面

image.png

項目技術架構分析及設計

在品牌管理模塊實現過程,咱們採用典型的C/S架構進行實現.客戶端咱們基於瀏覽器進行實現,服務端採用tomcat,數據庫使用MySQL.具體應用層基於MVC分層架構進行實現.java

項目技術棧應用分析及選型

  • 客戶端技術:html,css,javascript,bootstrap
  • 服務端技術:hikaricp,mybatis,spring,springboot,thymeleaf
  • 數據庫技術:mysql,sql
  • 開發工具集:jdk1.8,maven3.6.3,idea2020.2

項目品牌模塊核心API分析與設計

基於分層架構設計思想,現對品牌API進行設計,如圖所示:mysql

image.png

數據庫及表的分析與設計

設計並建立數據庫

假如數據庫已存在,則先刪除數據庫,代碼以下:web

drop database if exists dbbrand;

建立新的數據庫,代碼以下:spring

create database dbbrand default character set utf8;

設計並建立品牌(Brand)表

打開數據庫,語句以下:sql

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中,而後按以下步驟執行:bootstrap

打開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,如圖所示:

image.png

添加項目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 server

server.port=80

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

# spring mybatis

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

# spring log

logging.level.com.cy=debug

#spring thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

啓動項目進行初步環境測試分析

  • 端口號被佔用

image.png

  • 數據庫鏈接錯誤

image.png

品牌數據的查詢及呈現

業務描述

將數據庫中的品牌信息查詢出來,而後在客戶端基於html技術進行呈現,如圖所示:
image.png

服務端品牌查詢時序設計

基於查詢請求,進行訪問時序設計,如圖所示:
image.png

領域對象(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;
@Mapper
public 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;
@SpringBootTests
public 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,如圖所示:

image.png

  • ExecutorException,如圖所示:

image.png

業務邏輯對象(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;

@Service
public 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;
@SpringBootTest
public class BrandServiceTests{
    @Autowired
    private BrandService brandService;
    @Test
    void testFindBrands(){
        List<Brand> list=brandService.findBrands();
        for(Brand b:list){
            System.out.println(b);
        }
    }
}

第四步:測試過程當中的Bug分析

  • NoSuchBeanDefinition,如圖所示:

image.png

  • NullPointerException,如圖所示:

image.png

控制邏輯對象(Controller)查詢方法設計及實現

在控制邏輯對象中主要是負責請求和響應邏輯控制,例如請求url映射,參數映射,請求方式,結果集的封裝,解析,響應的設計等.

第一步:定義Controller類

package com.cy.pj.brand.controller;
@Controller
public class BrandController{
   @Autowired
   private BrandService brandService;
}

第二步:在Controller添加處理查詢請求的方法

@GetMapping(value={"/brand/doFindBrands/{name}","/brand/doFindBrands"})
public String doFindBrands(@PathVariable(required = false) String name, Model model){
    List<Brand> list=brandService.findBrands(name);
    model.addAttribute("list", list);
    return "brand/brand";//第一個brand爲目錄,第二brand爲view name
}

其中,
1)@GetMapping描述方法時,表示這個方法只能處理Get請求,註解內部的value屬性能夠指定多個url.
2)@PathVariable 用於描述方法參數,表示方法參數的值能夠來自url中{}內部的變量值,required=false表示參數能夠不傳值.

客戶端品牌列表頁面設計及實現

在項目的templates目錄下建立brand目錄並添加brand.html頁面,其關鍵代碼以下:

<table>
    <thead>
      <tr>
        <th>id</th>
        <th>name</th>
        <th>createdTime</th>
      </tr>
    </thead>
    <tbody>
      <tr th:each="brand: ${list}">
         <td th:text="${brand.id}">10</td>
         <td th:text="${brand.name}">AAA</td>
         <td th:text="${#dates.format(brand.createdTime, 'yyyy/MM/dd  
         HH:mm')}">2020/10/11</td>
       </tr>
 </tbody>
</table>

其中:
1)${}爲thymeleaf爲中的EL表達式,用於從服務端model中獲取數據
2)th:each爲thymeleaf定義的自定義標籤屬性,用於迭代數據.
3)th:text爲thymeleaf定義的自定義標籤屬性,用於設置文本內容.

啓動服務進行訪問測試並對結果進行分析

啓動服務,打開瀏覽器輸入指定url,進行訪問,其數據呈現過程,如圖所示:
image.png

啓動及運行過程當中的Bug分析及解決方案

  • 頁面元素解析異常,如圖所示:

image.png

  • 模板頁面找不到,如圖所示:

image.png

品牌模塊刪除業務分析及實現

業務描述

在品牌列表頁面中,點擊當前行記錄後面的刪除按鈕,基於當前行的記錄id執行品牌刪除操做,刪除成功之後,從新刷新頁面.如圖所示:

image.png

業務時序分析與設計

客戶端向服務端發起刪除請求,服務器端的處理時序以下:

image.png

數據邏輯對象(DAO)中刪除方法設計及實現

基於業務,在BrandDao接口中添加刪除方法,代碼以下:

int deleteById(Integer id);

基於刪除方法,定義SQL映射(本次直接以註解方式進行定義),代碼以下:

@Delete("delete from tb_brand where id=#{id}")
int deleteById(Integer id);

在BrandDaoTests單元測試類中添加單元測試方法,對刪除操做進行測試,關鍵代碼以下

@Test
void testDeleteById(){
    int rows=brandDao.deleteById(10);
    System.out.println("rows="+rows);
}

業務邏輯對象(Service)中刪除方法設計及實現

在業務邏輯對象方法中,要處理刪除操做須要的一些業務邏輯(後續有參數校驗,權限控制,....).

第一步:在BrandService接口中添加,品牌刪除的業務方法,代碼以下:

int deleteById(Integer id);

第二步:在BrandServiceImpl類中添加刪除業務的具體實現,代碼以下:

public int deleteById(Integer id){
     //1.參數校驗
     //2.執行刪除業務
     int rows=brandDao.deleteById(id);
     //3.校驗結果並返回
     return rows;
}

第三步:在BrandServiceTests類中添加單元測試方法,對其刪除業務作測試?

@Test
void testDeleteById(){
     int rows=brandService.deleteById(10);
     System.out.println("row="+row);
}

第四步:測試過程當中的Bug分析?

控制邏輯對象(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按鈕就數據提交到服務端進行保存.

image.png

image.png

添加時序分析及設計

image.png

數據邏輯對象(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=brandDao.insertBrand(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";
}

啓動服務進行訪問測試分析

image.png

image.png

啓動及運行過程當中的BUG分析

  • 客戶端提交到服務端的數據拿不到?

image.png

品牌模塊修改業務分析及實現

業務描述

在品牌列表頁面,點擊當前行的修改按鈕,先基於id查詢當前行記錄,並將記錄呈如今編輯頁面,如圖所示:

image.png

image.png

業務時序分析與設計

基於id查詢品牌信息並呈如今頁面上,其時序分析如圖所示:

image.png

在品牌編輯頁面,編輯數據,點擊save按鈕保存更新,其時序如圖所示:
image.png

數據邏輯對象(Dao)中方法設計與實現

在BrandDao中添加基於id查詢品牌信息的方法及SQL映射,代碼以下:

@Select("select * from tb_brand where id=#{id}")
Brand findById(Integer id);

在BrandDao中添加基於id執行品牌更新的方法及SQL映射,代碼以下:

@Update("update tb_brand set name=#{name},remark=#{remark} where id=#{id}")
 int updateBrand(Brand Brand);

業務邏輯對象(Service)中方法設計與實現

在BrandService 中添加基於id查詢品牌信息和更新品牌信息的方法,代碼以下:

Brand findById(Integer id);
int updateBrand(Brand brand);

在BrandServiceImpl中基於id查詢品牌信息和更新品牌信息的方法,代碼以下:

@Override
    public Brand findById(Integer id) {
        //.....
        return brandDao.findById(id);
    }
@Override
    public int updateBrand(Brand brand) {
        return brandDao.updateBrand(brand);
    }

控制邏輯對象(Controller)中方法設計與實現

在BrandController中添加基於id查詢品牌信息的方法,代碼以下:

@RequestMapping("/brand/doFindById/{id}")
    public String doFindById(@PathVariable Integer id,Model model) {
        Brand brand=brandService.findById(id);
        model.addAttribute("brand",brand);
        return "/brand/brand-update";
    }

在BrandController中添加更新品牌信息的方法,代碼以下:

@RequestMapping("/brand/doUpdateBrand")
    public String doUpdateBrand(Brand brand,Model model) {
        brandService.updateBrand(brand);
        List<Brand> list=brandService.findBrands(null);
       model.addAttribute("list",list);
     return "brand/brand";
    }

客戶端品牌編輯頁面設計與實現

第一步:設計品牌修改頁面brand-update.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 Update Page</h1>
       <input type="hidden" name="id" th:value="${brand.id}">
       <form th:action="@{/brand/doUpdateBrand}" method="post">
           <div class="form-group">
               <label for="nameId">Name</label>
               <input type="text" class="form-control" name="name" id="nameId" th:value="${brand.name}" placeholder="Brand Name">
           </div>
           <div class="form-group">
               <label for="remarkId">Remark</label>
               <textarea class="form-control" rows="5" cols="100" name="remark" th:text="${brand.remark}" id="remarkId">
               </textarea>
           </div>
           <button type="submit" class="btn btn-default">Submit</button>
       </form>
   </div>
</body>
</html>

啓動Tomcat服務進行訪問測試分析

啓動服務,先進入品牌列表頁面,而後點擊修改按鈕如圖所示:
image.png
此時,進入品牌編輯頁面,如圖所示:
image.png
在品牌編輯頁面,編輯數據之後,點擊save按鈕,執行更新操做。

啓動及運行過程當中的BUG分析

  • 405 異常

image.png

  • 呈現的數據不正確

image.png

  • 頁面元素解析異常

image.png

總結(Summary)

本章節,主要基於學過的springboot,Hikaricp,MyBatis,Spring,Thymeleaf等技術,對商品品牌模塊作了具體實現。重點掌握其基本設計及實現過程。

相關文章
相關標籤/搜索