JFinal 是基于Java 语言的极速 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。更多查看 Jfinal官网
com.jfinal.render.RenderException: freemarker.template.TemplateNotFoundException ,见图
2020-05-20 16:02:45
[ERROR]-[Thread: http-apr-80-exec-2]-[com.jfinal.core.ActionHandler.handle()]: /test/test
com.jfinal.render.RenderException: freemarker.template.TemplateNotFoundException: Template not found for name "/test.html".
The name was interpreted by this TemplateLoader: WebappTemplateLoader(subdirPath="/", servletContext={contextPath="", displayName=null}).
at com.jfinal.render.FreeMarkerRender.render(FreeMarkerRender.java:147)
at com.jfinal.core.ActionHandler.handle(ActionHandler.java:97)
at com.jfinal.ext.handler.ContextPathHandler.handle(ContextPathHandler.java:47)
at com.yoncent.handler.SessionHandler.handle(SessionHandler.java:96)
at com.yoncent.handler.FrontHandler.handle(FrontHandler.java:55)
at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:72)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:165)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1201)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:654)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2532)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2521)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: freemarker.template.TemplateNotFoundException: Template not found for name "/test.html".
The name was interpreted by this TemplateLoader: WebappTemplateLoader(subdirPath="/", servletContext={contextPath="", displayName=null}).
at freemarker.template.Configuration.getTemplate(Configuration.java:2797)
at freemarker.template.Configuration.getTemplate(Configuration.java:2599)
at com.jfinal.render.FreeMarkerRender.render(FreeMarkerRender.java:143)
... 23 more
报这个异常一般来说两种情况
①文件找不到(大多数是路径写的有问题)
②文件不存在或没有(少见)
很多博客说的解决办法是需要导入freemarker的jar包(不排除这种情况,如果你的项目是之前没有用这个,可能是;如果是接手的项目,人家之前已经有做好的功能,那就不是jar包的问题)
不是jar的问题或者不确定,看完这篇文章,你可能就明白了
首先配置configConstant(…)——Jfinal常量值,这里只关心baseViewPath,我的是“/WEB-INF/page”
@Override
public void configConstant(Constants me) {
PropKit.use("../config/druid.properties");
me.setMaxPostSize(204857600);
//配置 baseViewPath
me.setBaseViewPath("/WEB-INF/page");
me.setError404View("/404.html");
me.setError500View("/500.html");
me.setDevMode(PropKit.getBoolean("devMode", false));
}
接下来是配置configRoute(…)——Jfinal路由,有很多个,我只写了测试的
@Override
public void configRoute(Routes me) {
// me.add("/test", TestController.class,"/sys");
me.add("/test", TestController.class);
// me.add("/test", TestController.class,"/sys/test");
}
在看下控制器
//一定要继承Controller这个类
public class TestController extends Controller {
public void test() {
System.out.println("进入 TestController 中的test方法");
// render("../test.html");
// render("test.html");
render("/test.html");
}
}
再看下目录结构,对于非maven项目,存放资源的文件夹一般是WebRoot或者WebContent
配置路由Routes 类中添加路由的方法有两个
public Routes add(String controllerKey, Class<? extends Controller> controllerClass, String viewPath)
public Routes add(String controllerKey, Class<? extends Controller> controllerClass)
先说第一种方法
/**
说明:这是两个类的代码块,这里写在一起了
*/
//config类
@Override
public void configRoute1(Routes me) {
//一、写成下面这样,对应的test文件夹是 web-inf/page/test
me.add("/test", TestController.class,"/test");
//二、写成下面这样,对应的test文件夹是 web-inf/page/sys/test
me.add("/test", TestController.class,"/sys/test");
}
//controller类
public void test() {
//写一行太少了,加个打印语句吧
System.out.println("进入 TestController 中的test方法");
render("test.html");
/**
configRoute1()写的是第一种,render()不变,跳转的页面是web-inf/page/test/test.html,对应效果图⑤
configRoute1()写的是第二种,render()不变,跳转的页面是web-inf/page/sys/test/test.html,对应效果图⑥
*/
}
再看第二种
/**
说明:这是两个类的代码块,这里写在一起了
*/
//config类
@Override
public void configRoute1(Routes me) {
me.add("/test", TestController.class);
}
//controller类
public void test() {
//写一行太少了,加个打印语句吧
System.out.println("进入 TestController 中的test方法");
render("test.html");
}
这样写就会报错 com.jfinal.render.RenderException:freemarker.template.TemplateNotFoundException 为什么???
因为最终的视图路径,规则如下:
finalView = baseViewPath + viewPath + view
baseViewPath和view已经设置,viewPath咱们没有设置,理论上没有问题,但是,当viewPath未指定时默认值为controllerKey(第一个参数,靠它找对应的Controller的),而controllerkey可视为一个文件夹(我们忽略了这个文件夹,把test.html直接放在了page文件夹下面,也就是③处的test.html),返回的finalView找不到这个文件夹(③处的test文件夹),就会报错,解决办法有两个:
第一种、加上这个文件夹,就没有问题了
第二种、不加这个文件夹(③处的test.html还是在page文件夹下),把Controller类中的render(“test.html”)改成render("…/test.html"),…/表示上级(父级),这样就没问题了
注意:当view以 “/” 字符打头时表示绝对路径,baseViewPath 与 viewPath 将被忽略。
解释下:拿我测试来说,当Controller类中的render("/test.html")写成了这样子,前面的baseViewPath (我写的是WEB-INF/page)和controllerkey("/test")都是无效的,那最终的finalView 就是WebRoot(有的项目是WebContent)文件夹下的test.html(①处)点击查看官方说法
能力有限,如有错误,欢迎指正