简单宿舍管理系统(springboot+vue)
简单宿舍管理系统(springboot+vue)
- 1.创建项目
- 1.前端
- 2.数据库
- 3.后端
- 2.登陆
- 1.前端
- 1.准备工作
- 2.登陆组件
- 3.配置
- 2.后端
- 1.链接数据库
- 2.创建用户实体类
- 3.数据操作持久层
- 1.配置
- 2.内容
- 3.测试
- 4.中间业务层
- 1.异常
- 2.业务实现
- 3.测试
- 5.响应前端控制层
- 3.前后对接
- 4.效果
- 3.后台管理
最近看了springboot和vue,为了练一下把前后端打通就自己手动写个简单的系统,测试一下,把代码放在仓库。
1.创建项目
1.前端
我的前端项目名叫Dormitory,然后添加插件element-plus(页面设计)和axios(后端交互)。
npm init vue@latest#这里插件下载我都选no,之后自己会手动下载使用
cd Dormitory
npm install
npm install element-plus
npm install axios
npm run dev
2.数据库
首先创建库,第一个是登陆功能,我就顺便创建一个简单的用户表t_user。
mysql -u root -p
create database dormitory;
use dormitory;
use store
CREATE TABLE t_user (uid INT AUTO_INCREMENT COMMENT '用户id',username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',password CHAR(32) NOT NULL COMMENT '密码',role INT COMMENT '角色',name VARCHAR(20) NOT NULL UNIQUE COMMENT '姓名',gender INT COMMENT '性别:0-女,1-男',telephone VARCHAR(50) COMMENT '手机号',PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.后端
创建项目名叫dormitory_b,依赖库我用了三个(spring web,mybatis framework,mysql driver),然后配置一下jdk和maven环境和xml即可。
2.登陆
登陆这里我把uid和role保存到后端session中,username保存到前端cookie中,而且密码啥的我也没加密,就怎么简单怎么来。
1.前端
1.准备工作
这里我用到element-plus和icon,而且我是按需引入,所以首先下载插件:
npm install -D unplugin-vue-components unplugin-auto-import
npm install @element-plus/icons-vue
然后在vite.config.ts按需引入element-plus:
import { fileURLToPath, URL } from 'node:url'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
});
在main.ts里将icon全局注册到App上:
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}
就可以使用svg方式使用:
<el-icon><Menu /></el-icon>
然后配置路由用到了router,所以先下载:
npm install vue-router
然后在src里面建一个router文件夹,里面建一个index.js写路由配置文件,然后在main.js里面挂载一下:
import router from './router';
app.use(router)
2.登陆组件
这里登陆页面我写在了LoginView里面,后面我会配置路由和组件。
<template><div class="login-container"><div class="login-form"><el-form ref="login-form" :model="loginForm" label-width="80px" :rules="rules"><el-form-item label="用户名" prop="username"><el-input v-model="loginForm.username"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" v-model="loginForm.password"></el-input></el-form-item><el-form-item label="角色" prop="role"><el-radio-group v-model="loginForm.role"><el-radio label="admin">系统管理员</el-radio><el-radio label="dorm">宿舍管理员</el-radio></el-radio-group></el-form-item><el-form-item size="large"><el-button type="primary" @click="toLogin">登录</el-button></el-form-item></el-form></div></div></template><script>import { ref } from 'vue';import axios from 'axios';export default {setup() {const loginForm = ref({username: '',password: '',role: 'admin',});const rules = {username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' }],role: [{ required: true, message: '请选择角色', trigger: 'change' }],};const performLogin = async () => {try {const formData = new FormData();//axios默认是json格式发送数据,但我后端接受的是user,所以将数据放到表单formData.append('username', loginForm.value.username);formData.append('password', loginForm.value.password);formData.append('role',loginForm.value.role=='admin'?0:1);const response = await axios.post('http://localhost:8080/users/login', formData);const data = response.data;if (data.state === 200) {// 登录成功后,保存用户名到cookiedocument.cookie = `username=${loginForm.value.username}; expires=; path=/`;alert('登录成功');} else if (data.state === 400) {alert('用户名错误');} else if (data.state === 401) {alert('密码错误');}else if (data.state === 402) {alert('角色错误');}} catch (error) {console.error('An error occurred:', error);}};const toLogin = () => {performLogin();};return {loginForm,rules,toLogin,};},};</script><style scoped>.login-container {display: flex;align-items: center;justify-content: center;height: 100vh;}.login-form {padding: 80px;border-radius: 10px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);}</style>
3.配置
首先是在router/index.js里面写路由配置,将这个页面路由配置一下:
import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '@/components/LoginView.vue'
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/login',component: LoginView}]
})
export default router
然后在App.vue里面写一下这个路由出口
<template><RouterView></RouterView>
</template>
此时就可以通过http://localhost:5173/login/访问到这个页面。
2.后端
1.链接数据库
在application.properties中配置数据库。
spring.datasource.url=jdbc:mysql://localhost:3306/dormitory?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
2.创建用户实体类
在entity/User类里面创建用户实体类,和getset,equal,tostring方法(mac的快捷键是command+n)。
public class User {private Integer uid;private String username;private String password;private Integer role;private String name;private Integer gender;private String phone;
}
3.数据操作持久层
1.配置
首先是配置一下mapper层,在启动类里面添加项目的mapper路径,让自动扫包。
@MapperScan("com.hckj.dormitory_b.mapper")
在application.properties中配置mapper地址。
mybatis.mapper-locations=classpath:mapper/*.xml
2.内容
在mapper/UserMapper接口里面写SQL语句的抽象方法(类添加@Mapper注解),然后resources/mapper/UserMapper.xml里面写抽象方法的映射文件(这里放在resource是因为xml是静态文件)。
User findByUsername(String username);//接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hckj.dormitory_b.mapper.UserMapper"><select id="findByUsername" resultType="com.hckj.dormitory_b.entity.User">select * from t_user where username=#{username}</select>
</mapper>
3.测试
为了登陆测试,这里先给数据库里面插入一条数据:
INSERT INTO t_user (username, password, name,role, gender, telephone)
VALUES ('zoe', '111', 'dz', 0, 0,'188');
然后测试(测试类加注解:@SpringBootTest和@RunWith(SpringRunner.class))
@Autowiredprivate UserMapper userMapper;@Testpublic void findByUsername(){System.out.println(userMapper.findByUsername("zoe"));}
4.中间业务层
1.异常
在登录这个业务里会出现用户没有查询到和密码不匹配,所以在service的ex包里面创建UsernameNotFoundException和PasswordNotMatchException异常类,还有一个是角色不匹配RoleNotMatchException,并都继承RuntimeException,然后生成抛出异常的5种构造方法。
2.业务实现
然后写业务层的接口(加@Service注解)并写类实现这个接口。
User login(String username, String password,Integer role);//接口
@Service
public class UserServiceImpl implements IUserService{@Autowiredprivate UserMapper userMapper;@Overridepublic User login(String username, String password,Integer role) {User result = userMapper.findByUsername(username);if (result == null) {throw new UsernameNotFoundException("用户数据不存在");}String password_ = result.getPassword();if (!password_.equals(password)) {throw new PasswordNotMatchException("用户密码错误");}Integer role_=result.getRole();if (!role_.equals(role)) {throw new RoleNotMatchException("用户角色错误");}User user = new User();user.setUid(result.getUid());user.setUsername(result.getUsername());user.setRole(result.getRole());return user;}
}
3.测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTests {@Autowiredprivate IUserService userService;@Testpublic void login(){User user= userService.login("zoe","111",0);System.out.println(user);}
}
5.响应前端控制层
package com.hckj.dormitory_b.controller;import com.hckj.dormitory_b.entity.User;
import com.hckj.dormitory_b.service.IUserService;
import com.hckj.dormitory_b.service.ex.PasswordNotMatchException;
import com.hckj.dormitory_b.service.ex.RoleNotMatchException;
import com.hckj.dormitory_b.service.ex.UsernameNotFoundException;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("users")
public class UserController {@Autowiredprivate IUserService userService;@PostMapping("login")public Map<String, Object> login(User user, HttpSession session) {String username = user.getUsername();String password = user.getPassword();Integer role=user.getRole();Map<String, Object> response = new HashMap<>();try {User loggedInUser = userService.login(username, password,role);session.setAttribute("uid",loggedInUser.getUid());//将用户的uid和role保存到sessionsession.setAttribute("role",loggedInUser.getRole());response.put("state", 200);response.put("message", "登陆成功");response.put("data", loggedInUser);} catch (UsernameNotFoundException e) {response.put("state", 400);response.put("message", "用户名未找到");response.put("data", null);} catch (PasswordNotMatchException e) {response.put("state", 401);response.put("message", "密码不正确");response.put("data", null);} catch (RoleNotMatchException e){response.put("state",402);response.put("message","角色不正确");response.put("data",null);}return response;}
}
3.前后对接
对接这里其实就只是一个跨域问题,这个就是在后端工程的config/WebMvcConfig类里面加入设置,这里我前端的地址是http://localhost:5173
package com.hckj.dormitory_b.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://localhost:5173").allowedMethods("GET", "POST", "PUT", "DELETE").allowCredentials(true);}
}
4.效果

3.后台管理
相关文章:
简单宿舍管理系统(springboot+vue)
简单宿舍管理系统(springbootvue) 1.创建项目1.前端2.数据库3.后端 2.登陆1.前端1.准备工作2.登陆组件3.配置 2.后端1.链接数据库2.创建用户实体类3.数据操作持久层1.配置2.内容3.测试 4.中间业务层1.异常2.业务实现3.测试 5.响应前端控制层 3.前后对接4…...
Socks5代理、IP代理的关键作用
Socks5代理与SK5代理:网络安全的卫士 Socks5代理作为一项先进的代理协议,其多协议支持、身份验证功能以及UDP支持使其成为网络安全的重要支持者。 IP代理:隐私保护与无限访问的利器 IP代理技术通过隐藏真实IP地址,保护用户隐私…...
前端 CSS 经典:box-shadow
1. 基础属性 /* box-shadow: h-shadow v-shadow blur spread color inset; */ box-shadow: 10px 10px 2px 2px red inset; h-shadow: 必填,水平阴影的位置,允许负值 v-shadow: 必填,垂直阴影的位置,允许负值 blur: 可选ÿ…...
使用数组方法打印出 1 - 10000 之间的所有对称数。例如:121、1331等
(我从别的人那复制的,原文章请点击此处) 源代码: function getNum (start, end) {var arr [];for(var i start; i < end; i) {if (i.toString() i.toString().split().reverse().join() && i.toString().length &…...
DELM深度极限学习机回归预测研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Spark大数据分析与实战笔记(第一章 Scala语言基础-5)
文章目录 每日一句正能量章节概要1.5 Scala的模式匹配与样例类1.5.1 模式匹配字符匹配匹配字符串守卫匹配类型匹配数组、元组、集合 1.5.2 样例类 课外补充偏函数 每日一句正能量 “成功的秘诀,在于对目标的执着追求。”——爱迪生 无论是在工作、学习、还是生活中&…...
shell学习脚本04(小滴课堂)
他就可以直接读出来了。不需要在sh后面加参数。 可以用-s隐藏内容: 可以用-t进行指定几秒后显示。 -n限制内容长度。 输入到长度为5自动打印。 我们把-s放到-p后面的话: 这样会出错。 如果最后加5m会一直闪烁。 大家可以按照需求自行使用。...
Python数据结构(链表)
Python数据结构(链表) 单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向…...
连续/离散的控制系统阶跃测试(包括MATLAB里的step()函数)
阶跃测试 只要是连续时间系统,无论是传递函数还是连续状态空间形式的模型,直接可以用**step()**做阶跃测试;但是对于离散系统而言,不能用step()函数,可以自行编写代码,如下。 1、离散系统:x(k…...
【六:pytest框架介绍】
常见的请求对象requests.get()requests.post()requests.delete()requests.put()requests.request()常见的响应对象reprequests.request()//返回字符串格式数据print(req.text)//返回字节格式数据print(req.content)//返回字典格式数据print(req.json)#状态码print(req.status_c…...
提升医院安全的关键利器——医院安全(不良)事件报告系统源码
医院是人们寻求医疗服务和康复的场所,安全是医院运营的基石。然而,医疗过程中不可避免地会出现不良事件,如药物错误、手术事故等。为了及时发现、评估和解决这些问题,医院安全(不良)事件报告系统应运而生。…...
【瑞吉外卖部分功能补充】
瑞吉外卖部分功能补充 菜品的启售和停售 在浏览器控制台点击对应功能后可以看到前端发送的请求是:http://localhost:9999/dish/status/1?ids1413342036832100354,请求方式为POST。 接收到前端参数后,进行controller层代码补全,…...
react的setState做了什么
1、为什么需要setState setState的作用是帮助我们更改数据的同时并且通知视图进行渲染。因为React并不会绑定视图和state,需要我们手动去更新视图。 2、setState什么时候是同步的,什么时候是异步的 setState这个方法在调用的时候是同步的,…...
ubuntu18.04 RTX3060 rangnet++训练 bonnetal语义分割
代码链接: https://github.com/PRBonn/lidar-bonnetal 安装anaconda环境为 CUDA 11.0(11.1也可以) anaconda环境如下 numpy1.17.2 torchvision0.2.2 matplotlib2.2.3 tensorflow1.13.1 scipy0.19.1 pytorch1.7.1 vispy0.5.3 opencv_python…...
Linux:权限是什么
本篇文章来简单介绍一下Linux操作系统中权限的基本概念和一些操作方法,对Linux权限有一个基本的了解,希望对大家学习Linux有所帮助。 目录 1.权限的概念 2.Linux权限管理 2.1 文件访问者的分类 2.2 文件类型与访问权限(事物属性ÿ…...
uni-app yrkDataPicker 日期和时间选择控件
uni-app 选择日期时间控件有 2 月份有 31 天的问题,一直没有修复,uni-calendar 苹果有选择年份和月份后无法显示问题。自己写了一个,只支持 H5 和微信小程序,其他没有试过。 <template><view class"yrk-data-picke…...
PAM从入门到精通(十九)
接前一篇文章:PAM从入门到精通(十八) 本文参考: 《The Linux-PAM Application Developers Guide》 PAM 的应用开发和内部实现源码分析 先再来重温一下PAM系统架构: 更加形象的形式: 六、整体流程示例 2.…...
apache httpd 多后缀解析漏洞
形成原因 Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令 在有多个后缀的情况下,只要一个文件含有.php后缀的文件即将被识别成PHP文件,没必要是最后一个后缀。利用这个特性,将会造成一个可以绕过上传白名单…...
Flutter ☞ 数据类型
数值类型 int、double、num int 整型,取值通常在 -253 ~ 253 之间 int class double 64-bt(双精度)浮点数,符合 IEEE 754 标准。 double class num 数值类型的基类,int 和 double 都继承自num。 num class 数值转换 // String -> …...
MyBatis-Plus 实战教程一
这里写目录标题 简介快速上手数据库建立创建实体类修改参数引入依赖测试常见注解介绍TableNameTableIdTableField 常见配置仓库地址 简介 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,…...
纯 AI 高级攻击是伪命题?平庸的工业化才是未来三年最大的网络风险
在2026年的全球网络安全版图上,没有任何一个话题比“AI与网络攻击”更能撕裂行业共识。乐观派宣称AI将成为防御者的终极护城河,能自动识别并拦截所有未知威胁;悲观派则不断渲染“天网降临”的恐慌,声称具备自我意识的自主恶意软件…...
Superpowers - 15 用 Git Worktrees 打造“无尘室”开发环境:从 Superpowers 实践谈起
文章目录Pre一、为什么需要 Git Worktrees:上下文切换是真正的杀手1.1 传统分支切换的痛点1.2 Worktree 的核心价值:隔离,而不是复制二、Superpowers 的视角:Worktree 是必选项而非锦上添花2.1 三个关键技能的前置条件2.2 生命周期…...
高效PCK文件逆向工程:GDSDecomp工具深度解析与实战指南
高效PCK文件逆向工程:GDSDecomp工具深度解析与实战指南 【免费下载链接】gdsdecomp Godot reverse engineering tools 项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp 在Godot游戏开发与逆向工程领域,PCK文件处理一直是一个技术难点…...
Maven源码打包利器:maven-source-plugin实战配置与最佳实践
1. 为什么你的Maven项目需要源码包? 每次看到同事在IDE里对着你的库代码按CtrlB跳转却显示"反编译.class文件"时,是不是觉得特别尴尬?我们团队就遇到过这样的场景:某个工具库被其他项目组引用后,对方开发调试…...
Open Event Frontend 移动端适配与响应式设计:打造完美跨平台体验
Open Event Frontend 移动端适配与响应式设计:打造完美跨平台体验 【免费下载链接】open-event-frontend The frontend for the Open Event API Server https://test.eventyay.com 项目地址: https://gitcode.com/gh_mirrors/op/open-event-frontend Open Ev…...
各位爱因斯坦,小白想知道:
国产交换机、路由器、防火墙、AC/AP、负载均衡等设备的安装配置、调试。这些流程步骤与细节谢谢大佬们🙏...
计算机毕业设计:Python农产品电商数据采集与价格预估平台 Flask框架 Spark 线性回归 数据分析 可视化 大数据 大模型(建议收藏)✅
1、项目介绍 技术栈 采用 Python 语言开发,基于 Flask 框架搭建后端服务,使用 Spark 技术进行大数据处理,通过 requests 爬虫从惠农网采集农产品数据,运用线性回归预测算法模型进行价格预测,前端结合 Echarts 可视化库…...
基于Docker与WebVirtCloud的私有云实践:从零部署到虚拟机管理
1. 为什么选择DockerWebVirtCloud搭建私有云 最近几年我帮不少中小企业部署过私有云环境,发现很多团队都被传统虚拟化方案的复杂部署流程劝退。直到遇到WebVirtCloud这个基于Web的KVM管理工具,配合Docker容器化部署,真正实现了十分钟快速搭建…...
BK3633 Keil 工程中自动化构建与版本管理的进阶配置指南
1. 为什么需要自动化构建与版本管理 在嵌入式开发中,每次手动编译、打包、命名固件都是件费时费力的事情。特别是像BK3633这样的蓝牙芯片项目,往往需要同时维护Debug和Release两个版本。Debug版本用于开发调试,需要保留日志输出和调试信息&am…...
深入解析安路科技PH1系列FPGA的ERAM架构:从BRAM到高效存储方案
1. PH1系列FPGA的ERAM架构概览 第一次拿到安路科技PH1系列FPGA开发板时,我就被它的ERAM(嵌入式随机存取存储器)设计惊艳到了。相比传统FPGA的BRAM(块随机存取存储器),PH1的ERAM在架构上做了很多创新。每个E…...
