spring boot freemarker 500異常跳轉自定義錯誤頁


項目環境

  使用idea + maven + springboot 搭建的項目。

需求

  跳轉自定義錯誤頁。三方系統鏈接。

問題

  遇到問題是spring 定義的全局異常捕捉不到 freemarker 模板渲染時候的異常。

       1)嘗試AOP的異常通知進行 捕獲失敗( @ControllerAdvice+ @ExceptionHandler(Exception.class)

       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);
        }
    }
}

 3)或者使用 繼承BasicErrorController來實現

/**
 * 覆蓋spring boot默認的異常處理類 繼承BasicErrorController
 */
@Controller
public class CustomErrorController extends BasicErrorController {
    public CustomErrorController(ServerProperties serverProperties) {
        super(new DefaultErrorAttributes(), serverProperties.getError());
    }
    //通過瀏覽器訪問的url 如果發生異常全部會被瀏覽並跳轉到list.html頁面
    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        //請求的狀態
        HttpStatus status = getStatus(request);
        response.setStatus(getStatus(request).value());

        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        //指定自定義的視圖
        return(modelAndView == null ? new ModelAndView("list", model) : modelAndView);
    }
    //通過http client訪問的接口如果發生異常會調用這個方法
    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);

        //輸出自定義的Json格式
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("status", false);
        map.put("msg", body.get("message"));

        return new ResponseEntity<Map<String, Object>>(map, 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

   https://juejin.im/post/6844904135259602952

   https://blog.csdn.net/lh87270202/article/details/79925951

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM