近日,在与某平台调试的时候,发觉对方在一直发送,而我方按照他们文档的格式要求返回的数据,对方还是未能结束一直发送。
后经查证,对方要求我方返回状态码为Http/1.1 200 OK, 而我方返回的数据为Http/1.1 200;
经查证,我方使用的spring-boot-starter-tomcat:2.3.3.Release(tomcat版本为9.0.37),这个版本里面tomcat发行方已将OK这个描述去掉。
网上查找解决方案,多为建议降低Tomcat版本号,不使用SpingBoot自带的Tomcat而直接使用tomcat,然后利用TomcatConfig的方式来进行操作。我看到所有的设置里面,都用到了如下描述:
打开tomcat目录下的server.xml,在<Connector>标签中添加sendReasonPhrase="true"即可
参考链接:https://blog.csdn.net/qq_22937623/article/details/82998899
那么很显然,这个 sendReasonPhrase属性是Tomcat自带的,严格来说是无需干掉SpringBoot内嵌Tomcat的,直接在里面配置也行。
首先,在这个网址上Maven仓库上去查找最接近8点几的 Spring Boot Starter Tomcat 2.x,经查找,最低的版本为2.1.0.RELEASE那么降低SpringBoot版本为2.1.0.RELEASE,内嵌Tomcat就变成了9.0.12;就那么更改,最后得到的结果如下:
1、在代码中做如下配置:
package net.dlet.dhdemo.configure;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description:
* 1、配置转义字符, 解决当请求路径中特殊字符,解决高版本Tomcat对接口参数限制字符,
* 解析失败从而出现RFC7230、RFC3986问题
* 2、解决Header状态码加上描述字段的问题
* @PackageName: net.dlet.dhdemo.configure
* @Name: RF7230
* @Author: cure
* @CreateDate: 2020/09/06 00:30
* @ModifyUser: cure
* @ModifyDate: 2020/09/09 22:18
* @ModifyDesc: 新增解决Header状态码加上描述字段的问题
* @DayNameFull: 星期日
* @ProjectName: dhdemo
* @Version: 1.0
**/
@Configuration
public class RFC7230 {
/**
* 解决Tomcat RFC7230以及Header状态码加上描述字段的问题
*
* @return
*/
@Bean
public ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
//设置解析描述符为true,例如Header 状态码为200,那么解析出来就是200 ok
connector.setProperty("sendReasonPhrase", "true");
//以下设置为解决RFC7230问题
connector.setProperty("relaxedQueryChars", "|{}[](),/:;<=>?@[\\]{}\\");
connector.setProperty("relaxedPathChars", "|{}[](),/:;<=>?@[\\]{}\\");
//这个属性在tomcat为8.5的时候不生效
connector.setProperty("rejectIllegalHeader", "false");
});
return factory;
}
}
2、如何查看这个Tomcat的版本支持 sendReasonPhrase这个属性呢?不想查找文档的话,一个比较笨的方式就是打断点,查看返回值,如下:
3、pom.xml里面也要修改:
如果是gradle的工程,如下修改:
gradle.properties里面定义版本如下:
spring_boot_version = 2.1.1.RELEASE spring_boot_tomcat_version = 2.3.3.RELEASE tomcat_embed_version = 8.5.56
在build.gradle里面修改如下:
compile("org.springframework.boot:spring-boot-starter-web:${spring_boot_version}") {
//移除默认的版本
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-core:9.0.13'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-el:9.0.13'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.13'
}
compile("org.springframework.boot:spring-boot-starter-websocket:${spring_boot_version}") {
//移除默认的版本
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-core:9.0.13'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-el:9.0.13'
exclude module: 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.13'
}
//使用指定版本的tomcat内嵌版本
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: "${tomcat_embed_version}"
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-el', version: "${tomcat_embed_version}"
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-websocket', version: "${tomcat_embed_version}"
4、最终返回结果如下:
写在最后,吐槽一下:
厂商所用版本实在是太老,文档里面又没有说明他们所测试过的环境,真的十分坑,写tmd个对外文档,根本不像是一个大厂出品,建议这家写技术文档的人,参考一下我6年前写的这篇《Qt5.2.1 交叉编译,带tslib插件》的格式。在开始阶段我就指明了所用环境。
第二:吐槽一下百度,等我折腾完了以后,回过去按照现有的关键字(
connector.setProperty("sendReasonPhrase", "true");
)查找,竟然发觉已有人采用了我同样的方式处理问题。然后我将SpringBoot的版本号改为了2.1.5