SpringBootとVueを基盤とした研究業務管理システムの設計と実装

序文

現代の経済の高速発展と絶えず進化する情報技術は、伝統的なデータ管理をソフトウェアによる保存、分類、集中処理へと変革しています。この研究業務管理システムは、そのような環境下で誕生しました。管理者が短時間で大量のデータを処理し、業務効率を向上させることを支援します。このシステムは、成熟したSSMフレームワーク、クロスプラットフォームで大規模な商用ウェブサイトを開発可能なJava言語、そして最も人気のあるRDBMSアプリケーションの一つであるMySQLデータベースを利用して開発されています。ユーザーがオンラインで問題を選択して回答し、評価スコアを確認する機能を実現しています。管理者は辞書管理、業務量管理、研究賞管理、研究論文管理、秘書管理、研究プロジェクト管理、教員管理、管理者管理などの機能を管理できます。この研究業務管理システムは、操作者のニーズに基づいて設計されており、インターフェースは簡潔で美しく、機能モジュールのレイアウトは同種のウェブサイトと一貫しています。システムは基本機能を実現するだけでなく、データセキュリティに関する実用的なソリューションも提供しています。このシステムは、管理者が効率的に業務を処理するだけでなく、データの統合化、標準化、自動化を実現しています。

開発環境

開発言語:Java フレームワーク:springboot JDKバージョン:JDK1.8 サーバー:tomcat7 データベース:mysql5.7(必ず5.7バージョンを使用) データベースツール:Navicat11 開発ソフトウェア:eclipse/myeclipse/idea Mavenパッケージ:Maven3.3.9 ブラウザ:Google Chrome

バックエンドパス:localhost:8080/プロジェクト名/admin/dist/index.html フロントエンドパス:localhost:8080/プロジェクト名/front/dist/index.html(フロントエンドがない場合は入力不要)

管理者アカウント:admin 管理者パスワード:admin

開発技術の概要

Javaの概要

Javaはオブジェクト指向の静的プログラミング言語です。Javaプログラミング言語はマルチスレッドとオブジェクト指向の特徴を持ちます。その特徴は、ソリューションの属性に基づいてソリューションをいくつかの異なるモジュールに分割し、これらのモジュールは閉鎖的で多様性があり、アプリケーションプロセス中に高い独立性を持ちます。Java言語はコンピュータソフトウェア開発プロセスでの使用により、インタラクティブ操作の目的を達成できます。様々な形式の交換を通じて、必要なデータを効果的に処理し、コンピュータソフトウェア開発の制御可能性和可視性を確保できます。Java言語の開発時には、ネットワークインターフェースが保持されており、Javaが保持するデフォルトのネットワークインターフェースは、Webアプリケーションプログラミングに依存するクラスライブラリと一致します。Java開発のアプリケーションをより安定したものにするため、Javaは自動的にプログラム内のガベージを収集し、プログラム内に存在する例外を処理します。Java言語は、日常の開発プロセスで広く使用されている汎用的な基本言語です。その中で、Java言語のコースライブラリ、文、構文規則、およびキーワードは、コンピュータソフトウェアの開発とプログラミングに頻繁に使用されます。 オブジェクト指向プログラミングはJava言語の最も顕著な特徴です。元のインターフェースと補足インターフェース、継承を持ち、同じタイプの単一継承を実現できるだけでなく、インターフェース間の複数継承もサポートし、クラス、インターフェース、インターフェース間、およびクラスとインターフェース間の効果的な通信を実現します。Javaのオブジェクト指向の特性は主に3つの側面に分かれます:継承、ポリモーフィズム、およびカプセル化。カプセル化はJavaの核心であり、すべてのデータ操作をカプセル化できます。ポリモーフィズムは、オブジェクト指向の動作から派生した関連動作を指します。継承は特殊なプログラミングパターンであり、親クラスと子クラスの2つのタイプがあり、これらのタイプの属性は同じ機能と特性を持っています。親クラスの属性特性については、子クラスは継承と最適化を実現できます。

Spring Bootフレームワークの紹介

SpringBootは近年最も人気のあるバックエンド開発フレームワークであり、その誕生は過去のSpringフレームワーク開発における複雑な設定を一変させ、Springアプリケーションの構築と開発を大幅に簡素化しました。SpringBootフレームワークは、Springフレームワークのすべての優れた特性を保持しつつ、特定の設定方法を使用して、開発者がプロジェクト作成時に多くの設定を事前に実行するよう支援します。これにより、開発時には開発者が複雑な設定を過剰に行う必要がなくなります。さらに、SpringBootは多数のフレームワークを統合しており、開発者が依存するjarパッケージを探す必要がなくなり、依存パッケージのバージョン競合問題も解決し、依存パッケージの参照の安定性を向上させ、Springアプリケーションの構築と開発プロセスの簡素化を実現しています。

