如何在 spring 中创建一个后映射方法,以便客户端只需要输入部分对象而不是完整对象?
How to create a postmapping method in spring so that clients need only enter a partial object instead of full object?
这是我的 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;
}
现在在我的休息控制器中我有一个像这样的post映射方法
// 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?
}
所以从 post 人,我正在向这个端点发送一个 post 请求(当然要更改 ID),正文如下
{
"currentlyWatching" : [...some new stuff]
}
然而,我的 old
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 个字段(不仅仅是 currentlyWatching
和 completed
)。我想要一些动态的简单方法来做到这一点。无论如何,手动执行此操作可能不是最佳设计实践。
Extra Info
:
我正在使用 spring data mongo
以便 @Document
注释或存储库 class(扩展 MongoRepository)来自 mongo 罐子。此外,如果它很重要,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>
现在你需要创建另一个class(class名称可以是任何东西)如下:
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
的子 class,它扩展了 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;
这里我们检查是value is null
还是if value is a List
,是list empty
,然后我们跳过复制操作。因此,使用这种方法,如果用户从邮递员发送部分对象(例如),我们将只复制用户一直在其中放置一些东西的那些字段,而不更改目标 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;
}
现在在我的休息控制器中我有一个像这样的post映射方法
// 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?
}
所以从 post 人,我正在向这个端点发送一个 post 请求(当然要更改 ID),正文如下
{
"currentlyWatching" : [...some new stuff]
}
然而,我的 old
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 个字段(不仅仅是 currentlyWatching
和 completed
)。我想要一些动态的简单方法来做到这一点。无论如何,手动执行此操作可能不是最佳设计实践。
Extra Info
:
我正在使用 spring data mongo
以便 @Document
注释或存储库 class(扩展 MongoRepository)来自 mongo 罐子。此外,如果它很重要,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>
现在你需要创建另一个class(class名称可以是任何东西)如下:
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
的子 class,它扩展了 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;
这里我们检查是value is null
还是if value is a List
,是list empty
,然后我们跳过复制操作。因此,使用这种方法,如果用户从邮递员发送部分对象(例如),我们将只复制用户一直在其中放置一些东西的那些字段,而不更改目标 pojo 中的其他字段(已经有旧内容) .