(二期)12、开源博客项目mblog解读(二)

【课程12】freema...模板.xmind77.9KB

【课程12】hibernat...arch.xmind0.1MB

freemarker模板技术
模板技术

FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。

FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序。

对于FreeMarker而言,显示能力要比Jsp强一些,方便一些。

FreeMarker提供模板,开发人员利用后台语言提供数据,两者一结合,出现内容。

优点

1.freemark不支持写java代码,实现严格的mvc分离

2.性能非常不错

3.对jsp标签支持良好

4.内置大量常用功能,使用非常方便

5.宏定义(类似jsp标签)非常方便

6.使用表达式语言

基本语法

常用指令和宏

freemarker中使用指令时必须要在指令前面用#(如果是自定义指令用@,后面说),assign指令是用来声明变量的,注意:如果是布尔值,输出时一定要带?c,表示定义的变量是布尔值,不然会报错。

freemarker宏 macro , nested , 函数

macro可以理解为一个函数,根据输入的参数来生成结果

nested 功能是自定义marco的模板片段

在调用macro的时候可以传入自定义的模板片段

springboot集成freemarker

步骤一、导入pom文件

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

步骤二、在src/main/resource/创建一个templates文件夹,后缀为*.ftl,如新建一个index.ftl的文件。

步骤三、如果自定义标签什么的,需要定义全局配置FreemarkerConfig,引入自定义的标签。

@Component
public class FreemarkerConfig {
    @Autowired
    private Configuration configuration;
    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void setSharedVariable() throws TemplateModelException {
        configuration.setSharedVariable("author_contents", applicationContext.getBean(AuthorContentsDirective.class));
    }
}

Configuration

是一个存放应用级别(application level)公共配置信息,以及模版(Template)可使用的全局共享变量的一个对象。同时它还负责模版(Template)实例的创建以及缓存。

前端静态化

准备工作:

  • 需要静态化的页面模板
  • util工具类
  • 模板需要的参数

工具类:

import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.*;
import java.util.Map;  
  
/** 
 * 创建人: leon 
 * 创建时间: 2014年11月28日 上午10:07:51 
 * 类描述:Freemarker的工具类 
 */  
public class FreemarkerUtil {
      
    /** 
     * 通过指定的文件目录和文件名生成相应的文件 
     * @param fileDir 
     * @param fileName 
     */  
    public static Boolean printToFile(Template template,String fileDir,String fileName,Map<String,Object> root) {
        boolean done = false;  
        Writer writer = null;  
        try {  
            //判断多级目录是否存在,不存在则一级级创建  
            String[] paths = fileDir.split("\\\\");//注意:此处“\\”是错误的,必须要“\\\\”才能分割字符串  
            String dir = paths[0];  
            for (int i = 1; i < paths.length; i++) {  
                dir = dir + File.separator + paths[i];  
                File file=new File(dir.toString());  
                if (!file.exists()) {  
                    file.mkdir();  
                }  
            }  
            //创建输出流  
            File file = new File(fileDir +File.separator+ fileName);    
                 
            //设置生成的文件编码为UTF-8     
            //服务器不支持UTF-8格式HTML时候使用ANSI格式HTML文件,即系统默认编码     
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));  // 编码设置3  
            //writer = new FileWriter(fileDir +File.separator+ fileName);  
            //输出模板和数据模型都对应的文件  
            template.process(root, writer);  
            done = true;  
        } catch (IOException e) {  
            e.printStackTrace();  
        } catch (TemplateException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if(writer!=null){  
                    writer.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return done;  
    }
}  

页面模板:可以选择博客详情页作为需要静态化的模板

templates/default/channel/view.ftl

静态化过程:写了一个controller用于静态化。


@RestController
public class ToHtmlController extends BaseController {

    @Autowired
    private PostService postService;
    @Autowired
    private Configuration configuration;

    @ResponseBody
    @RequestMapping("/view/tohtml/{id}")
    public boolean toHtml(@PathVariable Long id, HttpServletRequest req) throws IOException {
        Template template = configuration.getTemplate("/default/channel/view.ftl");

        String fileName = id + ".html";
        String htmlDir = "D:/git-second/course-11-mblog/mblog/web/src/main/resources/static/html";

        PostVO view = postService.get(id);
        Map<String, Object> params = new HashMap<>();
        params.put("view", view);
        return FreemarkerUtil.printToFile(template, htmlDir, fileName, params);
    }
}

需要注意的是,由于这个模板有些数据是通过模板标签来活得数据的,所以静态化过程中不能活得,需要重写模板,还有登录状态,阅读数等问题~~

自定义标签

