服务端基础设施开发----编写自己的session插件【原始稿】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cdnight/article/details/86702749

前言

自定义session插件,将它们统一存放到一个redis中可以有效避免分布式web应用的session不同步的问题。
下面就来尝试写一份session插件—注意,这是初稿来的,可以保证能跑得动,不过性能优化等等需要进一步自行实现的。切记。

添加对应的配置类以及工具类

在WebExt下面添加对应的类,如下图:
在这里插入图片描述
代码分别是:

SessionConf

package net.w2p.WebExt.config;

import com.xxl.conf.core.annotation.XxlConf;

/***
 *
 * 自定义session配置,全系统通用。
 * ****/
public class SessionConf  {
    private static final String VarPrefix="session.";

    public final static String sessionInitKey="___rsession__init";

    /***session assets在request.setAttribute中的key。***/
    public final static String httpReqAttrKey4SessAssets="rsession_assets";

    /***
     *
     * 在redis中保存时候的key的前缀,key的规则是,prefix+sessionId
     * ***/
    @XxlConf(VarPrefix+"storePrefix")
    public String storePrefix="session_";


      /****
     * 该参数是浏览器或者url中作为sessionId的参数的名字,默认为token,而类似的有jsessionid,phpsessionid
     * 等等,可以随便改。
     *
     * ****/
      @XxlConf(VarPrefix+"sessionCookieName")
    public String sessionCookieName="ztoken";

    /***
     * 是否允许url传输sessionid
     * ***/
    @XxlConf(VarPrefix+"allowUrlWithSid")
    public Boolean allowUrlWithSid=true;


    public String getStorePrefix() {
        return storePrefix;
    }

    public void setStorePrefix(String storePrefix) {
        this.storePrefix = storePrefix;
    }



    public String getSessionCookieName() {
        return sessionCookieName;
    }

    public void setSessionCookieName(String sessionCookieName) {
        this.sessionCookieName = sessionCookieName;
    }

    public Boolean getAllowUrlWithSid() {
        return allowUrlWithSid;
    }

    public void setAllowUrlWithSid(Boolean allowUrlWithSid) {
        this.allowUrlWithSid = allowUrlWithSid;
    }
}

SessionRedisCache

package net.w2p.WebExt.Session;

import net.w2p.WebExt.Plugins.RedisPlugin;
import redis.clients.jedis.Jedis;

import java.util.concurrent.ConcurrentHashMap;

public class SessionRedisCache {
    public static final Integer MaxVisitPerSecond=10000;
    public static final ConcurrentHashMap<String, Jedis> cache_redis=new ConcurrentHashMap<>(MaxVisitPerSecond);
}

SessionAssets

package net.w2p.WebExt.Session;

import java.io.Serializable;

/***
 * session 杂项
 * ***/
public class SessionAssets  implements Serializable {
    public String sessionId="";
    public String redisClientId="";
    //--这是redis里面直接存储的key。即 storagePrefix+sessionId
    public String storageKey="";





    public String getStorageKey() {
        return storageKey;
    }

    public void setStorageKey(String storageKey) {
        this.storageKey = storageKey;
    }

    /****
     * 是否需要在response输出时候设定session cookie
     * ***/
    public Boolean needSetSessionCookie=false;

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public String getRedisClientId() {
        return redisClientId;
    }

    public void setRedisClientId(String redisClientId) {
        this.redisClientId = redisClientId;
    }

    public Boolean getNeedSetSessionCookie() {
        return needSetSessionCookie;
    }

    public void setNeedSetSessionCookie(Boolean needSetSessionCookie) {
        this.needSetSessionCookie = needSetSessionCookie;
    }
}

package net.w2p.WebExt.Session;

import net.w2p.WebExt.Plugins.RedisPlugin;
import redis.clients.jedis.Jedis;

import java.util.concurrent.ConcurrentHashMap;

public class SessionRedisCache {
    public static final Integer MaxVisitPerSecond=10000;
    public static final ConcurrentHashMap<String, Jedis> cache_redis=new ConcurrentHashMap<>(MaxVisitPerSecond);
}

RSession

package net.w2p.WebExt.Session;

