JavaとVueを用いたキャンパス学生アルバイト管理システムの実装

技術スタック

バックエンドフレームワークSpring Boot

Spring Bootは、独立した、本番環境対応のSpringベースのアプリケーションを構築するためのフレームワークです。主な目標は、Springアプリケーションの開発プロセスを簡素化し、すぐに使える機能を提供しながら、コアの強力さと柔軟性を維持することです。

Spring Bootは、自動設定と設定より規約の原則を通じて、開発者が定型コードの記述作業を減らし、アプリケーションの開発を迅速に行う方法を提供します。その設計理念は「規約大于設定」であり、開発者は設定ファイルの記述ではなく、ビジネスロジックの実装に集中できます。

Spring Bootには、Tomcat、Undertow、Jettyなどの組み込みWebサーバーが内蔵されており、アプリケーションを実行可能なJARファイルにパッケージ化することが可能です。この設計により、アプリケーションのデプロイと実行が非常に簡単になり、java -jarコマンドを実行するだけで済みます。同時に、Spring Bootは豊富なActuatorサポートを提供し、アプリケーションに実行時の監視と管理機能を提供できます。

さらに、Spring Bootは豊富なプラグインと拡張メカニズムを提供しており、セキュリティ認証、データアクセス、メッセージキュー、キャッシュなどの様々な機能を簡単に統合できます。Spring Boot Starter依存関係を使用することで、開発者は必要な機能モジュールを簡単に追加し、自動設定を通じて簡単な設定で使用できます。

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

Vue.jsは、ユーザーインターフェース(UI)とシングルページアプリケーション(SPA)を構築するための人気のあるJavaScriptフレームワークです。尤雨溪(ユー・ユーシー)によって2014年に作成され、軽量、学習が容易で柔軟なフレームワークです。

Vue.jsの核心的な強みは、そのリアクティブデータバインディングシステムにあります。これにより、開発者はビューとデータの変化を簡単に管理できます。また、簡潔で直感的なAPIセットを提供し、開発プロセスをより効率的で柔軟にします。

Vueのコンポーネントベースの開発モデルにより、開発者はアプリケーションを小さく独立したコンポーネントに分割し、これらのコンポーネントを組み合わせて完全なアプリケーションを構築できます。このモデルにより、コードの再利用性が高くなり、保守とテストも容易になります。

さらに、Vue.jsは非常に活発なコミュニティを持ち、多くの便利なプラグインやツール、豊富なドキュメントやチュートリアルを提供しています。これにより、Vue.jsの学習と使用がより簡単で楽しいものになります。

コアコード

package com.campus.parttime;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
@MapperScan(basePackages = {"com.campus.parttime.dao"})
public class PartTimeApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(PartTimeApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(PartTimeApplication.class);
    }
}
package com.campus.parttime.controller;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;

import com.campus.parttime.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.campus.parttime.annotation.PublicAccess;
import com.campus.parttime.entity.StudentEntity;
import com.campus.parttime.entity.view.StudentView;

import com.campus.parttime.service.StudentService;
import com.campus.parttime.service.TokenService;
import com.campus.parttime.utils.PageUtils;
import com.campus.parttime.utils.R;
import com.campus.parttime.utils.MPUtil;
import com.campus.parttime.utils.MapUtils;
import com.campus.parttime.utils.CommonUtil;

/**
 * 学生管理コントローラ
 * バックエンドインターフェース
 */
@RestController
@RequestMapping("/student")
public class StudentController {
    @Autowired
    private StudentService studentService;

    @Autowired
    private TokenService tokenService;
    
    /**
     * ログイン
     */
    @PublicAccess
    @RequestMapping(value = "/login")
    public R login(String username, String password, HttpServletRequest request) {
        StudentEntity user = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_number", username));
        if(user == null || !user.getPassword().equals(password)) {
            return R.error("ユーザー名またはパスワードが正しくありません");
        }
        
        String token = tokenService.generateToken(user.getId(), username, "student", "学生");
        return R.ok().put("token", token);
    }

