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;
}
网友评论