技術アーキテクチャ概要
本システムは、以下の技術スタックを採用しています:
- バックエンド: SpringBootフレームワーク
- フロントエンド: Vue.js
- モバイルアプリ: UniApp(微信小程序)
- データベース: MySQL
- ORM: MyBatis-Plus
SpringBootフレームワークの特徴
SpringBootは組み込みTomcatサーバーを提供し、自動設定機能により開発効率を大幅に向上させます。依存関係に基づいてアプリケーションを自動的に設定し、手動設定の手間を削減します。Spring Data、Spring Security、Spring Cloudなどの豊富な機能を統合しており、高速なアプリケーション構築を実現します。
Vue.jsの利点
Vue.jsは仮想DOM技術を採用し、効率的なDOM操作を実現します。リアクティブデータバインディングにより、データ変更時のUI更新が自動化されます。コンポーネントベースのアーキテクチャにより、保守性と再利用性が向上します。
MyBatis-Plusの機能
MyBatis-PlusはMyBatisを拡張したORMフレームワークです。コードジェネレーターによりエンティティクラス、Mapperインターフェース、XMLマッピングファイルを自動生成します。ページネーション、動的クエリ、楽観ロックなどの機能を提供し、データアクセス層の開発を効率化します。
システムテスト
テスト目的
システムテストは品質保証の最終段階であり、ユーザー体験を確保する重要なプロセスです。多角的なテストにより、システムの欠陥を特定し修正します。ユーザーの視点に立ち、実用的なシナリオを考慮してテストを実施します。
機能テスト
ログイン機能テスト
| 入力データ | 期待結果 | 実際結果 | 分析 |
|---|---|---|---|
| ユーザー名: admin, パスワード: 123456, 検証コード: 正しい | ログイン成功 | システムログイン成功 | 期待通り |
| ユーザー名: admin, パスワード: wrongpass, 検証コード: 正しい | パスワードエラー | パスワードが間違っています | 期待通り |
| ユーザー名: empty, パスワード: 123456, 検証コード: 正しい | ユーザー名必須エラー | ユーザー名を入力してください | 期待通り |
ユーザー管理機能テスト
| 操作 | 期待結果 | 実際結果 | 分析 |
|---|---|---|---|
| 新規ユーザー追加 | ユーザーリストに表示 | ユーザーが正常に追加 | 期待通り |
| ユーザー情報編集 | 情報が更新される | 変更が反映される | 期待通り |
| 重複ユーザー名追加 | 重複エラー | ユーザー名が既に存在します | 期待通り |
実装コード例
@RestController
@RequestMapping("/api/auth")
public class AuthenticationController {
@Autowired
private AuthenticationService authService;
@PostMapping("/authenticate")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
try {
UserAccount user = authService.verifyCredentials(loginRequest.getUsername(), loginRequest.getPassword());
if (user == null) {
return ResponseEntity.status(401)
.body(new ApiResponse("認証情報が正しくありません"));
}
String jwtToken = authService.generateJwtToken(user);
return ResponseEntity.ok(new AuthResponse(jwtToken, user.getRole()));
} catch (Exception e) {
return ResponseEntity.status(500)
.body(new ApiResponse("認証処理中にエラーが発生しました"));
}
}
}
@Service
public class JwtTokenService {
private static final long EXPIRATION_TIME = 3600000; // 1時間
public String generateJwtToken(UserAccount user) {
Date expiryDate = new Date(System.currentTimeMillis() + EXPIRATION_TIME);
return Jwts.builder()
.setSubject(user.getUsername())
.claim("userId", user.getId())
.claim("role", user.getRole())
.setIssuedAt(new Date())
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, "secret-key")
.compact();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey("secret-key").parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
}
データベース設計
-- ユーザーテーブル
CREATE TABLE user_accounts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
user_role ENUM('OWNER', 'RENTER', 'ADMIN') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 物件テーブル
CREATE TABLE rental_properties (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
owner_id BIGINT NOT NULL,
property_name VARCHAR(100) NOT NULL,
address TEXT NOT NULL,
monthly_rent DECIMAL(10,2) NOT NULL,
description TEXT,
status ENUM('AVAILABLE', 'RENTED') DEFAULT 'AVAILABLE',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (owner_id) REFERENCES user_accounts(id)
);
-- 予約テーブル
CREATE TABLE rental_reservations (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
property_id BIGINT NOT NULL,
renter_id BIGINT NOT NULL,
reservation_date DATETIME NOT NULL,
status ENUM('PENDING', 'CONFIRMED', 'CANCELLED') DEFAULT 'PENDING',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (property_id) REFERENCES rental_properties(id),
FOREIGN KEY (renter_id) REFERENCES user_accounts(id)
);