网站访问量统计功能的实现
实现方法:拦截器+session存储
拦截器初始化时,即在@PostConstruct注解的initMethod方法中读取数据库的isystem对象,该对象记录了网站访问量的信息。
拦截器销毁时,即在@PreDestroy注解的destroyMethod方法中向数据库更新isystem对象。
拦截器的初始化和销毁都只有在应用启动和关闭的时候才被调用,因此减少了对数据库的访问。
SpringMVC中,每一次请求控制器,都会先执行拦截器的preHandle方法,在该方法内先查看session中的一个标志accessedFlag,如果该标志不存在,说明此次会话没有被统计,因此在isystem对象中增加一次访问量,并向session添加标志accessedFlag,下一次访问时,该session不再添加访问量,即一个session算访问一次。并且在session中存储isystem对象,并于网页显示数据的调用。
为了保证并发的正确性,局部代码块使用同步锁,见下面红色部分。
总结:拦截器有一个静态属性isystem,用户第一次请求时,都会更新这个属性的值。用户的每一次请求都会把该属性放入到用户的session中去。因此,B用户第一次访问后,A用户第二次访问时(和第一次访问共享一个session),A用户的session中的isystem也会被更新。
拦截器类如下:
package com.wuchao.utils.interceptor;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.wuchao.blog.system.bo.intf.IsystemBo;
import com.wuchao.blog.system.po.Isystem;
import com.wuchao.blog.user.controller.LoginController;
import com.wuchao.utils.config.SpringContextHolder;
public class RequestInterceptor extends HandlerInterceptorAdapter {
private static Logger log = Logger.getLogger(LoginController.class);
@Resource(name="isystemBo")
public IsystemBo isystemBo;
@Resource(name="springContextHolder")
SpringContextHolder springContextHolder;
public static Isystem isystem;
//请求控制器前,处理请求
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
try {
log.info("RequestInterceptor");
//网站访问量+1
if(isystem==null) {
log.info("isystem==null");
isystem = isystemBo.getIsystemByDefault();
}
if(isystem!=null) {
//每一个session理论上只能记一次访问,因此在session里面存一个访问标记,如果存在标记,则不再计算此次访问
String accessedFlag = "accessedFlag";
if(request.getSession().getAttribute("accessedFlag")==null) {
//同步锁
synchronized(this) {
log.info("网站访问量+1,存入session");
isystem.setAmountOfAccess(isystem.getAmountOfAccess()+1);
request.getSession().setAttribute("Isystem", isystem);
request.getSession().setAttribute("accessedFlag", accessedFlag);
}
}
}
}catch(Exception e) {
e.printStackTrace();
throw e;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
/*
* 实例化时执行的操作
*/
@PostConstruct
public void initMethod() throws Exception {
log.info("initMethod 被执行");
//加载isystem对象
if(isystem==null) {
log.info("加载isystem");
isystem = isystemBo.getIsystemByDefault();
}
}
/*
* 销毁前执行的操作
*/
@PreDestroy
public void destroyMethod() throws Exception {
log.info("destroyMethod 被执行");
//保存isystem
if(isystem!=null) {
isystemBo.saveIsystem(isystem);
}
}
}