从我在 Spring-Boot 的服务器上调用另一个 rest api

我想调用另一个 web-api 从我的后端对用户的特定请求。例如,我想调用 谷歌 FCM发送消息 api 来向事件中的特定用户发送消息。

翻新有没有什么方法可以做到这一点? 如果没有,我怎么可以做到这一点?

341233 次浏览

This website has some nice examples for using spring's RestTemplate. Here is a code example of how it can work to get a simple object:

private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees.xml";


RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);


System.out.println(result);
}

Instead of String you are trying to get custom POJO object details as output by calling another API/URI, try the this solution. I hope it will be clear and helpful for how to use RestTemplate also,

In Spring Boot, first we need to create Bean for RestTemplate under the @Configuration annotated class. You can even write a separate class and annotate with @Configuration like below.

@Configuration
public class RestTemplateConfig {


@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}

Then, you have to define RestTemplate with @Autowired or @Injected under your service/Controller, whereever you are trying to use RestTemplate. Use the below code,

@Autowired
private RestTemplate restTemplate;

Now, will see the part of how to call another api from my application using above created RestTemplate. For this we can use multiple methods like execute(), getForEntity(), getForObject() and etc. Here I am placing the code with example of execute(). I have even tried other two, I faced problem of converting returned LinkedHashMap into expected POJO object. The below, execute() method solved my problem.

ResponseEntity<List<POJO>> responseEntity = restTemplate.exchange(
URL,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<POJO>>() {
});
List<POJO> pojoObjList = responseEntity.getBody();

Happy Coding :)

Create Bean for Rest Template to auto wiring the Rest Template object.

@SpringBootApplication
public class ChatAppApplication {


@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}


public static void main(String[] args) {
SpringApplication.run(ChatAppApplication.class, args);
}


}

Consume the GET/POST API by using RestTemplate - exchange() method. Below is for the post api which is defined in the controller.

@RequestMapping(value = "/postdata",method = RequestMethod.POST)
public String PostData(){


return "{\n" +
"   \"value\":\"4\",\n" +
"   \"name\":\"David\"\n" +
"}";
}


@RequestMapping(value = "/post")
public String getPostResponse(){
HttpHeaders headers=new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity=new HttpEntity<String>(headers);
return restTemplate.exchange("http://localhost:8080/postdata",HttpMethod.POST,entity,String.class).getBody();
}

Refer this tutorial[1]

[1] https://www.tutorialspoint.com/spring_boot/spring_boot_rest_template.htm

Does Retrofit have any method to achieve this? If not, how I can do that?

YES

Retrofit is type-safe REST client for Android and Java. Retrofit turns your HTTP API into a Java interface.

For more information refer the following link

https://howtodoinjava.com/retrofit2/retrofit2-beginner-tutorial

Modern Spring 5+ answer using WebClient instead of RestTemplate.

Configure WebClient for a specific web-service or resource as a bean (additional properties can be configured).

@Bean
public WebClient localApiClient() {
return WebClient.create("http://localhost:8080/api/v3");
}

Inject and use the bean from your service(s).

@Service
public class UserService {


private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(3);


private final WebClient localApiClient;


@Autowired
public UserService(WebClient localApiClient) {
this.localApiClient = localApiClient;
}


public User getUser(long id) {
return localApiClient
.get()
.uri("/users/" + id)
.retrieve()
.bodyToMono(User.class)
.block(REQUEST_TIMEOUT);
}


}

As has been mentioned in the various answers here, WebClient is now the recommended route. You can start by configuring a WebClient builder:

@Bean
public WebClient.Builder getWebClientBuilder(){
return WebClient.builder();
}

Then inject the bean and you can consume an API as follows:

@Autowired
private WebClient.Builder webClientBuilder;




Product product = webClientBuilder.build()
.get()
.uri("http://localhost:8080/api/products")
.retrieve()
.bodyToMono(Product.class)
.block();

In this case need download whit my API, files hosted in other server.

In my case, don't need use a HTTP client to download the file in a external URL, I combined several answers and methods worked in previous code for files that were in my local server.

My code is:

@GetMapping(value = "/download/file/pdf/", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<Resource> downloadFilePdf() throws IOException {
String url = "http://www.orimi.com/pdf-test.pdf";
    

RestTemplate restTemplate = new RestTemplate();
byte[] byteContent = restTemplate.getForObject(url, String.class).getBytes(StandardCharsets.ISO_8859_1);
InputStream resourceInputStream = new ByteArrayInputStream(byteContent);
    

return ResponseEntity.ok()
.header("Content-disposition", "attachment; filename=" + "pdf-with-my-API_pdf-test.pdf")
.contentType(MediaType.parseMediaType("application/pdf;"))
.contentLength(byteContent.length)
.body(new InputStreamResource(resourceInputStream));
}

and it works with HTTP and HTTPS urls!

Since the question explicitly tags spring-boot, it worth noting that recent versions already ship a pre-configured instance of a builder for WebClient, thus you can directly inject it inside your service constructor without the needing to define a custom bean.

@Service
public class ClientService {


private final WebClient webClient;


public ClientService(WebClient.Builder webClientBuilder) {
webClient = webClientBuilder
.baseUrl("https://your.api.com")
}


//Add all the API call methods you need leveraging webClient instance


}

https://docs.spring.io/spring-boot/docs/2.0.x/reference/html/boot-features-webclient.html

Simplest way I have found is to:

  • Create an annotated interface (or have it generated from somehing like OpenAPI)
  • Give that interface to Spring RestTemplate Client

The Spring RestTemplate Client will parse the annotations on the interface and give you a type safe client, a proxy-instance. Any invocation on the methods will be seamlessly translated to rest-calls.

final MyApiInterface myClient = SpringRestTemplateClientBuilder
.create(MyApiInterface.class)
.setUrl(this.getMockUrl())
.setRestTemplate(restTemplate)         // Optional
.setHeader("header-name", "the value") // Optional
.setHeaders(HttpHeaders)               // Optional
.build();

And a rest call is made by inoking methods, like:

final ResponseEntity<MyDTO> response = myClient.getMyDto();