【工作出现的一些问题记录】

代码类

前端

elementUI

前后端交互出现的问题
  1. 使用window.open的get方式传入参数到后端接口时出现AES解密报非16倍数的错误
    前端:其中Encrypt是前端AES加密,方法可在utils见
let req = freeUser+","+freeUserPass+","+new Date().getTime()
        window.open(baseUrl+'/ivasys/freeLogin?freeUsers='+Encrypt(req),'_blank')

后端:desEncryptTY是java后端解密方法见utils

try {
			if(!StrUtils.isEmpty(freeUsers)){
				freeUsers = AesEncryptUtil.desEncryptTY(freeUsers).trim();
				Users = freeUsers.split(",");
			}else{
				logger.info("传入参数为空");
				return new RedirectView(uri, true, false);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

在这里插入图片描述

解决方案:

前端url的base64加密(aes以16字节为组,用base64加密)中出现“+”等字符在地址中可能会被解析为空格
用urlencode加密,urlencode会将特殊符号加入
后端解密即可
⚠️:urlencode
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ’ ( ) 。
该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?😡&=+$,#
⚠️:上面的都解决不了都话还有一种方法:
在try里面加个替换空格为+ 的操作

该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?😡&=+$,#

代码:
前端

let req = freeUser+","+freeUserPass+","+new Date().getTime()
        window.open(baseUrl+'/ivasys/freeLogin?freeUsers='+encodeURI(Encrypt(req)),'_blank')

后端:

try {
			freeUsers = URLDecoder.decode(freeUsers,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.info("URL解密失败");
			e.printStackTrace();
		}
vue双向绑定失效

出现原因1: 表单绑定失败
解决方法如下:

this.$set(this.form,"phone",this.$route.query.mobile)
或者:
将this用vm替代
vm.$forceUpdate();

出现原因2: 页面返回参数

params.callback();

删除该行

table组件封装

使用render渲染

el-tab

实现功能:el-tab同一个页面标签页的切换
如:a和b页面,从b页面的某个dialog的按钮跳转到a子页面
b页面按钮方法:

handleConfig:function (data){
            let vm = this
            vm.containerVisible = false;
            vm.$router.push({path:'a页面路径?activeName=first&containerName='+data.row.onlyName});
            this.reload() //通过reload刷新返回到当前页面
          },

reload刷新页面不会将地址的参数等清除
此时a页面的搜索栏会自动带上变量值进行搜索
a页面方法:

mounted() {
    this.showface();
  },
  showface(){
      if(this.$route.query.activeName!=null){
        this.activeName = this.$route.query.activeName;
        this.containerName = this.$route.query.containerName;
        this.loading = true;
        this.$refs.Container.refresh(this.containerName);  //这里写一些跳转后必须要执行的函数
      }
    },
localStorage

Object.assign()与JSON.parse区别
this.$set(this.dataVirtual, ‘yunIp’, resData.res.data[0].ip)

set代码: //这里注意每个参数格式都要转换后才能被存储

localStorage.setItem('areasTree',JSON.stringify(res.res))

get代码:

this.tableTreeDdata = []
let treeData = JSON.parse(localStorage.getItem('areasTree'))
if(treeData!=null && treeData!=undefined){
  this.tableTreeDdata.push(treeData)
}
el-collapse折叠

template:

<el-collapse v-model="activeNames" @change="handleChange">
          <el-collapse-item title="算法挂载目录" name="5">
            <div v-for="(item,index) in dataForm.algs" >
              <el-row>
                <el-col :span="11"><el-form-item
                  label-width="10px"
                  label=" "
                  :key="'domainensalg'+ index"
                  :prop="'algs.'+ index+'.volume'"
                  :rules="{required: true, message: '宿主机目录不能为空', trigger: 'blur'}">
                  <el-input v-model="item.volume" placeholder="请输入宿主机目录" style="width: 280px;float: left"></el-input>
                </el-form-item></el-col>
                <el-col :span="2">-</el-col>
                <el-col :span="11"><el-form-item
                  label-width="10px"
                  label=" "
                  :key="'domainensalg'+ index"
                  :prop="'algs.'+ index+'.volumeMount'"
                  :rules="{required: true, message: '镜像目录不能为空', trigger: 'blur'}">
                  <el-input v-model="item.volumeMount" placeholder="请输入镜像目录" style="width: 280px;float: left"></el-input>
                </el-form-item></el-col>
              </el-row>
            </div>
                <el-button class="rightButton" icon="fa fa-plus" type="primary" size="small" @click="addCmd(5)" />
                <el-button class="leftButton" icon="fa fa-minus" type="primary" size="small" @click="delCmd('algs')" />
          </el-collapse-item>
        </el-collapse>

data:

activeNames: ['1','3'],

methods:

addCmd(index) {
        if(index==1){
          vm.dataForm.cmds.push({cmd: ''})
        }else if(index==2){
          vm.dataForm.envs.push({name:'',value:''})
        }else if(index==3){
          vm.dataForm.ips.push({ip:'',host:''})
        }else if(index==4){
          vm.dataForm.basics.push({name:'',volume:'',volumeMount:'',readOnly:"true"})
        }else if(index==5){
          vm.dataForm.algs.push({volume:'',volumeMount:''})
        }else if(index==6){
          vm.dataForm.algServices.push({volume:'',volumeMount:''})
        }
      },
      delCmd(type) {
        if (vm.dataForm[type].length> 0) {
          vm.dataForm[type].splice(0, 1)
        }
      },
refs表单

重置表单validate

this.$refs['dataForm'].resetFields()

指定清除某表单字段验证

this.$refs["字段"].clearValidate()
el-tree

实现效果如下:
在这里插入图片描述
template:

<el-input placeholder="输入关键字进行过滤" v-model="filterText">
</el-input>
<el-tree class="filter-tree" :data="tableTreeDdata" :props="defaultProps" node-key="code" 
default-expand-all :filter-node-method="filterNode" @node-click="handleNodeClick" ref="tree">
</el-tree>

js:


import PopupTreeInput from "@/components/PopupTreeInput"//见下面的组件封装代码

data:

filterText: '',
tableTreeDdata: [],
defaultProps: {
					children: 'children',
					label: 'name'
				},

methods:

filterText(val) {
				this.$refs.tree.filter(val);
			}
filterNode(value, data) {
				if(!value) return true;
				return data.name.indexOf(value) !== -1;
			},
handleNodeClick: function(data, node, obj) {
				if(data.code == 0 || data.code == "0")
					data.code = null
				this.filters.areaCode = data.code;
				this.findPage(null)
			},

popTree代码封装:

<template>
  <div>
    <el-popover ref="popover" :placement="placement" trigger="click">
      <el-tree
        class="treeinput"
        :data="data"
        :props="props"
        node-key="nodeKey"
        ref="popupTree"
        @current-change="currentChangeHandle"
        :default-expand-all="defaultExpandAll"
        :highlight-current="true">
      </el-tree>
    </el-popover>
    <el-input v-model="prop" v-popover:popover :readonly="true" :placeholder="placeholder" style="cursor:pointer;"></el-input>
  </div>
</template>

<script>
export default {
  name: 'PopupTreeInput',
  props: {
    data: {
      type: Array,
      default: []
    },
    props: {
      type: Object,
      default: {}
    },
    prop: {
      type: String,
      default: ''
    },
    nodeKey: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: '点击选择内容'
    },
    placement: {
      type: String,
      default: 'bottom-start'//top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
    },
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    currentChangeHandle: {
      type: Function,
      default: null
    }
  }
}
</script>

<style scoped>
.treeinput{
  width:200px;
  height:200px;
  overflow:scroll;
}
</style>

el-tree的另一种封装-实现效果如下:
在这里插入图片描述
表单:

<el-form-item label="所属地区" prop="areaCode">
                <SelectTree
                  :props="props"
                  :options="optionData"
                  :value="''+dataForm.areaCode"
                  :clearable="isClearable"
                  :isRoot="isRoot"
                  :accordion="isAccordion"
                  @getValue="getValue($event)"
                />
</el-form-item>

data:

isRoot: true,
isClearable: true, // 可清空(可选)
isAccordion: true, // 可收起(可选)
props: {
          // 配置项(必选)
          value: "id",
          label: "name",
          children: "children"
          // disabled:true
        },

computed:

computed: {
      /* 转树形数据 */
      optionData() {
        let cloneData = JSON.parse(JSON.stringify(this.treeList)); // 对源数据深度克隆
        return cloneData.filter(father => {
          // 循环所有项,并添加children属性
          let branchArr = cloneData.filter(child => father.id == child.parentId); // 返回每一项的子级数组
          branchArr.length > 0 ? (father.children = branchArr) : ""; //给父级添加一个children属性,并赋值
          return father.parentId == 0; //返回第一层
        });
      }
    },

methods:

getValue(value) {
        this.dataForm.areaCode = value;
      },
//data赋值
// 获取数据
			findTreeData: function() {
        this.tableTreeDdata = []
        let treeData = JSON.parse(localStorage.getItem('areasTree'))
        if(treeData!=null && treeData!=undefined) {
          this.tableTreeDdata.push(treeData)
        }else{
          var req = {level:2}
          this.$api.area.findTree(req).then((res) => {
            if(res.res!=null){
              localStorage.setItem('areasTree',JSON.stringify(res.res))
              this.tableTreeDdata.push(res.res)
            }
            this.editLoading = false
          })
        }

			},

selectTree组件封装:

<template>
  <el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle" ref="select">
    <el-input
      class="selectInput"
      :placeholder="placeholder"
      v-model="filterText">
    </el-input>

    <el-option :value="valueTitle" :label="valueTitle" class="options">
      <el-tree  id="tree-option"
                ref="selectTree"
                :accordion="accordion"
                :data="options"
                :props="props"
                :node-key="props.value"
                :default-expanded-keys="defaultExpandedKey"
                :filter-node-method="filterNode"
                @node-click="handleNodeClick">
      </el-tree>
    </el-option>
  </el-select>
</template>

<script>
export default {
  name: "el-tree-select",
  props:{
    /* 配置项 */
    props:{
      type: Object,
      default:()=>{
        return {
          value:'id',             // ID字段名
          label: 'title',         // 显示名称
          children: 'children'    // 子级字段名
        }
      }
    },
    /* 选项列表数据(树形结构的对象数组) */
    options:{
      type: Array,
      default: ()=>{ return [] }
    },
    /* 初始值 */
    value:{
      type: String,
      default: ()=>{ return null }
    },
    /* 可清空选项 */
    clearable:{
      type:Boolean,
      default:()=>{ return true }
    },
    /* 自动收起 */
    accordion:{
      type:Boolean,
      default:()=>{ return false }
    },
    /* 选择根节点 */
    isRoot:{
      type:Boolean,
      default:()=>{ return false }
    },
    placeholder:{
      type:String,
      default:()=>{return "检索关键字"}
    }
  },
  data() {
    return {
      filterText: '',
      valueId:this.value,    // 初始值
      valueTitle:'',
      defaultExpandedKey:[]
    }
  },
  mounted(){
    this.initHandle()
  },
  methods: {
    // 初始化值
    initHandle(){
      if(this.valueId){
        var node = this.$refs.selectTree.getNode(this.valueId)
        if(node){
          this.valueTitle = this.$refs.selectTree.getNode(this.valueId).data[this.props.label]     // 初始化显示
          this.$refs.selectTree.setCurrentKey(this.valueId)       // 设置默认选中
          this.defaultExpandedKey = [this.valueId]      // 设置默认展开
        }else{
          this.clearHandle()  // 如果valueId不存在,清除选中
        }
      } else {
        this.clearHandle()
      }
      this.initScroll()
    },
    // 初始化滚动条
    initScroll(){
      this.$nextTick(()=>{
        let scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]
        let scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')
        scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'
        scrollBar.forEach(ele => ele.style.width = 0)
      })
    },
    // 切换选项
    handleNodeClick(node){
      if (this.isRoot) {
        this.valueTitle = node[this.props.label]
        this.valueId = node[this.props.value]
        this.$emit('getValue',this.valueId)
        this.defaultExpandedKey = []
      } else {
        this.valueTitle = node[this.props.label]
        this.valueId = node[this.props.value]
        this.$emit('getValue',this.valueId)
        this.defaultExpandedKey = []
      }
    },
    // 清除选中
    clearHandle(){
      this.valueTitle = ''
      this.valueId = null
      this.defaultExpandedKey = []
      for (let i = 0; i < this.options.length; i++) {
        let nodes = this.$refs.selectTree.store.nodesMap[this.options[i][this.props.value]]
        if(nodes){
          this.$refs.selectTree.store.nodesMap[this.options[i][this.props.value]].expanded = false
        }
        // if (typeof(this.$refs.selectTree.store.nodesMap[this.options[i][this.props.value]].expanded) != undefined) {
        //   this.$refs.selectTree.store.nodesMap[this.options[i][this.props.value]].expanded = false
        // }
      }
      this.clearSelected()
      this.$emit('getValue',null)
    },
    /* 清空选中样式 */
    clearSelected(){
      let allNode = document.querySelectorAll('#tree-option .el-tree-node')
      allNode.forEach((element)=>element.classList.remove('is-current'))
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    }
  },
  watch: {
    value(){
      this.valueId = this.value
      this.$refs.select.handleClose()
      this.initHandle()
    },
    filterText(val) {
      this.$refs.selectTree.filter(val);
    }
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
  height: auto;
  max-height: 274px;
  padding: 0;
  overflow: hidden;
  overflow-y: auto;
}
.el-select-dropdown__item.selected{
  font-weight: normal;
}
ul li >>>.el-tree .el-tree-node__content{
  height:auto;
  padding: 0 20px;
}
.el-tree-node__label{
  font-weight: normal;
}
.el-tree >>>.is-current .el-tree-node__label{
  color: #409EFF;
  font-weight: 700;
}
.el-tree >>>.is-current .el-tree-node__children .el-tree-node__label{
  color:#606266;
  font-weight: normal;
}
.selectInput{
  padding: 0 5px;
  box-sizing: border-box;
}
</style>

父子调用,相互传值

父页面:
template:

<ConConfig v-if="configCreate" ref="ConConfig" @listen-add-config="listenAddConfig" @closeListDialog="closeListDialog"> </ConConfig>

js:

import ConConfig from "@/views/ConConfig"
export default {
    components: {
    ConConfig,
    },
    data...
}

data:

configCreate:false,

父页面收到子页面的回调方法:

listenAddConfig:function(){
  if(this.$refs.ConConfig.newData)
      this.initConfig(this.yunId,this.imgName,this.versions)
},

父页面调用子页面方法:

//新增对话框
handleAddConfig: function() {
  this.configCreate = true
  //未避免执行顺序乱序
  var st=setTimeout(() => {       	    
this.$refs.ConConfig.open(this.yunId,this.imgName,this.versions);
 },0)
},

子页面open方法:

open(yunId,imgName,versions) {
        this.imgName= imgName
        this.versions=versions
        this.yunId = yunId
        this.operation = true
        this.tableVisible = false
        this.dialogVisible = true
      },

子页面回传值给父页面:

this.newData = true
this.$emit('listen-add-config', this.newData);
js LocalStorage

存储JSON对象、存储数组

js Array filter()

返回数组 ages 中所有元素都大于 18 的元素:

var ages = [32, 33, 16, 40];
function checkAdult(age) {
    return age >= 18;
}
function myFunction() {
document.getElementById("demo").innerHTML = ages.filter(checkAdult);
}

vue实例:

let filterType = this.abilitys.filter((x) => {
        return x.value == row.ability;
      })

js search 方法:

var str="Visit Runoob!"; 
var n=str.search("Runoob");

vue实例:

this.filerAbilitys = this.abilitys.filter((x) => {
          return x.type.search(obj) != -1;
        })
页面刷新
export default {
    inject: ['reload'],
    }

方法调用:
this.reload()

进度条el-progress

template-el-table:

<el-table-column prop="startTime" label="任务进度" minWidth="120" header-align="center" align="center">
  <template slot-scope="scope">
    <el-progress :text-inside="true" :stroke-width="18" :percentage="progressFormat(scope.$index,scope.row)" :color="scope.row.color">
    </el-progress>
  </template>
</el-table-column>

methods:

progressFormat: function(indexTest, row) {
				var systime = new Date();
				row.color = 'green';
				var percent = 100;
				var jiange = 0;
				if(row.status == 0) {
					row.color = 'blue';
					if(row.type == 4 || row.type == 1 || row.type == 8) {
						jiange = 10 * 1000;
						var start = new Date(row.startTime)
						var index = Math.ceil((systime.getTime() - start.getTime()) / jiange);
						if(index < 0)
							index = 1;
						if(index > 99)
							index = 99;
						percent = index;
					} else {
						jiange = 2 * 1000;
						percent = 99;
					}
					//lun = window.setInterval(lunxun, jiange);
				} else if(row.status == 2 || row.status == '2') {
					row.color = 'red';
				} else
					row.color = 'green';

				return percent;
			},
页面跳转

一:js的跳转

1.直接跳转:window.location.href

<script language="javascript" type="text/javascript">
    window.location.href="login.jsp?backurl="+window.location.href; 
    //或者
   window.location.href='http://www.baidu.com';
</script>

2.回到上一层页面 window.history.back(-1)

<script language="javascript">
    //标签嵌套:
    <a href="javascript:history.go(-1)">返回上一步</a>
</script>

二:vue跳转
1.在template中的常见写法:

<router-link to="/miniCard/statement/horizon">
     <button class="btn btn-default">点击跳转</button>
</router-link>

2.this.$router.go()

  this.$router.go(1)  //在浏览器记录中前进一步
    this.$router.go(-1) //后退一步记录
  this.$router.go(3) //前进三步记录

3.this.$router.push()

  A:this.$router.push({ path: '/home', query: { site: '1111'} }) 
query传参,用path属性对应跳转路径,类似于get提交,参数是在路径里显示的。
  子页面接收时 var cityId = this.$route.query.cityId
  
  B:this.$router.push({ name: 'Home', params: { site: '2222'} })
params传参,用name属性对应跳转路径,类似于post提交,参数不会出现在跳转路径里。
  子页面接收时 var cityId = this.$route.params.cityId

  两个同级页面,用query传参。A通过路由带参跳转到B页面,然后通过参数过滤掉B页面的一些数据。
  之后刷新B页面,由于参数是在路径里的,还是过滤掉的数据,这个时候要么在B页面入口进 入B页面,要么就得在页面再做处理才能符合需求,改用params之后就没这个问题了。
  1. this.$router.replace() 用法同上
     打开新的页面,不会像history添加新纪录,而是直接替换掉当前记录。点击返回,会跳转到上上一个页面。上一个记录是不存在的。
批量导入导出

template:

<el-form-item>
          <kt-button
            icon="fa fa-arrow-circle-right"
            :label="$t('action.export')"
            perms="openapi:excel:pmexport"
            type="primary"
            :loading="exportLoading"
            @click="exportExcel"
          />
        </el-form-item>
        <el-form-item>
          <el-upload
            style="display: none"
            action
            ref="upload"
            :http-request="importExcel"
            :multiple="false"
            :auto-upload="true"
            :show-file-list="false"
            :limit="1"
            accept=".xls, .xlsx"
            :with-credentials="true"
          >
            <el-button ref="uploadBtn" />
          </el-upload>
          <kt-button
            icon="fa fa-arrow-circle-left"
            :label="$t('action.import')"
            perms="openapi:excel:pmimport"
            type="primary"
            :loading="importLoading"
            @click="triggerUpload"
          />
</el-form-item>

js:

//导出Excel文件
    exportExcel() {
      this.exportLoading = true;
      //1、获取总查询数据
      let httpCode = this.filters.httpCode == "" ? null : this.filters.httpCode;
      let httpName = this.filters.httpName == "" ? null : this.filters.httpName;
      if ('_' == httpCode) {
        httpCode = '/_'
      }
      if ('_' == httpName) {
        httpName = '/_'
      }
      //筛选条件
      const para = {
        version: this.filters.version == "" ? null : this.filters.version,
        mfCode: this.filters.mfCode == "" ? null : this.filters.mfCode,
        httpCode: httpCode,
        algCode: this.filters.algCode == "" ? null : this.filters.algCode,
        httpName: httpName,
        source: this.filters.source,
        pageNum: 1,
        pageSize: this.pageResult.totalRow
      };
      this.$api.httpinfo
        .findPage(para, { HEADMECNODE: "HEADMECNODE" })
        .then((res) => {
          if (res.resultCd == 0) {
            let data = res.res.data;
            if (data.length == 0) {
              this.exportLoading = false;
              this.$message({ message: "数据为空,导出失败", type: "error" });
              return;
            }
            //2、导出excel文件
            this.$api.httpexcel
              .pmExport(JSON.stringify(data), { HEADMECNODE: "HEADMECNODE" })
              .then((res) => {
                this.exportLoading = false;
                //responseType为arryBuffer,成功返回的是文件流,失败为json,则成功会转化json异常
                let json = null;
                try {
                  var enc = new TextDecoder("utf-8");
                  json = JSON.parse(enc.decode(new Uint8Array(res))); //转化成json对象
                  if (json.resultCd === -1) {
                    this.$message({
                      message: "导出失败," + json.msg,
                      type: "error",
                    });
                  }
                } catch (e) {
                  //成功返回时会解析异常
                  var a = document.createElement("a");
                  // 字符内容转变成blob地址
                  var blob = new Blob([res], {
                    type: "application/vnd.ms-excel;charset=utf-8",
                  });
                  var url = window.URL.createObjectURL(blob);
                  a.href = url;
                  a.download = "北向接口配置信息.xlsx";
                  a.click();
                  window.URL.revokeObjectURL(url);
                }
              });
          } else {
            this.exportLoading = false;
            this.$message({ message: "导出失败," + res.msg, type: "error" });
          }
        });
    },
    //导入Excel文件
    importExcel(content) {
      this.importLoading = true;
      var form = new FormData(); // FormData 对象
      form.append("file", content.file); // 文件对象
      this.$api.httpexcel
        .pmImport(form, { HEADMECNODE: "HEADMECNODE" })
        .then((res) => {
          this.importLoading = false;
          if (res.resultCd == 0) {
            this.$message({ message: "导入成功", type: "success" });
            //刷新
            this.findPage(null);
          } else {
            this.$message({ message: "导入失败," + res.msg, type: "error" });
          }
          //清空上传文件
          this.$refs.upload.clearFiles();
        });
    },
    //自定义组件按钮触发el-upload的选择文件框
    triggerUpload() {
      this.$refs.uploadBtn.$el.click();
    },

java代码见代码文件

后端

深入理解Java并发之synchronized实现原理
【Java 8 新特性】如何将Java流转化成数组
Optional 类
toString()与new String ()用法区别

定义一个经过Base64加密的字符串
String str=“TU0jV0xBTiNVYys5bEdiUjZlNU45aHJ0bTdDQStBPT0jNjQ2NDY1Njk4IzM5OTkwMDAwMzAwMA==”
现在解密:
=
String rlt1=new String( Base64.decode(str, Base64.DEFAULT));
String rlt2=Base64.decode(str, Base64.DEFAULT).toString();
结果是:
rlt1=“MM#WLAN#Uc+9lGbR6e5N9hrtm7CA+A==#646465698#399900003000”
rlt2="[B@41547740"
哪一个是正确的?为什么?
这里应该用new String()的方法,因为Base64加解密是一种转换编码格式的原理

toString()与new String ()用法区别

str.toString是调用了b这个object对象的类的toString方法。一般是返回这么一个String:[class name]@[hashCode]。
new String(str)是根据parameter是一个字节数组,使用java虚拟机默认的编码格式,将这个字节数组decode为对应的字符。若虚拟机默认的编码格式是ISO-8859-1,按照ascii编码表即可得到字节对应的字符。
什么时候用什么方法呢?

new String()一般使用字符转码的时候,byte[]数组的时候
toString()将对象打印的时候使用

Stream流集合

情况:只取数据里面的特定key组成数组
代码

//节点名称list
        String[] op = avail.stream().filter(
                x -> x.getInteger("num") > 0
        ).map(jsonObject -> jsonObject.getString("name")).toArray(String[]::new);

        //增加显卡版本筛选
        YunNode yunNode = yunNodeService.findByNodes(op, yun.getId(),containerVo.getVersionType());
        if (yunNode==null){
            lock.unlock(yun.getId());
            return new GlobalResponse(false, "找不到节点信息");
        }
        YunImgConfig yunImgConfig = yunImgConfigService.findYunImgConfigById(containerVo.getImgConfigId());
        
map排序
List<IvmFace> resJson = ivmFaceList.stream().map(face -> {
            String score = res.stream().filter(obj -> obj.getString("faceId").equals(face.getIvuFaceId())).findFirst().get().getString("score");
            IvmFace indexJson = new IvmFace();
            BigDecimal b = new BigDecimal(Float.parseFloat(score));
            float m_score =  b.setScale(2,  BigDecimal.ROUND_HALF_UP).floatValue();
            indexJson.setScore(m_score);
            indexJson.setOtherPara(face.getOtherPara());
            indexJson.setCreateTime(face.getCreateTime());
            indexJson.setFaceImageId(face.getId());
            indexJson.setName(face.getName());
            indexJson.setRepositoryId(face.getRepoId());
            indexJson.setPersonId(face.getCredentialNumber());
            indexJson.setFaceImageUrl(Common.IMG_PATH + face.getId() + ".jpg");
            return indexJson;
        }).sorted(Comparator.comparing(IvmFace::getScore).reversed()).collect(Collectors.toList());

MVC框架:

M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。
框架(framework):是一个框子——指其约束性,也是一个架子——指其支撑性。
在这里插入图片描述

JAVA常见设计模式

⚠️ 代码设计
⚠️常用设计模式

Spring框架

在这里插入图片描述

Springboot

初闻SpringBoot的开发者,必然会想到Spring这一时下最流行的开发框架,SpringBoot确实和Spring有着千丝万缕的关系。要想将SpringBoot学习透彻,对于Spring的学习也是必不可少的(不对Spring作过多介绍)。随着动态语言的流行(Ruby、Groovy、Scala、Node.js),Java的开发显得也就显得格外的笨重,即使是使用各种流行框架(Spring等),依然会有各种繁重的配置,导致了低效率的开发、复杂的部署流程以及第三方技术集成难度大。为了提升开发效率,节约开发成本,SpringBoot也就应用而生。它使用习惯优于配置的理念,让开发者无需繁重、复杂的文件配置就可以快速地将项目运行起来。
使用SpringBoot很容易创建一个独立运行(运行jar,内嵌Servlet)、准生产级别的基于Spring框架的项目,它可以不用或者说只需要使用很少的Spring配置。使用SpringBoot能为我们带来什么简单的概括起来就是简单、快速、配置少比起传统的Spring Web项目,
它不需要下列如此多的步骤:1. 配置web.xml,springmvc.xml和spring.xml 2. 配置数据库连接池,配置数据库事务等 3. 配置记录系统工作的日志 4. 配置加载系统运行时系统配置文件的读取… 5. 代码编写完成后,需要部署到tomcat等运行环境上调试 6. 不支持持续集成、持续部署等

SSH与Spring

⚠️⚠️概念区分

SSH框架一般指的是Struts、Spring、Hibernate,后来Struts2代替了Struts。最近5年,Struts2已经被Spring MVC代替,而Hibernate基本也被iBatis/MyBatis代替。所以你真正需要了解的是Spring,Spring你需要了解两个概念AOP和IOC,更进一步就是Spring的核心技术“动态代理”。持久层框架看看Hibernate/iBatis/MyBatis,研究一下Spring的数据库事务管理,各个持久层框架式如何实现ORM的,了解至少一种缓存框架,知道什么是数据库连接池。和数据库的交互最核心的不是ORM,而是掌握和数据库相关的能力,比如数据库编程、SQL优化、对范式的理解。MVC框架Struts2和Spring MVC,你需要知道他们在web.xml文件里配置了一些什么,Struts2/Spring MVC接到前台请求之后经过哪些步骤之后转到Action/Controller,return之后Struts2/Spring MVC又作了些什么。还有就是Filter、Listener和Struts2/Spring MVC的拦截器各有什么特点,适合处理什么样的问题。(转载自知乎)
原答案来源

mybatis

其中userids是String[] 型:

<if test="userIds!=null">
			and dev.user_id in
			<foreach collection="userIds" item="id" index="index" open="(" close=")" separator=",">
			#{id}
			</foreach>
</if>

另一种写法:

<foreach collection="users.split(',')" item="item" index="index" open="(" close=")" separator=",">
				'${item}'	        
</foreach>

大于小于写法:

<![CDATA[ <= ]]>
<![CDATA[ >= ]]>

相似:

LIKE CONCAT('%',#{username},'%')

分组搭配:

select GROUP_CONCAT(a.user_id) as users
group by ...

⚠️ mybatis trim 用法
⚠️ mybatis when then 用法
⚠️⚠️ mybatis批量操作
⚠️ ⚠️⚠️mybatis各种标签用法

创建临时表:
Long createTemp(@Param(“tableName”) String tableName);

<update id="createTemp">
        CREATE  TABLE  iva_feature.${tableName}
        (group_id varchar(100) PRIMARY key,
         tag varchar(100),
         engine_version varchar(45),
         is_repo tinyint(2),
         url varchar(200)
        )
</update>

插入:

<insert id="insertTemp">
        insert INTO iva_feature.${tableName}(group_id, tag, engine_version, is_repo,url)
        select id as group_id,name as tag, #{version}, 1, #{url} from iva_alg.alg_ivm_repository where
        engine_id= #{engineId}
    </insert>

微服务类

Consul

对Feign的请求url 重写

Kafka

简单的生产者和消费者代码

数据库类

mysql

⚠️mysql语句大全1
⚠️mysql语句大全2
⚠️mysql执行顺序
⚠️mysql JOIN图
在这里插入图片描述

服务器类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值