宿舍管理系统--前后端分离式项目架构流程复盘(三万字详解)

文章目录

  • 🐒个人主页
  • 🏅JavaEE系列专栏
    • 📖前言:
    • 【🎇前端】先创建Vue-cli项目(版本2.6.10,仅包含babel),请选择此项目并创建
  • 【整理简化项目模板】
    • 【🎀创建路由】
      • 打开命令行工具,进入你的项目目录,输入下面命令。并回车下载
      • 1.在src路径下创建 router 目录~创建 index.js 文件,在其中配置路由
      • 2.在🧸APP.vue中添加路由视图
      • 3.在🧸 main.js 中配置路由
    • 【🎀配置Element UI】
    • 【🏨创建组件并利用 Element UI修饰】
    • 【🎀如何使背景图片最大自适应】
    • 【🎀登录组件模板】
    • 【🎀注册组件模板】
    • 【🎇前端配置】
      • 安装ajax(异步请求)之axios---网络请求库.
      • 🎀在main.js中导入
  • 【🎀创建后端项目+数据库,先完成注册与登陆功能】
    • 1.在idea中创建一个项目,然后右键单击
    • 2.配置后端服务器tomcat
    • 3.创建处理程序,导入jar包
  • 🏨[这是需要导入的jar包下载地址---阿里云盘](https://www.aliyundrive.com/s/gox2K1pR8RL)
      • 记得配置servlet处理程序的地址,配置xml文件时,记得在标签里面写,优先配置编码过滤器EcondFilter
    • 🧸创建公共类(记得util包中定义commentResoult类)
      • 🧸可以在util包中定义JDBC的封装类(使代码更加简洁)
      • 🏅【采用json格式的打印】
        • 🪂后端借助ObjectMapper类将对象转为json格式的字符串
        • 🪂【前端发送数据时,由于axios发出的异步请求格式为json格式,利用jsonToString()方法转为默认键值对格式】
      • 🧸如果使用前端ajax的axios,后端记得使用“跨域请求声明”
    • 🏨补充知识:不同组件之间通过get()方式传递信息
    • 【🎀主面板组件模板(简洁版)】
  • 【🎀添加token令牌--临时会话跟踪】
    • 🏅在index.js中配置路由导航守卫
      • 🏅【前端配置:axios的响应拦截器、请求拦截器】=提高代码复用性
      • 🏅【后端配置:添加JWT jar包、创建modle包/Admin类、在util包下创建JWTUtil类、创建TokenFilter过滤器】“json web token”
        • 🎀添加JWT jar包
          • 🏨[这是需要导入的jar包下载地址---阿里云盘](https://www.aliyundrive.com/s/gox2K1pR8RL)
        • 🪂先在src路径下创建一个modle包,再创建一个Admin类
        • 🎀添加JWT jar包
        • 🧸创建TokenFilter过滤器
    • 🧸【🎀后端:】记得登录成功时,要生成一个token
        • 【🦓获取token,记得是请求头getHeader(),而不是请求体getParameter()】
    • 🧸【🎀前端:】记得登录成功时,从后端响应回来的数据中将token存入临时会话存储区中
    • 🧸【组件响应的`路由跳转`--跳转至新页面】
    • 🧸路由嵌套🎀【==组件嵌套==的路由跳转--局部跳转】
  • 🎀表格Table模板
    • 🎀源码如下:
    • 🪀表单dalog模板
    • 🎀源码如下:
      • 🎇刷新页面
  • 🎀【🐒持续更新中...】

🐒个人主页

🏅JavaEE系列专栏

📖前言:

本篇博客主要以巩固前后端分离式项目架构流程,通过开发一个宿舍管理系统为例,系统地梳理所学知识以及提高业务逻辑能力,欢迎大家来交流经验🐒

【🎇前端】先创建Vue-cli项目(版本2.6.10,仅包含babel),请选择此项目并创建

在这里插入图片描述

这个是创建完成后的样子

在这里插入图片描述

执行npm run serve命令,按回车进入浏览器,生成此页面,说明项目创建完成·在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vLvKFhdA-1685517220725)(../AppData/Roaming/Typora/typora-user-images/1685279544519.png)]

【整理简化项目模板】

1.直接删掉components文件下的HelloWorld.vue组件

在这里插入图片描述

在这里插入图片描述

2.清理APP.vue默认组件内容:在这里插入图片描述

【🎀创建路由】

打开命令行工具,进入你的项目目录,输入下面命令。并回车下载

npm i vue-router@3.5.3

在这里插入图片描述在这里插入图片描述

1.在src路径下创建 router 目录~创建 index.js 文件,在其中配置路由

在这里插入图片描述

【🧸在index.js配置】

import Vue from 'vue';
import router from 'vue-router'; /* 导入路由 */
import login from '../views/login'; /* 导入其他组件--【回头得改!】 */
import content from '../components/content'; /* 导入其他组件【回头得改!】 */
Vue.use(router)/* 定义组件路由 */
var rout = new router({routes: [{path: '/index',name: 'index',component: index},{path: '/content',component: content}]
})//导出路由对象
export default rout;

2.在🧸APP.vue中添加路由视图

<!-- 【路由组件】显示不同组件,就像一个画布 --><router-view/>

在这里插入图片描述

3.在🧸 main.js 中配置路由

