• freemarker学习 (servlet + freemarker -> Struts2+freemarker -> springMVC+freemarker)


    什么是freemarker?

      freemarker类似于jsp,但不是jsp!怎么说呢?freemarker文件后缀是.ftl,它不像jsp本质是servlet,它将构建模板、解析模板、使用模板分离开来了。

      这个回答很好:源于:https://zhidao.baidu.com/question/489425455706898652.html

      运行机制就不大一样,jsp是编译成继承自servlet的class文件,运行jsp就是运行一个servlet
      而freemarker就是套模板,通过模板+内容直接生成HTML然后输出
      从开发角度来说
      freemarker 自带一套模板语言,语法实现更简单直观,而且可以通过marco宏编写控件,如果宏无法满足,freemarker也还提供了很多JAVA扩展接口。
      而JSP不管JSTL还是其他,都是靠taglib实现的,taglib的效率其实并不高,所以在复杂页面的渲染上 ,freemarker会明显高于jsp
      同时 ,freemarker也不仅仅局限于B/S应用,可以广泛应用到比如代码生成、票据打印模板等各个方面

      jsp的功能在freemarker基本上都提供了,有jsp经验的上手会比较简单

    servlet + freemarker:

      导入freemarker jar包: 

     <dependency>
                <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>2.3.23</version>
            </dependency>

    如何使用模板技术:

      

    public class TestFreemarker {
        public static void main(String[] args) throws Exception{
    
            //1、创建Freemark配置实例
            Configuration cfg = new Configuration();
            cfg.setDirectoryForTemplateLoading(new File("template"));
    
            //2、创建数据模型
            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);
    
            //3、加载模板文件
            Template template = cfg.getTemplate("scope.ftl");
    
            //4、显示生成的数据
            Writer out = new OutputStreamWriter(System.out);
            template.process(root, out);
            out.flush();
            out.close();
        }
    }

    类似我们原来的servlet中画视图的做法,freemarker进行了视图的使用模板与填充参数得到字符串操作。

      语法与使用文档:

        链接: 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>
    &lt;#nested&gt;引用标签体的内容
    <#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:

      1、项目导入strtus2jar包,freemarkerjar包

      2、将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>

      3、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>

      4、注意:

          1、Struts2标签在JSP 页面中的写法与在Freemarker模板文件中的写法不同。
    Freemarker模板文件是以<@s.tag>开始,以</@s.tag>结束
    2、Freemarker模板文件的处理,通过Web容器是无法直接处理的,因此不要让用户直接访问模板 文件。在开发过程中,我们可以将Freemarker文件直接放到Web工程的 WEB-INF目录或其子目录下(用户无法访问WEB-INF目录下文件),并在相应的struts-*.xml文件中配置type="freemarker" 来输出模板

    项目代码:链接: https://pan.baidu.com/s/1GhBSOTGcAUH9BwVfXvx5fA 提取码: ttd1 

    SpringMVC+freemarker:

      1、引入springMvc有关jar,引入freemarker有关jar

        注意spring的freemarker支持在context-support模块

      2、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("/"); 问题解决
  • 相关阅读:
    屏幕截图 从安卓模拟器中识别出屏幕文字
    srcset
    Bitwise and Bit Shift Operators 位运算 取反 补码
    text recognizer (OCR) Engine 光学字符识别
    删除目录下 某类名字的文件
    appmaptile
    登录框
    将代码设置的剪切板内容通过输入法软件粘贴入app搜索框
    面向问题的高级语言
    使用心理视觉来进行图像处理
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/10331325.html
Copyright © 2020-2023  润新知