??需求:通過Springboot自定義注解的方式來實現(xiàn)權限和日志模塊的引用(這里側重應用層面作用)。
1晋渺、工程描述
??說明:InAuth.java為要定義的注解接口,AuthAspect.java為切面實現(xiàn),UserAuthEnum.java為用戶權限枚舉氛改,AuthServiceImpl.java為業(yè)務實現(xiàn),Auth.java為對外提供接口(控制層)比伏。
2胜卤、代碼步驟
第一:定義注解接口
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InAuth {
UserAuthEnum[] limit() default {};
}
第二:定義切面
/*****************************************
***說明:這里重點介紹權限,忽略登錄會話等***
*****************************************/
@Aspect
@Component
@Configuration
public class AuthAspect {
@Around("@annotation(inAuth)")
public Object around(ProceedingJoinPoint point, InAuth inAuth) throws Throwable {
UserAuthEnum[] ifAuth = inAuth.limit();// 獲取接口權限
if (ifAuth == null || ifAuth.length == 0) {
return point.proceed(); // 該接口不需要權限
}
int[] limit = {10,20,100}; //將ifAuth轉(zhuǎn)成權限碼
// 1、獲取用戶的會話Token赁项,我們是放在ThreadLocal中的
// 2葛躏、根據(jù)Token會話中取出用戶的權限列表,會話存在redis中
// 3悠菜、上面兩步略舰攒,用戶權限直接用數(shù)據(jù)模擬,我們用戶權限返回的是Set
// 4悔醋、可以加一些邏輯判斷摩窃,返回一些異常情況
Set<Integer> userSet = new HashSet<Integer>();
userSet.add(1000) ;
for (int lt : limit) {
if (userSet.contains(lt)) {
return point.proceed();
}
}
return "no acess auth!";
}
}
第三:定義權限的枚舉類
public enum UserAuthEnum {
A_ADMIN(10), // 管理員權限
A_READ(20), // 只讀權限
A_UPLOAD(30), // 上報權限
A_CHARTS(40), // 報表權限
A_LIST(50);// 名單管理權限
private int code;
private UserAuthEnum(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
}
第四:定義業(yè)務接口(引用自定的注解)
@Service("authService")
public class AuthServiceImpl implements AuthService {
@Override
@InAuth(limit={UserAuthEnum.A_CHARTS,UserAuthEnum.A_ADMIN}) //要么有管理員權限,要么有charts權限可以訪問
public String testAuth() {
return "---auth test---";
}
}
第五:定義切面
public interface EacProxy {
public String query(); //可以返回復雜對象類型
}
第六:定義測試接口
@RestController
public class Auth {
@Autowired
private AuthService authService ;
@RequestMapping("/auth")
public String sayHello() throws Exception {
return authService.testAuth() ;
}
}
??注解讓代碼代碼世界更簡潔、更簡單了猾愿,但也存在缺點鹦聪,讓異常定位更麻煩,讓理解spring執(zhí)行原理更復雜(感覺從spring原理慢慢修理才是正道)蒂秘。