代码评审是我们公司的一项流程,由公司组长定期抽查一部分人在办公室里面检查提交的代码.前几天我做了个需求,是关于权限控制的,业务细节就没有必要多说了.在这次抽查中发static静态变量的一些使用错误之处,如果不是公司里面的一些元老指出这个错误,一旦出现问题,就会有很深的隐患在里面
static 关键字 一旦被此修饰符定义,就说明他是 全局性的 独一份的. 我们公司用的是单体项目,也就是页面和后台都是在一起的,项目类型是教务方面的,也就是大学里面的教务管理系统
通常此系统是由两部分组成,一部分是教师和学生端,另一部分是管理端, 但是有些功能是教师端 依赖于管理端,当时我做的权限控制需求就是.
那么我要做的功能是控制教师端 能否使用 管理端的某些功能,因此我肯定是需要从教师端传一个标识过来,我才能知道是管理端还是教师端
第一步 ,从教师端传过来一个标识 暂且称之为 isJsd = “true” 都是String类型的
在管理端的代码中获得了一个从教师端传过来的标识,为了方便使用,我直接 使用了全局,因为页面不止一个 ,需要很多地方用到,当时也是图个方便
if(Boolean.parseBoolean(request.getAttributes("isJsd"))){
GlobalNames.isJsd = true;
}
class GlobalNames{
public static boolean isJsd = flase;
}
当时就是这么个逻辑,然后在很多的 jsp标签上面做判断 显示与不显示
之后问题就来了,当一个 老师进来之后 使用了管理端的功能 ,因为标识就是为true 了, 那么如果管理员进来之后 ,标识 还是 true,这时,管理人员本不该受到教师端权限的控制,但是也像教师端一样被权限控制了,这里有关键点就是 线程 问题,尽管不同的老师,或者管理员进来都会为之开启一条独立的线程,但是静态变量是共享的
下面使用了简单的代码来模拟场景
package com.mrwang.ThreadTest;
/**
* @Author Mr.wang
* @Date 2022/2/20 5:28 下午
*/
class GlobalNames{
public static boolean isJsd = false;
}
public class ThreadDemo {
public static void main(String[] args) {
//老师线程
new Thread(
() ->{
System.out.println("Teacher into!");
GlobalNames.isJsd = true;
//使用功能列表
funList();
System.out.println("Teacher exit!");
}
).start();
//管理员线程
new Thread(
() ->{
System.out.println("Admin into!");
//当前线程 延迟1000毫秒是为了 模拟老师先使用了功能列表
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
//使用功能列表
funList();
System.out.println("Admin exit!");
}
).start();
}
//管理端的功能列表
public static void funList(){
if(GlobalNames.isJsd){
System.out.println("教师 使用管理端受权限控制的功能列表");
}else {
System.out.println("管理员 使用管理端不受权限控制的功能列表");
}
}
}
看似很简单,但是运用到项目中去理解线程的问题不是那么的容易,原先以为不管是什么人进来,所有的代码都是进行隔离的,也就是互不到扰的,当然这里面的机制是复杂的,后面我是使用了Sestion来解决了这个问题,也是一个存标识和取出标识的业务逻辑.Sestion是每次连接都建立了一次会话,所以使用这个来解决是很安全的