    /**
     * 登録
     */
    @PublicAccess
    @RequestMapping("/register")
    public R register(@RequestBody StudentEntity student){
        StudentEntity existingUser = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_number", student.getStudentNumber()));
        if(existingUser != null) {
            return R.error("この学籍番号は既に登録されています");
        }
        
        Long userId = new Date().getTime();
        student.setId(userId);
        studentService.insert(student);
        return R.ok();
    }

    /**
     * ログアウト
     */
    @RequestMapping("/logout")
    public R logout(HttpServletRequest request) {
        request.getSession().invalidate();
        return R.ok("ログアウト成功");
    }
    
    /**
     * 現在のユーザーセッション情報の取得
     */
    @RequestMapping("/session")
    public R getCurrentUser(HttpServletRequest request){
        Long id = (Long)request.getSession().getAttribute("userId");
        StudentEntity user = studentService.selectById(id);
        return R.ok().put("data", user);
    }
    
    /**
     * パスワードリセット
     */
    @PublicAccess
    @RequestMapping(value = "/resetPassword")
    public R resetPassword(String username, HttpServletRequest request){
        StudentEntity user = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_number", username));
        if(user == null) {
            return R.error("ユーザーが存在しません");
        }
        user.setPassword("123456");
        studentService.updateById(user);
        return R.ok("パスワードは123456にリセットされました");
    }

