ssm如何在监听器中使用spring注解注入的service层?

在我的个人博客项目中,有这样的需求:利用seesion监听器统计在线人数和网站访问量情况。这个需求在我看来,应该有两种思路:

  1. 直接在监听器定义四个变量存储数据
  2. 在项目数据库中设计一张数据表来专门存储数据

 下面我从这两个思路分别来说明一下:

  • 直接在监听器定义四个变量存储数据

首先在session监听器中定义4个变量:
当前在线用户数(count)、总访问量(all)、今日访问量(today)、今日日期(day)
然后session监听器SessionCounter实现了HttpSessionListener接口,所以类中包含了sessionCreated以及sessionDestroyed方法,sessionCreated方法是在session创建的时候执行,而sessionDestroyed方法则是在session销毁时执行。在session创建时对当前在线用户数(count)、总访问量(all)的值进行++操作,然后通过对比今日日期(day) 的值以及直接获取到的日期,对今日访问量(today)进行不同的操作即可。所以具体的实现代码如下:

实现代码: 

package com.pwt.utils;

import org.springframework.stereotype.Component;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Date;

/**
 * count 当前在线用户数
 * all 总访问量
 * today 今日访问量
 * day 今日日期
 */
@Component
public class SessionCounter implements HttpSessionListener {

    private static Integer count = 0;
    private static long today = 0;
    private static long all = 0;
    private static int day = 0;

    //session创建
    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
        ServletContext context = arg0.getSession().getServletContext();
        count = (Integer) context.getAttribute("onlineCount");
        if (count == null) {
            count = new Integer(1);
        } else {
            int co = count.intValue();
            count = new Integer(co + 1);
        }
        // 保存人数
        context.setAttribute("onlineCount", count);
        all++;
        Date date=new Date();
        int tday=date.getDate();
        //如果日期发生变化则将today置为1,否则将today加1
        if(tday!=day){
            day=tday;
            today=1;
        }else{
            today++;
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {
        ServletContext context = arg0.getSession().getServletContext();
        count = (Integer) context.getAttribute("onlineCount");
        int co = count.intValue();
        count = new Integer(co - 1);
        count = count >= 0 ? count : 0;
        context.setAttribute("onlineCount", count);
    }

    public static Integer getCount() {
        return count;
    }

    public long getAll(){
        return all;
    }

    public long getToday(){
        return today;
    }
}
  •  在项目数据库中设计一张数据表来专门存储数据

经过我的深思熟虑,我就想把在线人数存储在session中,而今日访问量和总访问量则存储在mysql数据库中。所以我的数据表字段设计如下:

visit_id:某天访问量的id

visit_date:访问日期

visit_count:某天的访问量

到此,数据库设计完成,你们可能会说怎么没有存储总访问量的字段呢?因为我是通过数据库的sum函数来对每条数据的visit_count字段进行求和,从而得到总的访问量。

 具体代码如下:

package com.pwt.utils;

import com.pwt.model.vo.VisitTotalVo;
import com.pwt.service.IVisitTotalService;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author pwt
 */
@Component
public class SessionCounter implements HttpSessionListener {

    @Autowired
    private IVisitTotalService iVisitTotalService;

    private static Map sessionMap = new HashMap();

    public SessionCounter() {}

    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
        ServletContext context = arg0.getSession().getServletContext();
        Date date = new Date();
        boolean flag = true;
        for(Object key : sessionMap.keySet()){
            if(key.toString().equals(arg0.getSession().getId())){
                flag = false;
            }
        }
        if(flag){
            sessionMap.put(arg0.getSession().getId(), arg0.getSession());
        }

        context.setAttribute("onlineCount", sessionMap.size());
        VisitTotalVo visitTotalVo = new VisitTotalVo();
      
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        try {
            visitTotalVo.setVisitDate(new java.sql.Date(sdf.parse(sdf.format(date)).getTime()));
            iVisitTotalService.queryVisitTotalByVisitDate(visitTotalVo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {

        boolean flag = false;
        for(Object key : sessionMap.keySet()){
            if(key.toString().equals(arg0.getSession().getId())){
                flag = true;
            }
        }
        if(flag){
            sessionMap.remove(arg0.getSession().getId());
        }
        ServletContext context = arg0.getSession().getServletContext();
        context.setAttribute("onlineCount", sessionMap.size());
    }
}

从代码中可以看到,我直接在监听器中调用了service层的方法,如果你直接这样运行项目的话,项目会出现空指针异常,原因是监听器属于sevlet容器,不属于 Spring 框架的管理范围,拿不到spring注解注入的bean。要想让项目不会报错,我是这样解决的:

代码:

package com.pwt.utils;

import com.pwt.service.IVisitTotalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;


@Component
public class InjectServiceUtil {

    @Autowired
    private IVisitTotalService iVisitTotalService;

    @PostConstruct
    public void init(){
        InjectServiceUtil.getInstance().iVisitTotalService = this.iVisitTotalService;
    }

    /**
     *  实现单例 start
     */
    private static class SingletonHolder {
        private static final InjectServiceUtil INSTANCE = new InjectServiceUtil();
    }
    private InjectServiceUtil (){}
    public static final InjectServiceUtil getInstance() {
        return SingletonHolder.INSTANCE;
    }
    /**
     *  实现单例 end
     */
    public static IVisitTotalService getIVisitTotalService(){
        return InjectServiceUtil.getInstance().iVisitTotalService;
    }
}

修改监听器如下:

package com.pwt.utils;

import com.pwt.model.vo.VisitTotalVo;
import com.pwt.service.IVisitTotalService;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pwt
 */
@Component
public class SessionCounter implements HttpSessionListener {

    private static IVisitTotalService iVisitTotalService;

    private static Map sessionMap = new HashMap();

    public SessionCounter() {}

    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
        ServletContext context = arg0.getSession().getServletContext();
        Date date = new Date();
        boolean flag = true;
        for(Object key : sessionMap.keySet()){
            if(key.toString().equals(arg0.getSession().getId())){
                flag = false;
            }
        }
        if(flag){
            sessionMap.put(arg0.getSession().getId(), arg0.getSession());
        }

        context.setAttribute("onlineCount", sessionMap.size());
        VisitTotalVo visitTotalVo = new VisitTotalVo();
        iVisitTotalService = InjectServiceUtil.getIVisitTotalService();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        try {
            visitTotalVo.setVisitDate(new java.sql.Date(sdf.parse(sdf.format(date)).getTime()));
            iVisitTotalService.queryVisitTotalByVisitDate(visitTotalVo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {

        boolean flag = false;
        for(Object key : sessionMap.keySet()){
            if(key.toString().equals(arg0.getSession().getId())){
                flag = true;
            }
        }
        if(flag){
            sessionMap.remove(arg0.getSession().getId());
        }
        ServletContext context = arg0.getSession().getServletContext();
        context.setAttribute("onlineCount", sessionMap.size());
    }
}

这样项目运行就不会再出现空指针异常。最后两种思路还需要配置web.xml文件:

<listener>
  <listener-class>com.pwt.utils.SessionCounter</listener-class>
</listener>
<!-- session配置过期时间 -->
<session-config>
  <session-timeout>3</session-timeout>
</session-config>
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值