SpringBootとVue.jsによるフィットネスジムの個人トレーナー予約システムの設計と実装

技術スタック

バックエンドフレームワーク: SpringBoot

Spring BootはTomcatやJettyなどのサーバーを内蔵しており、追加の設定なしで利用可能です。自動設定機能により、プロジェクトの依存関係に基づいてアプリケーション構成を簡素化します。Spring DataやSpring Securityなどのモジュールが統合されており、開発効率が向上します。

フロントエンドフレームワーク: Vue.js

Vue.jsは仮想DOM技術を中核とし、データ変更時にUIを自動更新します。コンポーネントベースのアーキテクチャにより、柔軟で保守性の高い開発を実現します。

永続層フレームワーク: MyBatisPlus

MyBatis-PlusはMyBatisを拡張したORMツールで、SQL自動生成やCRUD操作を簡素化します。ページネーションや動的クエリ、楽観的ロックなどの機能を提供します。

システムテスト

テスト目的

システムの品質保証と信頼性向上を目的とし、ユーザー視点での機能検証を実施します。要件仕様との整合性を確認し、ユーザビリティの問題を早期に発見します。

機能テスト

ログイン機能テストケース

入力データ 期待結果 実測結果
正しいユーザー/パスワード ログイン成功 システムにアクセス可能
誤ったパスワード 認証エラー パスワード再入力要求
空のユーザー名 バリデーションエラー ユーザー名入力要求

ユーザー管理テストケース

操作 期待結果 実測結果
新規ユーザー追加 リストに表示 正常に登録
重複ユーザー登録 登録拒否 重複エラー表示
ユーザー削除 リストから消失 正常に削除

テスト結論

ブラックボックステストにより全機能を検証し、要件仕様との整合性を確認。ユーザビリティと機能性の両面で要求を満たすことを検証しました。

実装例

認証処理

@PostMapping("/login")
public ResponseEntity<?> authenticate(@RequestParam String userId, 
                                      @RequestParam String passphrase) {
  UserAccount account = accountRepository.findByUserId(userId);
  if (account == null || !account.verifyPassphrase(passphrase)) {
    return ResponseEntity.status(UNAUTHORIZED).build();
  }
  String accessToken = tokenProvider.generateToken(account.getId());
  return ResponseEntity.ok().body(Map.of("accessToken", accessToken));
}

トークン生成

public String createToken(Long accountId, String role) {
  Token existingToken = tokenRepository.findByAccountId(accountId);
  String newTokenValue = generateRandomString(32);
  
  Date expiration = Date.from(Instant.now().plus(1, HOURS));
  if (existingToken != null) {
    existingToken.updateToken(newTokenValue, expiration);
  } else {
    tokenRepository.save(new Token(accountId, role, newTokenValue, expiration));
  }
  return newTokenValue;
}

認証インターセプター

@Component
public class AuthInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
    
    if (handler instanceof HandlerMethod) {
      HandlerMethod method = (HandlerMethod) handler;
      if (method.hasMethodAnnotation(SkipAuth.class)) {
        return true;
      }
    }

    String tokenHeader = request.getHeader("Authorization");
    if (StringUtils.isEmpty(tokenHeader)) {
      response.setStatus(SC_UNAUTHORIZED);
      return false;
    }

    Token token = tokenService.validateToken(tokenHeader);
    if (token != null) {
      request.setAttribute("currentUser", token.getAccountId());
      return true;
    }

    response.setStatus(SC_UNAUTHORIZED);
    return false;
  }
}

データベース設計

トークンテーブル

CREATE TABLE access_tokens (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  account_id BIGINT NOT NULL,
  token_value VARCHAR(200) NOT NULL UNIQUE,
  role VARCHAR(50) NOT NULL,
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

タグ: SpringBoot vue.js MyBatis 微信小程序 UniApp

7月20日 01:42 投稿