基于SpringBoot和Freemarker的页面静态化

页面静态化能够缓轻数据库的压力,还能提高页面的并发能力,但是网页静态化是比较适合大规模且相对变化不太频繁的数据。

页面静态化在实际应用中还是比较常见的,比如博客详情页、新闻网站或者文章类网站等等。这类数据变化不频繁比较适合静态化页面。该篇博客就是介绍博客详情页的页面静态化输出。

页面静态化实现

导入Jar

compile group: 'org.springframework.boot', name: 'spring-boot-starter-freemarker', version: '2.1.6.RELEASE'

配置文件

server:
  port: 8015
  servlet:
    context-path: /staticftl

# freemarker静态资源配置
# 文件路径
spring:
  freemarker:
    tempalte-loader-path: classpath:/templates
# 关闭缓存,及时刷新
    cache:  false
    charset:  UTF-8
    content-type: text/html
    suffix: .html
  mvc:
    static-path-pattern: /static/**

编写模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>${blog.title}</title>
</head>
<body>
<h1>${blog.title}</h1>
<h2>${blog.author}</h2>
<div>${blog.content}</div>
</body>
</html>

Freemarker还提供很多其他的常用的指令和函数,功能也是非常强大的。

页面输出

 /**
 * 输出静态化页面
 * @param root
 * @param id
 */
public void productStaticPage(Map<String,Object> root, String id){
    Configuration config = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    config.setDefaultEncoding("UTF-8");
    //输出页面的全名
    String path = getStaticHtmlPath()+"/" + id + ".html";
    File f = new File(path);
    File parentFile = f.getParentFile();
    if(!parentFile.exists()){
        parentFile.mkdirs();
    }

    Writer out = null;
    try {
        //获取模板页面
        String templatePath =ClassLoader.getSystemResource("templates").getPath();
        TemplateLoader templateLoader=new FileTemplateLoader(new File(templatePath+"\\blog"));
        config.setTemplateLoader(templateLoader);
        Template template = config.getTemplate("detail.html");

        //输出页面
        out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");

        //处理数据
        template.process(root, out);
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(null != out){
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

通过Freemarker输出静态页面。

/**
 * 魔改的Freemarker的静态化页面输出地址
 * 不具备普遍性
 * @return 静态化页面输出地址
 */
public String getStaticHtmlPath(){
    //Thread.currentThread().getContextClassLoader().getResource("templates").getPath()
    String path = this.getClass().getClassLoader().getResource("").getPath();
    if(path==null || path.length()==0){
        return "";
    }
    path=path.substring(0,path.indexOf("build"))+"\\src\\main\\resources\\static\\html";
    return path;
}

这个代码在实际应用是需要更改的,目前是在本机Windows中,且把静态化页面放到了项目目录中,其实更好的结果是将输出静态化页面放到Nginx服务器中,这样在并发性也更高,而且目录环境也更好解决。

本身使用Freemarker输出静态页面是比较简单的,上述关键代码再加上一些串联代码应该能正常运行了,其中需要注意的就是相关目录,里面涉及到一个模板目录,用于读取模板;一个输出页面目录,目前是使用SpringBoot并把static目录当做静态资源,所以需要把静态页面放入此目录,但是建议使用Nginx来做静态页面的服务器。

加入消息中间件和MongoDB数据库

我又加入了一点小功能,实现当我们将博客数据保存到MongoDB数据库中,使用ActiveMQ队列功能,异步将博客数据静态化到页面中然后输出。

引入Jar

compile group: 'org.springframework.boot', name: 'spring-boot-starter-activemq', version: '2.1.6.RELEASE'
# 需要引入如下Jar包,不然ActiveMQ的配置无法导入。
compile group: 'org.messaginghub', name: 'pooled-jms', version: '1.1.0'
compile group: 'org.springframework.data', name: 'spring-data-mongodb', version: '2.1.6.RELEASE'

配置文件

spring:
  data:
    mongodb:
      host: 127.0.0.1
      port: 27017
      database: staticftl
  activemq:
    broker-url: tcp://localhost:61616
    #true 表示使用内置的MQ,false则连接服务器
    in-memory: false
    #true表示使用连接池;false时,每发送一条数据创建一个连接
    pool:
      enabled: true
      #连接池最大连接数
      max-connections: 10
      idle-timeout: 30000
    user: admin
    password: admin

使用MongoDB

import com.plf.learn.staticftl.bean.Blog;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;


@Repository
public interface BlogRepository extends MongoRepository<Blog,java.lang.String> {
}

SpringBoot自带的封装MongoDB的操作,使得数据库操作变得非常简单。

使用ActiveMQ

发送队列消息

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;


@Component
public class ActiveMQProducer {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    /**
     *
     * @param destination   队列
     * @param message   信息
     */
    public void sendMessage(String destination,String message){
        jmsMessagingTemplate.convertAndSend(destination,message);
    }
}

监听队列,将数据静态化到页面上

import com.plf.learn.staticftl.bean.Blog;
import com.plf.learn.staticftl.service.BlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;


@Component
public class BlogStaticFtlListener {

    @Autowired
    private BlogService blogService;

    @JmsListener(destination="staticftl.blog")
    public void ListenBlogQueue(String message){

        String blog_id = message;

        //获取到博客信息
        Blog blog = blogService.getById(blog_id);
        Map<String,Object> map = new HashMap<>();
        map.put("blog",blog);
        //输出静态化页面
        blogService.productStaticPage(map,blog_id);
    }
}

上述代码即可实现,将博客文章保存到MongoDB数据库中,然后通过消息中间件消费输出静态化页面,即可直接访问静态资源。完整代码可访问我的Github。

相关推荐
所待.3832 分钟前
JavaEE之线程初阶(上)
java·java-ee
Winston Wood6 分钟前
Java线程池详解
java·线程池·多线程·性能
Alive~o.07 分钟前
Go语言进阶&依赖管理
开发语言·后端·golang
手握风云-10 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
许苑向上13 分钟前
Dubbo集成SpringBoot实现远程服务调用
spring boot·后端·dubbo
喵叔哟30 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生36 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
郑祎亦1 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
不是二师兄的八戒1 小时前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
爱编程的小生1 小时前
Easyexcel(2-文件读取)
java·excel