1. 程式人生 > 實用技巧 >Spring的學習與實戰

Spring的學習與實戰

目錄

一、Spring起步

  • Spring早已經成為企業級開發的業界標準,尤其是Spring Boot 2.0、Spring 5釋出後,Spring的生態系統引領了技術架構發展的潮流,對於Java開發人員,深入掌握Spring全家桶的各種框架應用及必要的底層原理知識,是一件非常重要的事情。

學習路線圖

Spring的基礎知識

什麼是Spring

Spring的核心是提供了一個容器(container),通常稱為Spring應用上下文(Spring application context),它們會建立和管理應用元件。這些元件也可以稱為bean,會在Spring應用上下文中裝配在一起,從而形成一個完整的應用程式。

將bean裝配在一起的行為是通過一種基於依賴注入(dependency injection,DI)的模式實現的。此時,元件不會再去建立它所依賴的元件並管理它們的生命週期,使用依賴注入的應用依賴於單獨的實體(容器)來建立和維護所有的元件,並將其注入到需要它們的bean中。通常,這是通過構造器引數和屬性訪問方法來實現的。

Spring框架核心模組

SpringBoot

在歷史上,一般通過兩種配置方式為Spring應用上下文提供Bean

  1. 使用一個或多個XML檔案描述bean
  2. 使用@Configuration註解會告知Spring這是一個配置類

隨著Spring Boot 2.x的引入,Spring自動配置的能力已經大大加強,Spring Boot能夠基於類路徑中的條目、環境變數和其他因素合理猜測需要配置的元件並將它們裝配在一起。Java程式設計師儘可能多地使用Spring Boot,只有在必要的時候才使用顯式配置。

第一個Spring應用DEMO
  1. 在IntelliJ IDEA中建立新專案

  2. 通過地址為https://start.spring.io/初始化專案;

  3. 指定專案通用資訊:

  4. 選擇專案Starter:

  5. 生成的專案結構:

  6. maven規範
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

可參見本人部落格《Maven POM( Project Object Model,專案物件模型 )》《一圖說清maven常見要素》這兩篇文章。

  1. 入口類
/**
* SpringBoot應用
*/
@SpringBootApplication
public class DemoApplication { public static void main(String[] args) {
// 執行應用
SpringApplication.run(DemoApplication.class, args);
} }

@SpringBootApplication是一個組合註解,它組合了3個其他的註解。

  • @SpringBootConfiguration:將該類宣告為配置類。儘管這個類目前還沒有太多的配置,但是後續我們可以按需新增基於Java的Spring框架配置。這個註解實際上是@Configuration註解的特殊形式。
  • @EnableAutoConfiguration:啟用Spring Boot的自動配置。我們隨後會介紹自動配置的更多功能。就現在來說,我們只需要知道這個註解會告訴SpringBoot自動配置它認為我們會用到的元件。
  • @ComponentScan:啟用元件掃描。這樣我們能夠通過@[email protected]、@Service這樣的註解宣告其他類,Spring會自動發現它們並將它們註冊為Spring應用上下文中的元件。



8. 測試類

// SpringBoot測試
@SpringBootTest
class DemoApplicationTests { // 測試方法
@Test
void contextLoads() {
} }
  • 程式啟動

編寫自己的第一個SpringMVC例子
  • 第一個Controller

index()是一個簡單的控制器方法。它帶有@GetMapping註解,表明如果針對“/”傳送HTTP GET請求,那麼這個方法將會處理請求。該方法所做的只是返回String型別的index值,該控制器方法中還通過Spring自動注入IndexService服務元件,及呼叫服務元件方法。

/**
* 第一個SpringMVC程式--Controller層
*
* @author zhuhuix
* @date 2020-07-02
*/
@Controller
public class IndexController {
// Spring注入服務元件
@Autowired
private IndexService indexService; @GetMapping("/")
public String index(Model model) {
String index = indexService.getIndex();
model.addAttribute("index", index);
// 返回檢視 即index.html
return "index";
}
}
  • 第一個Service

getIndex()是一個簡單的服務方法。該方法所做的只是返回String型別的index值,該服務元件供控制層呼叫。

/**
* 第一個SpringMVC程式--Service層
* * @author zhuhuix
* @date 2020-07-02
*/
@Service
public class IndexService {
public String getIndex() {
return "hello world!!!";
}
}
  • 第一個View

-- 使用Thymeleaf模板引擎

### application.properties
###ThymeLeaf配置
spring:
thymeleaf:
#模板的模式,支援 HTML, XML TEXT JAVASCRIPT
mode: HTML5
#編碼 可不用配置
encoding: UTF-8
#內容類別,可不用配置
content-type: text/html
#開發配置為false,避免修改模板還要重啟伺服器
cache: false
#配置模板路徑,預設是templates,可以不用配置
prefix: classpath:/templates

-- 定義index.html檢視層

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<p th:text="${index}" />
</body>
</html>
  • 執行測試

嘗試使用Spring Boot DevTools

•程式碼變更後應用會自動重啟;

•當面向瀏覽器的資源(如模板、JavaScript、樣式表)等發生變化時,會自動重新整理瀏覽器

  • pom.xml
	<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--fork : devtools生效必須設定成true -->
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
  • idea設定

    -- 需勾選Build project automaticallty



    -- ctrl+alt+shift+/ :Registry 中第一項必須打勾

