ajax中的内容协商

遇到问题: @RequestMapping (value = "/view.html" )
       @ResponseBody
      public Object view( @RequestParam int id ) {
          User user = userService .findById( id );
           return user ;
     }

     $.ajax({
              type: "POST" ,
              url:path+ "/user/view.html" ,
              data:{id:obj.attr( "userid" )},
              dataType: "json" ,
              success: function (result){
                   alert(JSON.stringify(result));    
              } ,
              error: function (result){
                   console.log(JSON.stringify(result));
              }
          });

使用.html后缀的请求名,想依赖 @ResponseBody( 关于 @ResponseBody:将内容或对象作为 HTTP 响应正文返回,使用@ResponseBody将会跳过视图处理部分,而是调用适合HttpMessageConverter,将返回值写入输出流。 )(Jackson相关包已提交导入)自动返回json,发现报406错误,很是费解,查询网上各处文章,发现有同学说是 如果后缀是html是不能响应json数据的。需要修改后缀名。 
在做伪静态化过程中,以.html结尾的后缀,做post请求时,不能响应json格式,这是spring官方做出的处理 。看完之后本来想是好吧,既然是spring都申明这个问题采取规避原则,那我就不纠结了,然而后来反复想还是觉得不对,spring不至于ajax连后缀.html,.jsp这种都不支持吧,继续寻找解决方案,终于找到ajax中有个内容协商原则。

什么是内容协商
简单点说,就是同一资源,可以有多种表现形式,比如xml、json等,具体使用哪种表现形式,是可以协商的。
这是RESTfull的一个重要特性,Spring Web MVC也支持这个功能。

Spring MVC REST是如何决定采用何种方式(视图)来展示内容呢?
一:根据Http请求的header中的Accept属性的值来判读,比如:
Accept: application/xml                将返回xml格式数据 
Accept: application/json               将返回json格式数据
 
优点:是这种方式是理想的标准方式
缺点:是由于浏览器的差异,导致发送的Accept Header头可能会不一样,从而导致服务器不知要返回什么格式的数据
 
二:根据扩展名来判断,比如:
/mvc/test.xml  将返回xml格式数据 
/mvc/test.json 将返回json格式数据 
/mvc/test.html 将返回html格式数据 
 
缺点:丧失了同一URL的多种展现方式。在实际环境中使用还是较多的,因为这种方式更符合程序员的习惯
 
三:根据参数来判断
/mvc/test?format=xml        将返回xml数据 
/mvc/test?format=json       将返回json数据 
 
缺点:需要额外的传递format参数,URL变得冗余繁琐,缺少了REST的简洁风范

使用内容协商的功能,如果不使用第三种方式的话,3.2的版本可以什么都不用配置,默认就能支持前面两种。下面还是看看怎么配置,示例如下:

需要在spring的配置文件中做配置,示例如下:
<!--1、检查扩展名(如my.pdf);2、检查Parameter(如my?format=pdf);3、检查Accept Header-->
    <bean id= "contentNegotiationManager" class= "org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
        <property name= "favorPathExtension" value= "true" />
        <!-- 用于开启 /userinfo/123?format=json 的支持 -->
        <property name= "favorParameter" value= "true" />
        <property name= "parameterName" value= "format"/>
        <!-- 是否忽略Accept Header -->
        <property name= "ignoreAcceptHeader" value= "false"/>
 <property name= "mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用  -->
            <value>
                ccjson=application/json
                ccxml=application/xml
                html=text/html
            </value>
        </property>
        <!-- 默认的content type -->
        <property name= "defaultContentType" value= "text/html" />
    </bean>

<mvc:annotation-driven
      validator= "validator"
      conversion-service= "conversionService"
      content-negotiation-manager= "contentNegotiationManager"
      >
</mvc:annotation-driven>



现在对这段做下补充,经过测试发现:这边的3个规则是有优先顺序的,spring会优先匹配favorPathExtension(检查扩展名),其次匹配剩余2个规则,
根据上面的原则,在你的spring配置文件中添加下面内容即可
      <!-- 指定数据转换管理器 -->
      < mvc:annotation-driven content-negotiation-manager = "cnManager" />
      <!--  favorPathExtension属性值默认为true 会根据请求路径来识别你的数据类型,入.html返回html。.json返回json-->
      < bean id = "cnManager" class = "org.springframework.web.accept.ContentNegotiationManagerFactoryBean" >         
        < property name = "ignoreAcceptHeader" value = "false" />  
        < property name = "favorPathExtension" value = "false" />  
        < property name = "defaultContentType" value = "text/html" />  
        < property name = "favorParameter" value = " false " />  
  <!-- <property name="mediaTypes"> 
            <map> 
                <entry key="xml" value="application/xml"/> 
                <entry key="json" value="application/json"/>
            </map> 
        </property>   -->
    </ bean >
 我们利用第三种检查请求头的方式来决定要返回什么类型数据,所以把 favorPathExtension和 favorParameter都设为false,把 ignoreAcceptHeader也设为false,表示不忽略,需要检查请求头,因为我们申明dataType是json,查看控制台发现Accept是application/json, contentNegotiateManager就会认为你请求的内容类型(Content-Type)为application/json,那么它就要将响应的内容类型(Content-Type)设置为application/json,最终HttpMessageConverter能将你的json正确返回给前台。
总结:想要利用spring自己的 HttpMessageConverter 自动转成json的方式,那么需要了解其的内容协商规则,当然如果在返回之前手动转成json格式的数据,那么就可以一招制敌了。

  1. Accept:
    application/json, text/javascript, */*; q=0.01
  2. Accept-Encoding:
    gzip, deflate, br
  3. Accept-Language:
    zh-CN,zh;q=0.8
  4. Connection:
    keep-alive
  5. Content-Length:
    4
  6. Content-Type:
    application/x-www-form-urlencoded; charset=UTF-8
  7. Cookie:
    JSESSIONID=61B1FF442274EE9364FB05318EFDA30A; __utma=111872281.1109517436.1491358058.1492066273.1492070833.3; __utmz=111872281.1491358058.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
  8. Host:
    localhost:8080
  9. Origin:
    http://localhost:8080
  10. Referer:
    http://localhost:8080/springmvc_sun_12_1/user/userAdmin.html
  11. User-Agent:
    Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
  12. X-Requested-With:
    XMLHttpRequest
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值