SpringCloud exception handling unified encapsulation I do – use the article

Introduction to the

Let me write the repeat function. In the SpringBoot project, there are global exception handling and return packaging, etc., return front is with SUCC, code, MSG, data and other fields. It is easy to solve in the case of a single project. When there are many microservice modules, in many cases the development is to copy the original code to build another project, which results in the need to modify multiple services to upgrade these functions. On this basis, We have packaged a component called Unified Dispose – Spring-cloud-starter which contains some basic exception handling and return wrapper functionality.

Depend on add startup

Add the dependentps:Actual version Use the latest versionLatest version:

Check out the latest version

<dependency> <groupId>com.purgeteam.cloud</groupId> <artifactId>unified-dispose-spring-cloud-starter</artifactId> . < version > 0.3.0 RELEASE < / version > < / dependency >Copy the code

Startup class add the @enableGlobalDispose annotation to enable the following functions.

@EnableGlobalDispose @SpringBootApplication public class GlobalDisposeSpringBootApplication { public static void main(String[] args) { SpringApplication.run(GlobalDisposeSpringBootApplication.class, args); }}Copy the code

One Exception handling ⚠️

System exceptions, such as NullPointerExceptions, often occur in projects. If the default is not handled, SpringBoot will respond to the default error message, which is not friendly to the user experience. If the system level error is not perceived by the user, even if the error is 500, the user can be prompted with a friendly message like server alarm.

The module contains some basic exception handling methods (and does not need to do any coding already has basic exception handling), as well as some common exception code, users only need to care about business exception handling can be directly thrown by the way of new exception.

Exception handling contains types

# Common 500 Exception class catch 500 Exception handling # FeignException class catch FeignException ClientException class catch # Business custom BusinessException class catch Business general custom exception # parameters calibration abnormal HttpMessageNotReadableException error exception BindException parameter error exceptionCopy the code

The program actively throws an exception

throw new BusinessException(BusinessErrorCode.BUSINESS_ERROR); // throw new BusinessException("CLOUD800"," No excess inventory ");Copy the code

It is generally not recommended to throw a generic BusinessException directly. Instead, you should add a dome-specific exception handling class and the corresponding enumeration error type to the corresponding module.

Such as membership module: create UserException exception class, UserErrorCode enumeration.

UserException:

Inheritance BusinessException

/** * {@link RuntimeException} User service exception ** @author purgeyao * @since 1.0 */ Getter Public Class UserException extends  BusinessException { private String code; private boolean isShowMsg = true; @param errorCode Error enumeration */ public UserException(UserErrorCode errorCode) {super(errorcode.getCode (), errorCode.getMessage()); this.code = errorCode.getCode(); }}Copy the code

UserErrorCode:

@getter Public enum UserErrorCode {/** * permissions failed */ NOT_PERMISSIONS("CLOUD401"," you do not have permissions "),; private String code; private String message; UserErrorCode(String code, String message) { this.code = code; this.message = message; }}Copy the code

The final service usage is as follows:

Throw new UserException(userErrorCode.not_permissions);Copy the code

In the above manner, the exception thrown will be handled by the module. The front desk returns the following:

"Ts ": 1566467628851, // Timestamp "data": null, // data" code": "CLOUD800", // error type" MSG ": "Service exception ", // Error description}Copy the code

Tow unified return package 🗳

In REST-style development, avoid telling the foreground whether the return was successful and the status code. Here we usually return the util wrapper work, such as: Result similar class, which contains succ, code, MSG, data and other fields.

Interface calls are handled like this:

  @GetMapping("hello")
  public Result list(){
    return Result.ofSuccess("hello");
  }Copy the code

Results:

{"succ": true, // successful "ts": 1566467628851, // Timestamp "data": "hello", // data" code": null, // error type "MSG ": Null, // error description "fail": true}Copy the code

Function using

By default, all Web Controllers are encapsulated in the following return format.

Interface:

@GetMapping("test")
public String test(){
  return "test";
}Copy the code

return

{"succ": true, // successful "ts": 1566386951005, // timestamp "data": "test", // data" code": null, // error "MSG ": null, // error description}Copy the code

Ignore encapsulated annotations@IgnoreResponseAdvice

Public @interface IgnoreResponseAdvice {/** * Whether global exception handling encapsulates * @return true: this exception is processed; False: No exception handling */ Boolean errorDispose() default true; }Copy the code

The @ignoreresponseAdvice allows for: class + method, indicating that the return of all methods under this class on the class will ignore return encapsulation.

Interface:

@ignoreresponseadvice @getMapping ("test") public String test(){return "test"; }Copy the code

Return to the test

FeignClientInvoke exception return handling

The default FeignClient call exception returns a FeignException 500 exception. Because uniform exception handling is enabled, the called feign exception is handled as a wrapped result.

Server:

@override public Boolean testBoolean() throws Exception {throw new Exception(" Exception "); }Copy the code

Calls to end:

@getMapping ("testBoolean") public Boolean testBoolean() throws Exception {// Exception occurs when calling the server. // If the server is not added IgnoreResponseAdvice(errorDispose = false) There was an unexpected error (type=Internal Server error, status=500). // Error while extracting response for type [class java.lang.Boolean] and content type [application/json; charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.lang.Boolean` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.Boolean` out of START_OBJECT token at [Source: (PushbackInputStream); line: 1, column: 1] return exampleFeignClient.testBoolean(); }Copy the code

So the exampleFeignClient#testBoolean call has a FEIGN conversion exception.

Here you need to turn off the provider’s FeIGN interface exception handling. Or add @ignoreresponseAdvice (errorDispose = false) to this interface class

/** * Add the IgnoreResponseAdvice#errorDispose set to an exception that does not need to be wrapped */ @override @ignoreresponseAdvice (errorDispose = false) public Boolean testBoolean() throws Exception {throw new Exception(" simulated Exception "); }Copy the code

conclusion

There are many duplicate codes in the project. We can simplify them in certain ways to reduce the amount of development. PurgeTeam has some excellent open source components that reduce the amount of day-to-day development.

Example code address :unified-dispose-spring-cloud-starter

GitHub: Purgeyao welcome to follow

Qq communication group: 812321371 wechat communication group: MercyYao

Wechat Official Account:

This article is published by OpenWrite!