重要的几个类:

  • TemplateDirectiveModel:java中freemarker通过实现TemplateDirectiveModel接口,用户可以自定义标签(指令)进行任意操作,任意文本写入模板的输出。也就是说要实现自定义标签需要实现这个接口。重新execute方法。
  • TemplateDirective : 抽象类,实现TemplateDirectiveModel接口,并拓展execute的参数封装到DirectiveHandler类里面。统一页面使用的结果参数名称。
  • DirectiveHandler :模板处理中心接口中心,根据execute方法的几个参数拓展出一系列方法,提高模板定义的效率。
  • TemplateModelUtils : freemarker模板工具类。
  • ChannelDirective : 自定义的模板,需实现TemplateDirective接口,重新getName和execute方法。并在execute方法中写业务逻辑
  • FreemarkerConfig :freemarker自定义标签、函数全局配置。

1. Freemarker自定义标签需要自定义一个类,然后实现TemplateDirectiveModel,重写execute方法,完成获取参数,根据参数设置不通属性等等。

2. Freemarker自定义标签中,如果标签内什么也没有,开始标签和结束标签绝对不能再同一行,不然会报错。

自定义函数

TemplateMethodModelEx

覆盖该接口的Object exec(java.util.List arguments)方法,该方法里写的就是我们自己想要实现的效果,当使用方法表达式调用一个方法(exec)时,实际上就是在执行这个exec方法,页面中方法表达式的参数就是该方法的参数,方法的返回值就是方法表达式的返回值。

步骤一、TemplateMethodModelEx接口。

步骤二、实现exec这个方法。

步骤三、在controller中将这个实现类的对象,放入ModelAndView对象中

步骤四、在模板文件中调用这个方法

或者在FreemarkerConfig中全局配置。

hibernate search
lucene全文搜索

Lucene是一个全文搜索引擎。

Lucene不是一个完整的应用程序,而是一个能够轻松集添加搜索功能到一个应用程序中的核心代码库和API。

通过hibernate search 创建 lucene全文索引。

Hibernate Search是在apache Lucene的基础上建立的主要用于Hibernate的持久化模型的全文检索工具。像Lucene这样的检索引擎能够给我们的项目在进行检索的时候带来非常高的效率,但是它们在基本对象的检索时会有一些问题,比如不能实现检索内容跟实体的转换,Hibernate Search正是在这样的情况下发展起来的,基于对象的检索引擎,能够很方便的将检索出来的内容转换为具体的实体对象。此外Hibernate Search能够根据需要进行同步或异步的索引更新。

Hibernate Search是 hibernate 对著名的全文检索系统 Lucene 的一个集成方案,作用在于对数据表中某些内容庞大的字段(如声明为text的字段)建立全文索引,它这样通过hibernate search就可以对这些字段进行全文检索后获得相应的POJO,从而加快了对内容庞大字段进行模糊搜索的速度(sql语句中like匹配)。

Hibernate Search主要有以下功能特点:

1,功能强大,配置简单 - 配置只需要修改persistence.xml(JPA),hibernate.cfg.xml(Hibernate)

2,支持Hibernate,以及EJB3 JPA标准应用

3,集成全文搜索引擎Lucene - Lucene是Apache项目组下的一个功能强大的全文搜索引擎项目

4,可以简单透明索引查询过的数据

5,支持复杂检索 - 支持Wild Card(诸如*, ?等通配符号),多关键字,模糊查询,排序等

6,支持Clustering

7,支持直接访问Lucene API

8,对Lucene索引,API的高效管理。

原理:

Hibernate Search是给Hibernate持久化模型架构来使用的一套全文检索工具,其全文检索依赖于Lucence引擎。全文搜索引擎(lucence)会将你要查询的这个字段的词语,进行分词,直接匹配分词。

hibernate search常用注解

@Indexed

-> index 指定索引名称

@Field

-> name 指定当前属性在Lucene Document中存储的名称,默认为属性名

@NumericField

@Field的联合注解,用于Integer, Long, Float和Double属性,索引时采用字典树结构(Trie structure).

@Fields

同一个域采用不同的索引策略。需要为每个Field指定name属性(非强制).

@Analyzer

-> impl 指定具体的Analyzer实现类

-> definition 指向@AnalyzerDef标注中name属性定义的值

使用过程

步骤一、导入pom,注意:lucence版本必须和Hibernate版本对应!

<!--hibernate search orm-->
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-search-orm</artifactId>
   <version>5.6.3.Final</version>
</dependency>
<!--hibernate search dependency-->
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
</dependency>

<!--处理中文的分析器-->
<dependency>
   <groupId>org.apache.lucene</groupId>
   <artifactId>lucene-analyzers-smartcn</artifactId>
   <version>5.5.4</version>
</dependency>
<!--查询结果的高亮处理-->
<dependency>
   <groupId>org.apache.lucene</groupId>
   <artifactId>lucene-highlighter</artifactId>
   <version>5.5.4</version>
</dependency>
<!-- /end -->

步骤二、在yml文件中配置hibernate search信息

spring
  jpa:
    database: mysql
    show-sql: false
    hibernate:
        ddl-auto: update
    properties:
        hibernate.format_sql: true
        hibernate.naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        hibernate.cache.use_second_level_cache: false
        #把索引的文件保存在文件系统中
        hibernate.search.default.directory_provider: filesystem
        #指定索引保存的路径
        hibernate.search.default.indexBase: ./indexes


