Springboot项目监听器失效问题解决

网友投稿 332 2022-12-12


Springboot项目监听器失效问题解决

1.使用springboot项目,现在有个需求是在添加或者修改某个菜单后,菜单会影响角色,角色影响用户。所有受影响的用户在要退出重新登录。

自己实现的思路是这样的:写一个监听器,在收到某个特定的请求后,监听当前所有的用户,如果是受影响的用户,就销毁session,让重新登录。

有了思路后,刚开始上网搜的是怎么在spring boot中添加监听:网上大部分的思路都一样:使用@ServletComponentScan和一个实现了HttpSessionListener的方法就可以了。但是自己按照这个配置了后,一直不起作用。启动时候能debug到这个自定义的监听里面,但是登录后缺不能实现

sessionCreated()

package com.listener;

import javax.servlet.annotation.WebListener;

import javax.servlet.http.HttpSessionEvent;

import javax.servlet.http.HttpSessionListener;

/**

* sessioQRtrQQKxfQn监听器

* @author Administrator

*/

@WebListener

public class SessionListener implements HttpSessionListener{

private int onlineCount = 0;//记录session的数量

/**

* session创建后执行

*/

@Override

public void sessionCreated(HttpSessionEvent se) {

onlineCount++;

System.out.println("【HttpSessionListener监听器】 sessionCreated, onlineCount:" + onlineCount);

se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);

}

/**

* session失效后执行

*/

@Override

public void sessionDestroyed(HttpSessionEvent se) {

if (onlineCount > 0) {

onlineCount--;

}

System.out.println("【HttpSessionListener监听器】 sessionDestroyed, onlineCount:" + onlineCount);

se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);

}

}

还问了群里的大神帮忙看了下,也没问题。刚开始怀疑是 不是登录时候监听的HttpSession,因为实现的是HttpSessionListener,是需要有个发起的动作的.但是自己登录时候也有httpSession。然后在自己的测试类里面进行测试,发现sesionId是存在的:

package com.sq.transportmanage.gateway.api.auth;

import com.alibaba.fastjson.JSONObject;

import com.sq.transportmanage.gateway.api.web.interceptor.AjaxResponse;

import com.sq.transportmanage.gateway.api.web.interceptor.LoginoutListener;

import com.sq.transportmanage.gateway.service.common.shiro.session.RedisSessionDAO;

import com.sq.transportmanage.gateway.service.common.web.RestErrorCode;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.util.StringUtils;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

/**

* @Author fanht

* @Description

* @Date 2020/3/5 下午6:46

* @Version 1.0

*/

@RestController

@RequestMapping("/loginoutController")

public class LoginoutController extends RedisSessionDAO{

private Logger logger = LoggerFactory.getLogger(this.getClass());

@RequestMapping("/userLoginOut")

@ResponseBody

public AjaxResponse userLoginOut(String userIds, HttpSession httpSession,

HttpServletRequest request){

logger.info("httpSessionId" + httpSession.getId() + ",是否是session会话:" +

request.getSession(false));

HttpSession session = request.getSession();

String loginName = (String) session.getAttribute("loginName");

logger.info("loginName:" + loginName);

logger.info("调用退出接口并清除shiro缓存" + userIds);

logger.info("获取监听存取的信息" + JSONObject.toJSONString(LoginoutListener.sessionCount));

try {

String userId[] = StringUtils.tokenizeToStringArray(userIds,",");

for(int i = 0;i

clearRelativeSession(null,null,Integer.valueOf(userId[i]));

}

return AjaxResponse.success(null);

} catch (NumberFormatException e) {

e.printStackTrace();

logger.error("shiro退出异常" + e);

return AjaxResponse.fail(RestErrorCode.UNKNOWN_ERROR);

}

}

@Override

public void clearRelativeSession(Integer permissionId, Integer roleId, Integer userId) {

super.clearRelativeSession(null, null, userId);

}

}

是能够打印sessionId的,也就是说session是存在不为空的。

然后想到我们项目里面用的是shiro,会不会是shiro重写了session机制? 想到这个疑问,又上网搜索,最后通过这个发现是可以的

附上自己的配置:

自定义shiroSessionListener:

package com.sq.transportmanage.gateway.api.web.interceptor;

import com.google.common.collect.Maps;

import com.sq.transportmanage.gateway.service.common.shiro.session.RedisSessionDAO;

import org.apache.shiro.session.Session;

import org.apache.shiro.session.SessionListener;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.util.Map;

import java.util.concurrent.atomic.AtomicInteger;

/**

* @Author fanht

* @Description 监听当前有哪些用户,当收到特定通知后通知退出登录

* @Date 2020/3/5 下午1:48

* @Version 1.0

*/

//@WebListener

public class LoginoutListener extends RedisSessionDAO implements SessionListener {

private Logger logger = LoggerFactory.getLogger(this.getClass());

public static final Map mapUser = Maps.newHashMap();

public final static AtomicInteger sessionCount = new AtomicIntegerQRtrQQKxfQ(0);

@Override

public void onStart(Session session) {

//会话创建,在线人数加一

logger.info("======" + sessionCount);

sessionCount.incrementAndGet();

}

@Override

public void onStop(Session session) {

//会话退出,在线人数减一

sessionCount.decrementAndGet();

}

@Override

public void onExpiration(Session session) {

//会话过期,在线人数减一

sessionCount.decrementAndGet();

}

/**

* 获取在线人数使用

* @return

*/

public AtomicInteger getSessionCount() {

return sessionCount;

}

/*@Override

public void sessionCreated(HttpSessionEvent se) {

onlineCount++;

logger.info("创建start====== ===" + se.getSession().getId());

mapUser.put(se.getSession().getCreationTime(),se.getSession().getId());

}

@Override

public void sessionDestroyed(HttpSessionEvent se) {

logger.info("销毁session=============");

}*/

}

