关于在SpringMVC框架中 实现数据库session会话环境变量的功能

前言:
由于SpringMVC框架对于数据库会话处理方面,实现了会话池的功能,以提高数据库的工作效率。因为在数据库申请一个新的会话session确实是比较耗资源。
问题:
但是,这样子,session被公用就带来一个新的问题:数据库的session级的环境变量就可能不可以直接使用了。
首先我们要理解,为什么要用数据库的session的环境变量?用过OracleEBS开发的人都知道,数据库的session环境变量是相互隔离的:不同的session,session级的环境变量不同。举个例子,用户A登录用一个session,可以在session级添加一个环境变量:用户是A。然后,这个会话的所有的DML修改,获取新增人或者更新用户的时候,都可以自动抓到该session的环境变量即可。
可以大大提高开发的工作效率。
但是,由于SpringMVC框架的原因,在jdbc调用数据库的时候,可能session被公用。这样子就很可能出现张冠李戴的问题了。
问题解决:
这个问题也困扰了一点时间。
最后我的解决办法是:
在Service层添加一个AOP初始化对应的会话的环境变量。切面所有的Service的代码,在代码执行之前,先重新初始化该session的环境变量,即可。
需要注意的是,这样子做必须要注意2个问题:
1 Service层必须是启用Transaction事务处理的。因为启用了事务处理,service在调用数据库session的时候,才可以线程安全。经过测试,如果一个事务没执行完毕;另外一个新的sql要做事务的时候,是自动调用一个新的数据库session的!
2 需要注意SpringMVC框架的单例模式而带来的安全性的问题。
最简单初始化环境变量的ID是通过参数,从controller层传到Service层。这样子就没风险了。然后AOP可以直接监控到对应的ID,再自动初始化环境变量。但是,这个办法有一个致命的缺点:就是必须为每个方法添加参数。对于大型系统来说简直是噩梦,要改N个功能。
所以,我用的是另外一个办法:用java.lang.ThreadLocal技术提供线程安全。然后,在AOP运行的时候,可以自动获取到对应的初始化环境变量的ID信息,进行初始化。
具体步骤:
在Controller层,抓取session对应的环境变量ID,对service层进行初始化:

UVS.setLoginId((Long)sess.getAttribute("LOGIN_ID"));

对应的,在Service层添加ThreadLocal技术的成员变量:

    private ThreadLocal<Long> loginIdTL = new ThreadLocal<Long>();

    public Long getLoginId() {
        return this.loginIdTL.get();
    }

    public void setLoginId(Long loginId) {
        this.loginIdTL.set(loginId); 
    }

最后,写一个AOP,切所有的service层的代码,进行环境变量的自动初始化:

    /*** 
     * service层调用之前先自动初始化环境变量
     * @throws Exception 
     */  
    @Before("execution(* com.xinyiglass.springSample.service..*.*(..))")  
    public void alb2bInit(JoinPoint joinPoint) throws Exception{
        Method method = null;
        Object target = null;
        Long loginId=null;
        String methodName = "getLoginId";
        target = joinPoint.getTarget();
        method = getMethodByClassAndName(target.getClass(), methodName);
        if(method!=null){
            loginId=(Long) method.invoke(target);//LogUtil.log("loginId:"+loginId);
            if(loginId!=null&&loginId>0&&loginId!=utilDao.getLoginId()){
                PlsqlRetValue ret =utilDao.alb2bInit(loginId);//初始化环境变量!
                if(ret!=null&&!TypeConvert.isNullValue(ret.getErrbuf())) LogUtil.log("ret:"+ret.toJsonStr());
            }
        }
    }    

完工!

后语:
必须要理解几个知识点。
特别是关于Spring单例模式导致其层的全局变量的问题:
http://blog.sina.com.cn/s/blog_12bf601660102uwq2.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值