在这里插入图片描述

/* 【导入路由】 */
import router from './router/index.js'
Vue.use(router);new Vue({//【一个Vue对象】render: h => h(App),router,
}).$mount('#app')

【🎀配置Element UI】

🦓安装 Element UI

npm i element-ui -S

在这里插入图片描述
🪂在 main.js 中写入以下内容:

//【导入Element UI 并声明vue项目使用Element UI】
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

在这里插入图片描述

🦓进入 Element UI官网网站

https://element.eleme.cn/#/zh-CN
在这里插入图片描述

【🏨创建组件并利用 Element UI修饰】

1.在src路径components路径下创建组件login.vue,注意:《template》《/template》中只能有一个根标签《div》《/div》(就是可以理解为所有标签写在根标签div的里面)在这里插入图片描述
2.在index.js中导入该组件
在这里插入图片描述
3.利用 Element UI修饰
在这里插入图片描述
在这里插入图片描述

【🎀如何使背景图片最大自适应】

#divbox{width: 100%;height: 100vh;background-image: url("[图片链接]"); /*将图片路径替换为你自己的图片路径*/background-size: cover; /*保持图片比例并完全覆盖元素*/background-position: center center; /*将图片居中对齐*/ }

在这里插入图片描述

【🎀登录组件模板】

