spring boot freemarker 500異常跳轉自定義錯誤頁
阿新 • • 發佈:2020-10-12
專案環境
使用idea + maven + springboot 搭建的專案。
需求
跳轉自定義錯誤頁。三方系統連結。
問題
遇到問題是spring 定義的全域性異常捕捉不到 freemarker 模板渲染時候的異常。
1)嘗試AOP的異常通知進行 捕獲失敗( @ControllerAdvice+
)2)嘗試繼承HandlerExceptionResolver 捕獲失敗
解決方案
一、使用web.xml的方式,配置error-page 節點
1)配置檔案增加自定義的freemarker 錯誤處理類
spring: freemarker: settings: template_exception_handler: xxx.web.exception.FreemarkerExceptionHandler
類定義如下:
class MyTemplateExceptionHandler implements TemplateExceptionHandler { public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out) throws TemplateException { try { out.write("[ERROR: " + te.getMessage() + "]"); }catch (IOException e) { throw new TemplateException("Failed to print error message. Cause: " + e, env); } } }
2)然後再web.xml配置捕獲異常跳轉到對應的url,配置如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/500.jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/error.jsp</location> </error-page> <!-- 優先順序: 頁面中配置<%@page contentType="text/html; charset=UTF-8" errorPage="/2.jsp"%> > exception-type配置的頁面 > error-code配置的頁面 --> </web-app>
二、使用Spring Boot預設的對映處理
1)同 第一種處理方式,略
2)定義捕捉 /error 路徑的ErrorController
Spring Boot提供了一個預設的對映:/error
,當處理中丟擲異常之後,會轉到該請求中處理,並且該請求有一個全域性的錯誤頁面用來展示異常內容。
import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping(value = "error") public class CustomErrorController implements ErrorController { @Override public String getErrorPath() { return "error40x";//這是個我自己寫的404的頁面的fileName,在template根目錄下 } @RequestMapping public String error() { return getErrorPath(); } }
或者
@Controller @RequestMapping({"${server.error.path:${error.path:/error}}"}) public class BasicErrorController extends AbstractErrorController { /** * 錯誤的頁面響應 */ @RequestMapping(produces = {"text/html"}) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = this.getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); // 得到一個modelAndView物件 ModelAndView modelAndView = this.resolveErrorView(request, response, status, model); return modelAndView != null ? modelAndView : new ModelAndView("error", model); } /** * 錯誤的json響應 */ @RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = this.getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity(status); } else { Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL)); return new ResponseEntity(body, status); } } }
三、模板引擎 預設有錯誤頁的配置
1)同 第一種處理方式,略
2)在templates建立/error資料夾並新增錯誤的狀態碼對應的.html檔案
專案中使用的了模板引擎,如:thymeleaf 、freemarker等做為頁面的渲染時。在templates建立/error資料夾並新增錯誤的狀態碼對應的.html檔案,如下圖:
3)檔案中做二次跳轉
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> window.location.href="//xxxx/xxx"; </script> </body> </html>
參考
https://juejin.im/post/6844904135259602952
https://www.codetd.com/article/3038444