Springboot 整合WebFlux 实现RESTFUI风格API 及简单的CRUD
这里简单介绍下springboot整合webFlux(入门) ,使用netty通信。
首先是创建一个springboot项目,这里就不介绍怎么创建了。
接下来是导入依赖包:
<!--webflux-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
(使用这个依赖包后,不要再导入spring-boot-starter-web包了,因为我们webflux使用的是netty)
然后是创建一个简单的pojo:
User.java
package com.test.webflux.pojo;
import lombok.Data;
/**
* @Author:JCccc
* @Description:
* @Date: created in 16:08 2019/5/30
*/
@Data
public class User {
/**
* id
*/
private Long id;
/**
* 姓名
*/
private String name;
/**
* 描述
*/
private String desc;
}
接下来是dao层(netty不支持mysql,所以想要对数据进行CRUD可以采取整合mongodb和redis),这里我暂且采用的ConcurrentMap来操作数据:
UserRepository.java
package com.test.webflux.dao;
import com.test.webflux.pojo.User;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
/**
* @Author:JCccc
* @Description:
* @Date: created in 16:30 2019/5/30
*/
@Repository
public class UserRepository {
private ConcurrentMap<Long,User> repository = new ConcurrentHashMap<>();
private static final AtomicLong idGenerator = new AtomicLong(0);
public Long save(User user){
Long id=idGenerator.incrementAndGet();
user.setId(id);
repository.put(id, user);
return id;
}
public Collection<User> findAll() {
return repository.values();
}
public User findUserById(Long id) {
return repository.get(id);
}
public Long updateUser(User user) {
repository.put(user.getId(), user);
return user.getId();
}
public Long deleteUser(Long id) {
repository.remove(id);
return id;
}
}
接下来是handler层,这里简单列举了对ConcurrentMap进行CRUD的几个方法,
UserHandler.java
package com.test.webflux.handler;
import com.test.webflux.dao.UserRepository;
import com.test.webflux.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @Author:JCccc
* @Description:
* @Date: created in 16:38 2019/5/30
*/
@Component
public class UserHandler {
private final UserRepository userRepository;
@Autowired
public UserHandler(UserRepository userRepository) {
this.userRepository = userRepository;
}
public Mono<Long> save(User user) {
return Mono.create(userMonoSink -> userMonoSink.success(userRepository.save(user)));
}
public Mono<User> findUserById(Long id) {
return Mono.justOrEmpty(userRepository.findUserById(id));
}
public Flux<User> findAllUser() {
return Flux.fromIterable(userRepository.findAll());
}
public Mono<Long> modifyUser(User user) {
return Mono.create(userMonoSink -> userMonoSink.success(userRepository.updateUser(user)));
}
public Mono<Long> deleteUser(Long id) {
return Mono.create(userMonoSink -> userMonoSink.success(userRepository.deleteUser(id)));
}
}
最后,创建下controller层写几个API(这里采用restful风格):
UserWebFluxController.java
package com.test.webflux.controller;
import com.test.webflux.handler.UserHandler;
import com.test.webflux.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @Author:JCccc
* @Description:
* @Date: created in 16:44 2019/5/30
*/
@RestController
@RequestMapping(value = "/user")
public class UserWebFluxController {
@Autowired
private UserHandler userHandler;
/**
* 根据ID查询某个User
* @param id
* @return
*/
@GetMapping(value = "/{id}")
public Mono<User> findUserById(@PathVariable("id") Long id) {
return userHandler.findUserById(id);
}
/**
* 查找所有User
* @return
*/
@GetMapping()
public Flux<User> findAllUser() {
return userHandler.findAllUser();
}
/**
* 插入User
* @param user
* @return
*/
@PostMapping()
public Mono<Long> saveUser(@RequestBody User user) {
return userHandler.save(user);
}
/**
* 修改User
* @param user
* @return
*/
@PutMapping()
public Mono<Long> modifyUser(@RequestBody User user) {
return userHandler.modifyUser(user);
}
/**
* 根据ID删除User
* @param id
* @return
*/
@DeleteMapping(value = "/{id}")
public Mono<Long> deleteUser(@PathVariable("id") Long id) {
return userHandler.deleteUser(id);
}
}
到此,简单的webflux入门整合已经完成了。
那么我们最后把项目跑起来,简单测试一下,
接下来使用postman调用下插入user接口 :
再调一下查询接口:
OK,其余的接口也是一样调用,那么简单的介绍就此完毕了。
(PS:想了解更多的,可以去查下mono和flux的相关资料,可以往上翻下,controller里面用到了Mono)
Mono 和 Flux 适用于两个场景,即:
Mono:实现发布者,并返回 0 或 1 个元素,即单对象。
Flux:实现发布者,并返回 N 个元素,即 List 列表对象。
有人会问,这为啥不直接返回对象,比如返回 City/Long/List。
原因是,直接使用 Flux 和 Mono 是非阻塞写法,相当于回调方式。
利用函数式可以减少了回调,因此会看不到相关接口。这恰恰是 WebFlux 的好处:集合了非阻塞 + 异步