<template><div id="divbox"><!-- 【此图像是圆圈头像logo】 --><img src="https://ts1.cn.mm.bing.net/th/id/R-C.3aeeb6d5725738095a7ad521d46ce428?rik=prLV4puYz%2btYuw&riu=http%3a%2f%2fwww.gx8899.com%2fuploads%2fallimg%2f2018021008%2fjrmgrhcgro0.jpg&ehk=Im%2fy1GA0xuqdwYNnKtzfue2b09jzjym4jjUXy7e0Seo%3d&risl=&pid=ImgRaw&r=0"alt="Your Image"><div class="login-form"><div id="logo"><span style="font-family: 'Microsoft YaHei';letter-spacing: 0.5px; font-weight: bold; font-size: 40px;">&nbsp;<span style="color:#4F5155"> 欢迎登录</span><span style="color:rgb(137, 204, 255) ;">宿舍管理系统</span></span></div><el-form ref="form" :rules="rules" :model="form" label-width="80px"><el-form-item label="用户名" prop="account"><el-input v-model="form.account" class="input"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" v-model="form.password" class="input"></el-input></el-form-item><el-form-item><el-button type="primary" @click="onSubmit('form')" style="width: 300px;">登录</el-button><br /><span style="color: #006A5A;" @click="reg()">没有账号?点击注册</span></el-form-item></el-form></div></div>
</template><script>export default {data() {return {form: {account: '',password: '',},rules: {account: [{ required: true, message: '请输入账户', trigger: 'blur' },{ min: 3, max: 5, message: '长度在 3 到 10 个字符~', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 3, max: 5, message: '长度在 1 到 10 个字符~', trigger: 'blur' }],}}},methods: {reg() {alert("注册");},onSubmit(form) {//【登录】//数据向后端发送进行验证//$refs是一个引用this.$refs[form].validate((valid) => {if (valid) {//如果发送成功,跳转到其他组件//【跳转语句】this.$message({showClose: true,message: '恭喜你,账户正确✔',type: 'success'});/* this.$message({showClose: true,message: '输入的账户或密码错误~', type: 'error'});this.$message({showClose: true,message: '系统忙,维修人员正在抢修!',type: 'warning'}); */}});}}}
</script><style>#divbox {width: 100%;height: 100vh;/*将🎀页面背景  图片路径替换为你自己的图片路径*/background-image: url("https://ts1.cn.mm.bing.net/th/id/R-C.b923d0630782b4e46dcbb2121b22bdbf?rik=l7wVr9wcUyyTzw&riu=http%3a%2f%2fpic.bizhi360.com%2fbbpic%2f68%2f768.jpg&ehk=anhoZ%2fxmeecIhRHc2n9reoQbtJ2xXrvIEx0sJbLLMiI%3d&risl=&pid=ImgRaw&r=0");/*保持图片比例并完全覆盖元素*/background-size: cover;background-position: center center;/*将图片居中对齐*/}.login-form {width: 442px;height: 400px;background-color: rgba(248, 242, 235, 0.5);;position: relative;left: 455px;top: 170px;}#logo {width: 100%;height: 60px;/* background-color: aquamarine; */margin-bottom: 60px;}.input {max-width: 300px;}img {border-radius: 50%;width: 100px;position: absolute;left: 638px;top: 50px;}
</style>

【🎀注册组件模板】

在这里插入图片描述

在这里插入图片描述

<template><div id="divbox"><!-- 【此图像是圆圈头像logo】 --><img src="https://ts1.cn.mm.bing.net/th/id/R-C.3aeeb6d5725738095a7ad521d46ce428?rik=prLV4puYz%2btYuw&riu=http%3a%2f%2fwww.gx8899.com%2fuploads%2fallimg%2f2018021008%2fjrmgrhcgro0.jpg&ehk=Im%2fy1GA0xuqdwYNnKtzfue2b09jzjym4jjUXy7e0Seo%3d&risl=&pid=ImgRaw&r=0"alt="Your Image"><div class="login-form"><div id="logo"><span style="font-family: 'Microsoft YaHei';letter-spacing: 0.5px; font-weight: bold; font-size: 40px;">&nbsp; 欢迎注册🐒平台系统</span></div><el-form ref="form" :rules="rules" :model="form" label-width="80px"><el-form-item label="用户名" prop="account"><el-input v-model="form.account" class="input"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" v-model="form.password" class="input" show-password></el-input></el-form-item><el-form-item label="确认密码" prop="password1"><el-input type="password" v-model="form.password1" class="input" show-password></el-input></el-form-item><el-form-item><el-button type="primary" @click="RegAccount('form')" style="width: 300px;">注册</el-button><br /><span style="color: #006A5A;" @click="login()">已有账号?点击返回</span></el-form-item></el-form></div></div>
</template><script>export default {data() {var validatePass = (rule, value, callback) => {if (value === '') {callback(new Error('请输入密码'));} else {if (this.form.password1 !== '') {this.$refs.form.validateField('password1');}callback();}};var validatePass2 = (rule, value, callback) => {if (value === '') {callback(new Error('请再次输入密码'));} else if (value !== this.form.password) {callback(new Error('两次输入密码不一致!'));} else {callback();}};return {form: {account: '',password: '',password1: ''},rules: {account: [{required: true,message: '请输入注册的管理员账户!',trigger: 'blur'},{min: 3,max: 10,message: '长度在 3 到 10 个字符',trigger: 'blur'}],password: [{required: true,message: '请输入账户密码!',trigger: 'blur'},{min: 3,max: 10,message: '长度在 3 到 10 个字符',trigger: 'blur'},{ validator: validatePass, trigger: 'blur' }],password1: [{required: true,message: '请再次确认账户密码!',trigger: 'blur'},{min: 3,max: 10,message: '长度在 3 到 10 个字符',trigger: 'blur'},{ validator: validatePass2, trigger: 'blur' }]}}},methods: {login() {alert("登录页面");//this.$router.push('/');},RegAccount(reffrom) { //【注册】//数据向后端发送进行验证//$refs是一个引用this.$refs[reffrom].validate((valid) => {if (valid) {//如果发送成功,跳转到其他组件//【跳转语句】this.$message({showClose: true,message: '恭喜你,账户已注册✔',type: 'success'});/* this.$message({showClose: true,message: '输入的账户或密码错误~', type: 'error'});this.$message({showClose: true,message: '系统忙,维修人员正在抢修!',type: 'warning'}); */}});}}}
</script><style>#divbox {width: 100%;height: 100vh;/*将🎀页面背景  图片路径替换为你自己的图片路径*/background-image: url("https://ts1.cn.mm.bing.net/th/id/R-C.b923d0630782b4e46dcbb2121b22bdbf?rik=l7wVr9wcUyyTzw&riu=http%3a%2f%2fpic.bizhi360.com%2fbbpic%2f68%2f768.jpg&ehk=anhoZ%2fxmeecIhRHc2n9reoQbtJ2xXrvIEx0sJbLLMiI%3d&risl=&pid=ImgRaw&r=0");/*保持图片比例并完全覆盖元素*/background-size: cover;background-position: center center;/*将图片居中对齐*/}.login-form {width: 442px;height: 400px;background-color: rgba(248, 242, 235, 0.5);;position: relative;left: 455px;top: 170px;}#logo {width: 100%;height: 60px;/* background-color: aquamarine; */margin-bottom: 30px;}.input {max-width: 300px;}img {border-radius: 50%;width: 100px;position: absolute;left: 638px;top: 50px;}
</style>

【🎇前端配置】

安装ajax(异步请求)之axios—网络请求库.

npm install axios

🎀在main.js中导入

// 导入 axios
import axios from ‘axios’;
// 设置访问后台服务器地址
/* axios.defaults.baseURL=“http://127.0.0.1:8088/TsetWebProject/”; 这里记得模仿修改后端服务器地址 */
axios.defaults.baseURL = “http://127.0.0.1:8088/Test/”;
// 将 axios 挂载到 vue 全局对象中,使用 this 可以直接访问
Vue.prototype.$http = axios;

在这里插入图片描述

🏅操作方法

this.$http.get(地址?Key=value&key2=val1).then(function(response){ }

this.$http.post(“login”,{key:“value”,key2:“val2”}).then(function(response){ }

【🎀创建后端项目+数据库,先完成注册与登陆功能】

1.在idea中创建一个项目,然后右键单击

在这里插入图片描述
在这里插入图片描述

2.配置后端服务器tomcat

在这里插入图片描述
先点+,在滑动选择Tomcat Server 服务器,最好保存ok
在这里插入图片描述
点击路径配置,选择apache-Tomcat所在文件夹进行路径配置
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
3.点击运行,出现✔就算运行成功了在这里插入图片描述

3.创建处理程序,导入jar包

在这里插入图片描述

🏨这是需要导入的jar包下载地址—阿里云盘

记得配置servlet处理程序的地址,配置xml文件时,记得在标签里面写,优先配置编码过滤器EcondFilter

在这里插入图片描述
在这里插入图片描述

🧸创建公共类(记得util包中定义commentResoult类)

来规定代码传输格式:code , data , message

package util;public class CommentResoult {private int code;private Object data;private String message;public CommentResoult(int code, Object data, String message) {this.code = code;this.data = data;this.message = message;}@Overridepublic String toString() {return "CommentResoult{" +"code=" + code +", data=" + data +", message='" + message + '\'' +'}';}
}

🧸可以在util包中定义JDBC的封装类(使代码更加简洁)

在这里插入图片描述

package util;import com.mysql.jdbc.Driver;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;/*** Created by 罗铠威 on 2023/8/8 13:57* type: 对jdbc代码进行一个封装*/
public class JDBCUtil {static {/*加载启动项*/try {DriverManager.registerDriver(new Driver());} catch (SQLException throwables) {throwables.printStackTrace();}}/*获取数据库连接对象*/public static Connection getConnection(String dataBaseName) throws SQLException {String url="jdbc:mysql://127.0.0.1:3306/"+dataBaseName+"?serverTimezone=Asia/Shanghai";return DriverManager.getConnection(url,"root","newpassword");}/*关闭连接管道*/public static void close(Connection connection, PreparedStatement ps) throws SQLException {if(connection!=null){connection.close();}if(ps!=null){ps.close();}}
}

🏅【采用json格式的打印】

🪂后端借助ObjectMapper类将对象转为json格式的字符串

在这里插入图片描述
在这里插入图片描述

🪂【前端发送数据时,由于axios发出的异步请求格式为json格式,利用jsonToString()方法转为默认键值对格式】

//将json对象序列化为键=值&键=值function jsonToString(jsonObj){console.log(jsonObj);var str="";for (var s in jsonObj) {str+=s+"="+jsonObj[s]+"&";}return str.substring(0,str.length-1);}

🧸如果使用前端ajax的axios,后端记得使用“跨域请求声明”

在这里插入图片描述

🏨补充知识:不同组件之间通过get()方式传递信息

传递信息的组件

this.$router.push("/?account="+this.form.account);

接收信息的组件

mounted() {//一般情况下在页面加载时就接收信息,所以一般在mounted的方法中写this.form.account=this.$route.query.account;}

【🎀主面板组件模板(简洁版)】

在这里插入图片描述

<template><div><el-container><!--头部导航栏--><el-header style="text-align: right; font-size: 20px;"><span class="logo">&nbsp;&nbsp;&nbsp;&nbsp;陕西理工大学<span style="color:rgb(137, 204, 255) ;">宿舍管理</span>系统&nbsp;</span><el-dropdown><!-- <div class="school"></div> --><i class="el-icon-setting" style="margin-right: 15px;"></i><el-dropdown-menu slot="dropdown"><el-dropdown-item> <el-button type="text" @click="open"icon="el-icon-switch-button">安全退出</el-button></el-dropdown-item></el-dropdown-menu></el-dropdown><el-button icon="el-icon-s-custom" class="icon"> <spanstyle="font-weight: bolder">{{account}}</span></el-button></el-header><!-- 🪂侧边栏--><!--左边栏--><el-container><el-aside width="240px" style="background-color:  white"><el-menu router><el-menu-item-group><el-button type="success" icon="el-icon-user"style="width: 145px;">学生管理</el-button></el-menu-item></el-menu-item-group><el-menu-item-group><el-button type="success" icon="el-icon-office-building " style="width: 145px;">楼栋管理</el-button></el-menu-item></el-menu-item-group><el-menu-item-group><el-button type="success" icon="el-icon-s-home"style="width: 145px;">宿舍管理</el-button></el-menu-item-group><el-menu-item-group><el-button type="success" icon="el-icon-s-custom"style="width: 145px;">管理员管理</el-button></el-menu-item-group><el-menu-item-group><el-button type="success" icon="el-icon-setting"style="width: 145px;">入住登记管理</el-button></el-menu-item-group><el-menu-item-group><el-button type="success" icon="el-icon-setting"style="width: 145px;">综合查询</el-button></el-menu-item-group><el-menu-item-group><template slot="title"></template><el-menu-item ><el-button type="text" @click="open"icon="el-icon-switch-button">安全退出</el-button></el-menu-item></el-menu-item-group></el-menu></el-aside><img src="https://pic.baike.soso.com/ugc/baikepic2/16827/20171227225852-88762951_jpg_300_300_19329.jpg/300"alt="Your Image"><!--中间部分--><el-main>展示信息</el-main></el-container></el-container></div>
</template><script>export default {name: "Main",data() {return {account: ""}},methods: {open() {this.$confirm('此操作将退出登录, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {sessionStorage.clear(); //情况存储信息this.$message({type: 'success',message: '退出成功!'});this.$router.push("/");}).catch(() => {this.$message({type: 'info',message: '已取消操作'});});}},mounted() {this.account = sessionStorage.account;/* this.account=sessionStorage.getItem("account");if(this.account==null){//【更改为路由导航守卫】this.$router.push("/")} */}}
</script><style type="text/css" scoped>#in1 {background-color: white;width: 100%;height: 100vh;}.el-header {background-color: #6da5ee;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #67C23A;color: #333;text-align: center;}.el-main {background-color: white;color: #333;text-align: center;}body>.el-container {margin-bottom: 40px;}.icon {border-radius: 50%;background-color: #9dd79e;}.el-table .warning-row {background: oldlace;}.el-table .success-row {background: #f0f9eb;}.logo {font-weight: 900;font-size: 38px;background-color: #67C23A;font-family: 楷体;border-radius: 80px 50px 50px 80px;position: absolute;left: 0px;}img {border-radius: 50%;width: 70px;position: absolute;left: 0px;top: -2px;}
</style>

【🎀添加token令牌–临时会话跟踪】

🏅在index.js中配置路由导航守卫

== --目的:每次请求时验证用户是否登录==

// 为路由对象, 添加 beforeBach 导航守卫
// to - 将要访问的页面地址, from - 从哪个页面访问的, next - 放行函数
rout.beforeEach((to, from, next) => {if (to.path == '/login'|| to.path == '/reg') {//如果用户访问的登录页, 直接放行return next();} else {var account = sessionStorage.getItem("account");if (account == null) {return next("/login");} else {next();}}
})

在这里插入图片描述
在这里插入图片描述

🏅【前端配置:axios的响应拦截器、请求拦截器】=提高代码复用性

🎀我们需要在后端生成一个token令牌,然后在浏览器的临时存储空间中存储,每次向后端发送请求时,将token都会(加载的请求头中)随请求一同发往后端进行验证。== 由于token令牌中携带着用户的信息,会在后端进行解析,可以使后端知道到底是哪一个用户正在操作、发出请求,并且可以验证token是否失效,限制用户在线时间==。
在这里插入图片描述

//axios 🎀请求拦截
axios.interceptors.request.use(config => {//为请求头对象,添加 Token 验证的 token 字段config.headers.token = window.sessionStorage.getItem('token');return config;
})

🎀与此同时,当后端验证完token,并且完成对应的处理操作后,响应至前端,前端会进行响应拦截,提前判断是否token失效、被伪造 或数据库连接失败==>返回登录页面,重新进行登录。

// 🎀添加响应拦截器
axios.interceptors.response.use((resp) => { //正常响应拦截if (resp.data.code == 500) {ElementUI.Message({message: resp.data.message,type: "error"})}if (resp.data.code == 202) {//token失效、被伪造router.replace("/login");}return resp;
});

🏅【后端配置:添加JWT jar包、创建modle包/Admin类、在util包下创建JWTUtil类、创建TokenFilter过滤器】“json web token”

🎀添加JWT jar包

在这里插入图片描述在这里插入图片描述在这里插入图片描述

🏨这是需要导入的jar包下载地址—阿里云盘

🪂先在src路径下创建一个modle包,再创建一个Admin类

同时token也是根据此类的信息来生成token令牌的

提示一下:这里的属性是根据数据库表admins的属性来写的,这个admins表是存储登录界面的账户信息的在这里插入图片描述

package modle;/*** Created by 罗铠威 on 2023/8/11 10:16* type:*/import java.util.Date;public class Admin {private int id;private String account;private  String password;private Date reg_time;private  String token;public String getToken() {return token;}public void setToken(String token) {this.token = token;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getAccount() {return account;}public void setAccount(String account) {this.account = account;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Date getReg_time() {return reg_time;}public void setReg_time(Date reg_time) {this.reg_time = reg_time;}
}

🎀添加JWT jar包

package com.example.back.util;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** JWT工具类*/
public class JWTUtil {/*** 根据用户id,账号生成token* @param u* @return*/public static String getToken(User u) {String token = "";try {//过期时间 为1970.1.1 0:0:0 至 过期时间  当前的毫秒值 + 有效时间Date expireDate = new Date(new Date().getTime() + 600*1000);//10分钟后失效//秘钥及加密算法Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");//设置头部信息Map<String,Object> header = new HashMap<>();header.put("typ","JWT");header.put("alg","HS256");//携带id,账号信息,生成签名token = JWT.create().withHeader(header).withClaim("id",u.getId()).withClaim("account",u.getAccount()).withExpiresAt(expireDate).sign(algorithm);}catch (Exception e){e.printStackTrace();return  null;}return token;}/*** 验证token是否有效* @param token* @return*/public static boolean verify(String token){try {//验签Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");JWTVerifier verifier = JWT.require(algorithm).build();DecodedJWT jwt = verifier.verify(token);return true;} catch (Exception e) {//当传过来的token如果有问题,抛出异常return false;}}/*** 获得token 中playload部分数据,按需使用* @param token* @return*/public static DecodedJWT getTokenInfo(String token){return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);}}

🧸创建TokenFilter过滤器

package filter;import com.fasterxml.jackson.databind.ObjectMapper;
import util.CommentResoult;
import util.JWTUtil;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class TokenFilter implements Filter {@Override//【HttpServletRequest(子接口,定义了http请求相关的方法) extends ServletRequest(父类没有关于http相关的方法)】public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;//多态性HttpServletResponse resp = (HttpServletResponse) servletResponse;//多态性String token = req.getHeader("token");//【这个就是那个自定义的请求头】System.out.println(token+"已接收");//验证token代码是否有效--
//【verify()方法是验证token是否是伪造的、失效的,返回一个布尔类型的值】boolean res = JWTUtil.verify(token);//false-token【失效or伪造的】CommentResoult commentResoult=null;if(res){//【如果是真的】commentResoult= new CommentResoult(200, res, "token验证成功!");filterChain.doFilter(servletRequest,servletResponse);//【向下走】}else {commentResoult= new CommentResoult(202, res, "token已经失效或伪造!");PrintWriter responds = resp.getWriter();responds.print(new ObjectMapper().writeValueAsString(commentResoult));//发送json格式的信息至前端}}
}

【🪀记得配置xml】
在这里插入图片描述
【如何·🎀解析token中的用户信息】

package Servlet;import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import util.CommonResult;
import util.JWTUtil;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class TestServlet extends HttpServlet {@Override//【🎀解析token语句,】protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String token = req.getHeader("token");//【这个就是那个自定义的请求头】DecodedJWT tokenInfo = JWTUtil.getTokenInfo(token);Integer id = tokenInfo.getClaim("id").asInt();//拿到idString account = tokenInfo.getClaim("account").asString();//拿到账户System.out.println("测试请求!"+id+":"+account);//验证token代码是否有效boolean res = JWTUtil.verify(token);//false-token【失效or伪造的】CommonResult commonResult = new CommonResult(res?200:202, res, "token验证成功~");PrintWriter responds=resp.getWriter();responds.print(new ObjectMapper().writeValueAsString(commonResult));//发送json格式的信息至前端}
}

🧸【🎀后端:】记得登录成功时,要生成一个token

在这里插入图片描述

【🦓获取token,记得是请求头getHeader(),而不是请求体getParameter()】

在这里插入图片描述

🧸【🎀前端:】记得登录成功时,从后端响应回来的数据中将token存入临时会话存储区中

在这里插入图片描述

🧸【组件响应的路由跳转–跳转至新页面】

在menu标签上要添加router属性,否则没有反应,不会跳转
在这里插入图片描述

在这里插入图片描述
请添加图片描述

🧸路由嵌套🎀【组件嵌套的路由跳转–局部跳转】

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这是两个案例:目的是为了告诉你:要在《el-menu》组件里加router属性,否则会没有反应!!!! 在这里插入图片描述请添加图片描述

🎀表格Table模板

在这里插入图片描述
在这里插入图片描述这里是引用
这里的数据可根据需要自行更换,响应事件可自己添加(可以自己更换)

🎀源码如下:

<template><div><el-card class="box-card" style="text-align: left;"><!-- 【🎀查询列表】 --><el-row :gutter="20"><el-col :span="6"><el-input placeholder="学号" v-model="query.queryNum"/></el-col><el-col :span="6"><el-input placeholder="姓名" v-model="query.queryName"/></el-col><el-col :span="6"><el-button type="primary" icon="el-icon-search" @click="">查询</el-button><el-button type="danger" icon="el-icon-delete" size="small" @click="">清空查询</el-button></el-col></el-row><!-- 【🎀新增按钮】 --><el-button type="success" icon="el-icon-circle-plus" @click="">新增</el-button><!-- 【🎀返回按钮】 --><el-button type="primary" icon="el-icon-house" @click="">返回主页</el-button><!-- 【🎀学生列表】 --><el-table :data="studentList" border style="width: 100%;" max-height="530"><el-table-column fixed prop="oper_time" label="注册日期" width="170"></el-table-column><el-table-column type="index" fixed  label="序号" sortable="true" width="80"></el-table-column><el-table-column prop="name" label="姓名" width="70"></el-table-column><el-table-column prop="num" label="学号" width="70"></el-table-column><el-table-column prop="gender" label="性别" width="60"></el-table-column><el-table-column prop="majorName" label="专业" width="110"></el-table-column><el-table-column prop="birthday" label="生日" width="110"></el-table-column><el-table-column prop="birthday" label="生日" width="110"></el-table-column><el-table-column prop="birthday" label="生日" width="110"></el-table-column><el-table-column prop="address" label="地址" width="70"></el-table-column><el-table-column prop="phone" label="联系方式" width="90"></el-table-column><el-table-column  fixed="right" label="操作" width="190"><template slot-scope="scope"><el-button @click="" type="warning" icon="el-icon-edit" size="small"style="width: 40;">编辑</el-button><el-button @click="" size="small" type="danger" icon="el-icon-delete"style="width: 40;">移除</el-button></template></el-table-column></el-table></el-card></div>
</template><script>export default{data() {return{studentList: [],query:{queryName:"",queryNum:"",mark:"query"}}}}
</script><style>
</style>

🪀表单dalog模板

在这里插入图片描述
这里的数据可根据需要自行更换,响应事件可自己添加(可以自己更换)

🎀源码如下:

<template><div><!-- 【🎀新增信息】 --><el-dialog title="新增学生信息" :visible.sync="dialogFormVisible"><el-form :model="form" style="background-color: bisque;"><el-row><!-- 【🪀姓名】 --><el-col :span="4"><el-button type="success" style="width: 98px;">姓名</el-button> </el-col><el-col :span="6"><el-form-item><el-input v-model="form.name" maxlength="10" show-word-limitautocomplete="off"></el-input></el-form-item></el-col></el-row><el-row><!-- 【🪀学号】 --><el-col :span="4"><el-button type="success" style="width: 98px;">学号</el-button> </el-col><el-col :span="5"><el-form-item><el-input v-model="form.num" maxlength="10" show-word-limitautocomplete="off"></el-input></el-form-item></el-col></el-row><el-row><!-- 【🪀性别】 --><el-col :span="4"><el-button type="success" style="width: 98px;" plain>性别</el-button> </el-col><el-col :span="6"><el-radio v-model="form.gender" label=""></el-radio><el-radio v-model="form.gender" label=""></el-radio></el-col></el-row><el-row><!-- 【🪀专业】 --><el-col :span="4"><el-button type="success" style="width: 98px;" plain>专业</el-button> </el-col><el-col :span="6"><el-select v-model="form.majors" placeholder="请选择专业"><el-option v-for="item in form.major" :key="item.id" :label="item.name" :value="item.id"></el-option></el-select></el-col></el-row><el-row><!-- 【🪀生日】 --><el-col :span="4"><el-button type="success" style="width: 98px;" plain>生日</el-button> </el-col><el-col :span="7"><div class="block"><el-date-picker value-format="yyyy-MM-dd" v-model="form.birthday" align="right" type="date"placeholder="选择日期" :picker-options="pickerOptions"></el-date-picker></div></el-col></el-row><el-row><!-- 【🪀地址】 --><el-col :span="4"><el-button type="success" style="width: 98px;">地址</el-button> </el-col><el-col :span="18"><el-form-item><el-input type="textarea" :rows="2" placeholder="请输入地址" maxlength="20" show-word-limitv-model="form.address"></el-input></el-form-item></el-col></el-row><el-row><!-- 【🪀联系方式】 --><el-col :span="4"><el-button type="success" style="width: 98px;">联系方式</el-button> </el-col><el-col :span="18"><el-form-item><el-input v-model="form.phone" maxlength="15" show-word-limitautocomplete="off"></el-input></el-form-item></el-col></el-row></el-form><div slot="footer" class="dialog-footer"><el-button @click="concle()">取 消</el-button><el-button type="primary" @click="addSudent()">保 存</el-button></div></el-dialog></div>
</template><script>export default {data() {return {/* 【是否可见】 */dialogFormVisible: false,form: {name: '',num: '',gender: '',birthday: '',address: '',phone: '',delivery: false,major: [],majors: '',mark: 'add'},formLabelWidth: '120px',pickerOptions: {//【🎀日期选择器】disabledDate(time) {return time.getTime() > Date.now();}}}},methods: {concle() {this.$message({type: 'info',message: '退出成功!'});this.dialogFormVisible = false;},addSudent(){//【🎀请求事件自己添加~】this.$message({type: 'success',message:"保存成功!"});this.dialogFormVisible = false;//【🎀关闭对话框】}},mounted() {//【🎀获取专业信息】/* this.$http.get("admin/studentList?mark=major").then((resp) => {if (resp.data.code == 200) {this.form.major = resp.data.data;}}); */}}//将json对象序列化为键=值&键=值function jsonToString(jsonObj) {console.log(jsonObj);var str = "";for (var s in jsonObj) {str += s + "=" + jsonObj[s] + "&";}return str.substring(0, str.length - 1);}
</script><style scoped>
</style>

🎇刷新页面

this.$router.go();

🎀【🐒持续更新中…】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/87373.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言安装包Seurat

环境Ubuntu22&#xff0c;R4.1 also installing the dependencies ‘curl’, ‘openssl’, ‘httr’, ‘plotly’ R包安装的时候报了这个错误ERROR: dependencies httr, plotly are not available for package Seurat 解决方法&#xff0c;退出R&#xff0c;在terminal中键入…

C语言——指针进阶

本章重点 字符指针数组指针指针数组数组传参和指针传参函数指针函数指针数组指向函数指针数组的指针回调函数指针和数组面试题的解析 1. 字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* int main() { char ch w; char *pc &ch; *pc w; return 0; }…

Flink学习记录

可以快速搭建一个Flink编写程序 mvn archetype:generate \-DarchetypeGroupIdorg.apache.flink \-DarchetypeArtifactIdflink-quickstart-java \-DarchetypeVersion1.17.1 \-DgroupIdcom.zxx.langhuan \-DartifactIdlanghuan-flink \-Dversion1.0.0-SNAPSHOT \-Dpackagecom.zx…

ffmepg滤镜

视频按顺时针方向旋转90度 ffplay -vf transpose1 -i juren-30s.mp4 ffplay -f lavfi -i testsrc -vf transpose1 -f lavfi -i testsrc这个滤镜是ffmpeg给用户的一个测试使用的视频 视频水平翻转(左右翻转) -vf hflip 实现慢速播放&#xff0c;声音速度是原始速度的50% ffpla…

智慧家庭如何落地?三翼鸟把答案写在用户家里

近年来&#xff0c;学术界流行一句话&#xff0c;“把论文写在中国大地上”。 一项新技术从实验室到千万家&#xff0c;落地难、转化低&#xff0c;是技术创新经常碰到的问题。所以&#xff0c;如何让新技术扎根大地、扎根真实需求&#xff0c;普惠人间&#xff0c;是中国产学研…

构建Docker容器监控系统 (1)(Cadvisor +InfluxDB+Grafana)

目录 Cadvisor InfluxDBGrafana 1. Cadvisor 2.InfluxDB 3.Grafana 开始部署&#xff1a; 下载组件镜像 创建自定义网络 创建influxdb容器 创建数据库和数据库用户 创建Cadvisor 容器 准备测试镜像 创建granafa容器 访问granfana 添加数据源 Add data source 新建 …

开发过程中遇到的问题以及解决方法

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 开发过程中遇到的问题以及解决方法 简单易用的git命令 git命令&#xff1a; 查看有几个分支&#xff1a;git branch -a 切换分支&#…

设计模式(4)装饰模式

一、介绍&#xff1a; 1、应用场景&#xff1a;把所需的功能按正确的顺序串联起来进行控制。动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更加灵活。 当需要给一个现有类添加附加职责&#xff0c;而又不能采用生成子类的方法…

Linux查看GPU显卡/CPU内存/硬盘信息

显卡信息命令/CPU内存/硬盘 1.显卡2、CPU内存3、硬盘 1.显卡 nvidia-smi nvidia-smi&#xff08;显示一次当前GPU占用情况&#xff09; nvidia-smi -l&#xff08;每秒刷新一次并显示&#xff09; watch -n 5 nvidia-smi &#xff08;其中&#xff0c;5表示每隔6秒刷新一次终端…

2498. 青蛙过河 II;2568. 最小无法得到的或值;1954. 收集足够苹果的最小花园周长

2498. 青蛙过河 II 核心思想&#xff1a;这题有点开脑洞&#xff0c;就是如果想让代价最小只能是隔一个石头跳&#xff0c;因为其他方法的路径都会形成比这种方法大的结果&#xff0c;然后我们只需要统计出间隔石头的最大值即可。 2568. 最小无法得到的或值 核心思想&#xf…

在Ubuntu中使用Docker启动MySQL8的天坑

写在前面 简介&#xff1a; lower_case_table_names 是mysql设置大小写是否敏感的一个参数。 1.参数说明&#xff1a; lower_case_table_names0 表名存储为给定的大小和比较是区分大小写的 lower_case_table_names 1 表名存储在磁盘是小写的&#xff0c;但是比较的时候是不区…

白帽黑帽与linux安全操作

目录 白帽黑帽 Linux安全 白帽黑帽 白帽&#xff08;White Hat&#xff09;和黑帽&#xff08;Black Hat&#xff09;通常用于描述计算机安全领域中的两种不同角色。白帽黑客通常被认为是合法的安全专家&#xff0c;他们通过合法途径寻找和修复安全漏洞&#xff0c;帮助企业和…

Unity之ShaderGraph 节点介绍 Procedural节点

程序化 噪声Gradient Noise&#xff08;渐变或柏林噪声&#xff09;Simple Noise&#xff08;简单噪声&#xff09;Voronoi&#xff08;Voronoi 噪声&#xff09; 形状Ellipse&#xff08;椭圆形&#xff09;Polygon&#xff08;正多边形&#xff09;Rectangle&#xff08;矩形…

JavaScript 运行机制详解:再谈Event Loop

一、为什么JavaScript是单线程&#xff1f; JavaScript语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。那么&#xff0c;为什么JavaScript不能有多个线程呢&#xff1f;这样能提高效率啊。 JavaScript的单线程&#xff0c;与它的用途有关。…

【JVM】类装载的执行过程

文章目录 类装载的执行过程1.加载2.验证3.准备4.解析5.初始化6.使用7.卸载 类装载的执行过程 类装载总共分为7个过程&#xff0c;分别是 加载&#xff0c;验证&#xff0c;准备、解析、初始化、使用、卸载 1.加载 将类的字节码文件加载到内存(元空间&#xff09;中。这一步会…

AWS中Lambda集成SNS

1.创建Lambda 在Lambda中&#xff0c;创建名为AWSSNSDemo的函数 use strict console.log(loading function); var aws require(aws-sdk); var docClient new aws.DynamoDB.DocumentClient(); aws.config.regionap-southeast-1;exports.handler function(event,context,cal…

详细记录Pycharm配置已安装好的Conda虚拟环境

当安装好conda环境之后&#xff0c;想要在Pycharm中使用&#xff0c;那么就要在Pycharm中导入&#xff0c;我这里使用的pycharm-professional-2023.2这个版本&#xff0c;下面是详细步骤&#xff1a; 1.打开File->Settings&#xff1a; 2.找到Project——>Python Inter…

Openlayers实战:列表与图层双向信息提示

在Openlayers的实际项目中,经常会在左侧列出信息列表,右边的地图上显示的是对应的图层内容,两边是一一对应的,为了看出来选择的是哪一个,就需要两边互相提示,本示例就很好的展示了这种效果,具体的方法请参考源代码。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhu…

阶梯费用计算(配置化_最小demo)

本文旨在提供一种配置化思路计算阶梯费用&#xff0c;更高级的做法则是通过数据库配置&#xff0c;注册中心等&#xff1b;在表达式上可以采用自定义或者spel表达式等其他方式进行处理&#xff1b;(代码仅展示最小demo,部分不完善orBug地方自行补充) 思路&#xff1a;N个区间对…

【leetcode】前缀和

内容摘抄自&#xff1a; 小而美的算法技巧&#xff1a;前缀和数组 | labuladong 的算法小抄 一维数组的前缀和 看这个 preSum 数组&#xff0c;若想求索引区间 [1, 4] 内的所有元素之和&#xff0c; 就可以通过 preSum[5] - preSum[1] 得出。 class NumArray {private:// 前缀…