我正在使用 Jersey 构建一个非常简单的 REST API,并且我的日志文件中收到了一条我不确定的警告。
警告:servlet POST 请求 统一资源定位符 http://myserver/mycontext/myapi/users/12345?action=delete, 包含表单参数 请求正文,但请求正文有 已被 servlet 或 servlet 过滤器访问请求 参数。仅资源方法 使用@FormParam将起到作用 预期的。资源消耗方法 通过其他方式的请求主体将 没有按预期工作。
我的 web 应用程序仅定义了 Jersey servlet,映射到 /myapi/*
如何停止这些警告?
对我来说,警告是针对 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);
}
}
};
}
此消息旨在警告开发人员请求实体正文已被消耗,因此任何其他读取消息正文的尝试都将失败。
忽略该消息或将其从日志中过滤掉是安全的:
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;
}
});
以下线程描述了您收到的警告。听起来好像您可能在 web.xml 中定义了一个过滤器,该过滤器在 Jersey 之前处理请求。
最终通过确保我的请求标头中有 Content-Type: application/json 摆脱了这个问题(显然,在客户端)
我刚刚将 JQuery 中的 ajax 函数设置为
contentType: "application/x-www-form-urlencoded; charset=UTF-8"
,因为使用先前的解决方案(没有 Jersey)我遇到了一些编码问题。当我删除该消息时,该消息消失了,一切正常。
对。 所以我一直在遭受这个问题的困扰,并且我一直在尝试以不同的方式解决它,但我不想更改我的 web.xml 设置,只是因为如果我使用 Postman 测试我的应用程序,它会完美地工作,但是当它与 web 应用程序集成时,它会因上述问题而失败 (
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"
瞧,警告消失了。
谢谢
此警告是 WebComponent 记录的唯一内容,因此只需在 logback.xml 或配置了日志记录的任何位置将日志记录设置为错误级别或关闭此组件的日志记录即可。您不需要编写自定义过滤器来忽略此特定消息,因为没有从此组件记录其他消息。
来自 org.glassfish.jersey.servlet.WebComponent 版本 2.14 的源代码片段:
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"/>
就我而言,当我将方法中的对象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 {
将其放入您的资源签名中。或者在您的项目中找到这个字符串,如果使用了 @PUT 或 @POST,那么有人已经使用了这个字符串。这应该有帮助
import javax.ws.rs.Consumes;
@Consumes(MediaType.APPLICATION_JSON)
这个问题似乎已经在2.38版本中修复了
#5208