springboot + Vue前后端项目(第十七记)

项目实战第十七记

  • 写在前面
  • 1. 个人信息
    • 1.1 Person.vue
    • 1.2 设置路由并改动Header.vue
    • 1.3 动态刷新头像
      • 1.3.1 在保存个人信息时,触发方法
      • 1.3.2 父组件Manage.vue
      • 1.3.3 再将user以prop方式传递给子组件Header.vue
      • 1.3.4 Header.vue使用user
    • 1.4 效果图
  • 2. 修改密码
    • 2.1 前端页面编写(Password.vue)
    • 2.2 修改密码后退出系统
    • 2.3 路由设置并改动Header.vue
    • 2.4 后端接口编写
      • 2.4.1 UserController
      • 2.4.2 UserServiceImpl
      • 2.4.3 UserMapper
    • 2.5 页面效果
  • 总结
  • 写在最后

写在前面

  • 本篇主要讲解个人信息和修改密码页面,补充篇

1. 个人信息

1.1 Person.vue

<template><el-card style="width: 500px;"><el-form label-width="80px" size="small"><el-uploadclass="avatar-uploader"action="http://localhost:9000/file/upload":show-file-list="false":on-success="handleAvatarSuccess"><img v-if="form.avatarUrl" :src="form.avatarUrl" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload><el-form-item label="用户名"><el-input v-model="form.username" autocomplete="off"></el-input></el-form-item><el-form-item label="昵称"><el-input v-model="form.nickname" autocomplete="off"></el-input></el-form-item><el-form-item label="邮箱"><el-input v-model="form.email" autocomplete="off"></el-input></el-form-item><el-form-item label="电话"><el-input v-model="form.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="地址"><el-input v-model="form.address" autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="primary" @click="save">确 定</el-button></el-form-item></el-form></el-card></template><script>export default {name: "Person",data() {return {form: {},user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : {}}},created() {this.load();},methods: {load(){const username = this.user.usernameif(!username){this.$message.error("当前无法获取用户信息!");return false}// 数据库做了唯一性处理this.request.get("/user/username/"+username).then(res => {this.form = res.data})},save() {this.request.post("/user", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")//this.dialogFormVisible("保存成功")this.load()//向父组件传递值   触发方法this.$emit('refreshUser')} else {this.$message.error("保存失败")}})},handleAvatarSuccess(res) {console.log('===',res)//res就是文件的路径this.form.avatarUrl = res}}}</script><style>.avatar-uploader {text-align: center;padding-bottom: 10px;}.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;}.avatar-uploader .el-upload:hover {border-color: #409EFF;}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 138px;height: 138px;line-height: 138px;text-align: center;}.avatar {width: 138px;height: 138px;display: block;}</style>

1.2 设置路由并改动Header.vue

// 拼装动态路由const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }

在Header.vue中添加

<el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link>
</el-dropdown-item>

1.3 动态刷新头像

当更换头像时,点击确定时,实现头像的同步更新

1.3.1 在保存个人信息时,触发方法