import com.alibaba.fastjson.JSONObject;
import net.w2p.Shared.common.ValidateUtils;
import net.w2p.WebExt.config.SessionConf;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

public class RSession {
    private HttpServletRequest request;
    private SessionAssets assets=null;
    private Jedis redis=null;
    protected RSession(HttpServletRequest request){
        this.request=request;
        if(!ValidateUtils.isEmpty(request.getAttribute(SessionConf.httpReqAttrKey4SessAssets))){
            assets=(SessionAssets)request.getAttribute(SessionConf.httpReqAttrKey4SessAssets);
            redis= SessionRedisCache.cache_redis.get(assets.redisClientId);
        }

    }
    public String getToken(){

        if(this.assets==null){
            return null;
        }
        return this.assets.sessionId;
    }
    public static RSession getSession(HttpServletRequest request){
        RSession session=new RSession(request);
        return session;
    }
    public  String getVal(String key){

        if(assets==null){
            return null;
        }
        String res=redis.hget(assets.storageKey, key);
        return res;
    }
    public  <T>  T getVal(Class<T> classType,String key){
        String res=getVal(key);
        if(ValidateUtils.isEmpty(res)){
            return null;
        }
        T object = JSONObject.parseObject(res,classType);
        //Json.fromJson(classType, res);
        return object;
    }
    public  <T> List<T> getList(Class<T> classType,String key){
        String res=getVal(key);
        if(ValidateUtils.isEmpty(res)){
            return null;
        }
        List<T> object = JSONObject.parseArray(res,classType);// Json.fromJsonAsList(classType, res);
        return object;
    }
//    public  <T> Map<String,T> getMap(Class<T> classType,String key){
//        String res=getVal(key);
//        if(ValidateUtils.isEmpty(res)){
//            return null;
//        }
//        Map<String,T> object = JSONObject.ma Json.fromJsonAsMap(classType, res);
//        return object;
//    }

    public   void setVal(String key,Object value){
//        Jedis redis= RedisUtil.getJedis();
        if(assets==null){
            return;
        }
        if(value==null){
            return;
        }
        String res="";
        if(value instanceof String){
            res=(String)value;
        }
        else{
            res=JSONObject.toJSONString(value);//.toJson(value);
        }
        redis.hset(assets.storageKey, key, res);
    }

    public boolean remove(String key){
//        Jedis redis= RedisUtil.getJedis();
        if(assets==null){
            return false;
        }
        redis.hdel(assets.storageKey, key);
        return true;
    }

}

SessionInterceptor

package net.w2p.WebExt.Session;

import net.w2p.Shared.common.OpResult;
import net.w2p.Shared.common.RandomStringUtil;
import net.w2p.Shared.common.ValidateUtils;
import net.w2p.Shared.common.WebTools;
import net.w2p.WebExt.Plugins.CryptoPlugin;
import net.w2p.WebExt.Plugins.RedisPlugin;
import net.w2p.WebExt.config.SessionConf;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import redis.clients.jedis.Jedis;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import java.util.UUID;

/**
 * 注意:该文件用于对spring框架进行自定义session处理。
 * 这是一个拦截器,请将其排列为最优先---在所有需要用到session之前的。
 * -_- ps:这个版本的session拦截器是配合spring使用的,她依赖于redis插件,Crypto插件,还有需要有
 * SessionConf对象,所以,配置时候记得传入到到拦截器的构造函数中。
 */
public class SessionInterceptor extends HandlerInterceptorAdapter {
    public static final int SECONDS_30=30;
    public static final int Minutes_ONE=60;
    public static final int Minutes_TWO=120;
    public static final int Minutes_THREE=180;
    public static final int Minutes_FOUR=240;
    public static final int Minutes_FIVE=300;
    public static final int Minutes_30=60*30;
    public static final int HOUR_1=60*60;
    public static final int HOUR_5=60*60*5;
    public static final int HOUR_12=60*60*12;
    public static final int DAY_1=60*60*24;
    public static final int DAY_2=60*60*48;
    public static final int DAY_10=60*60*24*10;
    public static final int DAY_30=60*60*24*30;

