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

Posted

技术标签:

【中文标题】使用 Jackson 通过 AJAX 从 Spring MVC 控制器返回 java.util.List【英文标题】:Returning a java.util.List from a Spring MVC controller via AJAX using Jackson 【发布时间】:2012-08-05 01:27:13 【问题描述】:

根据几天前发布的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);
        
    );

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

@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;

我需要使用 EL 的 &lt;c:forEach&gt;&lt;/c:forEach&gt; 循环使用 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 请求和响应。从互联网上找到的那些教程中,我无法理解更多内容。更准确地说,如何在前面的&lt;c:forEach&gt;&lt;c:forEach&gt; 循环(例如items="$stateList")的items 属性中使用Ajax 响应?

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

我使用的是 NetBeans 6.9.1(不是 Eclipse)。在一些关于 Eclipse 中 Marvan 项目的教程中,提到需要配置 pom.xml 文件以包含 &lt;dependencies&gt;&lt;/dependencies&gt;(杰克逊依赖项)。在我的 NetBeans 项目中没有像 pom.xml 这样的东西。是否需要在 NetBeans 的某个 xml 文件中的某个位置进行配置,例如提到的here?

【问题讨论】:

我不确定我是否理解这个问题。 &lt;c:forEach&gt; 是一个 JSP 标签,因此在服务器端执行。当呈现的 HTML 到达客户端的浏览器(将在其中发出 AJAX 请求)时,代码将已经执行。 @Deejay-你是对的。从一个 选择框 中选择一个项目并基于通过 Ajax 请求传递的值填充其后续 选择框 是一件非常基本且非常常见的事情。我在问其他人他们如何在 Spring MVC 中做这些事情。这并不意味着事情应该只以我在这里指出的方式发生。这是我想到的事情,我的假设可能错误。我可以想到 Ajax 的 XML 响应,但在这里,我认为这不会发生,因为控制器必须映射到可能返回复杂数据结构的 JSP 页面 请看下面hyness的回答。您需要使用 jquery 而不是服务器端代码来更改 HTML。另一种方法是返回 html 而不是 json(在 ajax 上),但我更喜欢前一种方法。 【参考方案1】:

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

    将您的控制器更改为使用 GET 而不是 POST。一方面,在 REST 中在这里使用 POST 是不正确的(您只是在检索数据,而不是更改它)。但是,更重要的是,只需将 URL 放入浏览器以查看 JSON 响应,您就可以更轻松地测试控制器。使用 @ResponseBody 注释并在类路径中包含 Jackson 应该会在此处生成 JSON 响应(除非您有一些 Hibernate 延迟加载问题)。

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

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

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

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

希望有帮助

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

POST - 创建 GET - 检索 PUT - 更新 删除 - 删除

【讨论】:

INSERTUPDATEDELETE 为例,在更改RESTful 控制器(或带注释的控制器)中的数据时使用POST 方法是否合适?那么数据的检索(SELECT)呢?只有GET 方法合适吗?他们(GETPOST)不应该互换使用吗?顺便说一句,我已经成功完成了问题中提到的任务。谢谢。 我很高兴听到您成功了。我在上面的答案中添加了 HTTP 方法以及它们如何与 CRUD 方法相关,取自wikipedia【参考方案2】:

您应该尝试在 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);
    
  );

【讨论】:

以上是关于使用 Jackson 通过 AJAX 从 Spring MVC 控制器返回 java.util.List的主要内容,如果未能解决你的问题,请参考以下文章

Ajax请求

JackSon与AJAX的简单操作

校验用户名是否存在(ajax+jackson)

com.fasterxml.jackson.databind.JsonMappingException:java.util.Optional 不能转换为 java.time.LocalDate

使用 lombok @Builder 时通过 Jackson 反序列化“2021-09-24 00:00:00”日期格式

Ajax案例:简易的购书网页