Java - 用户在线的数据库实现方法和内存实现方法

一,数据库实现方法:(实现思路:基于Struts2.0的拦截器)

0,流程:struts.xml -> 
ApplicationContext.xml
 -> 
LoginInterceptor.java -> 
OnlineAction.java -> 
Online.ftl

1,
struts.xml:

<action name="index" class="indexAction">
            <result name="success" type="freemarker">/WEB-INF/ftl/OnLine.ftl</result>
        </action>
2,
ApplicationContext.xml:
    <bean id="indexAction" class="cn.company.OnlineAction">
        <property name="configService" ref="configService" />
        <property name="onlineService" ref="onlineService" />
    </bean>

<!-- 定期清理过期的在线用户 -->
    <bean id="onlineClear" class="cn.
company.OnLineClearTimerTask">
        <property name="onlineService" ref="onlineService" />
    </bean>
    <bean id="onlineClearTimerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
        <property name="delay">
            <value>10800000</value><!-- 3小时 * 60分钟 * 60秒 * 1000毫秒 = 10800000毫秒 -->
        </property>
        <property name="period">
            <value>10800000</value>
        </property>
        <property name="timerTask">
            <ref local="onlineClear" />
        </property>
    </bean>
    <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
        <property name="scheduledTimerTasks">
            <list>
                <ref local="onlineClearTimerTask" />
            </list>
        </property>
    </bean>
3,
LoginInterceptor.java

public String intercept(ActionInvocation actionInvocation) throws Exception {

Object action = actionInvocation.getAction();

// log.info("登录拦截器将拦截:" + action.getClass().getName().substring(24));

ActionContext ac = actionInvocation.getInvocationContext();

ServletContext servletContext = (ServletContext) ac.get(ServletActionContext.SERVLET_CONTEXT);

WebApplicationContext wc = WebApplicationContextUtils.getWebApplicationContext(servletContext);

if (wc == null) {

log.error("找不到Spring的配置文件:ApplicationContext.xml");

} else {

String username = "";

UserSession us = (UserSession) ac.getSession().get(Constant.USER_SESSION_KEY);

if (ac.getSession().get(User.SESSION_LOGIN_NAME_KEY) == null) {

if (us == null) {

username = (String) ac.getSession().get(User.SESSION_LOGIN_NAME_KEY);

// log.info("当前用户第一次进来:" + username);

} else {

username = ((UserSession) ac.getSession().get(Constant.USER_SESSION_KEY)).getUserName();

// log.info("当前登录用户:" + username);

}

}

if (us == null) {

OnLineService onlineService = (OnLineService) wc.getBean("onlineService");

long nowTime = System.currentTimeMillis();

// log.info("添加一个游客:[email protected]" + nowTime + "(" + String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS:%1$tL", nowTime) + ")");

UserOnLine userOnLine = new UserOnLine();

userOnLine.setUserId(0);

userOnLine.setUserName("[email protected]" + nowTime);

userOnLine.setOnlineTime(nowTime);

onlineService.saveUserOnLine(userOnLine);

// 加入UserSession

us = new UserSession();

us.setUserName(userOnLine.getUserName());

us.setLastActiveTime(nowTime);

ac.getSession().put(Constant.USER_SESSION_KEY, us);

} else {

OnLineService onlineService = (OnLineService) wc.getBean("onlineService");

if (ac.getSession().get(User.SESSION_LOGIN_NAME_KEY) == null) {

username = ((UserSession) ac.getSession().get(Constant.USER_SESSION_KEY)).getUserName();

} else {

username = (String) ac.getSession().get(User.SESSION_LOGIN_NAME_KEY);

}

UserOnLine userOnLine = onlineService.findUserOnLineByUserName(username);

if (userOnLine != null) {

//log.info("OnlineTime:" + userOnLine.getOnlineTime());

}

}

}

// 继续执行 Action

return actionInvocation.invoke();

}

