Spring 框架和 RestTemplate:无法使用 REST 服务
Spring Framework & RestTemplate: not being able to consume REST Service
首先,我有两个 Spring REST 服务:服务 A 和 服务 B。 服务 A 将需要使用 服务 B 公开的一些方法。 A 和 B 都是 Spring @RestController
.
服务 A 有一个 POST 方法:
@RequestMapping(value = "/mediumcandy/linkreachable", method = RequestMethod.POST)
public ResponseEntity<ShortURL> shortenerIfReachable(@RequestParam("url") String url,
@RequestParam(value = "sponsor", required = false) String sponsor,
@RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ShortURL su = null;
/*************************************************************
* CONSUMING REST Service
*************************************************************/
Map<String, String> vars = new HashMap<String, String>();
vars.put("url", url);
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject("http://SERVICE_URI_HERE/linkreachable", null, ShortURL.class, vars);
/****************************************************************/
if (su != null) {
HttpHeaders h = new HttpHeaders();
h.setLocation(su.getUri());
return new ResponseEntity<>(su, h, HttpStatus.CREATED);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
并且 服务 B 中的 POST 方法由 服务 A 使用 Spring RestTemplate 如下:
@RequestMapping(value = "/linkreachable", method = RequestMethod.POST)
public ShortURL shortenerIfReachable(@RequestParam("url") String url,
@RequestParam(value = "sponsor", required = false) String sponsor,
@RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ShortURL su = null;
boolean isReachableUrl = ping(url);
if (isReachableUrl){
su = createAndSaveIfValid(url, sponsor, brand, UUID
.randomUUID().toString(), extractIP(request));
System.out.println("URL REACHABLE!");
}
return su;
}
服务 A 中的 RestTemplate 方法 postForObject()
给我带来麻烦,总是抛出 HttpClientErrorException: 400 Bad Request
:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw
exception [Request processing failed; nested exception is org.springframework.web.client.H
ttpClientErrorException: 400 Bad Request] with root cause
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultR
esponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.ja
va:615)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:573)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:537)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:339
)
at urlshortener2014.mediumcandy.web.MediumCandyController.shortenerIfReachable(Med
iumCandyController.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(Invocabl
eHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(
InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMe
thod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdap
ter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdap
ter.handleInternal(RequestMappingHandlerAdapter.java:706)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(
AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:94
... etc
我已经按照一些 Spring 教程来构建我的服务,并且还检查了 Spring Framework api-docs,但我无法让它工作。
尝试以下 url :curl --data "url=http://www.whosebug.com" http://localhost:8080/linkreachable
使用Spring HATEOAS来解决!给定 ServiceA
和 ServiceB
,在 ServiceA
中使用 Spring HATEOAS 获取“ServiceB”中 controller/method 的运行时 URL,如下所示:
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
...
String restURI = linkTo(methodOn(ServiceB.class).
shortenerIfReachable(null, null, null, null)).toString();
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject(restURI, null, ShortURL.class, vars);
@Francisco 你快到了
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
...
String restURI = linkTo(methodOn(UrlShortenerControllerWithLogs.class).
shortenerIfReachable(url, null, null, null)).toString();
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject(restURI, null, ShortURL.class);
调用shortenerIfReachable时必须传递url参数
我还从 postForObject 调用中删除了变量。
首先,我有两个 Spring REST 服务:服务 A 和 服务 B。 服务 A 将需要使用 服务 B 公开的一些方法。 A 和 B 都是 Spring @RestController
.
服务 A 有一个 POST 方法:
@RequestMapping(value = "/mediumcandy/linkreachable", method = RequestMethod.POST)
public ResponseEntity<ShortURL> shortenerIfReachable(@RequestParam("url") String url,
@RequestParam(value = "sponsor", required = false) String sponsor,
@RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ShortURL su = null;
/*************************************************************
* CONSUMING REST Service
*************************************************************/
Map<String, String> vars = new HashMap<String, String>();
vars.put("url", url);
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject("http://SERVICE_URI_HERE/linkreachable", null, ShortURL.class, vars);
/****************************************************************/
if (su != null) {
HttpHeaders h = new HttpHeaders();
h.setLocation(su.getUri());
return new ResponseEntity<>(su, h, HttpStatus.CREATED);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
并且 服务 B 中的 POST 方法由 服务 A 使用 Spring RestTemplate 如下:
@RequestMapping(value = "/linkreachable", method = RequestMethod.POST)
public ShortURL shortenerIfReachable(@RequestParam("url") String url,
@RequestParam(value = "sponsor", required = false) String sponsor,
@RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ShortURL su = null;
boolean isReachableUrl = ping(url);
if (isReachableUrl){
su = createAndSaveIfValid(url, sponsor, brand, UUID
.randomUUID().toString(), extractIP(request));
System.out.println("URL REACHABLE!");
}
return su;
}
服务 A 中的 RestTemplate 方法 postForObject()
给我带来麻烦,总是抛出 HttpClientErrorException: 400 Bad Request
:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw
exception [Request processing failed; nested exception is org.springframework.web.client.H
ttpClientErrorException: 400 Bad Request] with root cause
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultR
esponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.ja
va:615)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:573)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:537)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:339
)
at urlshortener2014.mediumcandy.web.MediumCandyController.shortenerIfReachable(Med
iumCandyController.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(Invocabl
eHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(
InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMe
thod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdap
ter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdap
ter.handleInternal(RequestMappingHandlerAdapter.java:706)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(
AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:94
... etc
我已经按照一些 Spring 教程来构建我的服务,并且还检查了 Spring Framework api-docs,但我无法让它工作。
尝试以下 url :curl --data "url=http://www.whosebug.com" http://localhost:8080/linkreachable
使用Spring HATEOAS来解决!给定 ServiceA
和 ServiceB
,在 ServiceA
中使用 Spring HATEOAS 获取“ServiceB”中 controller/method 的运行时 URL,如下所示:
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
...
String restURI = linkTo(methodOn(ServiceB.class).
shortenerIfReachable(null, null, null, null)).toString();
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject(restURI, null, ShortURL.class, vars);
@Francisco 你快到了
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
...
String restURI = linkTo(methodOn(UrlShortenerControllerWithLogs.class).
shortenerIfReachable(url, null, null, null)).toString();
RestTemplate restTemplate = new RestTemplate();
su = restTemplate.postForObject(restURI, null, ShortURL.class);
调用shortenerIfReachable时必须传递url参数 我还从 postForObject 调用中删除了变量。