MySQLデータベース

MySQLはリレーショナルデータベース管理システムであり、Oracleの製品です。MySQLの言語は非構造化されており、ユーザーはデータ上で作業できます。このデータベース管理システムは登場以来、社会から広範な関心を集めています。あらゆる面で、同種のデータベースと比較して、MySQLの利点は非常に目立ちます。その実行速度は速く、適用範囲は広く、データベースのセキュリティ面では独自の特徴を持ちます。言語構造の面では、MySQLの言語はシンプルであり、他のデータベースが長いコードで実装する操作を、MySQLはわずかなコード、あるいは数行で実現できます。総じて、このリレーショナルデータベース管理システムは、開発者がプロジェクトのデータ開発と保存に使用する最良の選択肢となっています。MySQLの機能も多様であり、データ操作やデータベースの作成・保守などがあります。また、このデータベースのデータ共有性は高く、冗長性は低く、拡張が容易です。MySQLはセキュリティ面でも独自の特徴を持ち、ユーザー認証と識別技術を適用し、アクセスとデータを暗号化し、情報の信頼性を確保しています。データベースシステムの機能と強力さの性質を考慮して、このデータベースシステムの設計では主にMySQLを使用してデータ処理を実現しています。Webベースの有料自習室管理システムはMySQLデータベースを使用しており、Webアプリケーションにおいて、MySQLは最良の選択肢です。このシステム全体の開発、構築、実行、および保守に極めて重要な役割を果たしています。

システム機能の詳細

核心コード

package com.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
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 org.springframework.web.multipart.MultipartFile;

import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;

/**
 * ファイルアップロードマッピングテーブル
 */
