Using SpringBoot easy to get global exception

SpringBoot To simplify the  Spring creation of applications, run, debug, deploy a range of issues such as the birth of the product, characteristics of the automatic assembly so that we can better focus on the business itself, rather than external XML configuration, we simply follow the norms related to the introduction of dependence can easily build a WEB project

The actual project development, the program is often a wide range of abnormal happens, especially as our server developer, always keep the front-end interface to write call, in the case of division of labor, can not avoid abnormal happen if the wrong information directly exposed directly to users, this experience can be imagined, and for *** for detailed information on abnormalities tend to offer a very big help ...

First Look abnormal

A simple interface to request exception

@GetMapping("/test1")
public String test1() {
    // TODO 这里只是模拟异常,假设业务处理的时候出现错误了,或者空指针了等等...
    int i = 10 / 0;
    return "test1";
}

Open a browser to access it when found

Using SpringBoot easy to get global exception Exception information in the browser

Or is  postman simulation tools

Using SpringBoot easy to get global exception

If this interface is a call to a third party or the company's own system, see this miscalculation ... it was a runaway.

Stupid way (highly not recommended)

Use try-catchmode, manually capture the abnormality information, and returns a corresponding result set, I believe many people have seen a similar code (for example: Result object encapsulated as); Though the indirect method of solving the problems exposed errors, the same drawbacks it is also clear that increasing the number of code amount, corresponding to the excessive when abnormality catchlayer up increasingly more difficult to manage when a match between the business exceptions and error codes, so the best way is by simple configure global control ....

@GetMapping("/test2")
public Map<String, String> test2() {
    Map<String, String> result = new HashMap<>(16);
    // TODO 直接捕获所有代码块,然后在 cache
    try {
        int i = 10 / 0;
        result.put("code", "200");
        result.put("data", "具体返回的结果集");
    } catch (Exception e) {
        result.put("code", "500");
        result.put("message", "请求错误");
    }
    return result;
}

Specific code

Through the above reading you can understand why we all need to roughly abnormal globally captured, then look at  Spring Boot solutions offered

Import dependence

In  pom.xml the add  spring-boot-starter-web -dependent can

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Custom exception

In the application development process, in addition to the system itself unusual, different business scenarios used in the anomaly are not the same, with the title to  be easy to get global exception  more appropriate definition of their own exceptions, to see how to capture ...

package com.battcn.exception;

/**
 * 自定义异常
 *
 * @author Levin
 * @since 2018/6/1 0001
 */
public class CustomException extends RuntimeException {

    private static final long serialVersionUID = 4564124491192825748L;

    private int code;

    public CustomException() {
        super();
    }

    public CustomException(int code, String message) {
        super(message);
        this.setCode(code);
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

Abnormal Templates

Define the return format, this abnormal Style abnormal information is more unified

package com.battcn.exception;

/**
 * @author Levin
 * @since 2018/6/1 0001
 */
public class ErrorResponseEntity {

    private int code;
    private String message;
    // 省略 get set 
}

Control Layer

Look closely and is not usually normal write code lacks distinction, do not rush, then look ....

package com.battcn.controller;

import com.battcn.exception.CustomException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常演示
 *
 * @author Levin
 * @since 2018/5/31 0031
 */
@RestController
public class ExceptionController {

    @GetMapping("/test3")
    public String test3(Integer num) {
        // TODO 演示需要,实际上参数是否为空通过 @RequestParam(required = true)  就可以控制
        if (num == null) {
            throw new CustomException(400, "num不能为空");
        }
        int i = 10 / num;
        return "result:" + i;
    }
}

Exception Handling (key)

Notes Overview

  • @ControllerAdvice  capture  Controller layer thrown exception, if you add  @ResponseBody return information compared JSON format.
  • @RestControllerAdvice  corresponds to  @ControllerAdvice the  @ResponseBody binding body.
  • @ExceptionHandler  unitary one kind of exception classes, the repetition rate of the code decrease, reduce complexity.

Create a  GlobalExceptionHandler class and add the  @RestControllerAdvice annotation can define an exception notification class, and then add on the method defined  @ExceptionHandler to achieve unusual catch ...

package com.battcn.config;

import com.battcn.exception.CustomException;
import com.battcn.exception.ErrorResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 全局异常处理
 *
 * @author Levin
 * @since 2018/6/1 0001
 */
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    /**
     * 定义要捕获的异常 可以多个 @ExceptionHandler({})
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return 响应结果
     */
    @ExceptionHandler(CustomException.class)
    public ErrorResponseEntity customExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        CustomException exception = (CustomException) e;
        return new ErrorResponseEntity(exception.getCode(), exception.getMessage());
    }

    /**
     * 捕获  RuntimeException 异常
     * TODO  如果你觉得在一个 exceptionHandler 通过  if (e instanceof xxxException) 太麻烦
     * TODO  那么你还可以自己写多个不同的 exceptionHandler 处理不同异常
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return 响应结果
     */
    @ExceptionHandler(RuntimeException.class)
    public ErrorResponseEntity runtimeExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        RuntimeException exception = (RuntimeException) e;
        return new ErrorResponseEntity(400, exception.getMessage());
    }

    /**
     * 通用的接口映射异常处理方
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
                                                             HttpStatus status, WebRequest request) {
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
        }
        if (ex instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
            logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
                    + ",信息:" + exception.getLocalizedMessage());
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
        }
        return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
    }
}

The main function

package com.battcn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author Levin
 */
@SpringBootApplication
public class Chapter17Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter17Application.class, args);
    }

}

test

Upon completion Preparations start Chapter17Application, it can be found through the following test results, really  so easy, the code became clean, scalability is also changed for the better ...

access http://localhost:8080/test3

{"code":400,"message":"num不能为空"}

access http://localhost:8080/test3?num=0

{"code":400,"message":"/ by zero"}

access http://localhost:8080/test3?num=5

result:2

Guess you like

Origin blog.51cto.com/14230003/2416534