4,
OnlineAction.java:
public class OnlineAction extends ManageBaseAction {

/** 配置服务 */

private ConfigService configService;

/** 在线服务 */

private OnLineService onlineService;

/** 在线用户统计服务 */

private StatService statService;

/** 在线用户列表 */

private List<UserOnLine> onlineList = new ArrayList<UserOnLine>();

/** 在线会员数 */

private long onlineUserNum = 0;

/** 在线游客数 */

private long onlineGuestNum = 0;

/** 最高在线人数 */

private String onlineHighest;

/** 最高在线人数的出现时间 */

private String onlineAppear;

@Override

protected String execute(String cmd) throws Exception {

// 从游客变成注册用户

String username = "";

HttpSession session = request.getSession();

if (session.getAttribute(User.SESSION_LOGIN_NAME_KEY) == null) {

username = ((UserSession) session.getAttribute(Constant.USER_SESSION_KEY)).getUserName();

} else {

String guestName = ((UserSession) session.getAttribute(Constant.USER_SESSION_KEY)).getUserName();

// log.info("登录前的游客名:" + guestName);

if (guestName != null && !"".equals(guestName)) {

UserOnLine userOnLine = onlineService.findUserOnLineByUserName(guestName);

onlineService.removeUserOnLine(userOnLine);

}

username = (String) session.getAttribute(User.SESSION_LOGIN_NAME_KEY);

}

// log.info("当前在首页的用户:" + username);

long optTime = System.currentTimeMillis() - getTime();

// log.info("前五分钟:" + optTime + "(" + String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS:%1$tL", optTime) + ")");

onlineUserNum = onlineService.getOnLineUesrNum(optTime);

// log.info("在线会员:" + onlineUserNum);

onlineGuestNum = onlineService.getOnLineGuestNum(optTime);

// log.info("在线游客:" + onlineGuestNum);

long tmpHighest = onlineUserNum + onlineGuestNum;

// log.info("当前最高在线人数:" + tmpHighest);

int _h = Integer.valueOf(String.valueOf(tmpHighest));

UserOnLineStat userOnLineStat = statService.getUserOnLineStat();

// log.info("系统中的最高在线人数:" + userOnLineStat.getHighest());

if (tmpHighest > userOnLineStat.getHighest()) {

userOnLineStat.setHighest(_h);

userOnLineStat.setAppearTime(String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", new Date()));

statService.updateUserOnLineStat(userOnLineStat);

// 从更新的数据库中取最新的数据

onlineHighest = String.valueOf(userOnLineStat.getHighest());

// log.info("最高在线:" + onlineHighest);

onlineAppear = userOnLineStat.getAppearTime();

// log.info("出现时间:" + onlineAppear);

} else {

onlineHighest = String.valueOf(userOnLineStat.getHighest());

// log.info("最高在线:" + onlineHighest);

onlineAppear = userOnLineStat.getAppearTime();

// log.info("出现时间:" + onlineAppear);

}

// 当前在线用户列表

onlineList = onlineService.findOnLineUser(optTime);

/*

SimpleMailMessage msg = new SimpleMailMessage(this.message);

msg.setTo("[email protected]");

msg.setSentDate(new Date());

msg.setText("当前在线用户:" + username + " [" + String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS:%1$tL", new Date()) + "]" + "[" + request.getRemoteAddr() + "]");

try {

mailSender.send(msg);

} catch(MailException ex) {

log.error(ex.getMessage());

log.info("邮件发送失败!");

}*/

return SUCCESS;

}

/**

* 获取系统配置的超时时间

*

*
@return

*/

private long getTime() {

return Integer.valueOf(getConfigValue("site.user.online.time")) * 1 * 60 * 1000; // 5 * 1分钟 * 60秒 1000毫秒 = 300000毫秒 = 5分钟

}

/**

* 根据配置 Name 得到相应的 Value

*/

private String getConfigValue(String string) {

return (String) this.configService.getConfigure().getValue(string);

}

/** 配置服务的set方法 */

public void setConfigService(ConfigService configService) {

this.configService = configService;

}

/** 在线服务的set方法 */

public void setOnlineService(OnLineService onlineService) {

this.onlineService = onlineService;

}

/** 在线用户统计服务的set方法 */

public void setStatService(StatService statService) {

this.statService = statService;

}

public List<UserOnLine> getOnlineList() {

return onlineList;

}

public long getOnlineUserNum() {

return onlineUserNum;

}

public long getOnlineGuestNum() {

return onlineGuestNum;

}

public String getOnlineHighest() {

return onlineHighest;

}

public String getOnlineAppear() {

return onlineAppear;

}

}

5,
Online.ftl:

<div>

注册用户:
${onlineUserNum!0},游客:
${onlineGuestNum!0},最高在线人数:
${onlineHighest!0},发生在:
${onlineAppear!?html}</div>

</div>

<div>

<#if onlineList??>

<#list onlineList as online>

<#assign u = Util.userById(online.userId)>

<a href="${SiteUrl}go.py?loginName=${u.loginName!}">${u.trueName!}</a>

</#list>

</#if>

</div>

6,Util.userById:

public class UserById implements TemplateMethodModel {

public Object exec(List args) throws TemplateModelException {

if (args == null || args.size() == 0)

throw new TemplateModelException("userById 需要 1 个整数型参数");

String idstr = args.get(0).toString();

if (ParamUtil.isInteger(idstr) == false)

throw new TemplateModelException("userById 需要 1 个整数型参数");

// 得到用户标识参数

int id = Integer.parseInt(idstr);

User u = jtar_ctxt.getUserService().getUserById(id);

return u == null ? NOTHING : u;

}

}

7,OnlineDaoHibernate.java

public UserOnLine findUserOnLineByUserName(String userName) {

List<UserOnLine> list = this.getSession().createQuery(FIND_USERONLINE_BY_USERNAME).setString(0, userName).list();

return (null == list || list.isEmpty()) ? null : (UserOnline) list.get(0);

}

8,Constant.java

public class Constant {

public static final String USER_SESSION_KEY = "user_session";

}

9,UserSession

public class UserSession implements Serializable {

/** 用户名 */

private String userName;

/** 上次活动时间 (具体的时间格式) */

private long lastActiveTime = 0;

/** 已经活动时间 (当前系统时间-上次活动时间=差值) */

private long addedOnlineTime = 0;

/**

* Default Constructor

*/

public UserSession () {

//

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public long getLastActiveTime() {

return lastActiveTime;

}

public void setLastActiveTime(long lastActiveTime) {

this.lastActiveTime = lastActiveTime;

}

public long getAddedOnlineTime() {

return addedOnlineTime;

}

public void setAddedOnlineTime(long addedOnlineTime) {

this.addedOnlineTime = addedOnlineTime;

}

}

10,UserOnLine.java

public class UserOnLine implements Serializable {

// 对象标识

private int Id;

// 用户Id,如为游客,则可以为空

private Integer userId;

// 用户名,如为游客,则可以为:Guest

private String userName;

// 时间的毫秒数

private long onlineTime;

/** Default Construct */

public UserOnLine() {

//

}

public int getId() {

return Id;

}

public void setId(int id) {

Id = id;

}

public Integer getUserId() {

return userId;

}

public void setUserId(Integer userId) {

this.userId = userId;

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public long getOnlineTime() {

return onlineTime;

}

public void setOnlineTime(long onlineTime) {

this.onlineTime = onlineTime;

}

}

二,内存实现方法:(实现思路:基于
Session

Application
的作用范围)

1,web.xml:
    <!-- 监听 session 中的在线用户 -->
    <listener>
        <listener-class>cn.company.OnlineListener</listener-class>
    </listener>
2,
OnlineListener.java:
public class OnlineListener implements HttpSessionListener {
    @Override
    // 监听 Session 的创建
    public void sessionCreated(HttpSessionEvent se) {
        // Do Nothing
    }
    @Override
    // 监听 Session 的销毁,在 session.invalidate() 时自动触发
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        UserSession us = (UserSession) session.getAttribute(Constant.USER_SESSION_KEY);
        // session.getServletContext() 是全局的 Application
,这个是重点!
        List onlineList = (List) session.getServletContext().getAttribute("onlineList");
        if (null != onlineList && 0 < onlineList.size() && us != null) {
            onlineList.remove(us);
        }
    }
}
3,
LoginInterceptor.java

public String intercept(ActionInvocation actionInvocation) throws Exception {
        Object action = actionInvocation.getAction();
        String sessionId = ServletActionContext.getRequest().getSession().getId();
        
        // 不拦截 AdminStatAction
        if (action instanceof AdminStatAction) {
            return actionInvocation.invoke();
        }

ActionContext ac = actionInvocation.getInvocationContext();        
        UserSession us = (UserSession) ac.getSession().get(Constant.USER_SESSION_KEY);
        
        if (null == us) {
            long nowTime = System.currentTimeMillis();
            // 往用户Session对象中放入一个游客对象
            us = new UserSession();
            us.setSessionId(sessionId);
            us.setUsername("_" + nowTime);
            ac.getSession().put(Constant.USER_SESSION_KEY, us);
        } else {
            // 系统中的用户名
            String username = "";
            if (null == ac.getSession().get(User.SESSION_LOGIN_NAME_KEY)) {
                // 如果没有从Session中获取到用户名(几乎不可能),直接将游客Session赋给用户名
                username = us.getUsername();
            } else {
                username = (String) ac.getSession().get(User.SESSION_LOGIN_NAME_KEY);
            }
            // 从游客变成注册用户
            // 删除之前的游客session,如果还是游客、或已登录用户再次访问首页的就不必重复删除
            us.setUsername(username);
        }        
        // 继续执行 Action
        return actionInvocation.invoke();
    }
4,OnlineAction.java:
public class OnlineAction extends ManageBaseAction {    
    // 游客列表
    private ArrayList guestList = new ArrayList();    
    // 注册用户列表
    private ArrayList userList = new ArrayList();

/* (non-Javadoc)
     * 
     * @see cn.edustar.jitar.action.ManageBaseAction#execute(java.lang.String)
     */
    @Override
    protected String execute(String cmd) throws Exception {
        HttpSession session = request.getSession();
        UserSession us = (UserSession) session.getAttribute(Constant.USER_SESSION_KEY);        
        // session.getServletContext() 是全局的 Application,这个是重点!
        List onlineList = (List) session.getServletContext().getAttribute("onlineList");
        if (null == onlineList) {
            onlineList = new ArrayList();
            session.getServletContext().setAttribute("onlineList", onlineList);
        } else {
            // 游客session不为空,因为可能是已登录用户再次访问首页
            if (null != us) {
                onlineList.remove(us);
            }
        }
        onlineList.add(us);

guestList.clear();
        userList.clear();
//        for (Iterator iterator = onlineList.iterator(); iterator.hasNext();) {
//            UserSession _us = (UserSession) iterator.next();
//            if (null != _us) {
//                if (_us.getUsername().startsWith("_")) {
//                    guestList.add(_us.getUsername());
//                } else {
//                    userList.add(_us.getUsername());
//                }
//            }
//        }        
        for (Object object : onlineList) {
            UserSession u = (UserSession) object;
            if (null != u) {
                if (u.getUsername().startsWith("_")) {
                    guestList.add(u.getUsername());
                } else {
                    userList.add(u.getUsername());
                }
            }
        }        
        return SUCCESS;
    }

public ArrayList getGuestList() {
        return guestList;
    }
    public ArrayList getUserList() {
        return userList;
    }
}
5,Online.ftl:
<div>
    <#assign onlineStat = Util.getUserOnLineStat(userList?size + guestList?size)>
    当前在线总人数:${userList?size + guestList?size}
    注册用户:${userList?size!0}
    游客:${guestList?size!0}
    最高在线总人数:${onlineStat.highest!0}
    发生在:${onlineStat.appearTime!?html}
</div>
<#if userList??>
    <#list userList as user>
            <#assign u = Util.userByName(user)>
            <a href="${SiteUrl}go.py?loginName=${u.loginName!}">${u.trueName!}</a>
    </#list> 
</#if>
6,Util.userByName:
    public class UserByName implements TemplateMethodModel {
        @SuppressWarnings("unchecked")
        public Object exec(List args) throws TemplateModelException {
            // 判断参数.
            if (args == null || args.size() == 0)
                throw new TemplateModelException("userByName 需要 1 个字符串参数");            
            String loginName = args.get(0).toString();
            User u = getUserService().getUserByLoginName(loginName);
            return u == null ? NOTHING : u;
        }
    }
7,Util.getUserOnLineStat:
    public class getUserOnLineStat implements TemplateMethodModel {
        @SuppressWarnings("rawtypes")
        public Object exec(List args) throws TemplateModelException {
            int count = 0;
            // 判断参数
            if (null == args || 0 == args.size()) {
                count = 1;
            } else {
                count = Integer.valueOf((String) args.get(0));
            }
            // System.out.println("当前在线人数:" + count);
            UserOnLineStat us = (UserOnLineStat) jtar_ctxt.getCacheProvider().getCache("online").get("online");
            OnlineManage onlineManage = jtar_ctxt.getOnlineManage();
            if (null == us) {
                us = onlineManage.getUserOnLineStat();
                // 放入缓存
                jtar_ctxt.getCacheProvider().getCache("online").put("online", us);
            } else {
                // 如果当前在线人数大于数据库(此刻是缓存)中的人数,则更新数据库,并更新缓存
                if (count > us.getHighest()) {
                    // 更新数据库
                    onlineManage.updateOnLineStat(count);
                    // 更新缓存
                    jtar_ctxt.getCacheProvider().getCache("online").put("online", onlineManage.getUserOnLineStat());
                }
            }
            return us;
        }
    }
8,ehcache.xml:
  <cache name="online" maxElementsInMemory="1024" eternal="false" timeToIdleSeconds="600"  timeToLiveSeconds="3600" overflowToDisk="true" />
9,系统启动的时候将统计信息放到缓存中:cacheService.put("online", getUserOnLineStat());
    public UserOnLineStat getUserOnLineStat() {
        List<UserOnLineStat> list = this.getSession().createQuery("FROM UserOnLineStat").list();
        if (null == list || list.isEmpty()) {
            return new UserOnLineStat();
        } else {
            return ((UserOnLineStat) list.get(0));
        }
    }
10,更新数据库:
    public void updateOnLineStat(int count) {
        String hql = "UPDATE UserOnLineStat SET highest = ?, appearTime = ‘" + String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", new Date()) + "‘ WHERE id = 1";
        this.getSession().createQuery(hql).setInteger(0, count).executeUpdate();    
        this.getSession().flush();
    }

时间: 2024-12-20 06:13:05

Java - 用户在线的数据库实现方法和内存实现方法的相关文章

Java连接MySQL数据库实现用户名密码的验证方法 Java语句中sql查询语句&#39;&#39; &quot;&quot;作用

//方法一,可以验证登录,但方法不实用.package com.swift; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; public class Logi

防止sql注入方法 如何防止java中将MySQL的数据库验证密码加上 &#39; or &#39;1&#39;= &#39;1 就可以出现万能密码 的PreparedStatement

package com.swift; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class LoginJDBC$PreparedStatement { public static void main(String[] args

sql server 还原数据库后,删除用户,提示数据库主体在该数据库中拥有架构,无法删除解决方法

将另一台服务器上的数据库备份文件,在现在用的这台服务器上还原之后,再创建相同的用户名,提示用户已存在 想将之前的用户先删除掉,却提示“数据库主体在该数据库中拥有架构,无法删除解决方法” 在网上找到方法,试了一下,还真管用. --执行如下SQL语句 ALTER AUTHORIZATION ON SCHEMA::db_owner TO dbo; --然后手动删除就可以了 我看还原后的数据库中的db_owner架构所有者就是那个要删除的用户名,再看其他数据库中的db_owner架构的所有者就是db_o

java网上在线支付

/**----------------------java网上在线支付-------------------------------------1.创建WEB项目2.创建前端支付页面表单3.导入支付平台端口类jar4.创建类读取用户的平台账号密钥5.创建Servlet6.(重点)request.getparameter获取相应平台所需支付信息7.(重点)引用平台类提供方法对交易数据进行hmac加密8.(重点)request.setAttribute()发送平台所需支付信息到转接页面9.(重点)创

深入剖析Java编程中的中文问题及建议最优解决方法

摘录自:http://fafeng.blogbus.com/logs/3062998.html http://www.blogbus.com/fafeng-logs/3063006.html 深入剖析Java编程中的中文问题及建议最优解决方法 说明:本文为作者原创,作者联系地址为:[email protected].由于Java编程中的中文问题是一个老生常谈的问题,在阅读了许多关于Java中文问题解决方法之后,结合作者的编程实践,我发现过去谈的许多方法都不能清晰地说明问题及解决问题,尤其是跨平台

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(九) 之 用 Redis 实现用户在线离线状态消息处理(一)

前言 上一篇中简单讲解了用Redis缓存在线用户逻辑.篇幅也比较小,本篇将详细实现用户的上线下线通知.图片效果转换功能.而且,代码和开发思路都会详细介绍. 效果展示 目前有三个用户,user1,user2,user3.下图会简单展示用户上线,下线的消息推送效果. 图一:用户1登录,此时好友均不在线.(头像为灰色,谷歌浏览器) 图二:用户1登录(打开360浏览器模拟用户1登录),此时谷歌浏览器用户收到该用户上线通知,图标亮起 图三:用户2登录(打开搜狗浏览器模拟用户2登录),此时谷歌浏览器用户收到

Java程序中解决数据库超时与死锁

Java程序中解决数据库超时与死锁 2011-06-07 11:09 佚名 帮考网 字号:T | T Java程序中解决数据库超时与死锁,每个使用关系型数据库的程序都可能遇到数据死锁或不可用的情况,而这些情况需要在代码中编程来解决.本文主要介绍与数据库事务死锁等情况相关的重试逻辑概念. AD: Java程序中解决数据库超时与死锁,每个使用关系型数据库的程序都可能遇到数据死锁或不可用的情况,而这些情况需要在代码中编程来解决;本文主要介绍与数据库事务死锁等情况相关的重试逻辑概念,此外,还会探讨如何避

Java EE 7基于数据库的Apache Shiro配置

上一篇文章我介绍了在Java EE环境中配置Shiro的基本方法, 但是在真正的开发过程中我们基本上不 会使用基于配置文件的用户角色配置, 大多数情况下我们会将用户, 角色和权限存储在数据库中, 然后我们告诉Shiro去数据库中取数据, 这样的配置更灵活且功能更强大. 这样使Shiro能读数据库(或LDAP, 文件系统等)的组件叫做Realm, 可以把Realm看作是一个安全专用的DAO, 下面我详细介绍一下如何配置Realm: (所用到的技术和上一篇文章中的类似, 此外, 我们用到了JPA,

java实现简单的数据库的增删查改,并布局交互界面

一.系统简介 1.1.简介  本系统提供了学生信息管理中常见的基本功能,主要包括管理员.管理员的主要功能有对学生信息进行增加.删除.修改.查找等操作,对信息进行管理,对信息进行修改.查找等操作. 二.功能设计 2.1  需求分析 21世纪是信息化时代,信息化已更快捷更方便为目标来融入各行各业.学校也不例外.当前,我国的学校正在加紧实施信息化建设,其中学生信息管理是相对重要的 一部分. 目前,社会上信息管理系统发展飞快,各个企事业单位都引入了信息化管理软件来管理自己日益增长的各种信息,学生信息管理