Vue + Spring Boot 專案實戰(四):資料庫的引入

Evan-Nightly發表於2019-04-14

這一篇的主要內容是引入資料庫並實現通過資料庫驗證使用者名稱與密碼。

一、引入資料庫

之前說過資料庫的採用是 MySQL,算是比較主流的選擇,從效能和體量等方面都比較優秀,當然也有一些弊端,但資料庫不是我們這裡討論的重點,暫時能用就行。

1.安裝資料庫

我的 MySQL 版本是 5.7,官方下載頁面是
https://dev.mysql.com/downloads/mysql/5.7.html#downloads

安裝教程我隨便搜了一篇,可以參考
https://blog.csdn.net/ma524654165/article/details/77855431

目前最新的版本是 8.0,也可以下載最新版本,使用最新版本需要做三處修改:
一、修改後端專案 pom.xml 的 mysql 依賴配置
二、為資料庫設定一個長密碼,而不能用簡單的 admin
三、修改 mysql 的時區為 +8:00

操作 MySQL 有很多種方式,可以用官方的 Command Line Client、Workbench,也可以用其它的一些介面化軟體,比如 Navicat 等。如果之前沒有接觸過資料庫,可以先用 Navicat,比較直觀。安裝方法參照這個博文:
https://blog.csdn.net/wypersist/article/details/79834490
我真是個好人啊,到處推薦別人的文章。。。

2.使用 Navicat 建立資料庫與表

下面的內容主要針對初次使用資料庫的讀者,有經驗的讀者可以直接執行下面的 sql 語句,記得先新建一個資料庫,名稱最好叫 white_jotter,方便以後的配置。

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admin', '123');

按照上面貼出來的教程安裝完 MySQL 和 Navicat 後,開啟 Navicat,點選連線 -> MySQL,新建資料庫連線
在這裡插入圖片描述
在彈出的介面中配置相關資訊,如果之前安裝資料庫是按照上面的教程來的話,連線名隨便起一個,主機名、埠、使用者名稱都不用修改,密碼是 root,其實我習慣設定成 admin,但看上面的教程是 root,這個專案無所謂,但記住實際的專案千萬不要設定這麼簡單的密碼,有不少企業的資料庫密碼還真就是 admin,被脫褲了才反應過來。。。

輸入之後可以點選測試連線按鈕測試一下,然後確定。
在這裡插入圖片描述
雙擊在左側出現的連線 WJ,就開啟了這個連線。安裝完 MySQL 會有幾個預設的資料庫,這些不要動,我們在連線(即 WJ)上右鍵新建一個資料庫,命名為 white_jotter,字符集選擇 UTF-8,排序規則選擇 utf8_general_ci 即可。
在這裡插入圖片描述
建立之後左側就會出現一個名為 white_jotter 的資料庫,雙擊它,點選“表”,然後點選“新建表”按鈕,就進入了表設計介面。

為了完成登入驗證,我們需要一個使用者表,一般命名為 user,表裡面暫定設計 3 個欄位,分別是 id、username、password。

表設計介面預設有一個“欄位”,我們可以在這個欄位中加入第一個需要的欄位,即使用者的 id,其設定如下
在這裡插入圖片描述
箭頭指向的地方不要漏了。最後那把小鑰匙的意思是主鍵,可以點選上面的主鍵按鈕或者直接點選這個空白的欄位設定。

然後再新增第二、三個欄位,配置如下:
在這裡插入圖片描述
在這裡插入圖片描述
最後點選儲存,把表命名為 user,這樣我們就有了第一張表。之後也可以在物件介面中選中表並點選“設計表”按鈕重新設計。

接下來,我們雙擊 user 表,進入表中,新增一行使用者資訊,id 為 1,賬號是 admin,密碼是 123,也可以隨便按照自己喜好新增。
在這裡插入圖片描述
可以看到下面自動執行了一條 SQL 語句。這裡多說一句,真實的專案中,使用者資訊可不能這麼存,直接把賬號密碼寫上去太危險了,一般的做法是儲存密碼等資訊的 hash 值。

OK,到現在為止,資料庫的操作就完成了。

二、使用資料庫驗證登入

上一篇中我們直接在後端的控制器中用如下語句判斷了使用者名稱和密碼的正確性:

