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

谷粒商城第八天-商品服务之品牌管理的整体实现(直接使用逆向生成的代码;含oss文件上传)

目录

一、总述

二、前端部分

2.1 创建好品牌管理菜单

2.2 复制组件 

​编辑2.3 复制api ​​​编辑 

2.4 查看效果

​编辑2.5 需要优化的地方 

2.6 具体优化实现

2.6.1 优化一:将表格的状态列(这里是是否显示列)修改为开关,同时在修改页新增可显示修改开关

2.6.2 优化二:在修改页将logo地址文本框改为文件上传按钮

2.6.3 优化三:将表格列表的logo地址列改为显示图片

三、后端部分

四、总结


一、总述

之前的分类管理的前端部分基本上是手写的增删改查,虽然部分是直接使用的elementUI提供的组件,只是稍作修改,但是还是需要自己去找对应的组件,组件写数据域,自己写方法,自己绑定等,其实要写的还是比较多的。但其实仔细一想的话,其实这些组件都差不多,都是一些列表,提供一些按钮,一些文本框,然后进行增删改查,代码都差不多。既然差不多,没什么技术含量的东西,只是比较繁琐。那么应该就能自动生成的能给我们直接使用,是的若依也提供了前端部分的逆向代码。(ps:兄弟们,真的要努力的学了,这些基本的增删改查代码都不需要我们写了,如果你还只会这些简单的,会被淘汰的

现在要干的就是直接使用,然后根据自己的需求,修改部分即可。

二、前端部分

实现找到前端逆向生成的代码部分,其实就是和main同级的目录,一个vue目录,里面放着在网页所选择的很多张表所对应的前端代码:

2.1 创建好品牌管理菜单

这个没什么好说的,在之前的创建分类管理的时候已经操作过一遍了,只是部分属性修改一下就行了:

其实还可以选择在数据库中创建,之后可以使用数据库进行批量创建,其实都差不多

2.2 复制组件 

2.3 复制api ​​ 

2.4 查看效果

 效果就是下图这样子:

我们发现其实这种逆向生成的前端样子,大致是以下的这三部分:

2.5 需要优化的地方 

看着好像挺好的,基本上我们自己去写也就是写这些东西,现在都帮我们已经写好了,极大的提升了开发效率,但是这一般来说,不能这样就OK了,还需要优化,或者是需要根据一定的需求做调整。

那哪些部分需要我们去调整优化的呢?

1. 修改状态列为开关,修改页同理

像这种是否显示的这种或是其他字段使用01来表示状态的,一般来说我们不希望直接这么突兀的直接显示,主要是看着不美观,最重要的是不好直接修改,还需要到修改弹窗那里,手动的输入0或者1进行修改,这样不方便,如果在这个列表中这一个属性使用开关进行替换的话,就可以不打开修改弹窗,也不需要手动的去输入状态值了,而是直接点击一下,就能直接的修改了,很方面。

2. 修改图片地址列为真实图片

这个直接放置图片地址的方式肯定不可取,根本就不知道图片长什么样子,我们只需要使用elementUI为我们提供的图片组件将其进行替换即可。

3. 修改页面的品牌logo地址肯定要换成文件上传按钮

主要也就是这三部分,在其他组件页面其实大致都是这些地方需要进行修改。

2.6 具体优化实现

2.6.1 优化一:将表格的状态列(这里是是否显示列)修改为开关,同时在修改页新增可显示修改开关

现在表格的这一列已经是文本呢?如何替换呢?

其实很简单,既然这里是要替换表格中的一列,那么势必就得参考elementUI中的表格组件,如何进行替换?要有这种意识:哪个组件上面进行修改就查看哪个组件的文档(ps:像是废话,但很重要,思路就是这样产生的)。

好,现在就到官网中查看表格组件的文档,看到底如何替换列值:

 找到这个自定义模板。我们照葫芦画瓢直接复制这个template到我们自己的组件中去:

在表格列处:

这只是一个模板,就和组件文件中三大件中的模板一样,其实就是规定了组件写的位置,具体还是要在里面写好组件,例如现在需要放开关组件,而之后的表格的logo地址的那一列则需要放图片组件。现在的任务就是继续到官网里面去找修改状态开关组件:

放到那个模板中就可以在网页中 是否显示的那一列就能够显示 一个开关了。

最重要的就是将决定开关是否开还是闭与数据域中的数据进行关联,使用v-model指令进行动态的绑定:

这里关键要懂得这一列在数据域中如何表示!!!其实很简单 

但是这里会发现一个问题,就是无论我的数据库中,值无论是0还是1也就是无论是 显示还是不显示开关都是闭合的状态,那这是怎么回事呢?其实要有这么一种意识,那就是这个开关开与闭肯定是受到一个值,也就是我这里绑定的form.showStatus,对应数据库中对象的这一列值。

我们知道数据库中这一列值只会是0或者是1,其实啊这个开关组件,并不知道0代表关,1代表开,它默认自己是根据布尔值决定开还是关的,false代表关,true代表开,默认是这样。那肯定我们的数据库中一般不存布尔值是吧,所以肯定也得换,elementUI也知道肯定也会有这样的需求,所以也就提供了相应的参数,去自己指定,开是什么值,关又是什么值。elememtUI官网已经说的很明白了:

这里因为是需要动态和数据域中的属性进行绑定,因此需要使用在参数前加上 :冒号,进行指定

最终的样子长这样(ps:这里已经是将每一步都讲得很细节了,如果还不明白的话,请私信我):

 不要忘记修改页面同样得记得加上。都一样的东西只是绑定的值不一样:

下面我直接给出这两处地方的代码:

<el-table-column label="显示状态" align="center" prop="showStatus"><template slot-scope="scope"><el-switch@change="changeStatus(scope.row)"v-model="scope.row.showStatus"active-color="#13ce66"inactive-color="#ff4949":active-value="1":inactive-value="0"></el-switch></template></el-table-column>
<el-form-item label="是否显示" prop="showStatus"><el-switchv-model="form.showStatus"active-color="#13ce66"inactive-color="#ff4949":active-value="1":inactive-value="0"></el-switch></el-form-item>

到这里,这项优化工作就已经完成了;其实很简单,就是在你想要更换的那一列加个模板,然后放一个开关的组件,只是需要注意修改开关的开关规则。 

2.6.2 优化二:在修改页将logo地址文本框改为文件上传按钮

这里是我需要花大功夫讲的地方,主要就是使用oss进行文件上传,这里的前端部分的话,主要就是懂得加上一个文件上传按钮,然后这个按钮关联的许多参数,得注意一下就行了。

这里采用的oss上传方式为携带好凭证然后文件直传到阿里云服务器的方式。

这里的关键在于两点:

1. 上传文件组件从哪里来?

这个可以用谷粒商城中老师已经写好了的文件上传组件,直接用就行了,单文件的多文件的都有

这里我先贴上老师的代码,等下需要注意的地方再说一下:

单文件上传组件:

<template> <div><el-uploadaction="http://sq-bucket-02.oss-cn-hangzhou.aliyuncs.com":data="dataObj"list-type="picture":multiple="false" :show-file-list="showFileList":file-list="fileList":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleUploadSuccess":on-preview="handlePreview"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="fileList[0].url" alt=""></el-dialog></div>
</template>
<script>import {policy} from './policy'import { getUUID } from '@/utils/getUUID'export default {name: 'singleUpload',props: {value: String},computed: {imageUrl() {return this.value;},imageName() {if (this.value != null && this.value !== '') {return this.value.substr(this.value.lastIndexOf("/") + 1);} else {return null;}},fileList() {return [{name: this.imageName,url: this.imageUrl}]},showFileList: {get: function () {return this.value !== null && this.value !== ''&& this.value!==undefined;},set: function (newValue) {}}},data() {return {dataObj: {policy: '',signature: '',key: '',ossaccessKeyId: '',dir: '',host: ''},dialogVisible: false};},methods: {emitInput(val) {this.$emit('input', val)},handleRemove(file, fileList) {this.emitInput('');},handlePreview(file) {this.dialogVisible = true;},beforeUpload(file) {const crypto = require('crypto');let _self = this;return new Promise((resolve, reject) => {policy().then(response => {_self.dataObj.policy = response.data.policy;_self.dataObj.signature = response.data.signature;_self.dataObj.ossaccessKeyId = response.data.accessid;_self.dataObj.key = response.data.dir + "/"+getUUID()+"_${filename}";_self.dataObj.dir = response.data.dir;_self.dataObj.host = response.data.host;console.log("_self.dataObj",_self.dataObj);resolve(true)}).catch(err => {reject(false)})})},handleUploadSuccess(res, file) {console.log("上传成功...")this.showFileList = true;this.fileList.pop();this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });this.emitInput(this.fileList[0].url);}}}
</script>
<style></style>

