How to realize the unified return of the interface and the unified capture of exceptions in SpringBoot

Unified return of the interface

When developing the company interface, it is found that the interface return of the Controller layer needs to be wrapped in a Result, as shown in the following figure:

image

Whether it is creating an interface or querying an interface in the graphic code, a Result is needed to receive here, let's take a look at the structure of the Result:

There are several fields in this Result:

  • code: status code

  • message: status information

  • data: load the data returned

  • exception: abnormal data

Then we test the interface and see the return style:

image

image

Call the interface, the return format is:

{
  "code": 200,
  "message": "SUCCESS",
  "data": {
      ...
  }
  "exception": xxx
}

After writing, I was thinking that every interface needs to be wrapped with a layer of Result, which affects the readability of the interface. As a development, it is also very troublesome to wrap one layer in this way.

So is there a way to automatically wrap a layer of Result through the framework, and develop it as long as it returns the entity directly in the Controller layer?

There really is such a method that can realize the unified return of the Controller layer interface:

image

As in the above code, we use ResponseBodyAdviceto intercept the default return parameters of the Controller layer method. To put it bluntly, it is an interceptor. It mainly depends on the beforeBodyWrite()method. In this method, if the return in the Controller is already a Result, then the Result is returned directly. If not, use Result to wrap it.

Let's take a look at the effect:

image

As in the above code, we return the entity directly, let's take a look at the return of Swagger:

The format returned by swagger is the format of our interceptor.

Here I have another question. The normal interface return has been wrapped by Result. If the interface throws an exception, how can it return the same format?

Global exception capture

Here we need global exception capture. Regarding global exception capture, I believe many children's shoes know:

We need to write a capture class, add @ControllerAdviceannotations to it, and then write methods to handle exceptions:

image

We add @ResponseBodyannotations and @ExceptionHandlerannotations, here value = Exception.class, it means that we catch exceptions of type Exception. We can throw exceptions directly:

image

You can also throw it like this:

We test, if the code throws an exception, the interface will return:

The format is as expected.

But there is still a problem here, every time I need to write an if statement:

if(条件) {
   throw new RuntimeException("...");
}

It's still too troublesome to write this way, and everything is thrown away RuntimeException. This is still too rough.

So I decided to customize a business exception, and encapsulate some exception-throwing methods, and do whatever it takes.

Custom business exception

image

We define a business exception, which encapsulates the exception status code and exception information data.

Throw exception gracefully

Then we write a business exception judgment class:

image

Only part of the code is intercepted here, there are actually only two methods checkArgument()and checkNotNull(). What are they good for? If you want to do a non-empty check, it is generally done as follows:

if (updateEntity == null) {
    throw new RuntimeException("传入参数为null");
}

But now you can do this:

BusinessExceptionAssert.checkNotNull(updateEntity, "参数不能为null");

What is thrown is my custom business exception.

What if it is a general logic check? The previous code is written like this:

if(!"1".equals(id)) {
   throw new RuntimeException(String.format("参数id【%s】只能为1",id));
}

There can now be more elegant implementations:

BusinessExceptionAssert.checkArgument("1".equals(id), 500, "参数id【%s】只能为1",id);

Because the business exception is thrown, we can also customize the exception code.

Complete test code:

 @ApiOperation(value = "test-测试异常", httpMethod = "POST", notes = "测试代码,勿动")
 @PostMapping(value = "testBusinessException")
 public int testBusinessException(@RequestParam String id) {
     BusinessExceptionAssert.checkArgument("1".equals(id), 500, "参数id【%s】只能为1",id);
     return 1;
 }

Our test results:

image

In line with expectations.

This article is over here, this article mainly explains:

  • How to realize the unified return of the interface

  • How to customize business exceptions and be uniformly caught

  • How to throw an exception gracefully

If there are any improvements, you are welcome to communicate actively.

 

Guess you like

Origin blog.csdn.net/wujialv/article/details/111879692