    /**
     * 管理者向け一覧
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map params, StudentEntity student,
        HttpServletRequest request){
        EntityWrapper<StudentEntity> wrapper = new EntityWrapper<StudentEntity>();

        PageUtils page = studentService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(wrapper, student), params), params));

        return R.ok().put("data", page);
    }
    
    /**
     * 一般ユーザー向け一覧
     */
    @PublicAccess
    @RequestMapping("/list")
    public R list(@RequestParam Map params, StudentEntity student, 
        HttpServletRequest request){
        EntityWrapper<StudentEntity> wrapper = new EntityWrapper<StudentEntity>();

        PageUtils page = studentService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(wrapper, student), params), params));
        return R.ok().put("data", page);
    }

    /**
     * 一覧取得
     */
    @RequestMapping("/lists")
    public R lists(StudentEntity student){
        EntityWrapper<StudentEntity> wrapper = new EntityWrapper<StudentEntity>();
        wrapper.allEq(MPUtil.allEQMapPre(student, "student"));
        return R.ok().put("data", studentService.selectListView(wrapper));
    }

    /**
     * 検索
     */
    @RequestMapping("/search")
    public R search(StudentEntity student){
        EntityWrapper<StudentEntity> wrapper = new EntityWrapper<StudentEntity>();
        wrapper.allEq(MPUtil.allEQMapPre(student, "student"));
        StudentView studentView = studentService.selectView(wrapper);
        return R.ok("学生検索成功").put("data", studentView);
    }
    
    /**
     * 管理者向け詳細
     */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") Long id){
        StudentEntity student = studentService.selectById(id);
        return R.ok().put("data", student);
    }

    /**
     * 一般ユーザー向け詳細
     */
    @PublicAccess
    @RequestMapping("/detail/{id}")
    public R detail(@PathVariable("id") Long id){
        StudentEntity student = studentService.selectById(id);
        return R.ok().put("data", student);
    }
    
    /**
     * 管理者向け保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody StudentEntity student, HttpServletRequest request){
        if(studentService.selectCount(new EntityWrapper<StudentEntity>().eq("student_number", student.getStudentNumber())) > 0) {
            return R.error("この学籍番号は既に存在します");
        }
        
        student.setId(new Date().getTime() + new Double(Math.floor(Math.random() * 1000)).longValue());
        StudentEntity existingUser = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_number", student.getStudentNumber()));
        if(existingUser != null) {
            return R.error("ユーザーが存在します");
        }
        
        student.setId(new Date().getTime());
        studentService.insert(student);
        return R.ok();
    }
    
    /**
     * 一般ユーザー向け保存
     */
    @RequestMapping("/add")
    public R add(@RequestBody StudentEntity student, HttpServletRequest request){
        if(studentService.selectCount(new EntityWrapper<StudentEntity>().eq("student_number", student.getStudentNumber())) > 0) {
            return R.error("この学籍番号は既に存在します");
        }
        
        student.setId(new Date().getTime() + new Double(Math.floor(Math.random() * 1000)).longValue());
        StudentEntity existingUser = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_number", student.getStudentNumber()));
        if(existingUser != null) {
            return R.error("ユーザーが存在します");
        }
        
        student.setId(new Date().getTime());
        studentService.insert(student);
        return R.ok();
    }

    /**
     * 更新
     */
    @RequestMapping("/update")
    @Transactional
    public R update(@RequestBody StudentEntity student, HttpServletRequest request){
        if(studentService.selectCount(new EntityWrapper<StudentEntity>().ne("id", student.getId()).eq("student_number", student.getStudentNumber())) > 0) {
            return R.error("この学籍番号は既に存在します");
        }
        studentService.updateById(student);
        return R.ok();
    }

    /**
     * 削除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids){
        studentService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }
}

システムテスト

システムの問題点を複数の角度からテストして見つけることが、本システムの主なテスト目的です。機能テストを通じてシステムの欠陥を見つけ、修正し、システムに欠陥がないことを確保します。テストプロセス中に、システムが顧客の要件を満たしていることを証明し、問題や不足点を見つけ次第修正します。テスト完了後にテスト結論を導き出します。

システムテストの目的

アルバイト管理システムの開発ライフサイクルにおいて、システムテストは不可欠であり、忍耐力を試されるプロセスです。その重要性は、システム品質と信頼性を保証する最後の関門であり、システム開発プロセス全体の最後のチェックでもあります。

システムテストの主な目的は、ユーザーが使用中に問題が発生しないようにし、ユーザーエクスペリエンスを向上させることです。ユーザーの使用に影響を与えないためには、システムが遭遇する可能性のある問題を多角的、多面的に考慮し、異なるシミュレーションシナリオを通じて欠陥を見つけ、解決する必要があります。テストプロセス中に、システムの品質状況、システム機能が完全かどうか、システムロジックがスムーズかどうかを把握できます。合格したシステムテストプロセスが完了すると、システム品質と使用感が大幅に向上します。テストの目標は、システムが要件仕様書の定義に準拠しているかを検証し、要件仕様書と矛盾する内容を見つけることです。テストプロセス中は、常にユーザーの視点から問題を考慮し、非現実的なシナリオを避け、テスト時間の無駄を防ぎ、問題が発生し、予期される結果と実際の結果が一致しない可能性を引き起こさないようにします。

システム機能テスト

システムの機能モジュールをテストし、クリック、境界値の入力、必須項目と任意項目の検証などの方法を通じて一連のブラックボックステストを実施します。テストケースを作成し、テストケースの内容に基づいてテストを実行し、最終的にテスト結論を導き出します。

ログイン機能テスト方案:システムにログインする必要がある場合、アカウントとパスワードなどの機能ポイントで検証を行います。ユーザーはデータベースに保存されているデータと一致する内容を入力する必要があります。いずれかの入力が間違っている場合、システムは入力エラーを示します。このインターフェースはロール権限にも対応した検証があり、ユーザーのロールのアカウントが管理者ロールでログインすると、エラーが表示されます。ログイン機能テストケースは以下の表の通りです。

システムテスト結論

本システムは主にブラックボックステストを使用し、ユーザーがシステムを使用するシナリオをシミュレートして各機能のテストケースを作成し、テストを実施しました。これにより、システムフローの正確性を確保します。システムテストは不可欠であり、システムをより完璧にし、システムの使用可能性も向上させます。

このシステムをテストする主な目的は、システムの機能モジュールが当初の設計理念を満たしているかを検証し、各機能モジュールのロジックが正しいかを検証することです。このシステムは複雑なロジック処理を必要としないため、ユーザーの操作が容易になります。テストの最終目的もユーザーの使用に焦点を当てています。テストプロセス中に、すべてのシナリオがユーザーの要件を満たす必要があり、要件目標から逸脱してはなりません。問題に直面した場合は、ユーザーの視点から考える必要があります。一連のテストプロセスを経て最終的なテスト結果が得られ、テスト結果から、実装されたシステムが機能とパフォーマンスの両面で設計要件を満たしていることがわかります。

タグ: Java Spring Boot vue.js MyBatis 学生アルバイト管理

6月28日 21:37 投稿