当前位置: 首页 > 科技观察

WebFlux使用函数式编程

时间:2023-03-12 09:36:19 科技观察

本文主要内容:HandlerFunction使用概述SpringWebFlux包括WebFlux.Fn是一个轻量级的函数式编程模型,其中函数用于路由和处理请求,契约被设计为不可变的。它是基于注释的编程模型的替代方案,但在其他方面运行在相同的ReactiveCore基础上。在WebFlux.Fn中,HTTP请求由HandlerFunction处理:此函数接受ServerRequest并返回延迟的ServerResponse(即Mono)。请求和响应对象都有不可变的契约,提供对HTTP请求和响应的JDK8友好访问。HandlerFunction相当于注解编程模型中的@RequestMapping方法体。传入的请求被路由到具有RouterFunction的处理函数:一个接受ServerRequest并返回延迟的HandlerFunction(即Mono)的函数。当router函数匹配时,返回handler函数;否则是一个空的Mono。RouterFunction等同于@RequestMapping注解,但主要区别在于路由函数不仅提供数据,还提供行为。RouterFunctions.route()提供了一个路由器生成器,可以方便创建路由器,如下例所示:示例:importstaticorg.springframework.http.MediaType.APPLICATION_JSON;导入静态org.springframework.web.reactive.function.server。RequestPredicates.*;导入静态org.springframework.web.reactive.function.server.RouterFunctions.route;PersonRepositoryrepository=...PersonH??andlerhandler=newPersonH??andler(repository);RouterFunctionroute=route().GET("/person/{id}",accept(APPLICATION_JSON),handler::getPerson).GET("/person",accept(APPLICATION_JSON),handler::listPeople).POST("/person",handler::createPerson)。build();publicclassPersonH??andler{publicMonolistPeople(ServerRequestrequest){//todo业务处理逻辑}publicMonocreatePerson(ServerRequestrequest){//todo业务处理逻辑}publicMonogetPerson(ServerRequestrequest){//todo业务处理逻辑}}运行RouterFunction的一种方法是将其转换为HttpHandler,并通过安装服务器适配器之一:RouterFunctions.toHttpHandler(RouterFunction)RouterFunctions.toHttpHandler(RouterFunction,HandlerStrategies)。大多数应用程序都可以使用WebFluxJava配置运行。HandlerFunctionServerRequest和ServerResponse是不可变接口,提供对HTTP请求和响应的JDK8友好访问。请求和响应都提供了针对主体流的反应流背压。请求主体用反应器Flux或Mono表示。响应主体由任何反应流Publisher表示,包括Flux和Mono。ServerRequestServerRequest提供对HTTP方法、URI、标头和查询参数的访问,而对文字的访问是通过文字方法提供的。以下示例将请求正文提取为Mono:Monostring=request.bodyToMono(String.class);以下示例将文本提取为Flux(或Kotlin中的Flow),其中Person对象是从某种序列化形式(例如JSON或XML)解码中检索的:Fluxpeople=request.bodyToFlux(Person.class);前面的示例是使用更通用的ServerRequest.body(BodyExtractor)的快捷方式,它接受BodyExtractor函数策略接口。实用程序类BodyExtractors提供对多个实例的访问。例如,前面的例子也可以这样写:Monostring=request.body(BodyExtractors.toMono(String.class));Fluxpeople=request.body(BodyExtractors.toFlux(Person.class));下面的例子展示了如何访问表单数据:Mono>map=request.formData();以下示例显示了如何将多部分数据作为地图访问:Mono>map=request.multipartData();以下示例显示了如何一次流式访问多个部分:Fluxparts=request.body(BodyExtractors.toParts());ServerResponseServerResponse提供对HTTP响应的访问,因为它是不可变的,因此您可以使用build方法来创建它。您可以使用构造函数来设置响应状态、添加响应标头或提供响应文本。以下示例使用JSON内容创建200(OK)响应:Monoperson=Mono.just(newPerson("John",12))ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)。身体(人,Person.class);下面的示例显示了如何构建一个带有Location标头且没有文本的201(CREATED)响应:URIlocation=...ServerResponse.created(location).build();根据使用的编解码器,可以通过传递一个提示参数来自定义主体是如何序列化或反序列化的。例如,要指定JacksonJSON视图:ServerResponse.ok().hint(Jackson2CodecSupport.JSON_VIEW_HINT,MyJacksonView.class).body(...);处理程序类我们可以将处理程序函数编写为lambda,如以下示例所示。HandlerFunctionhelloWorld=request->ServerResponse.ok().bodyValue("HelloWorld");这很方便,但在一个应用程序中我们需要多个函数,多个内联lambda会变得混乱。因此,将相关的处理程序函数分组到一个处理程序类中很有用,该处理程序类在基于注释的应用程序中具有类似@Controller的角色。例如,下面的类公开了一个响应式Person存储库:importstaticorg.springframework.http.MediaType.APPLICATION_JSON;importstaticorg.springframework.web.reactive.function.server.ServerResponse.ok;publicclassPersonH??andler{privatefinalPersonRepository存储库;publicPersonH??andler(PersonRepositoryrepository){this.repository=repository;}publicMonolistPeople(ServerRequestrequest){Fluxpeople=repository.allPeople();返回ok().contentType(APPLICATION_JSON).body(people,Person.class);}publicMonocreatePerson(ServerRequestrequest){Monoperson=request.bodyToMono(Person.class);返回ok().build(repository.savePerson(person));}publicMonogetPerson(ServerRequestrequest){intpersonId=Integer.valueOf(request.pathVariable("id"));返回repository.getPerson(personId).flatMap(person->ok().contentType(APPLICATION_JSON).bodyValue(person)).switchIfEmpty(ServerResponse.notFound().build());}}验证功能端点可以使用Spring的验证工具来应用于请求主体验证例如,给定一个Person的自定义SpringValidator实现://...publicMonocreatePerson(ServerRequestrequest){Monoperson=request.bodyToMono(Person.class).doOnNext(this::validate);返回ok().build(repository.savePerson(person));}privatevoidvalidate(Personperson){错误errors=newBeanPropertyBindingResult(person,"person");validator.validate(人,错误);如果(errors.hasErrors()){thrownewServerWebInputException(errors.toString());}}}总结:路由函数中HandlerFunction的使用。ServerRequest、ServerResponse使用示例。