Spring起步小結

  • Spring核心框架:Spring核心框架是Spring領域中一切的基礎。它提供了核心容器和依賴注入框架。
  • Spring Boot:Spring Boot構建在Spring之上,通過簡化依賴管理、自動配置和執行時洞察,使Spring更加易用;
  • Spring MVC:我們通過SpringBoot初始化生成的框架上加入Controller,Service,View的分層,編寫了第一個Spring MVC程式,併成功執行。
  • 使用Idea開發環境,安裝Spring Boot DevTools並進行配置,提高了開發效率。

二、基於SpringMVC開發web應用

. 在上一小節中建立了第一個DEMO,本章將繼續基於SpringMVC框架構建我們的web應用,該應用需要實現使用者登記,具體實現步驟如下:

  1. 建立使用者的資料模型;
  2. 在服務層編寫使用者登記的業務邏輯;
  3. 生成為Web瀏覽器提供使用者登記內容的控制器
  4. 在檢視層運用模板引擎展示資料及校驗表單輸入

建立資料模型

  • 建立一個使用者類,定義使用者id,使用者名稱稱,郵箱三個屬性;
  • 新增預設構造方法與全屬性構造方法;
  • 對使用者屬性新增對應getter,setter方法;
/**
* 基於SpringMVC框架開發web應用--使用者類
*
* @author zhuhuix
* @date 2020-07-03
*/
public class User implements Serializable {
// 使用者id
private Long id;
// 使用者名稱
private String name;
// 郵箱
private String email; User(){ } public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
} public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
}
}

建立業務邏輯

  • 實現返回所有使用者資料的列表
  • 實現增加使用者的功能
/**
* 基於SpringMVC框架開發web應用--使用者服務類
*
* @author zhuhuix
* @date 2020-07-03
*/
@Service
public class UserService {
public static ArrayList<User> users = new ArrayList<>(); // mock資料
public UserService() {
users.add(new User(1L, "Mike", "[email protected]"));
users.add(new User(2L, "Jack", "[email protected]"));
users.add(new User(3L, "Kate", "[email protected]"));
users.add(new User(4L, "Mary", "[email protected]"));
users.add(new User(5L, "Rose", "[email protected]"));
} // 返回所有的使用者
public List<User> listUsers() {
return users;
} // 增加使用者
public User saveUser(User user) {
user.setId(users.size() + 1L);
users.add(user);
return user;
}
}

建立控制器

在Spring MVC框架中,控制器是重要的參與者。它們的主要職責是處理HTTP請求傳遞給檢視以便於渲染HTML(瀏覽器展現)。

  • SpirngMVC的請求註解
註解 描述
@RequestMapping 通用的請求
@GetMapping 處理HTTP GET請示
@PostMapping 處理HTTP POST請示
@PutMapping 處理HTTP PUT請示
@DeleteMapping 處理HTTP DELETE請示
  • 使用者控制器的處理內容

    -- 處理路徑為“/user”的HTTP GET請求,向服務層呼叫返回所有使用者資料列表的介面,獲取資料後傳遞給對應的檢視模板,併傳送給發起請求的Web瀏覽器。

    -- 處理路徑為“/user”的HTTP POST請求,向服務層呼叫增加使用者的介面,處理成功後呼叫路徑為“/user”的HTTP GET請求,併傳送給發起請求的Web瀏覽器。

    -- 處理路徑為“/user/form”的HTTP GET請求,產生一個新使用者資料模型,並呼叫對應的檢視模板,傳送給發起請求的Web瀏覽器。
