You can now connect to the DB with Last time. This time, let's use RestTemplate to send a request to an external API and receive the response. The API used this time is Zip Code Search API.
By adding query parameters to the base URL and sending It is an API that returns search results as a JSON object. For details, please refer to Link.
Let's create an API now.
The configuration this time is a controller class that receives the zip code as a query parameter, and Let's create a client class that sends the zip code as a query parameter to the zip code search API and receives the result. (I will omit the data class) Since we will receive the zip code as an input value, we will also implement a simple validation and error handler.
GetAddressController.java
@RestController
@RequiredArgsConstructor
@Validated // (1)
public class GetAddressController {
private final GetAddressApiClient client;
@GetMapping("/get/address")
public GetAddressResponse getAddress(@ZipCode @RequestParam("zipcode") String zipCode) { // (1)
return GetAddressResponse.create(client.request(zipCode));
}
}
ZipCode.java
@Documented
@Constraint(validatedBy = {})
@Target(PARAMETER)
@Retention(RUNTIME)
@Pattern(regexp = "[0-9]{3}[-]{0,1}[0-9]{4}") // (2)
public @interface ZipCode {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
CommonExceptionHandler.java
@RestControllerAdvice // (3)
public class CommonExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class) // (3)
public ResponseEntity handleConstraintViolationException(ConstraintViolationException ex) {
GetAddressResponse response = new GetAddressResponse(
"400",
"The zip code you entered is incorrect.",
null
);
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); // (4)
}
}
Then, I will give a brief explanation following the last time.
(1). Validation is enabled by @Validated
. You can also check the validation by adding your own annotation (@ZipCode
) to the query parameter, and if it violates, ConstraintViolationException
will be thrown.
(2). Implementation of self-made annotation. For details, please see the article here, but the validation logic is only the @ Pattern
part.
(3). By giving @RestControllerAdvice
, you can implement the process (** AOP **) common to all controllers with @RestController
. If the controller throws an exception that corresponds to the argument of @ExceptionHandler
, that method will work. I think this combination is often used, so it's useful to remember.
(4). The return value of the handler implemented using @ExceptionHandler
should be the ResponseEntity
class. It will nicely convert it to an HTTP response using the body and HTTP status given by this. By the way, you can also specify the Header attribute.
It's roughly like this. As you can see by looking at the regular expression, we have a policy that "-" may or may not be present according to the specifications of the postal code search API. Next is the Client class.
GetAddressApiClient.java
@Component
public class GetAddressApiClient {
private final RestTemplate restTemplate;
public GetAddressApiClient(RestTemplateBuilder restTemplateBuilder,
ResponseHeaderInterceptor interceptor) { // (1)
restTemplate = restTemplateBuilder
.rootUri("http://zipcloud.ibsnet.co.jp")
.additionalInterceptors(interceptor)
.build();
}
public GetAddressApiResponse request(String zipCode) {
return restTemplate.getForObject("/api/search?zipcode={zipCode}", // (2)
GetAddressApiResponse.class,
zipCode);
}
}
ResponseHeaderInterceptor.java
@Component
public class ResponseHeaderInterceptor implements ClientHttpRequestInterceptor {
@Override // (3)
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
ClientHttpResponse response = execution.execute(request, body);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
return response;
}
}
(1). RestTeplate
is initialized in the constructor. You can initialize it with each implementation method, but this time, assuming that multiple methods will be implemented, the common part will be initialized with the constructor. rootUri
sets the request URI that will be the root as it is, and ʻadditionalInterceptorssets the response format. (2). An implementation method that sends a request and receives a response. Pass the request path in the first argument of the
getForObject ()method, the response class in the second argument, and the value to be mapped to the parameter in the third argument. As an implementation, this is all you need to send a request and receive a response. (3). By adding the class that implements
ClientHttpRequestInterceptor to
RestTemplate, you will be able to receive the response in ʻapplication / json
. Please refer to here and here. * Implementation is round plagiarism.
This is all you need to do to complete the implementation. Finally, let's hit the API from Postman to see if it works as expected!
Let's use the following 5 test patterns.
Let's hit it.
Result: ** OK !! ** </ font>
Result: ** OK !! ** </ font>
Result: ** OK !! ** </ font>
Result: ** OK !! ** </ font>
Result: ** OK !! ** </ font>
It seems to be working safely! !!
You can now also send requests to external APIs! I was also able to implement a simple but simple validation check, so I think you can now create a simple API!
If you have any mistakes, we welcome your comments! Thank you for reading to the end! !!
Recommended Posts