天天看点

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入门整合已经完成了。

那么我们最后把项目跑起来,简单测试一下,

Springboot 整合WebFlux 实现RESTFUI风格API 及简单的CRUD

接下来使用postman调用下插入user接口 :

Springboot 整合WebFlux 实现RESTFUI风格API 及简单的CRUD

再调一下查询接口:

Springboot 整合WebFlux 实现RESTFUI风格API 及简单的CRUD
Mono 和 Flux 适用于两个场景,即: 
 Mono:实现发布者,并返回 0 或 1 个元素,即单对象。 
 Flux:实现发布者,并返回 N 个元素,即 List 列表对象。 
 有人会问,这为啥不直接返回对象,比如返回 City/Long/List。 
 原因是,直接使用 Flux 和 Mono 是非阻塞写法,相当于回调方式。 
 利用函数式可以减少了回调,因此会看不到相关接口。这恰恰是 WebFlux 的好处:集合了非阻塞 + 异步