java网站首页缓存的解决办法之一

来源:互联网 发布:淘宝 买家手机号 编辑:程序博客网 时间:2024/05/22 13:48

最近在做的一个网站,首页需要分块加载数据,每一块都需要使用一个很耗时的查询方法。最后想到了一个首页缓存的方法。

即在后台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;// 转换为jsonObjectMapper 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);// 锟斤拷锟矫凤拷锟酵碉拷锟斤拷锟斤拷锟斤拷锟斤拷为jsonresponse.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>




0 0
原创粉丝点击