    private RedisPlugin redisPlugin;
    private SessionConf sessionConf;
    private CryptoPlugin cryptoPlugin;


    public SessionInterceptor(SessionConf sessionConf,RedisPlugin redisPlugin,CryptoPlugin cryptoPlugin){
        this.redisPlugin=redisPlugin;
        this.cryptoPlugin=cryptoPlugin;
        this.sessionConf=sessionConf;
    }

    /**
     * 得到一个字符串形式的格式化UUID
     * @return
     */
    public static String getStrUUID(){
        Random random = new Random();
        int end = random.nextInt(999);
        //如果不足三位前面补0
        String endStr =String.format("%03d", end);
        return UUID.randomUUID().toString().replace("-", "")+endStr;
    }

    /**
     * 生成加密以后的session id字符串。
     * **/
    private String getSessionId() throws Exception{
        String random_chars= RandomStringUtil.getRandomCode(6, 6);
        String key=getStrUUID()+"_"+(WebTools.getPhpTimeStamp(new Date().getTime()))+"_"+random_chars;
        return this.cryptoPlugin.md5WithKey(key);
    }

    private String getRedisClientPrimaryKey() throws Exception{
        String random_chars= RandomStringUtil.getRandomCode(6, 6);
        String key="redis_client_"+getStrUUID()+(WebTools.getPhpTimeStamp(new Date().getTime()))+"_"+random_chars;
        return this.cryptoPlugin.md5WithKey(key);
    }




    /****检查是否需要发送session id等等,主要是生成sessionAssets***/
    private SessionAssets handleSessionRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {

        System.out.println("进入 session 初始化");

        //--获取redis连接。
        Jedis redisClient=redisPlugin.getJedis();
        String redisClientPk=null;

        redisClientPk= getRedisClientPrimaryKey();
        SessionRedisCache.cache_redis.put(redisClientPk,redisClient);
        SessionAssets assets=new SessionAssets();
        assets.redisClientId=redisClientPk;

        String clientSessionId=null;//--假如有session cookie或者url中带有sid的话,就放到这个变量里面去。
        /***
         *
         * 检查request中是否有session cookie。
         * ***/
        Cookie sessionCookie=null;
        if(request!=null){
            Cookie[] cookies=request.getCookies();
            if(cookies!=null){
                for(Cookie item:cookies){
                    if(item.getName().equals(sessionConf.sessionCookieName)){
                        sessionCookie=item;
                        break;
                    }

                }
            }

            //--如果request没有携带session cookie的话,那么判断是否允许在url上面传递sessionid
            //--可以的话,就获取,不可以就不获取

            if(sessionCookie==null){
                //--好了,从request里面取一个token字段,有的话也默认是。
                if(sessionConf.allowUrlWithSid){

                }
                else{
                    System.out.println("系统不允许从url上面传递sessionid,故此不分析。");
                }
                try{
                    HashMap<String,String> query_params=WebTools.getQueryParam(request.getQueryString());
                    if(query_params.containsKey(sessionConf.sessionCookieName)){
                        String tokenStr=query_params.get(sessionConf.sessionCookieName);
                        if(!ValidateUtils.isEmpty(tokenStr)){
                            clientSessionId =tokenStr;
                        }

                    }
                }
                catch (Exception ed){
                    ed.printStackTrace();
                }
                finally {

                }
            }
            else{
                clientSessionId=sessionCookie.getValue();
            }
        }

        else{
            throw new Exception("request对象为null!!!");
        }



        if(ValidateUtils.isEmpty(clientSessionId)){
            assets.sessionId=getSessionId();
            assets.needSetSessionCookie=true;

        }
        else if(redisClient.exists(sessionConf.storePrefix+clientSessionId)){
            //--在redis中包含有这个sessionid,那么可以认为这次的session是合法的。
            assets.needSetSessionCookie=false;
            assets.sessionId=clientSessionId;

        }
        else{
            //--clientsessionid非空,不过redis里面没有的,这是伪造的sessionid。重新发一个过去。
            assets.needSetSessionCookie=true;
            assets.sessionId=getSessionId();
        }
        //--assets放入request中。
        request.setAttribute(SessionConf.httpReqAttrKey4SessAssets,assets);
        assets.storageKey=sessionConf.storePrefix+assets.sessionId;
        if(assets.needSetSessionCookie){
            setSessionCookie(request,response,assets.sessionId);
        }
        else{
            redisClient.expire(assets.storageKey,DAY_30);
        }


        return assets;
    }


    /***
     * 需要时候,设置session cookie。
     * @param request request对象
     * @param response response 输出对象
     * @param token 需要写入session cookie的sessionid。
     * ***/
    private OpResult setSessionCookie(HttpServletRequest request,HttpServletResponse response,String token) throws Exception{
        OpResult opResult=new OpResult();
        if(ValidateUtils.isEmpty(request.getAttribute(sessionConf.httpReqAttrKey4SessAssets))){
            return opResult.setError("无法确认redis客户端连接!");
        }
        SessionAssets assets=(SessionAssets)request.getAttribute(sessionConf.httpReqAttrKey4SessAssets);
        String redisClientPk=assets.redisClientId;
        Jedis redis=SessionRedisCache.cache_redis.get(redisClientPk);
        StringBuffer url = request.getRequestURL();
        String tempContextUrl = url.delete(url.length() -
                request.getRequestURI().length(), url.length()).append("/").toString();
        if(tempContextUrl.indexOf("localhost")!=-1){
            //--对于cookie来说,这可不是合法domain,换了他。
            tempContextUrl=tempContextUrl.replace("localhost","127.0.0.1");
        }
        tempContextUrl="/";
        String sessionKey = ValidateUtils.isEmpty(token)?getSessionId():token;
        redis.hset(sessionConf.storePrefix+sessionKey, SessionConf.sessionInitKey, "1");
        redis.expire(sessionKey, Minutes_THREE);//--新创建的session 默认时间是3分钟是因为,可能这个sid对方没接收的。。

        String[] resCookieNames=new String[]{sessionConf.sessionCookieName};
        for(String cookieName:resCookieNames){
            Cookie sCookie=new Cookie(cookieName,sessionKey);
//            sessionCookie.setDomain(tempContextUrl);
            sCookie.setPath("/");
            sCookie.setMaxAge(DAY_30);  // 一天
            response.addCookie(sCookie);
            //--额外添加到response头部去
            response.setHeader(sessionConf.sessionCookieName,sessionKey);
        }

        opResult.setSuccess("成功创建");
        return opResult;
    }
    //--释放redis链接资源。
    private void  tryReleaseResource(HttpServletRequest request){
        if(ValidateUtils.isEmpty(request.getAttribute(sessionConf.httpReqAttrKey4SessAssets))){

            return;
        }
        SessionAssets assets=(SessionAssets)request.getAttribute(sessionConf.httpReqAttrKey4SessAssets);
        String redisClientPk=assets.redisClientId;
        Jedis redis=SessionRedisCache.cache_redis.get(redisClientPk);
        if(redis!=null){
            redisPlugin.returnResource(redis);
            SessionRedisCache.cache_redis.remove(assets.redisClientId);
        }

    }


    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {


        /***session begin ***/
        System.out.println("=========【SessionInterceptor】执行 preHandle");
        HttpServletRequest req=(HttpServletRequest)request;
        HttpServletResponse resp=(HttpServletResponse)response;


        System.out.println("开始处理session。");

        //--检查session具体情况。
        handleSessionRequest(request,response);
        return super.preHandle(request, response, handler);

    }

    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           org.springframework.web.servlet.ModelAndView modelAndView)
            throws Exception {
        // 你自己的业务逻辑

        //下面这句话不要动,就这样放着。你在处理你的业务逻辑之后,spring会将你的请求和响应继续往容器传或者往客户端进行传递
        super.postHandle(request, response, handler, modelAndView);
    }

    /***注意,只有在当前拦截器【对于sessionInterceptor来说就是自己了】异常,才无法进入自身的afterCompletion方法,而其他错误即使报错,afterCompletion也是会执行的,不需要过分担心redis链接没有释放的问题。***/
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 你自己的业务逻辑

        System.out.println("=========【SessionInterceptor】执行 afterCompletion");
        try{

            //--三个方面保证可以释放redis资源,一个正常lastFilter释放,一个400,500释放,一个定时任务释放。一个last process释放---在nutz框架内,所以,应该可以了。
//            System.out.println("=============执行到最后一个过滤器,释放资源。注意,并非所有请求都可以进行到这一步的,譬如,400,500就会到相应处理页面了,但是,起码一大部分正常执行的操作会释放redis资源的。");
            System.out.println("释放redis链接。");
            tryReleaseResource((HttpServletRequest)request);

        }
        catch (Exception ed){
            ed.printStackTrace();
        }

        //下面这句话不要动,就这样放着。你在处理你的业务逻辑之后,spring会将你的请求和响应继续往容器传或者往客户端进行传递
        super.afterCompletion(request, response, handler, ex);
    }

}