多文件上传组件:

<template><div><el-uploadaction="http://oss-cn-hangzhou.aliyuncs.com":data="dataObj"list-type="picture-card":file-list="fileList":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleUploadSuccess":on-preview="handlePreview":limit="maxCount":on-exceed="handleExceed"><i class="el-icon-plus"></i></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt /></el-dialog></div>
</template>
<script>
import { policy } from "./policy";
import { getUUID } from '@/utils'
export default {name: "multiUpload",props: {//图片属性数组value: Array,//最大上传图片数量maxCount: {type: Number,default: 30}},data() {return {dataObj: {policy: "",signature: "",key: "",ossaccessKeyId: "",dir: "",host: "",uuid: ""},dialogVisible: false,dialogImageUrl: null};},computed: {fileList() {let fileList = [];for (let i = 0; i < this.value.length; i++) {fileList.push({ url: this.value[i] });}return fileList;}},mounted() {},methods: {emitInput(fileList) {let value = [];for (let i = 0; i < fileList.length; i++) {value.push(fileList[i].url);}this.$emit("input", value);},handleRemove(file, fileList) {this.emitInput(fileList);},handlePreview(file) {this.dialogVisible = true;this.dialogImageUrl = file.url;},beforeUpload(file) {let _self = this;return new Promise((resolve, reject) => {policy().then(response => {console.log("这是什么${filename}");_self.dataObj.policy = response.data.policy;_self.dataObj.signature = response.data.signature;_self.dataObj.ossaccessKeyId = response.data.accessid;_self.dataObj.key = response.data.dir + "/"+getUUID()+"_${filename}";_self.dataObj.dir = response.data.dir;_self.dataObj.host = response.data.host;resolve(true);}).catch(err => {console.log("出错了...",err)reject(false);});});},handleUploadSuccess(res, file) {this.fileList.push({name: file.name,// url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名url: this.dataObj.host + "/" + this.dataObj.key.replace("${filename}",file.name)});this.emitInput(this.fileList);},handleExceed(files, fileList) {this.$message({message: "最多只能上传" + this.maxCount + "张图片",type: "warning",duration: 1000});}}
};
</script>
<style>
</style>

 请求后端获取凭证的api js文件:

import request from '@/utils/request'
export function policy() {return request({url: "/thirdparty/oss/policy",method: "get"});
}

还有最终服务器中文件存储时的文件名所包含的uuid的工具类来生成UUID的:

export function getUUID() {return "xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {const r = (Math.random() * 32) | 0;const v = c === "x" ? r : (r & 0x3) | 0x8;return v.toString(32).replace("-","");});
}

下面我简单的介绍一下这个文件上传组件文件:

其实简单来说就是:在真正的文件上传之前有一个前序方法,这个方法的目的就是向后端发送请求获得直传的凭证,只有获得了这个凭证,才可以进行直传,至于到底如何获取的,那是后端的事情了。然后获取到这个凭证之后,就会携带这个凭证,并带上文件直接向阿里云服务器发请求,直接保存到了阿里云服务器。 

2. 在我们的项目中具体如何使用这个文件上传?

这里才是真正需要注意的地方,其他其实都不重要

1. 修改单文件上传组件中的阿里云的桶地址(文件夹地址)

改成自己的地址就行了,地址可以在阿里云官网进行查看,在这个位置:

上面其实还是修改组件,下面是真正的将组件用到我们的项目中去:还是那几步:

1. 引组件

2. 在vue实例中声明好组件

3. 在模板的所需位置使用组件

完成了这些步骤,文件上传的组件也就在修改页展现出来了:

 展示出来了,也就代表这项工作成功的完成了。其实也很简单,就是在我们的前端项目中直接引入好老师直接提供好的前端文件上传所需的一些文件,然后改一下桶路径,然后在项目中引入直接使用即可。

2.6.3 优化三:将表格列表的logo地址列改为显示图片

这里有着之前改成开关的例子之后就变得很简单了,也是一样的既然是在表格中,要修改表格列,就只需要在那一列,使用template,然后在里面放上图片组件即可。

<el-table-column label="品牌logo" align="center" prop="logo"><template slot-scope="scope"><el-imagestyle="width: 50px; height: 50px":src="scope.row.logo"fit="contain"></el-image></template></el-table-column>

三、后端部分

总的来说后端这里很单纯,总是,哈哈哈,当然只是需要业务简单,反正写到目前为止,前端都相较于后端反而要繁琐一点。

在这里后端的话其实就一个接口:获取文件上传凭证接口。

在说这个接口之前,我先说一下,这里文件上传的解决方案;

文件上传我们其实比较熟悉了,就是上传到服务器嘛,这里使用的是oss文件上传技术,oss文件上传常用的有两种上传方式:

第一种:很简洁明了的方式,直接将文件发送到我们项目的后端服务器上面,然后后后端服务器再调用oss的api实现文件的上传,也就是说这里其实文件是直接到了我们的后端服务器上面去的,给我们的后端服务器一定的压力。

第二种:携带凭证的方式直接将文件上传到阿里云服务器,这种方式就是先携带文件的一些信息,比如说文件名,bucket名,bucket域名等信息,发送到我们的后端服务器,然后后端服务器调用oss的api获得凭证,然后发给前端,然后前端再携带上这个凭证以及文件,然后直接发到oss服务器。也就是说这种方式其实是并没有将文件直接上传到我们自己的服务器上面去的,减轻了我们自己的服务器的压力。

好,现在oss的上传方式大致理解了,我们现在采用第二种方式进行上传。

既然知道了方案,实施起来难不难呢?其实不难,其实这里后端的工作就是获取凭证,这里的凭证获取归根结底其实并不是我们直接获取的,还是调用oss的api进行获取的,那这个api到底是什么呢?这里就需要访问阿里云的官网,到官网中oss对象存储的文档那里去查看了,这里我就不查看了,其实不重要,我这里直接贴代码,能用就行了。

对了,这里的话,因为是oss文件上传,其实不是业务模块了,这里是第三方服务了,因此我新建一个第三方服务,以后的所有的第三方服务全放到这里,比如说还有短信服务,金融服务,物流服务等。

这个服务的创建简单说一下:

这并非业务服务,因此并不需要像业务服务那样,需要依赖那么多的依赖,只需要简单的几个依赖就行了,像这也是一个服务,以后使用网关路由到这里,因此得注册到nacos注册中心去,因此那cos注册中心的依赖少不了,还有现在是需要oss服务,因此oss服务依赖少不了(这里我并不是直接导入原生的oss依赖了,而是导入对应的starter,这样就是将方法更加封装起来了,可以拿来直接使用,一些参数只需要到配置文件中配好就行了)

1. pom文件的创建

这里这个第三方服务的pom服务我直接给出,这里我也还是直接引入的comment模块,其实也可以直接引入的,但是我这种方式还得注意排除掉一些依赖,比如说MP和security的依赖这是不需要的:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.sq</groupId><artifactId>gulimall</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>thirdparty</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>com.sq</groupId><artifactId>gulimall-common</artifactId><version>1.0-SNAPSHOT</version><exclusions><exclusion><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></exclusion><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alicloud-oss</artifactId><version>0.9.0.RELEASE</version></dependency></dependencies></project>

2. 配置文件

application.yml:

server:port: 8081
spring:cloud:util:enabled: falsenacos:discovery:server-addr: localhost:8848
#    alicloud:
#      access-key:
#      secret-key:
#      oss:
#        endpoint:application:name: thirdpartyautoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

这里由于使用了nacos配置中心,bootstrap.properties引导文件也是少不了的,里面主要写好文件的位置,文件的namespece命名空间,分组等信息,这里的话使用的是项目中的常用用法:就是配置中心中配的方式是采用配置分离的方式,也就是将原本在Java程序配置文件中的application.yml文件进行拆解,拆解成多个文件,比如说数据源可以拆开一个文件,注册中心又是一个文件,其他配置又是一个文件等等拆解成若干个文件,这样更加方便管理。

话不多说,这里直接给上bootstrap.properties里面的内容,其实就只需要注意一下,这种多文件怎么配置就行了:

spring.cloud.nacos.config.server-addr=localhost:8848
spring.application.name=thirdpartyspring.cloud.nacos.config.namespace=30366fc8-9ac7-44ef-846d-3ec8009fce8b
spring.cloud.nacos.config.ext-config[0].data-id=oss.yaml
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true

配置中心的样子长这样:

 3. 接口

也就是直接复制阿里云oss官网中给的样例,改一下就行了:

核心文件(从阿里云官网oss文档荡下来的)

主要在这里bucke和dir需要自己配一下,其他AK和endpoint从nacos配置中心中读取

public AjaxResult policy(){String bucket = "sq-bucket-02"; // 请填写您的 bucketname 。String host = "http://" + bucket + "." + endpoint; // host的格式为 bucketname.endpointString dir = new SimpleDateFormat("yyyy/MM/dd").format(new Date());// 用户上传文件时指定的前缀。Map<String, String> respMap = new HashMap<>();try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);respMap = new LinkedHashMap<String, String>();respMap.put("accessid", accessKey);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));} catch (Exception e) {System.out.println(e.getMessage());}return AjaxResult.success(respMap);}

接口完整代码:

@RestController
@RequestMapping("/thirdparty/oss")
public class OssController {@Autowiredprivate OSS ossClient;@Value(value = "${spring.cloud.alicloud.oss.endpoint}")private String endpoint;@Value(value = "${spring.cloud.alicloud.access-key}")private String accessKey;@RequestMapping("/policy")public AjaxResult policy(){String bucket = "sq-bucket-02"; // 请填写您的 bucketname 。String host = "http://" + bucket + "." + endpoint; // host的格式为 bucketname.endpointString dir = new SimpleDateFormat("yyyy/MM/dd").format(new Date());// 用户上传文件时指定的前缀。Map<String, String> respMap = new HashMap<>();try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);respMap = new LinkedHashMap<String, String>();respMap.put("accessid", accessKey);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));} catch (Exception e) {System.out.println(e.getMessage());}return AjaxResult.success(respMap);}}

4. 在网关中进行注册配置

最后一步很重要,这里又新增了一个服务,在前端都只会像网关发请求,至于需要网关发到我们的服务中去,就需要到网关中配置好,这个第三方服务的“关键信息”是thirdparty,因此在网关中配置上即可。

 

        - id: thirdparty_path_routeuri: lb://thirdpartypredicates:- Path=/thirdparty/**

注意:这里之前前端那里需要请求这个接口,在那个前端api文件中,的请求路径得与后端路径保持一致

四、总结

这次其实任务量还挺大的,但是仔细一想其实还是简单的,使用逆向生成的前端代码,已经帮我们省去了百分之80的内容。

这里前端就干了三件事:

1. 将状态列改成开关

2. 在修改页将logo地址改成文件上传按钮

3. 在表格列表中logo列改成图片

后端就干了一件事:获取凭证。

相关文章:

谷粒商城第八天-商品服务之品牌管理的整体实现(直接使用逆向生成的代码;含oss文件上传)

目录 一、总述 二、前端部分 2.1 创建好品牌管理菜单 2.2 复制组件 ​编辑2.3 复制api ​​​编辑 2.4 查看效果 ​编辑2.5 需要优化的地方 2.6 具体优化实现 2.6.1 优化一&#xff1a;将表格的状态列&#xff08;这里是是否显示列&#xff09;修改为开关&#xff…...

阿里云率先荣获容器集群稳定性先进级认证

7 月 25 日&#xff0c;由中国信通院发起的“2023 稳保体系”评估结果在可信云大会现场公布&#xff0c;阿里云容器服务 ACK 成为首批通过“云服务稳定运行能力-容器集群稳定性”评估的产品&#xff0c;并荣获“先进级”认证。 云原生技术正在激活应用构建新范式&#xff0c;构…...

【SpringBoot笔记37】SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket

这篇文章,主要介绍SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket。 目录 一、基于注解集成WebSocket 1.1、WebSocket常见注解 1.2、创建WebSocket服务端 1.3、配置ServerEndpointExpor...

PyTorch(安装及卸载)

目录 1. 安装 2. 卸载 参考文献 为什么用PyTorch&#xff1a;简单来说&#xff0c;19年之前tensorflow是大哥&#xff0c;19年tensorflow和PyTorch双龙并行&#xff0c;20年之后PyTorch一往无前。宗旨&#xff0c;哪个用的人多用哪个。 1. 安装 1. 先打开Anaconda Prompt&…...

webScoket

webScoket是什么&#xff1f; 支持端对端通讯可以由客户端发起&#xff0c;也可以有服务端发起用于消息通知、直播间讨论区、聊天室、协同编辑等 做一个简单的webScoket 客户端配置&#xff1a; 1、新建一个页面叫web-scoket.html <!DOCTYPE html> <html lang"…...

【C语言初阶(20)】调试练习题

文章目录 前言实例1实例2 前言 在我们开始调试之前&#xff0c;应该有个明确的思路&#xff1b;程序是如何完成工作的、变量到达某个步骤时的值应该是什么、出现的问题大概会在什么位置。这些东西在调试之前都需要先确认下来&#xff0c;不然自己都不知道自己在调试个什么东西…...

MicroPython ESP32网页实时更新DHT11数据显示

MicroPython ESP32网页实时更新DHT11数据显示 &#x1f4cc;相关篇《MicroPython ESP32 读取DHT11温湿度传感器数据》&#x1f4cd;《【Micropython esp32/8266】网页点灯控制示例》 ✨本例综合以上两篇文章内容实现&#xff1a;在本地网页中显示DHT11温度传感器数据。可以做到…...

JavaWeb之HTML基础篇(一)

系列文章目录 HTML基础篇&#xff08;一&#xff09; 文章目录 系列文章目录HTML基础篇&#xff08;一&#xff09;[TOC](文章目录) 前言一、HTML简介1.1介绍1.2HTML文件的书写规范1.3 HTML标签介绍1.4 HTML常见的标签 二、CSS的简介2.1css技术介绍2.2 CSS与HTML结合的三种方式…...

TVM_深度学习编译器

TVM_深度学习编译器 TVM所做的是要比传统compiler更偏上层的,你可以把它理解成source-to-source compiler,需要其他的后端(backend)来生成最后的指令。比如当编译的Target是Intel CPU时,翻译的顺序是Relay IR -> TVM IR/ Halide IR -> LLVM IR,之后交给LLVM生成最后…...

Flutter InheritedWidget 共享状态管理

InheritedWidget和React中的context功能类似&#xff0c;可以实现跨组件数据的传递。 定义一个共享数据的InheritedWidget&#xff0c;需要继承自InheritedWidget 这里定义了一个of方法&#xff0c;该方法通过context开始去查找祖先的HYDataWidget&#xff08;可以查看源码查找…...

什么是反射?Java反射?反射的优缺点

目录 什么是反射&#xff08;Reflection &#xff09;&#xff1f;Java反射&#xff1f;反射的优缺点获取Class对象的三种方式&#xff1a;java反射技术的应用场景 什么是反射&#xff08;Reflection &#xff09;&#xff1f; 主要是指程序可以访问、检测和修改它本身状态或行…...

小红书2020校招测试开发后端笔试题卷三

//完全背包求组合数 #include <iostream> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; int value[300]; // vector<int>vis; // vector<int>vis1; map<vector<int>,int>m…...

python数据可视化Matplotlib

1.绘制简单的折线图 # -*- coding: utf-8 -*- import matplotlib.pyplot as pltinput_values [1, 2, 3, 4, 5] squares [1, 4, 9, 16, 25] plt.style.use(seaborn) fig, ax plt.subplots() ax.plot(input_values, squares, linewidth3) # 线条粗细# 设置图表标题并给坐标…...

firewalld防火墙

firewalld防火墙 它属于包过滤防火墙。工作在网络层&#xff0c;是centos7自带的默认防火墙。主要是取代iptables。 firewalld的两种配置模式&#xff1a; 分别是运行时配置和永久配置。 iptable是静态防火墙 firewalld是动态防火墙 它是按照区域来划分的&#xff0c;有9…...

iMacros WebBrowser Component for .NET

iMacros WebBrowser Component for .NET 在几分钟内实现应用程序自动化 快速轻松地将iMacro集成到您的应用程序中。不需要单独的安装程序。 无缝集成 iMacros与您的.NET应用程序无缝集成&#xff0c;作为Microsoft WebBrowser控件的替代品。它甚至可以用作每个.NET应用程序中的…...

3,堆,桶排序,排序总结【p4-p5】

桶排序&#xff0c;排序总结 3.1堆3.1.1堆结构3.1.1.1完全二叉树3.1.1.2堆分为大根堆和小根堆3.1.1.2.1案例1-去掉最大数字&#xff0c;使剩下的数字依然是大根堆3.1.1.2.2案例23.1.1.2.3案例33.1.1.2.4案例4-方便制造大根堆方法 3.1.2堆排序3.1.2.1案例-堆排序的扩展3.1.2.1.1…...

使用langchain与你自己的数据对话(四):问答(question answering)

之前我已经完成了使用langchain与你自己的数据对话的前三篇博客&#xff0c;还没有阅读这三篇博客的朋友可以先阅读一下&#xff1a; 使用langchain与你自己的数据对话(一)&#xff1a;文档加载与切割使用langchain与你自己的数据对话(二)&#xff1a;向量存储与嵌入使用langc…...

如何快速开拓海外华人市场?附解决方案!

开拓华人市场对于企业来说是非常必要的。华人市场庞大且潜力巨大&#xff0c;拥有巨额的消费能力。随着华人经济的不断增长&#xff0c;越来越多的企业开始意识到华人市场的重要性。 通过开拓华人市场&#xff0c;企业可以获得更多的销售机会&#xff0c;并且在竞争激烈的市场…...

【云原生-制品管理】制品管理的优势

制品介绍制品管理-DevOps制品管理优势总结 制品介绍 制品管理指的是存储、版本控制和跟踪在软件开发过程中产生的二进制文件或“制品”的过程。这些制品可以包括编译后的源代码、库和文档&#xff0c;包括操作包、NPM 和 Maven 包&#xff08;或像 Docker 这样的容器镜像&…...

Java爬虫----HttpClient方式(获取数据篇)

目录 一、爬虫的定义 二、获取数据 &#xff08;1&#xff09;基于Get方式的请求&#xff08;无参&#xff09; &#xff08;2&#xff09;基于Get方式请求&#xff08;有参&#xff09; &#xff08;3&#xff09;基于Post方式的请求&#xff08;无参&#xff09; &…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...