最简单基本的Spring Boot + React 项目和部署,找了很久也没有找到很好的教程,还是靠自己摸索的,所以了解也不是很深,分享给有需要的人,有问题欢迎探讨~
先来看个效果吧
前端两个输入框,一个id一个name,只填id点Submit是get,都填了点Submit是post;点Delete会按id删除对应的数据。Button和Input都是用的Ant Design的组件。
源码:https://github.com/InvincibleDudu/Spring-Boot-React-Demo
工具准备
项目创建就不在这说了吧,就是前后端各创建一个最简单的项目。
- Spring Initializr项目创建
- Create-React-App项目创建
- 数据库创建。本项目仅使用一个greeting表,包含id(int)和name(varchar(30))两列。
Spring Boot
pom.xml
依赖包如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
application.yml
,记得把链接里的库名改了,当然还有密码
spring:
datasource:
url: jdbc:mysql://localhost:3306/DBName?characterEncoding=UTF-8
username: root
password: *****
driver-class-name: com.mysql.cj.jdbc.Driver
Java Bean:
Greeting.java
package com.invdu.nlp.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* Created by InvincibleDudu on 01/08/2021 at 13:44
*/
@Data
@AllArgsConstructor
public class Greeting {
private long id;
private String name;
}
主要的好戏就在下面这两个类里,Mapper类用iBatis负责数据库交互。Controller负责接口。
GreetingMapper.java
package com.invdu.nlp.mapper;
import com.invdu.nlp.bean.Greeting;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
/**
* Created by InvincibleDudu on 01/08/2021 at 13:39
*/
@Mapper
@Repository
public interface GreetingMapper {
@Select("select * from greeting where id = #{id}")
Greeting getGreetingById (long id);
@Insert("insert into greeting values(#{id}, #{name})")
int saveGreeting(long id, String name);
@Delete("delete from greeting where id = #{id}")
int deleteGreeting(long id); //how many rows are deleted
}
GreetingController.java
package com.invdu.nlp.controller;
import com.invdu.nlp.bean.Greeting;
import com.invdu.nlp.mapper.GreetingMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* Created by InvincibleDudu on 01/08/2021 at 11:46
*/
@CrossOrigin
@RestController
public class GreetingController {
GreetingMapper greetingMapper;
@Autowired
public void setGreetingMapper(GreetingMapper greetingMapper) {
this.greetingMapper = greetingMapper;
}
@GetMapping("/getGreeting")
public Greeting greeting(@RequestParam long id) {
return greetingMapper.getGreetingById(id);
}
@PostMapping("/greeting")
public String greetings(@RequestBody Greeting greeting) {
if (greeting.getId() != 0 && greeting.getName() != null) {
var result = greetingMapper.saveGreeting(greeting.getId(), greeting.getName());
System.out.println("result: " + result + " " + greeting.getId() + greeting.getName());
return "success " + result + " rows inserted";
}
return "failed";
}
@DeleteMapping("/greeting")
public String deleteGreeting(@RequestParam long id) {
if (id != 0) {
var delete = greetingMapper.deleteGreeting(id);
return "ok " + delete + " lines deleted";
}
return "failed";
}
}
后端差不多就是这点东西了,就负责get、post、delete三个请求。
React
依赖包:应该只加了axios和antd
package.json
{
"dependencies": {
"@testing-library/jest-dom": "^5.11.8",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",
"antd": "^4.10.0",
"axios": "^0.21.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1",
"web-vitals": "^0.2.4"
}
}
App.js
用了比较新的语法useState
,可以在函数组件中使用state。目前来看相比类组件还算比较好用(不用到处this.state
和this.setState
了),也是React官方在未来推荐使用的方案。
import './App.css';
import React, {useState} from 'react';
import axios from "axios";
import {Button, Input} from "antd"
function App() {
const [id, setId] = useState(1)
const [name, setName] = useState("")
const [response, setResponse] = useState("response will show up here")
const url = "http://localhost:8080/"
async function request() {
if (!name) { //get
console.log("requesting... " + id)
setId(1)
let res = await axios.get(url + "getGreeting?id=" + id)
setResponse(JSON.stringify(res.data))
} else {
console.log("posting... " + id + " " + name)
setId(1)
setName("")
let res = await axios.post(url + "greeting", {
id: id,
name: name
})
setResponse(res.data)
}
}
const deleteRequest = async () => {
console.log("deleting...")
setId(1)
setName("")
let res = await axios.delete(url + "greeting?id=" + id)
setResponse(res.data)
}
return (
<div style={{padding: 10}}>
<Input placeholder="id" value={id}
onChange={(e) => setId(e.target.value)}/>
<Input placeholder="name" value={name}
onChange={(e) => setName(e.target.value)}/>
<Button onClick={request}>Submit</Button>
<Button danger onClick={deleteRequest}>Delete</Button>
<br/>
{response}
</div>
);
}
export default App;
合并部署
在react项目目录下的命令行中执行npm run build
,生成生产环境的文件,在build文件夹中找到。
把index.html放入SB项目的template文件夹中;把其他文件放入SB的static文件夹中(两个static文件夹)。Spring Boot将会自动识别并编译。
最终项目结构
至此,启动Spring Boot项目即可正常访问前端界面。
如果想要部署到Linux常驻运行、域名相关、启用SSL证书(https)等,可以查看我此前的文章:https://blog.csdn.net/InvincibleDudu/article/details/107898480
如有问题,欢迎探讨和指正。