• 网站访问量统计功能的实现


    实现方法:拦截器+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);
        	}
        }  
    }
    
  • 相关阅读:
    IP保留地址
    HTML5读取本地文件
    angularjs中动态为audio绑定src
    canvas移动端常用技巧图片loading
    angularjs三级联动
    angular实现select的ng-options
    ng-bind-html在ng-repeat中问题的解决办法
    JS判断是否在微信浏览器打开
    angular实现select的ng-options
    创建 AngularJS 自定义过滤器,带自定义参数
  • 原文地址:https://www.cnblogs.com/wuchaodzxx/p/7172321.html
Copyright © 2020-2023  润新知