Java springrest模板接受头

Java springrest模板接受头,java,spring,rest,spring-mvc,resttemplate,Java,Spring,Rest,Spring Mvc,Resttemplate,在对我们的一个REST服务进行负载测试期间,当负载增加时,我们开始看到Spring的REST模板的此类日志: 在并发加载下,3-4小时后,http请求的Accept标头将变为 DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, application/json, application/*+json, text/plain, text/plain, t

在对我们的一个REST服务进行负载测试期间,当负载增加时,我们开始看到Spring的REST模板的此类日志:

在并发加载下,3-4小时后,http请求的Accept标头将变为

DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, application/json, application/*+json, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain, text/plain,<and so on>, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, */*, <and so on>]
我们正在向该服务发送POST类型的请求,请求内容格式为“someId”,例如“123”

在轻负载情况下,调用服务没有问题

令人费解的是,*/*文本/普通,*/*一直被添加到REST模板的接受头列表中。为什么会发生这种情况

REST模板bean声明如下所示:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg>
            <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
                <property name="readTimeout">
                    <value>90000</value>
                 </property>
                <property name="httpClient" ref="restHttpClient" />
            </bean>
        </constructor-arg>
    </bean>

    <bean id="restHttpClient"  class="org.apache.http.impl.client.DefaultHttpClient">
          <constructor-arg> 
            <bean class="org.apache.http.impl.conn.PoolingClientConnectionManager">
                <property name="defaultMaxPerRoute">
                    <value>100000</value>
                 </property>
                <property name="maxTotal">
                    <value>100000</value>
                 </property>                 

            </bean>
          </constructor-arg>
    </bean>

你能试试这个吗

restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

String postParams = "\"" + id + "\"";

String postResp = restTemplate.postForObject("findRecordById",postParams, String.class);

添加text/plain是因为您尝试读取字符串和RestTemplate,找到StringHttpMessageConverter作为请求的转换器,并且StringHttpMessageConverter支持的媒体类型为text/plain

正如您在RestTemplate的这个方法中所看到的

public void doWithRequest(ClientHttpRequest request) throws IOException {
            if (responseType != null) {
                List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
                for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
                    if (messageConverter.canRead(responseType, null)) {
                        List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
                        for (MediaType supportedMediaType : supportedMediaTypes) {
                            if (supportedMediaType.getCharSet() != null) {
                                supportedMediaType =
                                        new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
                            }
                            allSupportedMediaTypes.add(supportedMediaType);
                        }
                    }
                }
                if (!allSupportedMediaTypes.isEmpty()) {
                    MediaType.sortBySpecificity(allSupportedMediaTypes);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
                    }
                    request.getHeaders().setAccept(allSupportedMediaTypes);
                }
            }
        }
    }
public void doWithRequest(ClientHttpRequest请求)引发IOException{
if(responseType!=null){
List allSupportedMediaTypes=new ArrayList();
对于(HttpMessageConverter messageConverter:getMessageConverters()){
if(messageConverter.canRead(responseType,null)){
List supportedMediaTypes=messageConverter.getSupportedMediaTypes();
对于(MediaType支持的MediaType:supportedMediaTypes){
如果(supportedMediaType.getCharSet()!=null){
支持的媒体类型=
新的MediaType(supportedMediaType.getType(),supportedMediaType.getSubtype());
}
添加(supportedMediaType);
}
}
}
如果(!allSupportedMediaTypes.isEmpty()){
MediaType.sortBySpecificity(所有支持的媒体类型);
if(logger.isDebugEnabled()){
debug(“将请求接受头设置为”+allSupportedMediaTypes);
}
request.getHeaders().setAccept(所有支持的媒体类型);
}
}
}
}

如果有人因为海报反复出现的文本/普通接受标题问题而来到这里,我也经历了同样的事情,下面是发生的情况: 我们在servlet-context.xml中为rest模板定义了常用的bean,其中我们为application/json指定了一个消息转换器,如下所示(这是针对SpringBeans 4.0的):

然而,此messageConverter列表只是在每次请求时添加一个新的StringHttpMessageConverter实例。对于每个请求,Spring都会遍历消息转换器列表,并添加相应的Accept头(text/plain)。在如此多的请求之后,这会导致报头长度增长过大,以至于会被正在调用的服务器容器拒绝。解决此问题的最简单方法是在servlet-context.xml中将text/plain指定为supportedMediaTypes,并删除代码中的上述行。 如果不能这样做,则需要在代码中进行检查,以确保StringHttpMessageConverter不会重复添加到restTemplate实例中

下面是添加了text/plain supportedMediaType的servlet-context.xml:

<beans:bean id="myRestTemplate" class="com.mypackage.MyClass">
        <beans:property name="requestFactoryNonSSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="requestFactorySSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="messageConverters">
            <beans:list>
                <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <beans:property name="supportedMediaTypes">
                        <beans:list>
                            <beans:value>application/json;charset=UTF-8</beans:value>
                            <beans:value>text/plain</beans:value>
                        </beans:list>
                    </beans:property>
                </beans:bean>           
            </beans:list>
        </beans:property>
    </beans:bean>

应用程序/json;字符集=UTF-8
文本/纯文本

请向我们展示一个您使用
RestTemplate
发出请求的示例。编辑此问题以显示如何发出请求。是否直接从
ApplicationContext
获取
RestTemplate
,而无需额外修改?你发送了大量的像上面这样的请求?是的,就是这样。我找不到任何复制的东西。你能发布一个最小的测试用例吗?我看到构造器已经添加了这个消息转换器。看起来这不是问题的根源。
public void doWithRequest(ClientHttpRequest request) throws IOException {
            if (responseType != null) {
                List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
                for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
                    if (messageConverter.canRead(responseType, null)) {
                        List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
                        for (MediaType supportedMediaType : supportedMediaTypes) {
                            if (supportedMediaType.getCharSet() != null) {
                                supportedMediaType =
                                        new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
                            }
                            allSupportedMediaTypes.add(supportedMediaType);
                        }
                    }
                }
                if (!allSupportedMediaTypes.isEmpty()) {
                    MediaType.sortBySpecificity(allSupportedMediaTypes);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
                    }
                    request.getHeaders().setAccept(allSupportedMediaTypes);
                }
            }
        }
    }
<beans:bean id="myRestTemplate" class="com.mypackage.MyClass">
        <beans:property name="requestFactoryNonSSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="requestFactorySSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="messageConverters">
            <beans:list>
                <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <beans:property name="supportedMediaTypes">
                        <beans:list>
                            <beans:value>application/json;charset=UTF-8</beans:value>
                        </beans:list>
                    </beans:property>
                </beans:bean>           
            </beans:list>
        </beans:property>
    </beans:bean>
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
<beans:bean id="myRestTemplate" class="com.mypackage.MyClass">
        <beans:property name="requestFactoryNonSSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="requestFactorySSL" ref="restTemplateNonSSLRequestFactory"/>
        <beans:property name="messageConverters">
            <beans:list>
                <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <beans:property name="supportedMediaTypes">
                        <beans:list>
                            <beans:value>application/json;charset=UTF-8</beans:value>
                            <beans:value>text/plain</beans:value>
                        </beans:list>
                    </beans:property>
                </beans:bean>           
            </beans:list>
        </beans:property>
    </beans:bean>