开发者学堂课程【高校精品课-厦门大学 -JavaEE 平台技术:权限的缓存】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/80/detail/15941
权限的缓存
1、设计的代码
代码原来采用 bitmap 现在用 set ,set 的结构
Config 特别是 RedisConfig。
RedisConfig 因为有日期型的变量,在数据库产生日期型,日期型还要变成 json,无论是传到前面还是 json 串到 radius 里面,日期型都要做很特别的处理,日期型做序列化但代码写好了以后可以自己去用,注释写的非常的清楚。
2、dao
现在的目的是把东西从数据库里查出来,然后变成一个 redis 的对象,所以所有代码都在 dao 里面,前面的类图看到是usedao 用来
了 rowdao,rowdao 用 privatedao。
(1)PrivilegeDao
PrivilegeDao.java
package cn.edu.xmu.privilege.dao;
import cn.edu.xmu.ooad.util.SHA256:
import cn.edu.xmu.privilege.mapper.PrivilegeMapper;
import cn.edu.xmu.privilege.model.bo.Privilere:
import cn.edu.xmu.privilege.model.po.PrivilegePo;
import org.springframework.beans.factory.InitialízingBean;
import org.springframework.beans.factory.annotation.Autow
ired:
import org.springframework.beans.factory.annotation.Values
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List; import java.util.Map;
/**
*权ADAO
* @author Ming Qiu
**/
@Repository
public class PrivilegeDao implements InitializingBean {
@Value("${prvilegeservice.initialization}")
private Boolean initialization;
@Autowired
private PrivilegeMapper mapper;
private Map<String, Long> cache = null;
@Override
public void afterPropertiesSet() throws Exception {
List<PrivilegePo> privilegePos= mapper.selectAll();
if (null == cache){
cache =new HashMap<>(privilegePos.size());
}
StringBuffer signature = new StringBuffer();
for (PrivilegePo po : privilegePos){
signature.append(po.getUrl());
signature.append("-");
signature.append(po.getRequestType());
String key =signature.toString();
signature.append("-");
signature.append(po.getId());
String newsignature =SHA256.getSHA256(signature.tostrinp
if (null == po.getSignature() && initialization){
PrivilegePo newPo =new PrivilegePo();
newPo.setId(po.getId());
newPo.setSignature(newSignature);
newPo.setGmtModified(LocalDateTime.now()); mapper.updateByPrimaryKeySelective(newPo);
}else if (po.getSignature() != newsignature){
continue;
}
cache.put(key, po.getid());
}
}
PrivilegeDao 目的是获得权限的对象,因为 redis 非常的金贵所以权限对象一直拿最少的值,不需要权限的名称,只要它的ID,权限对象做了一个缓存,在 java1 视频缓存的结果讲述有多种缓存机制。做缓存不一定是 redis 的事情,在权限的缓存可以看到做到了应用服务器里面,在 pretty dao 里面做了一个属性 map string null。存的 string 是权限的 url 加上它的请求类型,这两个加起来就唯一的定义了一个权限是什么,null 是它的 ID,因为现在不用 bit 直接用一个 ID 的集合来说一个人有多少权限。
如果在前面发出一个请求的时候,其实要的是请求它对应的 ID是什么,所以用 private Map<String, Long> cache = null; 存起来,缓存什么时候来建立用了生命周期里面的 InitializingBean,用的非常常见的一个生命周期的接口,接口是在所有的并属性都设定完成之后在开始工作之前的最后一个并集的生命周期接口,并集的生命周期接口开始工作之前的最后一个方法,所以方法叫 afterPropertiesSet,可以看得出来上面这些属性全部已经设好,全弄完以后方法才会被调用,方法是到数据库里去查所有的权限是什么,所以用 mapper.selectAll 把所有的权限全部查出来,然后如果开启时空查出权限的数量进入 cache。
这里用的是 StringBuffer 的差别因为这是一个循环,循环会有很多,五百个就有五百次所以用了 StringBuffer 去 append 上来,只要在一个循环体里面的时候,都不要用 string 连接,还要用 String Buffer 去做append,所以产生它的签名,产生签名的原因不只是把对象捞起来,原则上在任何时候去读数据的时候都要去较练签名,签名写在那是被较练的,所有在读的时候都要去较练签名,所有在写的时候都要去改签名,较练签名所以把签名去生成一下。
又做了一个参数可以看到上面住进来的,
prvilegeservice.initialization写在 application 的文件中间,是 true 还是 false 把它做到属性里面,然后根据属性值来判断要不要较签名,因为有初始化数据,初始化数据灌进去的时候是没有签名的,因为签名的算法没办法用 sql 语句写出来,所以初始化数据灌进去以后会把值设成 true,在搂这些值的时候如果是 ture 可以看到会把签名反写到数据库里去,所以这是逐步的过程。包括之后如果要换密码加密的算法不是一天之内就全部换掉,而是逐步用到的把签名或者加密的方式换掉。
因为是全搂,所以只要第一次就会把所有权限的签名全部生成,其他的不是全搂的,但是用到才会去。所以基本上在三个 dao 对象里面,如果这些对象有签名,初始化数据没有签名特别是其他模块,有签名的是权限模块还有其他模块,两个模块都有签名,这些签名和加密的东西是需要在使用的过程中慢慢的签上和加密,初始化数据进去没有加密也没有签名,所以就是把签名反写回去,然后把值放到 cache 里面去。
可以看到写的定期生命周期方法中间,当容器在构建并对象的时候,把所有的权限读到内存里面,存的只是它的 url,加上 request 构成一个字符串作为key ,value 是它的 ID,便于去做查询。
/**
*以url ARequestType
获得缓存的Privilege id
*@param url:
访问链接
*@param requestType:
访问类型
* @return id
*/
public Long getPrivIdByKey(String url,Privilege.RequestType requestType)
StringBuffer key = new StringBuffer(url);
key.append("-");
key.append(requestType.getCode());
return this.cache.get(key.toString());
}
提供查询的方法就不用查数据库,直接在内存里面拿出来。这是利用应用服务器来做缓存。
两个问题:
第一缓存在整个应用服务器上会存一份,因为现在默认的是 sin的并,其它的并不行,所以缓存在应用服务器里只会存一份,每台应用服务器里都会存一份,如果布三台,三台服务器里都会存一份。所以存在应用服务器里面的东西有一个前提是不能改,如果想单独存在应用服务器里面,某一台应用服务器改变其他的服务器没改是会出错的。所以这个东西能存在这里的原因是权限不能改的,增加一个权限或者删除一个权限通常来说是程序做了升级,程序不做升级,增加一个权限和删除一个权限是没有任何意义的,所以 API 中心把删除权限和增加权限的两个 API 去掉,没
有意义因为做升级要用数据库的 sql 去完成。
所以升级了以后服务器重新起来,这些缓存全部读上来之后就再不会改。要改需要下次升级。所以有前提不是所有东西都能放到里面。整个过程中间是不会改的,如果要改的也是整个系统来做升级之后才会动的东西,才会放到里面,如果会改就必须放到 redis 里面。