任何一個電商系統中都有一個商品子系統,而與商品相關聯都會有一個品牌信息管理,在當前業務系統設計中咱們就是要對商品品牌信息的管理進行設計和實現.javascript
在品牌(Brand)信息管理中就是要實現對商品品牌信息的添加,修改,查詢,刪除等業務,如圖所示:css
基於品牌業務描述,對品牌模塊的業務原型進行分析和設計,如圖所示:html
在品牌管理模塊實現過程,咱們採用典型的C/S架構進行實現.客戶端咱們基於瀏覽器進行實現,服務端採用tomcat,數據庫使用MySQL.具體應用層基於MVC分層架構進行實現.java
基於分層架構設計思想,現對品牌API進行設計,如圖所示:mysql
假如數據庫已存在,則先刪除數據庫,代碼以下:web
drop database if exists dbbrand;
建立新的數據庫,代碼以下:spring
create database dbbrand default character set utf8;
打開數據庫,語句以下: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;
將數據庫設計腳本寫到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+
打開idea,而後基於設計,建立項目module,如圖所示:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
打開項目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
將數據庫中的品牌信息查詢出來,而後在客戶端基於html技術進行呈現,如圖所示:
基於查詢請求,進行訪問時序設計,如圖所示:
設置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 + '}'; } }
設計用於訪問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分析?
業務邏輯對象負責模塊的具體業務處理,例如參數校驗,事務控制,權限控制,日誌記錄等.
第一步:定義業務接口
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分析
在控制邏輯對象中主要是負責請求和響應邏輯控制,例如請求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,進行訪問,其數據呈現過程,如圖所示:
在品牌列表頁面中,點擊當前行記錄後面的刪除按鈕,基於當前行的記錄id執行品牌刪除操做,刪除成功之後,從新刷新頁面.如圖所示:
客戶端向服務端發起刪除請求,服務器端的處理時序以下:
基於業務,在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); }
在業務邏輯對象方法中,要處理刪除操做須要的一些業務邏輯(後續有參數校驗,權限控制,....).
第一步:在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分析?
在控制層對象中定義處理刪除請求的方法,具體代碼以下:
@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按鈕就數據提交到服務端進行保存.
第一步:在BrandDao中添加用於保存品牌信息的方法,代碼以下:
int insertBrand(Brand brand);
第二步:在BrandMapper中添加品牌保存操做對應的sql映射,代碼以下:
<insert id="insertBrand"> insert into tb_brand (name,remark,createdTime) values (#{name},#{remark},now()) </insert>
第一步:在BrandService業務接口中中定義用於保存品牌信息的方法,代碼以下:
int saveBrand(Brand brand);
第二步:在BrandServiceImpl業務實現類中添加保存品牌信息的具體實現,代碼以下:
public int saveBrand(Brand brand){ int rows=brandDao.insertBrand(brand); return rows; }
第一步:在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"; }
在品牌列表頁面,點擊當前行的修改按鈕,先基於id查詢當前行記錄,並將記錄呈如今編輯頁面,如圖所示:
基於id查詢品牌信息並呈如今頁面上,其時序分析如圖所示:
在品牌編輯頁面,編輯數據,點擊save按鈕保存更新,其時序如圖所示:
在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);
在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); }
在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>
啓動服務,先進入品牌列表頁面,而後點擊修改按鈕如圖所示:
此時,進入品牌編輯頁面,如圖所示:
在品牌編輯頁面,編輯數據之後,點擊save按鈕,執行更新操做。
本章節,主要基於學過的springboot,Hikaricp,MyBatis,Spring,Thymeleaf等技術,對商品品牌模塊作了具體實現。重點掌握其基本設計及實現過程。