一、前言
在前邊部分我們已經學會了基本的web開發流程,在web開發中,我們通常會對請求做統一處理,比如未登錄的用戶要攔截掉相關請求,報錯頁面統一顯示等等,這些都需要配置,可以大大簡化我們的代碼,實現功能的完整性與統一性。
二、攔截器配置
首先我們先做一個登錄身份驗證攔截器,來攔截那些沒有登錄的用戶,保護我們的資源。下面我們創建一個攔截器,需要實現攔截器接口。
1 package com.example.demo.component; 2 3 import org.springframework.web.servlet.HandlerInterceptor; 4 import org.springframework.web.servlet.ModelAndView; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 public class LoginHandlerInterceptor implements HandlerInterceptor { 10 11 @Override 12 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 13 if(request.getSession().getAttribute("loginUser") == null){ 14 request.setAttribute("msg","請先登錄"); 15 request.getRequestDispatcher("/index.html").forward(request,response); 16 return false; 17 } 18 return true; 19 } 20 21 @Override 22 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 23 24 } 25 26 @Override 27 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 28 29 } 30 }
這個攔截器的作用是獲取當前session中的loginUser屬性,如果有值說明登錄了就可以放行,當然我們需要在登錄成功的代碼里邊設置好session的這個屬性。
在WebConfig中添加我們的攔截器:
1 //所有的WebMvcConfigurerAdapter組件都會一起起作用 2 @Bean //將組件注冊在容器 3 public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){ 4 WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() { 5 @Override 6 public void addViewControllers(ViewControllerRegistry registry) { 7 registry.addViewController("/").setViewName("login"); 8 registry.addViewController("/index.html").setViewName("login"); 9 } 10 11 @Override 12 public void addInterceptors(InterceptorRegistry registry) { 13 registry.addInterceptor(new LoginHandlerInterceptor()) 14 .excludePathPatterns("/index.html","/","/user/login"); 15 } 16 }; 17 return adapter; 18 }
第12-15行,注冊我們攔截器之后,排除掉不需要驗證的頁面,默認情況下靜態資源不會做驗證。
三、統一錯誤處理
springboot默認已經配置了統一錯誤處理,只不過錯誤頁面是內置的,可能不是我們想要的,所以如果我們要自定義錯誤頁面,還得重新配置。
3.1 定制錯誤頁面
在使用模板的情況下,springboot默認會找到/templates/error/xxx.html頁面作為錯誤頁面顯示,比如我們用4xx.html處理所有httpstatuscode以4開頭的錯誤,比如401,403,404,如果有具體的數字,就先用具體的數字對應頁面,如果沒有就用有前綴開頭的頁面。
顯示錯誤頁面時,頁面上能獲取到以下信息,可以讓我們看到詳細的錯誤信息:
timestamp:時間戳。
status:狀態碼。
error:錯誤提示。
exception:異常對象。
message:異常消息。
errors:JSR303數據校驗的錯誤都在這里。
在沒有模板的情況下,會去找靜態資源下的相關頁面,如果靜態資源下也沒有,就用springboot默認的錯誤頁面。如下,我添加了一個4xx.html的錯誤處理頁面,當我訪問一個不存在的路徑(404錯誤)時,就會顯示我添加的4xx.html頁面:
3.2 自定義返回的json數據
默認情況下springboot會出現自適應的錯誤顯示,當用瀏覽器訪問(接受類型為text/html)時會顯示錯誤頁面,當用postman(接受類型為application/json)會顯示錯誤json數據。不過顯示的字段都是內置固定的,如果我們想要添加自己的錯誤數據,就要自己定制了。
在springboot中,出現錯誤以后,會來到/error請求,會被BasicErrorController處理,響應出去可以獲取的數據是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)規定的方法),這里我們就可以編寫一個ErrorController的實現類【或者是編寫AbstractErrorController的子類】,放在容器中替換掉原來的ErrorController,頁面上能用的數據,或者是json返回能用的數據都是通過errorAttributes.getErrorAttributes得到。
添加自定一個ErrorAttribute,重寫errorAttributes.getErrorAttributes,返回自己的數據map:
1 package com.example.demo.component; 2 3 import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; 4 import org.springframework.stereotype.Component; 5 import org.springframework.web.context.request.WebRequest; 6 7 import java.util.Map; 8 9 @Component 10 public class MyErrorAttributes extends DefaultErrorAttributes { 11 @Override 12 public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { 13 Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace); 14 map.put("code",1); 15 map.put("msg","自定義錯誤"); 16 return map; 17 } 18 }
訪問錯誤頁面和json返回:
四、總結
不得不說,springboot真是很懂我們,把所有東西都配置好了,只要我們稍微修修補補就能很好的滿足我們的需求了,這里我們可以完全不要原始的錯誤信息,可以把錯誤信息獲取數據組裝成我們標准統一格式的錯誤信息,也可以在這里統一記錄我們的錯誤日志,也是非常的方便。