💎
@AuthenticationPrincipalをラップしたい
どうしてそう思ったか
ユーザー情報などを管理するDBが以下のようになっていました。
この構造は、1人のユーザーがroleを複数持つ場合のDB構造なんですが、この構造が1人のユーザーに対して1個のロールしか割り当てられない場合でも使われていました。
そして、ロールごとにユーザー情報として別々の情報を持つようになっていたため、最終的に以下のようなDB構造になっていました。
この時、AuthenticationPrincipalをそのまま使うと、以下のようなコードがロールごとに大量に書かれることになります。
@GetMapping(value = "")
public String hoge(@AuthenticationPrincipal User user) {
String name = user.getRole1User().role1UserName;
}
このuser.getRole1Userの部分を毎回書くのが面倒なため、AuthenticationPrincipalをラップして一発でRole1Userのエンティティを取れるようにすることが目的です。
実装
まずAuthenticationPrincipalをラップしたアノテーションを作成します。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@AuthenticationPrincipal(expression = "@role1UserPrincipalExtractor.extract(#this)")
public @interface Role1UserPrincipal {
}
次に実際に処理を行うクラスを作成します。
@Component("role1UserPrincipalExtractor")
public class Role1UserPrincipalExtractor {
public KTGeneralDetail extract(User user) {
return user.getRole1User();
}
}
これでメソッドを次のように書き換えれば、一発でrole1Userが持って来れるようになります。
@GetMapping(value = "")
public String hoge(@Role1UserPrincipal Role1User role1User) {
String name = role1User.role1UserName;
}
どうしてこれで実装ができているのか
AuthenticationPrincipalの引数のexpressionには SpEL式 を記述することができます。
以下のコードは、role1UserPrincipalExtractorというBeanの、extractメソッドを呼び出す、という処理になっています。(#thisはAuthenticationPrincipalで取得されたUserのエンティティになります。)
@role1UserPrincipalExtractor.extract(#this)
よって、Role1UserPrincipalExtractor.extractメソッドが呼び出され、role1Userを取得することができます。
Discussion