@RestController
@RequestMapping("file")
@SuppressWarnings({"unchecked","rawtypes"})
public class FileUploadController{
	@Autowired
    private ConfigService configService;
	/**
	 * ファイルアップロード
	 */
	@RequestMapping("/upload")
    @IgnoreAuth
	public R uploadFile(@RequestParam("file") MultipartFile file, String fileType) throws Exception {
		if (file.isEmpty()) {
			throw new EIException("アップロードするファイルは空にできません");
		}
		String fileExtension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
		File path = new File(ResourceUtils.getURL("classpath:static").getPath());
		if(!path.exists()) {
		    path = new File("");
		}
		File uploadDir = new File(path.getAbsolutePath(),"/uploads/");
		if(!uploadDir.exists()) {
		    uploadDir.mkdirs();
		}
		String fileName = new Date().getTime()+"."+fileExtension;
		File destination = new File(uploadDir.getAbsolutePath()+"/"+fileName);
		file.transferTo(destination);
		/**
  		 * IDEAまたはEclipseでプロジェクトを再起動した後、以前にアップロードした画像やファイルが失われた場合、以下の行のコメントを解除してください
   		 * 以下の"D:\\springbootq33sd\\src\\main\\resources\\static\\upload"をローカルプロジェクトのuploadパスに置き換えてください。
 		 * また、プロジェクトパスには中国語、スペースなどの特殊文字を含めないでください
 		 */
//		FileUtils.copyFile(destination, new File("D:\\springbootq33sd\\src\\main\\resources\\static\\upload"+"/"+fileName)); /**パスを変更した後は、この行の先頭の//を削除してください**/

		if(StringUtils.isNotBlank(fileType) && fileType.equals("1")) {
			ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));
			if(configEntity==null) {
				configEntity = new ConfigEntity();
				configEntity.setName("faceFile");
				configEntity.setValue(fileName);
			} else {
				configEntity.setValue(fileName);
			}
			configService.insertOrUpdate(configEntity);
		}
		return R.ok().put("fileName", fileName);
	}
	
	/**
	 * ファイルダウンロード
	 */
	@IgnoreAuth
	@RequestMapping("/download")
	public ResponseEntity<byte[]> downloadFile(@RequestParam String fileName) {
		try {
			File path = new File(ResourceUtils.getURL("classpath:static").getPath());
			if(!path.exists()) {
			    path = new File("");
			}
			File uploadDir = new File(path.getAbsolutePath(),"/uploads/");
			if(!uploadDir.exists()) {
			    uploadDir.mkdirs();
			}
			File file = new File(uploadDir.getAbsolutePath()+"/"+fileName);
			if(file.exists()){
				/*if(!fileService.canRead(file, SessionManager.getSessionUser())){
					getResponse().sendError(403);
				}*/
				HttpHeaders headers = new HttpHeaders();
			    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);    
			    headers.setContentDispositionFormData("attachment", fileName);    
			    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
}
package com.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.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

import com.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.annotation.IgnoreAuth;

import com.entity.DiscussionEntity;
import com.entity.view.DiscussionView;

import com.service.DiscussionService;
import com.service.TokenService;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.CommonUtil;
import java.io.IOException;

/**
 * ディスカッションフォーラム
 * バックエンドインターフェース
 * @author 
 * @email 
 * @date 2023-03-05 11:20:58
 */
@RestController
@RequestMapping("/discussion")
public class DiscussionController {
    @Autowired
    private DiscussionService discussionService;


    


    /**
     * バックエンドリスト
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params,DiscussionEntity discussion,
		HttpServletRequest request){
    	if(!request.getSession().getAttribute("role").toString().equals("管理者")) {
    		discussion.setUserId((Long)request.getSession().getAttribute("userId"));
    	}
        EntityWrapper<DiscussionEntity> ew = new EntityWrapper<DiscussionEntity>();

		PageUtils page = discussionService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, discussion), params), params));

        return R.ok().put("data", page);
    }
    
    /**
     * フロントエンドリスト
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params,DiscussionEntity discussion, 
		HttpServletRequest request){
    	if(!request.getSession().getAttribute("role").toString().equals("管理者")) {
    		discussion.setUserId((Long)request.getSession().getAttribute("userId"));
    	}
        EntityWrapper<DiscussionEntity> ew = new EntityWrapper<DiscussionEntity>();

		PageUtils page = discussionService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, discussion), params), params));
        return R.ok().put("data", page);
    }

	/**
     * リスト
     */
    @IgnoreAuth
    @RequestMapping("/flist")
    public R flist(@RequestParam Map<String, Object> params,DiscussionEntity discussion, HttpServletRequest request){
        EntityWrapper<DiscussionEntity> ew = new EntityWrapper<DiscussionEntity>();
    	PageUtils page = discussionService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, discussion), params), params));
        return R.ok().put("data", page);
    }

	 /**
     * 検索
     */
    @RequestMapping("/search")
    public R search(DiscussionEntity discussion){
        EntityWrapper< DiscussionEntity> ew = new EntityWrapper< DiscussionEntity>();
 		ew.allEq(MPUtil.allEQMapPre( discussion, "discussion")); 
		DiscussionView discussionView =  discussionService.selectView(ew);
		return R.ok("ディスカッションフォーラムの検索に成功").put("data", discussionView);
    }
	
    /**
     * バックエンド詳細
     */
    @RequestMapping("/details/{id}")
    public R details(@PathVariable("id") Long id){
        DiscussionEntity discussion = discussionService.selectById(id);
        return R.ok().put("data", discussion);
    }

    /**
     * フロントエンド詳細
     */
	@IgnoreAuth
    @RequestMapping("/view/{id}")
    public R view(@PathVariable("id") Long id){
        DiscussionEntity discussion = discussionService.selectById(id);
        return R.ok().put("data", discussion);
    }
    
	/**
     * フォーラム詳細
     */
	@IgnoreAuth
    @RequestMapping("/forum/{id}")
    public R forum(@PathVariable("id") String id){
        DiscussionEntity discussion = discussionService.selectById(id);
        getReplies(discussion);
        return R.ok().put("data", discussion);
    }
    
	private DiscussionEntity getReplies(DiscussionEntity discussion) {
    	List<DiscussionEntity> replies = new ArrayList<DiscussionEntity>();
    	replies = discussionService.selectList(new EntityWrapper<DiscussionEntity>().eq("parentId", discussion.getId()));
    	if(replies == null || replies.size()==0) {
    		return null;
    	}
    	discussion.setReplies(replies);
    	for(DiscussionEntity reply : replies) {
    		getReplies(reply);
    	}
    	return discussion;
    }



    /**
     * バックエンド保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody DiscussionEntity discussion, HttpServletRequest request){
    	discussion.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(discussion);
    	discussion.setUserId((Long)request.getSession().getAttribute("userId"));
        discussionService.insert(discussion);
        return R.ok();
    }
    
    /**
     * フロントエンド保存
     */
    @RequestMapping("/add")
    public R add(@RequestBody DiscussionEntity discussion, HttpServletRequest request){
    	discussion.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(discussion);
    	discussion.setUserId((Long)request.getSession().getAttribute("userId"));
        discussionService.insert(discussion);
        return R.ok();
    }



    /**
     * 更新
     */
    @RequestMapping("/modify")
    @Transactional
    public R modify(@RequestBody DiscussionEntity discussion, HttpServletRequest request){
        //ValidatorUtils.validateEntity(discussion);
        discussionService.updateById(discussion);//すべて更新
        return R.ok();
    }


    

    /**
     * 削除
     */
    @RequestMapping("/remove")
    public R remove(@RequestBody Long[] ids){
        discussionService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }
    
    /**
     * リマインダーインターフェース
     */
	@RequestMapping("/reminder/{columnName}/{type}")
	public R reminderCount(@PathVariable("columnName") String columnName, HttpServletRequest request, 
						 @PathVariable("type") String type,@RequestParam Map<String, Object> map) {
		map.put("column", columnName);
		map.put("type", type);
		
		if(type.equals("2")) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Calendar c = Calendar.getInstance();
			Date startDate = null;
			Date endDate = null;
			if(map.get("start")!=null) {
				Integer start = Integer.parseInt(map.get("start").toString());
				c.setTime(new Date()); 
				c.add(Calendar.DAY_OF_MONTH,start);
				startDate = c.getTime();
				map.put("start", sdf.format(startDate));
			}
			if(map.get("end")!=null) {
				Integer end = Integer.parseInt(map.get("end").toString());
				c.setTime(new Date());
				c.add(Calendar.DAY_OF_MONTH,end);
				endDate = c.getTime();
				map.put("end", sdf.format(endDate));
			}
		}
		
		Wrapper<DiscussionEntity> wrapper = new EntityWrapper<DiscussionEntity>();
		if(map.get("start")!=null) {
			wrapper.ge(columnName, map.get("start"));
		}
		if(map.get("end")!=null) {
			wrapper.le(columnName, map.get("end"));
		}


		int count = discussionService.selectCount(wrapper);
		return R.ok().put("count", count);
	}
	









}

