【问题标题】:How to fix Jersey POST request parameters warning?如何修复 Jersey POST 请求参数警告?
【发布时间】:2011-01-01 23:37:52
【问题描述】:

我正在使用 Jersey 构建一个非常简单的 REST API,我的日志文件中有一个我不确定的警告。

警告:一个 servlet POST 请求, URI http://myserver/mycontext/myapi/users/12345?action=delete, 包含表单参数 请求正文,但请求正文有 已被 servlet 或 servlet 过滤器访问请求 参数。仅资源方法 使用 @FormParam 将作为 预期的。资源方法消耗 其他方式的请求体将 没有按预期工作。

我的 webapp 只定义了 Jersey servlet,映射到 /myapi/*

我怎样才能停止这些警告?

【问题讨论】:

  • 我已经在这里回答了这个问题 stackoverflow.com/a/23994132/616550>。希望对您有所帮助!
  • 没有看到警告并不意味着您解决了它背后的问题
  • 如果你使用的是 Spring Boot,这里是another workaround

标签: rest post warnings jersey


【解决方案1】:

将此添加到您的资源签名中。或者在你的项目中找到这个字符串,如果使用了@PUT 或@POST,那么有人已经使用了它。这应该会有所帮助

import javax.ws.rs.Consumes;

@Consumes(MediaType.APPLICATION_JSON)

【讨论】:

    【解决方案2】:

    对我来说,警告显示为 POST application/x-www-form-urlencoded。我正在使用 Spring Boot,它有一个 HiddenHttpMethodFilter,它在其他任何事情之前都会执行 getParameter ......所以我最终做了这个讨厌的覆盖:

    @Bean
        public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
            return new HiddenHttpMethodFilter() {
                @Override
                protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                        FilterChain filterChain) throws ServletException, IOException {
                    if ("POST".equals(request.getMethod())
                            && request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
                        filterChain.doFilter(request, response);
                    } else {
                        super.doFilterInternal(request, response, filterChain);
                    }
                }
            };
        }
    

    【讨论】:

    • 也解决了我的问题! (这是我们的一个非常特殊(愚蠢)的设置导致我们陷入这个问题,或者为什么其他人没有遇到这个问题?!?
    • 我在使用 Jersey MVC 时收到此错误。如果我切换到 Spring MVC,则不需要此覆盖。
    • 如果您根本不需要HiddenHttpMethodFilter,您可以禁用它。请参阅here 怎么做!
    【解决方案3】:

    最后通过确保我的请求标头中有 Content-Type: application/json (显然,在客户端)

    摆脱了这个问题

    【讨论】:

    • 如果你能解释一下为什么我们需要这个而不是application/x-www-form-urlencoded,这将是一个更好的答案。
    【解决方案4】:

    就我而言,当我在方法中将对象 Date 更改为 String 时,我已修复此错误。

    错误:

    @POST
    @Path("/myPath")
    @Produces(MediaType.APPLICATION_JSON)
    public List<MyObject> myMethod(@FormParam("StartDate") Date date) throws Exception {
    

    固定

    @POST
    @Path("/myPath")
    @Produces(MediaType.APPLICATION_JSON)
    public List<MyObject> myMethod(@FormParam("StartDate") String date) throws Exception {
    

    【讨论】:

      【解决方案5】:

      此警告是 WebComponent 记录的唯一内容,因此只需在 logback.xml 或您配置了日志记录的任何位置将日志记录设置为 ERROR 级别或关闭此组件的日志记录。您无需编写自定义过滤器即可忽略此特定消息,因为此组件没有记录其他消息。

      来自 org.glassfish.jersey.servlet.WebComponent 版本 2.14 的源代码 sn-p:

              if(!form.asMap().isEmpty()) {
                  containerRequest.setProperty("jersey.config.server.representation.decoded.form", form);
                  if(LOGGER.isLoggable(Level.WARNING)) {
                      LOGGER.log(Level.WARNING, LocalizationMessages.FORM_PARAM_CONSUMED(containerRequest.getRequestUri()));
                  }
              }
      

      用于此警告消息的本地化消息是:

      form.param.consumed=A servlet request to the URI {0} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
      

      在 logback.xml 中关闭 WebComponent 的注销,如下所示:

      <logger name="org.glassfish.jersey.servlet.WebComponent" level="OFF" additivity="false"/>
      

      【讨论】:

        【解决方案6】:

        没错。 所以我一直遇到这个问题,我一直在尝试以不同的方式解决它,但我不想更改我的 web.xml 设置,只是因为如果我用 Postman 测试我的应用程序,它工作得很好,但是当它与 webapp 集成时,它会因上述问题而失败 (A servlet request to the URI {MY_URI} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.)

        正如@clijk 提到的,您只需将标题设置为:

        "Content-Type":"application/json"
        "charset":"UTF-8"
        

        瞧,警告消失了。

        谢谢

        【讨论】:

          【解决方案7】:

          此消息旨在警告开发人员请求实体正文已被消耗,因此任何其他读取消息正文的尝试都将失败。

          忽略该消息或将其从日志中过滤掉是安全的:

          java.util.logging.Logger jerseyLogger =
                  java.util.logging.Logger.getLogger(WebComponent.class.getName());
          jerseyLogger.setFilter(new Filter() {
              @Override
              public boolean isLoggable(LogRecord record) {
                  boolean isLoggable = true;
                  if (record.getMessage().contains("Only resource methods using @FormParam")) {
                      isLoggable = false;
                  }
                  return isLoggable;
              }
          });
          

          【讨论】:

          • 应该放在你应用程序初始化部分的某个地方,在你开始服务请求之前。
          • 我认为您应该尝试解决问题而不是隐藏它。我的 2 美分(我也可能错了)。
          • 为什么可以安全地忽略它!?这显然是一个问题,因为您的代码没有得到它......如果您希望对数据做一些事情,那么您显然有问题。不要只是忽略它....@facundofarias 是对的。把你的头埋在沙子里,假装你没有问题是愚蠢的。
          • 在公共 API 场景中忽略是有意义的,在这种场景中,您无法控制 API 使用者在进行集成时可能会做的有趣事情,而且您有太多的事情无法处理日志噪音。
          【解决方案8】:

          我刚刚将 JQuery 中的 ajax 函数设置为 contentType: "application/x-www-form-urlencoded; charset=UTF-8",因为使用先前的解决方案(没有 Jersey)我遇到了一些编码问题。当我删除该消息时,一切正常。

          【讨论】:

            【解决方案9】:

            以下thread 描述了您收到的警告。听起来好像您可能在 web.xml 中定义了一个过滤器,该过滤器在 Jersey 之前处理请求。

            【讨论】:

            • 这一定是件坏事吗?有没有办法隐藏控制台/日志输出?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-26
            • 2013-08-03
            • 2019-08-08
            • 2020-11-28
            • 2017-10-25
            • 2017-07-03
            相关资源
            最近更新 更多