/**
* 基於SpringMVC框架開發web應用--使用者控制器
*
* @author zhuhuix
* @date 2020-07-03
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService; // 儲存使用者並返回到使用者列表頁面
@PostMapping
public ModelAndView saveUser(User user) {
userService.saveUser(user);
return new ModelAndView("redirect:/user");//重定向到list頁面
} // 獲取建立使用者表單頁面
@GetMapping("/form")
public ModelAndView createForm(Model model) {
model.addAttribute("user",new User());
return new ModelAndView("register","userModel",model);
} // 獲取使用者列表頁面
@GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList", userService.listUsers());
return new ModelAndView("userlist", "userModel", model);
}
}

設計檢視模板

  • 設計一個使用者列表的檢視模板

    -- Thymeleaf提供了一個屬性“th:each”,它會迭代一個元素集合,為集合中的每個條目渲染HTML,我們可以利用這個屬性,設計出使用者的列表檢視
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultrag.net.nz/thymeleaf/layout"
>
<head>
<meta charset="UTF-8">
</head>
<body>
<h3>使用者列表</h3>
<div>
<a th:href="@{/user/form}">建立使用者</a>
</div>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Email</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr th:if="${userModel.userList.size()} eq 0">
<td colspan="3">沒有使用者資訊!</td>
</tr>
<tr th:each="user:${userModel.userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.name}"></td>
</tr>
</tbody>
</table>
</body>
</html>
  • 設計一個提交新使用者的檢視模板

    -- 使用者通過這個檢視,錄用名稱與郵箱地址,提交新使用者的資訊。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultrag.net.nz/thymeleaf/layout"
>
<head>
<meta charset="UTF-8">
</head>
<body>
<h3>登記使用者</h3>
<form action="/users" th:action="@{/user}" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名稱:<br>
<input type="text" name="name" th:value="*{name}">
<br>
郵箱:<br>
<input type="text" name="email" th:value="*{email}">
<input type="submit" value="提交" >
</form>
</body>
</html>

執行Web應用

  • 到目前為止,我們已經開發了User使用者模型、UserService使用者服務類、UserController控制器、userlist使用者列表檢視模板、register使用者登記檢視模板,接下來我們可以嘗試執行一下。開啟瀏覽器並訪問http://localhost:8080/user。

  • 點選頁面上的建立使用者,登記新使用者,並提交





    該web應用一切執行正常。

表單校驗

雖然我們已經實現了使用者列表與登記新使用者,但檢視層還存在漏洞,比如使用者名稱稱為空的時候不能儲存,郵箱輸入格式要符合規則,所以程式要對錶單輸入的內容進行校驗。

  • 引入Validation API與Hibernate的Validation API 依賴
  		<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency> <dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
  • 在要被校驗的類上宣告校驗規則:即在User類上宣告校驗規則。
public class User implements Serializable {
// 使用者id
@NotNull
private Long id;
// 使用者名稱
@NotBlank(message = "使用者名稱稱不能為空")
private String name;
// 郵箱
@Pattern(message ="郵箱格式不符", regexp = "^[A-Za-z0-9\\u4e00-\\u9fa5][email protected][a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
private String email;
...
}
  • 在控制器方法中宣告要進行校驗:即在UserController類的saveUser上增加使用者資料的校驗規則。
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService; // 儲存使用者並返回到使用者列表頁面
@PostMapping
public ModelAndView saveUser(@Valid User user, Errors errors,Model model) {
if (errors.hasErrors()){
model.addAttribute("user",user);
if (errors.getFieldError("name")!=null) {
model.addAttribute("nameError", errors.getFieldError("name").getDefaultMessage());
}
if (errors.getFieldError("email")!=null) {
model.addAttribute("emailError", errors.getFieldError("email").getDefaultMessage());
}
return new ModelAndView("register","userModel",model);
}
userService.saveUser(user);
//重定向到list頁面
return new ModelAndView("redirect:/user");
}
...
}
  • 修改register表單檢視以展現校驗錯誤。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<h3>登記使用者</h3>
<form action="/users" th:action="@{/user}" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名稱:<br>
<input type="text" name="name" th:value="*{name}" >
<br>
郵箱:<br>
<input type="text" name="email" th:value="*{email}">
<br>
<input type="submit" value="提交" >
<div style="color:red" th:text="${nameError}"></div>
<div style="color:red" th:text="${emailError}"></div>
</form>
</body>
</html>
展現校驗錯誤

基於SpringMVC開發web應用小結

  • Spring提供了一個強大Spring MVC的Web框架。
  • Spring MVC是基於註解的,通過像@RequestMapping、@GetMapping和@PostMapping這樣的註解來啟用請求處理方法的宣告。
  • 請求處理方法返回一個Thymeleaf模板,同時會帶有模型資料。
  • Spring MVC支援表單校驗。

三、實現資料持久化

. 在上一小節中基於SpringMVC框架構建了我們的web應用,並在檢視層運用模板引擎展示資料及校驗表單輸入,本章將使用JdbcTemplate及Spring Data實現資料持久化的操作。

資料庫

  • 一說到資料的持久化,首選方案就是關係型資料庫,本文將使用網際網路領域最常用mysql資料庫。

MySQL 最流行的關係型資料庫管理系統,MySQL所使用的 SQL 語言是用於訪問資料庫的最常用標準化語言,MySQL由於效能高、成本低、可靠性好,已經成為最流行的開源資料庫,因此被廣泛地應用在網際網路領域中。

建立使用者資訊登記表
  • 根據使用者資訊模型類,設計使用者資訊登入表
DROP DATABASE IF EXISTS user_info;

CREATE DATABASE user_info
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci; use user_info; SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;

Web應用專案整合mysql
  • 增加依賴
 <!--Mysql依賴包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- 資料庫連線池:druid資料來源驅動 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
  • Spring配置
#配置資料來源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://user_info?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true

使用JdbcTemplate實現資料持久化

Spring對JDBC的支援要歸功於JdbcTemplate類。JdbcTemplate提供了一種特殊的方式,通過這種方式,開發人員在對關係型資料庫執行SQL操作的時候能夠避免使用JDBC時常見的繁文縟節和樣板式程式碼。

  • 增加依賴
 <!-- JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
  • 修改UserService業務邏輯
/**
* 基於SpringMVC框架開發web應用--使用者服務類
*
* @author zhuhuix
* @date 2020-07-03
* @date 2020-07-04 增加通過jdbcTemplate處理資料
*/
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate; // 返回所有的使用者
public List<User> listUsers() {
return jdbcTemplate.query("select id,name,email from user;",
new Object[]{}, new BeanPropertyRowMapper<>(User.class));
} // 增加使用者
public int saveUser(User user) {
return jdbcTemplate.update("insert into user(name,email) values(?,?);"
, user.getName(), user.getEmail());
} }