システム機能テスト

このシステムはまずローカルサーバー上でインストールとテストが行われ、その後、システムの構造と処理方法の十分な理解、およびシステムの特性の十分な理解に基づき、システムに対してホワイトボックステストとブラックボックステストが実施されました。 ソフトウェアシステムの開発過程全体において、人々は複雑な実際の問題に直面しなければなりません。そのため、ソフトウェアシステムのライフサイクルの各段階でエラーが必然的に発生します。アプリケーションソフトウェアのテストの目的は:エラーが発生し、プログラムを実行するステップを特定することであり、アプリケーションソフトウェアのテストの最も重要な目的は、まだ発生していないエラーを見つけることです。 合理的なテスト計画を策定するために、以下の原則に基づいて測定が開始されました:あらゆるテストは顧客のニーズに遡る必要があります;顧客の使用モデルが確定したら、テスト計画の策定を開始し、コーディング前にソフトウェアテスト全体の計画と策定を行います;パレートの原理を利用し、エラーの89%以上を占める約20%の最もエラーが発生しやすいテンプレートに主に焦点を当て、小規模から段階的に大量のテストを実施し、範囲は主に単一のプログラミングテンプレートのテストから完全に統合されたテンプレートのテストまでです;同時にテスト方法を慎重に設計し、すべてのプログラムロジックをできるだけ完全にカバーし、要件を満たす能力を確保します。

結論

このシステムは、私が調査した他の研究業務管理システムと比較して、以下の利点があります:機能が完全で、将来のプログラム更新が容易、データベース管理が簡単、インターフェースがユーザーフレンドリー、操作が簡単、効率が高く、セキュリティが良好です。 このシステムは技術面で以下の利点があります:第一に、Javaを使用して動的ページを実現し、ソフトウェアシステムに優れた保守性と再利用性を与えています。第二に、このシステムの開発プロセスではSpring Bootフレームワークを使用しており、このフレームワークは表示機能とロジックをより効果的に分離し、モジュールの管理を容易にし、特に大規模プロジェクトの開発に適しています。第三に、バックエンドで使用されるMySQLデータベースシステムは、XML標準のサポートに集中し、拡張性、使いやすさ、および高いセキュリティの利点を備えています。 総じて、ゼロから始まるこの卒業設計は、新たなスタートであり、円満な終了を期待しています。また、この設計が後の自主学習を通じて完璧に近づくことを望んでいます。

タグ: Spring Boot Vue Java MySQL SSM Framework

6月11日 19:45 投稿