步骤三、索引的内容配置(通过注解方式配置实体类,可对哪些数据进行索引)

@Indexed //hibernatesearch,将该类型的对象建立索引,放到luncene中

@DocumentId//数据表的主键字段对应的属性

@Field//对该字段的生成索引

@Analyzer//引入分词器

步骤四、Hibernate Search是基于lucence的,无需手动编写lucence代码即可进行Hibernate操作,会自动创建索引、修改索引、删除索引。所以这里重启服务器,查看索引

运行原理:

1、构造LuceneQuery查询索引库

2、EntityManager 构造 FullTextEntityManager 查询数据库

3、合并EntityManager 和 LuceneQuery —– FullTextQuery 查询索引库和数据库

4、查询索引库 fullTextQuery.getResultSize(); 查询索引,去重id

5、查询数据库 fullTextQuery.getResultList(); 根据索引库返回 id ,查询数据库

项目优化方向
前端静态化
单独设置CDN
优化慢sql-explain
多数据源或分库分表

(转)mblog解读(二)的更多相关文章

  1. (转)mblog解读(一)

    (二期)11.开源博客项目mblog解读(一) [课程11]图片上传模块.xmind54.6KB [课程11]消息发...通知.xmind55.2KB [课程11]异常处理分析.xmind95.4KB ...

  2. jQuery.Callbacks 源码解读二

    一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...

  3. java多线程解读二(内存篇)

    线程的内存结构图 一.主内存与工作内存 1.Java内存模型的主要目标是定义程序中各个变量的访问规则.此处的变量与Java编程时所说的变量不一样,指包括了实例字段.静态字段和构成数组对象的元素,但是不 ...

  4. mybatis源码解读(二)——构建Configuration对象

    Configuration 对象保存了所有mybatis的配置信息,主要包括: ①. mybatis-configuration.xml 基础配置文件 ②. mapper.xml 映射器配置文件 1. ...

  5. java8完全解读二

    继续着上次的java完全解读一 继续着上次的java完全解读一1.强大的Stream API1.1什么是Stream1.2 Stream操作的三大步骤1.2.1 创建Stream1.2.2 Strea ...

  6. (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

    转自:http://www.baiyuxiong.com/?p=886 ---------------------------------------------------------------- ...

  7. cJONS序列化工具解读二(数据解析)

    cJSON数据解析 关于数据解析部分,其实这个解析就是个自动机,通过递归或者解析栈进行实现数据的解析 /* Utility to jump whitespace and cr/lf *///用于跳过a ...

  8. NSObject头文件解析 / 消息机制 / Runtime解读 (二)

    本章接着NSObject头文件解析 / 消息机制 / Runtime解读(一)写 给类添加属性: BOOL class_addProperty(Class cls, const char *name, ...

  9. Nginx 小入门记录 之 Nginx 配置文件解读(二)

    上一小节主要是记录一些环境准备和Nginx的安装,接下来对Nginx基本配置进行记录. 查看配置文件安装记录 可以通过以下Linux命令进行查看: rpm -ql nginx rpm 是liunx的包 ...

随机推荐

  1. multiprocessing 源码解析 更新中......

    一.参考链接 1.源码包下载·链接:   https://pypi.org/search/?q=multiprocessing+ 2.源码包 链接:https://pan.baidu.com/s/1j ...

  2. git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法

    git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法提交代码流程:1.先提交代码到自己分支上2.切换到devlop拉取代码合并到当前分支3.合并后有变动的推送到自己 ...

  3. golang学习笔记19 用Golang实现以太坊代币转账

    golang学习笔记19 用Golang实现以太坊代币转账 在以太坊区块链中,我们称代币为Token,是以太坊区块链中每个人都可以任意发行的数字资产.并且它必须是遵循erc20标准的,至于erc20标 ...

  4. notepad 正则表达式 复制 文本

  5. Qt 之 pro 配置详解

    原文地址:https://blog.csdn.net/liang19890820/article/details/51774724 简述 使用Qt的时候,我们经常会对pro进行一系列繁琐的配置,为方便 ...

  6. 多进程wait、僵尸进程、孤儿进程、prctl

    1.概念 1.孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,从而保证每个进程都会有一个父进程.而Init进程会自 ...

  7. [转载]js 获取ASP RadioButtonList 选中的值

    var planList=document.all ('rblPlanType');    for(var i=1;i<planList.length;i++)    {     if(plan ...

  8. Django框架----中间件

    我们已经会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰器,这样是不是稍微有点 ...

  9. 自写Jquery插件 Tab

    原创文章,转载请注明出处,谢谢!https://www.cnblogs.com/GaoAnLee/p/9067017.html 每每看到别人写的Jquery插件,自己也试着学习尝试,终有结果,废话不多 ...

  10. django 生成动态的PDF文件

    需要依赖库. WeasyPrint,它是一个Python库可以生成PDF文件从HTML模板中.安装WeasyPrint pip install WeasyPrint 创建一个PDF模板(templat ...