頁面靜態化能夠緩輕數據庫的壓力,還能提高頁面的并發能力,但是網頁靜態化是比較適合大規模且相對變化不太頻繁的數據。
頁面靜態化在實際應用中還是比較常見的,比如博客詳情頁、新聞網站或者文章類網站等等。這類數據變化不頻繁比較適合靜態化頁面。該篇博客就是介紹博客詳情頁的頁面靜態化輸出。
頁面靜態化實現
導入Jar
compile group: 'org.springframework.boot', name: 'spring-boot-starter-freemarker', version: '2.1.6.RELEASE'
配置文件
server:port: 8015servlet:context-path: /staticftl# freemarker靜態資源配置
# 文件路徑
spring:freemarker:tempalte-loader-path: classpath:/templates
# 關閉緩存,及時刷新cache: falsecharset: UTF-8content-type: text/htmlsuffix: .htmlmvc: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.1port: 27017database: staticftlactivemq:broker-url: tcp://localhost:61616#true 表示使用內置的MQ,false則連接服務器in-memory: false#true表示使用連接池;false時,每發送一條數據創建一個連接pool:enabled: true#連接池最大連接數max-connections: 10idle-timeout: 30000user: adminpassword: 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 {@Autowiredprivate 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 {@Autowiredprivate 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。