初始化配置中心的数据

请执行




-- session 相关配置
create or replace function "initSessionConfig"(
in envName varchar
)
returns varchar
as $BODY$
  declare _defaultValues varchar;
  declare _envName varchar;
  declare _appname varchar;
  declare _prefix varchar;
  declare strArrays varchar[];

  declare arrItemLv1 varchar;
  declare tempArrSubItem varchar;
  declare valArrs varchar[];

  declare item_attr varchar;
  declare item_title varchar;
  declare item_val varchar;
  begin

    if envName <> 'test' and envName<> 'ppe' and envName<> 'product' then

      raise notice '环境变量异常,只能为test、ppe以及product其中一个。';
      return '环境变量异常,只能为test、ppe以及product其中一个。';

    end if;

    _appname:='session';
    _prefix:=concat(_appname,'.','');

  _defaultValues:='storePrefix->在redis中保存时候的key的前缀,key的规则是,prefix+sessionId->session_$$' ||
      'sessionCookieName->该参数是浏览器或者url中作为sessionId的参数的名字,默认为ztoken,而类似的有jsessionid,phpsessionid等等,可以随便改。->ztoken$$' ||
      'allowUrlWithSid->是否允许url传输sessionid->true$$'
    ;

  strArrays:=string_to_array(_defaultValues,'$$');
  _envName:=envName;

--   fastdfs.connect_timeout_in_seconds = 5
--     fastdfs.network_timeout_in_seconds = 30
--     fastdfs.charset = UTF-8
--     fastdfs.http_anti_steal_token = false
--     fastdfs.http_secret_key = FastDFS1234567890
--     fastdfs.http_tracker_http_port = 80
--                                        #fastdfs.tracker_servers = tw-server:22122,10.0.11.202:22122,10.0.11.203:22122
--     fastdfs.tracker_servers = localhost:22122
--     fastdfs.visit_url = http://localhost/

--   env     varchar(100) not null,
--     key     varchar(200) not null,
--     appname varchar(100) not null,
--     title   varchar(100) not null,
--     value   varchar(2000) default NULL::character varying,

insert into xxl_conf_project (appname, title) values (_appname,'session全局配置') on conflict ("appname") do nothing;
  <<loop4BigArray>>
    foreach arrItemLv1 in array  strArrays

      loop

        if char_length(arrItemLv1) < 1 then
          raise notice '空字符串无须处理';
          continue ;
        end if;
        valArrs:=string_to_array(arrItemLv1,'->');
        item_attr:=valArrs[1];
        item_title:=valArrs[2];
        item_val:=valArrs[3];

      raise notice '属性名称:%,描述:%,当前值:%',item_attr,item_title,item_val;
      raise notice '开始添加记录';
        insert into xxl_conf_node("env","key","appname","title","value")
        values (_envName,concat(_prefix,item_attr),_appname,item_title,item_val)
        on conflict ("env","key") do nothing ;

    end loop loop4BigArray;


    return envName||'环境下的'||_appName||'配置成功';
  end;

  $BODY$ language plpgsql volatile ;
-- 记住执行下面方法分别添加三个环境下的默认数据。
-- select "initSessionConfig"('test');
-- select "initSessionConfig"('ppe');
-- select "initSessionConfig"('product');


