假设我有两个微服务,我想在使用WebFlux的Spring REST控制器中实现BFF(前端的后端)模式。
来自2个远程服务的域对象是:
public class Comment {
private Long id;
private String text;
private Long authorId;
private Long editorId;
}
public class Person {
private Long id;
private String firstName;
private String lastName;
}
并且API编写器必须返回以下类型的对象:
public class ComposedComment {
private String text;
private String authorFullName;
private String editorFullName;
}
为了简洁起见,我编写了一个控制器,它将所有服务模拟在一个。
@RestController
@RequestMapping("/api")
public class Controller {
private static final List<Comment> ALL_COMMENTS = Arrays.asList(//
new Comment(1L, "Bla bla", 1L, null), //
new Comment(2L, "lorem ipsum", 2L, 3L), //
new Comment(3L, "a comment", 2L, 1L));
private static final Map<Long, Person> PERSONS;
static {
PERSONS = new HashMap<>();
PERSONS.put(1L, new Person(1L, "John", "Smith"));
PERSONS.put(2L, new Person(2L, "Paul", "Black"));
PERSONS.put(3L, new Person(3L, "Maggie", "Green"));
}
private WebClient clientCommentService = WebClient.create("http://localhost:8080/api");
private WebClient clientPersonService = WebClient.create("http://localhost:8080/api");
@GetMapping("/composed/comments")
public Flux<ComposedComment> getComposedComments() {
//This is the tricky part
}
private String extractFullName(Map<Long, Person> map, Long personId) {
Person person = map.get(personId);
return person == null ? null : person.getFirstName() + " " + person.getLastName();
}
@GetMapping("/comments")
public ResponseEntity<List<Comment>> getAllComments() {
return new ResponseEntity<List<Comment>>(ALL_COMMENTS, HttpStatus.OK);
}
@GetMapping("/persons/{personIds}")
public ResponseEntity<List<Person>> getPersonsByIdIn(@PathVariable("personIds") Set<Long> personIds) {
List<Person> persons = personIds.stream().map(id -> PERSONS.get(id)).filter(person -> person != null)
.collect(Collectors.toList());
return new ResponseEntity<List<Person>>(persons, HttpStatus.OK);
}
}
我的问题是我刚刚开始与反应堆,我不是真的确定我在做什么…这是我的composer方法的当前版本:
@GetMapping("/composed/comments")
public Flux<ComposedComment> getComposedComments() {
Flux<Comment> commentFlux = clientCommentService.get().uri("/comments").retrieve().bodyToFlux(Comment.class);
Set<Long> personIds = commentFlux.toStream().map(comment -> Arrays.asList(comment.getAuthorId(), comment.getEditorId())).flatMap(Collection::stream).filter(Objects::nonNull).collect(Collectors.toSet());
Map<Long, Person> personsById = clientPersonService.get().uri("/persons/{ids}", personIds.stream().map(Object::toString).collect(Collectors.joining(","))).retrieve().bodyToFlux(Person.class).collectMap(Person::getId).block();
return commentFlux.map(
comment -> new ComposedComment(
comment.getText(),
extractFullName(personsById, comment.getAuthorId()),
extractFullName(personsById, comment.getEditorId()))
);
}
它可以工作,但是我知道我应该用map、flatMap和zip进行几个转换,而不是调用block()和toStream()...你能帮我正确地重写这个方法吗?:)
您正在控制器中返回null。将其替换为返回反应流。
return commentFlux.flatMap(comment -> ....)
....
您的控制器签名返回
Flux<ComposedComment>
所以确保在最后一次返回中,您必须使用flatMap或map将它们转换为ComposedComment。您可以将其视为一个promise链,在该链中您可以在实现中执行许多flatMap、map,以转换为最终的数据集。
我正在尝试将Spring Cloud Contract应用于使用Spring WebFlux构建的反应API。基本上能够以以下方式从API发送通量和接收响应通量: 但是,我在网上或文档中找不到关于我是否可以使用Spring Cloud Contract实现这一点的信息。 甚至有可能为此写一份合同吗?它是否能够提供wiremock并生成适当的JUnit测试?
我发现在Hyperledger composer playground中,任何人都可以删除当前的商业网络。我如何限制它,使只有管理员可以删除他们自己的业务网络?
从我的角度来看,我认为可以有一种方法在代码中明确我的Rest API是反应性的,但可能是我不知道的。
问题内容: 我创建了以下聚合物元素: 我这样做是在我的index.html中调用此方法: 我期望对于todo数组中返回的每个对象,都会打印出一个。但是,当我运行该应用程序时,我在控制台中得到以下输出: 未捕获的TypeError:无法读取未定义的属性“ todos” 在 我不确定这里发生了什么以及如何引用从ajax响应接收回的数据。 问题答案: 将头撞在墙上几个小时后,我设法解决了这个问题。我创建
我用的是Spring助焊剂。我需要从不同的来源组装一个物体。如何确保两个流都返回了所需的数据? 比如:
在前端使用React,后端使用RESTful API,并通过JSON Web令牌(JWT)进行授权,我们如何处理会话?例如,在登录之后,我从REST获得一个JWT令牌。如果我把它保存到localStorage中,我就容易受到XSS的攻击,如果我把它保存到cookie,除了我把cookie设置为HttpOnly,但是React不能读取HttpOnly cookie(我需要读取cookie以从中获取J