Spring Boot實戰-使用WebFlux進行響應式編程(2)

響應式編程範式爲開發高性能 Web 應用帶來了新的機會和挑戰。Spring 5 中的 WebFlux 模塊可以作爲開發響應式 Web 應用的基礎。由於 Spring 框架的流行,WebFlux 會成爲開發 Web 應用的重要趨勢之一。

在上一節中我們對WebFlux進行了介紹並且使用WebFlux開發了一個極其簡單的接口,接下來展示更多關於WebFlux 的用法

  • 新建一個UserController.java
@RestController
@RequestMapping("/user")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(final UserService userService) {
        this.userService = userService;
    }

    @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource not found")
    @ExceptionHandler(ResourceNotFoundException.class)
    public void notFound() {
    }

    @GetMapping("")
    public Flux<User> list() {
        return this.userService.list();
    }

    @GetMapping("/{id}")
    public Mono<User> getById(@PathVariable("id") final String id) {
        return this.userService.getById(id);
    }

    @PostMapping("")
    public Mono<User> create(@RequestBody final User user) {
        return this.userService.createOrUpdate(user);
    }

    @PutMapping("/{id}")
    public Mono<User>  update(@PathVariable("id") final String id, @RequestBody final User user) {
        Objects.requireNonNull(user);
        user.setId(id);
        return this.userService.createOrUpdate(user);
    }

    @DeleteMapping("/{id}")
    public Mono<User>  delete(@PathVariable("id") final String id) {
        return this.userService.delete(id);
    }
}
  • 新建UserService.java
@Service
public class UserService {
    private final Map<String, User> data = new ConcurrentHashMap<>();

    public Flux<User> list() {
        return Flux.fromIterable(this.data.values());
    }

    public Flux<User> getById(final Flux<String> ids) {
        return ids.flatMap(id -> Mono.justOrEmpty(this.data.get(id)));
    }

    public Mono<User> getById(final String id) {
        return Mono.justOrEmpty(this.data.get(id))
                .switchIfEmpty(Mono.error(new ResourceNotFoundException()));
    }

    public Mono<User> createOrUpdate(final User user) {
        this.data.put(user.getId(), user);
        return Mono.just(user);
    }

    public Mono<User> delete(final String id) {
        return Mono.justOrEmpty(this.data.remove(id));
    }
     public void fromStream () {
        SortedMap<String, Charset> charSetMap = Charset.availableCharsets();
        Stream<String> charSetStream = charSetMap.keySet().stream();
        Flux<String> charsetFlux = Flux.fromStream(charSetStream);
        charsetFlux.subscribe(System.out::println);
    }

      public void range() {
        Flux.range(1, 5).subscribe(System.out::println);
        // 溢出
        Flux.range(Integer.MAX_VALUE, 5).subscribe(System.out::println);
    }
}

以上代碼使用Map完成了關於用戶的增刪改查操作。這也是我們在項目中運用最多的操作。如果只是想要在完成時給出完成信號,就可以使用 Mono<Void>。
接下來對service中用到的一些方法進行講解:

  • justOrEmpty|just
    這個方法比較簡單,直接將參數傳進方法然後返回。justOrEmpty只是比just多了一個判空操作,防止空指針。

  • Flux.fromIterable:fromIteratble方法使用接收到的Iterable對象構造Flux流,數據返回的順序和Iterable的next方法返回數據的順序一致。如下例子中使用fromIteratble構造了JVM支持的字符集的Flux流。

  • fromSteam方法:
    Flux數據流同樣可以使用java.util.stream.Stream對象構造出來,數據返回的順序和Stream.iterator()方法返回的Iterable對象的next方法返回數據的順序一致。如代碼中fromSteam方法使用fromSteam構造了JVM支持的字符集的Flux流。

  • range
    range(int start, int count)構造了一個Flux<Integer>流,返回從 [start,start+count) 區間的整數。如果該方法有類似於range(int start, int step,int count)的重載就更完美了。注意,range方法會處理整數溢出的場景,在溢出時拋出異常。

  • empty:方法返回一個沒有任何數據、異常的流。

  • error:方法返回一個沒有任何數據,只有異常的流程。

  • never:方法返回一個不會發送任何通知額流程。
    以上三個流都會觸發Subscriber的onSubscribe回調,都不會觸發onNext回調。同時empty流會觸發onComplete回調,error流會觸發onError回調。never方法只觸發Subscriber的onSubscribe回調,不會觸發其他任何回調。
    當然WebFlux還有更多高級的用法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章