在使用Freemarker模板引擎时,可能会遇到各种错误和问题,下面将详细分析几种常见的Freemarker报错及其解决方法,并提供一些常见问题的FAQs。
一、无法找到对应的模板路径
1. 报错原因:
请求到达服务后端后,Controller返回了对应的视图名称,但DispatcherServlet却爆出404 NOT_FOUND错误,显示无法找到对应的模板页面,这个报错通常是由于SpringBoot版本导致的,高版本的SpringBoot不会自动注入SpringMVC相关的配置,导致无法找到对应的模板资源路径。
2. 解决方法:
如果使用2.3.8.RELEASE或更高版本的SpringBoot,需要在配置类中加上@EnableWebMvc
注解,这样会自动配置SpringMVC相关的配置。
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @EnableWebMvc public class WebConfig { // 其他配置 }
二、无法解析Freemarker模板
1. 报错信息:
在多模块开发环境中,Freemarker视图解析的路径是另一个模块的路径,而需要解析的Freemarker模板文件则在当前模块,这会导致无法解析正确的视图。
2. 报错原因:
Freemarker视图解析的路径不正确,导致无法找到模板文件。
3. 解决方法:
配置Freemarker的preferFileSystemAccess
属性为false
,该属性默认为true
,通过设置该属性可以避免文件系统访问的问题。
freemarker: charset: UTF8 templateloaderpath: classpath:/templates/ contenttype: text/html suffix: .ftlh preferfilesystemaccess: false
三、变量未赋值导致异常
1. 报错原因:
在Freemarker模板中使用未赋值的变量会抛出异常。${userName}
如果userName
没有赋值,则会引发错误。
2. 解决方法:
可以通过以下几种方式处理未赋值的变量:
方法一:在页面上使用${xxx?if_exists}
来处理空值的情况。
方法二:在类路径下加入freemarker.properties
文件,配置classic_compatible=true
。
方法三:通过代码配置classic_compatible
属性为true
。
方法四:在FTL文件中引入<!#setting classic_compatible=true>
。
classic_compatible=true
四、统一异常处理
1. 实现方式:
为了处理Freemarker模板中的异常,可以自定义一个异常处理器,并在Spring Boot中实现ErrorController接口。
2. 示例代码:
package com.example.exception; import freemarker.core.Environment; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import java.io.IOException; import java.io.Writer; @Controller @RequestMapping(value = "error") public class CustomErrorController implements ErrorController, TemplateExceptionHandler { private static final Logger log = LoggerFactory.getLogger(CustomErrorController.class); @Override public String getErrorPath() { return "error40x"; // 自定义的错误页面名称 } @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(" "); 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); } } }
五、Freemarker模板后缀名问题
1. 报错原因:
在某些情况下,Freemarker模板的后缀名可能不匹配,导致无法正确加载模板。
2. 解决方法:
确保模板文件的后缀名与配置中的后缀名一致,如果配置中指定的后缀名是.ftlh
,则模板文件的后缀名也应为.ftlh
。
freemarker: suffix: .ftlh
六、循环引用导致500错误
1. 报错原因:
在SpringBoot项目中,如果视图名称生成未指定,可能会导致循环引用,从而引发500错误。
2. 解决方法:
确保ViewResolver的配置正确,避免循环引用,可以在配置文件中明确指定视图名称。
七、Freemarker异常类型及处理方法
1. 异常类型:
TemplateNotFoundException:模板文件未找到。
InvalidReferenceException:非法引用异常。
ParseException:解析异常。
TemplateException:模板执行期间的其他问题。
2. 处理方法:
可以使用TemplateExceptionHandler
对象来处理这些异常。
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());
八、FAQs
Q1: Freemarker模板中如何处理未赋值的变量?
A1: 可以通过以下几种方式处理未赋值的变量:
在页面上使用${xxx?if_exists}
。
在类路径下加入freemarker.properties
文件,配置classic_compatible=true
。
通过代码配置classic_compatible
属性为true
。
在FTL文件中引入<!#setting classic_compatible=true>
。
Q2: Freemarker模板找不到对应的模板路径怎么办?
A2: 如果使用高版本的SpringBoot(如2.3.8.RELEASE),需要在配置类中加上@EnableWebMvc
注解,这样可以自动配置SpringMVC相关的配置,解决模板路径找不到的问题。