再次執行Web應用

  • 我們只修改了UserService使用者服務類;控制器、檢視模板都未做任何改變,接下來我們可以再次嘗試執行一下。開啟瀏覽器並訪問http://localhost:8080/user。

  • 輸入使用者資訊並提交



  • 檢視資料庫使用者資訊表

實現資料持久化小結

相對於普通的JDBC,Spring的JdbcTemplate能夠極大地簡化關係型資料庫的使用。但是,你會發現使用JPA會更加簡單。接下來我們會繼續通過Spring Data框架讓資料持久化變得更簡單。

四、使用Spring Data實現資料持久化

在上篇文章中,我們使用mysql資料庫與JdbcTemplate簡單實現了資料持久化操作,並對web程式進行了測試,本篇文章將繼續通過Spring Data框架讓資料持久化變得更簡單。

Spring Data

  • Spring Data是一個用於簡化資料庫訪問,並支援雲服務的開源框架。其主要目標是使得資料庫的訪問變得方便快捷,常用的子專案有:

Spring Data JDBC -資料訪問元件對JDBC的支援。

Spring Data JPA:-基於關係型資料庫進行JPA持久化。

Spring Data MongoDB - 持久化到Mongo檔案資料庫。

Spring Data Redis-持久化到Redis key-value記憶體資料庫。

Spring Data REST:通過Spring Data資料訪問元件匯出為RESTful資源。

Spring Data Cassandra:持久化到Cassandra資料庫。

四、使用Spring Data JPA持久化資料

  • 本文會基於原JDBC的實現替換為使用SpringData JPA的repository
新增JPA starter依賴
<!--pom.xml-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
修改實體類,新增JPA對映註解
  • 首先我們給原來的user表增加兩個時間欄位
ALTER TABLE user ADD COLUMN create_time DATETIME;
ALTER TABLE user ADD COLUMN update_time DATETIME;
  • 修改user.class

    -- 給user類新增@Entity註解,宣告為JPA實體

    -- 給id欄位新增@Id註解將其指定為資料庫中唯一標識該實體的屬性

    -- 給id欄位新增@GeneratedValue註解,依賴資料庫自動生成ID值

    -- 給其它欄位新增@Column註解,並宣告對應user表中的欄位名稱

    -- 增加createTime成員,新增@CreationTimestamp註解,使用該註解可以讓Hibernate在插入資料時對註解的屬性對應的日期型別建立預設值

    -- 增加updateTime成員,新增@UpdateTimestamp註解,使用該註解可以讓Hibernate在更新資料時對註解的屬性對應的日期型別進行更新
/**
* 基於SpringMVC框架開發web應用--使用者類
*
* @author zhuhuix
* @date 2020-07-03
* @date 2020-07-07 新增JPA對映註解
*/
@Entity
public class User implements Serializable {
// 使用者id
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 使用者名稱
@NotBlank(message = "使用者名稱稱不能為空")
@Column(name="name")
private String name;
// 郵箱
@Column(name="email")
@Pattern(message ="郵箱格式不符", regexp = "^[A-Za-z0-9\\u4e00-\\u9fa5][email protected][a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
private String email; // 建立時間
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime; // 更新時間
@Column(name = "update_time")
@UpdateTimestamp
private Timestamp updateTime; public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
} public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
}
}
宣告JPA repository介面
  • 藉助Spring Data JPA,我們可以通過繼承CrudRepository介面,快速定義應用的資料層。CrudRepository定義並實現了很多用於CRUD(建立、讀取、更新、刪除)操作的方法,我們根本就不用編寫實現類!當應用啟動的時候,Spring DataJPA會在執行期自動生成實現類。這意味著,我們現在就可以在服務層直接設用repository的增刪改查操作了。
/**
* 基於SpringMVC框架開發web應用--資料操作層
*
* @author zhuhuix
* @date 2020-07-07
*/
public interface UserRepository extends CrudRepository<User,Long> { }
服務層repository
  • 接下來我們在UserService層直接呼叫UserRepository中由Spring Data JPA提供的各種方法,實現查詢及增加使用者資訊。
/**
* 基於SpringMVC框架開發web應用--使用者服務類
*
* @author zhuhuix
* @date 2020-07-03
* @date 2020-07-04 增加通過jdbcTemplate處理資料
* @date 2020-07-07 將jdbcTemplate處理資料程式改為Spring Data JPA的處理方式
*/
@Service
public class UserService {
@Autowired
private UserRepository userRepository; // 返回所有的使用者
public List<User> listUsers() {
return (List<User>) userRepository.findAll();
} // 增加使用者
public User saveUser(User user) {
return userRepository.save(user);
} }

再次執行Web應用

  • 我們增加了資料層並修改了UserService服務層;控制器、檢視模板都未做任何改變,接下來我們可以再次嘗試執行一下。開啟瀏覽器並訪問http://localhost:8080/user。

  • 輸入使用者資訊並提交



  • 檢視資料庫使用者資訊表

  • 測試結論:通過將JdbcTemplate替換成Spring Data JPA,同樣實現了使用者資訊的查詢與增加,而且通過JPA CrudRepository介面,我們沒有書寫一行SQL語句,也實現了資料的增加與查詢。

