javascript
html页面源码_整合SpringMVC之错误处理底层原理及源码分析
一. SpringBoot的默認錯誤處理策略
1. 對404的默認處理策略
我們在發送請求的時候,如果發生了404異常,SpringBoot是怎么處理的呢?
我們可以隨便發送一個不存在的請求來驗證一下,就會看到如下圖所示:
2. 對500的默認處理策略
當服務器內部發生代碼等錯誤的時候,會發生什么呢?
比如我們人為的制造一個異常出來,如下面的代碼所示:
@GetMapping("/user/{id:d+}")public User get(@PathVariable String id) { throw new RuntimeException();}結果產生了如下所示效果圖:
3.在error頁面中可以獲取的錯誤信息
timestamp: 時間戳.status: 狀態碼.error: 錯誤提示.exception: 異常對象.message: 異常消息.errors: 數據效驗相關的信息.二. Spring Boot錯誤處理機制探究
通過上面的兩個案例,我們發現無論發生了什么錯誤,Spring Boot都會返回一個對應的狀態碼以及一個錯誤頁面,那么這個錯誤頁面是怎么來的呢?
要弄明白這個問題,我們需要從Spring Boot中錯誤處理的底層源碼來進行分析。
1. SpringBoot的錯誤配置信息
SpringBoot的錯誤配置信息是通過ErrorMvcAutoConfiguration這個類來進行配置的,這個類中幫我們注冊了以下組件:
DefaultErrorAttributes: 幫我們在頁面上共享錯誤信息;ErrorPageCustomizer: 項目中發生錯誤后,該對象就會生效,用來定義請求規則;BasicErrorController: 處理默認的 ’/error‘ 請求,分為兩種處理請求方式:一種是html方式,一種是json方式;DefaultErrorViewResolver: 默認的錯誤視圖解析器,將錯誤信息解析到相應的錯誤視圖.2. Spring Boot處理error的流程
- 一旦系統中出現 4xx 或者 5xx 之類的錯誤, ErrorPageCustomizer就會生效(定義錯誤的相應規則);
- 然后內部的過濾器就會映射到 ’/error‘ 請求,接著該/error請求就會被BasicErrorController處理;
- 然后BasicErrorController會根據請求中的Accept來區分該請求是瀏覽器發來的,還是由其它客戶端工具發來的.此時一般分為兩種處理方式:errorHtml()和error().
- 在errorHtml()方法中,獲取錯誤狀態信息,由resolveErrorView解析器解析到默認的錯誤視圖頁面,默認的錯誤頁面是/error/404.html頁面;
- 而如果templates目錄中的error目錄里面有這個頁面,404錯誤就會精確匹配404.html;
- 如果沒有這個404.html頁面它就會模糊匹配4xx.html頁面;
- 如果templates中沒有找到錯誤頁面,它就會去static文件中找.
注:
static文件夾存放的是靜態頁面,它沒有辦法使用模板引擎表達式.
簡單概括就是:
1??. 當出現4xx或5xx的錯誤:ErrorPageCustomizer開始生效;
2??. 然后ErrorPageCustomizer發起 /error 請求;
3??. /error 請求被BasicErrorController處理;
4??. BasicErrorController根據請求頭中的Accept決定如何響應處理.
其實在以上的所有類中,最重要的一個類就是BasicErrorController,所以接下來我們來分析BasicErrorController源碼,看看Spring Boot底層到底是怎么實現error處理的。
三. BasicErrorController源碼詳解
在Spring Boot中,當發生了錯誤后,默認情況下,Spring Boot提供了一個處理程序出錯的結果映射路徑 /error。當發生錯誤后,Spring Boot就會將請求轉發到BasicErrorController控制器來處理這個錯誤請求。
1. BasicErrorController源碼
所以我們重點分析BasicErrorController源碼,首先呈上源碼內容:
@Controller@RequestMapping("${server.error.path:${error.path:/error}}")public class BasicErrorController extends AbstractErrorController { private final ErrorProperties errorProperties; /** * Create a new {@link BasicErrorController} instance. * @param errorAttributes the error attributes * @param errorProperties configuration properties */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) { this(errorAttributes, errorProperties, Collections.emptyList()); } /** * Create a new {@link BasicErrorController} instance. * @param errorAttributes the error attributes * @param errorProperties configuration properties * @param errorViewResolvers error view resolvers */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List errorViewResolvers) { super(errorAttributes, errorViewResolvers); Assert.notNull(errorProperties, "ErrorProperties must not be null"); this.errorProperties = errorProperties; } @Override public String getErrorPath() { return this.errorProperties.getPath(); } @RequestMapping(produces = "text/html") public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView == null ? new ModelAndView("error", model) : modelAndView); } @RequestMapping @ResponseBody public ResponseEntity> error(HttpServletRequest request) { Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity>(body, status);}2. error.path分析
這個源碼的注釋信息中說明了,這是一個Spring Boot自帶的全局錯誤Controller.
這個Controller中有一個RequestMapping注解,內部有一個相當于三元運算符的操作。如果你在配置文件配置了server.error.path的話,就會使用你配置的異常處理地址,如果沒有就會使用你配置的error.path路徑地址,如果還是沒有,則默認使用/error來作為發生異常時的處理地址。
所以我們可以按照如下圖中的配置,來設置自定義的錯誤處理頁面。
3. errorHtml()與error()方法解析
從上面的源碼我們可以看到,BasicErrorController中有兩個RequestMapping方法,分別是errorHtml()與error()方法來處理錯誤請求。
那么為什么會是兩個呢?請看下面的截圖:
BasicErrorController內部是通過讀取request請求頭中的Accept屬性值,判斷其內容是否為text/html;然后以此來區分請求到底是來自于瀏覽器(瀏覽器通常默認自動發送請求頭內容Accept:text/html),還是客戶端,從而決定是返回一個頁面視圖,還是返回一個 JSON 消息內容。
可以看到其中errorHtml()方法是用來處理瀏覽器發送來的請求,它會產生一個白色標簽樣式(whitelabel)的錯誤視圖頁面,該視圖將以HTML格式渲染出錯誤數據。
該方法返回了一個error頁面,如果你的項目靜態頁面下剛好存在一個error所對應的頁面,那么Spring Boot會得到你本地的頁面,如下圖:
而error()方法用來處理來自非瀏覽器,也就是其他軟件app客戶端(比如postman等)發送來的錯誤請求,它會產生一個包含詳細錯誤,HTTP狀態及其他異常信息的JSON格式的響應內容。
注:
BasicErrorController可以作為自定義ErrorController的基類,我們只需要繼承BasicErrorController,添加一個public方法,并添加@RequestMapping注解,讓該注解帶有produces屬性,然后創建出該新類型的bean即可。
4. /error映射默認處理策略總結
經過上面的源碼分析得知,在默認情況下,Spring Boot為這兩種情況提供了不同的響應方式.
4.1 響應'Whitelabel Error Page'頁面
一種是瀏覽器客戶端請求一個不存在的頁面或服務端處理發生異常時,這時候一般Spring Boot默認會響應一個html文檔內容,稱作“Whitelabel Error Page”:
4.2 響應JSON字符串
另一種是當我們使用Postman等調試工具發送請求一個不存在的url或服務端處理發生異常時,Spring Boot會返回類似如下的一個 JSON 字符串信息:
{ "timestamp": "2019-05-20T06:12:45.209+0000", "status": 404, "error": "Not Found", "message": "No message available", "path": "/login.html"}總結
以上是生活随笔為你收集整理的html页面源码_整合SpringMVC之错误处理底层原理及源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nodejs源码_格物致知记一次node
- 下一篇: cors跨域_Nginx通过CORS配置