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

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

即在后台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>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值