基于Springboot+Vue的WebApp开发实验报告

基于Springboot+Vue的WebApp开发实验报告

Java与面向对象设计的大作业,实验报告docx用pandoc转成了md。

【实验目的】

  1. 掌握Java与面向对象基本原理和概念。

  2. 掌握Java与面向对象编程思想和主流技术或框架。

  3. 掌握基于Java开发完整软件Demo,并能演示。

【实验装备】

个人笔记本,idea,JDK环境,mysql,navicat, vue,git等。

【实验内容】

基于所选择的主题方向,调研、分析和设计3-5个核心场景(模块)作为研究对象,根据掌握的Java和相关知识,实现相对完整的WebApp应用。以Java为基础,可以自由选择搭配其它技术和框架,输出详细的设计文档、项目源代码和可运行的Demo视频。

【实验要求】

  1. 按实验内容输出详细设计、实现、运行关键截图,要求行文整洁、紧凑、顺畅。

  2. 代码以团队gitee形式提交,视频以百度网盘形式提交,可限时公开访问。

团队Gitee: JavaGroup (gitee.com)

本项目代码: JavaGroup/project
(gitee.com)

视频百度网盘:链接
提取码:2s45

  1. 实验报告需要交代团队成员分工,以及自己承担的任务(要求任务量合理,鼓励交叉参与);个人报告要求完整,团队成果部分精炼描述,侧重个人为主部分加以详细描述。

【实验分析】

输出实验分析总结和心得体会。

【参考资料】

参考教程:带你从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等等后,决定按功能分工,各自实现负责的功能的前端+后端。虽然前后端分离,但是功能一个人同时写,不断加功能完善项目,同时锻炼写前端和后端的能力。

三.系统设计

下面是我们当时设计的方案:

  1. 系统:管理员、用户

登录界面参考:

  1. 首页

  1. 健康信息上传

  1. 商品推荐

  1. 运动知识

  1. 评估与建议

随后进行抽签,选择各自要实现的功能。抽签决定好后先写好头部和侧边栏,新建不同的.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文件的整理上传,详见gitee
health_management.sql

7.README,详见gitee
README.md

五.总结展望

这次作业前期准备断断续续用了快一个月,后面写项目差不多两周左右。使用多一点框架会在正式开发中快很多,但是想要知道怎么用还是要学不少知识的。我们每个人都写了前端后端,如果你看源码会发现4个人不同的代码风格。总的来说,这次大作业还是学到了很多东西,见证了项目一点点搭建起来,培养团队合作能力,也真的加强了自信”我们可以自己写原创项目”。

展望的话,我们以后可以实现更完整一点的项目,比如文件上传,更丰富的管理员功能,验证码,服务器部署等等。

基于Springboot+Vue的WebApp开发实验报告

https://strangersinsist.github.io/2024/06/18/health_management/

作者

zyh

发布于

2024-06-18

更新于

2024-11-10

许可协议

评论