用戶登錄前後端分離開發實戰案例:React,npm,webpack,ES6, Kotlin, Spring Boot, Gradle, Freemarker, Material UI
本章通過一個簡單用戶登錄模塊全棧開發案例,從前端 React工程的創建、開發,到後端 Spring Boot + Kotlin + Gradle工程的創建,使用 Spring Data JPA 來操作 MySQL數據庫, 使用Freemarker視圖引擎,從前往後完整的講解整個開發過程。
前端 React 工程開發
環境準備
本節實例工程的運行環境和技術棧相關清單如下:
運行環境準備:Node
開發工具 IDE:WebStorm
瀏覽器:Chrome
框架和組件庫:react, babel,jquery, material-ui
構建工具:webpack
我們用 webpack + es6 來結合 react 開發前端應用。本章中,我們手動使用npm來安裝各種插件,來從頭到尾自己搭建環境。當然,在實際的項目開發中,已經有大神們開發好了腳手架,例如 create-react-app(https://github.com/facebook/create-react-app),我們直接使用腳手架就可以了。爲了保持技術細節的原汁原味,我們本章先來帶領大家一步一步地來手工搭建 webpack + es6 的 React前端開發工程。
使用npm搭建React的webpack環境
本節我們來介紹如何通過 npm一步一步創建 React前端工程。我們通過Webpack打包構建React工程。
安裝配置Webpack環境
我們主要來安裝react react-dom babel等npm包,設置webpack.config.js,打包輸出bundle.js。
安裝Webpack
1.創建項目文件夾
mkdir simple-login
新建 simple-login 文件夾,在此文件夾內進行webpack本地安裝。
2.npm初始化
$ npm init -y Wrote to /Users/jack/spring-boot-book/chapter03/front-end/simple-login/package.json: { "name": "simple-login", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
初始化,目錄下生成一個 package.json
文件,內容如上。
3.安裝 webpack
WebPack是什麼:https://github.com/webpack/webpack-cli
npm install --save-dev webpack
安裝成功後 simple-login 目錄中會出現node_modules 目錄 。
注意:不推薦使用全局安裝npm install --global webpack
我們可以看到 .bin 目錄下面的webpack腳本:
image
打開腳本看到源碼如下:
#!/usr/bin/env node process.exitCode = 0; /** * @param {string} command process to run * @param {string[]} args commandline arguments * @returns {Promise<void>} promise */ const runCommand = (command, args) => { const cp = require("child_process"); return new Promise((resolve, reject) => { const executedCommand = cp.spawn(command, args, { stdio: "inherit", shell: true }); executedCommand.on("error", error => { reject(error); }); executedCommand.on("exit", code => { if (code === 0) { resolve(); } else { reject(); } }); }); }; ...
通過腳本中的
#!/usr/bin/env node
我們即可知道,這是一個使用 node運行環境執行的一個 js。此時,我們 package.json 文件中在devDependencies 下面多了一行 webpack 包的依賴:
{ "name": "simple-login", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.25.1" } }
安裝依賴包
使用 npm install 命令繼續安裝 react react-dom babel 等依賴包:
npm install --save react react-dom npm install --save-dev babel-core babel-loader babel-preset-react babel-preset-es2015
本地安裝的webpack命令爲: ./node_modules/.bin/webpack
我們可以通過打開 package.json
,在 "scripts": {}
中加入"start": "webpack" ,用 npm start
命令代替 webpack命令。
這個時候,我們的 package.json 文件內容變成了
{ "name": "simple-login", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^8.0.4", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "webpack": "^4.25.1" }, "dependencies": { "react": "^16.6.1", "react-dom": "^16.6.1" } }
這裏的 babel-loader:8.0.4跟babel-core:6.26.3 版本不兼容,我們改成 "babel-loader": "^7.1.5" 。
可以看到,babel、webpack依賴被放到了 devDependencies 中,react 依賴被放到了 dependencies中。那 package.json 文件裏面的 devDependencies 和 dependencies 對象有什麼區別呢?
devDependencies和dependencies的區別
我們在使用npm install 安裝模塊或插件的時候,有兩種命令把他們寫入到 package.json 文件裏面去,比如:
--save-dev --save
在 package.json 文件裏面提現出來的區別就是,使用 --save-dev 安裝的 插件,被寫入到 devDependencies 對象裏面去,而使用 --save 安裝的插件,則被寫入到 dependencies 對象裏面去。
devDependencies 裏面的插件只用於開發環境,不用於生產環境。而 dependencies 是需要發佈到生產環境的。
配置webpack
創建項目文件,最終結構如下:
image
文件說明如下:
- app/index.js 入口文件
- dist 用於盛放webpack打包輸出的bundle.js
- webpack.config.js 用於配置webpack環境。
編寫webpack.config.js配置文件
const path = require('path'); module.exports = { entry: "./app/index.js", //入口文件 output: { path: path.join(__dirname, "/dist/"), // 所有輸出文件的目標路徑,絕對路徑! filename: "bundle.js" }, module: { rules: [ { test: /\.js$/, //babel-loader將其他文件解析爲js文件 exclude: /node_modules/, loader: "babel-loader", options: { presets: ["es2015", "react"] //babel-loader需要解析的文件 } } ] } };
webpack 開箱即用,可以無需使用任何配置文件。然而,webpack 會假定項目的入口起點爲 src/index
,然後會在 dist/main.js
輸出結果,並且在生產環境開啓壓縮和優化。
通常,你的項目還需要繼續擴展此能力,爲此你可以在項目根目錄下創建一個 webpack.config.js
文件,webpack 會自動使用它。
更多關於 webpack的配置說明參考:https://webpack.github.io/
package-lock.json的作用
我們有看到上面的目錄中,多了一個package-lock.json文件。這個文件是幹嘛用的呢?其實用一句話來概括很簡單,就是鎖定安裝時的包的版本號,並且需要上傳到git,以保證其他人在npm install時大家的依賴能保證一致。
根據官方文檔,這個package-lock.json 是在 npm install
時候生成一份文件,用以記錄當前狀態下實際安裝的各個npm package的具體來源和版本號。它有什麼用呢?因爲npm是一個用於管理package之間依賴關係的管理器,它允許開發者在pacakge.json中間標出自己項目對npm各庫包的依賴。你可以選擇以如下方式來標明自己所需要庫包的版本。
這裏舉個例子:
"dependencies": { "@types/node": "^8.0.33", }
這裏面的向上標號^是定義了向後兼容依賴,指如果 types/node的版本是超過8.0.33,並在大版本號(8)上相同,就允許下載最新版本的 types/node庫包,例如實際上可能運行npm install時候下載的具體版本是8.0.35。
編寫React組件 App.js
代碼如下:
var React = require('react'); export default class App extends React.Component { render() { // Every react component has a render method. let now = new Date(); let datetimeString =`${now.toDateString()} ${now.toTimeString()}`; return ( // Every render method returns jsx. Jsx looks like HTML, but it's actually javascript and functions a lot like xml, with self closing tags requiring the `/` within the tag in order to work propperly <h1> Hello World, Now Time is {datetimeString} </h1> ); } }
其中,var React = require('react') 是引入 react 包。我們的App類繼承自React.Component。每個 React Component 都必須要有一個 render() 函數,該函數返回一個 JSX 對象。
在render() 函數中,我們實現了一個簡單的 App 組件:給世界問好,並展示當前的時間。
編寫index.js和index.html文件
我們在 index.js 中引入我們上面的 App組件,代碼如下:
import App from "./components/App"; var ReactDOM = require('react-dom'); ReactDOM.render( <App/>, document.getElementById('App') );
其中,元素 id = 'App' 是我們下面在index.html 中指定的 div 。
在 index.html中引用 webpack 打包生成的bundle.js, 代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>Hello React!</title> </head> <body> <div id="App"></div> <script src="dist/bundle.js"></script> <!--引用webpack打包輸出的bundle.js--> </body> </html>
執行webpack命令
我們使用 npm start 來執行 webpack打包動作,我們看到在dist目錄一下生成了一個bundle.js文件。然後,直接打開index.html 看到頁面效果:
Hello World, Now Time is Sat Nov 10 2018 12:49:10 GMT+0800 (中國標準時間)
使用 React前端組件庫 Material-UI
簡介
React Material-UI (https://github.com/mui-org/material-ui)是一組實現了谷歌 Material Design 設計語言的 React 組件。它在 GitHub 上的 Star 數> 4w,fork>8k,可能是最受歡迎的 React 組件庫了,目前最新版本是 v3.4.0。
安裝
下面我們來一步一步安裝Material-UI——這個世界上最受歡迎的React UI框架。Material-UI 可作爲 npm 包使用。
安裝核心依賴
npm install @material-ui/core
等待依賴安裝完畢,我們可以看到,此時我們的package.json文件內容新增了 "@material-ui/core": "^3.4.0" 的依賴:
"dependencies": { "@material-ui/core": "^3.4.0", "react": "^16.6.1", "react-dom": "^16.6.1" }
爲了使用預構建的SVG Material icons,例如在組件演示中找到的那些, 須先安裝 @material-ui/icons包:
npm install @material-ui/icons
詳細使用參考:https://material-ui.com/getting-started/installation/
開發一個簡單的登陸表單
下面我們就來使用Material UI組件庫,來開發一個簡單的登陸表單頁面。這個表單頁面的最終效果如下圖:
image
使用 Card 佈局
import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent';
使用表單 FormControl
import FormControl from '@material-ui/core/FormControl'; import Input from '@material-ui/core/Input'; import InputLabel from '@material-ui/core/InputLabel';
使用 Button 按鈕
import Button from '@material-ui/core/Button';
使用 prop-types
我們使用 prop-types 第三方庫對組件的props中的變量進行類型檢測。安裝命令:
$ npm install prop-types
最終,登陸頁面的 js組件類的代碼如下:
class LoginForm extends React.Component { render() { const {classes} = this.props; return ( <div className={classes.loginForm}> <Card className={classes.cardHeight}> <CardContent> <FormControl className={classes.formControl}> <InputLabel>用戶名</InputLabel> <Input id="username"/> </FormControl> <FormControl className={classes.formControl}> <InputLabel>密碼</InputLabel> <Input id="password" type='password'/> </FormControl> <div className={classes.inlineButton}> <Button variant="contained" color="primary" className={classes.button}> 登陸 </Button> <Button variant="contained" className={classes.button}> 重置 </Button> </div> </CardContent> </Card> </div> ) } }
登陸按鈕事件處理
登陸按鈕的前端代碼如下:
<Button onClick={this.handleClick} variant="contained" color="primary" className={classes.button}> 登陸 </Button>
其中,onClick 事件綁定當前LoginForm 類的handleClick 函數,代碼如下:
handleClick(event) { console.log(event.currentTarget); const username = document.getElementById('username').value const password = document.getElementById('password').value console.log({ username: username, password: password }) };
這樣我們可以在登陸頁面,輸入用戶名、密碼:
image
點擊“登陸”,可以看到控制檯的輸出:
image
簡單前端表單校驗
通常,我們會在前端頁面對用戶輸入做一些合理性校驗。例如,我們添加對用戶名長度>3的校驗。首先,監聽用戶的表單輸入函數是 onChange, 用戶名錶單的 JSX代碼如下:
<FormControl className={classes.formControl}> <InputLabel>用戶名</InputLabel> <Input id="username" onChange={this.handleUsernameChange} autoFocus={true}/> <FormHelperText id="component-helper-text">{this.state.helperText}</FormHelperText> </FormControl>
使用 FormHelperText 組件來提示用戶輸入的校驗結果。顯示的 helperText 存儲在 state 中。
其中,handleUsernameChange函數的代碼如下:
handleUsernameChange(event) { console.log(event.currentTarget); if (event.currentTarget.value.length < 3) { this.setState({ // 更新 helperText 提示文本 helperText: '用戶名長度不得小於3' }) } else { this.setState({ helperText: '' }) } };
爲了能夠在JSX代碼中,可以直接使用onChange={this.handleUsernameChange}這樣的語法:
<Input id="username" onChange={this.handleUsernameChange} autoFocus={true}/>
同時能夠在handleUsernameChange()函數中使用 this.setState({...}) , 我們需要在構造函數提前綁定 this:
constructor(props) { super(props); this.state = { helperText: '' }; // 這邊綁定是必要的,這樣 `this` (代表 LoginForm) 才能在回調函數中使用,例如:this.setState this.handleClick = this.handleClick.bind(this); this.handleUsernameChange = this.handleUsernameChange.bind(this); }
這樣,我們在輸入用戶名的過程中,會看到實時提示:
image
表單提交函數編寫
這裏我們使用熟悉的 jquery的 ajax 來進行登陸表單的提交。首先,安裝 jquery依賴如下:
$ npm install jquery --save
安裝完畢,我們可以在 package.json 中多了 "jquery": "^3.3.1" 。
下面,我們來使用 ajax 寫登陸 Post 請求。
引入 jquery
首先,我們在LoginForm.js文件頭部 import jquery,代碼如下:
import $ from 'jquery'
登陸 Post代碼
下面就是寫一個普通的 ajax POST請求的代碼。
handleClick(event) { console.log(event.currentTarget); const username = document.getElementById('username').value const password = document.getElementById('password').value const data = { username: username, password: password }; console.log(data); $.ajax({ url: '/login.json', data: data, type: 'POST', success: (res) => { console.log(data) }, error: (err) => { console.log(err) } }); };
在瀏覽器 console中測試運行,我們可以看到 POST請求已經成功的發出了:
image
只不過,我們還沒有後端的 HTTP接口/login.json 來接收這個請求。所以,我們看到的是404 Not Found。這種軟件開發的方法,我們可以稱之爲“前端驅動後端開發”。
前端核心組件 LoginForm.js的完整源代碼如下:
import React from 'react'; import PropTypes from 'prop-types'; import {withStyles} from '@material-ui/core/styles'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import Button from '@material-ui/core/Button'; import FormControl from '@material-ui/core/FormControl'; import Input from '@material-ui/core/Input'; import InputLabel from '@material-ui/core/InputLabel'; import FormHelperText from "@material-ui/core/es/FormHelperText/FormHelperText"; import $ from 'jquery' const styles = theme => ({ container: { display: 'flex', flexWrap: 'wrap', }, button: { margin: theme.spacing.unit, }, formControl: { margin: theme.spacing.unit, display: 'flex', }, loginForm: { textAlign: 'center', }, inlineButton: { display: 'inline-flex' }, cardHeight: { height: '360px' } }); class LoginForm extends React.Component { constructor(props) { super(props); this.state = { helperText: '' }; // 這邊綁定是必要的,這樣 `this` (代表 LoginForm) 才能在回調函數中使用,例如:this.setState this.handleClick = this.handleClick.bind(this); this.handleUsernameChange = this.handleUsernameChange.bind(this); } handleClick(event) { console.log(event.currentTarget); const username = document.getElementById('username').value const password = document.getElementById('password').value const data = { username: username, password: password }; console.log(data); $.ajax({ url: '/login.json', data: data, type: 'POST', success: (res) => { console.log(data) }, error: (err) => { console.log(err) } }); }; handleUsernameChange(event) { console.log(event.currentTarget); if (event.currentTarget.value.length < 3) { this.setState({ helperText: '用戶名長度不得小於3' }) } else { this.setState({ helperText: '' }) } }; render() { const {classes} = this.props; return ( <div className={classes.loginForm}> <Card className={classes.cardHeight}> <CardContent> <FormControl className={classes.formControl}> <InputLabel>用戶名</InputLabel> <Input id="username" onChange={this.handleUsernameChange} autoFocus={true}/> <FormHelperText id="component-helper-text">{this.state.helperText}</FormHelperText> </FormControl> <FormControl className={classes.formControl}> <InputLabel>密碼</InputLabel> <Input id="password" type='password'/> </FormControl> <div className={classes.inlineButton}> <Button onClick={this.handleClick} variant="contained" color="primary" className={classes.button}> 登陸 </Button> <Button variant="contained" className={classes.button}> 重置 </Button> </div> </CardContent> </Card> </div> ) } } LoginForm.propTypes = { classes: PropTypes.object.isRequired, }; export default withStyles(styles)(LoginForm);
下面,我們就來開始後端工程的開發。
後端 Web 工程開發
本節主要介紹簡單用戶登錄模塊的後端工程的開發。
環境準備
本節實例工程的運行環境和技術棧相關清單如下:
運行環境:JDK 8
編程語言:Java、Kotlin
Web 開發框架:Spring MVC,Spring Boot
ORM框架:Spring Data JPA
數據庫:MySQL,客戶端工具 mysql workbench
視圖模板引擎:Freemarker
開發 IDE: IDEA
創建 Spring Boot工程
接下來,我們創建一個使用 Kotlin編程語言,Gradle 來構建項目的 Spring Boot工程。瀏覽器訪問:https://start.spring.io/ 創建工程如下圖所示:
image
選擇 Gradle Project,Kotlin編程語言,選擇 Spring Boot 2.1.0 版本,然後在項目基本信息中,分別填入 Group、Artifact,起步依賴選擇:Web,MySQL,JPA,Freemarker。 點擊“Generate Project”,下載自動生成的樣板工程,解壓,導入到 IDEA中。
構建項目
打開 IDEA,點擊 Open
image
選擇剛纔自動生成的樣板工程的根目錄
image
點擊“Open”,進入到 Import Project from Gradle界面:
image
如上圖勾選,其中 Gradle 安裝包的根目錄是:/Users/jack/soft/gradle-5.0-rc-1(這個需要根據自己的機器上的目錄自己指定)。點擊“OK”,進入到IDEA項目主界面,耐心等待項目構建完成,我們將看到如下的項目目錄結構:
image
修改 maven 中央倉庫地址
國外的 maven中央倉庫國內訪問起來比較慢,改用阿里雲提供的中央倉庫鏡像。在build.gradle中添加阿里雲倉庫鏡像的地址如下:
repositories { maven { url 'https://maven.aliyun.com/repository/central' } mavenCentral() }
build.gradle 配置文件
我們可以看到在工程的依賴:
dependencies { implementation('org.springframework.boot:spring-boot-starter-data-jpa') implementation('org.springframework.boot:spring-boot-starter-freemarker') implementation('org.springframework.boot:spring-boot-starter-web') implementation('com.fasterxml.jackson.module:jackson-module-kotlin') implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlin:kotlin-reflect") runtimeOnly('mysql:mysql-connector-java') testImplementation('org.springframework.boot:spring-boot-starter-test') }
Spring Boot工程的入口類
我們可以看到,在 Spring Boot工程中,使用@SpringBootApplication註解標註 main 程序。
package com.easy.springboot.simpleloginbackend import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication class SimpleLoginBackEndApplication fun main(args: Array<String>) { runApplication<SimpleLoginBackEndApplication>(*args) }
這個時候,我們直接運行這個 main函數,我們將會在控制檯看到如下的報錯提示:
*************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
日誌告訴我們,Spring Boot應用在啓動過程中,自動初始化 DataSource 配置的時候失敗。因爲我們還沒有告訴程序,我們的數據庫連接的信息。
配置數據庫源
首先在數據庫中,創建 schema :
CREATE SCHEMA `simple_login` DEFAULT CHARACTER SET utf8 ;
然後,在 application.properties 中配置 datasource 如下:
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/simple_login?autoReconnect=true&useUnicode=true&createDatabaseIfNotExist=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root1234
再次啓動 main 程序,我們可以看到啓動成功了:
... o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' c.e.s.s.SimpleLoginBackEndApplicationKt : Started SimpleLoginBackEndApplicationKt in 8.981 seconds (JVM running for 10.534)
這個時候,我們訪問 http://127.0.0.1:8080/ ,會看到一個默認錯誤頁面
image
因爲,此時我們的代碼中還沒有對請求處理的 Controller。
寫一個 Rest 接口Hello World
下面我們就來寫一個 Rest 接口。代碼如下:
package com.easy.springboot.simpleloginbackend.controller import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController @RestController class HelloWorldController { @GetMapping(value = ["/hello"]) fun hello(): String { return "Hello World!" } }
重啓應用,再次訪問 http://127.0.0.1:8080/ , 頁面輸出:Hello World!
如果想更改服務端口,只需要在 application.properties 中添加如下配置:
server.port=9000
編寫登陸 POST 接口
我們先簡單返回一個結果示例:
package com.easy.springboot.simpleloginbackend.controller import com.easy.springboot.simpleloginbackend.result.Result import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController class LoginController { @PostMapping(value = ["/login.json"]) fun login(@RequestParam("username") username: String, @RequestParam("password") password: String): Result<String> { return Result(data = "username=${username},password=${password}", success = true, msg = "") } }
其中,Result類的代碼是:
package com.easy.springboot.simpleloginbackend.result class Result<T>( var data: T? = null, var success: Boolean = false, var msg: String = "" )
測試 POST 接口
爲了方便地進行測試,我們添加Spring Boot Actuator依賴到工程中:
dependencies { ... implementation('org.springframework.boot:spring-boot-starter-actuator') ... }
重新啓動應用,我們將會在底部工具欄中看到端點請求映射:
image
單擊 /login.json [POST], 選擇 Open in HTTP Request Editor, 在 POST 後面加上參數
POST http://127.0.0.1:9000/login.json?username=123&password=123
如下圖, 點擊綠色執行按鈕
image
可以得到輸出:
POST http://127.0.0.1:9000/login.json?username=123&password=123 HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Sat, 10 Nov 2018 16:19:10 GMT { "data": "username=123,password=123", "success": true, "msg": "" } Response code: 200; Time: 23ms; Content length: 60 bytes
好了,現在我們的前端表單頁面有了,後端的 /login.json 接口也好了。怎樣集成呢?且看下文分解。
前後端集成聯調
本節我們來把上面的前端 js、html頁面集成到後端的 Spring Boot應用中來。
把前端代碼放到後端工程中
我們後端視圖引擎使用的是 Freemarker。默認的視圖文件在 src/main/resources/templates 目錄下。
我們先手動把前端工程中的index.html、 bundle.js 分別放到 src/main/resources 相應的目錄下面,如下圖
image
視圖文件默認後綴
然後,爲了方便起見,我們把 Freemarker 的默認文件後綴名改成 .html, 這個配置在 application.properties中:
spring.freemarker.suffix=.html
編寫請求轉發路由
編寫一個控制器,把來自前端的請求 "", "/", "/index.html", "/index.htm" 路由到後端的視圖index.html上。代碼如下:
package com.easy.springboot.simpleloginbackend.controller import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.GetMapping @Controller class IndexController { @GetMapping(value = ["", "/", "/index.html", "/index.htm"]) fun index(): String { return "index" } }
前後端聯調測試
重啓應用,訪問 http://127.0.0.1:9000/ , 我們會看到登陸表單頁面。輸入用戶名、密碼,點擊登錄
image
觀察瀏覽器的控制檯,我們可以看到請求成功信息:
image
請求響應值:
{"data":"username=jack,password=123456","success":true,"msg":""}
有了上面的前後端完整的開發流程作爲基礎,我們就可以連接數據庫,判斷用戶名、密碼是否存在;也可以在前端做出登錄成功、失敗的跳轉提示等處理了。我們會在後面的章節中逐步介紹。
本章小結
本章通過一個簡單的用戶登錄表單的前端 React開發、後端 Spring Boot + Kotlin開發的完整實例,給大家講解了前後端分離開發的簡單過程。當然,在實際的項目開發中,我們有一系列的自動化腳手架、構建工具插件等,我們會在其他章節中逐步介紹。
前端工程代碼地址:https://github.com/EasySpringBoot/front-end-simple-login
後端工程代碼地址:https://github.com/EasySpringBoot/simple-login-back-end