1. 程式人生 > >實戰分析:Spring boot &&Freemarker統一異常處理FreeMarker template error

實戰分析:Spring boot &&Freemarker統一異常處理FreeMarker template error

在Freemarker頁面中如果使用${userName},

並且userName為空,那麼Freemarker頁面就會崩掉 需要設定預設值${userName!}來避免物件為空的錯誤。

同理 ${user.userName}也應該寫成這樣${(user.userName)!""}

現在有一個需求,就是萬一我用了${userName},但是我又不想頁面崩掉,怎麼辦呢?

文中使用的是配置springMVC-servlet.xml的方式

在Spring boot中呢,就properties或者yml檔案中新增

spring.freemarker.settings.template_exception_handler=com.***.FreemarkerExceptionHandler

指明一下,這類異常哪個類來處理一下

然後類的內容就是

package com.***.exception;

import freemarker.core.Environment;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.io.IOException;
import java.io.Writer;

public class FreemarkerExceptionHandler implements TemplateExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(FreemarkerExceptionHandler.class);
    @Override
    public void handleTemplateException(TemplateException te, Environment env, Writer out) throws TemplateException {
	    	log.warn("[Freemarker Error: " + te.getMessage() + "]");
	        String missingVariable = "undefined";
	        try {
	            String[] tmp = te.getMessageWithoutStackTop().split("\n");
	            if (tmp.length > 1)
	                tmp = tmp[1].split(" ");
	            if (tmp.length > 1)
	                missingVariable = tmp[1];
	            out.write("");
	            log.error("[出錯了,請聯絡網站管理員]", te);
	        } catch (IOException e) {
	            throw new TemplateException(
	                    "Failed to print error message. Cause: " + e, env);
	        }

    }
}

到這裡,只能說丟擲了異常,但是該報錯還是報錯,只能說在前臺渲染的過程中,這個錯誤可以攔截到了

然後該處理的地步:

Spring Boot提供了一個預設的對映:/error,當處理中丟擲異常之後,會轉到該請求中處理,並且該請求有一個全域性的錯誤頁面

用來展示異常內容。

畫重點--->>>>>該請求有一個全域性的錯誤頁面

所以我們要動手腳,就要從這個路徑呼叫的類下手

我們需要實現ErrorController介面,重寫handleError方法。

所以你的自定義統一異常處理類的結構就是 

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

}