if (!Objects.equals("admin", username) || !Objects.equals("123456", requestUser.getPassword())) {
            String message = "賬號密碼錯誤";
            System.out.println("test");
            return new Result(400);
        } else {
            return new Result(200);
        }

使用資料庫驗證的邏輯其實也類似,大概是如下過程:

第一步,獲得前端傳送過來的使用者名稱和密碼資訊
第二步,查詢資料庫中是否存在相同的一對使用者名稱和密碼
第三步,如果存在,返回成功程式碼(200),如果不存在,返回失敗程式碼(400)

這裡的語句很簡單,但在修改之前還需要一些準備工作。

1.專案相關配置

開啟我們的後端專案 wj,首先修改 pom.xml,配置我們需要的依賴。為了方便以後的開發,我直接把我的配置貼上上來,大家可以把原來的所有配置刪除掉,再貼上我的。

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.evan</groupId>
	<artifactId>wj</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>wj</name>
	<description>White Jotter - Your Mind Palace</description>
	<packaging>war</packaging>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<dependencies>
		<!-- springboot web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springboot tomcat 支援 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<!-- 熱部署 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- jpa-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<!-- redis -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<!-- springboot test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- thymeleaf -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- elastic search -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
		</dependency>
		<!-- 用了 elasticsearch 就要加這麼一個,不然要com.sun.jna.Native 錯誤 -->
		<dependency>
			<groupId>com.sun.jna</groupId>
			<artifactId>jna</artifactId>
			<version>3.0.9</version>
		</dependency>

		<!-- thymeleaf legacyhtml5 模式支援 -->
		<dependency>
			<groupId>net.sourceforge.nekohtml</groupId>
			<artifactId>nekohtml</artifactId>
			<version>1.9.22</version>
		</dependency>
		<!-- 測試支援 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<!-- tomcat的支援.-->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<version>8.5.23</version>
		</dependency>
		<!-- mysql-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.21</version>
		</dependency>

		<!-- junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version> 4.12</version>
		</dependency>
		<!-- commons-lang -->
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>
		<!-- shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.3.2</version>
		</dependency>
		<!-- hsqldb -->
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
		</dependency>
	</dependencies>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

貼上過去之後,IDE 會彈出提示,點選 Import Changes 或 Enable Auto-Import 都可以。
在這裡插入圖片描述
接下來就等待依賴的自動安裝。過程可能比較長。如果自動安裝的過程沒有執行,可以在 pom.xml 上右鍵,選擇 Maven -> Reimport 。

配置完依賴後,還需要配置資料庫。開啟 src\main\resources\application.properties ,在原來的基礎上,新增如下語句

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/white_jotter?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto = none

注意埠、資料庫名、使用者名稱、密碼要與你想使用的資料庫一致。

2.登入控制器

配置完成後,我們就可以完善登入控制器了。

User 類

首先,我們修改 User 類程式碼如下,以建立對資料庫的對映。

package com.evan.wj.pojo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;

@Entity
@Table(name = "user")
@JsonIgnoreProperties({"handler","hibernateLazyInitializer"})

public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    int id;

    String username;
    String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

上面使用了一些註解,其中

@Entity 表示這是一個實體類
@Table(name=“user”) 表示對應的表名是 user

為了簡化對資料庫的操作,我們使用了 Java Persistence API(JPA),對於 @JsonIgnoreProperties({ “handler”,“hibernateLazyInitializer” }),解釋起來比較複雜,下面的話看不懂可以忽略:

因為是做前後端分離,而前後端資料互動用的是 json 格式。 那麼 User 物件就會被轉換為 json 資料。 而本專案使用 jpa 來做實體類的持久化,jpa 預設會使用 hibernate, 在 jpa 工作過程中,就會創造代理類來繼承 User ,並新增 handler 和 hibernateLazyInitializer 這兩個無須 json 化的屬性,所以這裡需要用 JsonIgnoreProperties 把這兩個屬性忽略掉。

UserDAO

Data Access Object(資料訪問物件,DAO)即用來運算元據庫的物件,這個物件可以是我們自己開發的,也可以是框架提供的。這裡我們通過繼承 JpaRepository 的方式構建 DAO。

首先新建一個 package,命名為 dao,然後建立 Java Class,命名為 UserDAO,選擇種類為 Interface
在這裡插入圖片描述
程式碼如下

