(转)mblog解读(二)

(二期)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
多数据源或分库分表
posted @ 2018-10-24 09:47  free_wings  阅读(876)  评论(0编辑  收藏  举报