在實(shí)際開發(fā)中,我們會(huì)遇到很多異常,在發(fā)生異常的時(shí)候Spring Boot默認(rèn)提供了錯(cuò)誤頁面展示給用戶。看似比較友好,其實(shí)頁面很丑。
上面講的是做頁面開發(fā)的時(shí)候遇到的問題,還有一種情況就是用來開發(fā)Rest接口,當(dāng)錯(cuò)誤的時(shí)候我們希望返回給用戶的是我們接口的標(biāo)準(zhǔn)格式,不是返回一段html代碼。 接下來分別給大家介紹下解決方案: 頁面處理首先我們來看頁面錯(cuò)誤的處理情況,當(dāng)我們的程序內(nèi)部報(bào)錯(cuò)的時(shí)候或者訪問的頁面找不到的時(shí)候,我們可以看到下面的錯(cuò)誤頁面: 我們可以自己設(shè)計(jì)好看一點(diǎn)的頁面來替換這個(gè)頁面,這樣會(huì)更友好點(diǎn),比如我們看今日頭條的頁面:
以前用Spring MVC時(shí)都是直接配置web.xml error-page> error-code>404error-code> location>/WEB-INF/view/404.jsplocation> error-page> error-page> error-code>400error-code> location>/WEB-INF/view/400.jsplocation> error-page> error-page> error-code>500error-code> location>/WEB-INF/view/500.jsplocation> error-page>
在Spring Boot中也非常簡(jiǎn)單,直接編寫對(duì)應(yīng)的錯(cuò)誤頁面,進(jìn)行覆蓋即可: /** * 自定義錯(cuò)誤頁面覆蓋spring boot中的錯(cuò)誤頁面 * @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'; } }
頁面內(nèi)容可以自己寫: body> section id='error' class='container text-center' style='height:800px;'> h1>404, 頁面沒有找到h1> p>您正在尋找的頁面不存在或發(fā)生其他錯(cuò)誤。p> a class='btn btn-primary' href='http://pan.'>回到網(wǎng)站首頁a> section> body>
REST接口處理在開發(fā)rest接口時(shí),我們往往會(huì)定義統(tǒng)一的返回格式,列如: { 'status': true, 'code': 200, 'message': null, 'data': [ { 'id': '101', 'name': 'jack' }, { 'id': '102', 'name': 'jason' } ] }
但是如果調(diào)用方請(qǐng)求我們的api時(shí)把接口地址寫錯(cuò)了,就會(huì)得到一個(gè)404錯(cuò)誤頁面,最友好的方式就是返回固定的JSON格式,里面有個(gè)code為404。 所以我們需要在發(fā)生這種系統(tǒng)錯(cuò)誤時(shí)也能返回我們自定義的那種格式 定義一個(gè)異常處理類 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); /** * 系統(tǒng)異常處理,比如: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是我們返回格式的實(shí)體類 public class ResponseData { private Boolean status = true; private int code = 200; private String message; private Object data; }
這種在發(fā)生錯(cuò)誤時(shí)這邊會(huì)捕獲到,然后封裝好返回格式,返回給調(diào)用方 最后關(guān)鍵的一步是在spring boot的配置文件中加上如下配置: #出現(xiàn)錯(cuò)誤時(shí), 直接拋出異常 spring.mvc.throw-exception-if-no-handler-found=true #不要為我們工程中的資源文件建立映射 spring.resources.add-mappings=false
然后我們調(diào)用一個(gè)不存在的接口時(shí),返回的錯(cuò)誤信息就是我們自定義的那種格式了 { 'status': false, 'code': 404, 'message': 'No handler found for GET /rest11/auth', 'data': null }
頁面錯(cuò)誤和REST錯(cuò)誤共存當(dāng)我們加好rest接口處理的方式后,訪問頁面不存在就會(huì)返回一段json數(shù)據(jù),如果你的項(xiàng)目中既有rest接口,又有頁面,這個(gè)時(shí)候就有沖突了。 我們可以通過為rest接口增加統(tǒng)一的訪問前綴,比如:/rest/xxxx來區(qū)分請(qǐng)求,然后用@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); /** * 系統(tǒng)異常處理,比如: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'; } } } }
|