實現方法:攔截器+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);
}
}
}