[Spring&AWS][5-3]コードの改良


この記事は、本『SpringBootとAWS独自に実現したWebサービス』を学び、整理した記事です.

今日は前回作成したコードを改善します.

[音声ベースの拡張]


1.改善すべき点


IndexControllerからセッション値を取得するには、改善が必要です.
SessionUser user = (SessionUser) httpSession.getAttribute("user");
indexメソッドに加えて、他のコントローラおよびメソッドがセッション値を必要とする場合は、各セッションで直接値を取得する必要があります.このような重複を減らすために、このセクションを変更して、直接メソッドパラメータとしてセッション値を受信できるようにします.

2.改善


✅ LoginUser

@LoginUser文法を生成してみましょう!
  • config/auth/LoginUser.java
  • @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser {
    }
  • @Target(ElementType.PARAMETER)次に、
  • がノイズを生成できる位置を指定する.
  • 2PARAMETERとして指定した場合、メソッドパラメータとして宣言されたオブジェクトでのみ使用できます.
  • @interface
  • このファイルをアシスタントクラスとして指定します.
  • 2LoginUserという文法が生成されたと言える.
  • ✅ LoginUserArgumentResolver

    LoginUserArgumentResolverは、HandlerMethodArgumentResolverインターフェースを実装するクラスである.HandlerMethodArgumentResolverは、条件を満たす方法をHandlerMethodArgumentResolverのインプリメンテーションで指定された値でこの方法パラメータに伝達する機能を有する.
  • config/auth/LoginUserArgumentResolver.java
  • @RequiredArgsConstructor
    @Component
    public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
    
        private final HttpSession httpSession;
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;
            boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());
            return isLoginUserAnnotation && isUserClass;
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
            return httpSession.getAttribute("user");
        }
    }
  • supportsParameter()
  • コントローラメソッドの特定のパラメータがサポートされているかどうかを判断します.
  • において、パラメータに@LoginUser項が添付され、パラメータクラスタイプがSessionUser.classである場合、trueが返される.
  • resolveArgument()
  • パラメータに渡すオブジェクトを生成します.
  • は、セッションからオブジェクトを取得する.
  • ✅ WebConfig


    次に、Springで認識するためにLoginUserArgumentResolverをWebMvcConfiguratorに追加します.
  • config/WebConfig.java
  • @RequiredArgsConstructor
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        private final LoginUserArgumentResolver loginUserArgumentResolver;
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(loginUserArgumentResolver);
        }
    }
    HandlerMethodArgumentResolverは、WebMvcConfigureraddArgumentResolvers()によって常に追加されなければならない.他のHandlerMethodArgumentResolverが必要な場合は、同様に追加できます.

    ✅ IndexController


    すべての設定が完了し、IndexControllerコードで繰り返されるコードを@LoginUserに改善しました.
    public class IndexController {
    
        private final PostService postService;
        
        @GetMapping("/")
        public String index(Model model, @LoginUser SessionUser user) {
            model.addAttribute("post", postService.findAllDesc());
            SessionUser user = (SessionUser) httpSession.getAttribute("user");
            
            if (user != null) {
                model.addAttribute("userName", user.getName());
            }
            return "index";
        }
    }
  • @LoginUser SessionUser user
  • の既存のセッション情報値は、(User) httpSession.getAttribute("user")に改善された.
  • 現在、どのコントローラも@LoginUserでセッション情報を取得できます.
  • 実行結果


    動作が正常であることを確認するためにGoogle Loginを試してみました.

    ログイン成功!

    [セッションストレージとしてデータベースを使用]


    1.改善すべき点


    1)アプリケーションを再実行するとログインの問題が解決する


    これは、セッションがTomcat内蔵メモリに格納されているためであり、デフォルトでは、セッションは実行中のWAS(Web Application Server)メモリに格納および呼び出されます.メモリに格納されているため、アプリケーションの実行時の構造(内蔵のTomcatなど)では常に初期化が行われます.つまり、配布ごとにTomcatが再起動されます.

    2)2台以上のサーバで実行する場合は、Tomcatごとにセッション同期を設定する必要があります。


    「実際の作業」で、次の3つを選択します.
  • 猫セッションを使用
  • は、一般的には、特に設定されていない場合にデフォルトで選択される方法である.
  • の場合、セッションは「猫」(WAS)に格納されます.したがって、2つ以上のWASドライバ環境では、「猫」間でセッションを共有するために追加の設定が必要です.
  • MySQLなどのデータベースをセッションストレージとして使用します.
  • の複数のWAS間の共通セッションを使用する最も簡単な方法です.
  • はあまり設定する必要はありませんが、最終的にはログイン要求ごとにDB IOが発生するため、パフォーマンスに問題が発生する可能性があります.
  • は、通常、ログイン要求があまりないバックグラウンドオフィスおよび内部システムに使用される.
  • Redis、MemcachedなどのメモリDBをセッションストレージとして使用します.
    これは
  • B 2 Cサービスで最もよく使われる方法です.
  • 実際のサービスでは、組み込みRedisではなく外部メモリサーバが必要です.
  • ここでは、セッションストレージとしてデータベースを使用する2つ目の方法を選択します.設定が簡単で、ユーザーが多いサービスではなく、コストを削減するためです.

    2.改善


    登録


    build.ランプに次のコードを追加
    implementation 'org.springframework.session:spring-session-jdbc'

    ✅ h2-console


    アプリケーションを実行してログインテストを行い、h 2-consoleに接続します.

    セッションに対して2つのテーブル(SPRING SESSION、SPRING SESSION ATTRIBUTES)が作成されていることがわかります.JPAはセッションテーブルを自動的に作成するため、他のタスクはありません.

    ログインしたので、セッションを登録しました.

    📌 リファレンス


    ログインテスト中に次のエラーが発生した場合:
    org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [DELETE FROM SPRING_SESSION WHERE EXPIRY_TIME < ?]; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "SPRING_SESSION" not found; SQL statement:
    DELETE FROM SPRING_SESSION WHERE EXPIRY_TIME < ? [42102-200]
    次のコードを追加します.
    spring.session.jdbc.initialize-schema=always
    これにより、セッション・リポジトリがデータベースに置き換えられます.しかし、スプリングを再起動すると、セッションは解除されます.なぜなら、H 2ベースのスプリングが再運転されるとH 2も再起動するからである.AWSに後で配備されると、AWSのデータベースサービスRDSが使用され、セッションは解除されません.
    次のレッスンでNAVERログインの適用を開始します