自定義JPA repository

  • 除了CrudRepository提供的基本CRUD操作之外,還需要通過使用者名稱稱或郵箱地址查詢使用者資訊,那我們需要新增如下的方法宣告到UserRepository中:
public interface UserRepository extends CrudRepository<User,Long> {

     // 自定義新增通過使用者名稱稱查詢使用者資訊
List<User> findByName(String name); }

按照Spring Data的規範的規定,查詢方法以find | read | get開頭(比如 find、findBy、read、readBy、get、getBy),涉及查詢條件時,條件的屬性用條件關鍵字連線,要注意的是:條件屬性以首字母大寫。框架在進行方法名解析時,會先把方法名多餘的字首擷取掉,然後對剩下部分進行解析。

直接在介面中定義查詢方法,如果是符合規範的,可以不用寫實現,即不用寫SQL。

服務層增加查詢介面
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
...
// 根據名稱查詢使用者
public List<User> searchUser(String name){
return userRepository.findByName(name);
}
}
控制器增加使用者查詢功能
/**
* 基於SpringMVC框架開發web應用--使用者控制器
*
* @author zhuhuix
* @date 2020-07-03
* @date 2020-07-07 增加使用者查詢
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
...
// 查詢輸入頁面
@GetMapping("/index")
public ModelAndView index(Model model) {
model.addAttribute("user", new User());
return new ModelAndView("index", "userModel", model);
} // 查詢提交併跳轉使用者列表
@PostMapping("/search")
public ModelAndView search(@ModelAttribute User user, Model model) {
model.addAttribute("userList", userService.searchUser(user.getName()));
return new ModelAndView("userlist", "userModel", model);
}
}
檢視層增加使用者查詢頁面
<!-- index.html-->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body> <h3>查詢使用者</h3>
<form action="/users" th:action="@{/user/search}" method="POST" th:object="${userModel.user}">
名稱:<br>
<input type="text" name="name" th:value="*{name}" >
<br>
<input type="submit" value="查詢" >
</form> </body>
</html>
查詢功能測試







使用Spring Data實現資料持久化小結

  • Spring Data JPA能夠極大地簡化JPA持久化,我們只需編寫repository介面即可;
  • Spirng Data 對於實體類可以通過各種註解進行資料的管理:比如@Id ,@Column,@CreationTimestamp等等
  • 只需要符合JPA的介面命名規則,我們可以自定義JPA repository各種對於資料的操作方法:比如findBy... ,findAllBy...,findBy..And..等。

五、使用Spring Security安全框架保護web應用

  • 在前四篇文章中已經實現了一個非常簡單的使用者郵箱登記的web應用,並將資料儲存到mysql資料庫中。但這個web應用涉及的資料展示、查詢及操作都是開放的,如果部署在網際網路上,可以訪問應用的人員都可隨意增加及查詢資料,這顯然是不符合安全要求的。

    作為軟體開發人員,我們必須採取措施來保護應用程式中的資訊。

啟用Spring Security

Spring Security是一個功能強大且高度可定製的身份驗證和訪問控制框架。它是用於保護基於Spring的應用程式的標準。

本文將通過Spring Security配置實現web應用的如下功能:

  • 實現頁面的WEB安全保護
  • 實現管理員的帳戶註冊
  • 實現登入驗證的完整流程
Spring Security的基本登入認證
  • 在pom.xml檔案中新增依賴
<!-- Spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security </artifactId>
</dependency>

通過將security starter新增到專案的構建檔案中,我們得到了如下的安全特性:

  • 所有的HTTP請求路徑都需要認證;
  • 不需要特定的角色和許可權;
  • 沒有登入頁面;
  • 認證過程是通過HTTP basic認證對話方塊實現的;
  • 系統只有一個使用者,使用者名稱為user。

我們試著啟動一下應用,並訪問使用者列表頁面,發現程式竟然跳轉到了一個login登入頁面,並要求輸入使用者和密碼。



這是一個HTTP basic認證對話方塊,提示進行認證。要想通過這個認證,需要一個使用者名稱和密碼。使用者名稱為user,而密碼則是隨機生成的,可以在日誌監控介面上查到:



我們試著在登入介面上輸入使用者名稱user與圖中的密碼,進行認證登入:





程式順利通過了密碼認證,並進入到使用者列表介面。但顯然以上的方式是不符合需求的,我們需要的是:

  • 通過自定義的登入頁面來提示管理員使用者進行認證;
  • 提供一個註冊頁面,新管理員使用者能夠註冊;
  • 對不同的請求路徑,執行不同的安全規則。比如註冊頁面不需要進行認證,其他頁面需要進行認證。

使用Spring Security實現自定義使用者認證

增加管理員實體類
-- ----------------------------
-- Table structure for admin
-- ----------------------------
DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`user_password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
/**
* 基於SpringMVC框架開發web應用--管理員使用者類,用於登入認證
*
* @author zhuhuix
* @date 2020-07-08
*/
@Entity
public class Admin implements UserDetails { // 管理員id
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; @Column(name="user_name")
private String userName; @Column(name="user_password")
private String userPassword; @Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
} @Override
public String getPassword() {
return userPassword;
} @Override
public String getUsername() {
return userName;
} @Override
public boolean isAccountNonExpired() {
return true;
} @Override
public boolean isAccountNonLocked() {
return true;
} @Override
public boolean isCredentialsNonExpired() {
return true;
} @Override
public boolean isEnabled() {
return true;
} public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public void setUserName(String userName) {
this.userName = userName;
} public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
}
  • 管理員類實現了Spring Security的UserDetails介面。通過實現UserDetails介面,我們能夠提供更多資訊給框架,比如使用者都被授予了哪些許可權以及使用者的賬號是否可用。
  • getAuthorities()方法返回使用者被授予許可權的一個集合。各種is…Expired()方法要返回一個boolean值,表明使用者的賬號是否可用或過期。
