java - 如何在spring中创建postmapping方法,以便客户端只需要输入部分对象而不是完整对象?

标签 java spring post jackson pojo

这是我的pojo

// Removed getters, setters, constructors for brevity, Also don't worry about Movie pojo
@Document
public class WatchList {
    @Id
    private String _id;
    private List<Movie> currentlyWatching;
    private List<Movie> completed;
}

现在在我的休息 Controller 中,我有一个像这样的后映射方法

// Here id is the id of watchList I want to update
@PostMapping("/{id}/update")
public void updateItem(@PathVariable String id, @RequestBody WatchList watchList){
    WatchList old = watchListRepo.findById(id).get();  
    // Now update old with contents from watchList. However only change those fields that are sent from @RequestBody. How to do this?
}

因此,从 postman 那里,我正在向此端点发送一个 post 请求(当然要更改 id),正文如下

{
    "currentlyWatching" : [...some new stuff]
}

但是,我的 watchList pojo 已经有这样的东西:

{
    "currentlyWatching" : [...some old stuff],
    "completed" : [...some old stuff],
}

现在,一旦这个方法完成,我希望我的 pojo 变成这个

{
    "currentlyWatching" : [...some new stuff], // so this gets updated from post request
    "completed" : [...some old stuff], // this stays the same since post request body did not contain this field called completed
}

因此,我本质上只想在客户端发送正文包含 currentlyWatching 的 post 请求时更新 currentlyWatching 字段。现在我当然可以检查字段并手动映射它,但我的 WatchList 并不像此处所示的那么简单。它有超过 10 个字段(不仅仅是 currentlyWatchingcompleted)。我想要一些动态的简单方法来做到这一点。而且手动执行此操作的方式可能不是最佳设计实践。

额外信息: 我正在使用 spring data mongo,以便 @Document 注释或存储库类(扩展 MongoRepository)来自 mongo jar。另外,如果它很重要的话,Movie pojo 是另一个具有嵌套属性的 pojo。但是我想要一种动态地执行此操作的方法,因此 Movie pojo 可以是任何东西。因此,我们在这里找到的解决方案应该适用于任何 Movie pojo Schema。我还听说过一种叫做 BeanAwareUtils 的东西,它可以在这里使用吗?

最佳答案

这是我在网上搜索后发现的一种方法。您可以使用 BeanUtils。这是它的maven依赖(使用时请务必检查更新的版本)。

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

现在您需要创建另一个类(className 可以是任何内容),如下所示:

public class NullAwareBeanArrayUtilsBean extends BeanUtilsBean {

    @Override
    public void copyProperty(Object dest, String name, Object value) throws IllegalAccessException, InvocationTargetException {
        if (value == null || (value instanceof List<?> && ((List<?>) value).size() <= 0))
            return;
        super.copyProperty(dest, name, value);
    }

}

当您想在代码中的其他位置使用它时,请像这样使用它:

BeanUtilsBean notNull = new NullAwareBeanArrayUtilsBean();
notNull.copyProperties(dest, original);

说明

BeanUtils 是一个库,它具有一种将属性从一个 pojo 复制到另一个 pojo 的方法。它有一个 copyProperties 方法,该方法在内部调用 copyProperty 方法。在这里,我们创建了一个名为 NullAwareBeanArrayUtilsBean 的子类,它扩展了 BeanUtilsBean,并且我们为其名为 copyProperty 的方法之一提供了自定义功能。

请记住,此方法是从 copyProperties 方法内部调用的。您可以尝试在此 copyProperty 方法中控制台记录 name,以查看 name 引用了 pojo 中的 each 字段。

我们在自定义重写的 copyProperty 方法中做什么?

考虑这一行

BeanUtilsBean notNull = new NullAwareBeanArrayUtilsBean();
notNull.copyProperties(dest, original);

这里我们说的是,我们要将内容从original pojo复制到dest pojo。

对于 pojo 中的每个字段,copyProperties 在内部调用名为 copyProperty 的自定义重写方法。

考虑 copyProperty 方法的第一行:

if (value == null || (value instanceof List<?> && ((List<?>) value).size() <= 0)) return;

这里我们检查值是否为空如果值是一个列表并且列表是否为空,那么我们将跳过复制手术。因此,通过这种方法,如果用户从 postman 发送部分对象(例如),我们将仅复制用户一直在其中放置一些内容的那些字段,同时不更改目标 pojo 中的其他字段(已经有旧内容) .

关于java - 如何在spring中创建postmapping方法,以便客户端只需要输入部分对象而不是完整对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53918429/

相关文章:

java - 每小时运行一次java函数

java - 测试 Spring Boot REST API

java - 升级到 JAVA 8 后 Threadlocal 在 tomcat 上的不当行为

http - Go:跟踪POST请求进度

c# - ASP.Net 使用重定向创建服务器端发布到外部网站

java - double 组——最常见的值方法? (没有 HashMap 或排序)

java - 最小化空 PartStack 抛出异常

java - 无法找到 Spring Boot javabean

javascript - 在 POST AngularJS 上更改按钮样式

java - 从输入流 Java 解析 XML