[Day 22] Reactive Programming - Spring WebFlux(Hello World) Part 2

前言

在上一篇成功实作最基本的WebFlux功能,看到了一些有点熟悉又有点陌生的新朋友,在这边补充说明。

Handler&Router

Spring 同样保留了支援annotation-based,依然可以使用熟悉的Spring MVC各式annotation(@RequestMapping@RestController...),那为什麽需要有Handler&Router
首先如果你对原本的annotation感到十分亲切,当然可以继续采用原本的写法,一样直觉好用,但毕竟Reactive我们希望能够Functional,所以如果是一个新的专案想要尝试Reactive Spring,那拥抱FunctionalHandler&Router是一个不错的选择。

ServerResponse & ServerRequest 

ServerResponse类似以前的ResponseEntity,含有statusheaderbody,提供了更多方法更加的FunctionalServerRequest 在原有的Spring MVC当中并没有这样的角色,
Spring透过各式annotation(@RequestMapping@Valid)自动帮你带入指定的Object,虽然非常方便,但其实如果你没有深入去了解,是没办法从程序码去连结到行为与资料(都是背後处理掉),而且不容易继承来进行客制化,annotation如果要取得路径或是其他资料需要透过反射(reflection),相对就会有效能与type erasure的问题,ServerRequestServerResponse 改为Functional的风格则会让过程更佳清楚。


public class PersonHandler { 
    private final PersonRepository repository; 
    public PersonHandler(PersonRepository repository) { 
        this.repository = repository; 
    } 
    public Mono<ServerResponse> listPeople(ServerRequest request) {  
        Flux<Person> people = repository.allPeople(); 
        return ok().contentType(APPLICATION_JSON).body(people, Person.class); 
    } 
    public Mono<ServerResponse> createPerson(ServerRequest request) {  
        Mono<Person> person = request.bodyToMono(Person.class); 
        return ok().build(repository.savePerson(person)); 
    } 
    public Mono<ServerResponse> getPerson(ServerRequest request) {  
        int personId = Integer.valueOf(request.pathVariable("id")); 
        return repository.getPerson(personId) 
            .flatMap(person -> ok().contentType(APPLICATION_JSON).bodyValue(person)) 
            .switchIfEmpty(ServerResponse.notFound().build()); 
    } 
}

WebClient

类似於RestTemplate,是一个functional的Api,支援non-blocking/blocking、streaming,写起来更加的流畅。透过Codecs来处理(serializing /deserializing )我们需要使用的物件,Codecs同样类似於Spring MVCHttpMessageConverter

WebClient webClient = WebClient.builder() 
        .codecs(configurer -> { 
                CustomDecoder decoder = new CustomDecoder(); 
                configurer.customCodecs().registerWithDefaultConfig(decoder); 
        }) 
        .build();

其他

透过ntellij动demo专案时发生一个错误,推测可能是启动JMX(管理JVM的内的entity,视觉化的呈现)时pringApplication未开启完成导致

javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication

参考stackoverflow回答则可正常执行https://stackoverflow.com/questions/50436108/javax-management-instancenotfoundexception-org-springframework-boottype-admin

  • Edit Configurations
  • choose your project
  • remove the 'Enable launch optimization' and 'Enable JMX agent' checkboxes
    除了以上方法,或许是intellij版本比较旧,相容没有做好,升级後就没有这个问题了。

结语

接下来会稍微深入一点来看Handler&Router。

开始到了文章越来越难产的一个阶段,最後八篇!

资料来源

<<:  Day24 Shallow deep copy &Matrix

>>:  [DAY22]安装Heroku Postgres插件

day5: CSS style 规划 CSS module (global CSS, CSS module)

在 react 当中有提供了不同的 css 方法,除了常见的 css in css 外, 另外现在前...

WordPress 如何自动显示文章图片边框

在 WordPress 部落格文章中,图片是非常重要的资讯内容,俗话说”一图胜千言”,用一张图就可以...

Day21 - 前处理: 语者正规化

前一天在说明使用的语音特徵时有提到,模型有静态模型跟动态模型两种。在训练静态模型时,因为资料集中的语...

python的基本语法

Range Range-意即范围,设定你想要的数字范围的整数,但是给了之後不能修改!!! Range...

Day24 - Toast

Toast功能是可以在萤幕的下方显示一段即时的讯息文字 但文字会在几秒後消失 在Toast跳出来时,...