首先需求,是做一个短网址的服务,之前用 Spring MVC 的时候的代码,非常直观明了
@PostMapping("/generate")
public Map<String, String> generate(@RequestBody Map<String, String> map) {
if (!"sdjsioadijosaoidsa".equals(map.get("token"))) {
throw new RuntimeException("无权限");
}
String url = map.get("url");
Assert.isTrue(!StringUtils.isEmpty(url), "url absent");
byte[] sha256 = DigestUtils.sha256(url);
String path = redisOpt.get(sha256);
if (path == null) {
path = RandomStringUtils.randomAlphanumeric(6);
redisOpt.set(path.getBytes(StandardCharsets.ISO_8859_1), url, 365, TimeUnit.DAYS);
redisOpt.set(sha256, path, 365, TimeUnit.DAYS);
}
return ImmutableMap.of("url", urlPrefix + path);
}
然后换了 WebFlux,尝试写一下比较 Reactive 风格的代码
public Mono<ServerResponse> generate(ServerRequest serverRequest) {
return serverRequest.bodyToMono(String.class).map(JSON::parseObject)
.flatMap(jsonObject -> {
if (!"sdjsioadijosaoidsa".equals(jsonObject.get("token"))) {
return ServerResponse.status(HttpStatus.UNAUTHORIZED)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(ImmutableMap.of("errorMsg", "no privilege"));
}
String url = jsonObject.getString("url");
if (StringUtils.isEmpty(url)) {
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(ImmutableMap.of("errorMsg", "url is absent"));
}
byte[] sha256 = DigestUtils.sha256(url);
return redisTemplate.opsForValue().get(sha256)
.flatMap(path -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(ImmutableMap.of("url", urlPrefix + path)))
.switchIfEmpty(Mono.just(RandomStringUtils.randomAlphanumeric(6))
.filterWhen(newPath -> redisTemplate.opsForValue()
.set(newPath.getBytes(), url, Duration.ofDays(365)))
.filterWhen(newPath -> redisTemplate.opsForValue()
.set(sha256, newPath, Duration.ofDays(365)))
.flatMap(newPath -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(ImmutableMap.of("url", urlPrefix + newPath)))
.switchIfEmpty(ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(ImmutableMap.of("errorMsg", "Internal Server Error"))));
});
}
这个代码,说实话,一周后估计我自己都看不懂了。
其实我想问一下,针对逻辑稍微比较复杂的时候,响应式编程该怎么做,尤其是对这种条件分支比较多的时候。
这个代码该怎么优化?
现在我做的分支处理不外乎两种方式