我想对资源执行部分更新。我有一个想法,我可以结合使用@ModelAttribute(以加载现有资源)和@RequestBody,以使用提供的字段填充它,然后运行@Valid。据我了解,@ModelAttribute首先被调用。
我的控制器调用ModelAttribut,并使用我的ContentPatternConverter正确创建ContentPattern实体。尽管完成之后,我想用@RequestBody提供的字段填充“模式”,最后检查它是否有效。虽然我的ContentPattern通过ModelAttribute创建之后没有填充RequestBody。
@RequestMapping(value = "/patterns/{id}", method = RequestMethod.PUT, produces = "application/json")
@ResponseBody
public ResponseEntity<ContentPattern> updateContentPattern(Principal principal, @ModelAttribute("id") @RequestBody ContentPattern pattern) { //implementation }
有什么想法如何使用我的方法解决这个问题,或者是否有另一个(更好的)解决方案?
更新1
经过更多研究后,我提出了以下解决方案。
创建了我自己的注释@RequestBodyPathVariable
编写了实现HandlerMethodArgumentResolver的RequestBodyPathVariableMethodArgumentResolver。它的作用是1)基于URI路径变量(例如,patterns / {id})从自定义转换器获取现有资源。 2)从请求主体创建一个对象。 3)合并现有资源和提供的资源。 4)验证最终对象。 5)返回最终对象
请参见要点以获取源代码:https://gist.github.com/2687913
(在其他情况下,可能需要更好/其他合并方法。)
有用的网址:
http://blog.42.nl/articles/leveraging-the-spring-mvc-3.1-handlermethodargumentresolver-interface
http://stackoverflow.com/questions/6591665/merging-two-objects-in-java
最佳答案
我在考虑这个,这是我会做的事情(免责声明,我没有尝试过):
首先,@ModelAttribute仅在您要将对象传递给视图时才起作用。
@RequestBody允许Spring解析您的输入主体(假设它是Json)并构建ContentPattern对象。但是您想从存储库中获取该对象,然后更新相关字段。
首先,我将创建WebArgumentResolver的实现。使用MethodParameter来检查它是否来自ContentPattern类。此实现将以Dependency Injection的形式接收您用于创建ContentPattern对象的HttpMessageConverter。
然后从HttpInputMessage创建一个NativeWebRequest,如下所示:
return new ServletServerHttpRequest((HttpServletRequest)nativeWebRequest.getNativeRequest());
然后,使用Converter创建您的ContentPattern对象。该对象将填充一些字段,您要更新的字段以及其标识符。
使用标识符,存储库或EntityManager持久性上下文(均由Spring注入到类中),您可以从存储库中获取对象。
现在,您有两个ContentPattern对象,一个是从存储库获取的,另一个是从请求正文创建的。
使用对象的设置器,使用另一个对象的字段更新存储库中的对象,然后使用Spring注入到此类的Validator进行验证。
如果一切正常,则可以选择将已更新的对象保存为持久性,并将其用作resolverArgument方法的返回值。
我希望这足够清楚!