文章是根據江南一點雨(鬆哥)的視頻進行總結javascript
江南一點雨博客html
一般狀況下,咱們都須要對本身定義的異常進行相應的處理。捕獲指定的異常方式以下:前端
@ControllerAdvice public class ExceptionHandlers { // 捕獲自定義異常類進行處理 @ExceptionHandler(CustomException.class) public ModelAndView handler(CustomException e) { ModelAndView modelAndView = new ModelAndView("customException"); //自定義異常錯誤頁面 modelAndView.addObject("msg", e.getMessage()); // ... return modelAndView; } }
若服務器拋出404錯誤碼(頁面找不到)時,一般會返回以下頁面:
java
而咱們須要指定在服務器拋出相應的錯誤碼時,跳轉到指定的動態或靜態頁面。web
參考默認的視圖解析器org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver
源碼,取出部分代碼片斷以下:spring
public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered { private static final Map<Series, String> SERIES_VIEWS; // 存放不一樣錯誤碼對應的視圖 // 添加默認的視圖 static { Map<Series, String> views = new EnumMap<>(Series.class); views.put(Series.CLIENT_ERROR, "4xx"); views.put(Series.SERVER_ERROR, "5xx"); SERIES_VIEWS = Collections.unmodifiableMap(views); } ... // 開始解析錯誤視圖 @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { // status.value() 獲得的是錯誤碼 // 尋找錯誤碼指定的頁面,如404就找名爲404的頁面 ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); // 若找不到錯誤碼指定的頁面,則400,401,403,404...都會去找4xx的頁面 if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } // 若modelAndView仍是null,那麼就返回上面的那個圖片了 return modelAndView; } private ModelAndView resolve(String viewName, Map<String, Object> model) { String errorViewName = "error/" + viewName; //首先去動態資源中查看是否存在對應的頁面 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext); if (provider != null) { return new ModelAndView(errorViewName, model); } //若動態資源中找不到則到靜態資源中尋找對應的頁面 return resolveResource(errorViewName, model); } //獲取靜態頁面資源 private ModelAndView resolveResource(String viewName, Map<String, Object> model) { // 遍歷靜態資源,查找是否有對應的頁面 for (String location : this.resourceProperties.getStaticLocations()) { try { Resource resource = this.applicationContext.getResource(location); resource = resource.createRelative(viewName + ".html"); if (resource.exists()) { return new ModelAndView(new HtmlResourceView(resource), model); } } catch (Exception ex) { } } return null; } ... }
1.首先會去找指定錯誤碼的頁面,若指定頁面找不到則找4xx、5xx頁面,(400、401...都會找4xx)
2.先到動態資源下的error目錄尋找,再到靜態資源中的error目錄尋找
後端
若是爲動態資源的頁面,返回的ModelAttribute能夠查看org.springframework.boot.web.servlet.error.DefaultErrorAttributes
, 返回的數據以下:跨域
timestamp
status
error
message
...服務器
thymeleaf
下頁面使用以下:app
<table> <tr> <td th:text="${status}"></td> </tr> <tr> <td th:text="${message}"></td> </tr> </table>
若須要擴展,則繼承DefaultErrorAttributes
,對擴展類加@Component
註釋:
@Component public class CustomErrorAttribute extends DefaultErrorAttributes { // 擴展 }
在先後端分離進行開發的狀況下,通常都須要設置跨域訪問,springBoot提供CORS
跨域設置以下:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") //全部前綴 .allowedOrigins("http://localhost:8081") //跨域地址(前端地址) .allowedHeaders("*") //容許全部請求頭 .allowedMethods("*") //容許經過全部方法 .maxAge(30 * 1000); //探測請求的有效期 } }
攔截器能夠攔截request
請求,若自定義權限認證的功能,就可使用攔截器去進行實現。
public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return false; } public void postHandle ... public void afterCompletion ... }
preHandler
執行方法前調用,postHandler
在返回視圖前調用,afterCompletion
在方法執行完後調用。
添加攔截器到配置中,重寫addInterceptors
方法
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor()) .addPathPatterns("/**"); //攔截全部路徑 } @Bean MyInterceptor myInterceptor() { return new MyInterceptor(); } }
首先自定義的Servelt繼承javax.servlet.http.HttpServlet
;使用@WebServlet
進行url映射
@WebServlet(urlPatterns = "/myservlet") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doget"); } }
在啓動類xxxApplication
對自定義的Servlet的目錄進行掃描
@ServletComponentScan(basePackages = "org.java.servlet")
這就能夠成功訪問到啦!localhost:8080/myservlet
擴展(怕忘記了,記一下):
request
監聽實現接口javax.servlet.ServletRequestListener
, 而後對request
監聽類使用javax.servlet.annotation.WebListener
註解;
request
攔截器實現接口javax.servlet.Filter
,而後對攔截器使用javax.servlet.annotation.WebFilter
註解,如:
@WebListener public class MyRequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) {System.out.println("requestDestroyed");} @Override public void requestInitialized(ServletRequestEvent sre) {System.out.println("requestInitialized");} } @WebFilter(urlPatterns = "/*") //對全部目錄進行攔截 public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("doFilter"); chain.doFilter(request,response); } }
上述的監聽器和攔截器必定要在@ServletComponentScan
的掃描目錄下或子目錄。
若文章有錯誤或疑問,可在下方評論,Thanks♪(・ω・)ノ。