[MindDiary]ホットスポット2コントローラ・レイヤのビジネス・ロジックの大部分
ユーザーログインAPI機能の作成中に発生した問題.JWTインタフェース、Cookieインタフェース、キャッシュインタフェース、およびHttpServeretResponseクラスを使用する場合、ほとんどのロジックはコントローラレイヤで作成されます.
これらのコードは、エラーを修正したり、コードを修正したりする際に、クラスファイルをチェックしてコードを1つずつ修正する必要があり、mockitoを使用してAPIテストコードを作成する際に困難に直面します.
まず、ログインのロジックは次のとおりです.要求電子メールに一致するユーザをDBからインポートする. DBからインポートしたユーザのハッシュパスワードと要求パスワードが一致するかどうかを比較します. JWTトークンを使用してアクセストークンとリフレッシュトークンを発行します. refresh tokenは、トークンの再配布中にrefresh tokenを検証するためにRedisキャッシュに格納される. access tokenはjsonペイロードであり、refresh tokenはhttponlyクッキーに格納され、返される.
図に示すように、このような構造です.
このようにコードを記述するのは、コントローラ-サービス-レポート階層の役割が混同されているためです.
WTStrategy、CookieStrategy、RedisStrategyインタフェースは、ビジネスロジックの一部であるため、サービス層であると考えられています.そうであれば、UserServiceクラスに移動することなく、コントローラを直接使用できると考えています.
しかし,これらの構造はコードを修正する際に非常に困難であり,クラスに標準を確立することによって問題を解決する.
Controller:API要求と応答クラス
-CookieまたはHttpServeret関連コードはコントローラによって作成されます.(論理をサービス層に移行すると、要求と応答時に何が伝達されるかを特定するのは難しい.これは、DTOを応答主体とし、サーブレットResponseに入れるクッキーを作成したため、コントローラ層に配置したためである.)
サービス:ビジネスロジックの実行
-すべてのビジネスロジックコードがサービスによって生成されます.コントローラは、実際に実行された論理を表示せず、テストコードの作成を簡素化します.なお、以降のコード修正はサービス側をチェックするだけです.
上記の基準に従って、CookieヘッダをHttpServeretResponse応答に入れる部分はControllerクラスである.
データベースの問合せ、パスワードの検証、およびキャッシュにタグを追加する論理セクションは、Serviceクラスで実行されます.(コントローラとサービスはDTOクラスを介して通信する.)
図に示すように、構成は次のとおりです.
これらのコードは、エラーを修正したり、コードを修正したりする際に、クラスファイルをチェックしてコードを1つずつ修正する必要があり、mockitoを使用してAPIテストコードを作成する際に困難に直面します.
まず、ログインのロジックは次のとおりです.
修正前のLoginコード
@PostMapping("/login")
public ResponseEntity login(@RequestBody @Valid UserLoginRequestDTO userLoginRequestDTO,
HttpServletResponse httpServletResponse) {
User user = userService.findByEmail(userLoginRequestDTO.getEmail());
if (user == null) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
if (!passwordEncoder.matches(userLoginRequestDTO.getPassword(), user.getPassword())) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
String accessToken = jwtStrategy.createAccessToken(user.getId(), user.getRole(), user.getEmail());
String refreshToken = jwtStrategy.createRefreshToken(user.getId(), user.getRole(), user.getEmail());
AccessTokenResponseDTO accessTokenResponseDTO = new AccessTokenResponseDTO();
accessTokenResponseDTO.setAccessToken(accessToken);
Cookie cookie = cookieStrategy.createCookie(cookieRefreshTokenKey, refreshToken);
redisStrategy.setValueExpire(refreshToken, user.getEmail(), refreshTokenValidityInSeconds);
httpServletResponse.addCookie(cookie);
return new ResponseEntity(accessTokenResponseDTO, HttpStatus.OK);
}
これはコントローラのほとんどの論理です.図に示すように、このような構造です.
このようにコードを記述するのは、コントローラ-サービス-レポート階層の役割が混同されているためです.
WTStrategy、CookieStrategy、RedisStrategyインタフェースは、ビジネスロジックの一部であるため、サービス層であると考えられています.そうであれば、UserServiceクラスに移動することなく、コントローラを直接使用できると考えています.
しかし,これらの構造はコードを修正する際に非常に困難であり,クラスに標準を確立することによって問題を解決する.
Controller:API要求と応答クラス
-CookieまたはHttpServeret関連コードはコントローラによって作成されます.(論理をサービス層に移行すると、要求と応答時に何が伝達されるかを特定するのは難しい.これは、DTOを応答主体とし、サーブレットResponseに入れるクッキーを作成したため、コントローラ層に配置したためである.)
サービス:ビジネスロジックの実行
-すべてのビジネスロジックコードがサービスによって生成されます.コントローラは、実際に実行された論理を表示せず、テストコードの作成を簡素化します.なお、以降のコード修正はサービス側をチェックするだけです.
修正後のLoginコード
上記の基準に従って、CookieヘッダをHttpServeretResponse応答に入れる部分はControllerクラスである.
データベースの問合せ、パスワードの検証、およびキャッシュにタグを追加する論理セクションは、Serviceクラスで実行されます.(コントローラとサービスはDTOクラスを介して通信する.)
図に示すように、構成は次のとおりです.
//Controller 클래스
@PostMapping("/login")
public ResponseEntity login(@RequestBody @Valid UserLoginRequestDTO userLoginRequestDTO,
HttpServletResponse httpServletResponse) {
TokenResponseDTO tokenResponseDTO = userService.login(userLoginRequestDTO);
if (tokenResponseDTO == null) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
Cookie cookie = tokenResponseDTO.createTokenCookie(cookieStrategy, cookieRefreshTokenKey);
httpServletResponse.addCookie(cookie);
return new ResponseEntity(tokenResponseDTO.createAccessTokenResponseDTO(), HttpStatus.OK);
}
//Service 클래스
@Override
public TokenResponseDTO login(UserLoginRequestDTO userLoginRequestDTO) {
User user = userRepository.findByEmail(userLoginRequestDTO.getEmail());
if (user == null) {
return null;
}
if (!passwordEncoder.matches(userLoginRequestDTO.getPassword(), user.getPassword())) {
return null;
}
TokenResponseDTO tokenResponseDTO = user.createToken(tokenStrategy);
redisStrategy.setValueExpire(tokenResponseDTO.getRefreshToken(), user.getEmail(),
refreshTokenValidityInSeconds);
return tokenResponseDTO;
}
上記のコード修正により、後でコードを修正する難易度を低減できます.しかし、コードには正解がないので、より良いコードを作成することを考慮する必要があるかもしれません.Reference
この問題について([MindDiary]ホットスポット2コントローラ・レイヤのビジネス・ロジックの大部分), 我々は、より多くの情報をここで見つけました https://velog.io/@meme2367/MindDiary-이슈-2-Controller-계층에서-대부분의-비즈니스-로직이-이루어지는-문제テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol