Java writeBytes空白替换为'+';
当尝试使用HttpURLConnection执行post请求时,消息中的空格被替换为“+”并在字符串末尾添加“=”。 我正在使用JDK 1.8.091,以下是我的代码:Java writeBytes空白替换为'+';,java,web-services,spring-mvc,spring-boot,Java,Web Services,Spring Mvc,Spring Boot,当尝试使用HttpURLConnection执行post请求时,消息中的空格被替换为“+”并在字符串末尾添加“=”。 我正在使用JDK 1.8.091,以下是我的代码: public void sendPost(String message) throws Exception { String url = "http://localhost:8081/subscribe"; URL obj = new URL(url); HttpURLConnection co
public void sendPost(String message) throws Exception {
String url = "http://localhost:8081/subscribe";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
/*String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";*/
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(message);
wr.flush();
wr.close();
}
sendPost(“sayhi”)将在服务器端给出:Say+Hi=当您不设置
内容类型
请求头(使用setRequestProperty()
)时,它默认为application/x-www-form-urlcoded
当POST请求的内容类型为application/x-www-form-urlencoded
时,可以使用ServletRequest.getParameter
方法从请求正文中提取参数。这将消耗请求正文,因此对getInputStream()
或getReader()
的任何后续调用都将返回null
当您的Spring处理程序方法请求带有@RequestBody
注释的请求主体,并且主体已经被使用时,Spring将根据参数重建主体,以提供方法参数(基本上是伪造的)。当Spring从解析的参数重建请求主体时,它将根据应用程序/x-www-form-urlencoded
内容类型的要求对它们进行URL编码。此编码将空格转换为+
带有Say Hi
的原始请求正文被解析为参数带值的“Say Hi”
”(不带=
的参数具有空值)。当按照application/x-www-form-urlencoded
重新构建时,参数编码为Say+Hi=
,这就是您看到的
只有在调用了ServletRequest.getParameter
方法之一时,才会发生这种情况,因此您可能有一个过滤器来实现这一点。如果删除了该筛选器,请求正文就不会被使用,并且@RequestBody
参数将收到原始请求正文
防止该问题的另一种方法是将请求正文作为文本/普通
内容类型发送,因为这似乎是您想要的方式,即请求正文实际上不是x-www-form-urlencoded
:
con.setRequestProperty("Content-Type", "text/plain; charset=ISO-8859-1");
当然,如果请求主体确实是x-www-form-urlencoded
内容,就像您的注释代码所建议的那样,那么就不应该有任何空格,而且一开始就没有问题
总而言之:您的问题是您在帖子正文中发送任意文本,但您没有设置内容类型,因此它默认为application/x-www-form-urlencoded
,并且您的内容不符合该内容类型的规范,也就是说,您的请求格式不正确,行为不可预测。不相关,但为什么要使用DataOutputStream
?您在哪里看到“Say+Hi=”?您能提供一个吗?我正在将从客户端收到的消息记录在spingBoot应用程序的日志文件中。分步调试后的问题来自wr.writeBytes(消息)DataOutputStream.writeBytes()
肯定不会这样做,因为您可以通过使用它编写其他内容或阅读Javadoc轻松地为自己建立。问题可能出在HttpURLConnection
上,虽然可能性不大,但很可能是在接收端。您需要进行进一步调试。这是接收端所做的一切记录:code
@RequestMapping(value=“/subscribe”,method=RequestMethod.POST)public@ResponseBody String createNewUser(@RequestBody String message){log.info(message);}HttpURLConnection
不进行此编码,也不进行此编码(显然)没有DataOutputStream.writeBytes()
。问题在别处。@EJP你说得对,HttpURLConnection
并没有添加+
,而是将内容类型默认为application/x-www-form-urlencoded
,这意味着Servlet容器或Spring框架读取内容并将其作为参数解析,然后当你请求内容时t与@RequestBody
(与OP一样),它重建了它们,其副作用是将空格编码为+
。如果内容类型是其他类型,Servlet容器/Spring框架不会这样做,因此我相信设置内容类型仍然是解决问题的方法。您可以将其前后颠倒。Servlet容器将+解码为空格。没有理由r要编码的服务器端。@EJP我的观点是,当“表单字段”作为参数处理,因此当方法使用@RequestBody
注释请求完整负载时,必须根据参数重新生成。重新生成时不知道原始负载的编码不正确,因此它按照预期的编码方式对其进行编码。@Andreas您是对的,我将内容类型设置为to文本/纯文本,效果很好。非常感谢。