有一个Java spring MVC web应用程序,我正在发出一个jquery ajax post请求。我的控制器设置为接收和发送json数据。一切正常,JSON字符串格式良好,控制器可以创建和填充命令对象,并用JSON请求数据的内容填充它。然而,我正在更新联系人对象的数据,我的JSP表单元素只包含DB更新所需的所有数据的子集。在带有表单的JSP页面的初始GET请求中,我从DB中检索所有必要的数据,填充一个Contact命令对象,然后将该命令对象绑定到模型。
如果我在做一个普通的POST submit表单提交,我相信只要将我的命令对象声明为@SessionAttribute,并在onSubmit()POST方法中使用@modeldattribute引用该命令对象就足够了。Spring将从我的会话中检索已经填充的命令对象,然后绑定(覆盖)那些由于POST请求而更改的值。然后,可以将此更新的命令对象用作DB更新的参数。
然而,我正在使用Spring 3并利用@RequestBody参数类型。我无法让Spring既给我会话对象,又自动绑定请求中的新值。它要么只给我旧的会话命令对象(不应用更改),要么给我一个新的命令对象,其中只包含POST请求中的值。
这是一个小代码-不起作用:
@SessionAttributes("contactCommand")
@Controller
public class ContactController {
@RequestMapping(value = "/editContact", method=RequestMethod.GET)
public String init(ModelMap model, Locale locale, HttpServletRequest request, HttpServletResponse response) throws GeneralException {
final ContactCommand cmd = new ContactCommand();
// populate with data from DB etc
model.addAttribute("contactCommand", cmd);
// etc
}
@RequestMapping(value="/editContact",method=RequestMethod.POST, consumes = "application/json", produces = "application/json")
public @ResponseBody Map<String, ? extends Object> editContactInfo(@RequestBody @ModelAttribute("contactCommand") ContactCommand cmd, HttpServletRequest request, HttpServletResponse response) throws GeneralException {
// do business logic with command object here
}
有人能告诉我什么是“标准”或“最简单”的方法来使用@Request estbody和JSON请求数据,并使其绑定到现有的/@ModelAtort填充的命令对象,以便命令对象完全由旧数据和新数据构成(以同样的方式,使用完整的POST超文本传输协议提交很容易实现)。
一个相关的问题是上面的代码有什么问题?带有JSON内容的@SessionAttribute和@RequestBody可以一起使用吗?如果是,请解释如何!非常感谢您的任何意见。
我的解决方法是让Spring创建新的命令对象并自动填充表单数据。然后从会话中手动单独调用/检索旧的命令对象,最后手动将表单提交中不存在的所有属性复制到新的命令对象中。现在,我在一个命令对象中拥有了所有必要的数据,可以应用SQL更新。一定有更简单的方法……;)
更新时间:
今天在进一步研究这个问题时发现了这个SOF帖子:
Spring部分更新对象数据绑定
似乎没有现成的已知SPRING解决方案,但需要知道处理它的最佳方法。在我的例子中,是的,我使用的是嵌套的域对象,因此本文提供的解决方法并不好。有人有其他想法吗?明确地说,我希望将JSON格式的数据发布到控制器(而不仅仅是http格式的POST数据)。
好的,我已经为这个打开了一个Spring Source JIRA请求,也许这是一个非常需要的改进:
https://jira.springsource.org/browse/SPR-10552
或者,这是一个以聪明的方式利用Jackson转换功能的案例,听起来像是很多管道。
为什么要使用@Request estbody注释ModelAtort,在JSON的情况下,只需使用@SessionAtcm并使用@ModelAtcm引用该命令对象就足够了。
您使用@Request estbody的动机是什么
看见http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html和
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html
这不是一个完整的答案,但我希望它能为你指明正确的方向。
下面是一个类,我们使用它使用Jackson将JSON深度绑定到现有对象。此处改编自Jackson的一份bug报告:https://jira.springsource.org/browse/SPR-10552
public class JsonBinder
{
private ObjectMapper objectMapper;
public JsonBinder( ObjectMapper objectMapper )
{
super();
this.objectMapper = checkNotNull( objectMapper );
}
public void bind( Object objToBindInto, InputStream jsonStream ) throws JsonProcessingException, IOException
{
JsonNode root = objectMapper.readTree( checkNotNull( jsonStream ) );
applyRecursively( checkNotNull( objToBindInto ), root );
}
private void applyRecursively( Object objToBindInto, JsonNode node ) throws JsonProcessingException, IOException
{
PropertyAccessor propAccessor = null;
for( Iterator<Entry<String, JsonNode>> i = node.fields(); i.hasNext(); )
{
Entry<String, JsonNode> fieldEntry = i.next();
JsonNode child = fieldEntry.getValue();
if( child.isArray() )
{
// We ignore arrays so they get instantiated fresh every time
// root.remove(fieldEntry.getKey());
}
else
{
if( child.isObject() )
{
if( propAccessor == null )
{
propAccessor = PropertyAccessorFactory.forDirectFieldAccess( objToBindInto );
}
Object o2 = propAccessor.getPropertyValue( fieldEntry.getKey() );
if( o2 != null )
{
// Only remove the JsonNode if the object already exists
// Otherwise it will be instantiated when the parent gets
// deserialized
i.remove();
applyRecursively( o2, child );
}
}
}
}
ObjectReader jsonReader = objectMapper.readerForUpdating( objToBindInto );
jsonReader.readValue( node );
}
}
我们将其与Spring的HandlerMethod odArgumentResolver的实现一起使用。
我们没有使用很多Spring的MVC框架。我们只是使用Spring的许多不同部分构建一个JSON API后端。让它全部工作是相当多的管道,但现在我们的控制器非常简单。
不幸的是,我不能显示我们所有的代码,反正代码很长。我希望这至少解决了部分问题。
最近我正在努力学习SpringMVC。似乎我没有很好地理解@SessionAttributes和@ModelAttribute注释的功能。 这是我的控制器的一部分: 基本上有一个jsp列出所有的项目。用户点击"addToCart"获取特定商品,该商品将被添加到购物车列表中。我最好先解释一下我对这个控制器的理解,你可以告诉我我没有得到什么。 第一次调用ItemController时,将执行creat
我尝试使用和通过Postman发送JSON和多个文件,但它不起作用。有可能在API中同时使用这两个注释吗?
我有一个问题,在我的应用程序Android中使用soap请求。我使用Ksoap2库。这是我的代码: }
我有一个控制器,它的GET方法是这样写的: bean是正确的(getter和setter),服务调用返回带有thingId的正确ThingBean,并且显示了我在edit.jsp的JSP页面。 JSP是: 但是,JSP 显示主题和消息的空白值。是的,这些属性上有吸气剂/二传手。 我有一个非常相似的控制器,工作得很好,除了GET - mapped方法的签名中没有@RequestParam。 我在Sp
我不能用HttpEntity调用Spring RestTem板进行POST请求。我调用RestTem板给出Base64字符串在邮递员,但使用我的java实现,它会给出以下错误: 我的实施是: 我尝试过以下解决方案,但在这里不起作用 这个我也提到过这个
我有一些应用程序在Spring boot中使用微服务架构。我已经在RestTemplate中使用@PathVariable发送了查询参数、对象、模型等。开发应用程序后,我做了一些研究,要求使用@RequestParam和@RequestBody。但我无法理解,也不知道如何使用@RequestBody和@RequestParam。使用@RequestBody而不是@PathVariable有什么好处