【问题标题】:Migration from Spring 3 to Spring 4.1 HTTP Status 406 with Ajax/JSON request使用 Ajax/JSON 请求从 Spring 3 迁移到 Spring 4.1 HTTP 状态 406
【发布时间】:2015-11-20 04:52:39
【问题描述】:

我已将我的应用程序从 Spring 3 迁移到 Spring 4.1.7。 现在,当我执行 ajax 查询时,服务器会响应 HTTP 406 错误。

POST /extranet/EmailIdentificationGetFicheClient.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: application/json, */*; q=0.01
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

回应:

HTTP/1.1 406 不可接受的服务器:Apache-Coyote/1.1 内容类型: text/html;charset=utf-8 内容语言:fr 内容长度:1110 日期:格林威治标准时间 2015 年 8 月 26 日星期三 08:28:08

我在类路径中有最新的杰克逊库:

<dependency org="com.fasterxml.jackson.datatype" name="jackson-datatype-json-org" rev="2.6.1" />
<dependency org="org.codehaus.jackson" name="jackson-mapper-asl" rev="1.9.13" />

我的 dispatcher-servlet.xml

<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
    <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
           <property name="supportedMediaTypes" value="text/plain; charset=UTF-8" />
    </bean>    
    <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter">
            <property name="supportedMediaTypes" value="application/xml"/>
    </bean>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"/>
    </bean>

</mvc:message-converters>
</mvc:annotation-driven>

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
 <property name="favorPathExtension" value="false" />
 <property name="useJaf" value="false" />
 <property name="useNotAcceptableStatusCode" value="false" />
 <property name="viewResolvers">
    <list>
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
            <property name="order" value="1" />
        </bean>                     
    </list>
</property>
<property name="defaultViews">
    <list>
        <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
    </list>
</property>

由于应用程序与 struts 一起存在,因此 spring servlet 被映射到 *.html URL。

<servlet>
 <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>*.html</url-pattern>
</servlet-mapping>

我们有几个 ajax 查询,比如这个:

$.ajax({
    type : "post",
    accepts : {
      json : 'application/json'
    },
    url : "/extranet/emailIdentification.html",
    cache : false,
    dataType : 'json', ...

控制器代码(我可以在调试中看到它正确地到达那里)。

@RequestMapping(value="/extranet/EmailIdentification")
@ResponseBody
public Contact getContactFromEmail(HttpServletRequest request) throws SpringException {

另外,我们正在使用 spring-security,我们正在尝试让 spring 识别接受头,就像它在以前的版本中所做的那样。

感谢您的宝贵时间。

【问题讨论】:

    标签: json spring spring-mvc spring-4


    【解决方案1】:

    我终于找到了我的问题所在。

    问题不是由我的杰克逊库引起的,因为它们已正确加载。

    我在调试中注意到我收到了一个异常HttpMediaTypeNotAcceptableException

    这个异常是由 ContentNegotiationStrategy 加载的使用路径扩展而不是 HTTP 标头引起的,尽管我将视图解析器配置为忽略路径扩展:

    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="favorPathExtension" value="false" />
        <property name="useJaf" value="false" />
        <property name="useNotAcceptableStatusCode" value="false" />
        <property name="viewResolvers">
    

    我还添加了一个内容管理器工厂:

    <bean id="cnManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="favorPathExtension" value="false" />
        <property name="useJaf" value="false" />
        <property name="ignoreAcceptHeader" value="false" />
    </bean>
    

    但从未考虑过这个工厂,而是弹簧加载了自己的版本,称为mvcContentNegotiationManager

    因此,最后的破解是强制使用正确的类,这是通过 mvc:annotation-driven 标签设置它来完成的:

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

    等等。现在我仍然可以在 spring 4 中使用 .html 扩展名,即使是 json 查询。

    【讨论】:

      【解决方案2】:

      问题的原因是 Spring 无法加载 Jackson。默认情况下,依赖项不加载它。添加依赖后

      <dependency>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-jaxrs</artifactId>
          <version>1.9.2</version>
        </dependency>
      

      在浏览器中输入地址后返回 JSON,没有任何带有 Accept 标头的技巧(正如它应该做的那样)。

      【讨论】:

      • 对不起,这不是问题,罐子是通过我的应用程序服务器正确加载的。无论如何,感谢您指出这一点。
      猜你喜欢
      • 2011-06-26
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 2016-06-06
      • 2015-06-19
      • 1970-01-01
      相关资源
      最近更新 更多