SpringBoot第十一篇:SpringBoot+MyBatis+Thymelaf實現CRUD
作者:追夢1819
原文:https://www.cnblogs.com/yanfei1819/p/10936304.html
版權宣告:本文為博主原創文章,轉載請附上博文連結!
引言
總結前面幾章,我們瞭解了 SpringBoot 的基本用法及其配置,整合各大 ORM 框架,並瞭解了 Thymelaf 的基本用法。
本章將綜合前面的知識,做一個完整Java web 的增刪改查的示例。一來是對知識的整合,二來是考慮到很多讀者是新手,一個完整的示例可能更加有助於其對 SpringBoot 的理解和掌握。
前面的ORM 框架有多種,本章中選取的是 MyBatis(沒有使用 MyBatis 相關外掛) ,作者比較喜歡該框架,同時在行業中的應用也很廣泛。
版本資訊
- JDK:1.8
- SpringBoot :2.1.4.RELEASE
- maven:3.3.9
- MyBatis:2.0.1
- Thymelaf:2.1.4.RELEASE
- IDEA:2019.1.1
準備工作
初始化資料庫
本示例中,建立手機表,欄位包括:名稱、價格、顏色和生產日期。
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE `mobile_phone` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名稱', `price` decimal(7, 2) NOT NULL COMMENT '價格', `color` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '顏色', `production_date` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL COMMENT '生產日期', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; INSERT INTO `mobile_phone` VALUES (1, '蘋果', 6988.00, '銀色', '2018-12-12'); INSERT INTO `mobile_phone` VALUES (2, '華為', 3988.00, '白色', '2019-12-09'); SET FOREIGN_KEY_CHECKS = 1;
建立專案
以下是作者用 idea 建立的示例專案:
專案結構是作者的個人習慣,基本也符合 Java Web 的分層結構。下面也再次說明一下專案結構的含義:
com.yanfei1819.springbootmybatisthymeleafdemo.db.dao
專案的持久化層,與資料庫互動;
com.yanfei1819.springbootmybatisthymeleafdemo.db.dto
與資料庫互動的實體類;
com.yanfei1819.springbootmybatisthymeleafdemo.entity.response
介面返回的引數實體類;
com.yanfei1819.springbootmybatisthymeleafdemo.entity.vo
與頁面互動的實體類;
com.yanfei1819.springbootmybatisthymeleafdemo.service
專案業務層的介面和實現類;
com.yanfei1819.springbootmybatisthymeleafdemo.web.controller
專案的 controller 層,外部直接訪問;
com.yanfei1819.springbootmybatisthymeleafdemo.SpringbootMybatisThymeleafDemoApplication
專案入口啟動類;
\src\main\resources\static
存放專案靜態資原始檔;
\src\main\resources\templates
SpringBoot 預設的模板引擎存放位置(可自定義)。
程式碼說明
1、 程式碼是按照作者的以往的編寫習慣寫的,並非標準,僅供大家參考;
2、 示例中的程式碼,都是嚴格按照分層的,包括資料接收的實體類;
3、 有讀者有疑問,專案中為什麼會有兩個屬性完全一致的實體類,xxxDTO 和 xxxVO ?其實這是為了增加專案的擴充套件性和健壯性而設的,xxxDTO 與資料庫互動,xxxVO 與頁面互動,嚴格分層了。其實實體類的種類根據專案規模大小而定,專案越大,可能定義的實體類的種類越多。名稱可以參照《阿里巴巴Java開發手冊》:
4、 示例程式碼,作者雖然儘量遵守了程式碼規範,但是由於篇幅所限,還是簡化了邏輯,只演示了基本的功能。時間專案中的業務邏輯可能比這個複雜很多,比如,實際專案中可能有分頁查詢、條件查詢、排序等。所以讀者要注意;
5、 在本文中,通用由於篇幅的原因,只列出示例中的核心程式碼,如果讀者想獲取完整的程式碼,可以移步到 本人的GitHub 進行下載;
6、 示例中只做了功能的演示,沒有 CSS 樣式,讀者可自行新增。
綜合使用
一、引入 maven 依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
二、配置相關的資訊:
### 資料庫資訊
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
### 模板引擎
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
### 駝峰命名法轉換
mybatis.configuration.map-underscore-to-camel-case=true
其餘的資訊,可自行配置。
三、建立 db 層:
實體類:
public class MobilePhoneDTO {
private Long id;
private String name;
private Double price;
private String color;
private String productionDate;
// get/set 省略
}
dao類:
public interface MobilePhoneDAO {
@Select("select * from mobile_phone ")
List<MobilePhoneDTO> listMobilePhones();
@Select("select * from mobile_phone where id = #{id}")
MobilePhoneDTO getMobilePhoneById(Long id);
@Update("insert into mobile_phone(`name`,price,color,production_date) values(#{name},#{price},#{color},#{productionDate}")
int insertMobilePhone(MobilePhoneDTO dto);
@Update("UPDATE mobile_phone set `name`=#{name},price=#{price},color=#{color},production_date=#{productionDate} WHERE id=#{id}")
int updateMobilePhone(MobilePhoneDTO dto);
@Delete("DELETE FROM mobile_phone WHERE id = #{id}")
int deleteMobilePhoneById(Long id);
}
四、建立 service 層:
介面:
public interface MobilePhoneService {
List<MobilePhoneVO> listMobilePhones();
MobilePhoneVO getMobilePhoneById(Long id);
BaseResponse updateMobilePhone(MobilePhoneVO vo);
BaseResponse insertMobilePhone(MobilePhoneVO vo);
BaseResponse deleteMobilePhoneById(Long id);
}
實現類:
@Service
public class MobilePhoneServiceImpl implements MobilePhoneService {
@Autowired
private MobilePhoneDAO mobilePhoneDAO;
@Override
public List<MobilePhoneVO> listMobilePhones() {
List<MobilePhoneDTO> dtos = mobilePhoneDAO.listMobilePhones();
List<MobilePhoneVO> vos = new ArrayList<>();
for (MobilePhoneDTO dto : dtos) {
MobilePhoneVO vo = new MobilePhoneVO();
BeanUtils.copyProperties(dto,vo);
vos.add(vo);
}
return vos;
}
@Override
public MobilePhoneVO getMobilePhoneById(Long id) {
MobilePhoneDTO dto = mobilePhoneDAO.getMobilePhoneById(id);
MobilePhoneVO vo = new MobilePhoneVO();
BeanUtils.copyProperties(dto,vo);
return vo;
}
@Override
public BaseResponse updateMobilePhone(MobilePhoneVO vo) {
MobilePhoneDTO dto = new MobilePhoneDTO();
BeanUtils.copyProperties(vo,dto);
int updateCount = mobilePhoneDAO.updateMobilePhone(dto);
if(updateCount<1){
return new BaseResponse("資料更新失敗");
}
return new BaseResponse();
}
@Override
public BaseResponse insertMobilePhone(MobilePhoneVO vo) {
MobilePhoneDTO dto = new MobilePhoneDTO();
BeanUtils.copyProperties(vo,dto);
int insertCount = mobilePhoneDAO.insertMobilePhone(dto);
if(insertCount<1){
return new BaseResponse("資料插入失敗");
}
return new BaseResponse();
}
@Override
public BaseResponse deleteMobilePhoneById(Long id) {
int deleteCount = mobilePhoneDAO.deleteMobilePhoneById(id);
if(deleteCount<1){
return new BaseResponse("資料刪除失敗");
}
return new BaseResponse();
}
}
以上的實現中,包含了增刪改查等功能。
此處為了更加友好的返回數值,增加了 BaseResponse 類,該類是:
public class BaseResponse<T> {
private Integer code;
private String msg;
private T data;
// set/get 省略
public static BaseResponse defaultNo(String msg) {
return new BaseResponse(1,msg);
}
public static BaseResponse defaultOk() {
return new BaseResponse();
}
public BaseResponse() {
this.code = 0;
this.msg = "success";
}
public BaseResponse(String msg) {
this.code = 1;
this.msg = msg;
}
public BaseResponse(T data) {
this.data = data;
this.code = 0;
this.msg = "success";
}
public BaseResponse(Integer code, String msg){
this.code = code;
this.msg = msg;
}
}
細心的讀者可能會發現以上的一個細節,有的方法返回了 BaseResponse,但是有的方法直接返回了頁面的實體類 MobilePhoneVO。
此處為了做演示,特意做了兩種返回引數處理情況。通常情況下,我們在開發前後端分離專案的時候,都會將返回的數值封裝為 json 格式,以便後端可以與 PC 端和 APP 端同時進行互動。如果非前後端分離,那基本就不做要求了。
不過,作者給大家的建議是,能統一格式時儘量統一,程式碼看起來也更加優雅一些。
五、建立 controller 層:
@Controller
@RequestMapping("/mobile/phone")
public class MobilePhoneController {
@Autowired
private MobilePhoneService service;
@GetMapping("/listMobilePhones")
public String listMobilePhones(Model model){
List<MobilePhoneVO> vos = service.listMobilePhones();
model.addAttribute("response",vos);
return "mobilephoneList";
}
@GetMapping("/get/{id}")
@ResponseBody
public BaseResponse getMobilePhoneById(@PathVariable Long id){
MobilePhoneVO vo = service.getMobilePhoneById(id);
return new BaseResponse(vo);
}
@PostMapping("/insertMobilePhone")
@ResponseBody
public BaseResponse insertMobilePhone(@RequestBody MobilePhoneVO vo){
return service.insertMobilePhone(vo);
}
// 進入編輯頁面
@GetMapping("/toEditMobilePhone")
public String toAddMobilePhone(Model model,Long id){
MobilePhoneVO vo = service.getMobilePhoneById(id);
model.addAttribute("vo",vo);
return "toEditMobilePhone";
}
@PostMapping("/updateMobilePhone")
@ResponseBody
public String updateMobilePhone(@RequestBody MobilePhoneVO vo){
service.updateMobilePhone(vo);
return "redirect:mobilephoneList"; // 跳轉至列表頁
}
@GetMapping("/delete/{id}")
@ResponseBody
public BaseResponse deleteMobilePhoneById(@PathVariable Long id){
return service.deleteMobilePhoneById(id);
}
}
controller 層包括增刪改查介面,同時提供頁面跳轉的介面(此處只做了編輯功能,其餘的都類似)。在做增刪改後,一般是跳轉至列表頁面。當然,你也可以加入其它的互動邏輯。
六、建立頁面:
列表頁 mobilephoneList:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>追夢1819的SpringBoot教程</title>
<style>
table, table tr th, table tr td {
border: 1px solid #0094ff;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<main role="main">
<div class="content_bottom_right" id="mobilephoneList">
<div class="input-group">
<table class="table text-nowrap imagetable">
<thead>
<tr>
<th>序號</th>
<th>名稱</th>
<th>價格</th>
<th>顏色</th>
<th>生產日期</th>
<th>操作</th>
</tr>
</thead>
<tbody th:each="mobilephone,item:${response}">
<tr>
<td>[[${item.count}]]</td>
<td>[[${mobilephone.name}]]</td>
<td>[[${mobilephone.price}]]</td>
<td>[[${mobilephone.color}]]</td>
<td>[[${mobilephone.productionDate}]]</td>
<td>
<a>詳情</a>
<a th:href="@{/mobile/phone/toEditMobilePhone(id=${mobilephone.id})}">編輯</a>
<a>刪除</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
</div>
</div>
</body>
</html>
新增頁:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>追夢1819的SpringBoot教程</title>
</head>
<body class="container">
<br/>
<h2>修改手機</h2>
<br/>
<div>
<form class="form-horizontal" th:action="@{/mobile/phone/updateMobilePhone}" th:object="${vo}" method="post">
<div>
<label>名稱</label>
<input name="name" id="name" th:value="*{name}">
</div>
<div>
<label>顏色</label>
<input name="color" id="color" th:value="*{color}">
</div>
<div>
<label>價格</label>
<input name="price" id="price" th:value="*{price}">
</div>
<div>
<label>價格</label>
<input name="productionDate" id="productionDate" th:value="*{productionDate}">
</div>
<input type="submit" value="新增"/>
</form>
</div>
</body>
</html>
以上頁面說明幾點:
- 使用 thymelaf 模板引擎,頁面必須新增
xmlns:th="http://www.thymeleaf.org"
; - 為了簡化程式碼,以上只做了編輯頁,其餘的詳情什麼的,都是相同的用法;
- thymelaf 可以與其他框架整合,比如 bootstrap、JQuery 等。
最後,可以看看效果:
最後,補充一些關於thymelaf常用的屬性值配置:
# THYMELEAF (ThymeleafAutoConfiguration)
#開啟模板快取(預設值:true)
spring.thymeleaf.cache=true
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true
#檢查模板位置是否正確(預設值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(預設值:text/html)
spring.thymeleaf.content-type=text/html
#開啟MVC Thymeleaf檢視解析(預設值:true)
spring.thymeleaf.enabled=true
#模板編碼
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的檢視名稱列表,用逗號分隔
spring.thymeleaf.excluded-view-names=
#要運用於模板之上的模板模式。另見StandardTemplate-ModeHandlers(預設值:HTML5)
spring.thymeleaf.mode=HTML5
#在構建URL時新增到檢視名稱前的字首(預設值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在構建URL時新增到檢視名稱後的字尾(預設值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器鏈中的順序。預設情況下,它排第一位。順序從1開始,只有在定義了額外的TemplateResolver Bean時才需要設定這個屬性。
spring.thymeleaf.template-resolver-order=
#可解析的檢視名稱列表,用逗號分隔
spring.thymeleaf.view-names=
總結
至此,基本完成了 SpringBoot + MyBatis + Thymelaf 的綜合演示。功能很簡單,用法也很簡單,只不過做了整體的綜合。本章中演示的 ORM 框架是 MyBatis,讀者可以自行將 SpringBoot + Thymelaf + 其他 ORM 框架整合,以加深理解。
相關推薦
SpringBoot第十一篇:SpringBoot+MyBatis+Thymelaf實現CRUD
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/10936304.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 總結前面幾章,我們瞭解了 SpringBoot 的基本用法及其配置,整合各大 ORM 框架,並瞭解了 Thymelaf
(轉)第十一篇:springboot集成swagger2,構建優雅的Restful API
html 風格 lan round amt select() hash 指定 model 聲明:本部分內容均轉自於方誌明博友的博客,因為本人很喜歡他的博客,所以一直在學習,轉載僅是記錄和分享,若也有喜歡的人的話,可以去他的博客首頁看:http://blog.csdn.n
轉載:SpringBoot非官方教程 | 第十一篇:springboot整合swagger2,構建優雅的Restful API
swagger,中文“拽”的意思。它是一個功能強大的api框架,它的整合非常簡單,不僅提供了線上文件的查閱,而且還提供了線上文件的測試。另外swagger很容易構建restful風格的api,簡單優雅帥氣,正如它的名字。 一、引入依賴 <depend
一起來學SpringBoot | 第十一篇:整合Swagger線上除錯
SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程 隨著網際網路技
一起來學SpringBoot | 第十四篇:強大的 actuator 服務監控與管理
SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程 actuato
一起來學SpringBoot | 第十五篇:actuator與spring-boot-admin 可以說的祕密
SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程 一起來學Spr
輕輕鬆鬆學習SpringBoot2:第十六篇: SpringBoot和JPA(一)(mysql)
Spring操作資料庫的方式有很多種,這一遍我們講解的是jpa(Java Persistence API)一:建立資料庫testcreate database test二:引入maven配置檔案<dependency> <groupId>mys
一起來學SpringBoot | 第十九篇:輕鬆搞定資料驗證(一)
SpringBoot是為了簡化Spring應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程 對於任何一個
SpringBoot | 第十一章:Spring中application.properties用法大全
對 Spring 裡面的 Properties 不理解的開發者可能會覺得有點亂,主要是因為配置方式很多種,使用方式也很多種。 本文不是原理分析、原始碼分析文章,只是希望可以幫助讀者更好地理解和使用 Spring Properties。 Properties 的使用 先來看看 Prop
轉載:SpringBoot非官方教程 | 第十五篇:Springboot整合RabbitMQ
這篇文章帶你瞭解怎麼整合RabbitMQ伺服器,並且通過它怎麼去傳送和接收訊息。我將構建一個springboot工程,通過RabbitTemplate去通過MessageListenerAdapter去訂閱一個POJO型別的訊息。 準備工作 15min ID
SpringBoot非官方教程 | 第十五篇:Springboot整合RabbitMQ
這篇文章帶你瞭解怎麼整合RabbitMQ伺服器,並且通過它怎麼去傳送和接收訊息。我將構建一個springboot工程,通過RabbitTemplate去通過MessageListenerAdapter去訂閱一個POJO型別的訊息。 準備工作 15min ID
SpringBoot第十二篇:整合jsp
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/10953600.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 SpringBoot 雖然官方推薦使用 thymelaf 模板引擎,但是也支援jsp,只不過需要做一些修改。本文將講解
SpringBoot第十四篇:統一異常處理
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/10984081.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 本文將談論 SpringBoot 的預設錯誤處理機制,以及如何自定義錯誤響應。 版本資訊 JDK:1.8 Spri
SpringBoot第十五篇:swagger構建優雅文件
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11007470.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 前面的十四篇文介紹了 SpringBoot 的一些基本和常用的功能。後面,我們將介紹 SpringBoot 的高階的功
SpringBoot第十六篇:自定義starter
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11058502.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 前言 這一段時間專案趕進度,故該系列部落格更新沒有之前那麼頻繁,望諒解。 SpringBoot 用起來方便,它預設集成了
SpringBoot第十七篇:定時任務
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11076555.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 相信大家對定時任務很熟悉,其重要性也不言而喻。定時發簡訊、定時批量操作、定時統計資料等,都離不開定時任務。本文將講解定
SpringBoot第二十一篇:整合ActiveMQ
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11190048.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 前一章節中,我們詳細闡述了 ActiveMQ 的安裝和使用。其實在網站發展壯大的過程中,訊息中介軟體是無法忽視的技術框
SpringBoot第十一集:整合Swagger3.0與RESTful介面整合返回值(2020最新最易懂)
SpringBoot第十一集:整合Swagger3.0與RESTful介面整合返回值(2020最新最易懂) 一,整合Swagger3.0 隨著Spring Boot、Spring Cloud等微服務的流行,在微服務的設計下,小公司微服務工程jar小的幾十個,大公司大的工程拆分jar多則幾百上萬個,這麼多的
第十一篇:消息隊列、緩存
dir hash 廣播 body 消息分發 ash rec 模式 edi 一、消息隊列簡紹 二、RabbitMQ基本實列: 三、RabbitMQ消息分發輪詢 四、消息持久化 五、Fanout廣播模式 六、Direct廣播模式 七、Redis基本操作 八、Redis Hash
史上最簡單的SpringCloud教程 | 第十一篇: docker部署spring cloud項目
大數 imageview 建議 chapter 環境 多次 pan mas 存儲 Docker是一個開源的引擎,可以輕松的為任何應用創建一個輕量級的、可移植的、自給自足的容器。開發者在筆記本上編譯測試通過的容器可以批量地在生產環境中部署,包括VMs(虛擬機)、bare m