1. 概述
在大型网站中, 如京东和当当商品详情界面, 看到的页面基本上是静态页面. 为什么都要把页面静态化呢? 把页面静态化, 好处有很多. 例如: 访问速度快, 更有利于搜索引擎收录等.
一种常用的方法是通过程序将动态页面抓取并保存为静态页面, 这样的页面的实际存在于服务器的硬盘中. 本文采用该方法.
2. 实现代码
- @Service
- @Lazy(false)
- /**
- * 静态化页面
- * <p>
- * 定时发送 http 请求, 获取需要静态化的页面, 另存为 html 文件, 页面被访问时首先判断静态化页面是否生成成功.
- * 如果静态页面生成成功, 则访问静态页面 HTML.
- * 如果需要增加被静态化的页面, initUrl() 方法中初始化 url.
- * </p>
- */
- public class SiteStatics {
- Logger logger = Logger.getLogger(SiteStatics.class);
- /**
- * 静态化 URL
- **/
- private final String STATIC_URL = System.getProperty("user.contextPath")+Global.getConfig("statics.url");
- /**
- * 静态化文件名称
- **/
- private final String STATIC_NAME = "${code}.html";
- /**
- * 静态化文件存储路劲
- **/
- private final static String STATIC_ROOT = "/statics/";
- /**
- * 静态化列表 URL - 是否静态化 1 - 是 0 - 否
- */
- public HashMap<String, Boolean> STATIC_HTML = new HashMap<String, Boolean>();
- /**
- * 判断是否是 Windows 系统
- */
- public final static boolean IS_LOCAL = System.getProperty("os.name").startsWith("win") || System.getProperty("os.name").startsWith("Win");
- /**
- * IP
- ***/
- private final String LOGON_SITE = IS_LOCAL ? "localhost" : "localhost";
- /**
- * 端口
- ***/
- private final int LOGON_PORT = IS_LOCAL ? 80 : 80;
- /**
- * 运行锁: 程序运行时禁止访问静态化页面
- */
- public static boolean EXEC_LOCK = false;
- private HttpClient client = new HttpClient();
- // 五分钟刷新一次首页静态化
- //@Scheduled(cron = "0 0/1 * * * *")
- public void run() {
- try {
- dostatic();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 初始化 client
- */
- public void createClient() {
- client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);
- }
- /**
- * 初始化需要静态化的 url
- * K: url, V: active
- * <p>
- * V: true 静态化, false 不必静态化
- * 如果需要静态化的 url 很多, 全部放到 map 里面去就行了, 可以自行扩展
- * </p>
- */
- private void addUrl(String code) {
- STATIC_HTML.put(STATIC_URL.replace("${code}", code), true);
- }
- /**
- * 初始化 url
- * <p>
- * 根据需求构造 url, 这里我就写死了, 只初始化一个首页的 url
- * </p>
- */
- private void initUrl() {
- String code = "wzsy";
- addUrl(code);
- }
- /**
- * 静态化
- */
- private void dostatic() throws IOException {
- EXEC_LOCK = true;
- long s = System.currentTimeMillis();
- createClient();
- STATIC_HTML = new HashMap<String, Boolean>();
- initUrl();
- File parentFolder = new File(SiteStatics.class.getResource("/").getPath()).getParentFile().getParentFile();
- File folder = new File(parentFolder.getPath() + STATIC_ROOT);
- if (!folder.exists()) {
- folder.mkdirs();
- }
- int i = 0;
- int a = STATIC_HTML.size();
- logger.info("共计缓存界面" + a + "个");
- System.out.println("共计缓存界面" + a + "个");
- for (Map.Entry<String, Boolean> entry : STATIC_HTML.entrySet()) {
- i++;
- String url = entry.getKey();
- Boolean is_static = entry.getValue();
- Integer p = (int) (Double.valueOf(i) / a * 100);
- logger.info(url + "成功 (" + p + "%)");
- System.out.println(url + "成功 (" + p + "%)");
- if (is_static) {
- GetMethod get = new GetMethod(url);
- // 模拟表单元素
- File file = null;
- try {
- String code = url.split("=")[1];
- String fileName = STATIC_NAME.replace("${code}", code);
- file = new File(folder + "/" + fileName);
- int status = client.executeMethod(get);
- if (status>= 200 && status < 400) {
- if (!file.exists()) {
- file.createNewFile();
- }
- String HTML = get.getResponseBodyAsString();
- writeFile(file, HTML);
- logger.info(url + "成功 (" + p + "%)");
- } else {
- logger.info(url + "失败 (" + p + "%)");
- }
- } catch (Exception e) {
- logger.error("首页缓存失败", e);
- }
- entry.setValue(false);
- }
- }
- logger.info("----------- 缓存结束 -----------");
- long e = System.currentTimeMillis();
- logger.info("----------- 耗时:" + (e - s) / 1000 + "秒 -----------");
- EXEC_LOCK = false;
- }
- /**
- * 判断静态化页面是否存在
- *
- * @param code
- * @return
- */
- public static boolean existsStatics(String code) {
- String fileName = new File(SiteStatics.class.getResource("/").getPath()).getParentFile().getParentFile().getPath() + STATIC_ROOT + "/" + code + ".html";
- File file = new File(fileName);
- if (file.exists() && !EXEC_LOCK) {
- return true;
- }
- return false;
- }
- public static void main(String[] args) {
- System.out.println(SiteStatics.class.getResource("/").getPath());
- }
- /**
- * 将配置字符串写出到文件
- *
- * @param file 文件路径
- * @param str 待写入的字符串
- */
- private void writeFile(File file, String str) {
- try {
- if (!file.exists()) {
- file.createNewFile();
- }
- OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
- BufferedWriter writer = new BufferedWriter(write);
- writer.write(str);
- writer.close();
- } catch (Exception e) {
- System.out.println("写文件内容操作出错");
- e.printStackTrace();
- }
- }
- }
3. 访问控制
- String code = httpServletRequest.getParameter("code");
- if(SiteStatics.existsStatics(code)){
- String static_name = Global.getConfig("statics.url").replace("${code}", code);
- return "redirect:"+static_name;
- }
来源: http://www.jianshu.com/p/ef1ff78fb01a