SpringBoot 數(shù)據(jù)訪問
Spring Boot 整合 MyBatis
MyBatis 是一款優(yōu)秀的持久層框架击胜,Spring Boot 官方雖然沒有對 MyBatis 進行整合偶摔,但是 MyBatis 團隊自行適配了對應(yīng)的啟動器辰斋,進一步簡化了使用 MyBatis 進行數(shù)據(jù)的操作宫仗。
因為 Spring Boot 框架開發(fā)的便利性藕夫,所以實現(xiàn) Spring Boot 與數(shù)據(jù)訪問層框架(例如 MyBatis)的整合非常簡單毅贮,主要是引入對應(yīng)的依賴啟動器滩褥,并進行數(shù)據(jù)庫相關(guān)參數(shù)設(shè)置即可瑰煎。
-
基礎(chǔ)環(huán)境搭建
1. 數(shù)據(jù)準備
在 MySQL 中丢间,先創(chuàng)建了一個數(shù)據(jù)庫 springbootdata烘挫,然后創(chuàng)建了兩個表 t_article 和 t_comment 并向表中插入數(shù)據(jù)柬甥。其中評論表 t_comment 的 a_id 與文章表 t_article 的主鍵 id 相關(guān)聯(lián)苛蒲。
# 創(chuàng)建數(shù)據(jù)庫
CREATE DATABASE IF NOT EXISTS springbootdata DEFAULT CHARACTER SET utf8;
# 選擇使用數(shù)據(jù)庫
USE springbootdata;
# 創(chuàng)建表 t_article 并插入相關(guān)數(shù)據(jù)
DROP TABLE IF EXISTS t_article;
CREATE TABLE t_article
(
id int(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
title varchar(200) DEFAULT NULL COMMENT '文章標題',
content longtext COMMENT '文章內(nèi)容',
PRIMARY KEY (id)
) ENGINE = InnoDB AUTO_INCREMENT = 2 DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES (1, 'Spring Boot 基礎(chǔ)入門', '從入門到精通講解...');
INSERT INTO t_article VALUES (2, 'Spring Cloud 基礎(chǔ)入門', '從入門到精通講解...');
# 創(chuàng)建表 t_comment 并插入相關(guān)數(shù)據(jù)
DROP TABLE IF EXISTS t_comment;
CREATE TABLE t_comment
(
id int(20) NOT NULL AUTO_INCREMENT COMMENT '評論id',
content longtext COMMENT '評論內(nèi)容',
author varchar(200) DEFAULT NULL COMMENT '評論作者',
a_id int(20) DEFAULT NULL COMMENT '關(guān)聯(lián)的文章id',
PRIMARY KEY (id)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET=utf8;
INSERT INTO t_comment VALUES (1, '很全窟扑、很詳細', 'lucy', 1);
INSERT INTO t_comment VALUES (2, '贊一個', 'tom', 1);
INSERT INTO t_comment VALUES (3, '很詳細', 'eric', 1);
INSERT INTO t_comment VALUES (4, '很好嚎货,非常詳細', '張三', 1);
INSERT INTO t_comment VALUES (5, '很不錯', '李四', 2);
2. 創(chuàng)建項目殖属,引入相應(yīng)的啟動器
使用 Spring Initializr 來初始化項目洗显。
項目名:springbootmybatis
包名:com.zm
啟動器:SQL 的 MyBatis Framework挠唆、MySQL Driver损搬,Web 的 Spring Web
3. 編寫與數(shù)據(jù)庫表 t_comment 和 t_article 對應(yīng)的實體類 Comment 和 Article
com.zm.pojo.Comment
public class Comment {
private Integer id;
private String content;
private String author;
private Integer aId;
// getter setter toString ...
}
com.zm.pojo.Article
public class Article {
private Integer id;
private String title;
private String content;
// getter setter toString ...
}
4. 編寫配置文件
application.properties 更名為 application.yml巧勤。在 application.properties 配置文件中進行數(shù)據(jù)庫連接配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC&characterEncoding=UTF-8
username: root
password: password
-
注解方式整合 Mybatis
需求:實現(xiàn)通過 ID 查詢 Comment 信息颅悉。
1. 創(chuàng)建一個對 t_comment 表數(shù)據(jù)操作的接口 CommentMapper
com.zm.mapper.CommentMapper
public interface CommentMapper {
@Select("select * from t_comment where id = #{id}")
Comment findById(Integer id);
}
2. 在 Spring Boot 項目啟動類上添加 @MapperScan("xxx") 注解
com.zm.SpringbootmybatisApplication
@SpringBootApplication
@MapperScan("com.zm.bootmybatis.mapper") //執(zhí)行掃描mapper的包名
public class SpringbootmybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootmybatisApplication.class, args);
}
}
3. 編寫測試方法
導(dǎo)入 Junit 的依賴驹溃,增加測試方法:
com.zm.SpringbootmybatisApplicationTests
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootmybatisApplicationTests {
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Autowired
private CommentMapper commentMapper;
@Test
void findCommentById() {
Comment comment = commentMapper.findById(1);
System.out.println(comment);
}
}
控制臺中查詢的 Comment 的 aId 屬性值為 null豌鹤,沒有映射成功布疙。這是因為編寫的實體類 Comment 中使用了駝峰命名方式將 t_comment 表中的 a_id 字段設(shè)計成了 aId 屬性灵临,所以無法正確映射查詢結(jié)果儒溉。
為了解決上述由于駝峰命名方式造成的表字段值無法正確映射到類屬性的情況顿涣,可以在 Spring Boot 全局配置文件 application.yml 中添加開啟駝峰命名匹配映射配置涛碑,示例代碼如下:
mybatis:
configuration:
# 開啟駝峰命名匹配映射
map-underscore-to-camel-case: true
-
配置文件的方式整合 MyBatis
第一锌唾、二步驟使用 Free Mybatis plugin 插件生成:使用 IDEA 連接 Database晌涕,然后選中要自動生成代碼的表余黎,右鍵 -> mybatis-generator -> 按照需求輸入信息惧财,點擊 ok垮衷。
1. 創(chuàng)建一個用于對數(shù)據(jù)庫表 t_article 數(shù)據(jù)操作的接口 ArticleMapper
public interface ArticleMapper {
int deleteByPrimaryKey(Integer id);
int insert(Article record);
int insertSelective(Article record);
Article selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Article record);
int updateByPrimaryKey(Article record);
}
2. 創(chuàng)建 XML 映射文件
resources 目錄下創(chuàng)建一個統(tǒng)一管理映射文件的包 mapper搀突,并在該包下編寫與 ArticleMapper 接口方應(yīng)的映射文件 ArticleMapper.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.zm.mapper.ArticleMapper">
<resultMap id="BaseResultMap" type="com.zm.pojo.Article">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="content" jdbcType="VARCHAR" property="content" />
</resultMap>
<sql id="Base_Column_List">
id, title, content
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_article
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from t_article
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.Article" useGeneratedKeys="true">
insert into t_article (title, content)
values (#{title,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.Article" useGeneratedKeys="true">
insert into t_article
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null">
title,
</if>
<if test="content != null">
content,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null">
#{title,jdbcType=VARCHAR},
</if>
<if test="content != null">
#{content,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.renda.pojo.Article">
update t_article
<set>
<if test="title != null">
title = #{title,jdbcType=VARCHAR},
</if>
<if test="content != null">
content = #{content,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.renda.pojo.Article">
update t_article
set title = #{title,jdbcType=VARCHAR},
content = #{content,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
3. 配置 XML 映射文件路徑
在項目中編寫的 XML 映射文件,Spring Boot 并無從知曉施蜜,所以無法掃描到該自定義編寫的 XML 配置文件翻默,還必須在全局配置文件 application.yml 中添加 MyBatis 映射文件路徑的配置冰蘑,同時需要添加實體類別名映射路徑,示例代碼如下:
mybatis:
configuration:
# 開啟駝峰命名匹配映射
map-underscore-to-camel-case: true
# 加載 resources/mapper 文件夾下的所有的 xml 文件
mapper-locations: classpath:mapper/*.xml
# 配置 XML 映射文件中指定的實體類別名路徑
type-aliases-package: com.zm.pojo
4. 編寫單元測試進行接口方法測試
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootmybatisApplicationTests {
@Autowired
private ArticleMapper articleMapper;
@Test
void findArticleById() {
Article article = articleMapper.selectByPrimaryKey(1);
System.out.println(article);
}
}
Spring Boot 整合 Redis
1. 添加Redis依賴包
在項目的 pom.xml 中添加如下:
<!-- redis 依賴包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置 Redis 數(shù)據(jù)庫連接
在 application.yml 中配置redis數(shù)據(jù)庫連接信息仇箱,如下:
spring:
redis:
# Redis 服務(wù)器地址
host: 192.168.186.128
# Redis 服務(wù)器連接端口
port: 6379
jedis:
pool:
# 連接池最大連接數(shù)(使用負值表示沒有限制)
max-active: 18
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
max-wait: 3000
# 連接池中的最大空閑連接
max-idle: 20
# 連接池中的最小空閑連接
min-idle: 2
# 連接超時時間(毫秒)
timeout: 3000
# Redis 數(shù)據(jù)庫索引(默認為 0)
database: 0
3. 編寫 Redis 操作工具類
將 RedisTemplate 實例包裝成一個工具類剂桥,便于對 redis 進行數(shù)據(jù)操作权逗。
package com.zm.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author ZM
* @since 2021-10-30 1:00
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate redisTemplate;
/**
* 讀取緩存
*/
public Object get(final String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 寫入緩存
*/
public boolean set(String key, Object value) {
boolean result = false;
try {
redisTemplate.opsForValue().set(key, value, 1, TimeUnit.DAYS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 更新緩存
*/
public boolean getAndSet(final String key, String value) {
boolean result = false;
try {
redisTemplate.opsForValue().getAndSet(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 刪除緩存
*/
public boolean delete(final String key) {
boolean result = false;
try {
redisTemplate.delete(key);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
4. 測試
寫一個測試用例類來完成對 redis 的整合。
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootmybatisApplicationTests {
// 寫入堪滨,key:1袱箱,value:mysql 數(shù)據(jù)庫中 id 為 1 的 article 記錄
@Autowired
private RedisUtils redisUtils;
@Test
void writeRedis() {
redisUtils.set("1", articleMapper.selectByPrimaryKey(1));
System.out.println("success");
}
@Test
void readRedis() {
Article article = (Article) redisUtils.get("1");
System.out.println(article);
}
}
SpringBoot 視圖技術(shù)
支持的視圖技術(shù)
前端模板引擎技術(shù)的出現(xiàn)发笔,使前端開發(fā)人員無需關(guān)注后端業(yè)務(wù)的具體實現(xiàn)筐咧,只關(guān)注自己頁面的呈現(xiàn)效果即可量蕊,并且解決了前端代碼錯綜復(fù)雜的問題残炮、實現(xiàn)了前后端分離開發(fā)势就。Spring Boot 框架對很多常用的模板引擎技術(shù)(如:FreeMarker苞冯、Thymeleaf舅锄、Mustache 等)提供了整合支持皇忿。
Spring Boot 不太支持常用的 JSP 模板鳍烁,并且沒有提供對應(yīng)的整合配置幔荒,這是因為使用嵌入式 Servlet 容器的 Spring Boot 應(yīng)用程序?qū)τ?JSP 模板存在一些限制 :
- 在 Jetty 和 Tomcat 容器中爹梁,Spring Boot 應(yīng)用被打包成 war 文件可以支持 JSP卫键。但 Spring Boot 默認使用嵌入式 Servlet 容器以 JAR 包方式進行項目打包部署莉炉,這種 JAR 包方式不支持 JSP絮宁。
- 如果使用 Undertow 嵌入式容器部署 Spring Boot 項目绍昂,也不支持 JSP 模板窘游。(Undertow 是紅帽公司開發(fā)的一款基于 NIO 的高性能 Web 嵌入式服務(wù)器)
- Spring Boot 默認提供了一個處理請求路徑 “/error” 的統(tǒng)一錯誤處理器忍饰,返回具體的異常信息艾蓝。使用 JSP 模板時赢织,無法對默認的錯誤處理器進行覆蓋于置,只能根據(jù) Spring Boot 要求在指定位置定制錯誤頁面。
Thymeleaf
Thymeleaf 是一種現(xiàn)代的基于服務(wù)器端的 Java 模板引擎技術(shù),也是一個優(yōu)秀的面向 Java 的 XML休讳、XHTML、HTML5 頁面模板雏婶,它具有豐富的標簽語言留晚、函數(shù)和表達式,在使用 Spring Boot 框架進行頁面設(shè)計時告嘲,一般會選擇 Thymeleaf 模板错维。
Thymeleaf 語法
在 HTML 頁面上使用 Thymeleaf 標簽,Thymeleaf 標簽?zāi)軌騽討B(tài)地替換掉靜態(tài)內(nèi)容橄唬,使頁面動態(tài)展示赋焕。
為了更直觀的認識 Thymeleaf,下面展示一個在 HTML 文件中嵌入了 Thymeleaf 的頁面文件仰楚,示例代碼如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
<title>Thymeleaf</title>
</head>
<body>
<p th:text="${hello}">Hello Thymeleaf</p>
</body>
</html>
上述代碼中,“xmlns:th="http://www.thymeleaf.org" 用于引入 Thymeleaf 模板引擎標簽僧界,使用關(guān)鍵字 th 標注標簽是 Thymeleaf 模板提供的標簽侨嘀,其中,th:href="@{/css/gtvg.css}" 用于引入外聯(lián)樣式文件捂襟,th:text="${hello}" 用于動態(tài)顯示標簽文本內(nèi)容飒炎。
常用標簽:
- th:insert - 布局標簽,替換內(nèi)容到引入的文件
- th:replace - 頁面片段包含(類似 JSP 中的 include 標簽)
- th:each - 元素遍歷(類似 JSP 中的 c:forEach 標簽)
- th:if - 條件判斷笆豁,如果為真
- th:unless - 條件判斷郎汪,如果為假
- th:switch - 條件判斷,進行選擇性匹配
- th:case - 條件判斷闯狱,進行選擇性匹配
- th:value - 屬性值修改煞赢,指定標簽屬性值
- th:href - 用于設(shè)定鏈接地址
- th:src - 用于設(shè)定鏈接地址
- th:text - 用于指定標簽顯示的文本內(nèi)容
標準表達式:
- 變量表達式- ${...}
- 選擇變量表達式 - *{...}
- 消息表達式 - #{...}
- 鏈接 URL 表達式 - @{...}
- 片段表達式 - ~{...}
1. 變量表達式:${...}
變量表達式 ${...} 主要用于獲取上下文中的變量值,示例代碼如下:
<p th:text="${title}">這是標題</p>
示例使用了 Thymeleaf 模板的變量表達式 ${...} 用來動態(tài)獲取 P 標簽中的內(nèi)容哄孤,如果當前程序沒有啟動或者當前上下文中不存在 title 變量照筑,該片段會顯示標簽?zāi)J值“這是標題”;如果當前上下文中存在 title 變量并且程序已經(jīng)啟動,當前 P 標簽中的默認文本內(nèi)容將會被 title 變量的值所替換凝危,從而達到模板引擎頁面數(shù)據(jù)動態(tài)替換的效果波俄。
同時,Thymeleaf 為變量所在域提供了一些內(nèi)置對象蛾默,具體如下所示:
#ctx:上下文對象
#vars:上下文變量
#locale:上下文區(qū)域設(shè)置
#request:(僅限 Web Context)HttpServletRequest 對象
#response:(僅限 Web Context)HttpServletResponse 對象
#session:(僅限 Web Context)HttpSession 對象
#servletContext:(僅限 Web Context)ServletContext 對象
結(jié)合上述內(nèi)置對象的說明懦铺,假設(shè)要在 Thymeleaf 模板引擎頁面中動態(tài)獲取當前國家信息,可以使用 #locale 內(nèi)置對象支鸡,示例代碼如下:
The locale country is: <span th:text="${#locale.country}">China</span>
上述代碼中冬念,使用 th:text="${#locale.country}" 動態(tài)獲取當前用戶所在國家信息,其中標簽內(nèi)默認內(nèi)容為 China牧挣,程序啟動后通過瀏覽器查看當前頁面時急前,Thymeleaf 會通過瀏覽器語言設(shè)置來識別當前用戶所在國家信息,從而實現(xiàn)動態(tài)替換瀑构。
2. 選擇變量表達式:*{...}
選擇變量表達式和變量表達式用法類似裆针,一般用于從被選定對象而不是上下文中獲取屬性值,如果沒有選定對象寺晌,則和變量表達式一樣据块,示例代碼如下:
<div th:object="${book}">
<p>titile: <span th:text="*{title}">標題</span>.</p>
</div>
*{title} 選擇變量表達式獲取當前指定對象 book 的 title 屬性值。
3. 消息表達式:#{...}
消息表達式 #{...} 主要用于 Thymeleaf 模板頁面國際化內(nèi)容的動態(tài)替換和展示折剃,使用消息表達式 #{...} 進行國際化設(shè)置時另假,還需要提供一些國際化配置文件。
4. 鏈接表達式 :@{...}
鏈接表達式 @{...} 一般用于頁面跳轉(zhuǎn)或者資源的引入怕犁,在 Web 開發(fā)中占據(jù)著非常重要的地位边篮,并且使用也非常頻繁,示例代碼如下:
<a th:href="@{http://localhost:8080/order/details(orderId=${o.id})}">view</a>
<a th:href="@{/order/details(orderId=${o.id},pid=${p.id})}">view</a>
上述代碼中奏甫,鏈接表達式 @{...} 分別編寫了絕對鏈接地址和相對鏈接地址戈轿。在有參表達式中,需要按照 @{路徑(參數(shù)名稱=參數(shù)值阵子,參數(shù)名稱=參數(shù)值...)} 的形式編寫思杯,同時該參數(shù)的值可以使用變量表達式來傳遞動態(tài)參數(shù)值。
5. 片段表達式 :~{...}
片段表達式 ~{...} 用來標記一個片段模板挠进,并根據(jù)需要移動或傳遞給其他模板色乾。其中,最常見的用法是使用 th:insert 或 th:replace 屬性插入片段领突,示例代碼如下:
<div th:insert="~{thymeleafDemo::title}"></div>
上述代碼中暖璧,使用 th:insert 屬性將 title 片段模板引用到該標簽中。thymeleafDemo 為模板名稱君旦,Thymeleaf 會自動查找 /resources/templates/ 目錄下的 thymeleafDemo 模板澎办,title 為片段名稱嘲碱。
基本使用
1) Thymeleaf 模板基本配置
首先在 Springbootdemo2 項目中使用 Thymeleaf 模板,首先必須保證引入 Thymeleaf 依賴局蚀,示例代碼如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
其次麦锯,在全局配置文件中配置 Thymeleaf 模板的一些參數(shù)。一般 Web 項目都會使用下列配置琅绅,示例代碼如:
spring:
thymeleaf:
# 在開發(fā)階段扶欣,為了驗證建議關(guān)閉緩存
cache: true
# 模板編碼
encoding: UTF-8
# 應(yīng)用于模板的模板模式
mode: HTML5
# 指定模板頁面存放路徑
prefix: classpath:/templates/
# 指定模板頁面名稱的后綴
suffix: .html
上述配置中,spring.thymeleaf.cache 表示是否開啟 Thymeleaf 模板緩存奉件,默認為 true宵蛀,在開發(fā)過程中通常會關(guān)閉緩存,保證項目調(diào)試過程中數(shù)據(jù)能夠及時響應(yīng);spring.thymeleaf.prefix 指定了 Thymeleaf 模板頁面的存放路徑复唤,默認為classpath:/templates/陶缺;spring.thymeleaf.suffix 指定了 Thymeleaf 模板頁面的名稱后綴,默認為 .html念逞。
2)靜態(tài)資源的訪問
開發(fā) Web 應(yīng)用時,難免需要使用靜態(tài)資源。Spring boot 默認設(shè)置了靜態(tài)資源的訪問路徑摆碉。
使用 Spring Initializr 方式創(chuàng)建的 Spring Boot 項目,默認生成了一個 resources 目錄脓豪,在 resources 目錄中的 public巷帝、resources、static 三個子目錄下扫夜,Spring boot 默認會挨個從public楞泼、resources、static 里面查找靜態(tài)資源笤闯。
完成數(shù)據(jù)的頁面展示
1)創(chuàng)建 Spring Boot 項目堕阔,引入 Thymeleaf 依賴。
2)編寫配置文件颗味。
編輯 application.yml 全局配置文件超陆,在該文件中對 Thymeleaf 模板頁面的數(shù)據(jù)緩存進行設(shè)置。
# thymeleaf 頁面緩存設(shè)置(默認為 true)浦马,開發(fā)中方便調(diào)試應(yīng)設(shè)置為 false时呀,上線穩(wěn)定后應(yīng)保持默認 true
spring:
thymeleaf:
cache: false
使用 spring.thymeleaf.cache=false 將 Thymeleaf 默認開啟的緩存設(shè)置為了 false,用來關(guān)閉模板頁面緩存晶默。
3)創(chuàng)建 web 控制類
在項目中創(chuàng)建名為 com.zm.controller 的包退唠,并在該包下創(chuàng)建一個用于前端模板頁面動態(tài)數(shù)據(jù)替換效果測試的訪問實體類 LoginController。
@Controller
public class LoginController {
@RequestMapping("/toLogin")
public String toLoginView(Model model){
model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
return "login"; // resources/templates/login.html
}
}
toLoginView() 方法用于向登錄頁面 login.html 跳轉(zhuǎn)荤胁,同時攜帶了當前年份信息 currentYear瞧预。
4)創(chuàng)建模板頁面并引入靜態(tài)資源文件屎债。
在 classpath:/templates/ 目錄下引入一個用戶登錄的模板頁面 login.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">
<title>用戶登錄界面</title>
<link th:href="@{../static/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{../static/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<!-- 用戶登錄 form 表單 -->
<form class="form-signin">
<img class="mb-4" th:src="@{../static/img/login.png}" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal">請登錄</h1>
<input type="text" class="form-control"
th:placeholder="用戶名" required="" autofocus="">
<input type="password" class="form-control"
th:placeholder="密碼" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 記住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" >登錄</button>
<p class="mt-5 mb-3 text-muted">? <span th:text="${currentYear}">2019</span>-<span th:text="${currentYear}+1">2020</span></p>
</form>
</body>
</html>
通過 xmlns:th="http://www.thymeleaf.org 引入了 Thymeleaf 模板標簽垢油;
使用 th:href 和 th:src 分別引入了兩個外聯(lián)的樣式文件和一個圖片盆驹;
使用 th:text 引入了后臺動態(tài)傳遞過來的當前年份 currentYear。
5)效果測試
可以看出滩愁,登錄頁面 login.html 顯示正常躯喇,在頁面底部動態(tài)顯示了當前日期 2020-2021,而不是文件中的靜態(tài)數(shù)字 2019-2020硝枉。這進一步說明了 Spring Boot 與 Thymeleaf 整合成功廉丽,完成了靜態(tài)資源的引入和動態(tài)數(shù)據(jù)的顯示。
SpringBoot 實戰(zhàn)演練
實戰(zhàn)技能補充:lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<!-- 編譯期間生效 -->
<scope>provided</scope>
</dependency>
需求:實現(xiàn)用戶的 CRUD 功能
初始化數(shù)據(jù)庫信息:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`
(
id int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶id',
username varchar(100) DEFAULT NULL COMMENT '用戶名',
password varchar(100) DEFAULT NULL COMMENT '密碼',
birthday varchar(100) DEFAULT NULL COMMENT '生日',
PRIMARY KEY (id)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (1, 'zhangsan', '123', '2020-10-1');
INSERT INTO `user` VALUES (2, 'lisi', '123', '2020-10-2');
INSERT INTO `user` VALUES (3, 'wangwu', '123', '2020-10-10');
INSERT INTO `user` VALUES (4, 'yuanjing', '123', '2020-10-11');
1)創(chuàng)建 springboot 工程
使用 Spring Initializr 新建一個工程 springbootuser妻味,選擇依賴:Developer Tools -> Lombok正压,Web -> Spring Web,SQL -> [MyBatis Framework责球、MySQL Driver]焦履。
2)編輯 pom.xml
<!-- 引入阿里巴巴數(shù)據(jù)庫連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
3)User 實體類編寫
使用 FreeMyBatis 生成實體類。
使用 FreeMyBatis 生成 UserMapper 相關(guān)的代碼嘉裤。
com.zm.pojo.User
@Data // Lombok 自動生成 getter 和 setter
public class User implements Serializable {
/**
* 用戶id
*/
private Integer id;
/**
* 用戶名
*/
private String username;
/**
* 密碼
*/
private String password;
/**
* 生日
*/
private String birthday;
private static final long serialVersionUID = 1L;
}
4)UserMapper 編寫及 xml 文件
com.zm.mapper.UserMapper
public interface UserMapper {
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
src\main\resources\mapper\UserMapper.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.zm.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.zm.pojo.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="birthday" jdbcType="VARCHAR" property="birthday" />
</resultMap>
<sql id="Base_Column_List">
id, username, `password`, birthday
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.zm.pojo.User" useGeneratedKeys="true">
insert into user (username, `password`, birthday
)
values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{birthday,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.zm.pojo.User" useGeneratedKeys="true">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
username,
</if>
<if test="password != null">
`password`,
</if>
<if test="birthday != null">
birthday,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">
#{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
#{password,jdbcType=VARCHAR},
</if>
<if test="birthday != null">
#{birthday,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.zm.pojo.User">
update user
<set>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
`password` = #{password,jdbcType=VARCHAR},
</if>
<if test="birthday != null">
birthday = #{birthday,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.zm.pojo.User">
update user
set username = #{username,jdbcType=VARCHAR},
`password` = #{password,jdbcType=VARCHAR},
birthday = #{birthday,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
5)UserService 接口及實現(xiàn)類編寫
com.zm.service.UserService
public interface UserService {
/**
* 查詢所有
*/
List<User> queryAll();
/**
* 通過 ID 查詢
*/
User findById(Integer id);
/**
* 新增
*/
void insert(User user);
/**
* 通過 ID 刪除
*/
void deleteById(Integer id);
/**
* 修改
*/
void update(User user);
}
com.zm.service.impl.UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryAll() {
return userMapper.queryAll();
}
@Override
public User findById(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
public void insert(User user) {
// 將除 id 外所有的列都拼接入 SQL 語句
// userMapper.insert(user);
// 只將不為空的列才拼接入 SQL 語句(優(yōu)先使用妹孙,減少高并發(fā)下數(shù)據(jù)傳輸)
userMapper.insertSelective(user);
}
@Override
public void deleteById(Integer id) {
userMapper.deleteByPrimaryKey(id);
}
@Override
public void update(User user) {
userMapper.updateByPrimaryKeySelective(user);
}
}
6)UserController 編寫
com.zm.controller.UserController
/**
* restful 格式進行訪問
* 查詢:GET
* 新增: POST
* 更新:PUT
* 刪除: DELETE
*
* @author ZM
* @since 202`-10-31 1:36
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 查詢所有
*/
@GetMapping("/query")
public List<User> queryAll(){
return userService.queryAll();
}
/**
* 通過 ID 查詢
*/
@GetMapping("/query/{id}")
public User queryById(@PathVariable Integer id){
return userService.findById(id);
}
/**
* 刪除
*/
@DeleteMapping("/delete/{id}")
public String delete(@PathVariable Integer id){
userService.deleteById(id);
return "刪除成功";
}
/**
* 新增
*/
@PostMapping("/insert")
public String insert(User user){
userService.insert(user);
return "新增成功";
}
/**
* 修改
*/
@PutMapping("/update")
public String update(User user){
userService.update(user);
return "修改成功";
}
}
7)全局配置文件 application.yml
重命名 application.properties 為 application.yml
src\main\resources\application.yml
# 服務(wù)器配置
server:
port: 8090
spring:
# 數(shù)據(jù)源配置
datasource:
name: druid
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/springbootdata?characterEncoding=utf-8&serverTimezone=UTC
username: root
password: password
# 整合 MyBatis
mybatis:
# 聲明 MyBatis 文件所在的位置
mapper-locations: classpath:mapper/*Mapper.xml
8)啟動類
com.zm.SpringbootuserApplication
@SpringBootApplication
// 使用的 Mybatis, 掃描 com.zm.mapper
@MapperScan("com.zm.mapper")
public class SpringbootuserApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootuserApplication.class, args);
}
}
9)使用 Postman 測試
- GET http://localhost:8090/user/query
- GET http://localhost:8090/user/query/1
- POST http://localhost:8090/user/insert?username=zm&password=123456&birthday=1995-12-27
- PUT http://localhost:8090/user/update?username=zmmm&password=00000&birthday=1997-12-27&id=5
- DELETE http://localhost:8090/user/delete/5
Spring Boot 項目部署
需求:將 Spring Boot 項目使用 maven 指令打成 jar 包并運行測試笨触。
分析
1)添加打包組件將項目中的資源芦劣、配置虚吟、依賴包打到一個 jar 包中;可以使用 maven 的 package 命令偏塞。
2)部署:java -jar 包名
步驟實現(xiàn)
確保 pom.xml 文件中有如下的打包組件:
<build>
<plugins>
<!-- 打 jar 包時如果不配置該插件灸叼,打出來的 jar 包沒有清單文件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
部署運行:
java -jar springbootuser-0.0.1-SNAPSHOT.jar