Spring 3 AJAX POST请求与@RequestBody和@ModelAttribute和@SessionAttribute一起使用? [英] Spring 3 AJAX POST request with @RequestBody and @ModelAttribute and @SessionAttribute used together?

查看:1942
本文介绍了Spring 3 AJAX POST请求与@RequestBody和@ModelAttribute和@SessionAttribute一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个Java spring MVC web应用程序,并且做一个jquery ajax post请求。我的控制器设置为接收和发送json数据。一切正常,JSON字符串格式良好,Controller可以创建并填充Command对象并使用JSON请求数据的内容填充它。但是,我正在更新Contact对象的数据,并且我的JSP表单元素只包含数据库更新所需的所有数据的子集。在我对JSP页面的初始GET请求中,使用从数据库检索所有必需数据的形式,填充Contact Command对象,然后将该命令对象绑定到模型。

Have a Java spring MVC web app, and am making a jquery ajax post request. My Controller is setup to receive and send json data. Everything works, the JSON string is well formatted, and the Controller can create and populate a Command object and populate it with the contents of the JSON request data. However, I am updating data for a Contact object, and my JSP form element only contains a subset of all the data required for the DB update. In my initial GET request for the JSP page with the form I retrieve all the necessary data from the DB, populate a Contact Command object, and then bind that command object to the Model.

如果我正在进行正常的POST提交表单提交,我相信只是声明我的命令对象作为@SessionAttribute,并使用@ModelAttribute在我的onSubmit )POST方法就足够了。 Spring将从我的会话中检索已经填充的命令对象,然后绑定(覆盖)作为POST请求的结果而更改的那些值。这个更新的命令对象然后可以用作数据库更新的参数。

If I were doing a normal POST submit form submission, I believe that just declaring my command object as @SessionAttribute, and referencing that Command object using @ModelAttribute in my onSubmit() POST method would be sufficient. Spring would retrieve the already populated command object from my session and then bind (overwrite) those values that have changed as a result of the POST request. This updated command object could then be used as the parameter for a DB update.

但是,我使用Spring 3并利用@RequestBody参数类型。我不能得到Spring既给我会话对象,并自动绑定来自请求的新值。它给我只是旧的会话命令对象(不应用更改)或新的命令对象,只有来自POST请求的值。

However, I am using Spring 3 and leveraging @RequestBody paramater type. I cannot get Spring to both give me the session object and automatically bind the new values from the request. It either gives me just the old session command object (without applying the changes) or a new Command Object with only the values from the POST request.

这里是一个小代码 - 不工作:

Here is a little code - doesn't work:

@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

}

任何人都可以告诉我什么是标准或最简单的方式使用@RequestBody JSON请求数据并绑定到现有的/ @ModelAttribute填充的Command对象,以便Command对象完全由旧数据和新数据构成(以相同的方式使用完整的POST http提交轻松实现)。

Can anyone please tell me what is the "standard" or "easiest" way to use @RequestBody with JSON request data and make that bind to an existing / @ModelAttribute populated Command object so that the Command object fully constituted with both old and new data (in the same way it is easily achieved using a full POST http submit).

一个相关的问题是上面的代码有什么问题?可以@SessionAttribute和@RequestBody与JSON内容一起使用吗?如果是这样,请解释一下!非常感谢您的任何投入。

A related question is what is wrong with the code above? Can @SessionAttribute and @RequestBody with JSON content all be used together? If so, please explain how! Thank you so much for any input.

我的工作是让Spring创建一个新的Command对象,并自动填充表单数据。然后从会话手动单独调用/检索旧的命令对象,最后手动将表单提交中不存在的所有属性复制到新的命令对象中。现在我有一个命令对象的所有必要的数据在一起应用我的SQL更新。必须有一个更简单的方法....;)

My work around is to let Spring create the new Command object and auto-populate with form data. Then make a separate call / retrieve manually from session the old command object, finally manually copy all those attributes that were not present in the form submission into the new command object. Now I have all the necessary data together in one command object to apply my SQL update with. There must be an easier way.... ;)

更新:

今天找到这个SOF进一步研究此问题:

Found this SOF post today while further researching this problem:

Spring部分更新对象数据绑定

似乎没有已知的SPRING解决方案开箱即用,但很多需求知道最好的处理方式。在我的情况下,是的,我使用嵌套的域对象,所以在该职位提供的解决方法是不好的。有没有任何其他的想法?要清楚,我希望POST的JSON格式的数据到控制器(不只是http形式的post数据)。

It appears there is no known SPRING solution out of the box but a lot of demand to know the best way to handle it. In my case, yes, I am using nested domain objects so the workaround offered in the post is no good. Does anyone have any other ideas? To be clear, I wish to POST JSON format data to the Controller (not simply http form post data).

好,我已经打开一个Spring源JIRA请求这个,也许这是一个急需改进:

Ok, I've opened a Spring Source JIRA request for this one, perhaps it is a much needed improvement:

https: //jira.springsource.org/browse/SPR-10552

或者,这是一个利用Jackson转换功能的聪明方式的声音像很多管道。

Or else, it is a case of leveraging the Jackson conversion capabilities in clever ways which sounds like a lot of plumbing.

推荐答案

这不是一个完整的答案,但我希望它会指向正确的方向。

This isn't a complete answer, but I hope it will point you in the right direction.

下面是一个类,我们使用它从JSON到使用Jackson的现有对象进行深层绑定。这是根据杰克逊的错误报告修改的: https://jira.springsource.org/browse/ SPR-10552

Following is a class that we use to do deep binding from JSON to an existing object using Jackson. This is adapted from a bug report for Jackson here: 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的HandlerMethodArgumentResolver 。

We use this along with a an implementation of Spring's HandlerMethodArgumentResolver.

我们不使用很多Spring的MVC框架。我们只是使用Spring的很多不同部分构建一个JSON API后端。

We don't use a lot of Spring's MVC framework. We are just building a JSON API backend using a lot of different parts of Spring. It is a pretty good amount of plumbing to get it all working, but now our controllers are very simple.

很遗憾,我无法显示所有的代码,它很漂亮长反正。我希望这至少解决了部分问题。

Unfortunately I can't show all of our code, it's pretty long anyways. I hope this solves at least part of the problem.

这篇关于Spring 3 AJAX POST请求与@RequestBody和@ModelAttribute和@SessionAttribute一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