页面静态化能够缓轻数据库的压力,还能提高页面的并发能力,但是网页静态化是比较适合大规模且相对变化不太频繁的数据。
页面静态化在实际应用中还是比较常见的,比如博客详情页、新闻网站或者文章类网站等等。这类数据变化不频繁比较适合静态化页面。该篇博客就是介绍博客详情页的页面静态化输出。
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/**
${blog.title}
${blog.title}
${blog.author}
${blog.content}
Freemarker还提供很多其他的常用的指令和函数,功能也是非常强大的。
/**
* 输出静态化页面
* @param root
* @param id
*/
public void productStaticPage(Map 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数据库中,使用ActiveMQ队列功能,异步将博客数据静态化到页面中然后输出。
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
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 {
}
SpringBoot自带的封装MongoDB的操作,使得数据库操作变得非常简单。
发送队列消息
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 map = new HashMap<>();
map.put("blog",blog);
//输出静态化页面
blogService.productStaticPage(map,blog_id);
}
}
上述代码即可实现,将博客文章保存到MongoDB数据库中,然后通过消息中间件消费输出静态化页面,即可直接访问静态资源。完整代码可访问我的Github。