使用Jackson通过AJAX从Spring MVC控制器返回java.util.List

时间:2012-08-08 00:24:43

标签: java json ajax spring-mvc jackson

基于几天前发布的my question,我意识到SimpleFormController不适合处理Ajax请求。因此,我正在将我的应用程序迁移到带注释的控制器。

我正在尝试使用Spring MVC 3.0.2和Hibernate通过Ajax使用Jackson 1.9.8(下载page)从Oracle数据库返回java.util.List但我还没有工作过在任何技术中使用JSON。我已经阅读了一些教程/文章,但我无法理解如何返回这样复杂的数据结构并在Spring中使用JSON解析它们。我试图首先学习类似JSON的概念。

我正在尝试的是,当从国家/地区选择框中选择国家/地区时,应通过Ajax从数据库填充与该国家/地区对应的州。我不知道如何在Ajax响应上返回java.util.List,如何解析它并在Java代码中再次使用它。我只达到以下水平。

JS代码。

function getStates(countryId)
{
    $.ajax({
        datatype:"json",
        type: "POST",
        url: "/wagafashion/ajax/TempAjax.htm",
        data: "countryId=" + countryId,

        success: function(response)
        {
            $('#msg').html(response);
            $('#stateList').val('');
        },
        error: function(e)
        {
            alert('Error: ' + e);
        }
    });
}

Spring控制器类中的方法,当在国家/地区选择框的onchange事件上发出Ajax请求时调用该方法。

@RequestMapping(method=RequestMethod.POST, value="ajax/TempAjax")
public @ResponseBody List<StateTable> getStateList(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response)
{
    Session session=NewHibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();
    List<StateTable>list=session.createQuery("from StateTable where country.countryId=:countryId order by stateId").setParameter("countryId", new BigDecimal(request.getParameter("countryId"))).list();

    session.flush();
    session.getTransaction().commit();
    return list;
}

状态选择框我需要使用<c:forEach></c:forEach> EL循环填充Ajax响应返回的状态列表。

<form:select path="cmbState" class="validate[required] text-input tooltip" title="Mandatory select field.">
    <form:option value="">Select</form:option>

    <c:forEach items="${stateList}" var="row">
        <c:choose>
            <c:when test="${row.stateId==param['stateId'] and deselectCombo!=1}">
                <form:option value="${row.stateId}" selected="selected">${row.stateName}</form:option>
            </c:when>
            <c:otherwise>
                <form:option value="${row.stateId}">${row.stateName}</form:option>
            </c:otherwise>
        </c:choose>
    </c:forEach>
</form:select>

<font style="color: red"><form:errors path="stateId"/></font><br/>

我只能成功地进行Ajax请求和响应。通过互联网找到的那些教程我无法理解。更准确地说,我如何在前一个items循环的<c:forEach><c:forEach>属性中使用Ajax响应,例如items="${stateList}"

你能否给我一些提示/想法如何返回数据列表并在前面的循环中使用它来填充状态选择框?你能不能在这里向我提前几步?

我正在使用NetBeans 6.9.1(不是Eclipse)。在一些关于Eclipse中Marvan项目的教程中,有人提到需要配置pom.xml文件来包含<dependencies></dependencies>(杰克逊依赖)。在我的NetBeans项目中没有像pom.xml这样的东西。是否需要在NetBeans中的某个xml文件中的某处配置,例如提到的here

2 个答案:

答案 0 :(得分:13)

您应该使用的策略是从jQuery调用AJAX,使用JSON响应并使用它从jQuery而不是java动态更新表单。我可以看到的JSP标记的唯一用途是在加载时呈现页面。以下是我将如何处理这个......

  1. 将您的控制器更改为使用GET而不是POST。首先,在REST中使用POST是不正确的(您只检索数据,而不是更改数据)。但更重要的是,通过简单地将URL放入浏览器以查看JSON响应,您可以更轻松地测试控制器。使用@ResponseBody注释并在类路径中包含Jackson应该在这里产生一个JSON响应(除非你有一些Hibernate延迟加载问题)。

  2. 验证控制器返回JSON后,更新jQuery成功处理程序以动态填充下拉列表。这应该相对容易。在浏览器中测试。

  3. 编写一个新控制器来处理此表单提交。在此控制器中,只需包含一个返回列表的方法,并将其注释为@ModelAttribute("stateList")。这将使列表可用于<c:forEach>循环以在加载时呈现页面。您将拥有另一种方法来处理同一控制器中的实际表单提交。

  4. 要考虑的另一件事是通过将数据库代码放在自己的服务或存储库中来更好地分离关注点。在MVC架构中的控制器中进行数据访问是一种不好的做法。作为奖励,您不需要复制任何代码来将列表加载到两个不同的控制器中。

    另外,请查看Spring的@Transactional声明式事务处理。这样您就不需要为事务处理编写任何代码。您也可以简单地注入SessionFactory而不是编写自己的HibernateUtils

    希望有所帮助

    编辑:在REST中,这里是映射到相应CRUD操作的HTTP方法。

    • 发布 - 创建
    • 获取 - 检索
    • PUT - 更新
    • 删除 - 删除

答案 1 :(得分:4)

你应该尝试在ajax响应中选择你的选项列表而不是像json一样

<option value="1">Mumbai</option>
<option value="2">Delhi</option>
<option value="3">Kerala</option>
<option value="4">Rajasthan</option>

然后你应该把它添加到你的选择框下面一个

function getStates(countryId)
{
    $.ajax({
    datatype:"html",
    type: "POST",
    url: "/wagafashion/ajax/TempAjax.htm",
    data: "countryId=" + countryId,

    success: function(response)
    {
        $('#stateList').html(response);
    },
    error: function(e)
    {
        alert('Error: ' + e);
    }
  });
}

或者您可以在服务器端创建json,如下面的

[{"key":1, "value": "Mumbai"}, {"key":2, "value":"Delhi"}....]

和javascript代码

function getStates(countryId)
{
    $.ajax({
    datatype:"html",
    type: "POST",
    url: "/wagafashion/ajax/TempAjax.htm",
    data: "countryId=" + countryId,

    success: function(response)
    {
         if(response !=''){
              jQuery("#stateList").html("");
              jQuery.each(response, function(index,item) {
                jQuery("#stateList").append(jQuery("<option />")
                .attr("value",item.value)
                .text(item.key)); 
            });
         }

    },
    error: function(e)
    {
        alert('Error: ' + e);
    }
  });
}