当前位置: 首页 > 知识库问答 >
问题:

Spring反应式Mongo路由器处理程序中的UpdateById方法

子车睿
2023-03-14

在Spring ReactiveJava如何使用路由器和处理程序编写updateById()方法?

例如,路由器有以下代码:

RouterFunctions.route(RequestPredicates.PUT("/employees/{id}").and(RequestPredicates.accept(MediaType.APPLICATION_JSON))
    .and(RequestPredicates.contentType(MediaType.APPLICATION_JSON)),
        employeeHandler::updateEmployeeById);

我的问题是如何编写雇员处理程序::update雇员ById()保持ID不变,但更改雇员对象的其他成员?

java prettyprint-override">public Mono<ServerResponse> updateEmployeeById(ServerRequest serverRequest) {
    Mono<Employee> employeeMono = serverRequest.bodyToMono(Employee.class);

    <And now what??>

    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(employeeMono, Employee.class);
}

Employee类如下所示:

@Document
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class Employee {

    @Id
    int id;
    double salary;

}

谢谢你的帮助。

共有2个答案

锺离浩慨
2023-03-14

上述的一个稍有不同的版本毫无例外地发挥了作用:

public Mono<ServerResponse> updateEmployeeById(ServerRequest serverRequest) {

        Mono<ServerResponse> notFound = ServerResponse.notFound().build();

        Mono<Employee> employeeMono = serverRequest.bodyToMono(Employee.class);
        Integer employeeId = Integer.parseInt(serverRequest.pathVariable("id"));

        employeeMono = employeeMono.flatMap(employee -> employeeRepository.findById(employeeId)
                .map(foundEmployee -> {                 
                    foundEmployee.setSalary(employee.getSalary());
                    return foundEmployee;
                })
                .flatMap(employeeRepository::save));

        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(employeeMono, Employee.class).switchIfEmpty(notFound);
    }

感谢斯捷潘·齐布尔斯基。

李康安
2023-03-14

首先,您必须在类路径中添加ReactiveMongoRepository。你也可以在这里读到。

    @Repository
    public interface EmployeeRepository extends ReactiveMongoRepository<Employee, Integer> {
        Mono<Employee> findById(Integer id);
    }

然后,updateEmployeeById方法可以具有以下结构:

    public Mono<ServerResponse> updateEmployeeById(ServerRequest serverRequest) {
    return serverRequest
            .bodyToMono(Employee.class)
            .doOnSubscribe(e -> log.info("update employee request received"))
            .flatMap(employee -> {
                Integer id = Integer.parseInt(serverRequest.pathVariable("id"));
                return employeeRepository
                        .findById(id)
                        .switchIfEmpty(Mono.error(new NotFoundException("employee with " + id + " has not been found")))

                        // what you need to do is to update already found entity with
                        // new values. Usually map() function is used for that purpose
                        // because map is about 'transformation' what is setting new
                        // values in our case
                        .map(foundEmployee -> {
                            foundEmployee.setSalary(employee.getSalary());
                            return foundEmployee;
                        });
            })
            .flatMap(employeeRepository::save)
            .doOnError(error -> log.error("error while updating employee", error))
            .doOnSuccess(e -> log.info("employee [{}] has been updated", e.getId()))
            .flatMap(employee -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(employee), Employee.class));
}

更新:

根据Prana的回答,我已经更新了上面的代码,将我们的解决方案合并到了一起。添加了Slf4j帮助下的日志记录。和switchIfEmpty()用于未找到实体的情况。

我还建议您阅读关于全局异常处理的文章,这将使您的应用编程接口更好。其中一部分我可以在这里提供:

/**
 * Returns routing function.
 *
 * @param errorAttributes errorAttributes
 * @return routing function
 */
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
    return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}

private HttpStatus getStatus(Throwable error) {
    HttpStatus status;
    if (error instanceof NotFoundException) {
        status = NOT_FOUND;
    } else if (error instanceof ValidationException) {
        status = BAD_REQUEST;
    } else {
        status = INTERNAL_SERVER_ERROR;
    }
    return status;
}

/**
 * Custom global error handler.
 *
 * @param request request
 * @return response
 */
private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {

    Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);

    Throwable error = getError(request);
    HttpStatus errorStatus = getStatus(error);

    return ServerResponse
            .status(errorStatus)
            .contentType(APPLICATION_JSON)
            .body(BodyInserters.fromValue(errorPropertiesMap));
}
 类似资料:
  • 我一直在玩Spring Cloud Stream应用程序启动器中的路由器接收器,我对内容类型有一个问题。 我正在向路由器发送一个JSON字符串,我想编写一个SpEL表达式来确定路由。但是,即使我通过修改项目中的JUnit测试用例来运行它,“有效负载”也会显示为字符串,而不是解析的JSON。当为过滤器处理器运行JUnit测试用例时,也是在Spring Cloud Stream App Starter

  • 问题内容: 我需要react-router v2 +的帮助,例如,当路由更改时,我必须更改navbar的类,因为它将 尝试在navbar组件中使用,但它显示 希望你的帮助 问题答案: 您的组件(如您在问题中所描述的)可能不是路由组件,对吗?通过我的意思是你在使用一个被加载特定路由配置。 仅可通过此类访问,因此您需要将其传递给您。 让我们举个例子: 您的路由器配置: 路线部分:

  • 考虑以下事项: 我有一个应用模板,一个HeaderTemboard,和参数化的路由集与相同的处理程序(在应用模板)。我希望在没有找到东西的时候能够服务404路线。例如, /CA/SanFrancisco应该由区域查找和处理,而 /SanFranciscoz应该是404。 下面是我如何快速测试路线的。 问题是 /SanFranciscoz总是由区域页面处理,但我希望它是404。此外,如果我向第一个路

  • 在以下React应用程序中,有两个路由URLhttp://myapp 正确布线到布局构件。但是,URLhttp://myapp/login 也路由到布局组件,而不是登录。如果我将path=“/login”更改为“/sign”,它将正确路由到登录组件。 React路由器中的“/login”路径将其路由到路由是否有特殊之处?或者我设置这个路由的方式有错误吗?

  • 问题内容: 在安装组件之前进行授权检查的最佳实践是什么? 我使用react-router 1.x 这是我的路线 这是我的仪表板组件: 问题答案: 更新了 React Router v4的* 解决方案 * 反应路由器到v3 使用’onEnter’事件并在回调中检查用户是否被授权: