In the process of using Spring Boot to develop microservices, we will use interfaces provided by others, and also design interfaces for others to use. In this case, the collaboration between microservices applications needs to be standardized.
-
Based on RPC protocol, we generally have two ideas :(1) the application that provides services uniformly wraps exceptions and interacts with error codes; (2) The application that provides the service throws the run-time exception and throws the user-defined business exception. The caller of the service handles the exception through the exception catch.
-
Based on THE HTTP protocol, the most popular is RESTful protocol. The service provider will handle all exceptions by itself, and the return result will be combined with the HTTP status code. This article uses an example to illustrate how RESTful interface error handling is done.
First we need to create a simple Controller with the following code:
@RestController
class GreetingController {
@RequestMapping("/greet")
String sayHello(@RequestParam("name") String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("The 'name' parameter must not be null or empty");
}
return String.format("Hello %s!", name); }}Copy the code
Send an HTTP request via an HTTP request client: Httpie. This tool has several advantages over curl: syntax highlighting and automatic formatting of the returned JSON string. Start the server, use the command HTTP: http://127.0.0.1:8080/greet? Name =duqi initiates a request with the following result:
HTTP/1.1 200 OK Content-Length: 11 Content-type: text/plain; Charset =UTF-8 Date: Sat, 05 Dec 2015 05:45:03 GMT Server: Apache-coyote /1.1 X-application-context: ApplicationCopy the code
Now we make an error request, @requestParam is to get a parameter from the URL, if this parameter is not provided then an error will occur. So let’s send a command HTTP http://127.0.0.1:8080 to see what happens.
HTTP/1.1 400 Bad Request Connection: close Content-Type: Application /json; Charset =UTF-8 Date: Sat, 05 Dec 2015 05:54:06 GMT Server: Apache-coyote /1.1 Transfer-encoding: chunked X-Application-Context: application {"error": "Bad Request"."exception": "org.springframework.web.bind.MissingServletRequestParameterException"."message": "Required String parameter 'name' is not present"."path": "/greet"."status": 400,
"timestamp": 1449294846060}Copy the code
As you can see, since no name argument is provided, the server returns a status code of 400: wrong request. The contents in the response body are as follows:
- Error: indicates an error message.
- Exception: the type of exception, MissingServletRequestParameterExeption, see knowledge meaning, that is the lack of a request parameter;
- Message: description of an exception
- Path: displays the requested URL path.
- Status: Indicates the returned error code
- Timestamp: timestamp at which the error occurred, call system.currentmills ()
What if we give the name parameter and do not assign a value to it? Sends an HTTP command HTTP: 127.0.0.1:8080 / greet? Name, the server returns the following value:
HTTP/1.1 500 Internal Server Error Connection: close Content-Type: application/json; Charset =UTF-8 Date: Sat, 05 Dec 2015 06:01:24 GMT Server: Apache-coyote /1.1 Transfer-encoding: chunked X-Application-Context: application {"error": "Internal Server Error"."exception": "java.lang.IllegalArgumentException"."message": "The 'name' parameter must not be null or empty"."path": "/greet"."status": 500,
"timestamp": 1449295284160}Copy the code
The error code is 500, indicating an internal server error. Returns the exception type is a Java. Lang. IllegalArgumentException, said parameter is illegal. An internal server error indicates that the server threw an exception and did not handle it. We prefer that the API return 400 to tell the caller what they did wrong. How do you do that? Use the @ExceptionHandler annotation.
Add the following handlers to the GreetingController controller to catch exceptions for this controller.
@ExceptionHandler
void handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value());
}
Copy the code
Again send orders HTTP HTTP: 127.0.0.1:8080 / greet? Name, the following result is returned:
HTTP/1.1 400 Bad Request Connection: close Content-Type: Application /json; Charset =UTF-8 Date: Sat, 05 Dec 2015 06:08:50 GMT Server: Apache-coyote /1.1 Transfer-encoding: chunked X-Application-Context: application {"error": "Bad Request"."exception": "java.lang.IllegalArgumentException"."message": "The 'name' parameter must not be null or empty"."path": "/greet"."status": 400,
"timestamp": 1449295729978}Copy the code
We caught IllegalArgumentException on the server side and set the return code for Response to 400. If you want to treat multiple exceptions the same, the above ExceptionHandler code can be modified to look like this (passing the @ExceptionHandler argument) :
@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class})
void handleIllegalArgumentException(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value());
}
Copy the code
Now the exception handler code is added to the current controller, so it only handles the responses that belong to that controller. If we create a new class with the @ControllerAdvice annotation, and define the above exception handler code in that class, it will handle all requests.
After Spring Boot 1.2.0, it is also possible to modify the corresponding message in Response by passing the corresponding message into the sendError function, for example:
@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class})
void handleIllegalArgumentException(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value(),
"Please try again and with a non empty string as 'name'");
}
Copy the code
Execute the same command again and receive the following feedback:
HTTP/1.1 400 Bad Request Connection: close Content-Type: Application /json; Charset =UTF-8 Date: Sat, 05 Dec 2015 06:21:05 GMT Server: Apache-coyote /1.1 Transfer-encoding: chunked X-Application-Context: application {"error": "Bad Request"."exception": "java.lang.IllegalArgumentException"."message": "Please try again and with a non empty string as 'name'"."path": "/greet"."status": 400,
"timestamp": 1449296465060}Copy the code
If you want to validate the parameters of a request, you can use the JSR-303 Bean Validation API and refer to Spring Validation. There is also an example Validating Form Input on Spring. IO.
The resources
- Tools to simulate GET/POST requests
- Spring Boot Error Response
Spring Boot 1.x series
- Automatic configuration of Spring Boot, command-line-runner
- Learn about automatic configuration of Spring Boot
- Use of Spring Boot’s @propertysource annotation in integrating Redis
- How do I customize the HTTP message converter in the Spring Boot project
- Spring Boot integration Mongodb provides Restful interfaces
- Scope for a bean in Spring
- The event dispatcher pattern is used in Spring Boot projects
This issue focuses on topics such as backend technology, JVM troubleshooting and optimization, Java interview questions, personal growth and self-management, providing readers with front-line developer work and growth experience, looking forward to your harvest here.