Точка знаний - сводка обработки исключений Spring Boot

Spring Boot задняя часть WeChat Spring

В реальной разработке мы столкнемся со многими исключениями.Когда возникает исключение, Spring Boot предоставляет страницу ошибки для отображения пользователю по умолчанию. Выглядит дружелюбно, но на самом деле страница уродлива.

Выше было о проблемах, возникающих при разработке страницы.Другая ситуация - разработка интерфейса Rest.При возникновении ошибки мы хотим вернуть пользователю стандартный формат нашего интерфейса, а не вернуть кусок html кода.

Далее мы представим вам решения:

обработка страницы

Прежде всего, давайте посмотрим на обработку ошибок страницы, Когда наша программа сообщает об ошибке или посещенная страница не может быть найдена, мы можем увидеть следующую страницу ошибки:

1.png

Мы можем создать более красивую страницу, чтобы заменить эту страницу, которая будет более дружественной.Например, мы смотрим на страницу Toutiao:

2.png

В прошлом при использовании Spring MVC файл web.xml настраивался напрямую.

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/view/404.jsp</location>
</error-page>
<error-page>
    <error-code>400</error-code>
    <location>/WEB-INF/view/400.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/view/500.jsp</location>
</error-page>

В Spring Boot это также очень просто: вы можете напрямую написать соответствующую страницу ошибки и перезаписать ее:

/**
 * 自定义错误页面覆盖spring boot中的错误页面
 * @author yinjihuan
 *
 */
@Controller
public class ErrorController {
    @GetMapping("/400")
    public String badRequest() {
        return "error/400";
    }
    @GetMapping("/404")
    public String notFound() {
        return "error/404";
    }
    @GetMapping("/500")
    public String serverError() {
        return "error/500";
    }
}

Содержимое страницы можно написать самостоятельно:

<body>
    <section id="error" class="container text-center" style="height:800px;">
        <h1>404, 页面没有找到</h1>
        <p>您正在寻找的页面不存在或发生其他错误。</p>
        <a class="btn btn-primary" href="http://pan.cxytiandi.com">回到网站首页</a> 
    </section>
</body>

Работа с REST-интерфейсом

При разработке интерфейса для отдыха мы часто определяем унифицированный формат возврата, например:

{
  "status": true,
  "code": 200,
  "message": null,
  "data": [
    {
      "id": "101",
      "name": "jack"
    },
    {
      "id": "102",
      "name": "jason"
    }
  ]
}

Но если звонящий напишет неправильный адрес интерфейса при запросе нашего API, он получит страницу с ошибкой 404. Самый дружелюбный способ — вернуть фиксированный формат JSON с кодом 404.

Поэтому нам нужно иметь возможность возвращать наш пользовательский формат при возникновении этой системной ошибки.

Определите класс обработки исключений

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
	
	/**
	 * 系统异常处理,比如:404,500
	 * @param req
	 * @param resp
	 * @param e
	 * @return
	 * @throws Exception
	 */
	@ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
		logger.error("", e);
		ResponseData r = new ResponseData();
        r.setMessage(e.getMessage());
        if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
        	 r.setCode(404);
		} else {
			 r.setCode(500);
		}
        r.setData(null);
        r.setStatus(false);
        return r;
    }
}

Ответы нашего возврата формируют классы сущности

public class ResponseData {
	private Boolean status = true;
	private int code = 200;
	private String message;
	private Object data;
}

Это будет захвачено здесь при возникновении ошибки, а затем инкапсулировано в формате возврата и возвращено вызывающей стороне.

Последний ключевой шаг — добавить следующую конфигурацию в файл конфигурации весенней загрузки:

#出现错误时, 直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#不要为我们工程中的资源文件建立映射
spring.resources.add-mappings=false

Затем, когда мы вызываем несуществующий интерфейс, возвращается сообщение об ошибке в формате, который мы настроили.

{
  "status": false,
  "code": 404,
  "message": "No handler found for GET /rest11/auth",
  "data": null
}

Ошибки страницы и ошибки REST сосуществуют

Когда мы добавим метод обработки интерфейса rest, часть данных json будет возвращена, если страница доступа не существует.Если в вашем проекте есть и интерфейс rest, и страница, в это время будет конфликт.

Мы можем добавить префикс унифицированного доступа для интерфейса отдыха, например: / RECT / XXXX, чтобы отличить запрос, затем использовать @controllerAdvice для обработки:

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;


@ControllerAdvice
public class GlobalExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	/**
	 * 系统异常处理,比如:404,500
	 * 
	 * @param req
	 * @param resp
	 * @param e
	 * @return
	 * @throws Exception
	 */
	@ExceptionHandler(value = Exception.class)
	// @ResponseBody
	public Object defaultErrorHandler(HttpServletRequest req, HttpServletResponse response, Exception e)
			throws Exception {
		logger.error("", e);
		if (req.getRequestURI().startsWith("/rest")) {
			ResponseData r = new ResponseData();
			r.setMessage(e.getMessage());
			if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
				r.setCode(404);
			} else {
				r.setCode(500);
			}
			r.setData(null);
			r.setStatus(false);
			PrintWriter writer = response.getWriter();
			writer.println(JsonUtils.toJson(r));
			writer.flush();
			writer.close();
			return null;
		} else {
			if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
				return "error/404";
			} else {
				return "error/500";
			}
		}

	}

}

Для большего обмена технологиями, пожалуйста, обратите внимание на общедоступную учетную запись WeChat: Yuantiandi

image.png