使用休息模板时收到错误的请求

Posted

技术标签:

【中文标题】使用休息模板时收到错误的请求【英文标题】:Getting bad request when using rest template 【发布时间】:2018-11-18 16:09:25 【问题描述】:

我在尝试使用 RestTemplate 时不断收到错误请求错误。我尝试了getForObject()exchange() 两种方法,但都没有奏效,所以我做错了吗?

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());

MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("param1", "value1");
requestBody.add("param2", "true");

RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(API_URI, HttpMethod.POST,
                    new HttpEntity<>(requestBody, headers), String.class);

堆栈跟踪:(隐藏的 API 名称)

2018-06-08 14:59:20 错误 ErrorPageFilter:176 - 由于异常 [400 Bad Request] 从请求 [/api/cal/dep] 转发到错误页面 org.springframework.web.client.HttpClientErrorException:400 错误请求 在 org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63) 在 org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700) 在 org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653) 在 org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613) 在 org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531) 在 ddz.dd.vack.service.tar.gett(tar.java:51) 在 ddz.dd.vack.service.tar.calc(tar.java:57) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) 在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) 在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:661) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 在 org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 在 org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 在 org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 在 org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:115) 在 org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:59) 在 org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:90) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:108) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) 在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) 在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 在 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) 在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Thread.java:748)

【问题讨论】:

显示完整的堆栈跟踪。并检查接受和内容类型。它应该与 API_URI 定义的内容相匹配 当我在邮递员中手动调用远程 URI 时,它适用于内容类型 json.. 但在我的 java 代码中没有:/ 很难判断我们是否不知道所请求资源的细节。资源也是你开发的吗?你能提供那个代码吗? 不,我没有开发它,但我可以使用以下参数在邮递员中正常执行它:URI:与我在 java Content-Type: application/json 中使用的相同,这些参数为json: "param1": true, "param2": false 就是这样 org.apache.http.wire logger 上打开 TRACE 级别的日志记录,以查看 RestTemplate 实际发送到 URL 的内容。那么差异对您来说应该是显而易见的。 【参考方案1】:

您可以尝试删除 Accept 标头,因为它是默认的 json

headers.add("Accept", MediaType.APPLICATION_JSON.toString());

尝试如下添加接受标头

headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

并检查您提到的作为 String.class 的响应类型对象是什么,请交叉检查

您可以尝试如下更改

    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("param1", "value1");
        requestBody.add("param2", true);Try this? 

【讨论】:

headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));试试这个? 没有,顺便说一句,其余的api只能通过提及内容类型在post man中执行。 是的,postman默认accept header是application/json,我相信这个问题是由于boolean的数据类型转换问题,就像上面提到的那样。尝试只发送一个参数,不包括param2,我们可以交叉检查! 同样的错误,来自服务器的响应是 json 格式,但在 java 中也可以作为字符串返回 在从 Postman 中点击时,您是否对此 REST api 使用了任何授权?

以上是关于使用休息模板时收到错误的请求的主要内容,如果未能解决你的问题,请参考以下文章

传递 POST 请求。春季安全。休息模板。杰克逊转换器

休息模板 - 如何在发送之前检索原始 POST 请求字符串 [重复]

在颤动中打印休息请求错误时出现问题

WCF 休息 - 没有找到元素错误

WCF 休息 WebInvoke 获取方法不起作用返回 404 错误

BizTalk Server 2013 休息错误处理