Skip to content

Commit 3500a3c

Browse files
author
YunaiV
committed
增加 webflux mysql + 事务
1 parent f6b91bb commit 3500a3c

File tree

12 files changed

+491
-1
lines changed

12 files changed

+491
-1
lines changed

lab-27/lab-27-webflux-r2dbc/pom.xml

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>2.2.1.RELEASE</version>
9+
<relativePath/> <!-- lookup parent from repository -->
10+
</parent>
11+
<modelVersion>4.0.0</modelVersion>
12+
13+
<artifactId>lab-27-webflux-r2dbc</artifactId>
14+
15+
<dependencies>
16+
<!-- 实现对 Spring WebFlux 的自动化配置 -->
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-webflux</artifactId>
20+
<version>2.2.1.RELEASE</version>
21+
</dependency>
22+
23+
<!-- 自动化配置响应式的 Spring Data R2DBC -->
24+
<dependency>
25+
<groupId>org.springframework.boot.experimental</groupId>
26+
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
27+
<version>0.1.0.M2</version>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>com.github.jasync-sql</groupId>
32+
<artifactId>jasync-r2dbc-mysql</artifactId>
33+
<version>1.0.11</version>
34+
</dependency>
35+
36+
<!-- 方便等会写单元测试 -->
37+
<dependency>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-starter-test</artifactId>
40+
<scope>test</scope>
41+
</dependency>
42+
43+
</dependencies>
44+
45+
<repositories>
46+
<!-- 引入 Spring 的快照仓库 -->
47+
<repository>
48+
<id>spring-libs-snapshot</id>
49+
<url>https://repo.spring.io/libs-snapshot</url>
50+
</repository>
51+
<!-- 引入 Jcenter 的快照仓库 -->
52+
<repository>
53+
<id>jcenter</id>
54+
<url>https://jcenter.bintray.com/</url>
55+
</repository>
56+
</repositories>
57+
58+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package cn.iocoder.springboot.lab27.springwebflux;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class Application {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(Application.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cn.iocoder.springboot.lab27.springwebflux.config;
2+
3+
import com.github.jasync.r2dbc.mysql.JasyncConnectionFactory;
4+
import com.github.jasync.sql.db.mysql.pool.MySQLConnectionFactory;
5+
import io.r2dbc.spi.ConnectionFactory;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.transaction.annotation.EnableTransactionManagement;
9+
10+
@Configuration
11+
@EnableTransactionManagement
12+
public class DatabaseConfiguration {
13+
14+
// @Bean
15+
// @ConfigurationProperties("spring.jasync.r2dbc")
16+
// public com.github.jasync.sql.db.Configuration configuration() {
17+
// return new com.github.jasync.sql.db.Configuration("");
18+
// }
19+
20+
@Bean
21+
public ConnectionFactory connectionFactory() {
22+
// com.github.jasync.sql.db.Configuration configuration
23+
//// = URLParser.INSTANCE.parseOrDie("mysql://root:@localhost:3306/lab-27-webflux-r2dbc", StandardCharsets.UTF_8);
24+
// = URLParser.INSTANCE.parseOrDie("mysql://lab-27-webflux-r2dbc:0ed86@[email protected]:3306/lab-27-webflux-r2dbc", StandardCharsets.UTF_8);
25+
com.github.jasync.sql.db.Configuration configuration = new com.github.jasync.sql.db.Configuration(
26+
"lab-27-webflux-r2dbc",
27+
"47.112.193.81",
28+
3306,
29+
"0ed86@11-r2Dbc123",
30+
"lab-27-webflux-r2dbc"
31+
);
32+
return new JasyncConnectionFactory(new MySQLConnectionFactory(configuration));
33+
}
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package cn.iocoder.springboot.lab27.springwebflux.controller;
2+
3+
import cn.iocoder.springboot.lab27.springwebflux.dao.UserRepository;
4+
import cn.iocoder.springboot.lab27.springwebflux.dataobject.UserDO;
5+
import cn.iocoder.springboot.lab27.springwebflux.dto.UserAddDTO;
6+
import cn.iocoder.springboot.lab27.springwebflux.dto.UserUpdateDTO;
7+
import cn.iocoder.springboot.lab27.springwebflux.vo.UserVO;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.web.bind.annotation.*;
10+
import reactor.core.publisher.Flux;
11+
import reactor.core.publisher.Mono;
12+
13+
import java.util.Date;
14+
import java.util.Objects;
15+
import java.util.function.Function;
16+
17+
/**
18+
* 用户 Controller
19+
*/
20+
@RestController
21+
@RequestMapping("/users")
22+
public class UserController {
23+
24+
private static final UserDO USER_NULL = new UserDO();
25+
26+
@Autowired
27+
private UserRepository userRepository;
28+
29+
/**
30+
* 查询用户列表
31+
*
32+
* @return 用户列表
33+
*/
34+
@GetMapping("/list")
35+
public Flux<UserVO> list() {
36+
// 返回列表
37+
return userRepository.findAll()
38+
.map(userDO -> new UserVO().setId(userDO.getId()).setUsername(userDO.getUsername()));
39+
}
40+
41+
/**
42+
* 获得指定用户编号的用户
43+
*
44+
* @param id 用户编号
45+
* @return 用户
46+
*/
47+
@GetMapping("/get")
48+
public Mono<UserVO> get(@RequestParam("id") Integer id) {
49+
// 返回
50+
return userRepository.findById(id)
51+
.map(userDO -> new UserVO().setId(userDO.getId()).setUsername(userDO.getUsername()));
52+
}
53+
54+
/**
55+
* 添加用户
56+
*
57+
* @param addDTO 添加用户信息 DTO
58+
* @return 添加成功的用户编号
59+
*/
60+
@PostMapping("add")
61+
// @Transactional
62+
public Mono<Integer> add(UserAddDTO addDTO) {
63+
// 查询用户
64+
Mono<UserDO> user = userRepository.findByUsername(addDTO.getUsername());
65+
66+
// 执行插入
67+
return user.defaultIfEmpty(USER_NULL) // 设置 USER_NULL 作为 null 的情况,否则 flatMap 不会往下走
68+
.flatMap(new Function<UserDO, Mono<Integer>>() {
69+
70+
@Override
71+
public Mono<Integer> apply(UserDO userDO) {
72+
if (userDO != USER_NULL) {
73+
// 返回 -1 表示插入失败。
74+
// 实际上,一般是抛出 ServiceException 异常。因为这个示例项目里暂时没做全局异常的定义,所以暂时返回 -1 啦
75+
return Mono.just(-1);
76+
}
77+
// 将 addDTO 转成 UserDO
78+
userDO = new UserDO()
79+
.setUsername(addDTO.getUsername())
80+
.setPassword(addDTO.getPassword())
81+
.setCreateTime(new Date());
82+
// 插入数据库
83+
return userRepository.save(userDO).map(UserDO::getId);
84+
}
85+
86+
});
87+
}
88+
89+
/**
90+
* 更新指定用户编号的用户
91+
*
92+
* @param updateDTO 更新用户信息 DTO
93+
* @return 是否修改成功
94+
*/
95+
@PostMapping("/update")
96+
public Mono<Boolean> update(UserUpdateDTO updateDTO) {
97+
// 查询用户
98+
Mono<UserDO> user = userRepository.findById(updateDTO.getId());
99+
100+
// 执行更新
101+
return user.defaultIfEmpty(USER_NULL) // 设置 USER_NULL 作为 null 的情况,否则 flatMap 不会往下走
102+
.flatMap(new Function<UserDO, Mono<Boolean>>() {
103+
104+
@Override
105+
public Mono<Boolean> apply(UserDO userDO) {
106+
// 如果不存在该用户,则直接返回 false 失败
107+
if (userDO == USER_NULL) {
108+
return Mono.just(false);
109+
}
110+
// 查询用户是否存在
111+
return userRepository.findByUsername(updateDTO.getUsername())
112+
.defaultIfEmpty(USER_NULL) // 设置 USER_NULL 作为 null 的情况,否则 flatMap 不会往下走
113+
.flatMap(new Function<UserDO, Mono<? extends Boolean>>() {
114+
115+
@Override
116+
public Mono<? extends Boolean> apply(UserDO usernameUserDO) {
117+
// 如果用户名已经使用(该用户名对应的 id 不是自己,说明就已经被使用了)
118+
if (usernameUserDO != USER_NULL && !Objects.equals(updateDTO.getId(), usernameUserDO.getId())) {
119+
return Mono.just(false);
120+
}
121+
// 执行更新
122+
userDO.setUsername(updateDTO.getUsername());
123+
userDO.setPassword(updateDTO.getPassword());
124+
return userRepository.save(userDO).map(userDO -> true); // 返回 true 成功
125+
}
126+
127+
});
128+
}
129+
130+
});
131+
}
132+
133+
/**
134+
* 删除指定用户编号的用户
135+
*
136+
* @param id 用户编号
137+
* @return 是否删除成功
138+
*/
139+
@PostMapping("/delete") // URL 修改成 /delete ,RequestMethod 改成 DELETE
140+
public Mono<Boolean> delete(@RequestParam("id") Integer id) {
141+
// 查询用户
142+
Mono<UserDO> user = userRepository.findById(id);
143+
144+
// 执行删除。这里仅仅是示例,项目中不要物理删除,而是标记删除
145+
return user.defaultIfEmpty(USER_NULL) // 设置 USER_NULL 作为 null 的情况,否则 flatMap 不会往下走
146+
.flatMap(new Function<UserDO, Mono<Boolean>>() {
147+
148+
@Override
149+
public Mono<Boolean> apply(UserDO userDO) {
150+
// 如果不存在该用户,则直接返回 false 失败
151+
if (userDO == USER_NULL) {
152+
return Mono.just(false);
153+
}
154+
// 执行删除
155+
return userRepository.deleteById(id).map(aVoid -> true); // 返回 true 成功
156+
}
157+
158+
});
159+
}
160+
161+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package cn.iocoder.springboot.lab27.springwebflux.dao;
2+
3+
import cn.iocoder.springboot.lab27.springwebflux.dataobject.UserDO;
4+
import org.springframework.data.r2dbc.repository.query.Query;
5+
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
6+
import reactor.core.publisher.Mono;
7+
8+
public interface UserRepository extends ReactiveCrudRepository<UserDO, Integer> {
9+
10+
@Query("SELECT id FROM users u WHERE u.username = :username")
11+
Mono<UserDO> findByUsername(String username);
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package cn.iocoder.springboot.lab27.springwebflux.dataobject;
2+
3+
import org.springframework.data.annotation.Id;
4+
import org.springframework.data.relational.core.mapping.Table;
5+
6+
import java.util.Date;
7+
8+
/**
9+
* 用户 DO
10+
*/
11+
@Table(value = "users")
12+
public class UserDO {
13+
14+
@Id
15+
private Integer id;
16+
/**
17+
* 账号
18+
*/
19+
private String username;
20+
/**
21+
* 密码
22+
*/
23+
private String password;
24+
/**
25+
* 创建时间
26+
*/
27+
private Date createTime;
28+
29+
public Integer getId() {
30+
return id;
31+
}
32+
33+
public UserDO setId(Integer id) {
34+
this.id = id;
35+
return this;
36+
}
37+
38+
public String getUsername() {
39+
return username;
40+
}
41+
42+
public UserDO setUsername(String username) {
43+
this.username = username;
44+
return this;
45+
}
46+
47+
public String getPassword() {
48+
return password;
49+
}
50+
51+
public UserDO setPassword(String password) {
52+
this.password = password;
53+
return this;
54+
}
55+
56+
public Date getCreateTime() {
57+
return createTime;
58+
}
59+
60+
public UserDO setCreateTime(Date createTime) {
61+
this.createTime = createTime;
62+
return this;
63+
}
64+
65+
@Override
66+
public String toString() {
67+
return "UserDO{" +
68+
"id=" + id +
69+
", username='" + username + '\'' +
70+
", password='" + password + '\'' +
71+
", createTime=" + createTime +
72+
'}';
73+
}
74+
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cn.iocoder.springboot.lab27.springwebflux.dto;
2+
3+
/**
4+
* 用户添加 DTO
5+
*/
6+
public class UserAddDTO {
7+
8+
/**
9+
* 账号
10+
*/
11+
private String username;
12+
/**
13+
* 密码
14+
*/
15+
private String password;
16+
17+
public String getUsername() {
18+
return username;
19+
}
20+
21+
public UserAddDTO setUsername(String username) {
22+
this.username = username;
23+
return this;
24+
}
25+
26+
public String getPassword() {
27+
return password;
28+
}
29+
30+
public UserAddDTO setPassword(String password) {
31+
this.password = password;
32+
return this;
33+
}
34+
35+
}

0 commit comments

Comments
 (0)