Java与面向对象设计的大作业,实验报告docx用pandoc转成了md。
【实验目的】
掌握Java与面向对象基本原理和概念。
掌握Java与面向对象编程思想和主流技术或框架。
掌握基于Java开发完整软件Demo,并能演示。
【实验装备】
个人笔记本,idea,JDK环境,mysql,navicat, vue,git等。
【实验内容】
基于所选择的主题方向,调研、分析和设计3-5个核心场景(模块)作为研究对象,根据掌握的Java和相关知识,实现相对完整的WebApp应用。以Java为基础,可以自由选择搭配其它技术和框架,输出详细的设计文档、项目源代码和可运行的Demo视频。
【实验要求】
按实验内容输出详细设计、实现、运行关键截图,要求行文整洁、紧凑、顺畅。
代码以团队gitee形式提交,视频以百度网盘形式提交,可限时公开访问。
团队Gitee: JavaGroup (gitee.com)
本项目代码: JavaGroup/project (gitee.com)
视频百度网盘:链接 提取码:2s45
实验报告需要交代团队成员分工,以及自己承担的任务(要求任务量合理,鼓励交叉参与);个人报告要求完整,团队成果部分精炼描述,侧重个人为主部分加以详细描述。
【实验分析】
输出实验分析总结和心得体会。
【参考资料】
参考教程:带你从0搭建一个Springboot+vue前后端分离项目,真的很简单!_哔哩哔哩_bilibili
参考资料:
1. 一个 Vue 3 UI 框架 | Element Plus(element-plus.org)
2. Vue.js 教程 | Vue.js 中文文档(cn.vuejs.org)
3. SpringBoot+Vue个人健康管理系统Java毕业设计_哔哩哔哩_bilibili (主要参考要实现什么功能)
这个源代码上传至:JavaGroup/health_management(gitee.com)
【目录】
一.背景分析
经过了解和学习,为实现健康管理系统,我们采取了一种现代化的前后端分离架构,以下是我们选用的关键技术和工具:
1.前端技术
Vue.js:作为一个渐进式JavaScript框架,Vue.js被用于创建高效、灵活的用户界面。它的组件化架构让我们能够重用代码并加快开发速度。
Element-Plus:基于Vue3的桌面端组件库,提供了一套丰富的UI组件,帮助我们在保持界面美观的同时,减少了开发和设计的工作量。
2.后端技术
SpringBoot:简化了基于Spring的应用开发过程,使得我们能够快速搭建和部署微服务。SpringBoot自动配置的特性大幅度减轻了配置工作,让我们能够专注于业务逻辑的实现。
MyBatisPlus:它是一个支持定制SQL、存储过程以及高级映射的持久层框架。MyBatisPlus消除了几乎所有的JDBC代码,并手动设置参数以及获取结果集。通过简单的XML或注解,我们能够将接口映射成数据库中的记录。
Lombok:一个Java库,通过使用注解,能够自动化生成模板代码,如getters、setters、constructors等。Lombok极大地简化了我们的Java代码,使得它更加简洁易读。
3.数据库管理
MySQL:我们选择MySQL作为后端数据库,借助其强大和广泛支持的特性来存储应用数据。
Navicat:作为一款强大的数据库管理工具,Navicat让数据库的管理变得轻松便捷。它不仅支持MySQL,还支持大量其它数据库,提供直观的GUI方便进行数据管理、开发和维护。
二.需求分析
我们计划实现3-5个主核心功能,参考健康管理系统|拾果健康(sghealth.cn) 及网上找到一些健康管理系统找到大概想实现的功能。在写好vue+springboot基本框架,搭建好跨域配置,写好依赖,写好基本的响应码,数据库配置,引入数据库表格写好mapper,controller,entity等等后,决定按功能分工,各自实现负责的功能的前端+后端。虽然前后端分离,但是功能一个人同时写,不断加功能完善项目,同时锻炼写前端和后端的能力。
三.系统设计
下面是我们当时设计的方案:
系统:管理员、用户
登录界面参考:
首页
健康信息上传
商品推荐
运动知识
评估与建议
随后进行抽签,选择各自要实现的功能。抽签决定好后先写好头部和侧边栏,新建不同的.vue和路由,之后每个人写自己的.vue并根据需要补充后端.java即可。
四.系统实现
团队成果:
采用前端部分使用Vue.js和Element-Plus来构建用户界面,后端使用SpringBoot和MyBatisPlus进行业务逻辑的处理和数据持久化,同时使用Navicat来管理MySQL数据库,并借助Lombok简化Java代码的开发。
个人报告:
我的任务:准备阶段学习git,gitee的使用和navicat,idea的配置并创建gitee团队;正式写项目时负责4个小功能,分别是登录、注册、设置、健康问答。并简单改动一下其他部分的细节。最后整理项目时导出sql文件,写项目README。
我的gitee:Zhuyuehan (strangersinsist) -Gitee
1).准备阶段:
参照JavaGroup/health_management(gitee.com) 学会怎么运行前端后端数据库,git的一些操作。
2).正式项目:
1.登录 前端Login.vue
,并在health_manage_vue\src\router\index.js设置路由,点击按钮触发js,通过post与后端进行交互。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 <script> import request from "@/utils/request"; export default { name: "Login", components: {User,Lock}, data(){ return { form:{}, rules:{ username:[ {required:true,message:"请输入用户名",trigger:'blur'}, ], password:[ {required:true,message:"请输入密码",trigger:'blur'}, ], } } }, methods:{ login(){ request.post("/api/user/login",this.form).then(res =>{ console.log(res); if(res.code == '200'){ this.$message({ type: "success", message:"登录成功" }) //改一下试图存缓存 sessionStorage.setItem("user", JSON.stringify(res.data)); this.$router.push("/") }else{ this.$message({ type:"error", message:"用户名或密码错误" }) } }) } } } import { User,Lock, } from '@element-plus/icons-vue' </script> <template> <div class="login-container"> <div class="login-card"> <h1 class="login-title">欢迎登录</h1> <el-form :model="form" :rules="rules" class="login-form" ref="loginForm" size="large"> <el-form-item prop="username" class="form-item"> <el-icon class="icon"><User /></el-icon> <el-input v-model="form.username" placeholder="用户名:" class="input-field"></el-input> </el-form-item> <el-form-item prop="password" class="form-item"> <el-icon class="icon"><Lock /></el-icon> <el-input type="password" v-model="form.password" placeholder="密码:" class="input-field" show-password></el-input> </el-form-item> <div class="form-actions"> <el-button class="action-button" @click="login">登录</el-button> <el-button class="action-button" @click="this.$router.push('/register')">注册</el-button> </div> </el-form> </div> </div> </template> <style scoped> //这部分为了优化界面写的比较多,省略,详细看gitee代码 </style>
后端和队友共用的Result.java,User.java,UserMapper.java和UserController.java,用于获取数据库信息及返回数据给前端,我在队友写的代码基础上增加了需要的部分UserController.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.example.demo.controller; import … @RestController @RequestMapping("/user") public class UserController { @Resource UserMapper userMapper; @PostMapping("/login") public Result<?> login(@RequestBody User user){ User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPassword,user.getPassword())); if(res ==null){ return Result.fail("用户名或密码错误"); } return Result.success(res); } @PostMapping("/register") public Result<?> register(@RequestBody User user){ User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername())); if(res !=null){ return Result.fail("用户名重复"); } if(user.getPassword()==null){ user.setPassword("123456"); } userMapper.insert(user); return Result.success(user); }
最初是这样:
经过美化:
2.注册
与登录基本类似,前端Register.vue,并在index.js设置路由。详细代码可以看gitee。(这个后面和登录用了同样的方式美化了一下)
3.设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <script> import request from "@/utils/request"; export default { name: "Setting", components: { }, data(){ return{ form:{}, input:"" } }, created(){ let str=sessionStorage.getItem("user")||"{}" this.form=JSON.parse(str) }, methods:{ handleClose(){ this.$router.push('/home'); }, update(){ request.put("api/user",this.form).then(res =>{ console.log(res); if(res.code == '200'){ this.$message({ type: "success", message:"更新成功" }) sessionStorage.setItem("user",JSON.stringify(this.form)) this.$router.push('/home'); }else{ this.$message({ type:"error", message:"更新失败" }) } }) } } } </script> <template> <div> <el-dialog v-model="form" title="个人信息编辑" width="500" @close="handleClose"> <el-form :model="form"> <el-form-item label="用户名" :label-width="formLabelWidth"> <el-input v-model="form.username" disabled></el-input> </el-form-item> <el-form-item label="密码" :label-width="formLabelWidth"> <el-input v-model="form.password" show-password></el-input> </el-form-item> <el-form-item label="手机号" :label-width="formLabelWidth"> <el-input v-model="form.number"></el-input> </el-form-item> <el-form-item label="邮箱" :label-width="formLabelWidth"> <el-input v-model="form.email"></el-input> </el-form-item> </el-form> <div class="dialog-footer"> <el-button @click="this.$router.push('/home')">取消</el-button> <el-button type="primary" @click="update"> 确认 </el-button> </div> </el-dialog> </div> </template> <style scoped> </style>
这个是header.vue部分的设置,写这部分是新增了vue和路由实现的。这部分不难,是在element plus中找了表单,再写好script部分,获取的user信息就好了。后来优化这部分时补充handleClose方法点击叉号跳转/home页面,使操作更加流畅。
4.健康问答
前端实现:HomeView.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <template> <div class="container"> <div class="chatbox"> <h2 class="title">健康问答</h2> <div class="messages" ref="messageBox"> <div v-for="(message, index) in messages" :key="index" :class="{'message-container': true, 'user-message': message.sender === 'User', 'bot-message': message.sender !== 'User'}" > <el-avatar class="message-avatar" style="background-color: cornflowerblue;color: black">{{message.sender === 'User' ? 'User' : 'Bot'}}</el-avatar> <div class="message-content">{{message.text}}</div> </div> </div> <div class="input-section"> <input type="text" class="userinput" v-model="userInput" @keyup.enter="sendMessage" placeholder="输入:" /> <button class="send" @click="sendMessage" > 发送 </button> </div> </div> </div> </template> <script> import axios from 'axios' export default { name: 'HomeView', components: { }, data(){ return{ userInput: '', messages: [], } }, methods:{ async callAPIMethod(input) { try { const response = await axios.post('http://localhost:9091/reply', { message: input }); return response.data; } catch (error) { console.error(error); } }, async sendMessage() { this.messages.push({ sender: 'User', text: this.userInput, }); console.log("Ready to send message: " + this.userInput); const response = await this.callAPIMethod(this.userInput); console.log("Received message: " + response); if(response) { this.messages.push({ sender: 'Bot', text: response, }); } this.$refs.messageBox.scrollTop = this.$refs.messageBox.scrollHeight; this.userInput = ''; }, }, } </script> <style scoped> //这部分太长了省略,详细看gitee代码 </style>
后端实现:MessageController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.example.demo.controller; import … class Message { private String message; // getter // setter } @CrossOrigin(origins = "http://localhost:8080") @RestController public class MessageController { @PostMapping("/reply") public String reply(@RequestBody Message message) { Random rand = new Random(); String[] responses = {"保持健康~", "锻炼身体!", "饮食规律~"}; if ("你好".equals(message.getMessage())) { return "你好"; } else if ("什么是亚健康管理系统".equals(message.getMessage())) { return "这个亚健康管理系统是人工智能学院java小组开发的。包括主页,运动知识,健康购物,评估与建议,健康信息上传的功能"; } //省略一些else if else { return responses[rand.nextInt(responses.length)]; } } }
这部分本来我想连一个大语言模型的api,但是后来找不到适合的免费api,并且觉得如果是健康管理系统的话可能直接连一个大模型不太合适,要手动个性化设置一下,遂写了一些回复语代替,比较简洁,仅供演示。如果问”你好”和”什么是亚健康管理系统"等会回复特定的话,问其他就在"保持健康~","锻炼身体!", "饮食规律~"中随机回复一个。
最初是下面左图所示,右图是后来美化了一下。
5.一些其他的小细节
1)头部username显示
最初:
改动后:
显示具体的用户名
1 2 3 <template #title> <el-avatar style="background-color: cornflowerblue;color: black">{{ user.username }}</el-avatar> </template>
2)管理员和普通用户权限,管理员可以看到用户管理的页面,这里是在数据库增加了role(int类型,1表示管理员0表示普通用户),
在Aside.vue
:
1 2 3 4 <el-menu-item index="7" v-if="user.role===1" @click="this.$router.push('/user_manage')"> <el-icon><List /></el-icon> <span>用户管理</span> </el-menu-item>
v-if="user.role===1"
这样实现的
在User_manage.vue
:
1 2 3 4 5 6 <el-table-column label="角色"> <template #default="scope"> <span v-if="scope.row.role===1">管理员</span> <span v-if="scope.row.role===0">普通用户</span> </template> </el-table-column>
实现两者的显示。
3)未登录状况下强制跳转登录(这里是对我负责的登录功能的优化)
在index.js
:
1 2 3 4 5 6 7 8 9 10 11 12 // 添加一个 beforeEach 路由守卫,这里用于实现未登录情况下强制跳转/login router.beforeEach((to, from, next) => { // 检查 sessionStorage 中是否已经有 user let user = sessionStorage.getItem('user'); // 如果没有 user 且访问的不是登录界面,那么强制跳转至登录页面 if (!user && to.path !== '/login'&& to.path !== '/register') { return next({ path: '/login' }); } // 否则就继续进行本次路由 next(); });
6.sql文件的整理上传,详见giteehealth_management.sql
7.README,详见giteeREADME.md
五.总结展望
这次作业前期准备断断续续用了快一个月,后面写项目差不多两周左右。使用多一点框架会在正式开发中快很多,但是想要知道怎么用还是要学不少知识的。我们每个人都写了前端后端,如果你看源码会发现4个人不同的代码风格。总的来说,这次大作业还是学到了很多东西,见证了项目一点点搭建起来,培养团队合作能力,也真的加强了自信”我们可以自己写原创项目”。
展望的话,我们以后可以实现更完整一点的项目,比如文件上传,更丰富的管理员功能,验证码,服务器部署等等。