首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring REST模板接受标头

Spring REST模板接受标头
EN

Stack Overflow用户
提问于 2014-11-05 02:13:45
回答 3查看 4.2K关注 0票数 6

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

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

代码语言:javascript
复制
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>]

最后,使用RestTemplate对该服务的所有调用都开始失败,出现了400个错误(坏请求)

被调用的REST服务接受字符串作为输入,并具有以下签名

代码语言:javascript
复制
@RequestMapping(value = "/findRecordById", method = {RequestMethod.POST, RequestMethod.GET })
@ResponseBody
public String findRecordById(@RequestBody String id) {//method body}

我们向该服务发送的请求类型为"someId“形式的请求内容,例如"123”。

在轻负载下,调用该服务没有任何问题。

令人费解的是文本/平原、*/*,它一直被添加到REST模板的接受头列表中。这一切为什么要发生?

REST模板bean声明如下所示:

代码语言:javascript
复制
<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>

如何创建请求:

代码语言:javascript
复制
String postParams = "\"" + id + "\"";

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

回答 3

Stack Overflow用户

发布于 2015-12-28 12:17:25

添加text/平原是因为您尝试读取字符串和RestTemplate,发现StringHttpMessageConverter作为请求的转换器,而支持StringHttpMessageConverter的媒体类型是text/平原。

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

代码语言:javascript
复制
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);
                }
            }
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2017-02-08 10:35:48

如果有人因为海报上反复出现的文本/简单接受头问题而来到这里,我也经历了同样的事情,下面是正在发生的事情:我们在servlet-context.xml中为rest模板定义了我们通常的bean定义,其中我们为应用程序/json指定了一个消息转换器,类似于这样(这是针对spring 4.0的):

代码语言:javascript
复制
<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>

但是,在源代码中,我们还使用以下方法显式地添加了一个StringHttpMessageConverter:

代码语言:javascript
复制
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

但是,这个messageConverter列表只是在每个请求中添加了一个新的StringHttpMessageConverter实例。对于每个请求,Spring都会遍历消息转换器列表,并添加相应的Accept (text/平原)。在如此多的请求之后,这会导致标头长度变得如此之大,以至于您正在调用的服务器容器会拒绝它。解决这一问题的最简单方法是将文本/平原指定为Servletcontext.xml中的supportedMediaTypes,并删除代码中的上述行。如果无法做到这一点,则需要在代码中进行检查,以确保StringHttpMessageConverter不会被重复添加到restTemplate实例中。

以下是添加了文本/纯文本supportedMediaType的servlet-context.xml:

代码语言:javascript
复制
<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>
票数 1
EN

Stack Overflow用户

发布于 2014-11-05 05:04:19

你能试试这个吗?

代码语言:javascript
复制
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

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

String postResp = restTemplate.postForObject("findRecordById",postParams, String.class);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26748648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档