著作権管理-AOP
最近プロジェクトを見直したときに、AOP の権利管理を整理することにしました。
AOP とは何ですか? AOP を使用する理由は何ですか?
AOPとはソフトウェア設計分野におけるアスペクト指向プログラミングのことで、OOPではクラス(class)を基本単位としており、 AOPにおける基本単位はAspect(アスペクト)です。ロジックや責任(トランザクション処理、ログなど)モジュールから共通に呼び出される
コード**をカプセル化することで、システム内のコード**の重複を減らし、モジュール間の結合度を減らし、将来の拡張性や保守性を容易にするのに便利です。
AOP の主構造
実際、AOP は次の 3 種類のことを実行する必要があることを簡単に理解してください。
- Pointcut が介入する箇所、つまり、ビジネス コードが権限検証の実行などの非ビジネス操作である箇所です。
- ビジネスコードの実行前または実行後、いつアドバイスが割り込まれますか。
- アドバイスが割り込んだ後に行うべきこと(権限の確認、ログ記録など)。
Adviceタイプによって処理タイミングが決まり、具体的な処理ロジックはAspectアスペクトクラスに記述されていることがわかります。
メタアノテーション
ここでのメタアノテーションの使用は、主にモジュールごとの権限の配布を目的としています **@Permission**
@Target アノテーションは、アノテーションの使用位置を定義するために使用されます
@Retention アノテーションは、変更されたアノテーションのライフサイクルを示すために使用されます、つまりどの段階まで保持されるか
@Documented は変更されたメモを示します
コード
1. まず依存関係を導入します
<!--aop切面的使用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--切面注解支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
2. アスペクトアスペクトクラス **@Aspect** を定義します。
AOP アスペクト クラスを作成するには、クラスに @Aspect アノテーションを追加するだけです。@Aspect アノテーションはアスペクト クラスを記述するために使用され、アスペクト クラスを定義するときにマークする必要があります。@Component アノテーションは、管理のためにクラスを Spring に渡します。このクラスでアドバイスを実装します。
/**
* 定义切点(切入位置)
* Pointcut后定义哪些bean哪些方法是需要处理的目标
* *.* 代表controller包下所有类和所有方法
* execution(修饰符表达式? 返回值表达式 类路径表达式?方法名表达式(参数表达式)异常表达式?)
* 说明:包名部分的..表示当前包及其所有子包.后面带有?的表示为可选项.参数部分的..表示零个或多个任意参数
*/
@Pointcut("execution(public * cn.stu.scu.controller.*.*(..))")
public void privilege() {
// System.out.println("==>切入");//不执行
}
/**
* 下面是核心业务
* 权限环绕通知
* joinPoint连接点
*/
@ResponseBody
@Around("privilege()") //value=privilege(),对应切点方法
// @Around("execution(public * com.example.demo.controller.*.*(..))") //或者直接写入切入位置
// @Around("execution(* com.example.demo.controller.*.*(..))") //修饰符默认就是public
public Object isAccessMethod(ProceedingJoinPoint joinPoint) throws Throwable {
//增强处理
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();//获取访问的目标方法签名
Method targetMethod = methodSignature.getMethod(); //目标方法
//如果该方法上没有权限注解,直接调用目标方法
if (!targetMethod.isAnnotationPresent(Permission.class)) {
return joinPoint.proceed();//放行,调用目标组件方法
} else {
// 获取自定义注解对象
Permission permission = targetMethod.getAnnotation(Permission.class);
// 根据对象获取注解值
int authorities = permission.authorities();
Object[] args = joinPoint.getArgs();//获取目标方法的参数列表(用户名)
if (args == null) {
throw new RejectedExecutionException("参数错误");
}
String token = ((HttpServletRequest) args[0]).getHeader("X-Token");
String currentUser = token;
// 权限比对
int nowPermission = userService.getPermission(currentUser);
if (nowPermission >= 3) {
throw new SecurityException("请重新登录");
// return "sorry,您不是管理员";
} else if (nowPermission > authorities) {
throw new RejectedExecutionException("权限错误");
// return "sorry,您不是管理员";
} else {
// logger.info("您是管理员");
return joinPoint.proceed();//放行
}
}
}
3. カスタムアノテーション @Permission
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Permission {
// String authorities() default "ADMIN";
int authorities() default 3; //0开发者,1管理员,2普通用户
}
ここで、権限はユーザーデータテーブルで事前に定義されています
以下に、関連するさまざまな知識ポイントをまとめます。
AOP の基本原理
インターセプターとAOPの違い
複数の AOP の実行順序
@Permission - カスタムアノテーション
アノテーション クラスを作成します。これは **@インターフェイスであることに注意して、アノテーションを選択します**
@Target({ElementType.TYPE}) アノテーション
ElementType この列挙型定数は、単純な分類を提供します。アノテーションは Java プログラムに表示される場合があります。(内の構文の位置)これらの定数は、メタアノテーション タイプ (@Target) とともに、アノテーションの正当な位置を書き込む場所を指定します)
@Retention({RetentionPolicy.Runtime}) Annotation
RetentionPolicy この列挙型定数は、さまざまなタイプの保持アノテーション ストラテジを記述します。メタアノテーション( @Retention )を使用して、アノテーションを保持する期間を指定します
@Pointcut アノテーション、
これは、上記の関連するもののエントリ ポイントであるポイントカットを定義するために使用され、イベント トリガーのタイミングを定義し、何をインターセプトする必要があるかを定義します。実行式:例として、
execution(* * com.mutest.controller… . (…))) 式を取り上げます。
- 最初の * 記号の位置: は戻り値のタイプを示し、* はすべてのタイプを示します。
- パッケージ名: インターセプトする必要があるパッケージ名を示します。次の 2 つのピリオドは、現在のパッケージと現在のパッケージのすべてのサブパッケージを示します。この例では、com.mutest.controller パッケージの下のすべてのクラスのメソッドを指します。サブパッケージ。
- 2 番目の * 記号の位置: はクラス名を示し、* はすべてのクラスを示します。
- (…): このアスタリスクはメソッド名を表し、すべてのメソッドを表します。括弧内のパラメータはメソッドのパラメータを表し、2 つのピリオドは任意のパラメータを表します。
Around 拡張処理メソッドを定義する場合、メソッドの最初のパラメーターは ProceedingJoinPoint 型(少なくとも 1 つのパラメーター)である必要があります。