知識點-Spring Boot 異常處理彙總

在實際開發中,咱們會遇到不少異常,在發生異常的時候Spring Boot默認提供了錯誤頁面展現給用戶。看似比較友好,其實頁面很醜。html

上面講的是作頁面開發的時候遇到的問題,還有一種狀況就是用來開發Rest接口,當錯誤的時候咱們但願返回給用戶的是咱們接口的標準格式,不是返回一段html代碼。java

接下來分別給你們介紹下解決方案:web

頁面處理

首先咱們來看頁面錯誤的處理狀況,當咱們的程序內部報錯的時候或者訪問的頁面找不到的時候,咱們能夠看到下面的錯誤頁面:spring

1.png

咱們能夠本身設計好看一點的頁面來替換這個頁面,這樣會更友好點,好比咱們看今日頭條的頁面: json

2.png

之前用Spring MVC時都是直接配置web.xmlapi

<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中也很是簡單,直接編寫對應的錯誤頁面,進行覆蓋便可:bash

/**
 * 自定義錯誤頁面覆蓋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接口處理

在開發rest接口時,咱們每每會定義統一的返回格式,列如:mvc

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

可是若是調用方請求咱們的api時把接口地址寫錯了,就會獲得一個404錯誤頁面,最友好的方式就是返回固定的JSON格式,裏面有個code爲404。app

因此咱們須要在發生這種系統錯誤時也能返回咱們自定義的那種格式

定義一個異常處理類

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;
    }
}

複製代碼

ResponseData是咱們返回格式的實體類

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

這種在發生錯誤時這邊會捕獲到,而後封裝好返回格式,返回給調用方

最後關鍵的一步是在spring boot的配置文件中加上以下配置:

#出現錯誤時, 直接拋出異常
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接口,又有頁面,這個時候就有衝突了。

咱們能夠經過爲rest接口增長統一的訪問前綴,好比:/rest/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";
			}
		}

	}

}
複製代碼

更多技術分享請關注微信公衆號:猿天地

image.png
相關文章
相關標籤/搜索