【问题标题】:Investigate HTTP 406 Error code only on first call仅在第一次调用时调查 HTTP 406 错误代码
【发布时间】:2013-05-31 08:51:34
【问题描述】:

我有一个使用 Spring 公开一些 RestServices 的服务器。我有大约 20 种服务,它们几乎总是做同样的事情:获取、列出、保存......

在所有这些服务中,我有一个请求与其他请求不同:

@RequestMapping(value = {"/{id}"}, method = RequestMethod.GET)
@ResponseBody
public Line get(@PathVariable(value = "id") int id) {
  return lineService.getById(id);
}

问题:

  • 当我重新启动服务器并首次调用此特定请求时,我收到 406 错误代码。

  • 之后,所有其他调用都以成功结束,返回格式良好的 JSON 和 HTTP 200 代码等。

请求的 Accept Headers 包含“application/json”。

我试图在 requestMapping 上添加这个:

produces="application/json"

似乎在某个地方,服务器在第一次失败后调整了响应的内容/类型,但我绝对不明白在哪里。

我尝试使用 tomcat 和 jetty 作为后端服务器,但两者都有错误。

有什么想法吗?

编辑:

经过进一步调查,我在 tomcat 日志中发现了这种差异。在第一次调用(HTTP 406)时,我可以看到:

09:33:58.637 [http-bio-9090-exec-3] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
09:33:58.637 [http-bio-9090-exec-3] DEBUG o.s.w.a.FixedContentNegotiationStrategy - Requested media types is application/json (based on default MediaType)
09:33:58.654 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springServlet': assuming HandlerAdapter completed request handling
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

在第二次通话中,我可以看到这一点(差异从第 2 行开始):

09:50:52.384 [http-bio-9090-exec-7] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.mycompany.myproject.dto.patrimoine.mobile.ligne.LigneMobile@18949ad1] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@32a64bcd]
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springServlet': assuming HandlerAdapter completed request handling
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

所以,在第一种情况下,我在尝试将对象转换为 JSON 时收到一些 HttpMediaTypeNotAcceptableException。

【问题讨论】:

  • 如果示例有 Spring 注释(不是 JAX-RS),为什么你会写下你正在使用 Jersey?会不会对这些技术有一些误解?
  • 在检查 maven 依赖项后,这是一个错误:我们不使用 Jersey。我编辑了这个问题,谢谢。
  • 我认为 406 是关于请求和响应:它发生在响应的 Content-Type 与请求的“接受标头”不对应时,或者我错过了什么?对于 Spring 处理程序映射,我和团队正在对此趋同,仍在调查中。
  • 我已删除我的评论 - 不正确。这是关于接受头的。抱歉信息不正确。
  • @adenoyelle 您正在运行哪个 Spring 版本?

标签: spring http rest


【解决方案1】:

我会首先启动 Fiddler 之类的东西,以查看实际通过网络传输的位。

【讨论】:

    【解决方案2】:

    您说,Accept Headers 包含application/json。我会通过发送请求而不指定接受的内容类型来开始调查。当服务器响应不受特定内容类型的限制时,应该有一些相关的线索。如果 Web 服务器在处理请求期间遇到任何错误,它们通常倾向于返回格式为 HTML 的错误页面。在这种情况下,内容类型当然是 text/html,因此真正的问题被 406 错误混淆了。

    【讨论】:

      【解决方案3】:

      您是否尝试在控制器方法的第一行设置断点,即return lineService.getById(id);

      我怀疑你会打那一行,但如果你尝试使用调试器“进入”该方法,将会出现一些初始错误。如果我的假设是正确的,那么会在某个地方抛出异常,从而产生一个带有堆栈跟踪的 html 页面。接下来,您将看到 406 发生,因为 html 页面的媒体类型为application/html,或类似的无法转换为application/json

      【讨论】:

      • 我试图将这一行分成两部分 Line line=lineService.getById(id)return line; 并放置一个断点以查看返回行的结构。在这两种情况下,生成的line 似乎格式正确。当 Spring 尝试将其转换为 JSON 时,似乎会出现问题。
      【解决方案4】:

      鉴于您仅在重新启动服务器后才看到此错误,这让我认为这可能与延迟类加载有关。

      尝试使用在服务器启动时初始化的 servlet(即 load-on-startup 值为 1),在其 init 方法中 - 引用将 com.mycompany.myproject.dto.datagrid.LoadResult 渲染为 json 所涉及的所有类?

      请记住,您正在尝试确保所有涉及的类都在请求进入之前由 ClassLoader 加载。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-05
        • 2011-01-20
        相关资源
        最近更新 更多