当前位置: 首页 > news >正文

3.若依前后端分离版开发用户自定义配置表格功能

一、背景

在项目上线测试的时候,关于同一个界面的表格,不同的用户会出现不同的字段排列需求,有些用户希望把A字段排在最前面,有些用户则希望A字段不显示。针对这种情况,开发一个表格自定义配置的功能,每个用户根据自己的需求自己去设定表单字段的显示、隐藏、字段的宽度、左右固定等。

二、效果图

1.配置界面,可以拖动字段的顺序,是否显示、宽度、左右固定
在这里插入图片描述

三、实现方式

3.1 整体实现思路

将前端表格配置好的字段方式的Json存到数据库,用户打开界面的时候去数据库读取这个配置,前端用循环动态的渲染elemnet-table的表头即可。如果这个用户没有配置过,则读取默认的配置,默认配置写在前端一个JSON里面,每个vue界面的table设置一个table key用来标识table列表,数据库层面查找的时候根据用户code和tablekey来找到这个用户关于这个表格的配置。
最后’在前端进行动态渲染表头即可。整个功能的重点在于前端动态的拿到后端的json跟默认的存在前端的Json进行比较,然后生成最终的一个配置的json(注意:要以前端的默认Json为准,因为要考虑到字段的新增和删除的情况

3.2 建立配置表 test_table_config
 CREATE TABLE `test_table_config` (`Id` int NOT NULL AUTO_INCREMENT,`UserCode` varchar(100) COLLATE utf8mb4_bin NOT NULL COMMENT '用户编码',`TableKey` varchar(200) COLLATE utf8mb4_bin NOT NULL COMMENT '表名key',`TableConifgJsonStr` varchar(8000) COLLATE utf8mb4_bin NOT NULL COMMENT '配置的字段Json',`IsDelete` tinyint NOT NULL COMMENT '是否删除',`CreateTime` datetime DEFAULT NULL COMMENT '创建时间',`CreateUserId` int DEFAULT NULL COMMENT '创建人id',`UpdateTime` datetime DEFAULT NULL COMMENT '更新时间',`DeleteTime` datetime DEFAULT NULL COMMENT '删除时间',`UpdateUserId` int DEFAULT NULL COMMENT '更新用户',`DeleteUserId` int DEFAULT NULL COMMENT '删除人',PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='table配置表';
3.3 服务端test_table_config的crud
    /*** 新增table配置*/// @PreAuthorize("@ss.hasPermi('system:tableconfig:add')")public AjaxResult add( TestTableAddInput testTableAddInput){TestTableConfig  testTableConfig = new TestTableConfig();testTableConfig.setUserCode(this.getUsername());testTableConfig.setTableKey(testTableAddInput.getTableKey());testTableConfig.setTableConifgJsonStr(testTableAddInput.getTableConifgJsonStr());testTableConfig.setCreateUserId(this.getUserId());testTableConfig.setCreateBy(this.getUsername());testTableConfig.setCreateTime(new Date());testTableConfig.setIsDelete(0l);return toAjax(testTableConfigService.insertTestTableConfig(testTableConfig));}@Log(title = "编辑table配置", businessType = BusinessType.INSERT)@PostMapping@Anonymous@ApiOperation("编辑table配置")public   AjaxResult addAndUpdate(@RequestBody TestTableAddInput testTableAddInput){TestTableConfig  testTableConfig = new TestTableConfig();if(testTableAddInput.getTableConifgJsonStr() == null || testTableAddInput.getTableConifgJsonStr().length()==0){return  error("没有传入配置Json");}// 先查询testTableConfig = testTableConfigService.selectTestTableConfigByUserAndTableKey(this.getUsername(),testTableAddInput.getTableKey());if(testTableConfig==null) // 更新{return   add(testTableAddInput);}else{testTableConfig.setTableConifgJsonStr(testTableAddInput.getTableConifgJsonStr());// 修改return   edit(testTableConfig);}}/*** 修改table配置*///  @PreAuthorize("@ss.hasPermi('system:tableconfig:edit')")public AjaxResult edit(TestTableConfig testTableConfig){testTableConfig.setUpdateUserId(this.getUserId());testTableConfig.setUserCode(this.getUsername());testTableConfig.setUpdateTime(new Date());testTableConfig.setIsDelete(0l);return toAjax(testTableConfigService.updateTestTableConfig(testTableConfig));}
3.4 前端配置组件界面
<template><div>
<div><vuedraggable v-model="paramClounm"><transition-group><div v-for="(item,index) in paramClounm" :key="item.key" style="margin:10px; text-align: left;"><el-row :gutter="24"><el-col :span="8"> <el-checkbox  :label="item.label" v-model="item.visable"></el-checkbox></el-col><el-col :span="6"> <el-input-number v-model="item.width" placeholder="宽度"></el-input-number></el-col><el-col :span="4">  <el-checkbox v-model="item.isfix" label="固定"></el-checkbox></el-col><el-col :span="6">  <el-switch :span="8" v-model="item.fixlorr" active-text="固定右侧" inactive-text="固定左侧"></el-switch></el-col></el-row></div> </transition-group></vuedraggable></div><div><span slot="footer" class="dialog-footer"><el-button class="buttonLeft" type="primary" plain @click="recoverChecked">恢复默认</el-button><!-- <el-button @click="dialogVisible = false" class="buttonRight">取 消</el-button> --><el-button type="primary" @click="submit" class="buttonRight" >确 定</el-button></span></div></div></template>
<script>import vuedraggable from 'vuedraggable';import { getConfig, addAndUpdate  } from "@/api/system/tableconfig";export default{name: 'configTest',components: {vuedraggable},data(){return{paramClounm:[], // 参数列dialogVisible:false,}},// 计算属性computed:{activeFields: function(){//  alert(0);return this.fields.filter((item)=>{return item.visible;})}},// 加载完mounted(){// 加载列名 ;  this.loadingTableClounm(Object.assign([],this.$parent.$parent.teacherTableClonms));},methods:{      getRowKey(v){return v.id},// 指令之前beforeHandleCommand(index,row,command) {//alert(0);return {'index':index,'row':row,'command':command}},// 移动操作handleCommand(command) {switch(command.command) {case "search":this.search(command.index);break;case "edit":this.edit(command.index);break;case "delete":this.rowOperation(command.row.indexLine,"delete",command.row);break;case "moveTop":this.rowOperation(command.row.indexLine,"moveTop",command.row);break;case "moveUp":this.rowOperation(command.row.indexLine,"moveUp",command.row);break;case "moveDown":this.rowOperation(command.row.indexLine,"moveDown",command.row);break;case "moveBottom":this.rowOperation(command.row.indexLine,"moveBottom",command.row);break;};},// 加载表格的列loadingTableClounm(teacherTableClonms){this.paramClounm= Object.assign([],teacherTableClonms) ;},// 保存配置submit(){// alert(JSON.stringify(this.paramClounm));var objList = this.paramClounm;// 移除不需要存入数据库的属性,然后将Json存到数据库for(var i=0;i<objList.length;i++){var obj=objList[i];obj.sortNum =i; // 排序编号delete obj.ifRender;delete obj.renderFun;}// alert(JSON.stringify(objList));var inputData={tableConifgJsonStr:JSON.stringify(objList),tableKey: this.$parent.$parent.tableKey};addAndUpdate(inputData).then(res=>{this.$modal.msgSuccess("操作成功");window.location.reload();});},// 恢复默认recoverChecked(){//  this.checkedColumns=['编号','计划开始日期','计划完成日期','实际开始日期','实际完成日期'];//  this.fieldList=columnOptions;this.paramClounm= [];// 为了解决子组件改变导致父组件也跟着改变的问题this.paramClounm = Object.assign([],this.$parent.$parent.teacherTableDefaultClonms) ;  // alert(JSON.stringify(this.$parent.$parent.teacherTableDefaultClonms) );//window.location.reload();},edit(index,row){},},}</script>
3.5 前端Table界面对应table表头的配置Json
/********************************************** 功  能:teacher表列名* 创建人:cola* 创建时间:2023-08-11******************************************/
import Vue from 'vue'
const vm = new Vue()
export const 
columnOptions=
[{key:"id",label:"Id",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"name",label:"姓名",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"teachercode",label:"教师工号",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"fex",label:"性别",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"age",label:"年龄",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"createtime",label:"创建时间",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''
},{key:"isdelete",label:"删除",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''},{key:"deletetime",label:"删除时间",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''
},
{key:"updatetime",label:"更新时间",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:true,renderFun:(scope)=>{let   html="";html+="<span>";html+=  vm.parseTime(scope.row.updatetime,'{y}-{m}-{d}');html+= "</span>"return html;}
},
{key:"updateuserid",label:"更新人",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''
},
{key:"deleteuserid",label:"删除人",visable : true,width: 200,isfix : false,fixlorr: 0,ifRender:false,renderFun:''
},];
3.6 前端Table界面读取配置进行动态展示
<template><div class="app-container"><el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"><el-form-item label="姓名" prop="name"><el-inputv-model="queryParams.name"placeholder="请输入姓名"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="教师工号" prop="teachercode"><el-inputv-model="queryParams.teachercode"placeholder="请输入教师工号"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="性别 0 女 1男" prop="fex"><el-inputv-model="queryParams.fex"placeholder="请输入性别 0 女 1男"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="年龄" prop="age"><el-inputv-model="queryParams.age"placeholder="请输入年龄"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="是否删除" prop="isdelete"><el-inputv-model="queryParams.isdelete"placeholder="请输入是否删除"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="创建时间" prop="createtime"><el-date-picker clearablev-model="queryParams.createtime"type="date"value-format="yyyy-MM-dd"placeholder="请选择创建时间"></el-date-picker></el-form-item><el-form-item label="更新时间" prop="updatetime"><el-inputv-model="queryParams.updatetime"placeholder="请输入更新时间"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="删除时间" prop="deletetime"><el-date-picker clearablev-model="queryParams.deletetime"type="date"value-format="yyyy-MM-dd"placeholder="请选择删除时间"></el-date-picker></el-form-item><el-form-item label="创建人id" prop="createuserid"><el-inputv-model="queryParams.createuserid"placeholder="请输入创建人id"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="修改人id" prop="updateuserid"><el-inputv-model="queryParams.updateuserid"placeholder="请输入修改人id"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="删除人id" prop="deleteuserid"><el-inputv-model="queryParams.deleteuserid"placeholder="请输入删除人id"clearable@keyup.enter.native="handleQuery"/></el-form-item><el-form-item><el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button><el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button></el-form-item></el-form><el-row :gutter="10" class="mb8"><el-col :span="1.5"><el-buttontype="primary"plainicon="el-icon-plus"size="mini"@click="handleAdd">新增</el-button></el-col><el-col :span="1.5"><el-buttontype="success"plainicon="el-icon-edit"size="mini":disabled="single"@click="handleUpdate">修改</el-button></el-col><el-col :span="1.5"><el-buttontype="danger"plainicon="el-icon-delete"size="mini":disabled="multiple"@click="handleDelete">删除</el-button></el-col><el-col :span="1.5"><el-buttontype="warning"plainicon="el-icon-download"size="mini"@click="handleExport">导出</el-button></el-col><el-col :span="1.5"><el-buttontype="warning"plainicon="el-icon-download"size="mini"@click="openconifg">配置</el-button></el-col><right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar></el-row><!-- :data="teacherList" v-loading="loading"  :fixed="item.fixlorr==0? 'left':'right'"--><el-table :data="teacherList" v-loading="loading"   @selection-change="handleSelectionChange"  style="width: 400"><!-- <el-table-column type="selection" width="55" align="center"  :fixed="true" /> <template slot-name=''></template></el-table-column> --><el-table-column   v-for="item in this.teacherTableClonms " :key="item.key" :label="item.label"  :prop="item.key" :width="item.width" v-if="item.ifRender && item.visable" :fixed="item.isfix?item.fixlorr==0?left:right :false"><template slot-scope="scope" ><div  v-html="item.renderFun? item.renderFun(scope) : ''"></div></template></el-table-column><el-table-column :label="item.label" align="center" :prop="item.key" :width="item.width"  v-else-if="item.ifRender==false && item.visable" :fixed="item.isfix?item.fixlorr==0?'left':'right' :false" /><el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" ><template slot-scope="scope"><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleUpdate(scope.row)">修改</el-button><el-buttonsize="mini"type="text"icon="el-icon-delete"@click="handleDelete(scope.row)">删除</el-button></template></el-table-column><!-- <el-table-column label="id" align="center" prop="id" /><el-table-column label="姓名" align="center" prop="name" /><el-table-column label="教师工号" align="center" prop="teachercode" /><el-table-column label="性别 0 女 1男" align="center" prop="fex" /><el-table-column label="年龄" align="center" prop="age" /><el-table-column label="是否删除" align="center" prop="isdelete" /><el-table-column label="创建时间" align="center" prop="createtime" width="180"><template slot-scope="scope"><span>{{ parseTime(scope.row.createtime, '{y}-{m}-{d}') }}</span></template></el-table-column><el-table-column label="更新时间" align="center" prop="updatetime" /><el-table-column label="删除时间" align="center" prop="deletetime" width="180"><template slot-scope="scope"><span>{{ parseTime(scope.row.deletetime, '{y}-{m}-{d}') }}</span></template></el-table-column><el-table-column  label="创建人id" align="center" prop="createuserid" /><el-table-column label="修改人id" align="center" prop="updateuserid" /><el-table-column label="删除人id" align="center" prop="deleteuserid" />--></el-table><paginationv-show="total>0":total="total":page.sync="queryParams.pageNum":limit.sync="queryParams.pageSize"@pagination="getList"/><!-- 添加或修改测试_教师对话框 --><el-dialog :title="title" :visible.sync="open" width="500px" append-to-body><el-form ref="form" :model="form" :rules="rules" label-width="80px"><el-form-item label="姓名" prop="name"><el-input v-model="form.name" placeholder="请输入姓名" /></el-form-item><el-form-item label="教师工号" prop="teachercode"><el-input v-model="form.teachercode" placeholder="请输入教师工号" /></el-form-item><el-form-item label="性别 0 女 1男" prop="fex"><el-input v-model="form.fex" placeholder="请输入性别 0 女 1男" /></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="form.age" placeholder="请输入年龄" /></el-form-item><el-form-item label="是否删除" prop="isdelete"><el-input v-model="form.isdelete" placeholder="请输入是否删除" /></el-form-item><el-form-item label="删除时间" prop="deletetime"><el-date-picker clearablev-model="form.deletetime"type="date"value-format="yyyy-MM-dd"placeholder="请选择删除时间"></el-date-picker></el-form-item><el-form-item label="创建人id" prop="createuserid"><el-input v-model="form.createuserid" placeholder="请输入创建人id" /></el-form-item><el-form-item label="修改人id" prop="updateuserid"><el-input v-model="form.updateuserid" placeholder="请输入修改人id" /></el-form-item><el-form-item label="删除人id" prop="deleteuserid"><el-input v-model="form.deleteuserid" placeholder="请输入删除人id" /></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">确 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog><!-- 传入 参数--><el-dialog  title="配置表格列" :visible.sync="cofigshow" width="900px" append-to-body><ConfigTableTest :tableclounms="this.teacherTableClonms"></ConfigTableTest></el-dialog> </div>
</template><script>
import { listTeacher, getTeacher, delTeacher, addTeacher, updateTeacher } from "@/api/system/teacher";
import { getTableConfigByUserCodeAndTabelKey } from "@/api/system/tableconfig";
import  { columnOptions }  from "../../../tableclounm/teacherclounm";import ConfigTableTest from "../tableconfig/configtabletest.vue";import TableCloumRender from "../tableconfig/tableclounmrender.vue";
export default {name: "Teacher",components: {ConfigTableTest,TableCloumRender
},data() {return {// 遮罩层loading: true,// 选中数组ids: [],// 非单个禁用single: true,// 非多个禁用multiple: true,// 显示搜索条件showSearch: true,// 总条数total: 0,// 测试_教师表格数据teacherList: [],// 弹出层标题title: "",// 是否显示弹出层open: false,// 配置显示层cofigshow: false,// 表格的Key,用来自定义配置的标识 to do 命名规范定义 功能模_块功能界面_Table ?tableKey:'TeacherIndexTable',// 查询参数queryParams: {pageNum: 1,pageSize: 10,name: null,teachercode: null,fex: null,age: null,isdelete: null,createtime: null,updatetime: null,deletetime: null,createuserid: null,updateuserid: null,deleteuserid: null},// 表单参数form: {},// 表单校验rules: {},teacherTableClonms : [], // 获取后端返回的当前用户个性化配置的列名teacherTableDefaultClonms:[] //  获取js里面配置的列名};},created() {this.getTableConfig(); // 获取用户列表配置// alert(JSON.stringify(this.teacherTableClonms) );this.getList();},methods: {/** 查询测试_教师列表 */getList() {this.loading = true;listTeacher(this.queryParams).then(response => {this.teacherList = response.rows;this.total = response.total;this.loading = false;});},// 获取当前用户这个列表对应的配置:// 逻辑:// 1.先查询配置。// 2.如果这个用户还没配置 则取JS里面的默认配置。// 3.如果这个用户已经配置了,则取数据库里面保存的配置,然后循环比对存在js里面的字段,// 生成最后对应的配置(因为数据库里面没有存渲染的代码,考虑到字段的长度限制 8000 风险点 1 如果大宽表,需要修改数据库字段类型)。getTableConfig(){// 默认的配置 Object.assign防止  this.teacherTableDefaultClonms的变动影响columnOptionsthis.teacherTableDefaultClonms =  JSON.parse(JSON.stringify(columnOptions))  ; // alert(JSON.stringify(this.teacherTableDefaultClonms ));var param={tableKey:this.tableKey  // 表格的key 每个表格唯一};// 默认的配置 Object.assign防止  jsConfigClounms的变动影响columnOptionslet  jsConfigClounms =   Object.assign([],columnOptions); let  newClounms =[]; // 拼接成新的一个配置数组getTableConfigByUserCodeAndTabelKey(param).then(res=>{if(!!res){var data =JSON.parse(res.tableConifgJsonStr) ;// 以配置在JS里面的配置为循环的基础(需要考虑到增减字段)for(var  i=0;i<jsConfigClounms.length;i++){var jsClounmItem = jsConfigClounms[i];var newItem = jsClounmItem; // 新的项以JS的配置为基础,能设置的配置项取数据库里面的// 查询对应的配置// rfor(var j=0;j<data.length;j++){var dataItem = data[j];if(newItem.key == dataItem.key){// 说明匹配上了if(dataItem.visable!=null){newItem.visable = dataItem.visable; // 是否显示}if(dataItem.width!=null){newItem.width = dataItem.width;   // 宽度}if(dataItem.isfix!=null){newItem.isfix = dataItem.isfix;     // 是否固定}if(dataItem.fixlorr!=null){newItem.fixlorr = dataItem.fixlorr; // 固定左边or右边}if(dataItem.sortNum!=null){newItem.sortNum = dataItem.sortNum ; //排序编号}break; // 匹配上了,跳出一层循环} else{// 没有匹配上,则说明是新加的字段,把这些新加的字段放在最后newItem.sortNum = 10000-i; // 把排序号增加到最大} } // for 1 endnewClounms.push(newItem);}// for2 end// 这个时候需要排序一下,恢复顺序newClounms = newClounms.sort(this.sortByNum);}else{// 说明数据库里面没有配置,则直接取JS里面的配置newClounms = jsConfigClounms;}this.teacherTableClonms = newClounms;// alert(JSON.stringify(this.teacherTableDefaultClonms ));});},// 根据排序编码号进行排序
sortByNum(a, b) {return a.sortNum - b.sortNum;
},// 取消按钮cancel() {this.open = false;this.reset();},// 表单重置reset() {this.form = {id: null,name: null,teachercode: null,fex: null,age: null,isdelete: null,createtime: null,updatetime: null,deletetime: null,createuserid: null,updateuserid: null,deleteuserid: null};this.resetForm("form");},/** 搜索按钮操作 */handleQuery() {this.queryParams.pageNum = 1;this.getList();},/** 重置按钮操作 */resetQuery() {this.resetForm("queryForm");this.handleQuery();},// 多选框选中数据handleSelectionChange(selection) {this.ids = selection.map(item => item.id)this.single = selection.length!==1this.multiple = !selection.length},/** 新增按钮操作 */handleAdd() {this.reset();this.open = true;this.title = "添加测试_教师";},/** 修改按钮操作 */handleUpdate(row) {this.reset();const id = row.id || this.idsgetTeacher(id).then(response => {this.form = response.data;this.open = true;this.title = "修改测试_教师";});},/** 提交按钮 */submitForm() {this.$refs["form"].validate(valid => {if (valid) {if (this.form.id != null) {updateTeacher(this.form).then(response => {this.$modal.msgSuccess("修改成功");this.open = false;this.getList();//});} else {addTeacher(this.form).then(response => {this.$modal.msgSuccess("新增成功");this.open = false;this.getList();});}}});},/** 删除按钮操作 */handleDelete(row) {const ids = row.id || this.ids;this.$modal.confirm('是否确认删除测试_教师编号为"' + ids + '"的数据项?').then(function() {return delTeacher(ids);}).then(() => {this.getList();this.$modal.msgSuccess("删除成功");}).catch(() => {});},/** 导出按钮操作 */handleExport() {this.download('system/teacher/export', {...this.queryParams}, `teacher_${new Date().getTime()}.xlsx`)},/**打开配置 */openconifg(){this.cofigshow = true;}}
};
</script>
3.7 功能完成

在这里插入图片描述

相关文章:

3.若依前后端分离版开发用户自定义配置表格功能

一、背景 在项目上线测试的时候&#xff0c;关于同一个界面的表格&#xff0c;不同的用户会出现不同的字段排列需求&#xff0c;有些用户希望把A字段排在最前面&#xff0c;有些用户则希望A字段不显示。针对这种情况&#xff0c;开发一个表格自定义配置的功能&#xff0c;每个…...

【操作系统】24王道考研笔记——第三章 内存管理

第三章 内存管理 一、内存管理概念 1.基本概念 2.覆盖与交换 覆盖技术&#xff1a; 交换技术&#xff1a; 总结&#xff1a; 3.连续分配管理方式 单一连续分配 固定分区分配 动态分区分配 动态分区分配算法&#xff1a; 总结&#xff1a; 4.基本分页存储管理 定义&#xf…...

Spring缓存深入解析:@Cacheable的使用详解

摘要&#xff1a;在本文中&#xff0c;我们将深入研究Spring框架中的Cacheable注解。我们会通过详细的Java示例&#xff0c;探讨如何使用这个功能强大的注解来提升应用程序性能。 一、什么是缓存&#xff1f; 在计算机科学中&#xff0c;缓存是一种存储技术&#xff0c;用于保…...

软件配置安装(破解)--- jdk下载配置

下载jdk 如果有oracle账号的话直接登录下载你想要的版本 不然可以尝试镜像站 HUAWEI镜像&#xff1a;https://repo.huaweicloud.com/java/jdk/ 安装 配置&#xff08;细节&#xff09; 这里的JAVA_HOME就是java的家&#xff0c;也就是解压(或安装)之后的java的目录&#xff…...

idea使用docker生成镜像(打包镜像,导入镜像,导出镜像)

1&#xff1a;先下载安装dockerdesktop&#xff0c;安装成功后 2&#xff1a; 在cmd执行docker -v&#xff0c;查看安装的docker版本 C:\Users\dell>docker -v Docker version 24.0.5, build ced09963&#xff1a;需要启动 dockerdesktop应用&#xff0c;才算启动docker&a…...

wazuh环境配置

目录 一、wazuh的安装 1.1官方仓库安装 1.2虚拟机OVA安装 1.2.1 然后执行下面命令 1.2.2 这里还要下载脚本和config.yml配置文件&#xff0c;用来生成证书​编辑 1.2.3然后编辑config.yml文件&#xff0c;将下面的三个IP地址改为一样的 1.2.4运行./wazuh-certs-tool.sh以…...

【Linux】Linux下常用压缩解压缩指令及选项小结

0x00 前言 版本信息&#xff1a;Ubuntu 18.04.6 LTS 最后更新日期&#xff1a;2023.8.22 0x01 Linux下常用压缩解压缩指令小结 1.gzip指令 gzip file&#xff1a;压缩file文件为file.gz &#xff0c;但是只能压缩文件不能压缩目录&#xff0c;且不保留源文件。若想打包目录…...

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…...

A 题:震源属性识别模型构建与震级预测 :代码分析:

问题 1&#xff1a; 针对附件 1&#xff5e;8 中的地震波数据&#xff0c;找出一系列合适的指 标与判据&#xff0c;构建震源属性识别模型&#xff0c;进行天然地震事件&#xff08;附件 1&#xff5e;7&#xff09; 与非天然地震事件&#xff08;附件 8&#xff09;的准确区…...

源码分析CompletableFuture使用默认线程池ForkJoinPool的弊端

先说结论&#xff1a; 假如有20CompletableFuture任务并发执行时&#xff0c;都使用默认线程池ForkJoinPool&#xff0c;但cpu的核心数又小于3&#xff0c;那么就会新建20个线程&#xff08;不使用默认线程池了&#xff09;&#xff0c;这20个线程相互竞争cpu资源和内存&#x…...

连接pgsql数据库 sslmode sslrootcert sslkey sslcert 参数的作用

sslmode 参数的作用 sslmode 参数用于指定数据库连接时使用的 SSL 加密模式。SSL&#xff08;Secure Sockets Layer&#xff09;是一种加密协议&#xff0c;用于保护数据在客户端和服务器之间的传输过程&#xff0c;以增加数据传输的安全性。sslmode 参数可以设置不同的值&…...

从零学算法3

3.给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”&…...

宠物小程序开发

在当今社会&#xff0c;宠物已成为许多人生活中不可或缺的一部分。宠物市场的持续增长为创业者提供了巨大的商机。然而&#xff0c;作为一个创业者&#xff0c;要在竞争激烈的宠物市场中脱颖而出并不容易。因此&#xff0c;开发一个专属于自己的宠物小程序成为了解决这一难题的…...

07-Vue基础之综合案例——小黑记事本

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;懒惰受到的惩罚不仅仅是自己的失败&#xff0c;还有别人的成功。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章…...

vite4+vue3+electron23.3+ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包

vite4vue3electron23.3ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包 主要包依赖 "electron-store": "^8.1.0", //全局数据状态管理&#xff0c;可选择性安装"electron": "23.3.8","electron-builder": &q…...

限制 el-input 输入 emoji

1. 电脑如何输入 emoji 表情 ? 快捷键 win; 或 win. 2. 代码实现 <template><el-input v-model"input" placeholder"请输入内容" input"inputChange"></el-input> </template><script> export default {name: D…...

【AI】解决Number_Words的安装和使用

It appears that you encountered an error while trying to install the “Numbers_Words” package using the specific version 0.18.2 of the PEAR channel. The error message indicates that there was a problem unpacking the “Math_BigInteger-1.0.3” package, whi…...

开启MySQL的binlog日志

在/etc/my.cnf增加如下配置 #binlog相关 log-bin /testdata/mysql/log/bin/mysql-bin expire_logs_days 7 binlog-format ROW binlog_cache_size 4M max_binlog_cache_size 20G binlog_rows_query_log_events 1 binlog_row_image FULL sync_binlog 1 log_bin_trust_fun…...

【支付宝小程序】支付宝小程序自定义组件技术教程

&#x1f996;我是Sam9029&#xff0c;一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 **&#x1f431;‍&#x1f409;&#x1f431;‍&#x1f409;恭喜你&#xff0c;若此文你认为写的不错&#xff0c;不要吝啬你的赞扬&#xff0c…...

CSDN编程题-每日一练(2023-08-23)

CSDN编程题-每日一练(2023-08-23) 一、题目名称:圆小艺二、题目名称:连续子数组的最大和三、题目名称:投篮一、题目名称:圆小艺 时间限制:1000ms内存限制:256M 题目描述: 最近小艺酱渐渐变成了一个圆滑的形状-球!! 小艺酱开始变得喜欢上球! 小艺酱得到n个同心圆。 …...

解决:Appium Inspector刷新页面一直加载转圈

目录 问题&#xff1a;Appium Inspector刷新页面一直加载转圈 解决办法&#xff1a; 1.进入设置页面-电池-后台耗电管理 2.找到下面3个应用&#xff0c;修改为允许后台高耗电 问题&#xff1a;Appium Inspector刷新页面一直加载转圈 1、手机进行操作后&#xff0c;Appium I…...

Apache Doris 入门教程34:Join 优化

Bucket Shuffle Join Bucket Shuffle Join 是在 Doris 0.14 版本中正式加入的新功能。旨在为某些 Join 查询提供本地性优化&#xff0c;来减少数据在节点间的传输耗时&#xff0c;来加速查询。 它的设计、实现和效果可以参阅 上面的图片展示了Bucket Shuffle Join的工作原理…...

【神州数码】BGP路由器案例

SwitchB、SwitchC和SwitchD位于AS200中&#xff0c;SwitchA位于AS100中。SwitchA和SwitchB共享一个相同的网络段11.0.0.0。而SwitchB和SwitchD彼此物理上不相邻。 则SwitchA的配置如下&#xff1a; SwitchA(config)#router bgp 100SwitchA(config-router-bgp)#neighbor 11.1.1…...

gin框架实现大文件下载

在gin框架中实现大文件下载主要分为两个步骤&#xff1a; 将文件分块读取 由于大文件一次性读取会占用大量内存&#xff0c;容易导致内存溢出等问题&#xff0c;需要将文件分块读取&#xff0c;逐一发送给客户端。 在gin框架中&#xff0c;可以使用context.File方法向客户端…...

数据可视化-canvas-svg-Echarts

数据可视化 技术栈 canvas <canvas width"300" height"300"></canvas>当没有设置宽度和高度的时候&#xff0c;canvas 会初始化宽度为 300 像素和高度为 150 像素。切记不能通过样式去设置画布的宽度与高度宽高必须通过属性设置&#xff0c;…...

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞[2023-HW]

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞 一、漏洞描述二、漏洞影响三、网络测绘四、漏洞复现小龙POC检测: 五、 修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间…...

java反序列化泛型中json对象

使用 jackson的objectMapper 来实现 import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMa…...

Docker Compose一键管理容器

可以一键批量管理docker的容器。将所有需要创建的容器定义在compose配置文件中&#xff0c;通过一个命令一键可以创建并运行这些容器&#xff0c;而不需要一个一个启动。可以批量启动停止服务。 安装 #安装Docker-Compose并安装到/usr/local/bin/docker-compose curl -L &quo…...

API接口文档利器:Swagger 和 接口调试利器:Postman

2.接口相关工具 2.1API接口文档利器&#xff1a;Swagger 2.1.1Swagger介绍 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务 (https://swagger.io/)。 它的主要作用是&#xff1a; 使得前后端分离开发更加方便&#xff0…...

Redis手动实现分布式锁-Demo

1、pom文件依赖 <!--引入Redis操作依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 2、具体实现 package com.xch;import org.spring…...

有用dojo做的网站吗/图片优化是什么意思

本文主要向大家介绍了JAVA语言中字符串indexof() 的使用方法介绍&#xff0c;通过具体的内容向大家展示&#xff0c;希望对大家学习JAVA语言有所帮助。Java中字符串中子串的查找共有四种方法(indexof())indexOf 方法返回一个整数值&#xff0c;指出 String 对象内子字符串的开始…...

当当网网站建设方案/站长工具seo推广

&#xff08;一&#xff09;Spring IoC 重要概念 1、控制反转&#xff08;Inversion of control&#xff09;&#xff1a; 控制反转是一种通过描述&#xff08;在java中通过xml或者注解&#xff09;并通过第三方去产生或获取特定对象的方式。 控制反转IoC(Inversion of Control…...

深圳网站建设哪些/今日刚刚发生新闻事件

文章目录 1)、为什么要自定义UITabBarController2)、重复代码的抽取3)、统一所有控制器导航栏左上角和右上角的内容4)、"duplicate symbol _OBJC_METACLASS_$_类名 in:"错误的解决方案5)、创建UIBarButtonItem的代码为什么放在UIBarButtonItem分类中最合适?6)iOS开…...

环保主题静态网站模板下载/百度站长平台论坛

上一篇:04-Excel的基本设置本篇内容结构如下&#xff1a;本篇在章节中的位置5.文件打印尽管现在都在提倡无纸办公&#xff0c;但在具体的工作中将电子文档打印成纸质文档还是必不可少的。大多数Office软件用户都擅长使用Word软件打印文稿&#xff0c;而对于Excel的打印&#xf…...

社交app开发成本预算表/优化网站的方法有哪些

实现了 出/入 分别计数&#xff1b; - 检测类别&#xff1a;行人、自行车、小汽车、摩托车、公交车、卡车。 -支持yolov5s.pt yolov5x.pt yolov5m.pt yolov5l.pt模型...

潍坊 网站建设/各大引擎搜索入口

上半年流畅度的新机排名&#xff0c;哇&#xff01;第一名居然是这款2019-05-11 22:26:4510点赞6收藏29评论要了解更多流行资讯、玩机技巧、数码体验、科普深扒&#xff0c;点击右上角关注我-----------2019年到现在已经过半了&#xff0c;各大手机厂商的新机发布热潮也慢慢降了…...