我现在实现得方法
//返回map数据
public Map<String, Object> getAuthentication() {
//获取token
HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader( "token" );
//根据token解析jwt
String Id = JWT.decode(token).getAudience().get(0);
Long userId = Long.valueOf( Id );//获取用户id
//根据返回得用户id查询该用户得详细
user.setId(userId);//传输用户id
User userList = userMapper.selectOne(user);//根据传输得用户id查询用户数据
String unionId = userList.getUnionId();//获取用户的微信unionId
String openid = userList.getOpenid();//获取用户的微信Openid
Map<String , Object> map = new HashMap<>( );
map.put( "userId", userId);//返回用户敏感数据
map.put( "unionId", unionId);//返回用户敏感数据
map.put( "openid", openid);//返回用户敏感数据
return map;
}
但是,有大佬说我这种方法不好每次都要查询数据库,以下是大佬得截图
请问,大佬说得方法是怎么样得,有类似得文档吗或者我应该怎么修改这个方法呢
就事论事,单例(singleton)模式是合理的,内存消耗少(空间优势),响应时间快(时间优势)。
内存消耗少:因为有一个全局的,静态的map,不需要每次登录在内存创建临时map对象并返回,减少内存申请和回收的消耗。
响应时间快:一旦ID在全局静态map中存在,意味着不需要查询数据库,直接更加根据ID取出结构体的value(即user类的对象)即可。
以下为示意代码,不全,能看懂就行。
static map userlist;//全局map, key为用户ID,value为用户信息的类对象
public User getAuthentication() {
//获取token
HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader( "token" );
//根据token解析jwt
User user;
String Id = JWT.decode(token).getAudience().get(0);
if (userlist.containsKey(id))
{
user =userlist.get(id);
}
else
{
Long userId = Long.valueOf( Id );//获取用户id
//根据返回得用户id查询该用户得详细信息,并赋值给user
userlist.put( id, user);
}
return user;
}
估计意思是:你这样用户每次进来都会查询一次数据库,不论之前用户是否查询过。
做一个全局静态map,把查询过得用户放入map,下次用户再进来,
先判断用户是否在map中,存在就不需要查询数据库,不存在再执行查询。
他说的应该是在登录的时候,将用户信息存到单例map里面(Map),应该是这种类型。以后你去当前用户信息的时候可以从map里面直接取出来。
public class test{
// id 和 用户信息对应集合
static Map<Long,UserInfo> mapId = new HashMap();
// token 和 用户信息对应集合
static Map<String,UserInfo> mapToken = new HashMap();
}
登录的时候将用户信息存入集合。。。。以后用户信息可以直接从静态map中取出来
1、单例这个说法不用纠结,目的是为了开辟全局缓存,让缓存的生命周期足够长
2、建立缓存相比数据库访问,可以节省大量的IO操作。
3、如果建立缓存,而目标数据除了查询之外还有其他更新操作,那需要增加缓存更新机制,否则会出现脏读
4、既然是全局缓存,那在多线程更新操作的情况下,需要互斥
5、看应用的用户数量级,如果仅是小规模系统,用户三两个,可以不用增加缓存。
6、再有一点,如果数据库访问框架启用了缓存机制,比如mybatis,启用了二级缓存,那再次建立缓存的必要性就需要根据业务实现情况进行二次确认
另外,自定义的变量名,尽量不要出现表述性的明显歧义,比如list这类的含义指向复数,不合理的名称,对代码执行没有影响,但会降低可读性。
你说的大佬是想释放数据库的压力,这个要看你实际的业务场景是怎么样做选择,要是说你用户量不多,你那用户的三个id是创建好就固定不会变的,你可以是用map进行缓存,如果就一个类里面会调用的话,例如一个controller类,它本身就是 单例的,你这个map写在这个controller类里,不用去考虑什么单不单例的问题,在全局变量定义的时候new一次后不要再new就行了,如果是很多controller都需要调用这个map,你就可以写个类封装下单例,并且因为是多线程调用,所以要考虑线程安全,HashMap是线程不安全的,要使用线程安全的ConcurrentHashMap;若是用户量非常的大,不推荐使用map进行缓存,容易使jvm内存溢出系统崩溃,也就是内存爆满的意思,用户量大的话又想释放数据库的压力,可以使用Redis做缓存服务,Redis缓存查询的数据是肯定比数据库快很多的