使用Spring Data JPA定義管理員的持久化介面
/**
* 基於SpringMVC框架開發web應用--管理員資料操作層
*
* @author zhuhuix
* @date 2020-07-08
*/
public interface AdminRepository extends CrudRepository<Admin,Long> { // 根據使用者名稱查詢管理員
Admin findByUserName(String username);
}
建立獲取管理員詳情資訊的服務層
/**
* 基於SpringMVC框架開發web應用--管理員服務層
*
* @author zhuhuix
* @date 2020-07-08
*/
@Service
public class AdminService implements UserDetailsService {
private final Logger logger = LoggerFactory.getLogger(Logger.class);
@Autowired
private AdminRepository adminRepository; @Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Admin admin = adminRepository.findByUserName(s);
if (admin == null) {
logger.error("管理員" + s + "未找到");
throw new UsernameNotFoundException("User " + s + "not found");
}
return admin;
} // 儲存管理員
public Admin save(Admin admin){
return adminRepository.save(admin);
}
}
配置Spring Security
/**
* Spring Security配置類
*
* @author zhuhuix
* @date 2020-07-08
*/ @Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AdminService adminService; @Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder
.userDetailsService(adminService)
.passwordEncoder(new BCryptPasswordEncoder());
} }
測試自定義的登入驗證方法

以上通過建立管理員資訊表,及通過JPA定義資料處理層,編寫獲取管理員資訊的服務實現,最後配置Spring Security Web安全類,實現了自定義的登入驗證方法,下面具體來測試一下:





web應用程式已經實現了自定義的使用者登入驗證。

實現管理員的註冊

  • 以上雖然完成了管理員的登入驗證,但沒有涉及管理員的新增,以下需要完成管理員註冊流程。
管理員註冊控制器
/**
* 基於SpringMVC框架開發web應用--管理員註冊控制器
*
* @author zhuhuix
* @date 2020-07-08
*/
@RestController
@RequestMapping("/admin")
public class AdminController { @Autowired
private AdminService adminService; // 管理註冊頁
@GetMapping
public ModelAndView registerForm(Model model) {
model.addAttribute("admin", new Admin());
return new ModelAndView("registration", "adminModel", model);
} // 提交註冊資訊
@PostMapping("/register")
public ModelAndView save(Admin admin) {
BCryptPasswordEncoder bCryptPasswordEncoder =new BCryptPasswordEncoder();
admin.setUserPassword(bCryptPasswordEncoder.encode(admin.getPassword()));
if (adminService.save(admin) != null) {
return new ModelAndView("redirect:/login ");
} else {
return null;
}
}
}
管理員註冊頁面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<h3>管理員註冊</h3>
<form action="/admin" th:action="@{/admin/register}" method="POST" th:object="${adminModel.admin}">
名稱:<br>
<input type="text" name="userName" th:value="*{userName}" >
<br>
輸入密碼:<br>
<input type="password" name="userPassword" th:value="*{userPassword}">
<br>
<input type="submit" value="註冊" >
</form>
</body>
</html>
配置保護Web請求的安全性規則
  • 以上完成了管理員註冊的業務邏輯、控制層、與頁面檢視,但如果我們直接訪問管理員註冊頁面的時候,web應用程式仍然會跳轉到login頁面,要求輸入使用者名稱和密碼,這顯然不符合需求,我們只需要對需要認證的頁面進行登入驗證保護,對於註冊頁面是開放的,所以我們需要配置保護web請求的安全性規則:
/**
* Spring Security配置類
*
* @author zhuhuix
* @date 2020-07-08
*/ @Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AdminService adminService; // 自定義使用者驗證
@Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(adminService)
.passwordEncoder(new BCryptPasswordEncoder());
} // 保護web請求的安全性規則 @Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/user/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/**").permitAll()
.and().formLogin().defaultSuccessUrl("/user")
.and().httpBasic();
}
}

完整測試

  • 訪問管理員註冊頁面進行註冊



  • 使用註冊的管理員帳戶進行登入驗證



使用Spring Security安全框架保護web應用小結

  • Spring Security的自動配置是實現基本安全性功能的好辦法,但是大多數的應用都需要自定義安全規則,這樣才能滿足特定的安全需求。
  • 認證使用者詳情資訊可以通過自定義使用者儲存機制進行管理,它的後端可以是關係型資料庫。
  • 注意:以上實現功能有不完全處:如管理員註冊時,需在頁面進行密碼的兩次確認,服務層需判斷帳戶名是否存在等,請大家借鑑使用。