-- session 需要用到的redis单独做一份配置,是全局配置形式的。
create or replace function "initSessionRedisConfig"(
in envName varchar
)
returns varchar
as $BODY$
  declare _defaultValues varchar;
  declare _envName varchar;
  declare _appname varchar;
  declare _prefix varchar;
  declare strArrays varchar[];

  declare arrItemLv1 varchar;
  declare tempArrSubItem varchar;
  declare valArrs varchar[];

  declare item_attr varchar;
  declare item_title varchar;
  declare item_val varchar;
  begin

    if envName <> 'test' and envName<> 'ppe' and envName<> 'product' then

      raise notice '环境变量异常,只能为test、ppe以及product其中一个。';
      return '环境变量异常,只能为test、ppe以及product其中一个。';

    end if;

    _appname:='session';
    _prefix:=concat(_appname,'.redis.','');

  _defaultValues:=
      'auth->验证用的密码,假如没有不需要验证的话,请留空->$$' ||
      'dbIndex->redis默认使用的db的序号【共有12个】->1$$' ||
      'host->redis服务器所在ip地址或者hostname->localhost$$' ||
      'max_active->redis最大激活连接数量->1000$$' ||
      'max_idle->redis控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。->200$$' ||
      'max_wait->等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;->5000$$' ||
      'needAuth->是否需要验证,输入 true 或者 false 两种布尔值->false$$' ||
      'port->redis的服务端口,请填写数字->6379$$' ||
      'test_on_borrow->在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的->true$$' ||
      'timeout->超时时间->10000$$'
    ;

  strArrays:=string_to_array(_defaultValues,'$$');
  _envName:=envName;

--   fastdfs.connect_timeout_in_seconds = 5
--     fastdfs.network_timeout_in_seconds = 30
--     fastdfs.charset = UTF-8
--     fastdfs.http_anti_steal_token = false
--     fastdfs.http_secret_key = FastDFS1234567890
--     fastdfs.http_tracker_http_port = 80
--                                        #fastdfs.tracker_servers = tw-server:22122,10.0.11.202:22122,10.0.11.203:22122
--     fastdfs.tracker_servers = localhost:22122
--     fastdfs.visit_url = http://localhost/

--   env     varchar(100) not null,
--     key     varchar(200) not null,
--     appname varchar(100) not null,
--     title   varchar(100) not null,
--     value   varchar(2000) default NULL::character varying,

insert into xxl_conf_project (appname, title) values (_appname,'session全局配置') on conflict ("appname") do nothing;
  <<loop4BigArray>>
    foreach arrItemLv1 in array  strArrays

      loop

        if char_length(arrItemLv1) < 1 then
          raise notice '空字符串无须处理';
          continue ;
        end if;
        valArrs:=string_to_array(arrItemLv1,'->');
        item_attr:=valArrs[1];
        item_title:=valArrs[2];
        item_val:=valArrs[3];

      raise notice '属性名称:%,描述:%,当前值:%',item_attr,item_title,item_val;
      raise notice '开始添加记录';
        insert into xxl_conf_node("env","key","appname","title","value")
        values (_envName,concat(_prefix,item_attr),_appname,item_title,item_val)
        on conflict ("env","key") do nothing ;

    end loop loop4BigArray;


    return envName||'环境下的'||_appName||'配置成功';
  end;

  $BODY$ language plpgsql volatile ;
-- 记住执行下面方法分别添加三个环境下的默认数据。
-- select "initSessionRedisConfig"('test');
-- select "initSessionRedisConfig"('ppe');
-- select "initSessionRedisConfig"('product');




用工具远程登录配置中心的数据库,直接执行即可:

select "initSessionConfig"('test');
select "initSessionConfig"('ppe');
select "initSessionConfig"('product');
select "initSessionRedisConfig"('test');
select "initSessionRedisConfig"('ppe');
select "initSessionRedisConfig"('product');

使用java代码整合到spring中进行设置

在MasterWebApp中整合。

BeanConfiguration下面添加:

package net.w2p.local.plugins.BeanConfiguration;

