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("添加一个游客:Guest@" + 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("Guest@" + 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
: