从spring mvc控制器返回一个简单的映射结构到ajax

Posted

技术标签:

【中文标题】从spring mvc控制器返回一个简单的映射结构到ajax【英文标题】:Returning a simple map structure from spring mvc controller to ajax 【发布时间】:2015-05-07 18:19:27 【问题描述】:

我正在使用 spring mvc 4 并尝试将简单的 map 返回到 ajax - 从我的控制器到 jsp 文件。

控制器:

    @RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, String> myTest() 
        System.out.println("------------------------------------test");

        Map<String,String> myMap = new HashMap<String, String>();
        myMap.put("a", "1");
        myMap.put("b", "2");
        return myMap;
    

来自jsp文件的Ajax:

function testAjax() 
        $.ajax(
            url : '../../ajaxtest.html',
            dataType: "json",
            contentType: "application/json;charset=utf-8",
            success : function(data) 
                alert("1");
                alert(data);
            
        );
    

但我没有收到任何警报,而只是收到错误 HTTP/1.1 406 Not Acceptable

但是,更改代码以返回一个简单的字符串可以正常工作。 控制器:

    @RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
    public @ResponseBody
    String myTest() 
        System.out.println("------------------------------------test");
        return "hello";
   

阿贾克斯:

function testAjax() 
        $.ajax(
            url : '../../ajaxtest.html',
            success : function(data) 
                alert("1");
                alert(data);
            
        );
    

按预期从 ajax 提醒 1hello

我按预期添加了 jackson jar 文件(通过 pom.xml):

dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.5.1</version>
    </dependency>

我错过了什么吗? 我只想返回一个简单的映射结构(或将来的其他类结构)。

更新: 从弹簧控制台(不确定它是否相关): Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

提前致谢! 迈克

【问题讨论】:

【参考方案1】:

我不知道它是否正确,但我解决了它。

在控制器中,我将地图转换为json:

    @RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
    public @ResponseBody
    String myTest() 
        System.out.println("------------------------------------random");

        Map<String,String> myMap = new HashMap<String, String>();
        myMap.put("a", "1");
        myMap.put("b", "2");
        ObjectMapper mapper = new ObjectMapper();
        String json = "";
        try 
            json = mapper.writeValueAsString(myMap);
         catch (JsonProcessingException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
        return json;

在jsp中:

function testAjax() 
        $.ajax(
            url : '../../ajaxtest.html',
            type:"GET",
            contentType: "application/json;charset=utf-8",
            success : function(data) 
                alert("1");
                alert(data);
                var obj = jQuery.parseJSON( data );
                alert(obj.a);
                alert(obj.b);
            
        );

谢谢大家! 麦克风

【讨论】:

没关系,但是您是否尝试按照我的建议进行配置。否则,您将不得不对每个需要 JSON 的请求进行手动操作,并且您失去了框架为您处理这些事情的意义【参考方案2】:

尝试将consumes="application/json"produces= "application/json"添加到@RequestMapping,让spring处理你的json

UPDATE 406 错误说明

HTTP 错误 406 不可接受

简介

客户端(例如您的 Web 浏览器或我们的 CheckUpDown 机器人)可以向 Web 服务器(运行网站)指示它将从 Web 服务器接收回的数据的特征。这是使用以下类型的“接受标头”完成的:

Accept:客户端接受的 MIME 类型。例如,浏览器可能只接受它知道如何处理的返回类型的数据(HTML 文件、GIF 文件等)。 Accept-Charset:客户端接受的字符集。 Accept-Encoding:客户端接受的数据编码,例如它理解的文件格式。 Accept-Language:客户接受的自然语言(英语、德语等)。 Accept-Ranges:客户端是否接受来自资源的字节范围,即资源的一部分。 如果 Web 服务器检测到它要返回的数据不被客户端接受,它会返回一个包含 406 错误代码的标头。

这意味着您应该以某种方式更改您的服务器逻辑以接受您从客户端发送的请求的 MIME/Charset/Encoding 等。不能确切地说出了什么问题,但尝试使用请求映射的标头和消耗。

【讨论】:

添加了@RequestMapping(value = "/ajaxtest", method = RequestMethod.GET, consumes="application/json", produces= "application/json")但没有解决问题...【参考方案3】:

您的“问题”是由于您的请求以.html 结尾。您需要添加以下配置以使其按预期工作

<bean id="contentNegotiationManager"              class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
    <property name="defaultContentType" value="application/json" />
</bean>

 <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />

而不是像 @StanislavL 建议的那样添加 produces= "application/json" 不要添加消耗,因为您没有发布任何 JSON

解释

当spring确定它转换成的表示时,它首先查看请求的路径部分(例如.html、.json、.xml),然后寻找显式设置转换表示的参数,最后寻找一个Accept header(所谓的 PPA 策略)

这就是您的示例有效的原因

function testAjax() 
        $.ajax(
            url : '../../ajaxtest.html',
            success : function(data) 
                alert("1");
                alert(data);
            
        );
    

您将返回 HTML。但是随着请求

function testAjax() 
        $.ajax(
            url : '../../ajaxtest.html',
            dataType: "json",
            contentType: "application/json;charset=utf-8",
            success : function(data) 
                alert("1");
                alert(data);
            
        );
    

您明确表示您希望从服务器返回 JSON,但是,.html 暗示它应该是 HTML,而您最终会遇到问题

要了解内容协商策略的详细信息,您应该阅读此blog,它现在几乎很有名:) 它还将向您展示纯 java 配置版本

