DBMNG数据库管理与应用

才能是来自独创性。独创性是思维、观察、理解和判断的一种独特的方式。
当前位置:首页 > 经验分享 > Java开发

java重写request的getSession方法实现集群session共享

我们在用redis实现session共享的时候,会遇到这样的问题:当一个用户登陆后,可能集群环境下给你分配到另一台服务器,这时候你用request.getSession()获取的session是现在服务器上的session,里面没有你想要的用户信息,然后你又要重新登录,这样是你会同意吗,肯定不行的,所以我们不需要系统自动创建session了,我们来自己写一个实现共享;


首先实现重写的第一步就是使用过滤器,那么我们来配置一个过滤器:他能在目标方法之前对请求进行处理,这样我们就可以用过滤器代替原有的创建session的方法;


<!-- 自定义过滤器:testFilter1 -->   

<filter>  

    <filter-name>sessionFilter</filter-name>  

    <filter-class>util.SessionFilter</filter-class>  

</filter>  

<filter-mapping>  

    <filter-name>sessionFilter</filter-name>  

    <url-pattern>/*</url-pattern>  

</filter-mapping> 

然后我们去创建这个过滤器:


public class SessionFilter implements Filter {

public FilterConfig config;

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

// TODO Auto-generated method stub

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse res=(HttpServletResponse)response;

         req = new SecurityServletRequestWrapper(req, res);

         chain.doFilter(req, res);

}

@Override

public void destroy() {

// TODO Auto-generated method stub

this.config=null;

}

@Override

public void init(FilterConfig filterConfig) throws ServletException {

// TODO Auto-generated method stub

this.config=filterConfig;

}

}

上面的SecurityServletRequestWrapper类就是我们要去重写的类,这里我们要重写HttpServletRequestWrapper中的getSession方法:


public class SecurityServletRequestWrapper extends HttpServletRequestWrapper{

private HttpSession session;

private HttpServletRequest request;

private HttpServletResponse response;

public SecurityServletRequestWrapper(HttpServletRequest request,HttpServletResponse response) {

super(request);

this.request=request;

this.response=response;

}

//重写获取session的方法

public HttpSession getSession() {

return this.getSession(true);

public HttpSession getSession(boolean create) {

if(create){

String id = CookieUtil.getCookieValue(request, "pcxSessionId");

if(StringUtils.isEmpty(id)){

id=UUID.randomUUID().toString();

CookieUtil.setCookie(request, response, "pcxSessionId", id, 60*60);

}

this.session=new DispacherSessionImmpl(this.request,this.response,id);

return this.session;

}else{

return null;

}

    }

}

我们从cookie里面获取session的ID,如果获取不到,那就创建一个id然后保存到session中,这个ID就是新的session的ID;这里有个CookieUtil类它里面两个方法就是从cookie中获取数据和保存数据到cookie;当然其他方法没有实现;


public class CookieUtil {

    public static void setCookie(HttpServletRequest request,

            HttpServletResponse response, String name, String value, int seconds) {

        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value))

            return;

        Cookie cookie = new Cookie(name, value);

        //cookie.setDomain(domain);

        cookie.setMaxAge(seconds); 

        cookie.setPath("/");

        response.setHeader("P3P",

                "CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'");

        response.addCookie(cookie);

    }

    public static String getCookieValue(HttpServletRequest request,String name){

        Cookie cookies[] = request.getCookies();

        if (cookies != null) {

            for (int i = 0; i < cookies.length; i++) {

                if (name.equalsIgnoreCase(cookies[i].getName())) {

                    return cookies[i].getValue();

                }

            }

        }

        return "";

    }

}

然后我们重点看的就是DispacherSessionImmpl类;它实现了HttpSession接口,方法有些多,只说一下修改了的方法,没有说的都是实现原方法就可以;


public class DispacherSessionImmpl implements HttpSession{

private HttpSession session;

private HttpServletRequest request;

private HttpServletResponse response;

private Map<String,Object> sessionMap=null;

private SessionStore sessionStore=new SessionStore();

private String sid;

public DispacherSessionImmpl(){

}

public DispacherSessionImmpl(HttpSession session){

this.session=session;

}

public DispacherSessionImmpl(HttpServletRequest request,HttpServletResponse response,String id){

this.sid=id;

this.request=request;

this.response=response;

}

sessionMap存储放进session中的数据的;


SessionStore是将session数据与redis进行关联实现共享;


@Override

public Object getAttribute(String name) {

// TODO Auto-generated method stub

if(sessionMap==null){

sessionMap=sessionStore.getSession(this.getId());

}

return sessionMap.get(name);

}

这个是获取你存储的信息的;


@Override

public void setAttribute(String name, Object value) {

// TODO Auto-generated method stub

if(sessionMap==null){

sessionMap=sessionStore.getSession(this.getId());

}

this.sessionMap.put(name, value);

sessionStore.saveSession(this.getId(), sessionMap);

}

往session中存储数据的;这里就是redis中存储了;


@Override

public void removeAttribute(String name) {

// TODO Auto-generated method stub

if(sessionMap==null){

sessionMap=sessionStore.getSession(this.getId());

}

sessionMap.remove(name);

sessionStore.removeSession(this.getId());

}

移除数据的方法;


@Override

public void invalidate() {

// TODO Auto-generated method stub

this.sessionMap.clear();

sessionStore.removeSession(this.getId());

}

删除用的;


接下来我们就看一下存储那个类,这里要用到序列化,我们先写一个序列化得到类出来,直接调用就行


public class Hessian2Serialization {

public byte[] serialize(Object obj) throws IOException{  

    if(obj==null) throw new NullPointerException();  

    ByteArrayOutputStream os = new ByteArrayOutputStream();  

    HessianOutput ho = new HessianOutput(os);  

    ho.writeObject(obj);  

    return os.toByteArray();  

}  

public Object deserialize(byte[] by) throws IOException{  

    if(by==null) throw new NullPointerException();  

    ByteArrayInputStream is = new ByteArrayInputStream(by);  

    HessianInput hi = new HessianInput(is);  

    return hi.readObject();  

}  

}

在这里,我们需要hession的jar包,


我们看一下存储:


public class SessionStore {

private Hessian2Serialization h2Serialization=new Hessian2Serialization();

//private RedisUtil redisUtil;

private Jedis jedis=new Jedis("127.0.0.1", 6379);

public Map<String,Object> getSession(String sid){

Map<String,Object> session=new HashMap<String, Object>();

try {

byte[] bs = jedis.get(sid.getBytes());

if(bs!=null){

Object deserialize = h2Serialization.deserialize(bs);

session=(Map<String, Object>) deserialize;

}

} catch (Exception e) {

// TODO: handle exception

}

return session;

}

public void saveSession(String sid,Map<String, Object> session){

try {

byte[] bs = h2Serialization.serialize(session);

jedis.set(sid.getBytes(), bs);

jedis.expire(sid.getBytes(), 3600);//设置过期时间

} catch (Exception e) {

// TODO: handle exception

}

}

public void removeSession(String sid){

try {

jedis.del(sid.getBytes());

} catch (Exception e) {

// TODO: handle exception

}

}

}

到这里,我们就可以去测试了。


本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号