JFinal 是基于Java 语言的极速 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。更多查看 Jfinal官网
com.jfinal.render.RenderException: freemarker.template.TemplateNotFoundException ,见图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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”
1 2 3 4 5 6 7 8 9 10 | @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路由,有很多个,我只写了测试的
1 2 3 4 5 6 | @Override public void configRoute(Routes me) { // me.add("/test", TestController.class,"/sys"); me.add("/test", TestController.class); // me.add("/test", TestController.class,"/sys/test"); } |
在看下控制器
1 2 3 4 5 6 7 8 9 | //一定要继承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 类中添加路由的方法有两个
1 2 | public Routes add(String controllerKey, Class<? extends Controller> controllerClass, String viewPath) public Routes add(String controllerKey, Class<? extends Controller> controllerClass) |
先说第一种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** 说明:这是两个类的代码块,这里写在一起了 */ //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,对应效果图⑥ */ } |
再看第二种
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** 说明:这是两个类的代码块,这里写在一起了 */ //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 为什么???
因为最终的视图路径,规则如下:
1 | 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(①处)点击查看官方说法

能力有限,如有错误,欢迎指正