我是一个新的反应编程和我的手,我试图建立一个接近真实的例子。
当你看到反应堆教程时,他们会给你很简单的例子,比如。
return userRepository.findById(1);
或者像处理通量,打破“布朗小狐狸”字符串和查找唯一的字母等,但大多数这些教程坚持单一对象,不幸的是,我找不到任何指导线或教程显示一个并排的例子,以输入相同的代码,首先在命令式,然后在反应,这就是为什么我看到许多新手在反应编程面临很多学习问题。
但我的观点是,在实际应用程序中,我们处理多个对象,如下我在Reactor中编写的示例代码所示。抱歉,我还在学习错误的代码。
public Mono<ServerResponse> response(ServerRequest serverRequest) {
return
Mono.just(new UserRequest())
.map(userRequest -> {
Optional<String> name = serverRequest.queryParam("name");
if (name.isPresent() && !name.get().isEmpty()) {
userRequest.setName(name.get());
return userRequest;
}
throw new RuntimeException("Invalid name");
})
.map(userRequest -> {
Optional<String> email = serverRequest.queryParam("email");
if (email.isPresent() && !email.get().isEmpty()) {
userRequest.setEmail(email.get());
return userRequest;
}
throw new RuntimeException("Invalid email");
})
.map(userRequest -> {
userRequest.setUuid(UUID.randomUUID().toString());
return userRequest;
})
.flatMap(userRequest ->
userRepository
.findByEmail(userRequest.getEmail())
.switchIfEmpty(Mono.error(new RuntimeException("User not found")))
.map(user -> Tuples.of(userRequest, user))
)
.map(tuple -> {
String cookiePrefix = tuple.getT2().getCode() + tuple.getT1().getUuid();
return Tuples.of(tuple.getT1(), tuple.getT2(), cookiePrefix);
})
//Some more chaining here.
.flatMap(tuple ->
ServerResponse
.ok()
.cookie(ResponseCookie.from(tuple.getT3(), tuple.getT2().getRating()).build())
.bodyValue("Welcome")
);
}
首先考虑上面的代码,我从UserRequest对象开始将querystring映射到该对象中。然后我需要一些数据从数据库等反应链接继续更多的工作做。现在考虑一下
tuple.getT()
tuple.getT2()
所以最后我想问的是,正确的方式还是我在这里错过了什么。因为我在反应中学到了一件事,数据没有更多的流动,只是在逻辑中间的命令式中,我们得到了哦,我需要另一个变量/对象,所以我在上面定义它并使用它,但在反应中,在第5个或第6个运算符之后,当开发人员意识到哦,我也需要那个对象,在这里,我在第2个运算符中创建的,然后我必须回去,在链接中传递它,得到我的第5个或第6个运算符,这是一个正确的方法。
通常有两种策略可以用来避免“元组地狱”,有时是孤立的,有时是一前一后的:
元组
类);map()
/flatmap()
调用,以便不需要声明元组。此外,这里还有更多的规则需要记住,这些规则可以帮助解决问题:
如果我们将上面的示例付诸实践,我们可以使用@WITH样式而不是setters将前三个map调用转移到一个“填充”用户对象的方法中(不过如果您真的需要,可以在这里使用setters):
private UserRequest populateUser(UserRequest userRequest, ServerRequest serverRequest) {
return userRequest
.withName(serverRequest.queryParam("name")
.filter(s -> !s.isEmpty())
.orElseThrow(() -> new RuntimeException("Invalid name")))
.withEmail(serverRequest.queryParam("email")
.filter(s -> !s.isEmpty())
.orElseThrow(() -> new RuntimeException("Invalid email")))
.withUuid(UUID.randomUUID().toString());
}
我们还可以将链中从数据库中查找用户的部分转移出去。这部分可能需要某种形式的新类型,但不是元组
,而是创建一个单独的类--我们称之为VerifiedUser
-它将使用UserRequest
和User
对象。然后,该类型还可以负责生成响应cookie对象,并通过一个简单的getter提供它。(我将编写verifieduser
任务作为作者的练习--这应该非常简单。)
然后我们就会有一个这样的方法:
private Mono<VerifiedUser> lookupUser(UserRequest userRequest) {
return userRepository
.findByEmail(userRequest.getEmail())
.map(user -> new VerifiedUser(userRequest, user)) //VerifiedUser can contain the logic to produce the ResponseCookie
.switchIfEmpty(Mono.error(new RuntimeException("User not found")));
}
所以现在我们有两个单独的小方法,它们各自承担一个单一的责任。我们还有另一个简单的类型verifieduser
,它是一个命名容器类型,比元组
更具描述性和实用性。此类型还为我们提供了一个cookie值。
这一过程意味着我们的主要反应链现在可以变得非常简单:
return Mono.just(new UserRequest())
.map(userRequest -> populateUser(userRequest, serverRequest))
.flatMap(this::lookupUser)
.flatMap(verifiedUser ->
ServerResponse.ok()
.cookie(verifiedUser.getCookie())
.bodyValue("Welcome")
);
(顺便说一句,您当然是正确的,在撰写本文的时候,有很多琐碎的教程,但很少有“深入”或“真实世界”的材料。对于相当新的框架来说,这通常是一种情况,但这肯定会使它们很难掌握,并导致大量不可维护的代码出现在野外!)
我试图在UI测试中使用页面对象模式。许多示例假设在类字段中按(定位器)保存。其他人建议保存WebElement(或SelenideElement,如果您使用的是Selenide)。虽然这两种方法都适用于硬编码定位器,但我不知道如何将其用于路径包含变量的定位器。 例如,如何在类字段中保存此定位器?
问题内容: 我正在与我的CompSci教授交谈,他建议将所有String 方法编写为: 而不是: 这两行都可以编译,但是我想知道第一种方法的好处是什么?我一直都是后一种方式。错了吗 什么是普通/常规? 问题答案: 第一种方法确保执行比较时不会收到 NullPointerException 。当您尝试在不存在的对象上调用方法时,抛出(发生)此异常。 以下是一些相关的切线:仔细阅读风险自负 不过要注意
我是反应编程的新手,我想出的唯一解决方案是+,比如 这是最好的解决方案,还是这个问题有更好的范式?
我刚刚遇到了一个奇怪的问题,这是我第一次在服务器上部署spring boot应用程序 像往常一样,我使用java命令java-jar myApp运行应用程序。罐子 过了一会儿,我看到应用程序停止了,没有留下任何错误消息。 所以我不知道问题出在哪里, 可能的原因是java内存不够,所以我将其增加到7GB,因为它有套接字 但问题依然存在 请注意,我没有docker,服务器是Amazon light s
问题内容: 在Python中,我想在代码中编写多行字典。有几种方法可以格式化它。我想到的是一些: mydict = { “key1”: 1, “key2”: 2, “key3”: 3, } mydict = { “key1”: 1, “key2”: 2, “key3”: 3, } mydict = { “key1”: 1, “key2”: 2, “key3”: 3, } 我知道以上任何一种在语法上
问题内容: 有一种获取layoutInflater的方法: 另一种方法是: 第三个(当我参加活动时)是: 那么它们之间有什么区别? 请注意,当我将第三个充气机发送到适配器时,我的应用程序正常工作。但是,当我发送上下文并通过第二种方式创建充气机时,却没有! 问题答案: 它们之间没有太大区别。 正如文档所说,公共抽象对象getSystemService(字符串名称) LayoutInflater,用于