【讨论】:

【参考方案4】:

您的 Ajax 调用应该类似于:

$("#someId" ).click(function()
            $.ajax( 
                url:"getDetails",    
                type:"GET", 
                contentType: "application/json; charset=utf-8",
                success: function(responseData)
                    console.log(JSON.stringify(responseData));
                    // Success Message Handler
                ,error:function(data,status,er)  
                    console.log(data)
                 alert("error: "+data+" status: "+status+" er:"+er);
               
            );
            );

Spring 控制器代码如下:

@RequestMapping(value="/getDetails",method=RequestMethod.GET)
    public @ResponseBody Map<String,String> showExecutiveSummar()
        Map<String,String> userDetails = new HashMap<String,String>();
        userDetails .put("ID","a" );
        userDetails .put("FirstName","b" );
        userDetails .put("MiddleName","c" );
        userDetails .put("LastName","d" );
        userDetails .put("Gender","e" );
        userDetails .put("DOB","f" );
    return userDetails 
    

您也可以参考link 了解支持此功能的库。

【讨论】:

【参考方案5】:

试试这个:

 $.ajax(
        type:"GET",
        url: "/ajaxtest",
        dataType: "json",
        contentType: "application/json;charset=utf-8",
        success: function(data)
        alert("1");
        alert(data);
    
    );

【讨论】:

【参考方案6】:

你需要这个依赖:

<dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version></version>
    </dependency>

如果还没有,请添加:

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
  <list>
    <ref bean="jacksonMessageConverter"/>
  </list>
</property>
</bean>

【讨论】:

1.9.2 版本中添加了jackson-mapper-asljackson-core-asl,但仍然不起作用... 你原来的依赖没问题,spring mvc 4使用jackson 2.x。所以我建议恰恰相反,确保您没有 2.x 版本之前的杰克逊依赖项。另外,我认为单个 jackson-databind dep.就足够了,因为它应该传递核心和注释

以上是关于从spring mvc控制器返回一个简单的映射结构到ajax的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Spring MVC 控制器映射到特定文件夹?

错误:没有找到带有 URI spring mvc 且没有 xml 的 HTTP 请求的映射

Spring MVC 请求映射不起作用

Spring MVC 控制器工作但未创建指定的响应 URL,它正在从请求映射字符串创建 url

Spring MVC 控制器工作但未创建指定的响应 URL,它正在从请求映射字符串创建 url

spring MVC概述