import com.xxl.conf.core.XxlConfClient;
import net.w2p.WebExt.Plugins.CryptoPlugin;
import net.w2p.WebExt.Plugins.RedisPlugin;
import net.w2p.WebExt.Session.SessionInterceptor;
import net.w2p.WebExt.config.RedisConf;
import net.w2p.WebExt.config.SessionConf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;

/***
 *
 * 这是自定义的session机制。session将放到redis中。
 * 注意,出于各个子模块网站都需要用同一个session,所以所有网站session存放的redis应该要是同一个才行。
 * 这意味这这里还需要多一个redisConf,请在整合了的redisConf上面添加@Primary 注解,这个redisconf是session专用不是默认的。
 * ***/
@Configuration
public class SessionConfiguration {
    @Bean(name="sessionRedisConf")
    public RedisConf sessionRedisConf(){
        RedisConf redisConf=new RedisConf();
        final String VarPrefix="session.redis.";
        redisConf.needAuth= XxlConfClient.getBoolean(VarPrefix+"needAuth");
        redisConf.auth=XxlConfClient.get(VarPrefix+"auth");
        redisConf.host=XxlConfClient.get(VarPrefix+"host");
        redisConf.port=XxlConfClient.getInt(VarPrefix+"port");
        redisConf.dbIndex=XxlConfClient.getInt(VarPrefix+"dbIndex");
        redisConf.max_active=XxlConfClient.getInt(VarPrefix+"max_active");
        redisConf.max_idle=XxlConfClient.getInt(VarPrefix+"max_idle");
        redisConf.max_wait=XxlConfClient.getInt(VarPrefix+"max_wait");
        redisConf.timeout=XxlConfClient.getInt(VarPrefix+"timeout");
        redisConf.test_on_borrow=XxlConfClient.getBoolean(VarPrefix+"test_on_borrow");
        return redisConf;
    }


    @Bean(name="sessionConf")
    public SessionConf sessionConf(){
        SessionConf conf=new SessionConf();

        return conf;
    }

    @Bean(name="sessRedis")
    @Autowired
    public RedisPlugin sessRedis(@Qualifier("sessionRedisConf") RedisConf conf){

        RedisPlugin plugin=new RedisPlugin(conf);


        return plugin;
    }

    /****初始化 session 拦截器****/
//    @Bean("sessionInterceptor")
//    @Autowired
//    public HandlerInterceptor sessionInterceptor(@Qualifier("cryptoPlugin") CryptoPlugin cryptoPlugin
//            , @Qualifier("sessRedis") RedisPlugin sessRedis
//            , @Qualifier("sessionConf") SessionConf sessionConf
//    ){
//        SessionInterceptor interceptor=new SessionInterceptor(sessionConf,sessRedis,cryptoPlugin);
//
//        return interceptor;
//    }

}

在spring-mvc.xml中注册拦截器

在这里插入图片描述

代码如下:

    <!--拦截器 配置 begin -->
    <mvc:interceptors>
        <!--设定session拦截器-->
        <mvc:interceptor>
            <!-- 进行拦截:/**表示拦截所有controller -->
            <mvc:mapping path="/**" />

            <bean class="net.w2p.WebExt.Session.SessionInterceptor">
                <!--注意,session interceptor构造函数需要几个参数,别忘记了-->
                <constructor-arg name="sessionConf"
                                 ref="sessionConf"></constructor-arg>

                <constructor-arg name="cryptoPlugin"
                                 ref="cryptoPlugin"></constructor-arg>

                <constructor-arg name="redisPlugin"
                                 ref="sessRedis"></constructor-arg>
            </bean>
        </mvc:interceptor>

        <!--设定session拦截器 end-->

    </mvc:interceptors>
    <!--拦截器 配置 end -->

进行测试

启动网站,访问/hello/index.do
然后查看控制台输出:
在这里插入图片描述

在这里插入图片描述
可以看到系统生成的session已经放到cookie里面去了。
一切正常。

结语

自己编写session插件本身是相对来说有难度的,无论是从session机制考虑,还是从整个流程来看都有一定难度,需要慢慢调试整个代码,整个流程。

猜你喜欢

转载自blog.csdn.net/cdnight/article/details/86702749