什么是freemarker?html
freemarker相似于jsp,但不是jsp!怎么说呢?freemarker文件后缀是.ftl,它不像jsp本质是servlet,它将构建模板、解析模板、使用模板分离开来了。java
这个回答很好:源于:https://zhidao.baidu.com/question/489425455706898652.htmlweb
运行机制就不大同样,jsp是编译成继承自servlet的class文件,运行jsp就是运行一个servlet
而freemarker就是套模板,经过模板+内容直接生成HTML而后输出
从开发角度来讲
freemarker 自带一套模板语言,语法实现更简单直观,并且能够经过marco宏编写控件,若是宏没法知足,freemarker也还提供了不少JAVA扩展接口。
而JSP无论JSTL仍是其余,都是靠taglib实现的,taglib的效率其实并不高,因此在复杂页面的渲染上 ,freemarker会明显高于jsp
同时 ,freemarker也不只仅局限于B/S应用,能够普遍应用到好比代码生成、票据打印模板等各个方面spring
jsp的功能在freemarker基本上都提供了,有jsp经验的上手会比较简单缓存
servlet + freemarker:服务器
导入freemarker jar包: mvc
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
如何使用模板技术:app
public class TestFreemarker { public static void main(String[] args) throws Exception{ //一、建立Freemark配置实例 Configuration cfg = new Configuration(); cfg.setDirectoryForTemplateLoading(new File("template")); //二、建立数据模型 Map root = new HashMap(); root.put("user", "老高"); root.put("random", new Random().nextInt(100)); List<Address> addressList = new ArrayList<Address>(); addressList.add(new Address("中国", "北京")); addressList.add(new Address("法国", "巴黎")); root.put("addressList", addressList); //三、加载模板文件 Template template = cfg.getTemplate("scope.ftl"); //四、显示生成的数据 Writer out = new OutputStreamWriter(System.out); template.process(root, out); out.flush(); out.close(); } }
相似咱们原来的servlet中画视图的作法,freemarker进行了视图的使用模板与填充参数获得字符串操做。dom
语法与使用文档:jsp
连接: https://pan.baidu.com/s/1jbHpy7QIBjBwjppxXfrZWw 提取码: 3d7v
输出if else 和遍历集合例子:
<#if user=="老高">你是老师</#if>
<#if random gte 18>
成年
<#else>
未成年
</#if>
<#if random gte 90>
优秀
<#elseif random gte 80>
良好
<#elseif random gte 60>
及格
<#else>
不及格
</#if>
<#list addressList as address>
${address_index}->${address.country}->${address.city}
</#list>
输出字符串:
你好,${user},今天你的精神不错!
include:
<#include "included.text"/>
宏指令(相似函数):
<#macro m1>
<b>测试宏指令</b>
</#macro>
<#macro add a b>
带参的宏add: ${a + b}
</#macro>
<#macro welcome>
<#nested>引用标签体的内容
<#nested>
</#macro>
使用前面定义的函数:
<@m1/>
<@add 1, 2/>
<@welcome>
欢迎guodaxa!
</@welcome>
当引入了2个ftl有一样的函数或者变量时,scope:
a.ftl
<#macro copyRight date>
<p>Copyright (C) ${date} 北京尚学堂.</p>
</#macro>
<#-- assign指令是定义变量的意思 -->
<#assign mail="1580909730@qq.com">
b.ftl
<#macro copyRight date>
<p>Copyright (C) ${date} 北京尚学堂1.</p>
</#macro>
<#-- assign指令是定义变量的意思 -->
<#assign mail="3291984010@qq.com">
scope
<#import "a.ftl" as a>
<#import "b.ftl" as b>
<@a.copyRight "2018-12-24"></@a.copyRight>
<@b.copyRight "2018-12-24"></@b.copyRight>
${a.mail}
${b.mail}
<#assign mail = "13700215420@11.com" in a>
${a.mail}
项目代码:
连接: https://pan.baidu.com/s/1_v3ymqHAYMnxnIHQleUBxQ 提取码: ytuk
struts2整合freemarker:
一、项目导入strtus2jar包,freemarkerjar包
二、将freemarker的配置加到web.xml:
<servlet> <servlet-name>freemarker</servlet-name> <servlet-class> freemarker.ext.servlet.FreemarkerServlet </servlet-class> <!--下面的配置freemarke的ftl文件的位置 --> <init-param> <param-name>TemplatePath</param-name> <param-value>/WEB-INF/template</param-value> </init-param> <!-- 是否和服务器(tommcat)一块儿启动。--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>freemarker</servlet-name> <url-pattern>*.ftl</url-pattern> </servlet-mapping>
三、struts.xml中的result中的type设置成为freemarker:
<action name="userAction" class="com.zhen.struts2freemarker.action.UserAction"> <result name="success" type="freemarker">/WEB-INF/template/user_show.ftl</result> </action>
四、注意:
一、Struts2标签在JSP 页面中的写法与在Freemarker模板文件中的写法不一样。
Freemarker模板文件是以<@s.tag>开始,以</@s.tag>结束
二、Freemarker模板文件的处理,经过Web容器是没法直接处理的,所以不要让用户直接访问模板 文件。在开发过程当中,咱们能够将Freemarker文件直接放到Web工程的 WEB-INF目录或其子目录下(用户没法访问WEB-INF目录下文件),并在相应的struts-*.xml文件中配置type="freemarker" 来输出模板
项目代码:连接: https://pan.baidu.com/s/1GhBSOTGcAUH9BwVfXvx5fA 提取码: ttd1
SpringMVC+freemarker:
一、引入springMvc有关jar,引入freemarker有关jar
注意spring的freemarker支持在context-support模块
二、springMvc配置中自定义视图解析器,定义freemarker配置Bean
@Bean public FreeMarkerConfigurer freeMarkerConfigurer(){ FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); freeMarkerConfigurer.setDefaultEncoding("UTF-8"); freeMarkerConfigurer.setTemplateLoaderPath("/"); return freeMarkerConfigurer; } @Override public void configureViewResolvers(ViewResolverRegistry registry) { //spring4 默认不是freemarker,而是Thymeleaf FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver(); freeMarkerViewResolver.setPrefix("/WEB-INF/view"); freeMarkerViewResolver.setSuffix(".ftl"); freeMarkerViewResolver.setCache(false);//cache最好配置为false,不然再次去缓存若是与request有关则gg //这行必定要配置,否则容易中文乱码,默认的charset是ISO-8859-1 freeMarkerViewResolver.setContentType("text/html;charset=UTF-8"); registry.viewResolver(freeMarkerViewResolver); registry.freeMarker(); }
项目代码:连接: https://pan.baidu.com/s/19MSg7kq5QSZEy8PaaMv5TA 提取码: x7rn
springMvc+ freemarker时遇到的问题以及解决:
1、java.lang.ClassNotFoundException: org.springframework.ui.freemarker.FreeMarkerConfigurationFactory 首先怀疑是freemarker少了什么支持包 freemarker版本更换试试无效 打开freemarker包源文件,没发现对应支持spring的类与包,则判断支持类由spring提供,则依次打开spring-webmvc、web、context,发现只有context里面有ui这个文件夹,且里面没有freemarker文件夹,则知道是缺乏了context-support这个补充包 2、org.springframework.beans.factory.BeanInitializationException: In addition to a FreeMarker view resolver there must also be a single FreeMarkerConfig bean in this web application context (or its parent): FreeMarkerConfigurer is the usual implementation. This bean may be given any name. at org.springframework.web.servlet.config.annotation.ViewResolverRegistry.freeMarker(ViewResolverRegistry.java:183) 这个首先本身理解: 觉得是freemarker解析器没给名字,因而瞎setViewName了一下,无效,记得mvc的setViewName是设置一些默认的页面连接 把错误翻译一下: 是freemarker的解析器必须须要一个freemarker的配置器,配置器的Bean我没有提供,由于freemarker不是mvc的默认支持部分,因此配置默认没有 补充一下freemarker配置便可: @Bean public FreeMarkerConfigurer freeMarkerConfigurer(){ FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); freeMarkerConfigurer.setDefaultEncoding("UTF-8"); return freeMarkerConfigurer; } 3、No mapping found for HTTP request with URI [/springMVC_freemarker/base/testFreemarker] in DispatcherServlet with name 'servletDispatcher' 初步怀疑是springmvc没扫描到controller 解决方案: @ComponentScan("com.zhen.springmvc_freemarker") 4、Servlet.service() for servlet [servletDispatcher] in context with path [/springMVC_freemarker] threw exception [Could not resolve view with name 'test_freemarker' in servlet with name 'servletDispatcher'] with root cause javax.servlet.ServletException: Could not resolve view with name 'test_freemarker' in servlet with name 'servletDispatcher' at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1237) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 初步怀疑是配置的解析器的先后缀无效 往return地址的地方写全依旧无效 怀疑是解析器配置得有问题,没有将对应文件当成freemarker处理,则增长freemarkerConfigurer的baseTemplatePath解决 freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/view"); 5、freemarker出现中文乱码 1、是不是对应的html里面没有设置 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 加上这句,没啥用 2、百度得知freemarkerViewResource还要配置一下contentType设置下response的类型和编码,因而增长: registry.freeMarker()获得的对象没有设置contentType方法,所以自定义进去,改成: @Override public void configureViewResolvers(ViewResolverRegistry registry) { //spring4 默认不是freemarker,而是Thymeleaf FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver(); freeMarkerViewResolver.setPrefix("/WEB-INF/view"); freeMarkerViewResolver.setSuffix(".ftl"); freeMarkerViewResolver.setCache(false);//cache最好配置为false,不然再次去缓存若是与request有关则gg //这行必定要配置,否则容易中文乱码,默认的charset是ISO-8859-1 freeMarkerViewResolver.setContentType("text/html;charset=UTF-8"); registry.viewResolver(freeMarkerViewResolver); } 而后一直报错找不到视图:test_freemarker 怀疑是解析器没有执行,没有进行封装view,因而解析器解析方法打断点,发现成功封装了view,那么为何找不到视图呢? 断点freemarker找视图的方法,发现那里传入我认为的正确的视图url找不到,检查class编译后文件感受还没错 回退到乱码前配置,断点看下找视图的地方,发现传入的url不是/WEB-INF/view/test_freemarker.ftl而是test_freemarker.ftl,发现contentType中的编码为iso-8859-1 回到个人配置地方,认真一看: registry.freeMarker(); //这样配置的视图解析器 @Bean public FreeMarkerConfigurer freeMarkerConfigurer(){ FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); freeMarkerConfigurer.setDefaultEncoding("UTF-8"); freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/view"); return freeMarkerConfigurer; } 原来freemarker configure中设置的模板基础路径是/WEB-INF/view,因此我传入/WEB-INF/view/test_freemarker.ftl找不到,因而更改成:freeMarkerConfigurer.setTemplateLoaderPath("/"); 问题解决