最近在做的一个网站,首页需要分块加载数据,每一块都需要使用一个很耗时的查询方法。最后想到了一个首页缓存的方法。
即在后台java服务器脚本中维护一个application的变量(setAttribute("","")),该对象将每一块数据都作为一个对象参数保存,在服务器启动的时候就加载一次,再写一个timer计时器每天晚上定时更新一下就行了。参见代码:
维护的对象对应的首页类(获取的每一块数据都作为一个单独的属性):
public class IndexItems {
private ResultContent AllSubject;// 所有学科
private ResultContent Physical;// 物理
private ResultContent Chemistry;// 化学
private ResultContent LifeScience;// 生命科学
private ResultContent EnginMat;// 工程材料
private ResultContent EarthScience;// 地球科学
private ResultContent InformaScience;// 信息科学
private ResultContent Manager;// 管理
private ResultContent Medicine;// 医学
public synchronized ResultContent getAllSubject() {
return AllSubject;
}
public synchronized ResultContent getPhysical() {
return Physical;
}
public synchronized ResultContent getChemistry() {
return Chemistry;
}
public synchronized ResultContent getLifeScience() {
return LifeScience;
}
public synchronized ResultContent getEnginMat() {
return EnginMat;
}
public synchronized ResultContent getEarthScience() {
return EarthScience;
}
public synchronized ResultContent getInformaScience() {
return InformaScience;
}
public synchronized ResultContent getManager() {
return Manager;
}
public synchronized ResultContent getMedicine() {
return Medicine;
}
// 获取一个首页对象,并解析成json字符串,将它保存在application里面以供调用
public void SetApplication() {
try {
String limit = "5";
String offset = "0";
AllSubject = StaticFunc.getItemBySubject("[[]]", limit, offset);// 获取全部前几项
MetadataEntry meta = new MetadataEntry();
meta.key = "dc.subject";
meta.value = "数理科学部";
meta.language = null;
// 转换为json
ObjectMapper mapper = new ObjectMapper();
String jsonStr = "[[]]";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
Physical = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "化学科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
Chemistry = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "生命科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
LifeScience = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "工程与材料科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
EnginMat = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "地球科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
EarthScience = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "信息科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
InformaScience = StaticFunc
.getItemBySubject(jsonStr, limit, offset);
meta.value = "管理科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
Manager = StaticFunc.getItemBySubject(jsonStr, limit, offset);
meta.value = "医学科学部";
jsonStr = "[[" + mapper.writeValueAsString(meta) + "]]";
Medicine = StaticFunc.getItemBySubject(jsonStr, limit, offset);
} catch (Exception e) {
}
}
}
servlet在初始化的时候加载:
package com.Service.Servlet;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import com.Service.Models.IndexItems;
import com.Service.Models.MetadataEntry;
import com.Service.Models.ResultContent;
/**
* Servlet implementation class IndexServlet
*/
@WebServlet("/IndexServlet")
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public IndexServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// 重写了Servlet的init方法后一定要记得调用父类的init方法,否则在service/doGet/doPost方法中使用getServletContext()方法获取ServletContext对象时就会出现java.lang.NullPointerException异常
super.init(config);
// 生成首页对象
IndexItems indexItem = new IndexItems();
// 调用获取数据的内部方法
indexItem.SetApplication();
// 设置到application中
getServletContext().setAttribute("index", indexItem);
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 根据传递过来的参数判断返回哪一块
// 设置字符集
request.setCharacterEncoding("utf-8");
// 鑾峰彇鍙傛暟
String metaListStr = request.getParameter("metaList");// 若查询全部,则传递[[]]
// [[{"key":"dc.contributor.author","value":"Smith","language":null}],
// [{"key":"dc.contributor.author","value":"Smith","language":null}]
// ]
String content = request.getParameter("content");
String limit = request.getParameter("limit");
String offset = request.getParameter("offset");
ObjectMapper mapper = new ObjectMapper();
ArrayList<ArrayList<MetadataEntry>> listlist = mapper.readValue(
metaListStr,
new TypeReference<ArrayList<ArrayList<MetadataEntry>>>() {
});
String sql = null;
int lengthList = listlist.size();
ResultContent resultContent = new ResultContent();
IndexItems indexItems = (IndexItems) getServletContext().getAttribute(
"index");
if (lengthList == 1) {
ArrayList<MetadataEntry> metaList = listlist.get(0);
if (metaList.size() == 0) {
// 此时调用的应该是获取全部的那一个
resultContent = indexItems.getAllSubject();
} else {
MetadataEntry metadataEntry = metaList.get(0);
String strTemp = metadataEntry.getValue();
switch (strTemp) {
case "数理科学部":// 物理学科
resultContent = indexItems.getPhysical();
break;
case "化学科学部":// 化学
resultContent = indexItems.getChemistry();
break;
case "生命科学部":// 生命科学
resultContent = indexItems.getLifeScience();
break;
case "工程与材料科学部":
resultContent = indexItems.getEnginMat();
break;
case "地球科学部":
resultContent = indexItems.getEarthScience();
break;
case "信息科学部":
resultContent = indexItems.getInformaScience();
break;
case "管理科学部":
resultContent = indexItems.getManager();
break;
case "医学科学部":
resultContent = indexItems.getMedicine();
break;
}
}
}
// 序列化成json向前端发送
String jsonStr = null;
jsonStr = mapper.writeValueAsString(resultContent);
// 锟斤拷锟矫凤拷锟酵碉拷锟斤拷锟斤拷锟斤拷锟斤拷为json
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
// 锟斤拷锟斤拷锟斤拷锟斤拷
response.getWriter().write(jsonStr);
}
}
计时器监听类:
package com.Service.Timer;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextListener implements ServletContextListener {
private static final long serialVersionUID = 1L;
public ContextListener() {
}
private java.util.Timer timer = null;
public void contextInitialized(ServletContextEvent event) {
/**
* 设置一个定时器
*/
timer = new java.util.Timer(true);
event.getServletContext().log("定时器已启动");
/**
* 定时器到指定的时间时,执行某个操作(如某个类,或方法)
*/
// 后边最后一个参数代表监视器的监视周期,现在为一小时
timer.schedule(new SetIndexTimer(event.getServletContext()), 0,
60 * 60 * 1000);
event.getServletContext().log("已经添加任务调度表");
}
public void contextDestroyed(ServletContextEvent event) {
timer.cancel();
System.out.println("定时器销毁");
event.getServletContext().log("定时器销毁");
}
}
计时器任务类:
package com.Service.Timer;
import java.io.IOException;
import java.util.Calendar;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import com.Service.Models.IndexItems;
public class SetIndexTimer extends TimerTask {
public SetIndexTimer() {
super();
}
/** 这个代表23点钟的时候执行任务 */
private static final int C_SCHEDULE_HOUR = 23;
private static boolean isRunning = false;
private ServletContext context = null;
public SetIndexTimer(ServletContext context) {
this.context = context;
}
public void run() {
Calendar cal = Calendar.getInstance();
if (!isRunning) {
if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
isRunning = true;
context.log("开始执行指定任务");
IndexItems indexItems = (IndexItems) context
.getAttribute("index");
indexItems.SetApplication();
context.setAttribute("index", indexItems);
isRunning = false;
context.log("指定任务执行结束");
}
} else {
context.log("上一次任务执行还未结束");
}
}
}
在web.xml中注册监听类
<listener>
<listener-class>com.Service.Timer.ContextListener</listener-class>
</listener>