RestTemplate GET 请求抛出 400 Bad Request

Posted

技术标签:

【中文标题】RestTemplate GET 请求抛出 400 Bad Request【英文标题】:RestTemplate GET request throws 400 Bad Request 【发布时间】:2013-10-02 06:29:51 【问题描述】:

当我从 JUnit 测试用例向 Rest Service 发送请求时,我收到 400 Bad Request。 PFB 我的代码。错误日志接近尾声。请帮助我解决问题。当我将服务器调用为:restTemplate.getForObject(BASE_URL + "/remote?serviceName=simpleService&source=WEB", HelloWorld.class) 通过直接在 URL 中传递参数时,我没有收到任何错误。但是如何使用地图通过,这就是问题所在。

我的控制器:

@Controller
@RequestMapping("/remote")

public class RESTController implements IController

@RequestMapping(method = RequestMethod.GET, headers = "Accept=application/xml,  application/json")
public @ResponseBody HelloWorld getMessage(@RequestParam("serviceName") String serviceName, @RequestParam("source") String source) throws ApplicationException
    System.out.println("got the request:");
    serviceLocator serviceLocator = new serviceLocator();
    HelloWorld helloWorld = new HelloWorld();
    helloWorld.setMessage(serviceLocator.getMessage(serviceName));
    return helloWorld;

我的配置:

<context:annotation-config />

<context:component-scan base-package="com" />

<mvc:annotation-driven />

<bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean
                class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean id="jsonViewResolver"
                class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper" ref="JacksonObjectMapper" />
                <property name="supportedMediaTypes">
                    <list>
                        <bean class="org.springframework.http.MediaType">
                            <constructor-arg value="application" />
                            <constructor-arg value="json" />
                            <constructor-arg
                                value="#T(java.nio.charset.Charset).forName('UTF-8')" />
                        </bean>
                    </list>
                </property>
            </bean>

        </list>
    </property>
</bean>
<bean id="JacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />

我的控制器测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("applicationContextTest.xml")
public class RESTControllerTest 

private static final String BASE_URL = "http://localhost:8080/SimpleServiceWeb/rest";

@Autowired
private RestTemplate restTemplate;

@Test
public void getMessage() throws Exception  

    String expected = "Hello Spring!";
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setAccept(Collections
            .singletonList(MediaType.APPLICATION_XML));     

    MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
    map.add("serviceName", "simpleService");
    map.add("source", "WEB");

    ObjectMapper mapper = new ObjectMapper();
    ObjectWriter normalWriter = mapper.writer();
    String jsonString = normalWriter.writeValueAsString(map);;
    HttpEntity<Object> requestEntity = new HttpEntity<Object>(httpHeaders);     

    HelloWorld helloWorld = restTemplate.exchange(BASE_URL + "/remote",
             HttpMethod.GET, requestEntity, HelloWorld.class, map) .getBody();

    assertThat(helloWorld.getMessage(), is(expected));

我的测试配置:

.simple" />

<mvc:annotation-driven />

<bean id="springServiceLocator" class="com.servicelocator.simple.SpringServiceLocator">
    <property name="simpleService" ref="simpleService" />
</bean>

<bean id="simpleService" class="com.service.simple.SimpleService" />

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">

    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean
                class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean id="jsonViewResolver"
                class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper" ref="JacksonObjectMapper" />
                <property name="supportedMediaTypes">
                    <list>
                        <bean class="org.springframework.http.MediaType">
                            <constructor-arg value="application" />
                            <constructor-arg value="json" />
                            <constructor-arg
                                value="#T(java.nio.charset.Charset).forName('UTF-8')" />
                        </bean>
                    </list>
                </property>
            </bean>

        </list>
    </property>
</bean>
<bean id="JacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />

<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
    <constructor-arg ref="httpClientParams" />
</bean>

<bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">

    <property name="connectionManagerClass"
        value="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager" />
</bean>

<bean id="httpClientFactory"
    class="org.springframework.http.client.CommonsClientHttpRequestFactory">
    <constructor-arg ref="httpClient" />
</bean>

错误:

org.springframework.web.client.HttpClientErrorException: 400 错误请求 在 org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:75) 在 org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:486) 在 org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:443) 在 org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409) 在 org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:384) 在 test.com.servicefacade.simple.RESTControllerTest.getMessage(RESTControllerTest.java:85) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源) 在 java.lang.reflect.Method.invoke(未知来源) 在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:300) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

【问题讨论】:

【参考方案1】:
    您的控制器接受 application/xml 和 application/json 类型。 只有在 messageConverters 中配置的 JSON 转换器,我没有看到任何 XML 转换器。 在测试用例中,您将媒体类型设置为 application/xml。

可能是由于缺少 xml 转换器,Spring 无法适当地编组您的请求并因此给出 400?尽管如控制器中所述,支持媒体类型,这就是您没有得到 415 的原因。

【讨论】:

我试过这个选项..它不工作......得到同样的错误..你能分享任何工作示例,以便我可以微调我的......

以上是关于RestTemplate GET 请求抛出 400 Bad Request的主要内容,如果未能解决你的问题,请参考以下文章

Spring RestTemplate 之get请求

RestTemplate put请求,参数传递不进去

Spring之RestTemplate常用API实践

Spring之RestTemplate常用API实践

SpringBoot系列之实现RestTemplate Get请求传javabean参数

RestTemplate请求访问简单使用