二进制思维设定权限

背景

之前做权限判定的基本都是通过Boolean类型,但是当权限比较多的时候,此时数据库的字段和持久层的pojo的维护都会比较麻烦,比如如下:

1
2
3
4
5
6
7
8
public final static Long OP_BIND_PHONE = 1L << 0; // 用户绑定手机状态码
public final static Long OP_BIND_EMAIL = 1L << 1; // 用户绑定邮箱
public final static Long OP_BASIC_INFO = 1L << 2;// 用户是否填写基本资料
public final static Long OP_REAL_AUTH = 1L << 3;// 用户是否实名认证
public final static Long OP_VEDIO_AUTH = 1L << 4;// 用户是否视频认证
public final static Long OP_HAS_BIDREQUEST_PROCESS = 1L << 5;// 用户是否有一个借款正在处理流程当中
public final static Long OP_BIND_BANKINFO = 1L << 6;// 用户是否绑定银行卡
public final static Long OP_HAS_MONEYWITHDRAW_PROCESS = 1L << 7;// 用户是否有一个提现申请在处理中

思路

位运算法(非短路的运算符)
&(按位进行‘与’运算)
仅当两个操作数都为1时。输出结果才为1。否则为0
|(按位进行‘或’运算)
仅当两个操作数都为0时,输出的结果才为0
^(按位进行‘异或’运算)
仅当两个操作数不同一时候。对应的输出结果才为1,否则为0
~(按位进行‘取反’运算)
全部的0置为1,1置为0
http://www.runoob.com/java/java-operators.html

扩展
一个值表示多个权限
优点:操作处理比较简单
缺点:数据库查询是否繁琐
移位运算符
1
2
3
4
5
6
7
8
9
10
11
12
java中有三种移位运算符

<< : 左移运算符,num << 1,相当于num乘以2

>> : 右移运算符,num >> 1,相当于num除以2

>>> : 无符号右移,忽略符号位,空位都以0补齐
43210 位数
--------
1010 十进制:10 原始数 number
10100 十进制:20 左移一位 number = number << 1;
1010 十进制:10 右移一位 number = number >> 1;
验证是否可行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.smniuhe.bitStates;

import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.Assert;
import org.junit.Test;

/**
* Desc: 二进制状态码测试
*
* @author niuhesm
* @date 2018/6/10
*/
public class BitStatesTest {


@Test
public void testBidStatesUtils() {

/**
* java中有三种移位运算符
* << : 左移运算符,num << 1,相当于num乘以2
* >> : 右移运算符,num >> 1,相当于num除以2
* >>> : 无符号右移,忽略符号位,空位都以0补齐
* 43210 位数
* --------
* 1010 十进制:10 原始数 number
* 10100 十进制:20 左移一位 number = number << 1;
* 1010 十进制:10 右移一位 number = number >> 1;
*/
System.out.println(BitStatesUtils.OP_BIND_PHONE);
System.out.println(BitStatesUtils.OP_BIND_EMAIL);
System.out.println(BitStatesUtils.OP_BASIC_INFO);
System.out.println(BitStatesUtils.OP_REAL_AUTH);
System.out.println(BitStatesUtils.OP_VEDIO_AUTH);
System.out.println(BitStatesUtils.OP_HAS_BIDREQUEST_PROCESS);


/**
* 0001 1001 2^4+2^3+2^0=25
* 0001 1010 2^4+2^3+2^1=26
* 0000 0010 2^1=2
* 0000 1010 2^3+2^1=10
* &(按位进行‘与’运算)
* 仅当两个操作数都为1时。输出结果才为1。否则为0
* |(按位进行‘或’运算)
* 仅当两个操作数都为0时,输出的结果才为0
* ^(按位进行‘异或’运算)
* 仅当两个操作数不同一时候。对应的输出结果才为1,否则为0
*/
System.out.println("--------------------------------------------");
int value1 = Integer.parseInt("11010", 2);
int value2 = Integer.parseInt("11001", 2);
int value3 = Integer.parseInt("00010", 2);
int value4 = Integer.parseInt("01010", 2);
Integer valueInterger = Integer.valueOf("11010", 2);
String valueBinary = Integer.toBinaryString(value2);
boolean isHaveValue1 = BitStatesUtils.hasState(value1, BitStatesUtils.OP_BIND_EMAIL);
boolean isHaveValue2 = BitStatesUtils.hasState(value2, BitStatesUtils.OP_BIND_EMAIL);
long addState = BitStatesUtils.addState(value1, BitStatesUtils.OP_BIND_EMAIL);
long removeState1 = BitStatesUtils.removeState(addState, BitStatesUtils.OP_BIND_EMAIL);
long removeState2 = BitStatesUtils.removeState(addState, value4);

System.out.println("十进制 int " + value2);
System.out.println("十进制 Interger " + valueInterger);
System.out.println("二进制 String " + valueBinary);
System.out.println("是否存在该状态 " + isHaveValue1);
System.out.println("是否存在该状态 " + isHaveValue2);
System.out.println("添加该状态 " + addState);
System.out.println("移除该状态 " + removeState1);
System.out.println("移除该状态 " + removeState2);
}
}

控制台可知,思路可行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1

2

4

8

16

32

十进制 int 25

十进制 Interger 26

二进制 String 11001

是否存在该状态 true

是否存在该状态 false

添加该状态 26

移除该状态 24

移除该状态 16