package com.evan.wj.dao;

import com.evan.wj.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserDAO extends JpaRepository<User,Integer> {
    User findByUsername(String username);

    User getByUsernameAndPassword(String username,String password);
}

這裡關鍵的地方在於方法的名字。由於使用了 JPA,無需手動構建 SQL 語句,而只需要按照規範提供方法的名字即可實現對資料庫的增刪改查。

findByUsername,就是通過 username 欄位查詢到對應的行,並返回給 User 類。

這裡我們構建了兩個方法,一個是通過使用者名稱查詢,一個是通過使用者名稱及密碼查詢。

UserService

新建 package,命名為 service,新建 Java Class,命名為 UserService,程式碼如下

package com.evan.wj.service;

import com.evan.wj.dao.UserDAO;
import com.evan.wj.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Autowired
    UserDAO userDAO;

    public boolean isExist(String username) {
        User user = getByName(username);
        return null!=user;
    }

    public User getByName(String username) {
        return userDAO.findByUsername(username);
    }

    public User get(String username, String password){
        return userDAO.getByUsernameAndPassword(username, password);
    }

    public void add(User user) {
        userDAO.save(user);
    }
}

這裡實際上是對 UserDAO 進行了二次封裝,一般來講,我們在 DAO 中只定義基礎的增刪改查操作,而具體的操作,需要由 Service 來完成。當然,由於我們做的操作原本就比較簡單,所以這裡看起來只是簡單地重新命名了一下,比如把 “通過使用者名稱及密碼查詢並獲得物件” 這種方法命名為 get

LoginController

登入控制器是我們功能的核心部分,儘管它十分簡單。邏輯上面已經講過了,具體的實現,就是通過 UserService 提供的 get 方法查詢資料庫,如果返回的物件為空,則驗證失敗,否則就驗證成功。程式碼如下

package com.evan.wj.controller;

import com.evan.wj.pojo.User;
import com.evan.wj.result.Result;
import com.evan.wj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.HtmlUtils;

@Controller
public class LoginController {

    @Autowired
    UserService userService;

    @CrossOrigin
    @PostMapping(value = "/api/login")
    @ResponseBody
    public Result login(@RequestBody User requestUser) {
        String username = requestUser.getUsername();
        username = HtmlUtils.htmlEscape(username);

        User user = userService.get(username, requestUser.getPassword());
        if (null == user) {
            return new Result(400);
        } else {
            return new Result(200);
        }
    }
}

這個沒有其它要說的,忘記了怎麼回事的話可以回過頭看下上一篇文章
Vue.js + Spring Boot 前後端分離專案實踐(三):前後端結合測試(登入頁面開發)

我們的專案會在很長一段時間內採取這種簡單的三層架構(DAO + Service + Controller),希望大家能慢慢體會這三個模組的分工。這裡我簡單總結一下,先有個初步印象:

  • DAO 用於與資料庫的直接互動,定義增刪改查等操作
  • Service 負責業務邏輯,跟功能相關的程式碼一般寫在這裡,編寫、呼叫各種方法對 DAO 取得的資料進行操作
  • Controller 負責資料互動,即接收前端傳送的資料,通過呼叫 Service 獲得處理後的資料並返回

在實踐中我們傾向於讓 Controller 顯得清涼一些,以方便程式碼的閱讀者尋找分析功能的入口。但由於教程中各個層的迭代並不是同步的,可能會暫時捨棄這個原則,後期會逐漸重構。

3.測試

同時執行前端專案 wj-vue 與後端專案 wj,訪問 http://localhost:8080/#/login,輸入使用者名稱 admin,密碼 123456,我去,沒進去!沒進去就對了,因為資料庫中 admin 的密碼式 123 啊。

重新輸入密碼 123,成功進入 localhost:8080/#/index
在這裡插入圖片描述
OK,截至目前,前後端、資料庫之間的關係都打通了。下一篇我打算講講怎麼做表面功夫,即通過 Element 優化前端的介面。

檢視系列文章目錄:
https://learner.blog.csdn.net/article/details/88925013

上一篇:Vue + Spring Boot 專案實戰(三):前後端結合測試(登入頁面開發)

下一篇:Vue + Spring Boot 專案實戰(五):使用 Element 輔助前端開發

相關文章