zoukankan      html  css  js  c++  java
  • FreeMarker在项目中实际运用随感

    一,FreeMarker百度百科定义

      FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

      假设在一个应用系统中需要一个HTML页面如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <html>
        <head>
            <title>Welcome!</title>
        </head>
        <body>
            <h1>Welcome Big Joe!</h1>
            <p>Our latest product:
            <a href="products/greenmouse.html">green mouse</a>!
        </body>
    </html>
      页面中的用户名(即上面的“Big Joe”)是登录这个网页的访问者的名字, 并且最新产品的数据应该来自于数据库才能随时更新。所以,不能直接在HTML页面中输入“Big Joe”、“greenmouse”及链接, 不能使用静态HTML代码。可以使用要求输出的模板来解决,模板和静态页面是相同的,只是它会包含一些FreeMarker将它们变成动态内容的指令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <html>
        <head>
            <title>Welcome!</title>
        </head>
        <body>
            <h1>Welcome ${user}!</h1>
            <p>Our latest product:
            <a href="${latestProduct.url}">${latestProduct.name}</a>!
        </body>
    </html>
      模板文件存放在Web服务器上,当有人来访问这个页面,FreeMarker就会介入执行,然后动态转换模板,用最新的数据内容替换模板中${...}的部分,之后将结果发送到访问者的Web浏览器中。访问者的Web浏览器就会接收到例如第一个HTML示例那样的内容(也就是没有FreeMarker指令的HTML代码),访问者也不会察觉到服务器端使用的FreeMarker。(存储在Web服务器端的模板文件是不会被修改的;替换也仅仅出现在Web服务器的响应中。)
    为模板准备的数据整体被称作为数据模型。数据模型是树形结构(就像硬盘上的文件夹和文件),在视觉效果上, 数据模型可以是(这只是一个形象化显示,数据模型不是文本格式,它来自于Java对象):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (root)
      |
      +- user = "Big Joe"
      |
      +- latestProduct
          |
          +- url = "products/greenmouse.html"
          |
          +- name = "green mouse"
      早期版本中,可以从数据模型中选取这些值,使用user和latestProduct.name表达式即可。类比于硬盘的树形结构,数据模型就像一个文件系统,“(root)”和latestProduct就对应着目录(文件夹),而user、url和name就是这些目录中的文件。
    总体上,模板和数据模型是FreeMarker来生成输出所必须的组成部分:模板 + 数据模型 = 输出  。

     二,项目的时序图

    三,获取模板和数据
    (一)dataurl数据获得
    1.通过nginx,数据源操作的表先搞清楚根据id获得model
    实体
    @Data
    @ToString
    @Document(collection = "cms_config")
    public class CmsConfig {
    
        @Id
        private String id;
        private String name;
        private List<CmsConfigModel> model;
    
    }

    其中的

    CmsConfigModel
    @Data
    @ToString
    public class CmsConfigModel {
        private String key;
        private String name;
        private String url;
        private Map mapValue;
        private String value;
    
    }
    api
    1 @Api("Cms配置接口管理")
    2 public interface CmsConfigControllerApi {
    3     @ApiOperation("根据id查询数据")
    4     CmsConfig getModel(String id);
    5 
    6 }

    controller

    @RestController
    @RequestMapping("/cms/config")
    public class CmsConfigController implements CmsConfigControllerApi {
    @Autowired
    CmsConfigService cmsConfigService;
    
        @Override
       @GetMapping("/getmodel/{id}")
        public CmsConfig getModel(@PathVariable("id") String id) {
            CmsConfig model = cmsConfigService.getModel(id);
            return model;
        }
    }

    repository

    1 public interface CmsConfigRepository extends MongoRepository<CmsConfig,String> {
    2 }

    2,远程调用resttemplate

    用okhttpclient

    2.1添加okhttpclient的pom.xml依赖

    2.2启动类上加上bean声明,

    @Bean
        public RestTemplate restTemplate(){
    
            return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    
    }

    2.3测试

    restTemplate.getForEntity获得
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class ResttemplateTest {
    @Autowired
        RestTemplate restTemplate;
        @Test
    public void resttemplateTest(){
            ResponseEntity<Map> forEntity = restTemplate.getForEntity("http://localhost:31001/cms/config/getmodel/5a", Map.class);
            Object body = forEntity.getBody();
    
            System.out.println(body); }
    }

    (二)模板从属于一个站点,

    @Controller
    public class TestController {
      @Autowired
        RestTemplate restTemplate;
    
    
    
        @RequestMapping("/banner")
        public String banner(Map map){
            //获取数据
            ResponseEntity<Map> responseEntity = restTemplate.getForEntity("http://localhost:31001/cms/config/getmodel/5a", Map.class);
            Map body = responseEntity.getBody();
    
            map.putAll(body);
            return "index_banner";
        }

    index_banner.ftl模板

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div class="banner-roll">
        <div class="amodel as item>
                    <div class="item" style="background-image: url(${item.value});"></div>
                </#list>
            </#if>
        <#-- <div class="item" style="background-image: url(../img/widget-bannerA.jpg);"></div>
            <div class="item" style="background-image: url(../img/widget-banner3.png);"></div>
            <div class="item" style="background-image: url(../img/widget-bannerB.jpg);"></div>
            <div class="item" style="background-image: url(../img/widget-bannerA.jpg);"></div>
            <div class="item" style="background-image: url(../img/widget-banner3.png);"></div>-->
        </div>
        <div class="indicators"></div>
    </div>
    <script type="text/javascript" src="http://www.x.com/plugins/jquery/dist/jquery.js"></script>
    <script type="text/javascript" src="http://www.x.com/plugins/bootstrap/dist/js/bootstrap.js"></script>
    <script type="text/javascript">
        var tg = $('.banner-item .item');
        var num = 0;
        for (i = 0; i < tg.length; i++) {
            $('.indicators').append('<span></span>');
            $('.indicators').find('span').eq(num).addClass('active');
        }
    
        function roll() {
            tg.eq(num).animate({
                'opacity': '1',
                'z-index': num
            }, 1000).siblings().animate({
                'opacity': '0',
                'z-index': 0
            }, 1000);
            $('.indicators').find('span').eq(num).addClass('active').siblings().removeClass('active');
            if (num >= tg.length - 1) {
                num = 0;
            } else {
                num++;
            }
        }
        $('.indicators').find('span').click(function() {
            num = $(this).index();
            roll();
        });
        var timer = setInterval(roll, 3000);
        $('.banner-item').mouseover(function() {
            clearInterval(timer)
        });
        $('.banner-item').mouseout(function() {
            timer = setInterval(roll, 3000)
        });
    </script>
    </body>
    </html>

    (三)数据+模板=页面

    四,页面文件存在GridFS中,并从GridFS中获取页面文件

    (一)GridFS简介

    1.GridFS是MongoDB规范用于存储和检索大文件,如图片,音频文件,视频文件等。这是一种文件系统用来存储文件,但数据存储于MongoDB集合中。GridFS存储文件比其文档大小16MB限制的更大能力。

    2.GridFS的划分一个文件分成块存储数据每个块在一个单独的文件,每个最大尺寸255K

    GridFS默认使用两个集合 fs.files (文件简要信息)和 fs.chunks (具体内容)存储该文件的元数据和块。

    (二)存取测试

    1.存模板

     1 @SpringBootTest
     2 @RunWith(SpringRunner.class)
     3 public class GridsTest {
     4 @Autowired
     5     private GridFsTemplate gridFsTemplate;
     6 @Autowired
     7   private GridFSBucket gridFSBucket;
     8 @Test
     9     public void saveFile() throws FileNotFoundException{
    10 
    11     FileInputStream inputStream = new FileInputStream(new File("E:\xuecheng\ce.ftl"));
    12     ObjectId store = gridFsTemplate.store(inputStream, "ourse", "");
    13     System.out.println(store);
    14 
    15 }

    2.取模板

    配置文件

    import com.mongodb.MongoClient;
    import com.mongodb.client.MongoDatabase;
    import com.mongodb.client.gridfs.GridFSBucket;
    import com.mongodb.client.gridfs.GridFSBuckets;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MongoConfig {
        @Value("${spring.data.mongodb.database}")
        String db;
    
        @Bean
        public GridFSBucket getGridFSBucket(MongoClient mongoClient){
             MongoDatabase database = mongoClient.getDatabase(db);
             GridFSBucket bucket = GridFSBuckets.create(database);
             return bucket;
        }
    }

    测试

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class GridsTest {
    @Autowired
        private GridFsTemplate gridFsTemplate;
    @Autowired
      private GridFSBucket gridFSBucket;
    @Test
        public void queryFile() throws IOException{
        GridFSFile gridFSFile = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is("5cff9c915321159f")));
        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        GridFsResource gridFsResource = new GridFsResource(gridFSFile, gridFSDownloadStream);;
        InputStream inputStream = gridFsResource.getInputStream();
        String template = IOUtils.toString(inputStream, "utf-8");
        System.out.println(template);
    
    }
    gridFsTemplate.findOne(Query.query(Criteria.where("_id").is("5cff9c915321159f")));
    HQL语句

    文件id(fileId)是唯一标识

    四,应用

    两种页面静态化选择,我们用第二种

        //基于模版文件生成静态化文件
        @Test
        public void generateHtml() throws IOException, TemplateException {
    
            //声明配置类
            Configuration configuration = new Configuration(Configuration.getVersion());
            //设置默认编码
            configuration.setDefaultEncoding("utf-8");
    
            //获取模版
            String classpath = this.getClass().getResource("/").getPath();
            configuration.setDirectoryForTemplateLoading(new File(classpath+"/templates/"));
            Template template = configuration.getTemplate("test1.ftl");
    
            //获取数据
            Map map = new HashMap();
            map.put("name","黑马程序员");
    
            //生成静态化页面
            String htmlContentString = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
    
            InputStream inputStream = IOUtils.toInputStream(htmlContentString, "utf-8");
            OutputStream outputStream = new FileOutputStream(new File("E:\xuecheng\test1.html"));
            IOUtils.copy(inputStream,outputStream);
        }
    
        //基于模版字符串生成静态化页面
        @Test
        public void generateHtmlByString() throws IOException, TemplateException {
    
            //声明配置类
            Configuration configuration = new Configuration(Configuration.getVersion());
            //设置默认编码
            configuration.setDefaultEncoding("utf-8");
    
            //模版
            StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
            String content="<!DOCTYPE html>
    " +
                    "<html lang="en">
    " +
                    "<head>
    " +
                    "    <meta charset="UTF-8">
    " +
                    "    <title>Title</title>
    " +
                    "</head>
    " +
                    "<body>
    " +
                    "        ${name}
    " +
                    "
    " +
                    "</body>
    " +
                    "</html>";
            stringTemplateLoader.putTemplate("myTemplate",content);
    
            configuration.setTemplateLoader(stringTemplateLoader);
    
            Template template = configuration.getTemplate("myTemplate");
    
            //获取数据
            Map map = new HashMap();
            map.put("name","传智播客");
    
            //生成静态化页面
            String htmlContentString = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
    
            InputStream inputStream = IOUtils.toInputStream(htmlContentString, "utf-8");
            OutputStream outputStream = new FileOutputStream(new File("E:\xuecheng\test2.html"));
            IOUtils.copy(inputStream,outputStream);
        }
      2.基于模版字符串生成静态化页面
    servcie
    /model和数据结合,生成静态化页面,根据id生成静态化页面
        public String getHtml(String pageId) {
            //获取数据
            Map model = this.getModelByPageId(pageId);
            if(model == null){
                ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAISNULL);
    
            }
            //获取模版
            String templateById = this.getTemplateById(pageId);
    if(StringUtils.isEmpty(templateById)){
        ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
    
    }
    //生成静态页面
            String pageHtml = this.generateHtml(model, templateById);
    if (pageHtml.isEmpty()){
    
        ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_HTMLISNULL);
    
    }
    return pageHtml;
        }
        //生成静态页面方法
        private String generateHtml(Map model,String templateString){
    
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDefaultEncoding("utf-8");
            StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
            stringTemplateLoader.putTemplate("myTemplate",templateString);
            configuration.setTemplateLoader(stringTemplateLoader);
            try{
                Template template = configuration.getTemplate("myTemplate");
                String pageHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
                return pageHtml;
            }
            catch (Exception e){
                e.printStackTrace();
            }
        return null;
        }
        //获取模版方法
    private String getTemplateById(String pageId) {
        CmsPage cmsPage = this.findOne(pageId);
        if(cmsPage == null ){
            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
        }
        String templateId = cmsPage.getTemplateId();
        Optional<CmsTemplate> repositoryById = cmsTemplateRepository.findById(templateId);
    if(!repositoryById.isPresent()){
        ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
    }
        CmsTemplate cmsTemplate = repositoryById.get();
        String templateFileId = cmsTemplate.getTemplateFileId();
    
        GridFSFile gridFsTemplateOne = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(templateFileId)));
        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFsTemplateOne.getObjectId());
        GridFsResource gridFsResource=new GridFsResource(gridFsTemplateOne,gridFSDownloadStream);
        try {
            InputStream inputStream = gridFsResource.getInputStream();
            String templateContent = IOUtils.toString(inputStream);
    return templateContent;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
        //获取数据
        private Map getModelByPageId(String pageId){
            CmsPage one = this.findOne(pageId);
            if (one == null) {
    
            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
            }
            String dataUrl = one.getDataUrl();
            if(StringUtils.isEmpty(dataUrl)){
                ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAISNULL);
    
            }
            ResponseEntity<Map> responseEntity = restTemplate.getForEntity(dataUrl, Map.class);
            return  responseEntity.getBody();
    
        }
     
    当一个男人不再对你啰嗦,不再缠着你,不再没事找你,对你说话也客气了,也不再气你了。那么恭喜你,你已经成功的失去了他。别嫌弃男人幼稚,那是他喜欢你,爱你。女人说男人像小孩子一样不成熟,可又有谁知道,男人在自己喜欢的女人面前才像小孩子,如果不喜欢你了,不爱你了,他比你爸还成熟。
  • 相关阅读:
    jmeter如何连接数据库
    jmeter基础之录制篇
    php解压缩
    composer基本使用
    react组件之间的参数传递
    解决VMware Workstation 不可恢复错误: (vcpu-0)
    虚拟机vmware11装Mac ox 10.8 解决windows8.1下unlocker202 vmxsmc.exe已停止工作的问题
    Photoshop学习:打开PS之前需要...
    汇编语言之启航
    Markdown语法介绍
  • 原文地址:https://www.cnblogs.com/fengtangjiang/p/11111203.html
Copyright © 2011-2022 走看看