shiro 减少用redis实现的自定义SessionDAO的doUpdate的调用次数

本文介绍了一种对Apache Shiro框架中的SimpleSession进行优化的方法,通过增加一个标识位来判断是否需要更新Redis,从而减少不必要的Redis访问,降低网络压力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于SimpleSession lastAccessTime更改后也会调用SessionDao update方法,更新的字段只有LastAccessTime(最后一次访问时间),由于会话失效是由Redis数据过期实现的,这个字段意义不大,为了减少对Redis的访问,降低网络压力,实现自己的Session,在SimpleSession上套一层,增加一个标识位,如果Session除lastAccessTime意外其它字段修改,就标识一下,只有标识为修改的才可以通过doUpdate访问Redis,否则直接返回。


import org.apache.shiro.session.mgt.SimpleSession;  
  
import java.io.Serializable;  
import java.util.Date;  
import java.util.Map;  
  
  
/** 
 * 由于SimpleSession lastAccessTime更改后也会调用SessionDao update方法, 
 * 增加标识位,如果只是更新lastAccessTime SessionDao update方法直接返回 
 */  
public class ShiroSession extends SimpleSession implements Serializable {  
    // 除lastAccessTime以外其他字段发生改变时为true  
    private boolean isChanged;  
  
    public ShiroSession() {  
        super();  
        this.setChanged(true);  
    }  
  
    public ShiroSession(String host) {  
        super(host);  
        this.setChanged(true);  
    }  
  
  
    @Override  
    public void setId(Serializable id) {  
        super.setId(id);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setStopTimestamp(Date stopTimestamp) {  
        super.setStopTimestamp(stopTimestamp);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setExpired(boolean expired) {  
        super.setExpired(expired);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setTimeout(long timeout) {  
        super.setTimeout(timeout);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setHost(String host) {  
        super.setHost(host);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setAttributes(Map<Object, Object> attributes) {  
        super.setAttributes(attributes);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setAttribute(Object key, Object value) {  
        super.setAttribute(key, value);  
        this.setChanged(true);  
    }  
  
    @Override  
    public Object removeAttribute(Object key) {  
        this.setChanged(true);  
        return super.removeAttribute(key);  
    }  
  
    /** 
     * 停止 
     */  
    @Override  
    public void stop() {  
        super.stop();  
        this.setChanged(true);  
    }  
  
    /** 
     * 设置过期 
     */  
    @Override  
    protected void expire() {  
        this.stop();  
        this.setExpired(true);  
    }  
  
    public boolean isChanged() {  
        return isChanged;  
    }  
  
    public void setChanged(boolean isChanged) {  
        this.isChanged = isChanged;  
    }  
  
    @Override  
    public boolean equals(Object obj) {  
        return super.equals(obj);  
    }  
  
    @Override  
    protected boolean onEquals(SimpleSession ss) {  
        return super.onEquals(ss);  
    }  
  
    @Override  
    public int hashCode() {  
        return super.hashCode();  
    }  
  
    @Override  
    public String toString() {  
        return super.toString();  
    }  
}  


import org.apache.commons.lang3.StringUtils;  
import org.apache.shiro.session.Session;  
import org.apache.shiro.session.mgt.SessionContext;  
import org.apache.shiro.session.mgt.SessionFactory;  
import org.apache.shiro.web.session.mgt.DefaultWebSessionContext;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
import javax.servlet.http.HttpServletRequest;  
  
public class ShiroSessionFactory implements SessionFactory {  
    private static final Logger logger = LoggerFactory.getLogger(ShiroSessionFactory.class);  
  
    @Override  
    public Session createSession(SessionContext initData) {  
        ShiroSession session = new ShiroSession();  
        HttpServletRequest request = (HttpServletRequest)initData.get(DefaultWebSessionContext.class.getName() + ".SERVLET_REQUEST");  
        session.setHost(getIpAddress(request));  
        return session;  
    }  
  
    public static String getIpAddress(HttpServletRequest request) {  
        String localIP = "127.0.0.1";  
        String ip = request.getHeader("x-forwarded-for");  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  
}  


在自定义的RedisDAO中的做判断

    /** 
     * 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用 
     */  
    @Override  
    protected void doUpdate(Session session) {  
        //如果会话过期/停止 没必要再更新了  
        try {  
            if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {  
                return;  
            }  

            if (session instanceof ShiroSession) {  
                // 如果没有主要字段(除lastAccessTime以外其他字段)发生改变  
                ShiroSession ss = (ShiroSession) session;  
                if (!ss.isChanged()) {  
                    return;  
                }  
                //更新redis
                ......				
        } catch (Exception e) {  
            logger.warn("更新Session失败", e);  
        }   
    }  


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值