ShiroConfiguration里面添加配置的监听:

@Bean("sessionManager")

public DefaultWebSessionManager sessionManager(RedisSessionDAO sessionDAO, SimpleCookie sessionIdCookie) {

DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

//session存活时间60分钟

sessionManager.setGlobalSessionTimeout(3600000);

sessionManager.setDeleteInvalidSessions(true);

//自定义监听 fht 不能使用@WebListern的 HttpSessionListerner 因为shiro重写了session 2020-03-05

Collection sessionListeners = new ArrayList<>();

sessionListeners.add(sessionListener());

sessionManager.setSessionListeners(sessionListeners);

//sessionManager.setSessionValidationSchedulerEnabled(true);

//sessionManager.setSessionValidationScheduler(sessionValidationScheduler);

sessionManager.setSessionDAO(sessionDAO);

sessionManager.setSessionIdCookieEnabled(true);

sessionManager.setSessionIdCookie(sessionIdCookie);

return sessionManager;

}

/**

* 自定义shiro监听

* @return

*/

@Bean("sessionListener")

public LoginoutListener sessionListener(){

LoginoutListener loginoutListener = new LoginoutListener();

return loginoutListener;

}

然后重新启动,测试 ,发现可以进入到shiro自定义的监听里面了。。。。

clearRelativeSession(null,null,Integer.valueOf(userId[i]));

}

return AjaxResponse.success(null);

} catch (NumberFormatException e) {

e.printStackTrace();

logger.error("shiro退出异常" + e);

return AjaxResponse.fail(RestErrorCode.UNKNOWN_ERROR);

}

}

@Override

public void clearRelativeSession(Integer permissionId, Integer roleId, Integer userId) {

super.clearRelativeSession(null, null, userId);

}

}

是能够打印sessionId的,也就是说session是存在不为空的。

然后想到我们项目里面用的是shiro,会不会是shiro重写了session机制? 想到这个疑问,又上网搜索,最后通过这个发现是可以的

附上自己的配置:

自定义shiroSessionListener:

package com.sq.transportmanage.gateway.api.web.interceptor;

import com.google.common.collect.Maps;

import com.sq.transportmanage.gateway.service.common.shiro.session.RedisSessionDAO;

import org.apache.shiro.session.Session;

import org.apache.shiro.session.SessionListener;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.util.Map;

import java.util.concurrent.atomic.AtomicInteger;

/**

* @Author fanht

* @Description 监听当前有哪些用户,当收到特定通知后通知退出登录

* @Date 2020/3/5 下午1:48

* @Version 1.0

*/

//@WebListener

public class LoginoutListener extends RedisSessionDAO implements SessionListener {

private Logger logger = LoggerFactory.getLogger(this.getClass());

public static final Map mapUser = Maps.newHashMap();

public final static AtomicInteger sessionCount = new AtomicIntegerQRtrQQKxfQ(0);

@Override

public void onStart(Session session) {

//会话创建,在线人数加一

logger.info("======" + sessionCount);

sessionCount.incrementAndGet();

}

@Override

public void onStop(Session session) {

//会话退出,在线人数减一

sessionCount.decrementAndGet();

}

@Override

public void onExpiration(Session session) {

//会话过期,在线人数减一

sessionCount.decrementAndGet();

}

/**

* 获取在线人数使用

* @return

*/

public AtomicInteger getSessionCount() {

return sessionCount;

}

/*@Override

public void sessionCreated(HttpSessionEvent se) {

onlineCount++;

logger.info("创建start====== ===" + se.getSession().getId());

mapUser.put(se.getSession().getCreationTime(),se.getSession().getId());

}

@Override

public void sessionDestroyed(HttpSessionEvent se) {

logger.info("销毁session=============");

}*/

}

ShiroConfiguration里面添加配置的监听:

@Bean("sessionManager")

public DefaultWebSessionManager sessionManager(RedisSessionDAO sessionDAO, SimpleCookie sessionIdCookie) {

DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

//session存活时间60分钟

sessionManager.setGlobalSessionTimeout(3600000);

sessionManager.setDeleteInvalidSessions(true);

//自定义监听 fht 不能使用@WebListern的 HttpSessionListerner 因为shiro重写了session 2020-03-05

Collection sessionListeners = new ArrayList<>();

sessionListeners.add(sessionListener());

sessionManager.setSessionListeners(sessionListeners);

//sessionManager.setSessionValidationSchedulerEnabled(true);

//sessionManager.setSessionValidationScheduler(sessionValidationScheduler);

sessionManager.setSessionDAO(sessionDAO);

sessionManager.setSessionIdCookieEnabled(true);

sessionManager.setSessionIdCookie(sessionIdCookie);

return sessionManager;

}

/**

* 自定义shiro监听

* @return

*/

@Bean("sessionListener")

public LoginoutListener sessionListener(){

LoginoutListener loginoutListener = new LoginoutListener();

return loginoutListener;

}

然后重新启动,测试 ,发现可以进入到shiro自定义的监听里面了。。。。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:spring使用redis操作key
下一篇:Spring Boot Admin Server管理客户端过程详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~