六、Spring的配置屬性

  • 本小節將瞭解Spring的配置屬性及完成自定義的配置

Spring的環境抽象(Environment)

Spring的環境抽象是各種配置屬性的一站式服務。它抽取了原始的屬性,這樣需要這些屬性的bean就可以從Spring本身中獲取了。Spring環境會拉取多個屬性源,包括:

  • JVM系統屬性;
  • 作業系統環境變數;
  • 命令列引數;
  • 應用屬性配置檔案。

通過應用屬性配置檔案完成Spring的環境配置

  • 我們回顧下原web應用中的application.properties檔案:
###資料來源配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/user_info?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true #thymelea模板配置
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
  • Spring Boot引入了具有層次關係的yml格式的配置檔案:
spring:
port:8080

顯然具有層次關係的配置檔案更易於理解與書寫,接下來我們將使用application.yml取代application.properties完成各種屬性配置。

配置資料來源
###資料來源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/user_info?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
配置模板引擎
#thymelea模板配置
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML5
encoding: UTF-8
content-type: text/html
cache: false
配置日誌
  • 預設情況下,Spring Boot通過Logback配置日誌,日誌會以INFO級別寫入到控制檯中,我們希望重新配置顯示日誌的格式;
  • 同時我們希望通過監控sql日誌輸出到控制檯,並將輸出的資訊進行篩選列印;
  • 首先需引入log4jdbc依賴
		 <dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
  • 其次生成配置檔案log4jdbc.log4j2.properties:
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.auto.load.popular.drivers=false
log4jdbc.drivers=com.mysql.cj.jdbc.Driver
  • 最後建立一個logback.xml檔案完成配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds" debug="false">
<contextName>web demo</contextName>
<property name="log.charset" value="utf-8" />
<property name="log.pattern" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)" /> <!--輸出到控制檯-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
</appender> <!--普通日誌輸出到控制檯-->
<root level="info">
<appender-ref ref="console" />
</root> <!--監控sql日誌輸出 -->
<logger name="jdbc.sqlonly" level="INFO" additivity="false">
<appender-ref ref="console" />
</logger> <logger name="jdbc.resultset" level="ERROR" additivity="false">
<appender-ref ref="console" />
</logger> <!-- 如想看到表格資料,將OFF改為INFO -->
<logger name="jdbc.resultsettable" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger> <logger name="jdbc.connection" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger> <logger name="jdbc.sqltiming" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger> <logger name="jdbc.audit" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger>
</configuration>
  • 輸出格式如下:

建立自定義的配置屬性

為了支援配置屬性的注入,Spring Boot提供了@ConfigurationProperties註解。將它放到Spring 應用上下文的 bean之後,它就會為該bean中那些能夠根據Spring環境注入值的屬性賦值。

  • 我們希望給管理員註冊時,新增一個應用的預設密碼,假設使用者註冊時,不輸入密碼,web應用就以這個預設密碼進行註冊,並寫入資料庫。
在application.yml中加入配置
#管理員預設密碼
admin:
password: 123456
編寫配置類
  • 使用 @ConfigurationProperties 配置模組
  • 過新增 @Component 註解讓 Component Scan 掃描到
/**
* 基於SpringMVC框架開發web應用--管理員使用者預設金鑰
*
* @author zhuhuix
* @date 2020-07-09
*/
@Component
@ConfigurationProperties(prefix = "admin")
public class DefaultPasswordProperties {
private String password; public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}
使用自定義的配置屬性
/**
* 基於SpringMVC框架開發web應用--管理員註冊控制器
* * @author zhuhuix
* @date 2020-07-08
* @date 2020-07-09 註冊密碼為空時使用自定義的預設密碼屬性
*/
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
private AdminService adminService;
@Autowired
private DefaultPasswordProperties defaultPasswordProperties; // 管理註冊頁
@GetMapping
public ModelAndView registerForm(Model model) {
model.addAttribute("admin", new Admin());
return new ModelAndView("registration", "adminModel", model);
} // 提交註冊資訊
@PostMapping("/register")
public ModelAndView save(Admin admin) {
// 如果註冊密碼為空,則賦值預設密碼
if (StringUtils.isEmpty(admin.getPassword())) {
admin.setUserPassword(defaultPasswordProperties.getPassword());
}
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
admin.setUserPassword(bCryptPasswordEncoder.encode(admin.getPassword()));
if (adminService.save(admin) != null) {
return new ModelAndView("redirect:/login ");
} else {
return null;
}
}
}
屬性配置測試
  • 註冊admin2管理員,密碼保持為空,並提交





  • 用admin2管理員,密碼為123456進行登入

  • 登入成功

Spring的配置屬性小結

  • Spring的配置屬性可以通過命令列引數、環境變數、JVM系統屬性、屬性檔案或YAML檔案等方式進行設定。
  • Spring的配置屬性可以用來覆蓋自動配置相關的設定,包括指定資料來源URL和日誌級別。
  • Spring的配置屬性可以新增@ConfigurationProperties註解,這樣就能夠從多個屬性源中選取一個來注入它的值。

七、Spring整合REST API服務

本節將進入到新的單元:Spring與應用的整合,今天先實現整合REST API服務。

REST API服務

微服務架構,前後端分離目前已成為網際網路專案開發的業界標準,其核心思想就是前端(APP、小程式、H5頁面等)通過呼叫後端的API介面,提交及返回JSON資料進行互動。

  • 移動裝置、平板電腦、智慧裝置已經非常常見,許多應用程式採用了一種通用的設計,那就是將使用者介面推到更接近客戶端的地方,而讓伺服器公開API,通過這種API,各種客戶端都能與後端功能進行互動。
  • REST API(REpresentation State Transfer Application Programming Interface):通過URL定位資源,用HTTP動詞(GET,POST,DELETE,PUSH等)描述操作,與後端服務進行互動。

Spring整合REST API服務

  • 在前幾篇文章中我們用了模板引擎開發了多頁應用(MultiPage Application,MPA),我們將在原有基礎上按以下步驟實現整合API服務:

  • 建立使用者管理的Restful Api(UserRestfulApi.java)的介面,實現增加、刪除、修改、查詢使用者資訊的API互動服務;

  • 整合Swagger2,對上述API介面進行測試。

用Spring MVC實現使用者管理Restful Api
  • Controller
/**
* 基於SpringMVC框架開發web應用--使用者restful api
* 增加、刪除、修改、查詢使用者資訊的API互動服務
*
* @author zhuhuix
* @date 2020-07-10
*/
@RestController
@RequestMapping("/user/api")
public class UserRestfulApi {
@Autowired
private UserService userService; // 增加使用者資訊
@PostMapping
public ResponseEntity<User> addUser(User user) {
return ResponseEntity.ok(userService.saveUser(user));
} // 根據id刪除使用者
@DeleteMapping("/{id}")
public ResponseEntity deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.ok(HttpStatus.OK);
} // 根據id修改使用者
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@RequestBody User user) {
return ResponseEntity.ok(userService.saveUser(user));
} // 根據id查詢使用者
@GetMapping("/{id}")
public ResponseEntity<User> findUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.findUser(id));
}
}
  • Service
/**
* 基於SpringMVC框架開發web應用--使用者服務類
*
* @author zhuhuix
* @date 2020-07-03
* @date 2020-07-04 增加通過jdbcTemplate處理資料
* @date 2020-07-07 將jdbcTemplate處理資料程式改為Spring Data JPA的處理方式
* @date 2020-07-10 增加
*/
@Service
public class UserService {
@Autowired
private UserRepository userRepository; // 返回所有的使用者
public List<User> listUsers() {
return (List<User>) userRepository.findAll();
} // 儲存使用者
public User saveUser(User user) {
return userRepository.save(user);
} // 刪除使用者
public void deleteUser(Long id){
userRepository.deleteById(id);
} // 查詢使用者
public User findUser(Long id){
return userRepository.findById(id).get();
} // 根據名稱查詢使用者
public List<User> searchUser(String name){
return userRepository.findByName(name);
} }
  • Repository
/**
* 基於SpringMVC框架開發web應用--資料操作層
*
* @author zhuhuix
* @date 2020-07-07
*/
public interface UserRepository extends CrudRepository<User,Long> { // 自定義新增通過使用者名稱稱查詢使用者資訊
List<User> findByName(String name); }
Spring 整合Swagger2

Swagger2 作為一個規範和完整的框架,可以用於生成、描述、呼叫和視覺化 RESTful 風格的 Web 服務:

1、 介面檔案線上自動生成,檔案隨介面變動實時更新,節省維護成本

2、 支援線上介面測試,不依賴第三方工具

  • 新增maven依賴
 <!-- RESTful APIs swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
  • 建立 Swagger2配置類
/**
* Swagger2配置類
*
* @author zhuhuix
* @date 2020-07-10
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
@SuppressWarnings("all")
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.select()
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build();
} private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Restful Api介面測試")
.version("1.0")
.build();
}
}

API介面進行測試
  • 在測試之前,為防止post、put、delete請求出現 403 Forbidden ,需要禁用跨域請求的安全驗證
/**
* Spring Security配置類
*
* @author zhuhuix
* @date 2020-07-08
* @date 2020-07-10 禁用跨域請求的安全驗證
*/ @Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AdminService adminService; // 自定義使用者驗證
@Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(adminService)
.passwordEncoder(new BCryptPasswordEncoder());
} // 保護web請求的安全性規則 @Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/user/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/**").permitAll()
.and().formLogin().defaultSuccessUrl("/user")
.and().httpBasic()
// 禁用 CSRF
.and().csrf().disable();
}
}
增加使用者(HTTP POST請求)





查詢使用者(HTTP GET請求)





修改使用者(HTTP PUT請求)





刪除使用者(HTTP DELETE請求)





Spring整合REST API服務小結

至此我們完成了Spring整合restful api服務,並通過整合Swagger2,簡單直觀地對http的各種請求進行了完整地測試,下面做個總結:

  • Rest端點可以通過Spring MVC來建立,這裡的控制器與面向瀏覽器的控制器遵循相同的程式設計模型。
  • @RestController註解簡化了REST控制器,使用它的話,處理器方法中就不需要新增@ResponseBody註解了。
  • Restful Api一般會新增JWT認證機制進行安全驗證,具體可參見《SpringBoot整合SpringSecurity實現JWT認證》。