Spring Boot 2.1.5 (27) --- WebFlux REST API global exception handler Error Handling

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/zhangbijun1230/article/details/91354529

In this article

  • Why global exception handler?
  • WebFlux REST combat global exception handler
  • summary

Excerpt: only continue to develop good habits, while continuing to break bad habits, our behavior will be able to from beginning to end is correct.

First, why should global exception handler?

Development separated front and rear ends, generally provide REST API, will return to normal body response, there will be an error code corresponding to the response abnormality.

A lot of people consulting, Spring Boot MVC Exception handling section with  @RestControllerAdvice notes go to achieve global exception handler. Then how WebFlux handle exceptions? How to achieve a unified error exception handling code?

The benefits of the global exception handling:

  • Exception Error codes unified maintenance
  • Avoid some duplication of code

Two, WebFlux REST combat global exception handler

Here's how unified intercept abnormal, responds process.

 

2.1 Project Information

 

file

2.2 CityRouter class router

City router code is as follows:

@Configuration
public class CityRouter {

    @Bean
    public RouterFunction<ServerResponse> routeCity(CityHandler cityHandler) {
        return RouterFunctions.route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), cityHandler::helloCity);
    }

}

RouterFunctions routing processing based on the request, i.e. requests are routed to the processor, which will be a GET request / hello helloCity routed to the processor-cityHandler. Similarly with HandleMapping in Spring MVC pattern.

RouterFunctions.route (RequestPredicate, HandlerFunction) method, the corresponding reference parameter and a request handler, if the request matches, on the transfer function corresponding to the processor.

2.3 CityHandler service processing class

Urban server processing class code is as follows:

@Component
public class CityHandler {

    public Mono<ServerResponse> helloCity(ServerRequest request) {
        return ServerResponse.ok().body(sayHelloCity(request), String.class);
    }

    private Mono<String> sayHelloCity(ServerRequest request) {
        Optional<String> cityParamOptional = request.queryParam("city");
        if (!cityParamOptional.isPresent()) {
            throw new GlobalException(HttpStatus.INTERNAL_SERVER_ERROR, "request param city is ERROR");
        }

        return Mono.just("Hello," + cityParamOptional.get());
    }
}

Mono: to achieve the publisher, and returns 0 or an element that is a single object. Mono Publisher stream having a base responsive rx operator. Elements can successfully publish or error. Mono used as the return target, because a ServerResponse returns a object rather than a plurality of elements.

ServerResponse encapsulation response is to be provided in response to the state, the first response, the response body. For example, ok represents the 200 response code, MediaType enumeration is a representative of this text type, returns a String object.

ServerRequest is packaged to the request. City out value from the request, if no corresponding exception is thrown. GlobalException overall package is abnormal.

Mono.justOrEmpty (): Optional created Mono from a null object or objects.

2.4 GlobalError processing class

Figure:

file

GlobalException global exception classes, as follows:

public class GlobalException extends ResponseStatusException {

    public GlobalException(HttpStatus status, String message) {
        super(status, message);
    }

    public GlobalException(HttpStatus status, String message, Throwable e) {
        super(status, message, e);
    }
}

GlobalErrorAttributes global exception class attribute value, as follows:

@Component
public class GlobalErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(request, includeStackTrace);

        if (getError(request) instanceof GlobalException) {
            GlobalException ex = (GlobalException) getError(request);
            map.put("exception", ex.getClass().getSimpleName());
            map.put("message", ex.getMessage());
            map.put("status", ex.getStatus().value());
            map.put("error", ex.getStatus().getReasonPhrase());

            return map;
        }

        map.put("exception", "SystemException");
        map.put("message", "System Error , Check logs!");
        map.put("status", "500");
        map.put("error", " System Error ");
        return map;
    }
}

Override the default parent DefaultErrorAttributes getErrorAttributes error attribute class property methods of obtaining the error, the request from the service package corresponding to the acquired abnormal ServerRequest.

It is then determined whether GlobalException, if a service such CityHandler thrown GlobalException, error information corresponding to the return.

GlobalErrorWebExceptionHandler global exception handler class, as follows:

@Component
@Order(-2)
public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext,
            ServerCodecConfigurer serverCodecConfigurer) {
        super(g, new ResourceProperties(), applicationContext);
        super.setMessageWriters(serverCodecConfigurer.getWriters());
        super.setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(final ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    private Mono<ServerResponse> renderErrorResponse(final ServerRequest request) {

        final Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);

        return ServerResponse.status(HttpStatus.BAD_REQUEST)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .body(BodyInserters.fromObject(errorPropertiesMap));
    }

}

Code analysis as follows:

  • AbstractErrorWebExceptionHandler abstract class is extended and when implemented to handle global error
  • @Order sorting section AspectJ annotation tag, the smaller value has the higher priority, the high priority set here.
  • Constructor GlobalErrorAttributes global exception class attribute value is set to the local variables AbstractErrorWebExceptionHandler abstract class.
  • GetRoutingFunction rewriting method, provided the corresponding service response objects and Mono RequestPredicates
  • The global GlobalErrorAttributes exception property value map, can be set to the new ServerResponse.

Basic to this end. Spring Boot MVC how to combat error codes, refer to the address: https: //www.bysocket.com/archives/1692

2.5 verification run

IDEA performed in the  Application class started, the normal mode or any Debug mode. Then open a browser to access:

http://localhost:8091/hello

Abnormal interface is as follows:

 

See, this is a global exception of information thrown at CityHandler city service such logic. So how would normally be?

Change the next URL, visit the following:

http://localhost:8080/hello?city=WenLing

Normal interface is as follows:

 

III Summary

Class represents no error response in the Spring framework, but returns a response, a Map. If an error return code to define business body, how to combat error code reference

This article focuses on is different from the traditional MVC pattern Spring Boot unified exception handling, the WebFlux combat global exception handling mechanism. Combat this extension need to be considered:

  • Abnormal delamination, extend from the base class
  • Error code stratified design, easy to expand, such as new fields in call volume error codes ...

 

 

Guess you like

Origin blog.csdn.net/zhangbijun1230/article/details/91354529