save() {this.request.post("/user", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")this.load()/*这段Vue模板代码定义了一个方法,当调用这个方法时,会触发名为refreshUser的自定义事件。这个事件可以被父组件监听到,从而在父组件中执行相应的逻辑操作。**/this.$emit('refreshUser')} else {this.$message.error("保存失败")}})},

1.3.2 父组件Manage.vue

// 触发@refreshUser自定义事件
<el-main><!--  表示当前页面的子路由会在 <router-view/> 里面显示     --><router-view @refreshUser="getUser"/>
</el-main>// 获取用户的最新数据
getUser(){const username = localStorage.getItem('loginUser') ?         			 JSON.parse(localStorage.getItem('loginUser')).username : '';this.request.get('/user/username/' + username).then(res => {if(res.code == '200'){// 重新赋值后台的最新User数据this.user = res.data;}})}

1.3.3 再将user以prop方式传递给子组件Header.vue

<el-header style="border-bottom: 1px solid #ccc;"><Header :collapse-btn-class="collapseBtnClass" :collapse="isCollapse" :user="user"/>
</el-header>

完整的Manage.vue代码

<template><el-container style="min-height: 100vh"><el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 0.35);"><Aside :is-collapse="isCollapse" :logo-text-show="logoTextShow"/></el-aside><el-container><el-header style="border-bottom: 1px solid #ccc;"><Header :collapse-btn-class="collapseBtnClass" :collapse="isCollapse" :user="user"/></el-header><el-main><!--  表示当前页面的子路由会在 <router-view/> 里面显示     --><router-view @refreshUser="getUser"/></el-main></el-container></el-container>
</template><script>import Aside from "@/components/Aside";
import Header from "@/components/Header";export default {name: 'HomeView',components: {Aside,Header},data() {return {collapseBtnClass: 'el-icon-s-fold',isCollapse: false,sideWidth: 200,logoTextShow: true,headerBg: 'headerBg',user: {}}},created() {this.getUser()},methods: {collapse() {  // 点击收缩按钮触发this.isCollapse = !this.isCollapseif (this.isCollapse) {  // 收缩this.sideWidth = 64this.collapseBtnClass = 'el-icon-s-unfold'this.logoTextShow = false} else {   // 展开this.sideWidth = 200this.collapseBtnClass = 'el-icon-s-fold'this.logoTextShow = true}},// 获取用户的最新数据getUser(){const username = localStorage.getItem('loginUser') ? JSON.parse(localStorage.getItem('loginUser')).username : '';this.request.get('/user/username/' + username).then(res => {if(res.code == '200'){// 重新赋值后台的最新User数据this.user = res.data;}})}}
}
</script><style>
.headerBg {background: #eee!important;
}
</style>

1.3.4 Header.vue使用user

// 接收数据
props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 使用数据
<div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>

完整的Header.vue代码

<template><div style="line-height: 60px; display: flex"><div style="flex: 1;"><span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span><el-breadcrumb separator=">" style="display: inline-block; margin-left: 10px"><el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
<!--        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>--><el-breadcrumb-item v-for="(item, index) in breadCrumbs" :key="item.path"><router-link :to="item.path">{{ item.meta.title }}</router-link></el-breadcrumb-item></el-breadcrumb></div><el-dropdown style="width: 100px; cursor: pointer"><div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i></div><el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center"><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0"><span style="text-decoration: none" @click="logout">退出</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div>
</template><script>
export default {name: "Header",props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 当当前路由发生变化时,调用getBreadcrumb方法来更新面包屑导航的数据watch: {$route() {this.getBreadcrumb();}},data(){return {breadCrumbs: [],//user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : ""}},created() {this.getBreadcrumb()},methods: {getBreadcrumb(){// 从当前路由的匹配记录中过滤出具有meta属性且包含title属性的路由记录this.breadCrumbs = this.$route.matched.filter(item => item.meta && item.meta.title);},// 退出登录logout(){this.$router.push("/login");localStorage.removeItem("loginUser")this.$message.success("退出成功")}}// computed: {//   currentPathName () {//     return this.$store.state.currentPathName;  //需要监听的数据//   }// },}
</script><style scoped></style>

1.4 效果图

在这里插入图片描述
在这里插入图片描述
注意:上传的头像最好是正方形的大小,形成的头像才会是规整的

2. 修改密码

2.1 前端页面编写(Password.vue)

<template><el-card style="width: 500px;"><el-form label-width="120px" size="small" :model="form" :rules="rules" ref="pass"><el-form-item label="原密码" prop="password"><el-input v-model="form.password" autocomplete="off" show-password></el-input></el-form-item><el-form-item label="新密码" prop="newPassword"><el-input v-model="form.newPassword" autocomplete="off" show-password></el-input></el-form-item><el-form-item label="确认新密码" prop="confirmPassword"><el-input v-model="form.confirmPassword" autocomplete="off" show-password></el-input></el-form-item><el-form-item><el-button type="primary" @click="save">确 定</el-button></el-form-item></el-form></el-card>
</template><script>
export default {name: "Password",data() {return {form: {},user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : {},rules: {password: [{ required: true, message: '请输入原密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],confirmPassword: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],}}},created() {// 通过用户名和旧密码来唯一标识用户,然后再修改密码this.form.username = this.user.username},methods: {save() {this.$refs.pass.validate((valid) => {if (valid) {if (this.form.newPassword !== this.form.confirmPassword) {this.$message.error("2次输入的新密码不相同")return false}this.request.post("/user/password", this.form).then(res => {if (res.code === '200') {this.$message.success("修改成功")this.$store.commit("logout")} else {this.$message.error(res.msg)}})}})},}
}
</script><style>
.avatar-uploader {text-align: center;padding-bottom: 10px;
}
.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}
.avatar-uploader .el-upload:hover {border-color: #409EFF;
}
.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 138px;height: 138px;line-height: 138px;text-align: center;
}
.avatar {width: 138px;height: 138px;display: block;
}
</style>

2.2 修改密码后退出系统

// 退出系统
this.$store.commit("logout")

store文件下index.js

import Vue from 'vue'
import Vuex from 'vuex'
import router from "@/router";Vue.use(Vuex)export default new Vuex.Store({state: {currentPathName: ''},getters: {},mutations: {// setPath(state){//   state.currentPathName = localStorage.getItem('currentPathName')// },logout() {// 清空缓存localStorage.removeItem("loginUser")localStorage.removeItem("menus")router.push("/login")// 重置路由//resetRouter()}},actions: {},modules: {}
})

2.3 路由设置并改动Header.vue

// 拼装动态路由
const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }

完整的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Manage from '../views/Manage.vue'
import store from "@/store";Vue.use(VueRouter)
//定义一个路由对象数组
const routes = [{path: '/login',name: '登录',component: () => import('../views/Login.vue')},{path: '/register',name: '注册',component: () => import('../views/Register.vue')},{path: '/404',name: '404',component: () => import('../views/404.vue')}]//使用路由对象数组创建路由实例,供main.js引用
const router = new VueRouter({mode: 'history',base: process.env.BASE_URL,routes
})// 注意:刷新页面会导致页面路由重置
export const setRoutes = () => {const storeMenus = localStorage.getItem("menus");if (storeMenus) {// 获取当前的路由对象名称数组const currentRouteNames = router.getRoutes().map(v => v.name)if (!currentRouteNames.includes('Manage')) {// 拼装动态路由const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }const menus = JSON.parse(storeMenus)menus.forEach(item => {if (item.path) {  // 当且仅当path不为空的时候才去设置路由let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)} else if(item.children.length) {item.children.forEach(item => {if (item.path) {let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)}})}})// 动态添加到现在的路由对象中去router.addRoute(manageRoute)}}
}// 重置我就再set一次路由
setRoutes()// 路由守卫
router.beforeEach((to, from, next) => {// localStorage.setItem('currentPathName',to.name);   // 设置当前的路由名称,为了在Header组件中去使用// store.commit('setPath')    // 触发store的数据更新// 未找到路由情况if(!to.matched.length){const storeMenus = localStorage.getItem("menus");if(storeMenus){   // 有菜单没有找到路由,跳转至 404页面next("/404")}else {    // // 没有菜单,直接跳转至登录页next("/login")}}next()   // 放行路由
})export default router

Header.vue改动

<el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link>
</el-dropdown-item>

完整的Header.vue

<template><div style="line-height: 60px; display: flex"><div style="flex: 1;"><span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span><el-breadcrumb separator=">" style="display: inline-block; margin-left: 10px"><el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
<!--        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>--><el-breadcrumb-item v-for="(item, index) in breadCrumbs" :key="item.path"><router-link :to="item.path">{{ item.meta.title }}</router-link></el-breadcrumb-item></el-breadcrumb></div><el-dropdown style="width: 100px; cursor: pointer"><div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i></div><el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center"><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0"><span style="text-decoration: none" @click="logout">退出</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div>
</template><script>
export default {name: "Header",props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 当当前路由发生变化时,调用getBreadcrumb方法来更新面包屑导航的数据watch: {$route() {this.getBreadcrumb();}},data(){return {breadCrumbs: [],//user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : ""}},created() {this.getBreadcrumb()},methods: {getBreadcrumb(){// 从当前路由的匹配记录中过滤出具有meta属性且包含title属性的路由记录this.breadCrumbs = this.$route.matched.filter(item => item.meta && item.meta.title);},// 退出登录logout(){this.$router.push("/login");localStorage.removeItem("loginUser")this.$message.success("退出成功")}}// computed: {//   currentPathName () {//     return this.$store.state.currentPathName;  //需要监听的数据//   }// },}
</script><style scoped></style>

2.4 后端接口编写

2.4.1 UserController

@PostMapping("/password")
public Result updatePassword(@RequestBody UserPasswordDTO userPasswordDTO){if(StrUtil.isBlank(userPasswordDTO.getUsername()) || StrUtil.isBlank(userPasswordDTO.getPassword())){return Result.error(Constants.CODE_400,"参数错误");}userService.updatePassword(userPasswordDTO);return Result.success();}

用UserPasswordDTO接收前端传过来的表单参数

package com.ppj.entity.dto;import lombok.Data;@Data
public class UserPasswordDTO {private String username;private String password;private String newPassword;
}

2.4.2 UserServiceImpl

@Override
public void updatePassword(UserPasswordDTO userPasswordDTO) {int res = userMapper.updatePassword(userPasswordDTO);if(res<1){throw new ServiceException(Constants.CODE_600,"密码修改失败");}
}

2.4.3 UserMapper

package com.ppj.mapper;import com.ppj.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ppj.entity.dto.UserPasswordDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;/*** <p>*  Mapper 接口* </p>** @author ppj* @since 2024-04-20*/
@Mapper
public interface UserMapper extends BaseMapper<User> {int updatePassword(UserPasswordDTO userPasswordDTO);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ppj.mapper.UserMapper"><update id="updatePassword" parameterType="com.ppj.entity.dto.UserPasswordDTO">update sys_userset password = #{newPassword}where username = #{username} and password = #{password}</update></mapper>

2.5 页面效果

在这里插入图片描述

总结

  1. 这篇主要的难点是头像上传后的同步刷新;
  2. 修改密码其实是更新用户,通过用户名和旧密码确定唯一用户,然后才进行密码更改。

写在最后

如果此文对您有所帮助,请帅戈靓女们务必不要吝啬你们的Zan,感谢!!不懂的可以在评论区评论,有空会及时回复。
文章会一直更新

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

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

相关文章

配置 python 脚本操作Excel 环境

在已装python的前提下 一、安装依赖库 pip install pandas pip install openpyxl安装完后&#xff0c;可以在 Python 中运行以下命令来查看 pandas 或 openpyxl 的安装路径&#xff1a; import pandas as pd print(pd.__path__)import openpyxl print(openpyxl.__path__)二、测…

【CT】LeetCode手撕—415. 字符串相加

目录 题目1- 思路2- 实现⭐415. 字符串相加——题解思路 3- ACM 实现 题目 原题连接&#xff1a;415. 字符串相加 1- 思路 模式识别&#xff1a;字符串相加 逆向遍历过程模拟 数据结构 ① String res &#xff1a;记录res 、② carry 记录进位值① 定义两个整数遍历 nums1 …

本地项目上传到gitee

本地项目通过webstorm上传到gitee 1.登录gitee选择新建仓库 2.输入新建仓库的名字&#xff08;名字与本地项目名一致&#xff09; 3.复制链接 4.找到本地项目&#xff0c;选中地址输入cmd打开命令提示框 5.输入git init初始化git&#xff0c;生成.git文件 6.webstorm中打开项目…

Android修行手册-ImageView的adjustViewBounds和设置透明度

点击跳转>GameFramework文档系列&#xff08;二&#xff09;- 场景相关 点击跳转>GameFramework文档系列&#xff08;三&#xff09;- 日志管理和UI 点击跳转>GameFramework文档系列&#xff08;四&#xff09;- 事件订阅 点击跳转>保姆式Cocos合成大西瓜案例 …

JDK19特性

JDK19特性 一、JAVA19概述 JDK 19 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。 JDK 19 只有 7 个新特性: JEP 405: Record Patterns(记录模式)[1] (预览)JEP 422: Linux/RISC-V Port[2]JEP 424: Foreign …

qt 一个可以拖拽的矩形

1.概要 2.代码 2.1 mycotrl.h #ifndef MYCOTRL_H #define MYCOTRL_H#include <QWidget> #include <QMouseEvent>class MyCotrl: public QWidget {Q_OBJECT public://MyCotrl();MyCotrl(QWidget *parent nullptr); protected:void paintEvent(QPaintEvent *even…

DVWA 靶场 CSP Bypass 通关解析

前言 DVWA代表Damn Vulnerable Web Application&#xff0c;是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序&#xff0c;旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。 DVWA提供了一系列的漏洞场…

高速公路声光预警定向广播助力安全出行

近年来&#xff0c;高速重大交通事故屡见不鲜&#xff0c;安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段&#xff0c;创新、智能、高效的压降交通事故的发生概率&#xff0c;优化交通安全管控质量&#xff0c;是近年来交管部门的主要工作&#xff0c;也是…

STM32人工智能检测-筛选机器人

前言 本文描述了一种使用STM32进行机器人筛选的办法。筛选对象是我的粉s&#xff0c;删选办法是瞪眼法。 问题现象 每次当我的STM32 向外界发出一篇新的的报文&#xff0c;总能在1H之内得到focus&#xff0c;格式如下 [title][body][tail]于是我对各个focus 我报文的对象进…

Flask之模板

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、模板的基本用法 1.1、创建模板 1.2、模板语法 1.3、渲染模板 二、模板辅助工具 2.1、上下文 2.2、全局对象 2.3、过滤器 2.4、测试…

C语言| 数组倒置算法

数组倒置 方法一 1 定义两个数组a[5] b[5],两个循环变量i j 2 用for循环&#xff0c;把数组a的最后一个数&#xff0c;赋值给数组b第一个元素 3 输出数组b 【程序代码】 #include <stdio.h> int main(void) { int a[5] {11, 22, 33, 44, 55}; int b[5]; …

进程、线程的区别

进程、线程的关系 开工厂生产手机&#xff0c;制作一条生产线&#xff0c;这个生产线上有很多的器件以及材料。一条生产线就是一个进程。 只有生产线是不够的&#xff0c;使用找五个工人来进行生产&#xff0c;这个工人能够利用这些材料最终一步步的将手机做出来&#xff0c;这…

内外网映射访问内网服务器

如果本地有公网ip&#xff0c;比如连接的宽带有公网ip&#xff0c;可以直接通过路由配置转发就行了&#xff0c;如果本地没有公网ip&#xff0c;那就需要通过下面这种方式来访问内网服务器了。 1&#xff1a;首先内网服务器需要连接外网&#xff0c;可以通过网线或者WiFi都可以…

RabbitMQ实践——交换器(Exchange)绑定交换器

在《RabbitMQ实践——交换器&#xff08;Exchange&#xff09;和绑定&#xff08;Banding&#xff09;》一文中&#xff0c;我们实验了各种交换器。我们可以把交换器看成消息发布的入口&#xff0c;而消息路由规则则是由“绑定关系”&#xff08;Banding&#xff09;来定义&…

【JUC并发编程】

Java并发常见面试题总结&#xff08;上&#xff09; 线程 什么是线程和进程? 何为进程? 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。 在 Java 中&am…

Docker 搭建 MinIO 对象存储

Docker 搭建 MinIO 对象存储 一、MinIO MinIO 是一个高性能的对象存储服务器&#xff0c;用于构建云存储解决方案。MinIO 允许你存储非结构化数据&#xff08;如图片、视频、日志文件等&#xff09;以对象的形式。MinIO 提供简单的部署选项和易于使用的界面&#xff0c;允许你…

深度神经网络——什么是降维?

引言 什么是降维&#xff1f; 降维是用于降低数据集维度的过程&#xff0c;采用许多特征并将它们表示为更少的特征。 例如&#xff0c;降维可用于将二十个特征的数据集减少到仅有几个特征。 降维通常用于无监督学习任务 降维是一个用于降低数据集维度的过程&#xff0c;采用许…

【Mysql服务无法启动,使用 ibd数据文件恢复数据方法(windows版本)】

Mysql服务无法启动&#xff0c;使用 ibd数据文件恢复数据方法&#xff08;windows版本&#xff09; 前置条件 1.需要安装python3环境 2.查询本地python版本命令 python --version一&#xff1a;工具下载 1.github工具下载链接&#xff1a; https://github.com/ddcw/ibd2sql…

C语言| 数组倒置II

数组倒置第二种方法&#xff1a;直接在数组内进行倒置 第一个元素和最后一个元素交换&#xff0c; 第二个元素和倒数第二个元素交换 第三个元素和倒数第三个元素交换...... 数组元素个数为偶数&#xff0c;每个元素都能交换一次&#xff1b; 数组元素个数为奇数&#xff0c;最…

如何为自己的项目生成changelog

背景 在github上看到人家的更新日志感觉很cool&#xff0c;怎么能给自己项目来一套呢 环境信息 tdstdsdeMacBook-Pro demo-doc % node -v v14.18.1 tdstdsdeMacBook-Pro demo-doc % npm -v 6.14.15硬件信息 型号名称&#xff1a;MacBook Pro版本&#xff1a; 12.6.9芯片&…