请求时注意添加responseType this.$axios.get(`/attachment/files/view/${id}`, { responseType: 'blob' }).then(res => { this.previewUrl = '' // img的src绑定的变量 // 处理方式1——使用FileReader处理 const reader = new FileReader() reader.onload = (e) => { this.previewUrl = e.target.result } reader.readAsDataURL(res.data) // 处理方式2——直接使用URL.createObjectURL // res.data必须是Blob类型数据 this.previewUrl = URL.createObjectURL(res.data) }).catch(() => { this.getImageFailedInfo = '获取预览文件失败' })
方法一:用户主动授权
1. 在公众号中添加网页授权的域名(在公众号设置中配置);
2. 引导用户点击相关链接或按钮;
3. 用户点击后,会跳转到你配置的网页;
4. 你可以通过微信网页授权接口获取到用户的openid。
方法二:通过中间转换
1. 用户在公众号中输入指令或点击相关按钮;
2. 公众号向用户发送自定义的链接,将用户重定向到中间页面;
3. 中间页面通过code鉴权,获取到用户的openid,并将openid传递给你的后台服务器。
方法三:使用小程序
1. 提供一款关联着你的公众号的小程序;
2. 用户使用小程序登录,小程序会返回用户的openid;
3. 你可以将openid传递给你的后台服务器。
方法一代码示例
<template> <div> <button @click="redirectToAuth">点击授权</button> </div> </template> <script> export default { methods: { redirectToAuth() { const appid = 'YOUR_APP_ID'; const redirectUri = encodeURIComponent('http://yourwebsite.com/callback.html'); const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`; window.location.href = authUrl; }, }, mounted() { const code = (new URLSearchParams(window.location.search)).get('code'); if (code) { const appid = 'YOUR_APP_ID'; const requestUrl = `https://api.
1.手机开启开发者模式 测试手机:华为mate40Pro (设置-关于手机-HarmobyOS版本,点击7下,弹出‘您正处于开发者模式!’) 2.假设需要安装的包是 a.apk 3.用USB线缆连接手机和电脑,手机弹出一个调试选项页面,选择。 如果未弹出该页面,可能会有以下几种原因: 3.1没有启用USB调试选项:在Settings(设置)> Developer options(开发者选项)中启用该选项。
3.2没有安装手机驱动程序:可能需要手动安装设备的驱动程序或在安装过程中需要额外的步骤。
3.3没有正确连接USB:1)尝试更换USB数据线;2)换到另一个USB端口;3)连接到另一台电脑上。
4.在a.apk的目录下cmd进入doc命令行 1.输入命令:adb devices(列出当前连接的 Android 设备列表)
2.输入命令:adb install a.apk(安装a.apk)
3.手机弹出安装页面,点击‘安装’
5.手机退出开发者模式 华为mate40Pro手机退出开发者模式:设置-系统和更新-开发人员选项-关闭开关 仅供自己学习记录
infinite-scroll通过滑动加载更多数据是另一种常见的分页方式,通过监测是否滑动到底部,改变页码+1,调用接口将返回的数据追加渲染到页面上。
Eg:展示公司列表 上滑加载更多
1、<template>
infinite-scroll-disabled:上滑是否禁用,loading和noMore控制加载提示
2、<script>
当下滑到底部触发下拉事件loadData,当前页current+1去请求接口 ,返回的数据concat到companyList集合。
第一次下拉后端成功返回的参数,每次增加20条,第一次下拉current = 2
3、关键点:<style>
.infinite-list-wrapper { height: calc(100vh - 200px); overflowauto; }
一个给定高度的盒子,给盒子绑定overFlow: auto,这样表示当数据超过盒子本身高度时 出现一个滚动轴。infinite-scroll组件就会判断这个滚滑轮,当它滑倒盒子的底部时触发load方法。
前言:
💞💞从前⾯的课程我们可以看出 Spring 是⽤来读取和存储 Bean,因此在 Spring 中 Bean 是最核⼼的操作资源,所以接下来我们深⼊学习⼀下 Bean 对象。
前路漫漫,希望大家坚持下去,不忘初心,成为一名优秀的程序员
个人主页⭐: 书生♡
gitee主页🙋♂:奋斗的小白
专栏主页💞:JavaEE进阶专栏
博客领域💥:java编程前端,算法,强训题目
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬
目录 1.常见的作用域问题1.1 问题所在1.2 代码示例 2. 作用域2.1 作用域定义2.2Bean 的 6 种作⽤域2.2.1 singleton 单例作⽤域2.2.2 prototype 原型作⽤域2.2.3request 请求作⽤域2.2.4 session 会话作⽤域2.2.5 application 全局作⽤域(了解)2.2.6 websocket :HTTP WebSocket 作⽤域 2.3 singleton 和 application 的区别2.4 设置作用域 3. Spring执行流程4.Bean ⽣命周期4.1Bean ⽣命周期4.2 实例化和初始化的区别4.3 Bean生命周期代码 1.常见的作用域问题 1.1 问题所在 有一个公共类,类对象被@Controller注解修饰,里面的方法被方法注解@Bean修饰。现在有两个用户都使用这个公共类,但是其中一个用户突然改变了里面的值,这个就导致了另一个用户使用的时候变量值已经发生了变化,因此第二个用户得到的应该是修改以后的。
1.2 代码示例 公共类
@Controller public class StudentBeans { @Bean public Student student1() { // 伪代码,构建对象 Student stu = new Student(); stu.
1.搭建python环境 1.1 安装python2.7版本以上(官方推荐),我这里安装3.11版本,记得勾上path选项(能省很多事)
1.2 安装web.py,libxml2,lxml
pip install web.py pip install libxml2-python3 pip install lxml 2.编辑代码 # -*- coding: utf-8 -*- # filename: main.py import web from handle import Handle urls = ( '/wx', 'Handle', ) if __name__ == '__main__': app = web.application(urls, globals()) app.run() """ handle.py """ import hashlib import web class Handle(object): def GET(self): try: data = web.input() if len(data) == 0: return "hello, this is handle view" signature = data.
MQTT(Message Queuing Telemetry Transport)中的 QoS(Quality of Service)级别是指消息传递的可靠性。MQTT 客户端和服务器可以使用以下三种不同的 QoS 级别来交换消息:
QoS 0:最多一次,即发布者发送一条消息后,不关心该消息是否已被接收方接收。这是最低的 QoS 级别,通常用于实时数据,例如传感器读数。
QoS 1:至少一次,即发布者要确保每条消息至少发送一次到接收方。如果某个消息在传输过程中出现了丢失或重复,MQTT 会自动重新传送该消息。这是一种中等的 QoS 级别,通常用于需要可靠性但允许轻微延迟的应用程序,例如智能家居控制系统。
QoS 2:恰好一次,即发布者确保每条消息只会发送一次到接收方。如果某条消息在传输过程中出现了丢失或重复,MQTT 会自动尝试再次发送该消息,直到接收方成功确认收到该消息。这是最高的 QoS 级别,通常用于需要高可靠性,并允许较大的延迟的应用程序,例如金融交易系统。
总之,QoS 级别越高,消息传递越可靠,但会导致更高的延迟和网络负载。在选择 QoS 级别时,需要根据具体应用场景的需求进行权衡和选择。
怎么修改照片尺寸?首先,修改照片尺寸可以减少存储空间的占用。现在的相机拍摄出来的照片一般都有很高的像素,而这种高像素的照片所占据的存储空间也很大。如果你想在电脑上保存很多照片,那么就需要压缩照片的尺寸以减少它们所占用的存储空间。同时,修改照片尺寸还能够减少存储设备的坏块率,使得存储设备更加稳定可靠。其次,修改照片尺寸也可以提高照片的加载速度。大尺寸的照片需要更长时间来加载,这会给用户带来不好的体验。通过修改照片尺寸,可以提高照片的加载速度,让用户更快地看到他们想要的内容,提高用户的满意度和使用体验。最后,修改照片尺寸还能够提高照片的美感和品质。当照片被压缩到一个合适的尺寸时,画面上的细节更加丰富,颜色更加鲜艳,画质更加清晰。这样可以使照片更具有吸引力和美感,同时也可以提高照片的品质。
通过减少存储空间的占用、提高照片的加载速度、适应不同的设备屏幕、提高照片的美感和品质以及保护隐私等方面,修改照片尺寸成为了当前处理和管理照片的必要手段之一,下面给大家分享几个方法。
方法一:使用“优速图片格式转换器”修改照片尺寸
步骤1、可以在我们的电脑上将“优速图片格式转换器”下载下来,在安装完成之后,打开直接使用,点击左边列表中的【更改尺寸】功能;
步骤2、这个时候,我们需要将待处理的照片上传到软件中,直接点击软件上方的【添加文件】按钮就可以了;这个软件支持文件批量操作,所以我们可以将多张照片直接上传;
步骤3、按照实际情况,对参数进行更改和设置,支持两种设置方法:按比例可以将所有图片尺寸等比例放大或者缩小;按尺寸则是将所有图片尺寸修改成设置的宽度和高度,锁定比例可以让图片不变形。大家根据自己的实际情况进行选择。
步骤4、完成上述操作之后,设置后,点击【开始转换】按钮,启动软件程序,修改完成后,软件会自动输出文件夹,可以看到修改尺寸后的图片全部保存在这里。
步骤5、查看输出文件夹内照片尺寸,我们看到都按我们设置的尺寸修改完毕了。说明小编推荐的工具能满足我们的要求。
方法二:使用PS软件修改照片尺寸
第一步,开安装在电脑上的PS(Photoshop)软件,将需要调整尺寸的照片导入到PS软件中。您可以直接将照片拖入软件工具栏中,或者通过“文件”菜单中的“打开”命令来导入照片。导入照片之后,在PS软件顶部的功能栏中单击“图像”菜单,然后选择“图像大小”命令即可。
第二步,在弹出的“图像大小”对话框中,我们可以看到当前图片的尺寸和分辨率信息,以及可以进行修改的参数。如果我们只考虑图片的尺寸,而不考虑分辨率,那么可以直接在“宽度”或“高度”的输入框中输入新的数值来进行调整。如果想按比例调整图片尺寸,那么需要先勾选“约束比例”选项。随后,在“宽度”或“高度”的输入框中输入我们需要的尺寸。这时,另一个数值将自动适应比例进行调整。
第三步,完成调整后,单击“确定”按钮即可。此时,图片就会按照我们所设置的尺寸进行缩放。最后我们将照片保存到电脑上就可以了。使用“图像大小”对话框来设置图片尺寸非常方便。通过简单的参数调整,我们就可以轻松地实现尺寸的修改和优化,满足不同需求和场景下的使用要求。
方法三:使用在线工具修改照片尺寸
如果不想下载和安装专业软件,也可以通过在线工具来实现照片尺寸的修改。下面,我们介绍一种常见的在线工具——“在线图片宝”,它可以帮助我们快速、方便地实现照片尺寸的调整。
第1步:首先,打开浏览器,搜索“在线修改照片尺寸工具”,在搜索结果中,选择“在线图片宝”并点击进入其首页。进入首页后,我们可以看到很多功能选项。
第2步:要进行照片尺寸的调整,我们先选择在“图片大小调整”功能,然后点击“选择图片”按钮,选择需要修改尺寸的图片。
第3步:在上传完照片后,我们可以看到一个简单的编辑页面。这个页面中,有许多参数可以供我们进行调整,包括图片尺寸、比例、格式等等。如果只需要修改尺寸,那么可以在“尺寸”栏中输入所需的数值,或者按比例进行调整。完成设置后,点击“开始处理”按钮,即可立即获取调整尺寸后的图片。
方法四:使用画图工具修改照片尺寸
第1步:首先,打开需要修改尺寸的照片,右键点击该照片并选择“打开方式”中的“画图”选项。这时,照片会在画图软件中打开。
第2步:接下来,单击顶部菜单栏中的“重新调整大小”选项卡,在弹出的下拉列表中选择调整依据。然后我们就可以根据个人的需求就行修改,修改完成点击“确认”。
第3步:完成调整后,可以将新的照片保存到本地电脑中,或者复制到其它操作中使用。
总之,使用画图工具进行照片尺寸的修改是一种直接实用的方式。它不需要下载和安装额外的软件,只需要一个自带的画图工具就可以轻松搞定,非常方便快捷。
怎么修改照片尺寸?照片尺寸的大小是指照片在屏幕上显示的像素数量。随着数码相机的普及和人们对于图片处理需求的增加,修改照片尺寸变得越来越必要。 综上,通过修改照片尺寸,可以减少存储空间的占用、提高照片的加载速度、适应不同的设备屏幕、提高照片的美感和品质以及保护隐私等方面,成为了现代人处理和管理照片的必要手段之一。同时,人们对于图片处理和分享的需求越来越高,而大尺寸的照片所占据的存储空间也越来越大,图片的加载速度也是影响用户体验的重要因素之一。通过修改照片尺寸,可以更加贴近用户需求,提高图片的质量和用户体验,并且减少存储空间的占用,合理地利用资源,从而推动数字化时代的信息技术创新和进步。我们可以利用优速图片格式转换器,将图片尺寸进行修改,从而保证图片的有效应用。
import axios from 'axios' import qs from 'qs' import { ElMessage } from 'element-plus' import store from '@/store' import cache from '@/utils/cache' // axios实例 const service = axios.create({ baseURL: import.meta.env.VITE_API_URL as any, timeout: 60000, headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) // 请求拦截器 service.interceptors.request.use( (config) => { const userStore = store.userStore if (userStore?.token) { config.headers.Authorization = 'Bearer ' + userStore.token } config.headers['Accept-Language'] = cache.getLanguage() // 追加时间戳,防止GET请求缓存 if (config.method?.toUpperCase() === 'GET') { config.
获取季度起始日期
要获取季度的起始日期,可以使用Day.js的startOf方法结合quarter单位来实现。 下面是一个示例代码,演示如何使用Day.js获取当前季度的起始日期:
const dayjs = require('dayjs'); require('dayjs/plugin/quarterOfYear'); dayjs.extend(require('dayjs/plugin/quarterOfYear')); // 获取当前季度的起始日期 const currentQuarterStart = dayjs().startOf('quarter'); console.log(currentQuarterStart.format('YYYY-MM-DD')); 在这个示例中,我们首先导入了Day.js库和quarterOfYear插件,该插件添加了用于季度操作的方法。然后,我们使用dayjs()创建了一个Day.js对象,表示当前日期和时间。接下来,我们使用startOf方法,传递quarter作为参数,以获取当前季度的起始日期。最后,我们使用format方法将结果格式化为’YYYY-MM-DD’形式,并进行输出。
获取月份起始日期
要获取月份的起始日期,可以使用Day.js的startOf方法结合month单位来实现。
以下是一个示例代码,演示如何使用Day.js获取当前月份的起始日期: const dayjs = require('dayjs'); // 获取当前月份的起始日期 const currentMonthStart = dayjs().startOf('month'); console.log(currentMonthStart.format('YYYY-MM-DD')); 在这个示例中,我们使用dayjs()创建了一个Day.js对象,表示当前日期和时间。然后,我们使用startOf方法,传递month作为参数,以获取当前月份的起始日期。最后,我们使用format方法将结果格式化为’YYYY-MM-DD’形式,并进行输出。
获取年度起始日期
要使用 Day.js 获取年度的起始日期,可以使用 startOf 方法结合 ‘year’ 单位来实现。
以下是一个示例代码,演示如何使用 Day.js 获取当前年度的起始日期: const dayjs = require('dayjs'); // 获取当前年度的起始日期 const currentYearStart = dayjs().startOf('year'); console.log(currentYearStart.format('YYYY-MM-DD'));
引言: 现在是北京时间的2023年6月15日早上的10点14分。时间过得飞快,现在已经大一的最后一个星期了。明天也是大一最后一次课,线下的实训课。线下实训内容为c语言二级的内容,对我来说跟学校的课效率太低下了,我还是比较喜欢按自己的节奏来,一般我是直接带笔记本过去按自己计划学习。可能大多数的同学还是意识不到在人生的无限博弈中,持续学习的重要性吧,兴许今天大家都是在同一个教室里,但是,三年后也许大家的人生就会步入不一样的道路。当然,也恳请看到本篇文章的你,不要放弃学习这则有较大概率改变人生的选项!
文章目录 引言:operator[]重载迭代器的介绍迭代器与范围for迭代器跟算法配合反向迭代器 容量相关的成员函数 operator[]重载 string因为支持了下标访问操作符重载,使得访问string实例化生成的对象可以像访问字符数组那样直接使用下标访问操作符进行指定编译量的访问以及修改。下面简单演示一下string的下标访问操作符的运算符重载。
#include<iostream> using namespace std; int main() { string s1("hello world"); char s2[] = "hello world"; cout << s2 << endl; for (size_t i = 0; i < s1.size(); i++) { s1[i]++;//通过下标进行修改 } s1[0]--; for (size_t i = 0; i < s1.size(); i++) { cout << s1[i];//进行打印 } cout << endl; s1[1]++;//(s1.operator[](1))++ s2[1]++;//->(*(s2+1))++ return 0; } 虽然两者在使用时是类似的,但这也并不意味着string类对象和char类型字符数组在底层实现上是一样的。string类对象使用下标访问操作符时,编译器会去调用它的运算符重载函数,而字符数组在使用下标访问操作符时,编译器根据数组首元素地址去进行解引用操作来访问。
迭代器的介绍 迭代器(iterator)是一种用于遍历数据集合的对象,可以按照一定顺序依次访问数据中的元素,而无需了解底层数据结构的实现方式。迭代器适用于各种不同类型的数据结构,包括数组、链表、树等等,并且支持可自定义的遍历顺序,例如前序、中序、后序等访问方式。迭代器的使用可以简化代码的编写,提高代码的可读性和可维护性。下面就简单介绍一下string类对象是如何用迭代器的。
在正式介绍迭代器之前,先介绍两个与迭代器相关的函数,begin()和end()。老规矩我们还是先查看文档,begin()函数返回的是指向string类对象第一个元素的迭代器。end()函数返回的是指向string类对象’\0’前元素的迭代器。
#include<iostream> using namespace std; int main() { string s1("
在当今互联网时代,网页数据的获取和分析对于很多行业都非常重要。而在这个过程中,使用C#编程语言来实现自动化网页抓取和数据分析已成为一种非常流行的方式。本文将从多个方面详细介绍如何使用C#来抓取网页内容并分析获取数据。
一、什么是网页抓取
网页抓取是指通过程序自动访问网站,获取其中的信息的过程。通常情况下,我们需要向目标网站发送HTTP请求,然后解析该请求返回的HTML文件,从而获得我们需要的信息。
二、使用C#实现网页抓取
在C#中,我们可以使用HttpClient类来实现对目标网站的HTTP请求。具体步骤如下:
1.创建HttpClient对象,并设置请求头信息
HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("User-Agent","Mozilla/5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"); 2.发送HTTP请求,并获取响应结果
HttpResponseMessage response = await httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); 3.解析HTML文件,并提取需要的信息
在这个过程中,我们可以使用HtmlAgilityPack类库来解析HTML文件,并提取其中需要的信息。例如,我们可以使用以下代码来获取HTML文件中所有的链接:
HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(responseBody); var linkNodes = doc.DocumentNode.Descendants("a").ToList(); foreach (var linkNode in linkNodes) { string href = linkNode.GetAttributeValue("href",""); Console.WriteLine(href); } 三、网页抓取的常见问题及解决方法
在实际应用中,我们可能会遇到一些网页抓取的问题。例如,有些网站可能会限制访问频率,或者需要登录才能访问。针对这些问题,我们可以采取以下措施:
1.通过设置请求头信息来模拟浏览器访问
在上面的代码中,我们通过设置User-Agent请求头信息来模拟浏览器访问。此外,还可以设置Referer、Cookie等请求头信息来进一步模拟浏览器行为。
2.通过代理服务器来隐藏真实IP地址
有些网站会根据IP地址来限制访问频率或者禁止某些IP地址的访问。在这种情况下,我们可以通过使用代理服务器来隐藏真实IP地址。
3.通过登录来获取更多信息
有些网站需要登录才能访问某些页面或者获取某些信息。在这种情况下,我们可以使用HttpClient类的PostAsync方法来发送登录请求,并保存Cookie信息。之后,我们可以使用这些Cookie信息来访问需要登录才能访问的页面。
四、使用C#实现网页数据分析
除了网页抓取外,C#还可以用来对网页数据进行分析。例如,我们可以使用以下代码来统计HTML文件中某个标签出现的次数:
HtmlDocument doc = new HtmlDocument(); doc.
前言 之前用模板写了订单页面,由于需求改了导致这个页面做更新麻烦,弄了一下午,索性全部删除了自己写了,上面的tabs用的是b-ui框架写的,其他的都是原生写法。
🙏如果这篇文章对你有帮助还请收藏点赞+关注🙏
推荐Mqtt相关文章(也许能帮到你)
《解决微信小程序MQTT真机连接问题与合法域名配置SSL问题》
《解决微信小程序MQTT通讯真机调试失败的问题附加可用代码》
《Esp8266-01s、51单片机实现连接MQTT踩坑:附加烧录安信可固件+宝塔搭建MQTT服务器 全套攻略》
推荐专栏
⭐⭐欢迎订阅⭐⭐
⭐⭐这是我的付费专栏,希望你可以订阅支持我🙏~⭐⭐
🚀Python爬虫项目实战系列文章!!
⭐⭐欢迎订阅⭐⭐
⭐⭐欢迎订阅⭐⭐
该专栏下的往期文章:
【Python爬虫项目实战一】获取Chatgpt3.5免费接口文末付代码(过Authorization认证)
【Python爬虫项目实战二】Chatgpt还原验证算法-解密某宝伪知网数据接口
订单页面的UI可以根据具体需求进行设计,以下是一些常见的UI设计元素:
订单信息:包括订单号、下单时间、订单状态等。商品列表:展示用户购买的商品信息,包括商品名称、价格、数量等。订单金额:展示订单的总金额、优惠金额、实际支付金额等。操作按钮:包括取消订单、支付订单、确认收货等操作按钮。 分析 根据我的需求,通过订单号查一个群组的商品数据,然后将订单状态以及点击事件、创建时间,商品数量总计 显示出来,在开发时,需要先了解uniapp小程序的开发流程和基本UI组件,以及订单页面的设计原则和需求分析。
布局 首先确定订单页面的整体布局,包括订单信息、商品列表、价格总计等内容。 通过颜色将大致的轮廓勾勒出来,可以使用不同的颜色来区分不同的内容区域,比如订单信息区域使用灰色背景,商品列表区域使用白色背景等。调整好每一本书的距离,可以使用margin和padding属性来控制每个商品之间的距离,保证页面整体美观。 对于商品列表中的每个商品,可以使用flex布局来实现自适应排列,同时使用图片和文字来展示商品信息。最后,根据实际需求添加一些交互效果,比如点击商品可以跳转到商品详情页面等。
代码:
由于我习惯先写在调整样式,所以现在看上去乱糟糟的,但这不是最终版
<template> <view> <view class="b-bg-white b-text-black-d"> <!-- tabs --> <view class="b-tabs"> <scroll-view scroll-x> <view class="b-tabs-container"> <view class="b-tabs-item" v-for="(item,index) in tabs1" :key="index" :class="{'b-tabs-active':tabs1Current == index}" @click="tabs1Current = index" > {{item}} </view> </view> </scroll-view> </view> <!-- tabs --> <view style="width: 735rpx;height: 350rpx;background-color: yellowgreen;margin-top: 10rpx;margin-left: 10rpx;border-radius: 10rpx;display: flex;flex-direction: column;"
前言:
💞💞今天我们依然是学习Spring,这里我们会更加了解Spring的知识,知道Spring是怎么更加简单的读取和存储Bean对象的。也会让大家对Spring更加了解。
💟💟前路漫漫,希望大家坚持下去,不忘初心,成为一名优秀的程序员
个人主页⭐: 书生♡
gitee主页🙋♂:奋斗的小白
博客领域💥:java编程 ,前端,算法,强训题目
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬
我们之前的博客讲述了如何通过注解(类注解和方法注解)简单的读取和存储Bean对象
类注解和方法注解的博客地址 :博客链接
目录 1.获取 Bean 对象1.1 属性注入1.2 set注入1.3 构造方法注入 2.@Resource:另⼀种注⼊关键字3. @Autowired 和 @Resource 的区别4.同⼀类型多个 @Bean 报错5. 总结 1.获取 Bean 对象 获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊
现实工作中一般是将,将 Service 类注⼊到 Controller 类中。
我们获取Bean有三种方法,分别是属性注入,set注入,构造方法注入,下面为大家挨个分享一下。
1.1 属性注入 属性注入我们也是通过注解实现的,通过@Autowired来实现的
通过这个@Autowired注解,我们就可以将Service类注入到Controller类中。
@Service public class StudentService { public void hello() { System.out.println("Hi,Service。"); } } @Controller public class StudentController { //获取 Bean 对象=>属性注入 @Autowired private StudentService studentService; public void hello() { studentService.
在工程化过程中遇到一个需求,需要在ubuntu环境下开启一个定时任务,定时执行sh脚本,下面参考网上的解决方案记录如下。
1、crontab linux中crontab命令用于设置周期性被执行的指令,该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。
可以使用 crontab 在每天的任何时间段自动运行任务,或在一周或一月中的不同时段运行。
crontab命令允许用户提交、编辑或删除相应的作业。每一个用户都可以有一个crontab文件来保存调度信息。
crontab [-u username] [-l|-e|-r]
-u: 只有root才能进行这个任务,也即帮其他用户新建/删除crontab工作调度;-e: 编辑crontab 的工作内容;-l: 查阅crontab的工作内容;-r: 删除所有的crontab的工作内容,若仅要删除一项,请用-e去编辑。 直接输入命令crontab -e 或者编辑文件/etc/crontab 就可以直接设置定时任务,如
# 每分钟把hello world字符串写入/home/string.txt文件中 * * * * * echo "hello world" >> /home/string.txt 2、crontab相关命令 安装:apt-get install cron或yum install crontabs 启动:service cron start 重启:service cron restart 停止:service cron stop 检查状态:service cron status 查询cron可用的命令:service cron 设置开机自启动:chkconfig --level 345 crond on 3、crontab例子 每天夜里0点执行 0 0 * * * sh /root/test.sh 每晚的21:30重启apache 30 21 * * * service httpd restart 每月1、11、21日的2:30重启apache 30 2 1,11,21 * * service httpd restart 每月的1-10日的2:45重启apache 45 2 1-10 * * service httpd restart 每隔2分钟重启apache */2 * * * * service httpd restart 晚上11点到早上7点之间,每隔一小时重启apache 0 23-7 * * * service httpd restart 每天18点至23:00点之间,每隔30分钟重启apache 0,30 18-23 * * * service httpd restart 两个小时运行一次 0 */2 * * * /root/test.
有 N 堆石子,每堆的石子数量分别为 a1,a2,…,aN。
你可以对石子堆进行合并操作,将两个相邻的石子堆合并为一个石子堆,例如,如果 a=[1,2,3,4,5],合并第 2,3 堆石子,则石子堆集合变为 a=[1,5,4,5]。
我们希望通过尽可能少的操作,使得石子堆集合中的每堆石子的数量都相同。
请你输出所需的最少操作次数。
本题一定有解,因为可以将所有石子堆合并为一堆。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 N。
第二行包含 N 个整数 a1,a2,…,aN。
输出格式
每组数据输出一行结果。
数据范围
1≤T≤10,
1≤N≤105,
0≤ai≤106,
∑ai≤106,
每个输入所有 N 之和不超过 105。
自己的解法:
用堆排序的方法,对于每一组数据,建立初始小根堆,进行堆排序。每次排好一个元素后,进行对已排序序列检查,如果已经完成堆排序的序列的部分和(从前往后)可以大于等于目前的最大值,则合并这部分。(全是0的情况除外)合并后更新下次排序需要的参数,继续进行堆排序,合并。直至所有的数都一样或者合成一堆,算法停止,输出答案,进行下一组的堆排序。这需要每次合并后都检查是否每个数都一样。因为考虑到数据量的问题,用枚举是O(n2)的复杂度,会超时,用堆排序降到O(nlog2n)的复杂度。 我的推导过程:
但是考虑到如果每次排序后都进行检查,那么时间复杂度也会上升到O(n2)
自己的代码(没写完):
#include<iostream> #include<vector> using namespace std; vector<vector<int> > v; //v存放所有的数组 int max_vj = -0xffff; //每组数据的最大值 int res = 0; //小根堆的建立 void HeapAdjust(vector<int> &A, int k, int len){ int t = A[k]; //暂存这个分支结点 for(int i = 2*k; i <= len; i *= 2){ //从这个分支结点开始向下调整 if(i < len && A[i] > A[i+1]) i++; //右孩子更小 if(t <= A[i]) break; //分支结点已是子堆中的最小值,符合特性 else{ //不符合特性,需要调整 A[k] = A[i]; //换的时候只是覆盖 k = i; //下标要交换,下次还说与A[0]比较 } } A[k] = t; //放到最终符合特性的位置上 } void BuildMinHeap(vector<int> &A, int len){ //从最后一个分支结点开始,逐级向上建堆 for(int i = len/2; i > 0; i--) HeapAdjust(A, i, len); } //堆排序 void HeapSort(vector<int> &A, int len){ for(int i = len; i > 1; i--){ //n-1趟交换和建堆过程 swap(A[i], A[1]); //堆顶元素和堆底元素互换 //交换后检查是否符合合并的条件 //如果已经完成堆排序的序列的部分和(从后往前)可以大于等于目前的最大值,则合并这部分 //合并后更新下一次需要的参数 if(){ A[len-1] = A[len]+A[len-1]; //合并 if(A[len-1] > max_vj) max_vj = A[len-1]; //更新最大值、长度、合并次数 A[0]--; len--; res++; } HeapAdjust(A, 1, i-1); //将剩余的元素调整 } } int main(){ int T, N, an; //T组测试数据,每组数据包含N个整数an cin >> T; //测试数据的数量 vector<int> vj; //每组数据存放的数组 //下面搞定输入 for(int i = 0; i < T; i++){ cin >> N; //N个整数 vj.
文章目录 1、总览2、元素定位不到的原因之【页面元素没有及时加载】3、元素定位不到的原因之【页面元素不可见或不可点击】4、元素定位不到的原因之【页面元素是动态的】 1、总览 原因解决方法没有打开正确的网址填写正确的网址定位器选择错误选择合适的定位器定位表达式错误简单粗暴:F12 copy或手写定位调试元素嵌套在iframe中1,切换到iframe中:driver.switch_to.frame(’ iframe的id或name值 ');2,再进行元素定位元素在新窗口中1,获取打开的多个窗口句柄:handles = driver.window_handles;2,切换到新窗口中: driver.switch_to.window(handles[-1])页面元素没有及时加载1,加等待,不要加的太少,加10s,如果10秒还找不到说明不是因为页面加载导致的元素找不到;2,确定是页面元素没有及时加载原因后,可以使用以下三种等待方式,详见1.2页面元素不可见或不可点击1,使用JavaScript实现元素定位和动作执行;2,使用鼠标事件ActionChains来操作;3,如果是被伪元素遮挡了原本的元素,可以直接定位到伪元素上进行点击操作 。详见1.3页面元素是动态的1.根据其他静态属性定位;2.根据元素属性值模糊匹配定位。 详见1.4脚本流程与实际不符调整脚本以符合实际业务流程 2、元素定位不到的原因之【页面元素没有及时加载】 问题定位思路:
加等待,不要加的太少,加10s,如果10秒还找不到说明不是因为页面加载导致的元素找不到确定是页面元素没有及时加载原因后,可以使用以下三种等待方式
(1)调试代码使用强制等待:sleep(10) ;
(2)作用于全局使用隐式等待:driver.implicitly_wait(10)
隐式等待一般在实例化dirver之后就设置,在服务端等待,作用于全局,也就是在driver的整个生命周期中生效。隐式等待是动态的查找所有元素,默认每隔0.5s轮询一次(也可以手动设置间隔时间),要查找的元素未加载完就继续等待,如果要查找的元素在规定的timeout时间内提前加载完,则结束等待,执行下一步操作;如果要查找的元素在规定的timeout时间内没有加载完,则会抛出异常。
(3)提升用例执行效率使用显式等待:
显式等待在客户端等待,作用于指定元素,也就是只有在写了显式等待的语句中生效。显式等待也是动态的查找元素,要查找的元素未加载完就继续等待,如果要查找的元素在规定的timeout时间内提前加载完,则结束等待,执行下一步操作;如果要查找的元素在规定的timeout时间内没有加载完,则会抛出异常。需要用到两个类:WebDriverWait 和 expected_conditions 为什么要使用显式等待?
先来了解一下一般html页面上元素的呈现:
title出现 首先出现titledom树出现 存在presence,但还不完整css出现 可见visibilityjs出现,js特效执行 可点击clickable html文档是自上而下进行加载的,有些js通过异步加载的方式来完成js的加载
样式表下载完成之后会跟之前的样式表一起进行解析,会对之前的元素重新渲染
基于以上原理,我们知道,我们看到元素已经显示出来了,但是元素的某些属性可能还没有加载完全,比如元素是否是可见visibility、元素是否是可点击clickable,如果用隐式等待只能判断元素是否在dom树中出现,它无法判断元素是否可见,元素是否可点击,因此我们需要使用显式等待
显式等待可以处理隐式等待无法解决的一些问题,比如:上传文件(可以设置长一点),文件上传需要设置20s以上,但是如果设置隐式等待,它会在每个find方法都等这么长时间,一旦发现没有找到元素,就会等20s以后才抛出异常,影响case的执行效率,这时候就需要用显式等待,显式等待可以设置的长一点
设置显式等待的两种方法:
方法1:使用selenium自带的WebDriverWait 和 expected_conditions类,expected_conditions里面有很多定义好的判断条件供until使用
示例:
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC locator = (By.XPATH, '//*[@id=”current_price“]') WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) 方法2:使用lambda表达式
示例:
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By locator = (By.XPATH, '//*[@id=”current_price“]') ele = WebDriverWait(self.
1 内存的分区 1、内存:物理内存、虚拟内存 物理内存:实实在在存在的存储设备 虚拟内存:操作系统虚拟出来的内存。 操作系统会在物理内存和虚拟内存之间做映射。 在32位系统下,每个进程的寻址范围是4G,0x00 00 00 00 ~0xff ff ff ff 在写应用程序的,看到的都是虚拟地址。 在 32 位操作系统中,虚拟内存被分为两个部分, 3G 的用户空间和 1G 内核空间,其中用户空间是当前进程所私有的,内核空间,是一个系统中所有的进程所公有的 2、在运行程序的时候,操作系统会将 虚拟内存进行分区 1).堆 在动态申请内存的时候,在堆里开辟内存。 2).栈 主要存放局部变量。 3).静态全局区 1:未初始化的静态全局区 静态变量(定义变量的时候,前面加static修饰),或全局变量 ,没有初始化的,存在此区 2:初始化的静态全局区 全局变量、静态变量,赋过初值的,存放在此区 4).代码区 存放程序代码 5).文字常量区 存放常量的。 2 普通的全局变量 概念: 在函数外部定义的变量 int num=100;//num就是一个全局变量 int main() { return 0; } 作用范围: 全局变量的作用范围,是程序的所有地方。 只不过用之前需要声明。声明方法 extern int num; 注意声明的时候,不要赋值。 生命周期: 程序运行的整个过程,一直存在,直到程序结束。 注意:定义普通的全局变量的时候,如果不赋初值,它的值默认为0 1 # include <stdio.h> 2 3 // 定义一个普通全局变量 4 // 只要是在 main 函数外(也在子函数外)的变量,就是全局变量 5 // 如果全局变量没有进行初始化,则系统自动将其初始化为 0 6 int num ; 7 8 // 全局变量可以在程序的任意一个位置进行对其的操作 9 void myfun () 10 { 11 num = 888 ; 12 } 13 14 int main ( int argc , char * argv []) 15 { 16 printf ( "
手机设置了代理后导致无法使用 Wi-Fi 的原因可能有以下几点: 代理配置错误:如果代理设置不正确或与网络环境不兼容,可能会导致 Wi-Fi 连接问题。请确保代理服务器地址、端口和身份验证等信息正确无误,并与网络管理员或服务提供商确认这些设置是否有效。
代理服务器不可用:如果配置了代理服务器但服务器不可用或无法连接,那么可能无法正常使用 Wi-Fi。您可以尝试切换到其他可靠的代理服务器或联系网络管理员解决代理服务器问题。
网络防火墙限制:某些网络环境中,特别是在企业或学校的网络中,可能会设置了严格的防火墙规则,限制了外部代理服务器的访问。这可能导致通过代理的 Wi-Fi 连接无法正常工作。您可以与网络管理员沟通,了解是否存在此类限制,并寻求解决方案。
安全策略限制:某些手机设备可能具有安全策略,例如企业管理策略或安全软件等,可以禁止或限制使用代理服务器,以保护数据安全和隐私。如果是受限于设备的安全策略,您可能需要联系设备管理员或检查设备设置,以了解如何解决此问题。
综上所述,华为手机设置代理后无法使用 Wi-Fi 的原因可能是配置错误、代理服务器问题、网络防火墙限制或设备安全策略限制等。根据具体情况,请检查并调整代理设置,并与网络管理员或设备管理员进行进一步的沟通和协助解决问题。
一、函数的概念 函数是c语言的功能单位,实现一个功能可以封装一个函数来实现。 定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值。 函数就是讲特定功能的代码封装在一个函数内部,当要使用这些代码时,只需要通过函数名 就可以使用,这样操作起来更加方便 二、函数的分类 1、从定义角度分类(即函数是谁实现的) 1.库函数 (c库实现的) 2.自定义函数 (程序员自己实现的函数) 3.系统调用 (操作系统实现的函数) 2、从参数角度分类 1.有参函数 函数有形参,可以是一个,或者多个,参数的类型随便 完全取决于函数的功能 int fun(int a,float b,double c) { } int max(int x,int y) { } 2.无参函数 函数没有参数,在形参列表的位置写个void或什么都不写 int fun(void) { } int fun() { } 3、从返回值角度分类 (1).带返回值的函数 在定义函数的时候,必须带着返回值类型,在函数体里,必须有return 如果没有返回值类型,默认返回整型。 1 char fun () // 定义了一个返回字符数据的函数 2 { 3 char b = 'a' ; 4 return b ; 5 } 1 fun () 2 { 3 return 1 ; 4 } 如果把函数的返回值类型省略了,默认返回整型 注:在定义函数的时候,函数的返回值类型,到底是什么类型的,取决于函数的功能。 (2).
在 CSS 样式中,可以使用 :root 伪类来定义进行全局的变量设置和样式设置。:root 表示文档根元素,一般情况下是表示 <html> 元素。
定义 :root 后,所有变量都将被保存在 :root 中,并且可以在整个页面的任何位置使用。这使得我们可以轻松地为网站设置一些通用的变量,如颜
色、字体、间距等等。
:root { --primary-color: #007bff; /* 设置主要颜色(蓝色) */ --secondary-color: #6c757d; /* 设置次要颜色(灰色) */ --font-family: Arial, sans-serif; /* 设置字体 */ } body { font-family: var(--font-family); /* 使用 var() 函数调用字体 */ background-color: var(--primary-color); /* 使用 var() 函数调用背景色 */ color: var(--secondary-color); /* 使用 var() 函数调用文字颜色 */ } 在上述例子中,我们首先在 :root 中定义了三个变量,包括主要颜色、次要颜色以及字体类型。接着,在 body 中使用了这些变量进行样式的设置,调用了颜色和字体的变量,并设置了背景色和文字颜色。
通过这种方式,我们可以统一管理全局样式,方便快捷地进行修改和更新。
目录
🍁while的语法格式
🍁while循环案例
🍃案例一:输出10-1的降序
🍃案例二:输出10的升序和降序
🍃案例三:批量创建用户
🍁内置跳出循环
🍃案例一:exit退出脚本
🍃案例二:break跳出本次循环
🍃案例三:continue结束本次循环
🦐博客主页:大虾好吃吗的博客
🦐专栏地址:Linux从入门到精通
for循环语句非常适用于列表对象无规律,且列表来源固定(如某个列表文件)的场合。而对要求控制循环次数,操作对象按数字顺序编号,按特定条件执行重复操作等情况,则更适合使用另外一种循环——while。
循环语句的条件只要成立,就会循环执行命令,直到命令不成立。
while的语法格式 true条件,表示变量为真,无线循环直到遇到退出或停止命令才会停止。
#!/bin/bash while true do 命令 done 限制次数循环,let i++,每次加1,从零开始小于等于10以内的次数,如果大于10则停止循环。
#!/bin/bash i=0 while [ $i -le 10 ] do 命令 let i++ done while循环案例 我们已经知道了循环语法的格式,上面基本的语法格式一定要牢记,下面我们通过几个简单的案例来看一下怎么使用。
案例一:输出10-1的降序 输出从10到1的两列降序数字,并计算出总和。
[root@daxia sh]# vim while1.sh #!/bin/bash i=10 while [ $i -gt 0 ] do sum=$(( $i + $i )) echo $i + $i = $sum let i-- done [root@daxia sh]# sh while1.
1.去掉左边空格.replace(/^\s*/g,"");
2.去掉右边空格.replace(/\s*$/g,"");
3.去掉前后空格.replace(/(^\s*)|(\s*$)/g,"")
4.去掉所有的空格.replace(/\s+/g,"")
一、数组的概念 数组是 若干个 相同类型 的 变量 在内存中 有序存储的集合 。 概念理解: 数组用于存储一组数据 数组里面存储的数据类型必须是相同的 数组在内存中会开辟一块连续的空间 int a[10];//定义了一个整型的数组a,a是数组的名字,数组中有10个元素,每个元素的类型 都是int类型,而且在内存中连续存储。 这十个元素分别是a[0] a[1] …. a[9] a[0]~a[9]在内存中连续的顺序存储 二、数组的分类 2.1 按元素的类型分类 1)字符数组 即若干个字符变量的集合,数组中的每个元素都是字符型的变量 char s[10]; s[0],s[1]....s[9]; 2)短整型的数组 short int a[10]; a[0] ,a[9]; a[0]=4;a[9]=8; 3)整型的数组 int a[10]; a[0] a[9]; a[0]=3;a[0]=6; 4) 长整型的数组 lont int a[5]; 5)浮点型的数组(单、双) float a[6]; a[4]=3.14f; double a[8]; a[7]=3.115926; 6)指针数组 char *a[10] int *a[10]; 7)结构体数组 struct stu boy[10]; 2.2 按维数分类 一维数组 int a[30]; 类似于一排平房 二维数组 int a[2][30]; 可以看成一栋楼房 有多层,每层有多个房间,也类似于数学中的矩阵 二维数组可以看成由多个一维数组构成的。 有行,有列, 多维数组 int a[4][2][10]; 三维数组是由多个相同的二维数组构成的 int a[5][4][2][10]; 三、数组的定义 3.
1、数据集构建 MMRoteate 支持的数据集
类别 The object categories in DOTA-v1.0: plane, ship, storage tank, baseball diamond, tennis court, basketball court, ground track field, harbor, bridge, large vehicle, small vehicle, helicopter, roundabout, soccer ball field and swimming pool. The object categories in DOTA-v1.5: plane, ship, storage tank, baseball diamond, tennis court, basketball court, ground track field, harbor, bridge, large vehicle, small vehicle, helicopter, roundabout, soccer ball field, swimming pool and container crane.
什么是Taro? Taro(或称为Taro框架)是一种用于构建跨平台应用程序的开源JavaScript框架。它基于React和React Native,可以用于开发Web、iOS、Android和微信小程序等平台上的应用程序。
Taro的目标是实现一套代码多端运行的方案,开发者可以使用一套React语法编写代码,然后通过Taro编译器将代码转换为不同平台上的原生代码。这样,开发者可以在不同平台上共享大部分代码,并且可以根据特定平台的需求进行微调或定制化开发。
Taro提供了一组丰富的组件和API,可以让开发者在不同平台上构建高性能、可扩展的应用程序。它还支持CSS预处理器,例如Sass和Less,以及第三方UI组件库,如Ant Design和WeUI。
Taro框架的优势 Taro在跨平台开发框架中具有一些独特的优势,这些优势是开发者选择Taro的原因之一:
一套代码多端运行:Taro的主要目标是实现一套代码可以在多个平台上运行。开发者可以使用一套React语法编写代码,然后通过Taro编译器将代码转换为不同平台上的原生代码。这样,开发者可以在多个平台上共享大部分代码,减少了重复工作并提高了开发效率。
完整的跨平台支持:Taro支持多种平台,包括Web、iOS、Android和微信小程序等。开发者可以通过Taro的组件和API在不同平台上构建应用程序,并在不同平台之间共享代码和逻辑。
性能优化和扩展性:Taro致力于提供高性能和可扩展的应用程序开发框架。它使用了一些优化策略和技术,如虚拟DOM、异步渲染和代码分割,以提高应用程序的性能和用户体验。同时,Taro还支持第三方UI组件库和CSS预处理器,可以方便地扩展和定制化应用程序的外观和功能。
生态系统支持:Taro拥有活跃的社区和丰富的生态系统。开发者可以从社区中获取技术支持、学习资源和开源组件,以及与其他开发者分享经验和交流。此外,Taro还有一些官方插件和工具,以及与其他流行框架(如React Native和Vue)的整合方案。
Taro在中国的小程序案例 正因为Taro上述的独特优势,因此在中国有许多丰富的应用实践。尤其是小程序。以下是几个基于Taro框架开发的在中国知名的小程序案例:
美团外卖小程序:美团外卖是中国领先的外卖配送平台之一,他们的小程序使用Taro框架进行开发。该小程序提供了在线订餐、外卖配送、优惠券等功能,用户可以通过小程序方便地订购美食并享受送餐服务。
喜马拉雅FM小程序:喜马拉雅FM是中国最大的音频分享平台,他们也使用Taro框架开发了小程序。该小程序提供了丰富的音频内容,包括电台、有声读物、音乐和播客等。用户可以通过小程序在线收听各种音频内容,随时随地享受优质的音乐和声音。
京东小程序:京东是中国知名的电商平台,他们的小程序也采用了Taro框架进行开发。该小程序提供了在线购物、商品搜索、订单管理和优惠活动等功能。用户可以通过小程序方便地浏览和购买京东商城的各种商品,并享受快速的配送和优质的售后服务。
结合小程序容器,构建如微信App搬灵活的移动应用架构 市面上一些比较知名的小程序容器技术产品包括:微信、支付宝、百度、抖音小程序等,他们都是以完善大社交平台自有小程序生态的技术底座,能提供第三方进行私有化部署的有:FinClip、mPaaS等产品。据了解,FinClip自行研发的小程序容器技术,能够让企业的App能具备快速运行小程序的能力,他们家的SDK还能嵌入除App以外的职能设备终端中(如 Linux、Windows、MacOS、麒麟等操作系统上运行)。
当我们将Taro等跨端框架与小程序容器结合时,跨端框架可以提供一种统一的开发方式,开发者可以使用相同的代码base来编写小程序的业务逻辑和界面。跨端框架通常提供了对小程序容器技术的封装,使开发者可以在不同的小程序平台上(如微信小程序、支付宝小程序、百度小程序等)进行开发和发布。
总结起来,跨端框架和小程序容器的结合可以实现在不同小程序平台上进行跨端开发,提供一种统一的开发方式和代码复用的能力,同时还可以充分利用小程序容器技术的功能和特性。这种结合能够提高开发效率,降低开发成本,并且使开发者能够更好地面对多个小程序平台的开发需求。
通过使用跨端框架,开发者可以在不同的小程序平台上共享代码和逻辑,减少重复开发的工作量。同时,跨端框架也能够提供一些平台特定的扩展能力和适配方案,以适应不同小程序平台的特殊需求和特性。
活动目录(AD)凭借其独特管理优势,从众多企业管理服务中脱颖而出,成为内网管理中的佼佼者。采用活动目录来管理的内网,称为AD域。
了解AD域,有助于企业员工更好地与其它部门协作,同时提高安全意识。中安网星由此推出AD域安全科普系列,为大家讲解AD域的安全管理。
上一篇文章,我们了解了AD域的架构和原理。本篇文章我们将引入AD域服务的重头戏——AD域的功能。
众所周知,AD域在企业内网中扮演了重要的角色,集身份验证和服务管理于一身。它是如何进行身份验证和资源管理的,在企业内网管理中有什么明显优势呢?
本篇文章从AD域服务对资源对象的管理方式开始,逐步讲述它的身份验证能力和策略配置特性。
全局资源管理 要将内网中的资源部署到AD域内,需要在域控上注册。域计算机和打印机、共享文件夹等一起组成域环境,企业员工要在这个域环境内办公,需要注册成为域用户。
所有资源注册成功后,由AD域来统一管理。下面,我们通过AD域管理域计算机和域用户的一些特点,来探查其一般模式。
本地计算机在域控上注册后就成为域计算机,拥有单独的域账户,该账户记录计算机的位置、操作系统类型和计算机名等信息。
这个计算机名并非原名,而是在加域后重新生成的。它采用DNS格式,在允许分配单独名称的基础上,还能清晰显示组织单位中的计算机结构。比如在zawx.com域下注册的计算机,名称可能为pc.zawx.com。
企业员工在域控上注册成为域用户后,也会生成单独的域账户,账户上保存了员工的电话、邮箱、身份证号等基本信息,还有权限、账号密码等信息。
不同用户拥有不同权限:
普通域用户:
普通域用户接受域管理员的指派,对资源的使用程度有限制。一般是根据员工岗位的实际情况赋予权限,比如允许使用打印机,拒绝修改共享文件夹等。
域管理员:
域管理员管理域内资源的使用关系,委派域用户间的适应关系,比如允许A用户更改其它用户的密码。
企业管理员:
企业管理员账户存在于企业的每一个域中,拥有对每一个域的登录权限。它是企业中权限级别最高的账户,能够指派或取消域管理员权限。
由上,我们可以看出AD域对资源的一般管理模式是:为注册资源创建一个单独账户,在这个账户上记录资源的一般信息(如位置、电话)和特殊的域内信息(如权限、域内名称)。
在数据库中,AD域将这些资源信息以树形目录的方式组织,在叶子节点存储数据。
这种形式下,管理员可以直接使用标识名(DN)和相对标识名(RDN)两种命名路径来访问资源,相比于挨个对比,极大地提升了资源搜索效率。
统一身份验证 域用户在内网中采用单点登录方式,即登录过程由域控统一验证,验证成功就可访问域内资源。
登录过程中,域计算机将用户信息发送给域控,域控会进行计算机和用户两个账号的验证。
域控对计算机进行验证的方式是通过对比本地和域控上保存的计算机账户密码。本地密码每30天更新一次,新旧密码同时保存。验证过程中,先发送新密码,再发送旧密码。两密码中的任何一个与域控上保存的密码相同,就能通过验证。
而对域用户的验证一般是用的Kerberos认证。Kerberos认证服务器KDC安装在域控上,由AS和TGS组成。用户信息先发送给AS,由AS在AD数据库中查询是否有该用户记录,如果存在且信息吻合,就返回一个TGT。之后用户使用TGT向TGS请求Ticket,然后就能使用该Ticket访问特定服务了。
正是因为登录验证过程是在域控上统一进行,域用户在任一域计算机上都能登录,并获得同样的该用户权限。这种方式让用户登录更具灵活性,也增强了抵抗主机故障的能力。
集中策略配置 AD域最大的管理优势是,只需一次操作,就能实现大量资源属性的配置。
要达到这种效果,有分组和组策略两种方式。
分组情况下,需要域管理员手动将符合条件的域用户加到一个组中,然后对该组对象进行配置,最终作用到组内每一个用户身上,一般有通信组和安全组两种类型。
在通信组中,对该通信组发送一次消息,就会分发给组内所有成员,比如邮件组。
安全组主要是用来设置权限,通常将企业内同一岗位的员工放到一个组中配置权限;对新加入的用户,可以将它添加到相应的组,直接继承该组权限。
组策略对象由容器和模板两部分组成。如果将容器用食物来比喻,模板就像调味料,决定食物是什么味道的。容器一般由组织单位、域、站点等来充当,而模板可以是首选项设置、软件安装等。
创建域时,通常会形成两个默认组策略对象,一个是默认域策略,一个是默认域控制器策略。这两个组策略配置了域的基本属性,一般不能被修改。
拿域组策略来说,组策略会对域中的每个计算机和用户产生影响。组策略的应用效果保存在注册表中,计算机通过读取注册表来表现组策略内容。
如果计算机所属的域和组织单位等都分别配置了组策略,它将根据优先级从小到大地应用。通常的优先级顺序是:本地组策略——站点组策略——域组策略——组织单位组策略,如果有冲突,则以最高优先级为准。
集中策略配置为管理员省去了不少麻烦,帮助企业提高了整体工作效率。
# 结语 # 本文我们探讨了AD域的资源管理、身份验证和策略配置等功能属性,此基础上,更多特性等着我们在企业应用实践中一一探索。
同时,AD域在发展得越来越适应企业管理需求时,也面临着更多针对它的独特攻击手法。在大量应用AD域的基础上,我们也应当注重其安全防护建设。
活动目录(AD)凭借其独特管理优势,从众多企业管理服务中脱颖而出,成为内网管理中的佼佼者。采用活动目录来管理的内网,称为AD域。
了解AD域,有助于企业员工更好地与其它部门协作,同时提高安全意识。中安网星由此推出AD域安全科普系列,为大家讲解AD域的安全管理。
AD域将企业内网中的所有资源对象集中到域控上,存储在AD数据库中,采用DNS规则命名,方便管理的同时提高安全性。
这一篇文章中,我们先给大家介绍下AD域服务的应用环境——域,在了解清楚域的形成和结构之后,才能对AD域服务的功能有更深入的理解。
域的形成
在企业办公场景中,经常需要部门间互相共享资源,如果每与其它计算机通信一次,都要经过一次身份验证,会大大影响部门间的协调性,影响办公效率。
如果我们简单地关闭身份验证服务,将会导致计算机面临严重的安全风险,这种方法得不偿失。最好是与企业内部计算机通信时能够免去身份验证,而与外部计算机通信时依然保留身份验证服务。
这就需要在内部员工计算机间构建信任关系,建立了信任关系的计算机连起来就形成域。域外计算机与域内计算机通信需要进行身份验证,不同域的域计算机通信前需建立信任关系。当以域为单位建立信任关系时,可以在两域中的所有计算机间进行免验证通信。
而企业员工只需注册成域用户,在任一台域计算机上登录,就能与其它域用户通信。
这其实与单点登录的功能类似。单点登录中,用户只需进行一次身份验证,就能访问所有服务器。在域中,域用户只需要在登录时进行一次身份验证,就能与其它域用户进行免验证通信。
这个对用户进行身份验证的服务器就是域控制器(DC),简称域控。
域控
域控是集中存储域内所有资源对象及其属性的服务器。如果把域内资源对象看作团队成员,域控就相当于团队的领导者,所有人都要听它安排,所有事情都要给它汇报,包括对象信息变动、权限划分、资源分配等。
比如,企业中有新员工入职时,就要在域控上给他注册一个账号。该账号作为他进行域内活动的唯一凭证,关联他的所有信息,包括工作岗位、电话号码、对域内资源的使用权限等。
也正因此,黑客侵入企业内网后,都会想方设法横向移动到域控主机,夺取其控制权,进而掌握域内所有资源信息。
更为棘手的是,假使黑客攻破了域控主机,删除其上存储的全部信息,并破坏域控主机的正常功能,那么即使企业能够检测查杀入侵活动,也无法恢复正常业务功能。
这种情况下,我们通常会通过部署额外域控的方式来降低风险。顾名思义,额外域控就是在在已经存在一个域控的基础上,又多设置的域控。
我们只要将主域控上的信息备份到额外域控,并同步更新,那么在主域控发生故障时,就能用额外域控暂时代替主域控,保证信息系统的正常运行。
除此之外,额外域控还有一个重要作用,就是提高效率,它可以在有许多域用户要求提供服务时,替主域控分担压力,由它来响应部分用户的请求,从而提高企业整体效率。
除了以上提到的两种类型,还有一种只能读不能写的域控,简称只读域控(RODC)。
在只读域控管辖的域范围,用户只能进行登录验证和查找资源,而无法修改资源信息和配置组策略等,一般在企业的分支机构中应用较多。
当分支机构与中心内网间断开联系,用户无法通过中心域控登录,为了不影响他的正常工作,就由中心域控将用户信息拷贝到只读域控上,用户就能通过只读域控验证登录。
这样,就能保证分支机构的权限不必过大,也能正常运行。
域控作为域内资源管理的主导者,拥有极大的权限,也经常成为攻击者侵入企业内网的目标。保护内网安全,我们必须加强对域控的防护。
域树、域林
作为一台集中管理资源的设备,单一域控的承载能力是有限的,当域内用户数量达到它的承载极限时,为了满足需求,需要在其下再划分一个域。
新划分的域从旧域中衍生出来,与旧域建立了双向传递的信任关系,两者共享同一个存储结构和配置。因为他们间存在上下层次的依赖关系,一般我们将旧域称为父域,新域称为子域。
父域和子域形成连续的名字空间,同一名字空间的域连成域树。通常将第一个创建的域作为树根,其它随后创建的域就作为树的枝干延伸。每一个子域都用其上父域的名字作为域名后缀,比如,父域的名称是zawx.com时,子域的名称可能为a.zawx.com。
当内网中形成了多棵域树,会给管理增加困难。实际上,不管划分了多少片域形成了多少棵域树,他们都是属于同一个企业的。我们可以将企业中的所有域树连起来,用统一的活动目录管理,这就形成了域林。
“林”中的所有“树”共享同一个存储结构、配置和全局目录。通常将“林”中第一个创建的域作为根域,根域相当于“林”的主人,能够管理其它域,并在其上存储部分其它域的资源。
“林”中的域用户登录后,不仅可以与本域用户进行免验证通信,还能与林中其它域用户免验证通信。甚至在其它域赋予权限后,能查找及使用它域的资源。
简单来说,域树、域林是多个域的集合,从概念上来看,域树、域林代表了更大范围的信任联系,能协调更多部门间的通信和资源使用关系,更大程度上提高企业整体的协作效率。
# 结语 #
以上篇章中,我们为大家讲解了域、域控和域树、域林。在企业中应用时,通常将每个子公司单独划分成域,由子公司管理,再在各个域间建立双向传递的信任关系形成域树、域林,由企业统一管理。
实际上,域树域林的形成是借助了活动目录强大的拓展性。活动目录(AD)在内网管理中的优势不限于此,还有很多值得探索的地方,下一篇文章中,我们将给大家详细介绍AD域服务的功能。
在 Java 中,isEmpty() 和 isBlank() 方法用于判断字符串是否为空或空格字符。这两个方法的区别在于,isEmpty() 只能检测字符串是否为空,而isBlank()不仅能检测字符串是否为空,还可以检测一个字符串是否只包含空格字符。
具体来说,如果一个字符串为 null 或长度为0,那么isEmpty()方法将返回 true。例如:
String str1 = ""; String str2 = null; System.out.println(str1.isEmpty()); // 输出 true System.out.println(str2.isEmpty()); // 报错:NullPointerException 而如果一个字符串只包含空格字符,即使它的长度不为0,isEmpty()方法也会返回 false。例如:
String str3 = " "; System.out.println(str3.isEmpty()); // 输出 false 与之不同的是,isBlank()方法除了检测字符串是否为空,还会检查字符串是否只包含空格字符。例如:
String str1 = ""; String str2 = null; String str3 = " "; System.out.println(str1.isBlank()); // 输出 true System.out.println(str2.isBlank()); // 报错:NullPointerException System.out.println(str3.isBlank()); // 输出 true 因此,如果程序需要考虑到字符串只包含空格字符的情况,那么应该使用isBlank()方法。如果需要检查字符串是否为空,则可以使用isEmpty()方法。
问题描述:在实际开发, 我们经常会通过v-if控制表格列的显隐,来实现不同条件下展示不同的表格列,这时候就可能会出现表格列显示错乱、以及表头闪动等问题
问题分析:
表格列显示错乱:由于key值不会被及时的更新,在显示或者隐藏列时,部分DOM会被继续复用,不会重新渲染,导致列显示错乱
表头闪动:由于列的显示或者隐藏,导致了重排以及重绘,表格发生闪动
问题解决:
表格列显示错乱问题解决:
为表格的el-table-column 添加key值 :key=“Math.random()”
<el-table-column v-if="isGetFl" :key="Math.random()" label="xxx" align="center" width="120"> <template> <el-input v-model="wasteWeight" style="width: 100px;" onkeyup="value=value.replace(/[^0-9.]/g,'').replace(/^0[0-9][0-9]*$/g,'')" > <span style="margin-top: 9px; display: block" slot="suffix">kg</span> </el-input> </template> </el-table-column> 表头闪动问题解决: 在生命周期函数beforeUpdate中调用表格的 doLayout() 方法 (尽量加上可选链,不然可能存在获取不到table实例,造成doLayout为undefined的情况)
beforeUpdate () { this.$nextTick(() => { this.$refs.table?.doLayout() }) }
题目描述
有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究。
但此电脑除了有一个3.5寸软盘驱动器以外,没有任何手段可以将文件持贝出来,而且只有一张软盘可以使用。
因此这一张软盘是唯一可以用来拷贝文件的载体。
科学家想要尽可能多地将计算机中的信息拷贝到软盘中,做到软盘中文件内容总大小最大。
已知该软盘容量为1474560字节。文件占用的软盘空间都是按块分配的,每个块大小为512个字节。一个块只能被一个文件使用。拷贝到软盘中的文件必须是完整的,且不能采取任何压缩技术。
输入描述
第1行为一个整数N,表示计算机中的文件数量。1 ≤ N ≤ 1000.
接下来的第2行到第N+1行(共N行),每行为一个整数,表示每个文件的大小Si,单位为字节。
0 ≤ i < N,0 ≤ Si
输出描述
科学家最多能拷贝的文件总大小
备注 为了充分利用软盘空间,将每个文件在软盘上占用的块记录到本子上。即真正占用软盘空间的只有文件内容本身。
用例
输入3
737270
737272
737288输出1474542说明3个文件中,每个文件实际占用的大小分别为737280字节、737280字节、737792字节。
只能选取前两个文件,总大小为1474542字节。虽然后两个文件总大小更大且未超过1474560字节,但因为实际占用的大小超过了1474560字节,所以不能选后两个文件。 输入6
400000
200000
200000
200000
400000
400000输出1400000说明 从6个文件中,选择3个大小为400000的文件和1个大小为200000的文件,得到最大总大小为1400000。
也可以选择2个大小为400000的文件和3个大小为200000的文件,得到的总大小也是1400000
目录
1、神经网络
2、前反馈神经网络
3、卷积神经网络
1、神经网络 说明 神经网络(Neural Network)是一种由神经元(neuron)构成的计算模型,它通过构建多个层次结构,并在不同层之间传递数据来实现输入数据到输出结果的转换。神经网络的构建过程就是确定神经元之间的连接方式和权重,并通过不断调整权重来优化网络的性能。 主流的连接方式有全连接、卷积连接(提取局部特征、权重共享)、残差连接(添加跨层的直接连接)、循环连接(添加时间上的循环连接)激活函数的特点 连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以利用数值优化的方法来学习网络参数激活函数及其导函数要尽可能的简单,有利于提高网络计算效率激活函数的的导函数的值域要在一个合适的区间内,不能太大也不能太小,否则会影响训练的效率和稳定性。(主要是避免梯度消失和梯度爆炸)常见激活函数 Sigmoid型函数 一类S型函数,为两端饱和函数,常用的Sigmoid函数有Logistic函数和Tanh函数(左饱和:x趋于负无穷,其f(x)的导数趋于0) Logistic函数 图像因为logistic函数的性质,使得装备了Logistic激活函数的神经元具有以下两条性质 其输出可以直接看做概率分布其可以看做一个软性门(Soft Gate),用来控制其他神经元的输出信息(类似于一个阈值函数,大于会怎样,小于又会怎样)Tanh函数 图像(公式)Hard-Logistic函数和Hard-Tanh函数 因为Logistic函数和Tanh函数的计算开销较大,然后其图像中间部分又近似线性。所以把其原函数改为分段函数表示,中间写成一段线性函数。图像(g公式)说明 Sigmoid型激活函数会导致一个非稀疏的神经网络Relu函数(Rectified Lineat Unit ,修正线性单元) 图像(公式)优点 神经元只需要进行加、乘和比较的运算,计算比较高效Relu具有很好的稀疏性,大约50%的神经元会处于激活状态相比Sigmoid函数,relu函数为左饱和函数,且在X>0时导数为1,在一定程度上缓解了神经网络的梯度消失问题,加速梯度下降的收敛速度。缺点 输出不是以0为中心的:ReLU函数的输出范围为[0, +∞),因此其输出值不是以0为中心的,这可能会导致网络优化时出现偏差问题。Dead ReLU问题:当输入值小于等于0时,ReLU函数的导数为0,导致对应的神经元无法再被激活。如果出现大量神经元无法激活的情况,就会出现“Dead ReLU”问题,导致模型性能下降。参数不可共享:由于ReLU函数是基于每个神经元的输入值进行计算的,因此其参数无法共享,这使得模型的参数量相对较大。Relu的变种 带泄露的ReLU(Leaky ReLU) 说明 在输入小于0时候,保持一个很小的梯度,这样当神经元非激活时也能有一个非0的 梯度进行更新参数,避免永远不能被激活图像(公式)带参数的ReLU(Parametric ReLU,PReLU) 说明 引入一个可学习的参数,不同神经元可以有不同的参数图像公式()Leaky ReLu和PReLU的联系 Leaky ReLU在输入小于0时不是返回0,而是返回一个比较小的值,这个小值是一个固定的超参数,比如0.01。Leaky ReLU可以缓解Dead ReLU问题,但这个超参数需要手动设置,不能根据数据自动学习。PReLU是Leaky ReLU的进一步发展,它将这个超参数变成可学习的参数,从而可以通过反向传播算法自动学习得到最优的值。PReLU在深层神经网络中通常比Leaky ReLU表现更好,因为它可以自适应地调整参数,更好地适应不同的数据集和任务。总的来说,Leaky ReLU和PReLU都是对ReLU的优化和改进,它们都可以缓解Dead ReLU问题,并且具有比ReLU更好的鲁棒性和表现。ELU函数Softplus函数Swish函数GELU函数Maxout函数 说明 Maxout单元也是一种分段线性函数,Maxout单元的输入是上一层神经元的全部原始输出,是一个向量。优点 Maxout单元的优点是,它比一般的激活函数具有更大的表达能力。它可以拟合几乎所有函数,包括线性和非线性函数,而且具有更好的鲁棒性和泛化能力。此外,Maxout单元的训练过程比较简单,可以使用常规的反向传播算法进行优化。缺点 它需要更多的参数来进行训练。每个Maxout单元都有$k$个线性函数,因此需要学习的参数比其他激活函数要多得多。此外,Maxout单元的计算成本也比较高,因为需要计算$k$个线性函数的输出并选择最大值。说明2 Maxout单元的确是一种比较简单粗暴的激活函数,但由于其需要更多的参数和计算成本,因此在实践中并不是最优的选择。在深度学习的实际应用中,我们通常会根据具体任务和数据集的特点选择合适的激活函数,综合考虑模型的性能和计算效率。而在大多数情况下,ReLU仍然是最常用的激活函数之一,因为它简单、高效,而且在大多数任务中表现良好。常见激活函数及其导数 图像常用的神经网络结构 前馈网络 说明 前馈网络可以看作一个函数,实现简单非线性函数的多次复合,实现输入空间到输出空间的复杂映射,这种网络简单,易于实现记忆网络 常见的记忆网络 循环神经网络、Hopfield网络、波尔茨曼机、受限波尔茨曼机说明 记忆网络可以看作一个程序,具有更强的计算和记忆能力图网络 说明 图神经网络具有任意连接的能力,其节点之间的连接关系不仅仅是简单的前向连接或反向连接,还包括节点之间的任意连接,因此其网络结构也比较复杂。优化问题 说明 神经网络的参数学习比线性模型要更加困难,主要原因有两点1)非凸优化问题2)梯度消失问题 2、前反馈神经网络 说明 前馈神经网络(Feedforward Neural Network,也称为多层感知机,Multilayer Perceptron,MLP)是一种最常见的神经网络模型之一。它包含输入层、若干个隐藏层和输出层,其中每个隐藏层由若干个神经元组成,每个神经元都与上一层的所有神经元相连,并根据它们的权重对上一层的输出进行加权求和,然后将结果通过激活函数进行非线性映射,最终传递到下一层。输出层的神经元数量取决于任务的类型,例如二元分类任务需要一个输出神经元,而多类别分类任务则需要多个输出神经元。图像(前馈神经网络的记号)通用近似定理 在神经网络领域中,通用近似定理(Universal Approximation Theorem)是指一个前馈神经网络具有足够的参数,可以以任意精度来逼近一个连续函数。简单来说,就是给定一个连续函数,只要神经网络的结构足够复杂,就可以用神经网络来逼近该函数的值。参数学习(定义参数变化的方向)反向传播 误差反向传播算法的前馈神经网络可以分为以下三步 前馈计算每一层的净输入z(l)和激活值a(l),直到最后一步反向传播计算每一层的误差项计算每一层参数的偏导数,并更新参数全连接前馈神经网络的缺点 参数太多:这会导致整个神经网络的训练效率非常低,也很容易出现过拟合局部不变性特征:自然图像的物体都具有局部不变性特征,比如尺度缩放、平移、旋转等操作不影响其语义信息。而全连接前馈神经网络很难提取这些局部不变性特征,一般需要进行数据增强来提高性能 3、卷积神经网络 卷积 一维卷积 说明 一维卷积常用在信号处理中,用于计算信号的延迟累积二维卷积在图像处理中,一幅图像在经过卷积操作后得到结果称为特征映射卷积的变种 说明 在卷积的标准定义下,还可以引入卷积核的滑动步长和零填充来增加卷积的多样性,可以灵活地进行特征提取步长:是指卷积核在滑动时的时间间隔零填充:是在输入向量两端进行补零窄卷积、宽卷积、等宽卷积 图像互相关 说明 在机器学习和图像处理领域,卷积的主要功能是在一个图像(或某种特征)上滑动一个卷积核(及滤波器),通过卷积操作得到一组新的特征,在计算卷积的过程中需要进行卷积核翻转。对比 互相关和卷积的区别仅仅在于卷积核是否进行翻转,因此互相关也可以称为不翻转的卷积说明:在机器学习中所说的卷积计算其实就是互相关操作。因为在神经网络中使用卷积是为了进行特征抽取,卷积核是否进行翻转何其特征的抽取能力无关。说明 卷积神经网络(CNN)是一种具有局部连接、权重共享等特性的深层前馈神经网络卷积神经网络一般是由卷积层、汇聚层(池化层)和全连接层交叉堆叠而成的前馈神经网络卷积神经网络的三个结构上的特点 局部连接、权重共享、汇聚卷积神经网络主要使用在图像和视频分析的各种任务上用卷积来代替全连接 卷积层两个重要性质 局部连接 卷积层和前一层直接的连接数大大减少权重共享 权重共享可以理解为一个卷积核只捕捉输入数据中的一种特定的局部特征,因此,如果要提取多种特征就需要使用多个不同的卷积核。卷积层 说明 卷积层的作用是提取一个局部区域的特征,不同的卷积核相当于不同的特征提取器。特征映射 说明 特征映射为一幅图像(或其他特征映射)在经过卷积提取到的特征,每个特征映射可以作为一类抽取的图像特征。特征映射 在输入层,特征映射就是其本身如果是灰度图像,就是有一个特征映射,输入层的深度D=1如果是彩色图像,分别有RGB三个颜色通道的特征映射,输入层的深度D=3汇聚层(池化层) 说明 汇聚层也叫子采样层,其作用是进行特征选择,降低特征的数量,从而减少参数数量卷积层虽然可以显著减少网络中连接的数量,但特征映射组中的神经元个数并没有显著减少,如果后面接一个分类器,分类器的输入维度依然很高,很容易出现过拟合。常见的汇聚函数 最大汇聚平均汇聚图像说明 目前主流的卷积网络中,汇聚层仅包含下采样操作,但在早期的一些卷积网络(比如LeNet-5)中,又是也会在汇聚层使用非线性激活函数。卷积网络的整体结构 图像趋势 整体结构趋向于使用更小的卷积核以及更深的结构汇聚层的比例正在逐渐减低,趋向于全卷积网络参数 计算 卷积层参数计算 输出特征图通道数=卷积核个数每个卷积核的权重参数个数=卷积核宽度*卷积核高度*输入特征图的通道数卷积层总参数量=每个卷积核的权重参数个数*卷积核个数+卷积核个数(p偏置)池化层参数计算 池化层的参数通常没有权重参数,只有一个池化核的大小和步长参数。输出的特征图通道数=输入特征图通道数每个池化核的输入大小=池化核宽度*池化核高度*输入特征图通道数池化层的总参数量为0全连接层参数计算 输出特征数=全连接层神经元个数 (特征数是指输入数据的通道数或特征图的深度)每个神经元的权重参数个数=输入特征数。全连接层总参数量=输入特征数*全连接层神经元个数+全连接层神经元个数(偏置项) (全连接层的神经元个数通常是指上一层输出的特征数)
环境:win10系统上,使用VMware安装CentOS虚拟机。
遇到的问题:虚拟机运行后,使用Xshell或Termius连接ssh,失败,在CentOS中使用ifconfig查询ip,发现为192.168.44.131,真机ip是192.168.31.142。
解决办法:设置虚拟机的网卡为桥接模式,之后查询ip为192.168.31.132,可以正常连接ssh了。
本文主要说明perf和FrameGraph的使用,例如:火焰图的输出,系统性能状态查看等。
Author:mayimin
perf version 3.10.0-1160.80.1.el7.x86_64.debug
参考资料:perf example: https://www.brendangregg.com/perf.html
一、 Perf perf 中包含工具众多,本文只说明其中一部分,如:perf bench、perf list、perf record、perf report、perf stat、perf top。
1. perf list perf list不是实际的功能工具,主要是列出 perf 支持的事件,例如:cpu周期、总线周期等。
Usage: perf list [<options>] [hw|sw|cache|tracepoint|pmu|sdt|event_glob] 主要有以下几种事件:
hw:Hardware event,8个 # 硬件事件
sw:Software event,11个 # 软件事件
cache:Hardware cache event,20个 # 硬件缓存事件
tracepoint:Tracepoint event,2196个 # 跟踪点事件
下面看看每种事件中都有什么:
硬件 List of pre-defined events (to be used in -e): branch-instructions OR branches [Hardware event] # 分支指令 branch-misses [Hardware event] # 分支预测失败 // CPU 取指执行需要提前载入数据和指令,在流水线处理中硬件会有分支预测 bus-cycles [Hardware event] # 总线周期 cache-misses [Hardware event] # 缓存未命中 cache-references [Hardware event] # 缓存命中 cpu-cycles OR cycles [Hardware event] # CPU周期 instructions [Hardware event] # 指令 ref-cycles [Hardware event] # 参考周期 软件 List of pre-defined events (to be used in -e): alignment-faults [Software event] bpf-output [Software event] context-switches OR cs [Software event] # 上下文切换 // CPU从在内核态和用户态切换,或者在进程间切换,引起的寄存器值的变化,称为上下文切换 cpu-clock [Software event] # cpu 时钟 cpu-migrations OR migrations [Software event] dummy [Software event] emulation-faults [Software event] major-faults [Software event] minor-faults [Software event] page-faults OR faults [Software event] # 内存缺页 task-clock [Software event] 缓存 List of pre-defined events (to be used in -e): L1-dcache-load-misses [Hardware cache event] # L1缓存未命中(数据寄存区) L1-dcache-loads [Hardware cache event] # L1缓存命中(数据寄存区) L1-dcache-stores [Hardware cache event] # L1 缓存写回命中 L1-icache-load-misses [Hardware cache event] # L1缓存未命中(指令寄存区) LLC-load-misses [Hardware cache event] # 最后一级缓存未命中 LLC-loads [Hardware cache event] # 最后一级缓存命中 LLC-store-misses [Hardware cache event] # LLC缓存写回丢失 LLC-stores [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] dTLB-store-misses [Hardware cache event] dTLB-stores [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] node-load-misses [Hardware cache event] node-loads [Hardware cache event] node-store-misses [Hardware cache event] node-stores [Hardware cache event] 其中loads和stores分别代表预测和写回过程,一个是CPU要载入、一个是CPU要存储,i和d分别代表
目录
网络环境配置
1. 配置windows环境下协议
2. 配置linux环境下的网络
3. 开发板
4. Ping 不通解决办法
搭建TFTP服务器环境搭建
》1.验证tftp服务器环境是否搭建
》2.若是未安装,执行下面命令
》3.修改tftp服务器配置文件
》4.在ubuntu下创建工作目录并设置为最高权限
》5.重启tftp服务
》6.验证是否成功
网络环境配置 1. 配置windows环境下协议 注:windows开启或者关闭防火墙影响开发板和linux能否链接到windows
2. 配置linux环境下的网络 3. 开发板 网关IP(gateway ip)
IP地址(Ipaddr)
网络掩码(netmask)
服务器IP(server ip)
设置上面代码方法
setenv gatewayip 192.168.1.1 setenv ipaddr 192.168.1.200 setenv netmask 255.255.255.0 setenv serverip 192.168.1.125 saveenv //保存所有 在开发板输入ping 192.168.1.125会出现两种情况
第一种:
第二种:
4. Ping 不通解决办法 关闭防火墙
检查硬件连接、检查服务器 IP 网卡配置等。
如果你是电脑的网口,那需要改一下速率。配置为百兆全双工
搭建TFTP服务器环境搭建 》1.验证tftp服务器环境是否搭建 dpkg -s tftpd-hpa
下图代表安装完成
》2.若是未安装,执行下面命令 sudo apt-get install tftpd-hpa tftp-hpa
1 选择控制语句 if语句 形式: 1) if(条件表达式) { //复合语句,若干条语句的集合 语句1; 语句2; } 2) if(条件表达式) { 语句块1 } else { 语句块2 } 3) if(条件表达式1) { 语句块1 } else if(条件表达式2) { 语句块2 } else if(条件表达式3) { 语句块3 } ... else { 语句块n } switch语句 switch(表达式)//表达式只能是字符型或整型的(short int int long int) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; ... default: 语句3; break; } 运行顺序:将常量表达式的值语句switch后面的表达式的值对比,如果表达式的值刚好等于case后面的某一个值,就会立即去执行case后的语句,如果都不是,则会执行default 后面的语句 注意事项: (1)switch后面的表达式不能是浮点型,只能是整形的 (2)如果case后面的常量表达式与switch的表达式的值都不同,则执行default后面的语句 (3)每一个case执行结束后理论上必须跟一个break,作用就是跳出整个switch语句 (4)case后面如果语句很多,不需要加大括号 2 循环控制语句 for循环 for(表达式1;表达式2;表达式3) { //复合语句,循环体 语句块 } 执行顺序: 先执行表达式1,然后执行表达式2,如果表达式2成立,则执行语句块 当语句块执行完毕之后,接着执行表达式3,然后再执行表达式2, 如果表达式2成立,则继续执行语句块,以此类推,直到表达式2不成立,循环结束 例如: int i; for(i = 1; i <= 10; i++) { } #include <stdio.
哈喽,大家好~我是你们的老朋友:保护小周ღ Cookie 和 Session 都是网页中常用的状态保持的技术,它们可以帮助网站识别用户身份,保存用户状态等,什么是 Cookie ?什么是 Session ?他们具体是什么?他们有什么区别和联系,本文将为你详细解惑,一起来看看叭~
本期收录于博主的专栏:网络编程_保护小周ღ的博客-CSDN博客
适用于编程初学者,感兴趣的朋友们可以订阅,查看其它 “网络基础知识”。
更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* ‘
一、Cookie 简介 Cookie —— 浏览器提供的一种持久化存储的机制。
为什么有浏览器需要给用户提供Cookie 这种持久化存储呢,直接存硬盘不好吗,换而言之 Cookie机制到底是个啥???
早期浏览器为了避免用户访问恶意网站,进而网站内部的恶意代码可能会对用户设备上的资源造成影响,例如:植入病毒,爬取用户资源,删除用户资源…… 这些情况都可以通过网站代码对设备进行操作,联想一下网站可以上传文件,图片等资源,这是我们主动的行为,但是有些行为可以由代码自动执行。浏览器——默认不允许网站随便访问用户设备上的资源
针对上述情况,网站又需要浏览器能够存储一些关键信息,用于客户端与服务器进行交互,提高用户体验度。Cookie 主要存储的数据就是 用户的账号和密码,当用户登录进入网站后,网站服务器会先对账户进行校验,校验无误后将账户信息写回到浏览器,浏览器就会将账户信息存在 Cookie 中,当用户点击网页上的某些操作向网站的服务器发出请求时,浏览器会将 Cookie 中用户信息也附带着写入请求中,例如:张三整个用户登录了百度的网站,我们一般是游客模式,登录后用百度搜索引擎搜索了“美女”,此时服务器就可以根据 Cookie 中的信息判断当前是那个用户在操作页面——张三某年某月某日,那个IP地址,什么设备,什么浏览器,什么搜索引擎,搜索了美女 。不要随便用网页浏览啥哦,因为服务器全知道而且非常详细~
Cookie是一种用于存储用户相关信息的 “小文件” (一般来说,每个Cookie的大小限制为4KB以内),它通常由服务器发送到客户端的Web浏览器,然后由浏览器存储在本地的计算机上。当用户访问同一网站时,浏览器会将该网站相关的cookie传递给服务器,使服务器可以读取并使用其中的数据——Cookie 是以键值对的形式保存数据。
浏览器会针对每一个域名(IP 地址的映射 例如:www.baidu.com),在硬盘上划分一块空间,这块空间就是Cookie.
总结:
1. Cookie 是个啥?
浏览器提供的持久化存储的机制,防止恶意网站代码对用户设备资源造成影响,不允许网页随便访问用户资源,有的时候又希望,浏览器能持久化存储一些关键信息,用于给服务器交互,最常见的是存储用户的账户信息,所有浏览器会将针对每一个域名,在硬盘上划分一块空间,这块空间就是Cookie
2. Cookie 中的数据从哪里来?
Cookie 中的数据是从服务器返回给浏览器的,服务器代码中由程序猿决定要把啥样的信息保存到客户端这边,通过 HTTP 响应的 Set-Cookie字段,把键值对写回去。
3. Cookie 中的数据到哪里去?
Cookie 的数据会在后续的浏览器访问服务器的时候带到请求的 header 中的 Cookie 字段中发送给服务器。
4. Cookie 有什么用?
1. 便于客户端与服务器进行交互
数禾科技 AI 模型服务基于云原生架构,为不同业务环节提供智能决策支持。随着业务的快速发展,摆在数禾面前的难题是支撑模型计算的底层应用资源无法根据请求量来调整机器资源支持运算能力。同时,随着模型在线推理服务数量的增加,数禾的模型服务也变得越来越庞大、臃肿,难以管理。这种状况不仅导致了资源浪费,还增加了维护和升级的成本。
为了解决这些“顽疾”,数禾科技采用阿里云 ASK 部署线上模型,无需 K8s 节点管理,根据实时流量动态使用 POD,资源成本节省 60%;通过 ASK Knative 服务,解决了数禾模型的灰度发布和多版本并存问题;得益于ASK 自动伸缩和缩容到 0 的优势,降低运行成本,大幅提升服务可用性。
目前,该系统已上线部署 500+AI 模型服务,每天能够提供上亿次查询决策服务,具备无限横向扩展的能力。同时,数禾科技 AI 模型服务支持自动调整容量,满足不同业务压力下的需求,从而保障业务的稳定运行。不仅如此,采用云原生架构方案,平均部署周期由之前的1天缩短至 0.5天,大幅提升了研发迭代效率,从而加速商业化应用的进程,为金融业务提供新的增长动力。
关于 Serverless Kubernetes(ASK) Kubernetes(K8s)作为一个开源容器编排系统,被广泛运用于云原生应用的开发与管理。其优势在于降低运维成本,提高运维效率,形成了以 K8s 为核心的云原生生态。然而使用 K8s 常常需要用户面对的问题较多,例如资源规划、容量规划、Node 与 Pod 的亲和关系、容器网络规划、节点生命周期管理、操作系统版本、容器运行时版本兼容性等,这些问题显然不是用户所希望关心的,用户期望做的事情是专注在自身的业务逻辑,尽可能不关心这些基础设施。Serverless 的核心理念在于让开发者更聚焦业务逻辑,减少对基础设施的关注。因此我们将 K8s 复杂性下沉,提供 Serverless Kubernetes 的产品能力。
那么 Serverless Kubernetes 有哪些优势呢?主要包括以下三个方面:免运维、自动弹性、按需付费。
首先,Serverless Kubernetes 组件全托管免运维,支持自动升级 k8s 版本。其次,该产品具有极致弹性能力。可以根据业务需求,自动弹性、秒级扩容,从而在满足业务增长时自动容量规划。最后,使用 Serverless Kubernetes 的用户,只需根据实际使用量按需计费。除此之外,ASK 还提供了新增的 U 实例规格支持,统一支持多款处理器,相比上一代主售实例降价高达 40%。
为了让更多用户体验最佳实践,我们特地将其打造成了一个体验场景,配合热门开源的 AI 项目 Stable Diffusion,用户可以通过真实的云上环境,轻松体验容器化部署具备企业级弹性能力的 AI 模型。
在 ASK 中部署 Stable Diffusion 随着生成型 AI 技术的能力提升,越来越多的注意力放在了通过 AI 模型提升研发效率上。作为 AIGC(AI Generated Content)领域的知名项目 Stable Diffusion,可以帮助用户快速、准确地生成想要的场景及图片。不过当前直接在 K8s 使用 Stable Diffusion 面临如下问题:
我25岁,中级测试,外包,薪资13.5k,人在上海。内卷什么的就不说了,而且人在外包那些高级精英年薪大几十的咱也接触不到,就说说外包吧。
假设以我为界限,25岁一线城市13.5k,那22-24大部分情况下是不会超过13的。而我旁敲侧击了30岁以上未做到管理层的老大哥们,他们估计到手15-16k。
我有过认真学习的时候,可是人生曲线配合这个职业,我自己是觉得,我到头了。我不能被限制在这样的一个圈里!
在外包磨平了棱角 我二十出头的时候,朋友说我月入过万,一顿吹,我也觉得我好像挺厉害的。几年后,我麻了,外包是不被当人看待的,我不是什么人中龙凤,也许五年后十年后,老大哥们的现在就是我的未来,我慌了。年轻的时候疯狂加班,我现在感觉自己很虚,现在已经是咬牙加班了,而老大哥们已经有头发发灰发白迹象了。
对了,劳累使人变丑头秃是真的,我的好搭档已经由乌黑浓密变得稀疏了,他才26!我那次离职是得了失眠症,又是吃药又是针灸推拿,花了一万多养了一个月才恢复一点。
而且,由于人经常对着电脑,直线思维,铁直男很难找到女朋友的,如果头秃,就更难了,这家公司最近貌似要我去接手一个维护的班。
(听说)老哥在我这年纪做了维护,然后恍惚之间已然30岁,然后毅然辞职回家,要找女朋友,要结婚。。。老实说我觉得很晚了,大城市不在乎你几岁,但小城市在乎,但愿他能成功。
外包前途渺茫 人生很长,没有什么工作能从一而终,测试我始终认为下限高,刚入行就能很快破万,但是上线也是真的低。我不能接受,我30岁以后在上海996的怼,而工资还不到两万(即使能突破,又能高几分?)
人生自有得失,我在这个年纪,虽然怼着996,可确实工资还不错,但是随着年龄增长,工资却不怎么动的时候,就该走了。
我也需要一段大量的时间,去恋爱,去结婚。而不是在方寸之间与电脑共度青春。什么?你说好好干升职加薪?醒醒吧,外包哪有前途,你只是块干电池而已,随时都会被换的。
最后祝大家都能找到心仪的工作,快乐工作,幸福生活,广阔天地,大有作为。
整理了一波之前发布的软件测试资源【点击文末小卡片免费领取】,无套路领取!
全网首发-涵盖16个技术栈 第一部分:测试理论(测试基础+需求分析+测试模型+测试计划+测试策略+测试案例等等)
第二部分:Linux( Linux基础+Linux练习题)
第三部分:MySQL(基础知识+查询练习+万年学生表经典面试题汇总+数据库企业真题)
第四部分:Web测试
第五部分:API测试
第六部分:App测试
第七部分:管理工具
第八部分:Python基础(Python基础+编程题+集合+函数+Python特性等等)
第九部分:Selenium相关
第十部分:性能测试
第十一部分:LordRunner相关
第十二部分:计算机网络
第十三部分:组成原理
第十四部分:数据结构与算法
第十五部分:逻辑题
第十六部分:人力资源
由于整个笔记比较全面,内容相当的多 ,这里仅展示资料的一部分,【点击文末小卡片免费领取】
一、 测试基本功 测试入门(基础概念与常识)
需求分析
测试模型
测试计划
计算机网络
......
二、 linux grep和find的区别? grep 都有哪些用法?
查看IP地址?
创建和删除一个多级目录?
在当前用户家目录中查找haha.txt文件?
如何查询出tomcat的进程并杀掉这个进程,写出linux命令?
......
三、MySQL 你用的Mysql是哪个引擎,各引擎之间有什么区别?
如何对查询命令进行优化?
数据库的优化?
Sql注入是如何产“生的,如何防止?
NoSQL和关系数据库的区别?
MySQL与MongoDB本质之间最基本的差别是什么?
.....
四、Python编程 统计python源代码文件中代码行数,去除注释,空行,进行输出?
python调用cmd并返回结果?
1,2,3,4 这4个数字,能组成多少个互不相同的且无重复的三位数,都是多少?
请用 python 打印出 10000 以内的对称数(对称数特点:数字左右对称,如:1,2,11,121,1221 等)
前言:
💞💞今天我们开始学习Spring,这里我们会了解什么是Spring,知道什么是框架,为什么要学Spring框架,框架有什么作用等等。
💟💟前路漫漫,希望大家坚持下去,不忘初心,成为一名优秀的程序员
个人主页⭐: 书生♡
gitee主页🙋♂:奋斗的小白
博客领域💥:java编程 ,前端,算法,强训题目
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬
目录 1.什么是Spring框架2. 为什么要学习框架3.框架的优点展示(SpringBoot VS Servlet)4.SpringBoot 项⽬开发4.1 创建并添加引⽤4.2 编写代码 5.SpringBoot VS Servlet 1.什么是Spring框架 Spring 框架是一个轻量级的 Java 开发框架,为应用开发提供平台。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一是分层架构,分层架构允许使用者选择使用哪一个组件。
Spring 使用基本的 JavaBean 来完成以前只能只可能由 EJB 完成。
Spring 提供 IOC 容器,可以将对象直接的依赖关系交由 Spring 进行控制,避免通过硬编码造成程序过度耦合。
Spring 提供 AOP 功能,方便进行面向切面的编程,传统 OOP 实现的功能可以通过 AOP 实现。
2. 为什么要学习框架 学习框架相当于从“小公司”到“大公司”的升级,小公司什么都要⾃⼰做自给自足,大公司是拿别人的或者是以前准备好的直接使用组装就行,特点就是⾼效。框架更加易⽤、简单且⾼效。 3.框架的优点展示(SpringBoot VS Servlet) Servlet 时代
1.创建一个Maven项目
2.添加Servlet引用(Maven搜索相应jar包,选择合适版本)人
3.配置 web.xml 文件 ;写代码
4.运行时需要进行准备工作
1.安装smart tomcat插件
2.下载一个tomcat在本地
5.部署
1)linux下载并运行一个外置的 tomcat
2)将jar放在tomcat/webapps 下
肝了一个月的pandas进阶小册子出炉了👉「pandas进阶宝典」
日常用Python做数据分析最常用到的就是查询筛选了,按各种条件、各种维度以及组合挑出我们想要的数据,以方便我们分析挖掘。
东哥总结了日常查询和筛选常用的种骚操作,供各位学习参考。本文采用sklearn的boston数据举例介绍。
from sklearn import datasets import pandas as pd boston = datasets.load_boston() df = pd.DataFrame(boston.data, columns=boston.feature_names) 1. [] 第一种是最快捷方便的,直接在dataframe的[]中写筛选的条件或者组合条件。比如下面,想要筛选出大于NOX这变量平均值的所有数据,然后按NOX降序排序。
df[df['NOX']>df['NOX'].mean()].sort_values(by='NOX',ascending=False).head() 当然,也可以使用组合条件,条件之间使用逻辑符号& |等。比如下面这个例子除了上面条件外再加上且条件CHAS为1,注意逻辑符号分开的条件要用()隔开。
df[(df['NOX']>df['NOX'].mean())& (df['CHAS'] ==1)].sort_values(by='NOX',ascending=False).head() 2. loc/iloc 除[]之外,loc/iloc应该是最常用的两种查询方法了。loc按标签值(列名和行索引取值)访问,iloc按数字索引访问,均支持单值访问或切片查询。除了可以像[]按条件筛选数据以外,loc还可以指定返回的列变量,从行和列两个维度筛选。
比如下面这个例子,按条件筛选出数据,并筛选出指定变量,然后赋值。
df.loc[(df['NOX']>df['NOX'].mean()),['CHAS']] = 2 3. isin 上面我们筛选条件< > == !=都是个范围,但很多时候是需要锁定某些具体的值的,这时候就需要isin了。比如我们要限定NOX取值只能为0.538,0.713,0.437中时。
df.loc[df['NOX'].isin([0.538,0.713,0.437]),:].sample(5) 当然,也可以做取反操作,在筛选条件前加~符号即可。
df.loc[~df['NOX'].isin([0.538,0.713,0.437]),:].sample(5) 4. str.contains 上面的举例都是数值大小比较的筛选条件,除数值以外当然也有字符串的查询需求。pandas里实现字符串的模糊筛选,可以用.str.contains()来实现,有点像在SQL语句里用的是like。
下面利用titanic的数据举例,筛选出人名中包含Mrs或者Lily的数据,|或逻辑符号在引号内。
train.loc[train['Name'].str.contains('Mrs|Lily'),:].head() .str.contains()中还可以设置正则化筛选逻辑。
case=True:使用case指定区分大小写
na=True:就表示把有NAN的转换为布尔值True
flags=re.IGNORECASE:标志传递到re模块,例如re.IGNORECASE
regex=True:regex :如果为True,则假定第一个字符串是正则表达式,否则还是字符串
5. where/mask 在SQL里,我们知道where的功能是要把满足条件的筛选出来。pandas中where也是筛选,但用法稍有不同。
where接受的条件需要是布尔类型的,如果不满足匹配条件,就被赋值为默认的NaN或其他指定值。举例如下,将Sex为male当作筛选条件,cond就是一列布尔型的Series,非male的值就都被赋值为默认的NaN空值了。
cond = train['Sex'] == 'male' train['Sex'].where(cond, inplace=True) train.head() 也可以用other赋给指定值。
cond = train['Sex'] == 'male' train['Sex'].
在我之前的文章里,我已经解释了如何创建拥有多个子窗口的指标,在使用自定义指标时如此这般会变得很有趣。 这很容易做到。 但当我们尝试在智能交易系统中实现相同的功能时,事情会越加变得复杂,因为在自定义指标中我们没有可用的工具。 在这一点上,编程变得至关重要:能够编写正确的代码来创建子窗口至关重要。 尽管这项任务并非那么容易,但知道如何在 EA 中设置子窗口并不需要很多编码,只需通晓 MQL5 的工作原理。
计划 我们已经有了自定义指标,也就是说,我们的对象类已经功能齐备,而且由于这是一个对象类,我们可以轻松地将其转换到其它模型。 然而,在我们的 EA 中简单地声明并尝试使用这个类,并不能让事情如同我们在自定义指标中一样工作,原因是我们的 EA 中未提供子窗口功能。 但又冒出了这样一个想法:“如果我们用一个已经编译过,且可工作的自定义指标,然后用 iCustom 命令从 EA 调用它,会怎么样? 好吧,这也许是可行的,因为这样不需要子窗口,命令如下所示:
#property copyright "Daniel Jose" //+------------------------------------------------------------------+ input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follow //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... Expert Advisor code ... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!
1. ‘&’和‘|’ import pandas as pd score={'student':['LiLei','HanMeiMei','David','Mary','oldwang'],'chinese':[90,65,72,38,42],'math':[68,32,75,60,92], 'english':[63,75,82,74,91],'physics':[93,32,71,24,85]} data=pd.DataFrame(score) print(data) out: student chinese math english physics 0 LiLei 90 68 63 93 1 HanMeiMei 65 32 75 32 2 David 72 75 82 71 3 Mary 38 60 74 24 4 oldwang 42 92 91 85 #筛选数学大于60分且物理大于80分 data1=data.loc[(data.math>60)&(data.physics>80)] print(data1) out: student chinese math english physics 0 LiLei 90 68 63 93 4 oldwang 42 92 91 85 #筛选语文大于80分或者物理低于60分 data2=data.loc[(data.chinese>80)|(data.physics<60)] print(data2) out: student chinese math english physics 0 LiLei 90 68 63 93 1 HanMeiMei 65 32 75 32 3 Mary 38 60 74 24 #筛选数学高于平均分,并且按照分数从高到低排列 data3=data[data['math']>data['math'].
一、类成员的可访问范围 在类的定义中,用下列访问范围关键字来说明类成员可被访问的范围:
private:私有成员,只能在成员函数内访问public:公有成员,可以在任何地方访问protected:保护成员,以后再说 以上三种关键字出现的次数和先后次序都没有限制。
定义一个类:
class className { private: 私有属性和函数 public: 公有属性和函数 protected: 保护属性和函数 }; 如果某个成员前面没有上述关键字,则缺省地被认为是私有成员。
class Man { int nAge; //私有成员 char szName[20]; // 私有成员 public: void SetName(char* szName) { strcpy(Man::szName, szName); } }; 在类的成员函数内部,能够访问:
当前对象的全部属性、函数;同类其它对象的全部属性、函数。 在类的成员函数以外的地方,只能够访问该类对象的公有成员。
class CEmployee { private: char szName[30]; //名字 public: int salary; //工资 void setName(char* name); void getName(char* name); void averageSalary(CEmployee e1, CEmployee e2); }; void CEmployee::setName(char* name) { strcpy(szName, name); //ok } void CEmployee::getName(char* name) { strcpy(name, szName); //ok } void CEmployee::averageSalary(CEmployee e1, CEmployee e2) { cout << e1.
# -*- coding: utf-8 -*-
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.datastream.functions import MapFunction, RuntimeContext, KeyedProcessFunction
from abc import ABC, abstractmethod
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.datastream.functions import MapFunction, RuntimeContext, KeyedProcessFunction
from pyflink.datastream.state import MapStateDescriptor
from pyflink.datastream.connectors.kafka import FlinkKafkaConsumer
from pyflink.common.typeinfo import Types, TypeInformation
from pyflink.datastream.connectors.elasticsearch import Elasticsearch7SinkBuilder, ElasticsearchEmitter, FlushBackoffType
from pyflink.datastream.connectors import DeliveryGuarantee
from pyflink.common.serialization import SimpleStringSchema
import json
import re
from datetime import datetime
from elasticsearch import Elasticsearch
题目描述 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:
或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:
示例1:
输 入:{1,3,5},{2,4,6} 返回值:{1,2,3,4,5,6} 示例2:
输 入:{},{} 返回值:{} 示例3:
输 入:{-1,2,4},{1,3,4} 返回值:{-1,1,2,3,4,4} 代码 class Solution { public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {//定义两个头节点指针 if (pHead1 == NULL) { return pHead2; } else if (pHead2 == NULL) { return pHead1; } ListNode* MergeHead = NULL;//初始化合并头节点 if (pHead1->val < pHead2->val) {//pHead1->val = 1 < pHead2->val=2,合并头节点的值为1,继续寻找下一个节点。 MergeHead = pHead1; pHead1 = pHead1->next; } else { MergeHead = pHead2; pHead2 = pHead2->next; } ListNode* tmpNode = MergeHead; while (pHead1 && pHead2) { if (pHead1->val < pHead2->val) {//当两个链表的值都存在时,pHead1的值小于pHead2的值,就将值小的赋给合并节点的下一个节点,继续遍历链表 MergeHead->next = pHead1; pHead1 = pHead1->next; } else { MergeHead->next = pHead2; pHead2 = pHead2->next; } MergeHead = MergeHead->next; } //如果链表中的值仅有一个,则直接赋值,为空也直接赋值 if (pHead1) { MergeHead->next = pHead1; } if (pHead2) { MergeHead->next = pHead2; } return tmpNode; }; };
描述 给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
示例1
输 入:{1,2,3} 返回值:{3,2,1} 示例2
输 入:{} 返回值:{} 说明:空链表则输出空 题解 对于单链表1 -> 2 -> 3 - > 4,反转过程为:
1 <- 2 -> 3-> 4 -> NULL =>>NULL <- 1 <- 2 <- 3 -> 4 =>>NULL <- 1 <- 2 <- 3 <- 4
主要是pHead和pHead->next的交换。
代码 class Solution { public: ListNode* ReverseList(ListNode* pHead) { if(!pHead||!pHead->next)//判断头节点和头节点的下一个节点是否为空 { return pHead; } ListNode*tail= ReverseList(pHead->next);//定义尾节点为头节点下一个节点的反转 pHead->next->next = pHead; pHead->next = NULL; return tail; } };
目录
一、REDIS 持久化
RDB 持久化配置:
AOF 持久化:
二、REDIS 数据恢复
三、REDIS 示例数据
四、REDIS 导入数据
一、REDIS 持久化 概述: Redis 提供了两种方式进行持久化,RDB 和 AOF。 RDB:将 Redis 在内存中的数据定期 dump 到硬盘上的一个快照文件,用于进行备份和恢复。其优点是安全,可靠且 性能高,缺点是在最近一次 RDB 文件被 dump 之后的数据丢失风险较高。 AOF:将所有的对 Redis 的写入操作都记录在一个追加类型的文件中,用于恢复数据。其优点是数据丢失的风险较 低,缺点是相对于 RDB 文件而言,文件体积更大,恢复速度更慢。 可以通过配置文件中的以下参数来控制持久化方式: - save:设定在 N 秒内,如果有 M 个 key 被修改,则自动执行一次 RDB 操作;
- appendfsync:设定数据同步时的方式,如 always 表示每次操作都同步,everysec 表示每秒同步一次,no 表示不同 步。 需要注意的是,在同时开启 RDB 和 AOF 持久化方式时,恢复数据时 AOF 的优先级高于 RDB。 要在 Redis 中配置 RDB 持久化,需要在 redis.conf 配置文件中进行设置。 RDB 持久化配置: # 在多长时间后,如果有多少个键发生更改,Redis 执行写操作 save 900 1 save 300 10 save 60 10000 # 持久化文件的名称和位置 dbfilename dump.
目录
一、个人负责模块
二、功能框架图
三、个人任务简述
1、重写paint方法,定义一个Graphics2D,来消除棋子锯齿,使棋子更加圆润。
2、双人对战功能判断输赢以及人机对战功能
1.双人对战判断输赢 2、人机对战
四、课程设计感想
一、个人负责模块 界面设置中paint方法,功能中的双人对战功能和人机对战功能,以及判断游戏输赢的算法。
二、功能框架图 三、个人任务简述 1、重写paint方法,定义一个Graphics2D,来消除棋子锯齿,使棋子更加圆润。 public void paint(Graphics g) { //定义一个Graphics2D消除棋子锯齿,使棋子更加圆润 Graphics2D gg = (Graphics2D) g; gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); //棋盘 initPaint(g, gg); //棋子 ovalPaint(gg); //提示框 sidePaint(gg); } 其中,Graphics g 参数表示画笔对象,通过它可以对画布进行绘制操作。
在方法中,首先使用 Graphics2D 对象将画笔转换为 2D 画笔(因为它具有更丰富的绘图功能),然后使用以下两个渲染提示设置来消除棋子锯齿:
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON):开启抗锯齿效果,使棋子边缘更加平滑;gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE):对线条进行归一化,以消除由浮点数的不精确表示而导致的锯齿和其他视觉伪影。 2、双人对战功能判断输赢以及人机对战功能 1.双人对战判断输赢 当双人对战模式时,我的任务主要是通过算法来判断输赢。
private void judge(int type, int x, int y) { //传入参数,来判断是黑(2)或白(1)子 int sum=0; //判断四个方向 //1)左 右 { int k = x - 1; while (k >= 0) { if (table[k][y] == type) {//二维数字记录棋盘上每个位置上的棋子 (0无棋子 1白子 2黑子) sum++; } else { break; } k--; } } for (int k = x + 1; k < NUM; k++) { if (table[k][y] == type) { sum++; } else { break; } } if (sum >= 4) { isWin = true; return; } //2)上 下 sum = 0; for (int k = y - 1; k >= 0; k--) { if (table[x][k] == type) { sum++; } else { break; } } for (int k = y + 1; k < NUM; k++) { if (table[x][k] == type) { sum++; } else { break; } } if (sum >= 4) { isWin = true; return; } //3)左上 右下 sum = 0; for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) { if (table[i][j] == type) { sum++; } else { break; } } for (int i = x + 1, j = y + 1; i < NUM && j < NUM; i++, j++) { if (table[i][j] == type) sum++; else { break; } } if (sum >= 4) { isWin = true; return; } //4)右上 左下 sum = 0; for (int i = x - 1, j = y + 1; i >= 0 && j < NUM; i--, j++) { if (table[i][j] == type) { sum++; } else { break; } } for (int i = x + 1, j = y - 1; i < NUM && j >= 0; i++, j--) { if (table[i][j] == type) sum++; else { break; } } if (sum >= 4) { isWin = true; //return; } } 这段代码是五子棋游戏中的胜利判断。传入参数 type 表示要判断的是黑子(2)还是白子(1), x 和 y 表示当前落子位置的横纵坐标。通过对当前角色棋子在四个方向上是否连续出现 5 颗棋子,来判断这个角色是否胜利。其中,具体实现的方式是通过遍历分别对应四个方向的二维棋盘数组 table,从当前位置开始往左、右、上、下、斜线方向查找同色的棋子数量。如果某方向上达到了 5 颗或以上同色棋子,则判断该角色已经胜利并将标记变量 isWin 设为 true。
json介绍 Json是一种轻量级的数据交换格式(也叫数据序列化方式)。Json采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
json的优点 语法直观;所有代码由一个json.hpp头文件组成,不存在子项目、依赖关系、复杂的构建系统,使用起来方便;使用C++11标准编写;类似STL容器,可以直接调用,可以和STL容器之间相互转换; 常用的数据传输序列化 XML: 数据具有层次结构,可以被大多数编程语言使用,使用XML获取XML文档,接数据解析出来复制给变量。JSON:json更加简短,读写速度快,占用带宽小,可以使用数组,解析起来比XML更容易,与XML相比,最大的不同是XML 需要使用 XML 解析器来解析,JSON 可以使用标准的 JavaScript 函数来解析。ProtoBuf:通常使用在公司级别的项目中,大量使用ProtoBuf作为数据序列化的方式,占用带宽比以上两种方式小,但是使用起来比JSON复杂,所以通常在项目中选择使用json格式来打包传输数据。 调用JSON头文件 #include "json.hpp" using json = nlohmann::json; JSON数据序列化 把想要打包的数据或对象直接处理成JSON字符串。可以分为两种:
普通数据序列化 json js; // 添加数组 js["id"] = {1,2,3,4,5}; // 添加key-value js["name"] = "zhang san"; // 添加对象 js["msg"]["zhang san"] = "hello world"; js["msg"]["liu shuo"] = "hello china"; // 上面等同于下面这句一次性添加数组对象 js["msg"] = {{"zhang san", "hello world"}, {"liu shuo", "hello china"}}; cout << js << endl; 容器序列化 json js; // 直接序列化一个vector容器 vector<int> vec; vec.