一:创建mock/spy对象 0:概述 Mockito可以帮助我们方便的创建被测对象、mock对象和spy对象。
创建被测对象: 先解释一下被测对象:就是单元测试中我们想要测试的那个类。如xxxService、xxxUtils等等。使用@InjectMocks注解创建: 配合@RunWith(MockitoJUnitRunner.class)使用或在@Before方法中使用MockitoAnnotations.openMocks(this)来激活Mockito 注解的相关功能。如果同时也使用了@Mock注解或者@Spy注解。Mockito可以方便的将这两个注解生成的对象注入到@InjectMocks注解的对象的成员变量中。直接创建: 当然我们可以直接new一个被测对象,但是我们不能方便的使用Mockito为我们提供的自动注入成员变量的功能了。当然我们可以手动的现在这些注入的工作。创建mock对象: mock对象:一般是被测对象依赖的对象(比如被测对象的成员变量)。使用@Mock注解: 配合@RunWith(MockitoJUnitRunner.class)使用或在@Before方法中使用MockitoAnnotations.openMocks(this)来激活Mockito 注解的相关功能。被@Mock注解的对象会被自动注入到@InjectMocks注解生成的被测对象中。使用Mockito.mock(); 生成的mock对象需要手动配置到被测对象中,不推荐。注意: mock对象中的方法被调用时默认会返回对应类型对象的空值。方法实际的代码不会被执行。当前如果我们想要执行实际的代码也是可以的: 我么可以先对此方法进行存根操作,此时使用doCallRealMethod()或者thenCallRealMethod()方法即可。下文会具体描述如何操作。也可以通过指定返回值策略(Mockito.CALLS_REAL_METHODS)的方式实现。即创建mock对象时指定返回值策略为Mockito.CALLS_REAL_METHODS。mock对象中的方法被调用时默认会返回对应类型对象的空值。许多情况下当我们不对某个方进行存根时那么返回的值就是null,测试过程中就会产生NPE。但是我们可以在创建mock对象时指定返回值生成策略(Answer策略)。下文会具体描述如何操作。创建spy对象: spy对象:部分mock的对象。一般是被测对象依赖的对象(比如被测对象的成员变量)。使用@Spy注解: 配合@RunWith(MockitoJUnitRunner.class)使用或在@Before方法中使用MockitoAnnotations.openMocks(this)来激活Mockito 注解的相关功能。被@Spy注解的对象会被自动注入到@InjectMocks注解生成的被测对象中。使用Mockito.spy(); 生成的spy对象需要手动配置到被测对象中,不推荐。注意: spy对象中的方法被调用时默认情况下方法实际的代码会被执行。当前如果我们想要不执行实际的代码也是可以的: 我么可以先对此方法进行存根操作,此时使用doXXXX()方法即可(注意不要使用或者thenXXXX()方法,会给我们带来麻烦:实际的代码会在此时被调用一次)。下文会具体描述如何操作。 1:创建mock对象 使用Mockito.mock()方法。
//org.mockito.Mockito.mock(java.lang.Class<T>) //org.mockito.Mockito.mock(java.lang.Class<T>, java.lang.String) //org.mockito.Mockito.mock(java.lang.Class<T>, org.mockito.stubbing.Answer) //org.mockito.Mockito.mock(java.lang.Class<T>, org.mockito.MockSettings) //方式1 Foo foo1 = Mockito.mock(Foo.class); //方式2:给mock指定名称 Foo foo2 = Mockito.mock(Foo.class, "mock_1"); //方式3:给mock指定自定义返回逻辑 Foo foo3 = Mockito.mock(Foo.class, new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { //自定义返回逻辑 return null; } }); //方式4:使用MockSettings配置当前mock Foo foo4 = Mockito.mock(Foo.class, Mockito.withSettings().defaultAnswer(Mockito.RETURNS_SMART_NULLS)); 复制代码 使用@InjectMocks和@Mock注解。
前言: 最近完成了一个多功能时钟的编写,其中涉及到了一些形如exe文件如何读写外部配置文件,jre体积太大的小问题。虽然后面都一一解决了,不过我觉得有必要写上来,为可能遇到类似问题的程序猿们提供一些思路(* ̄︶ ̄):
问题1:jar/exe文件读写外部配置文件 听起来不是很难,但我之前只学会了如何在项目中读取配置文件,比如像这样—— File file3 = new File(Test.class.getResource("file3.txt").getFile());
RandomAccessFile file4=new RandomAccessFile(new File(Test.class.getResource("file4.txt").toURI,"rw"));//示范
他人的博客里有这么一句话:至于getResouce()方法的参数,你以class为出发点,再结合相对路径的概念,就可以准确地定位资源文件了,这句话准确的概括出了getResource()的用法,所以我不多说,感兴趣的可以看看:java中Class.getResource用法(用于配置文件的读取) - 路修远而求索 - 博客园
到后面开始着手于这个小程序后,我才发现在eclipse中的项目中读取配置文件和在实际生产环境中读写配置文件完全是两回事,因为在你将项目打包成jar后,里面的文件夹层次完全乱套了——
原来的src文件夹直接变没了,bin文件夹也只剩下其子文件夹,而且配置文件要求具有一定的灵活性,直接打包在jar里面未免不太妥当。所以按照以前的getResource()方法,明显是行不通的,所以我找到了可行的方法,也就是通过寻找jar/exe文件,进而找到同一个文件夹内的配置文件。
String path = System.getProperty("user.dir") + "\\XXX.properties"
其中,System.getProperty("user.dir")会寻找调用它的程序的当前路径,再与配置文件名拼接,这样就使得无论jar包移动到哪个位置,都可以使用与jar包在同一个目录下的XXX.properties配置文件。同时也保证了配置文件的灵活性,没有把配置文件包死在jar包中。
附如何修改配置文件:java 更新properties配置文件 - gavinwangxj - 博客园
问题2:jar打包成exe遇到的问题 本人的小程序中,有一个爬取百度新闻的功能,在使用exe4j打包生成exe文件后运行时,error.log中出现了个很不可思议的异常/error——java.lang.NoClassDefFoundError
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/apache/hc/core5/http/ClassicHttpRequest at Quicky_Clock.MainFrame.initialize(MainFrame.java:126) at Quicky_Clock.MainFrame.<init>(MainFrame.java:31) at Quicky_Clock.MainFrame$1.run(MainFrame.java:23) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.
echarts 数据区域缩放 官方文档:Documentation - Apache ECharts
********************* 配置属性
****************
内置型组件(鼠标拖拽、鼠标滚轮、触屏手指滑动实现区域缩放)
基本属性
dataZoom.type:缩放组件类型,inside(内置组件)、slider(滑动条) dataZoom.id:组件id,默认不指定 dataZoom.disabled:是否停止组件功能,默认false dataZoom.start:数据窗口范围的起始百分比,范围是:0 ~ 100,表示0% ~ 100% dataZoom.end:数据窗口范围的结束百分比,范围是:0 ~ 100 dataZoom.startValue:数据窗口范围的起始数值,如果设置start,startValue失效 dataZoom.endValue:数据窗口范围的结束数值,如果设置end,endValue失效 dataZoom.minSpan:窗口最小值(百分比),范围是 0 ~ 100,如果设置了minValueSpan,minSpan失效 dataZoom.maxSpan:窗口最大值(百分比),范围是 0 ~ 100 dataZoom.minValueSpan:窗口最小值(实际数值) dataZoom.maxValueSpan:窗口最大值(实际数值) dataZoom.orient:布局方式,可选值:horizontal、vertical dataZoom.zoomLock:是否锁定窗口大小,若为true,则只能平移,不能缩放,默认false dataZoom.throttle:视图刷新的频率,单位为毫秒(ms),默认100ms dataZoom.rangeMode:范围模式,可选值value、percent,默认自动设置 如果指定了start、end,rangeMode设为percent 如果指定了startValue、endValue,rangeMode设为value dataZoom.preventDefaultMouseMove:是否阻止mousemove事件的默认行为,默认true 组件控制的坐标轴
dataZoom.xAxisIndex:组件缩放的x轴index,可为多个 dataZoom.yAxisIndex:组件缩放的y轴index,可为多个 dataZoom.radiusAxisIndex:缩放组件控制的radius轴,可为多个 dataZoom.angleAxisIndex:缩放组件控制的angle轴,可为多个 # 示例 option: { xAxis: [ {...}, // 第一个xAxis {...}, // 第二个xAxis {...}, // 第三个xAxis {...} // 第四个xAxis ], dataZoom: [ { // 第一个dataZoom组件 xAxisIndex: [0, 2] //dataZoom组件控制第一个和第三个xAxis }, { // 第二个dataZoom组件 xAxisIndex: 3 //dataZoom组件控制第四个xAxis } ] } 过滤模式
方法一:
import numpy as np data_file = 'iris.txt'#你的数据集.txt文件 def get_dataset(data_file): with open(data_file,'r') as in_file: txt = in_file.readlines()#将数据集以字符串列表的形式放在txt里面['1.2 3 4\n','1 2 #3\n'] txt = [txt[i].split(' ') for x in range(len(txt))]#将字符串txt[i](['1.2 3 4\n','1 #2 3\n'])转化为[['1.2','2','3','\n'],['1','2','3','\n']] txt = [txt[i].strip('[\n,\t]') for i in range(len(txt))]#去掉字符串不能转换为float的 #特殊字符--->[['1.2','2','3'],['1','2','3']] for i in range(len(txt)): #数据集长度(样本个数) for j in range(len(txt[0])):#样本特征数(因为每一个样本一般取同样数目特征数,所以可以用 #txt[0]代替任意长度) txt[i][j] = float(txt[i][j]) return txt 方法二:
#法二:用map的方法转 def get_dataset(data_file): with open(data_file,'r') as in_file: txt = in_file.readlines()#read()返回字符串 readline()读一行,返回字符串 readlines() # 全部读,返回字符串列表,含有\n for i in range(len(txt)): txt[i] = list(map(float, filter(None,re.
1-1.全部删除的三部分,index.js
// 全部删除 $(".delAll").click(function () { $.get("/delAll", function (res) { if (res.code == 200) { $(".showDiv").html(""); console.log("全部删除成功"); } else { alert(res.msg); } }) }) 1-2全部删除的接口
app.get("/delAll", handleData.getDelAll); 1-3全部删除的handleData.js
module.exports.getDelAll = function (req, res) { db.drop(res, "case1110", function (err, result, db1) { if (err) { res.send({ code: 404, msg: "全部删除失败" }); } else { res.send({ code: 200, msg: "全部删除成功" }); db1.close(); } }) } 2-1修改---index.js
渲染中的button按钮 function uptFn (id) { $.
文章目录 1、low2、medium3、high4、impossible5、使用sqlmap进行盲注 1、low 源码解析:
<?php if( isset( $_GET[ 'Submit' ] ) ) { // Get input $id = $_GET[ 'id' ]; // Check database $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors // Get results $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors if( $num > 0 ) { // Feedback for end user echo '<pre>User ID exists in the database.
文章目录 1、low2、medium3、high4、impossible 1、low 源码解析:
<?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["
STM32主频 F1主频只有72M,F4芯片主频最高可以达到168M。
F4定时器频率 因为系统初始化SystemInit函数里初始化APB1总线时钟为4分频即42M,APB2总线时钟为2分频即84M,所以TIM1、TIM8~TIM11的时钟为APB2时钟的两倍即168M,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍即84M。
步进电机参数 电机参数如下:步距角 = 1.8° 细分=16 螺距= 1mm(电机转一圈,对应的距离是1mm)
一圈360°需要的脉冲数 = 360/1.8*16 = 3200 pulse 又因为电机转一圈,对应的距离是1mm, 所以 电机带动轮子走1mm = 3200pulse
#define MM_TO_PLUSE 3200//1mm对应的脉冲数 #define PLUSE_TO_MM (1/3200)//一个脉冲对应的距离 #define DIS_MM_TO_PLUSE(dis) ( MM_TO_PLUSE * (dis) ) //将以mm为单位的长度抓换成对应的脉冲数 #define SPEED_TO_PLUSE(speed) ( (speed) *MM_TO_PLUSE ) //将mm/s的速度转换成HZ 到此为止,电机之间脉冲和距离之间的关系已经搞明白了,那我们开始言归正传,如何计算出我们需要的定时器频率输出了?
假设我们系统需要达到30mm/s的速度而且我们用的是timer2,30mm/s即1s内路程30mm,30mm需要30*3200=96000个脉冲,即1s内需要96000个脉冲(即频率96KHz),调用宏计算 30mm/s * 3200 = 96000Hz的频率 = 96KHz。意思就是说们只要定时器输出的PWM能够满足96KHz的频率就可以了。
将上面的公式换算成 输出频率 = 定时器的时钟频率(注意是时钟频率不是输出频率)/(分频系数 + 1)/( 计数值+1)
将psc = (84-1) ,内部自动加1 ,带入上面的公式就可以计算出计数值 = 1000。就可以输出对应的速度了。
#define TIMER_CLK (84000000/84) //84Mhz 84分频 #define CALC_ARR(speed) (TIMER_CLK /(speed)*MM_TO_PLUSE ) 知道速度值就可以调用CALC_ARR宏返回对应的ARR寄存器值啦,我们就可以根据机器的系统参数来控制了。
文章目录 准备工作1、low2、medium3、high4、impossible 准备工作 需要下载 蚁剑 进行测试
点击跳转下载所需工具
1、low 源码解析:
<?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // Can we move the file to the upload folder? if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // No echo '<pre>Your image was not uploaded.
这是今天要完成的动画:
先创建好所需要的控件:
import UIKit class ViewController: UIViewController { let screenWidth = UIScreen.main.bounds.size.width let screenHeight = UIScreen.main.bounds.size.height let backgroundImage = UIImageView() let VSLabel = UILabel() let status = UILabel() let searchButton = UIButton() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.addSubview(backgroundImage) view.addSubview(VSLabel) view.addSubview(status) view.addSubview(searchButton) backgroundImage.image = UIImage(named: "bg-boxingring") backgroundImage.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) searchButton.frame = CGRect(x: 30, y: screenHeight - 120, width: screenWidth - 60, height: 60) searchButton.
文章目录 1、low2、medium3、high4、impossible 1、low 源码解析:
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = $_REQUEST[ 'ip' ]; // Determine OS and execute the ping command.确定操作系统并执行ping命令 if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "
文章目录 1、安装PHPstudy2、将DVWA解压文件放入PHPstudy软件目录下3、打开网页4、修改DVWA安全等级5、查看源码位置注意事项 1、安装PHPstudy 点击跳转下载PHPstudy
打开网页,下载Windows版本的PHPstudy软件,并进行安装,安装过程较简单,不做赘述;
2、将DVWA解压文件放入PHPstudy软件目录下 点击跳转下载DVWA安装包
下载文件为具体安装包,解压即可获取到DVWA目录
解压后将其放入PHPstudy目录下,具体路径为:D:\phpstudy_pro\WWW(此处安装盘为D盘,若为C盘替换即可),修改名称为DVWA;
打开DVWA目录下文件,并修改配置文件;
复制config.inc.php.dist文件生成config.inc.php(需要修改文件后缀为php)
打开config.inc.php,修改数据库账户密码并保存;
3、打开网页 打开浏览器,输入:http://127.0.0.1/dvwa/或者http://localhost/dvwa/创建数据库
点击[创建/重置数据库];
通过[login]登录页面,可以通过修改本地hosts文件定义域名解析;默认登录密码为admin/password
4、修改DVWA安全等级 登录成功后,打开[DVWA Security],修改安全等级,安全等级分为四种:low、medium、high、impossible;具体说明见网页;
5、查看源码位置 点击具体攻击测试项内下标[view source]即可查看网页php源码;
注意事项 由于某些攻击项实用性问题,因此不做赘述,如:Insecure CAPTCHA、Weak Session IDs;
登录或者注册用户 百度找到官网链接: 点击控制台: 登录上去,没有百度账户的可以先注册: 点击产品服务,找到人工智能,然后点击文字识别(下面的图片是老版的智能云): 点击创建应用 随便填自己的想要的名字,应用类型也可以自己选一个: 自己填点内容进去,点击立即创建即可: 创建成功,这两个东西以后要用到的: 下面是代码调用api 分两种方式: 第一是直接url调用api: 官方api链接:http://ai.baidu.com/docs#/OCR-API/top 下面是java实现方式,案例是表格文字识别
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Base64; import java.util.List; import java.util.Map; import org.json.JSONObject; import com.alibaba.fastjson.JSON; public class TestApi { public static void main(String[] args) throws Exception { /* String ss= "中国"; String s=Base64.getEncoder().encodeToString(ss.getBytes("gbk")); System.out.println(s); byte[] b = Base64.getDecoder().decode(s); System.out.println(new String(b,"gbk"));*/ //第一步,官方要求需要把图片转base64再转URLEncoder //获取图片base64编码 String image =getImageStr("
## 机器学习(二)对航空公司客户价值进行聚类分析 使用sklearn.cluester的KMeans类对航空公司客户数据进行聚类分析,
把乘客分到不同的类别中
数据集:air_data.csv
数据集大小:62052条不重复数据
原数据有40个属性,为了大家训练模型方便,本实验使用预处理后的标准化数据;
该数据有5个属性。
数据说明:
ZL:入会至当前时长,反应可能的活跃时间
ZR:最近消费时间间隔,反应最近一段时间活跃程度
ZF:消费频次,反应客户忠诚度
ZM:消费里程总额,反应客户对乘机的依赖程度
ZC:舱位等级对应折扣系数,一般舱位等级越高,折扣系数越大
## 题目一 载入训练数据、显示读入数据的前5行 import pandas as pd data = pd.read_csv("air_data.csv",header = 0) print(data.shape) print("1.载入数据,输出前五条") print(data.head()) ## 训练KMeans聚类模型,把数据聚成5类 from sklearn.cluster import KMeans k = 5 kmodel = KMeans(max_iter=300,n_clusters=5,random_state=None,tol=0.0001) kmodel.fit(data) 题目三 :检查每个聚类类别样本数、每个聚类类别中心点,统计聚类个数及中心点 r1 = pd.Series(kmodel.labels_).value_counts() print('统计各个类别的数目') print(r1) r2 = pd.DataFrame(kmodel.cluster_centers_)#找出聚类中心 print('聚类中心:') print(r2) r = pd.concat([r2, r1], axis = 1)#聚类中心对应的类别下的数目 r.
递归法实现全排列。
全排列就是指n个元素随机组合,且不重复的所有排列方式。
比如{1,2,3},就有123,132,213,231,312,321一共6种排列方式。
递归法的思路:
假设要实现{1,2,3,4}的全排列,整体思路是以1作为第一个,剩下的三个数字做全排列,然后以2作为第一个,剩下的三个数字做全排列,3作为第一个,剩下的三个数字做全排列,4作为第一个,剩下的三个数字做全排列。
具体的,每一层的递归,假设先固定第一位是1,剩下对后面3位子序列进行全排列,这时固定子序列的第一位是2,以此类推,直到子序列只剩下1位。
递归结束条件:当只有一个数字做全排列的时候,则它的全排列就等于其本身。
#include <iostream> #include <algorithm> using namespace std; //打印全排列 void prt(int arr[], int end) { for (int i = 0; i <= end; i++) cout << arr[i] << " "; } void perm(int arr[], int begin, int end) { //递归终止条件:当只有一个数字做全排列的时候,则它的全排列就等于其本身。 if (begin == end) { prt(arr, end); cout << endl; return; } for (int i = begin; i <= end; i++) { swap(arr[begin], arr[i]); //将第i个元素放到begin起始位置 perm(arr, begin + 1, end); //将剩下的从begin+1到最后的元素进行全排列 swap(arr[begin], arr[i]); //将交换的数进行还原 } } int main(void) { int arr[4] = { 1,2,3 }; perm(arr, 0, 2); }
牛客刷题日记(2021-11-8) 题目: JVM内存不包含如下哪个部分( ) A.Stacks B.PC寄存器 C.Heap D.Heap Frame 解析: 正确答案: D
题目: A 是抽象父类或接口, B , C 派生自 A ,或实现 A ,现在 Java 源代码中有如下声明: 1. A a0=new A(); 2. A a1 =new B(); 3. A a2=new C(); 问以下哪个说法是正确的?( ) 第1行不能通过编译 第1、2行能通过编译,但第3行编译出错 第1、2、3行能通过编译,但第2、3行运行时出错 第1行、第2行和第3行的声明都是正确的 解析: 正确答案: A
抽象类和接口都不能实例化
题目: 以下代码运行输出的是 public class Person{ private String name = "Person"; int age=0; } public class Child extends Person{ public String grade; public static void main(String[] args){ Person p = new Child(); System.
想把弹簧拉钩挂在孔里,要怎么配合?
可以用点对点重合的配合,就是用草图之间的配合,具体操作就是两个零件都分别画草图,有只打一个点的草图
画草图时在孔里点个点,然后点和弹簧扫描线重合
我写博客的初衷是为了系统的构建自己的知识体系,目前使用的平台有微信公众号,CSDN,博客园,GitHub Pages和Gitee Pages,他们都各有优缺点,整理的笔记多了之后发现这些平台不是很方便,比如公众号,CSDN和博客园,每次写完文章后,还需要再平台上进行编辑再发布,比较麻烦;GitHub Pages和Gitee Pages虽然可以快速发布,但是在文章系统管理上不是很方便。我希望将笔记整理成类似电子书一样,方便搜索和管理,经过查询资料,发现了ReadTheDocs这个文档管理工具,比较符合我的需求。可以使用 Sphinx 生成文档,GitHub 托管文档,然后导入到 ReadtheDocs进行展示,本文记录一下搭建过程。
目录 准备条件Sphinx创建文档1. 安装Sphinx2. 创建文档3. 编译4. 配置主题5. 配置markdown 关联Read the Docs 准备条件 1、github账号
使用github对文档进行版本管理
2、注册Read the Docs账号
官网地址:https://readthedocs.org/
3、安装Python
Sphinx是一个python工具,用于生成文档,所以需要安装Python环境。
Sphinx创建文档 Sphinx是一个基于Python的文档生成项目,开始是用来生成 Python 官方文档的工具,更多介绍可参考官网:https://www.sphinx.org.cn/ 。
1. 安装Sphinx Sphinx的GitHub地址:https://github.com/sphinx-doc/sphinx
pip安装Sphinx
$ pip install -U sphinx 2. 创建文档 先将远程github仓库clone到本地,这个仓库是你要托管文档的仓库,如果没有就新建一个。
clone到本地后,在项目根目录创建一个docs目录,cd进入docs目录,执行如下命令:
$ sphinx-quickstart Welcome to the Sphinx 4.2.0 quickstart utility. Please enter values for the following settings (just press Enter to accept a default value, if one is given in brackets).
题目描述
给定一个二元一次方程组,形如:
a * x + b * y = c;
d * x + e * y = f;
x,y代表未知数,a, b, c, d, e, f为参数。
求解x,y
输入
输入包含六个整数: a, b, c, d, e, f; 数据规模和约定
0 < = a, b, c, d, e, f < = 2147483647
输出
输出为方程组的解,两个整数x, y。 样例输入
3 7 41 2 1 9 样例输出
2 5 package parctice; import java.util.Scanner; public class ph1559 { public static void main(String[] args) { Scanner sc=new Scanner(System.
原始数据如下(实际数据肯定要比这个多的多)
名称品牌罗技键盘宁芝键盘樱桃键盘鼠标(罗技)NIZ键盘键盘cherry 编辑匹配的关键词和返回的内容
关键词品牌罗技罗技宁芝宁芝NIZ宁芝樱桃樱桃cherry樱桃 设置函数
=LOOKUP(9^9,FIND($E$2:$E$6,A2),$F$2:$F$6)
一.递归的使用环境 在写一些逻辑的时候,如果碰到一些很杂乱的数据,比如在一个多层嵌套数组找出你需要的数据,这时候是可以通过循环去循环数组去查找你需要的数据,但是如果这个数组并不是一两层,而是五六层,甚至更多,没有一个固定的层数,那么这个时候如果用循环不停去找这个数据并不是一个好的解决办法,而且循环每循环一层消耗的性能特别大,如果循环多了,就也会报超出执行栈的错误.
这个时候可以试试用递归解决这个困难的问题.
二.递归的概念 递归的概念非常简单,也就是在程序的函数中直接或间接的调用自己,并且必须要有一个跳出结果.
三.递归的步骤 假设递归函数已经写好寻找递推关系将递推关系的结构转换为递归体将临界条件加入到递归体中 四.递归的写法 说了这么多,展示代码说明吧!!!
data: [ { name: '1-1', children: [ { name: '1-1-1', children: [ { name: '1-1-1-1', children: [], }, { name: '1-1-2-1', }, ], }, { name: '1-2-1', }, { name: '1-3-1', }, ], }, { name: '2-1', }, { name: '3-1', }, { name: '4-1', }, ], 就比如这个是后端返回的数据
如果需求是要查找最下一级的数据,但是因为数据嵌套的特别深,如果要拿到里面的数据,如果用循环可能用三个以上的循环才能拿到数据,这样的话可能消耗的性能特别大,甚至浏览器卡死
但是用递归就能解决这个困难的问题
send(task) { for (const item of task) { if ('children' in item) { if (item.
排序有三个地方需要写,
1.自己排序的代码,
$(".sort").click( function (){ var obj ={ sort:{age:1} } getDataShow(obj); }) 2.对应获取数据函数的地方
function getDataShow(obj){ obj? obj :obj={} $.get("/show",obj,function(res){ if(res.code == 200){ show(res.info); }else{ alert(res.msg); } }) } 3.后端的一个代码,不用写接口,与渲染一个接口
module.exports.postAdd=function(req,res){ var obj =req.body; obj.age = +obj.age; db.insertOne(res,obj,"case1111a",function(err,result,db1){...} 搜索有三个地方需要改
1.搜索自己代码
$(".searchBtn").click(function () { var obj = { find: { user: $(".search").val() } } if (!$(".search").val()) { obj = {}; } getDataShow(obj); $(".search").val(""); }) 2.渲染 数据函数穿对象obj
function getDataShow (obj) { obj ?
1.介绍 对于实现三子棋游戏我使用了3个文件分别是1.头文件(game.h)放函数的声明,#include包含的头文件,以及#define定义的常量都会放到game.h这个头文件中。2.(game.c)游戏中的各种函数实现放到了其中。3.(test.h)游戏的大体框架包括游戏的入口函数,界面效果等等。接下来我们从各个文件开始了解
2.代码 game.h
#pragma once #define ROW 3 #define COL 3 #include<stdio.h> #include<stdlib.h> #include<time.h> void Init_board(char board[ROW][COL],int row,int col);//初始化棋盘 void Display_board(char board[ROW][COL],int row,int col);//打印棋盘 void playermove(char board[ROW][COL], int row, int col);//玩家下棋 void computmove(char board[ROW][COL],int row,int col);//电脑下棋 char is_win(char board[ROW][COL], int row, int col);//判断输赢 //玩家赢-'*' //电脑赢-'#' //平局-'Q' //继续-'C' 上诉代码中包含了游戏实现的大部分函数的声明,在头文件声明的函数可以在不同的.c文件中依靠#include"game.h",包含头文件来使用
game.c
#include"game.h" void Init_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } void Display_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf("
错误写法:
//订单金额 BigDecimal orderAmount = new BigDecimal(0); for (Object o : dayPriceDtos) { JSONObject obj = JSONObject.parseObject(o.toString()); //每日房价累加 orderAmount.add(obj.getBigDecimal("roomPrice")); } 问题:这样累加会导致orderAmount的值为0,累计无效
正确写法:
//订单金额 BigDecimal orderAmount = new BigDecimal(0); for (Object o : dayPriceDtos) { JSONObject obj = JSONObject.parseObject(o.toString()); //每日房价累加 orderAmount = orderAmount.add(obj.getBigDecimal("roomPrice")); } 原理:据说是因为 bigDecimal作为参数传入一个方法中,比如add(),累加之后返回的是一个新的对象,跟方法外部定义的BigDecimal对象不是同一个。重新赋值,覆盖掉就好了。
linux内核的软中断处理程序中能不能睡眠?
这是一个值得讨论的问题。
答案其实很简单,那就是不能。
因为Linux的软中断处理程序的运行上下文有可能是中断上下文。(注意此处是有可能,而并非一定)
那我们首先来了解下上下文,那什么是进程上下文?什么是中断上下文呢?
1.先来看进程上下文
我们知道:用户空间的应用程序,通过系统调用,进入内核空间。
所谓的“进程上下文”,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等。
2.再来看中断上下文
硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的 一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。
所谓的“ 中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境。
接下来我们来看下软中断处理程序的调用时机。
首先,大家知道,所有的软中断处理程序都要在do_softirq()中执行。
而do_softirq被调用的时机是:
从硬件中断处理程序返回时;在ksoftirqd内核线程中;在那些显式调用软中断的代码中,比如网络子系统中的NET_TX_SOFTIRQ和NET_RX_SOFTIRQ; 接着我们分析如上三种情形所处的上下文是什么?
对于情形1, 我们知道硬件中断处理程序的最后会执行irq_exit(),但是请注意:irq_exit() 这个函数所在的上下文还是中断上下文!而irq_exit()会调用invoke_softirq(),而invoke_softirq又会调用do_softirq()函数执行软中断的操作。所以,此时,do_softirq()的执行环境还是中断上下文!但是与中断上半部不同的是,do_softirq()执行过程中是开中断的,能够被硬件中断所中断。
再看情形2,ksoftirqd是一个普通的内核线程,在ksoftirqd中会不断的检查和执行do_softirq()函数,所以,此时,do_softirq()的执行环境还是进程上下文!
再看情形3,在这种情形下,软中断会在处理程序中再次触发自己。在目前的内核实现中,如果这种触发发生在硬件中断处理程序中,那么并不会立刻处理,而是会留给ksoftirqd去处理。所以,在这种情形下,do_softirq()的执行环境还是进程上下文!
综合以上三种情形,如果一个函数既要适用进程上下文的运行环境,还要适用中断上下文的运行环境,那当然是以严格的那个环境为准了。所以,软中断的运行环境其实和中断的运行环境是一样的,都运行在中断上下文,既不能睡眠、也不能调用schedule让出cpu。
最后一个问题,软中断被硬件中断打断之后,如何再恢复列表执行呢?
这个问题其实也很简单,分情况讨论:
如果软中断的执行函数运行在进程上下文:在这种情况下被硬件中断打断,会把进程上下文信息记录在task_struct结构体中,等到合适的时机再调度执行;如果软中断的执行函数运行在中断上下文:那就涉及到中断的嵌套了。针对这种情形,其实也是有相应的机制保证的: __handle_domain_irq()负责内核的硬件中断的处理,在函数开始会保存中断上下文信息,在这个函数的结尾会恢复中断上下文信息。这样保证了硬件中断被优先级更高的中断抢占之后,原先的中断上下文信息可以得到保存,进而得到恢复和执行。
linux内核代码是许许多多遵循相同内核开发规范的牛人们的共同的创造的结晶。作为一名linux内核或者驱动开发工程师,很有必要了解这些内核开发规范。好处有以下几个:
这些约定或者规范对我们阅读linux内核源码、了解设计思路有很大帮助我们基于linux内核做开发,也要往内核里添加代码,遵守开发规范,有助于别人阅读和理解我们的代码。 linux内核代码规范约定如下:
1.强烈推荐单行的宽度为八十列。
任何一行超过八十列宽度的语句都应该拆分成多个行,除非超过八十列的部分可以提高可读性且不会隐藏信息。但是,千万不要把用户可见的字符串,比如 printk 的信息,拆分成多行,因为这样会导致使用 grep 的时候找不到这些信息。
2.关于大括号
c语言里的if,do, while, for语句都会使用到大括号,内核代码倾向于把左括号放在行末,把右括号放在行首,并且大括号和前面的语句,以及if和后面的语句,都保留一个空格,例如:
以上红圈标注都代表一个空格。
3.关于空格
这个还是单独列出来说明一下吧,因为内核代码里用到空格的地方太多了。
Linux 内核风格的空格主要用在一些关键字上,即在关键字之后添一个空格。值得关注的例外是一些长得像函数的关键字,比如:sizeof, typeof, alignof, attribute,在 Linux 中,这些关键字的使用都会带上一对括号,比如sizeof(int)。
所以在下面这些关键字后面需要添加一个空格:
if, switch, case, for, do, while 但是, sizeof, typeof, alignof, attribute 之后则不需要添加空格:
s = sizeof(struct file); 在声明指针或者返回值为指针的函数时,星号的位置应该紧靠着变量名或函数名,而不是类型名,例如:
char *linux_banner; unsigned long long memparse(char *ptr, char **retptr); char *match_strdup(substring_t *s); 在二元操作符和三元操作符周围添加一个空格,例如:
= + - < > * / % | & ^ <= >= == != ?
我们生活在人间,但《西游记》里提到,在天上还有一个仙界。
人间不知道仙界的存在;而仙界知道人间的存在,神仙也可以从仙界下凡到人间,但是被严格管控的。
软件设计的灵感其实都来自于生活:用户空间就等同于我们理解的人间;而内核空间就等同于所谓的仙界。
人间在地上,仙界在天上,地理上是隔离的。
linux内核里的用户空间和内核空间也是一样。
以32位linux系统为例:
32位linux系统的地址空间分布
用户空间地址范围:0x00000000~0xBFFFFFFF,大小3G
内核空间地址范围:0xC0000000~0xFFFFFFFF,大小1G
有小伙伴问了,你这个地址是啥地址啊,是逻辑地址、虚拟地址、线性地址、还是物理地址咩?
当然是虚拟地址了。
在intel x86下,逻辑地址,是由一个段标识符加上一个指定段内的相对地址的偏移量(offset)组成,表示为 [段标识符:段内偏移量],例如:[cs:eip] 虚拟地址其实就是上述组成逻辑地址的段内偏移offset 而线性地址,则是由逻辑地址经过一系列转换得到的,具体来讲就是: 线性地址=段描述符所在段的基地址+offset 而物理地址,则是真正的物理内存的地址。 那么问题来了,linux内核为什么要特意划分内核空间和用户空间呢?有以下几方面的原因:
1.安全考量
整个系统中有各种资源,比如计算资源、内存资源和外设资源。而linux是多用户、多进程系统。所以,这些资源必须在受限的、被管理的状态下使用,要不然就陷入了混乱。官方介绍空间隔离可以保证即便是单个应用程序出现错误也不会影响到操作系统的稳定性。
2.处理器模式不同,权限不同
前面说到内核空间代码要管理各种底层的资源,而用户空间代码更多是实现业务逻辑的。所以内核空间和用户空间代码运行时的处理器模式是不同的。
对于x86体系的cpu, 用户空间代码运行在Ring3模式(用户模式),内核空间代码运行Ring 0模式(特权模式);
对于arm体系的cpu,用户空间代码运行在usr模式(用户模式),内核空间代码运行在svc模式(特权模式);
用户模式只能正常执行程序,而特权模式才能访问外设、处理中断等。
3.核心代码和业务代码的解耦
我们在设计应用系统的时候会考虑耦合性,内核集中了这么多人的智慧,难道它们不会考虑到这一点吗?
内核代码偏重于系统和资源管理;而用户空间代码(也即应用程序)偏重于业务逻辑代码的实现。
两者分工不同,隔离也是解耦。
现在的linux系统基本都是64位的。所以,我们再稍微介绍下64位系统的内核空间和用户空间的地址分布:
摘自:《linux高性能服务器编程》
64位系统的地址线有64位,但是在具体实现上,并没有使用这么多,一般来说,48位的地址线就够了。所以在这样的系统中,比如armv8-A,高64TB是内核空间,低64TB是用户空间,发现规律了没有?内核空间的的高16位都是1,用户空间的低16位都是0,这样可以方便的对用户空间和内核空间进行有效性检测,防止越界。
总结一下下:
32位linux系统的整个虚拟地址空间最大为4G,这4G的虚拟地址空间,高1G(也就是0xC0000000~0xFFFFFFFF)属于内核空间;低3G(也就是0x00000000~0xBFFFFFFF)属于用户空间,linux系统中的所有进程共用这3G的虚拟地址空间。
你说了什么?
共用?如何共用?
所有的进程共用这3G的虚拟地址空间该如何理解呢?
预知后事如何,请看下回分解。
在安装完sonarqube 和 sonar-scanner 之后,试验可以正常扫描。需要要求还要生成PDF报告,并下载,功能看似简单,但生成PDF 却比较多问题。
1. 下载安装,这个问题不大,因为这个只是sonarqube的一个插件,通过连接下载插件:https://gitee.com/zzulj/sonar-pdf-plugin ,在统计版本中可以查到适合已安装的sonarqube 版本的版本,本次安装的是sonarqube7.5,可以下载的版本在3.0以上
2. 直接将jar 包丢到/sonarqube-7.5/extensions/plugins 下面
3. 重新启动sonarqube , 登陆之后就可以看到增加了PDF的配置
4. 将原来的项目删除,然后重新进行扫描就可以有PDF了
正常是这样子的,可是头大开始
踩坑1: 扫描日志报错,明明已经生成了PDF,却在上传的时候说找不到。
解决方法:网上找了很久才在论坛里看到有人提到是配置的没对。Sonar ->配置->pdf report
这里搞混了配了数据库的登陆账号,然后把它换成sonar 的账号和密码,这里是否跳过要打开,不然会找不到文档,再重新扫描。
可是还是没找到PDF 跳过的日志。
踩坑2: pdf 确实是生成了,在服务器也找到了,可是下载却报错
解决方法:这个查找过程挺麻烦的,但是在之前的安装sonar时不停的掉进同一个localhost的坑里才有方向。
网上一般安装sonarqube 和sonar-scanner都直接安装在/usr/local/下面,然后sonar.web.context=/sonar 这个会保留默认,所以它请求的时候直接,域名+ 端口就可以访问,但我安装的是在/usr/local/sonar/路径下,然后sonar.web.context=/sonar 这个也打开了,所以正常的访问方式是:域名+端口/sonar?这个样的。
于是在下载的链接上/api/pdfreport/get?componentKey=TestEpay 前面增加 sonar ,变成/ sonar/api/pdfreport/get?componentKey=TestEpay , 然后请求下载就正常了。
通过刷新查看页面信息,下载这个拼接也不是从环境变量里面取的,也不知道它取的是哪个参数,于是直接修改其他的部分
于是直接修改插件的js文件,让拼接的链接正确
Linux 中解压jar 文件,因为会直接解压到当前文件,最好新建一个文件夹
Jar –xvf sonar-pdfreport-plugin-3.0.2.jar
vim ./static/download.js
重新压缩为jar包 jar cvf0M sonar-pdfreport-plugin-3.0.2.jar ./
然后替换原来的jar 包。
从新启动sonarqube , 查看页面元素
修改成功,点击download 下载成功。
1. 不要用1.1.8 因为nvm use x.x.x时会有错误代码,必须使用管理员运行cmd 但是一但回到了普通版cmd就又不行了,例如node -v就没反应。nvm ls也不显示正在使用。所以使用1.1.7 版
2. symlink选择的路径是正在使用的node的快捷方式 例如F:\nodejs 需要空文件夹
3. nvm安装node前设置镜像,便于更快下载
root: F:\nvm
path: F:\program files\nodejs
arch: 64
node_mirror: http://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
4. 由于之前安装nodejs时设置了两个文件夹
npm config set prefix "F:\nvm\v16.12.0\node_global"
npm config set cache "F:\nvm\v16.12.0\node_cache"
所以我在新的nvm安装的nodejs里面也设置了这两个文件夹,只不过有个问题,这个设置是全局的,那么使用不同版本的nodejs就要重新设置一下,并且重新安装全局包,例如yarn啥的
5. 做了更改环境变量的操作后记得重启一下电脑,有些情况不重启是无法生效的好像
教程 4: 自定义模型 我们通常把模型的各个组成成分分成6种类型:
编码器(encoder):包括 voxel layer、voxel encoder 和 middle encoder 等进入 backbone 前所使用的基于 voxel 的方法,如 HardVFE 和 PointPillarsScatter。骨干网络(backbone):通常采用 FCN 网络来提取特征图,如 ResNet 和 SECOND。颈部网络(neck):位于 backbones 和 heads 之间的组成模块,如 FPN 和 SECONDFPN。检测头(head):用于特定任务的组成模块,如检测框的预测和掩码的预测。RoI 提取器(RoI extractor):用于从特征图中提取 RoI 特征的组成模块,如 H3DRoIHead 和 PartAggregationROIHead。损失函数(loss):heads 中用于计算损失函数的组成模块,如 FocalLoss、L1Loss 和 GHMLoss。 开发新的组成模块 添加新建 encoder 接下来我们以 HardVFE 为例展示如何开发新的组成模块。
1. 定义一个新的 voxel encoder(如 HardVFE:即 DV-SECOND 中所提出的 Voxel 特征提取器) 创建一个新文件 mmdet3d/models/voxel_encoders/voxel_encoder.py :
import torch.nn as nn from ..builder import VOXEL_ENCODERS @VOXEL_ENCODERS.register_module() class HardVFE(nn.
方法重写:
规则: 1.子类继承父类的前提
2.方法名相同
3.参数列表相同
4.子类方法的返回值类型要与父类方法相同或者是其子类
5.访问修饰符不能比父类更严格
6.不能扩散异常(把父类方法抛出的异常增大)
7.静态方法不属于对象,因此不能被继承,想调用直接用类名.方法名()
静态方法不能与普通方法重名
重载和重写的区别:
重载涉及同一个类中的同名方法,要求方法名相同,参数列表不同,与返回值类型无关
重写涉及的是子类和父类之间的同名方法,要求方法名相同、参数列表相同、返回值类型相同
多态:子类对象引用父类类型
1.父类中的方法被子类重写(前提)
2.在别的类中,有一个参数为父类类型的方法,调用了被重写的父类方法
3.调用时(传递实参时),实参是子类对象,那么就会调用该子类对象重写后的方法
类型转换:
大类型接收小类型,默认转换成大类型
小类型接收大类型,强制转换成小类型(会丢失精度)
原则上类型要能转才允许转换,一般用instanceof关键字来判断
if(对象名 instance of 类型){ //判断一个对象是否属于一个类
子类型 新对象名=(子类型)对象名;
//可以用新对象名来调用子类特有的方法
}
启动错误如下 Error: Could not find or load main class Caused by: java.lang.ClassNotFoundException: 解决方案 首先进入nacos配置文件下的bin目录;
执行命令
vi startup.sh 在startup.sh文件中替换下方配置:
x JAVA_OPT_EXT_FIX="-Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext" √ JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext" x echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}" √ echo "$JAVA ${JAVA_OPT}" x echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 & x nohup "$JAVA" "$JAVA_OPT_EXT_FIX" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 & √ echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 & √ nohup $JAVA ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 & 启动nacos即可。
2021 MySql 8.0.26 安装教程(最详细的傻瓜教程) 1. 下载安装2. 初始化 MySql3. 用 Navicat 链接 MySql 1. 下载安装 打开官网网址,点击 downloan
点击 MySQL Community (GPL) Downloads » 点击 MySQL Community Server 选择自己对应的版本,下载安装 下载后,解压到自己喜欢的目录下(最好不要是C盘),并记录下自己的目录 新建文本文档,输入以下内容,并保存到自己解压的目录下,并将格式修改为 .ini [mysqld] # 设置3306端口 port=3306 # 设置mysql的安装目录 ----------是你的文件路径------------- basedir=D:\mysql-8.0.27-winx64 (1)\mysql-8.0.27-winx64 # 设置mysql数据库的数据的存放目录 ---------是你的文件路径data文件夹自行创建 #datadir=E:\mysql\mysql\data # 允许最大连接数 max_connections=200 # 允许连接失败的次数。 max_connect_errors=10 # 服务端使用的字符集默认为utf8mb4 character-set-server=utf8mb4 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 #mysql_native_password default_authentication_plugin=mysql_native_password [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8mb4 [client] # 设置mysql客户端连接服务端时默认使用的端口 port=3306 default-character-set=utf8mb4 2. 初始化 MySql 以管理员身份打开 cmd ,进入到你的解压目录下的 bin 目录 输入 mysqld --initialize --console 得到默认的初始密码,一定要记住,复制下来 :h4Y&sBG_,4<!
问题描述 今天在配置nacos作为配置中心时遇到了一个问题,我按照官方步骤新建bootstrap.properties,添加了@Value和@RefreshScope注解,并且也在nacos中按照步骤新建了配置。
但是当我修改时,发现配置中心始终不起作用。
解决方案 经排查,是bootstrap.properties没有起作用,通过添加依赖即可。依赖如下:
<!-- nacos配置管理依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> <version>3.0.4</version> </dependency> 第一个依赖为nacos启动器,第二个依赖是bootstrap的启动器,添加如上依赖,更新maven即可成功启用。
https://ihax.io/adb-fastboot-commands/#ADB_Shell_Commands_List
http://adbcommand.com/adbshell/am
C:\Users\XX>adb help
Android Debug Bridge version 1.0.41
Version 31.0.2-7242960
Installed as D:\02_sofeware_install\Sdk\platform-tools\adb.exe
global options:
-a listen on all network interfaces, not just localhost
-d use USB device (error if multiple devices connected)
-e use TCP/IP device (error if multiple TCP/IP devices available)
-s SERIAL use device with given serial (overrides $ANDROID_SERIAL)
-t ID use device with given transport id
-H name of adb server host [default=localhost]
-P port of adb server [default=5037]
前言 光阴似箭,日月如梭!跟着孤尽老师学习的第二周也即将结束,训练营的日子也已经过去了一半。古人云,学而不思则罔,思而不学则殆。今天我们来对第二周的学习做个总结。
内容回顾 day08
首先,孤尽老师对上一周的作业做了一个标准解答:
用例图核心:用户 + 行为,有哪些用户角色,使用了系统什么功能类图核心:模型的抽象、模型之间的关系时序图核心:对象之间的协作、随着时间线,做了什么状态图核心:有哪些状态、什么条件触发状态变化活动图核心:有哪些系统参与了协助、每个流程的判断 无尘老师介绍了应用分层,传统的MVC架构(Model模型,View视图,controller控制器),每层承担不同的职责,让专门的模块做专门的事。
还学习了主流的构建工具maven
主要功能:依赖管理、规范目录结构、完整的项目构建阶段、支持多插件
依赖仲裁:DependencyManager进行声明仲裁,如果没有声明仲裁,则按照最短路径、如果路径也相同,按照第一声明优先原则
查找依赖:利用插件 maven helper
解决冲突:exclusion 排除依赖、option 可选依赖
二方库的介绍,命名规范、引用规范、引用建议、发布原则
day09
网络协议 TCP/IP
ios 的七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
tcp五层模型:物理层、链路层、网络层、传输层、应用层
tcp 连接的三次握手 和 四次挥手
day 10
技术选型
为什么需要技术选型?降低开发成本、提高研发效率、系统可维护性
微服务架构三部曲:单体应用、SOA(面向服务架构)、微服务
常见的数据库访问层技术
JDBC :java database connectivity 是sun公司指定的java数据库连接技术简称
JdbcTemplate:是spring 对jdbc的封装 JdbcTemplate处理了资源的建立和释放,比如数据库连接的创建和释放,statement 的建立和执行
Hibernate:全自动化持久层框架
Mybatis:优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)
Mybatis-plus:一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。它封装了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA
常见数据库连接池
Druid 提供了一个高效、功能强大、可扩展性好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池
Docker 容器的操作 1 新建并运行容器1.1 创建容器1.2 新建并运行容器 2 查看运行的容器3 查看容器日志4 进入容器的内部4.1 attach4.2 exec 5 删除容器6 导入和导出容器 1 新建并运行容器 1.1 创建容器 docker create -it ubuntu:latest # 使用如上命令新建的容器处于停止状态,可以使用如下命令启动它 docker start [CONTAINER ID] 1.2 新建并运行容器 # docker run # 有两种:第一种:基于镜像新建一个容器并启动,第二种是处于终止状态【stop】的容器重新启动 当利用docker run来创建并启动容器时,Docker 在后台运行的标准操作包括: 1. 检查本地是否存在指定的镜像,不存在就从公有仓库下载。 2. 利用镜像创建并启动一个容器。 3. 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层。 4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去。 5. 从地址池配置一个IP地址给容器。 6. 执行用户指定的应用程序。 7. 执行完毕后容器被终止。 ---------------------------- # 启动一个bash终端,允许用户进行交互 docker run -it ubuntu /bin/bash -t 分配一个伪终端 -i 让容器的标准输入保持打开 ---------------------------- # 运行容器需要定制具体镜像,如果镜像不存在,会直接下载 docker run -d -p 宿主机端口:容器端口 --name [CONTAINER NAMES] [IMAGE ID] | REPOSITORY[:tag] #-d 代表后台运行容器 #-p 宿主机端口:容器端口:为了映射当前Linux的端口和容器的端口 #--name 容器名称:指定容器的名称【唯一】 如果不指定,则随机名称 # [IMAGE ID] | REPOSITORY[:tag] 镜像的标识或者镜像名称[:tag],二选一 例如: docker run -d -p 8081:8080 --name tomcat b8dfe9ade316 2 查看运行的容器 查看全部正在运行的容器信息 docker ps [-qa] #-a 查看全部的容器,包括没有运行 #-q 只查看容器的标识 例如: docker ps -a # 查看所有容器 docker ps -qa # 仅仅是查看所有容器的ID # 重点: docker ps -af # 文档:https://docs.
转载于:浏览器控制台报JS脚本执行错误:Module is not defined - 踏得网
现在JS分成了两个分支,一部分在服务器端发展如NodeJS,一部分是传统的浏览器运行环境。
有些插件在编写JS代码时,是针对Node编写的,所以直接在浏览器中使用会报错,通常是:
require is not defined
module is not defined
解决第一个错误的方法是,去除require,直接在页面中使用script标签加载,或者使用require.js。
解决第二个错误的方法是把原来的代码改写为兼顾浏览器和服务器类型的代码,示范如下:
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { module.exports = PolyBezier; } else { if (typeof define === 'function' && define.amd) { define([], function() { return PolyBezier; }); } else { window.PolyBezier = PolyBezier; } }
2021年全球与中国助听器行业市场规模及发展前景分析
本报告研究全球与中国市场助听器的发展现状及未来发展趋势,分别从生产和消费的角度分析助听器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。
主要生产商包括:
Sonova Holding AG
William Demant Holdings A/S
Sivantos
Starkey
Benson Hearing
ReSound Group
MicroTech
Widex A/S
AGX Hearing
Beltone
Audicus
Miracle-Ear
针对产品特性,本报告将其分为下面几类,主要分析这几类产品的价格、销量、市场份额及增长趋势。主要包括:
耳后式(BTE)
耳内式(ITE)
耳道式(ITC)
深耳道式(CIC)
针对产品的主要应用领域,本报告提供主要领域的详细分析、每种领域的主要客户(买家)及每个领域的规模、市场份额及增长率。主要应用领域包括:
先天性
老年人听力损失
获得性创伤
本报告同时分析国外地区的生产与消费情况,主要地区包括北美、欧洲、日本、东南亚和印度等市场。对比国内与全球市场的现状及未来发展趋势。
主要章节内容:
第一章,分析助听器行业特点、分类及应用,重点分析中国与全球市场发展现状对比、发展趋势对比,同时分析中国与全球市场的供需现在及未来趋势。
第二章,分析全球市场及中国生产助听器主要生产商的竞争态势,包括2019年和2020年的产量 、产值(万元)、市场份额及各厂商产品价格。同时分析行业集中度、竞争程度,以及国外先进企业与中国本土企业的SWOT分析。
第三章,从生产的角度,分析全球主要地区助听器产量 、产值(万元)、增长率、市场份额及未来发展趋势,主要包括美国、欧洲、日本、中国、东南亚及印度地区。
第四章,从消费的角度,分析全球主要地区助听器的消费量 、市场份额及增长率,分析全球主要市场的消费潜力。
第五章,分析全球助听器主要厂商,包括这些厂商的基本概况、生产基地分布、销售区域、竞争对手、市场地位,重点分析这些厂商的助听器产能 、产量 、产值(万元)、价格、毛利率及市场占有率。
第六章,分析不同类型助听器的产量 、价格、产值(万元)、份额及未来产品或技术的发展趋势。同时分析全球市场的主要产品类型、中国市场的产品类型,以及不同类型产品的价格走势。
第七章,本章重点分析助听器上下游市场情况,上游市场分析助听器主要原料供应现状及主要供应商,下游市场主要分析助听器的主要应用领域,每个领域的消费量 ,未来增长潜力。
第八章,本章分析中国市场助听器的进出口贸易现状及趋势,重点分析中国助听器产量、进口量、出口量 及表观消费量关系,以及未来国内市场发展的有利因素、不利因素等。
第九章,重点分析助听器在国内市场的地域分布情况,国内市场的集中度与竞争等。
第十章,分析影响中国市场供需的主要因素,包括全球与中国整体外部环境、技术发展、进出口贸易、以及行业政策等。
第十一章,分析未来行业的发展走势,产品功能、技术、特点发展趋势,未来的市场消费形态、消费者偏好变化,以及行业发展环境变化等。
第十二章,分析中国与欧美日等地区的销售模式、销售渠道对比,同时探讨未来销售模式与渠道的发展趋势。
第十三章,是本报告的总结部分,该章主要归纳分析本报告的总体内容、主要观点以及对未来发展的看法。
正文目录
第一章 行业概述及全球与中国市场发展现状
1.1 助听器行业简介
1.1.1 助听器行业界定及分类
1.1.2 助听器行业特征
1.1.3不同种类助听器价格走势(2021-2027年)
1.2 助听器产品主要分类
1.2.1.耳后式(BTE)
Docker 私有仓库 1. 私有仓库1.1 创建私有仓库1.2 管理私有仓库 1. 私有仓库 1.1 创建私有仓库 docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry 1.2 管理私有仓库 # 查需要上传的镜像 docker images # 将镜像标记为私有仓库 docker tag ubuntu:latest 192.168.10.10:5000/ubuntu:1.1.0 # 标记为1.1.0 docker tag ubuntu:latest 192.168.10.10:5000/ubuntu # 自动设置为latest # 上传标记的镜像 docker push 192.168.10.10:5000/ubuntu:1.1.0 # 仅上传1.1.0 docker push 192.168.10.10:5000/ubuntu # 上传所有ubuntu本地仓库下的REPOSITORY的镜像 # 查看是否上传成功 curl http://192.168.10.10:5000/v2/_catalog # 下载刚才的上传的私有镜像 docker pull 192.168.10.10:5000/ubuntu:1.1.0
1.部分原因是ServinceImpl或者Mapper层未添加注解@SERVER
2.我这边是Controller层报错,Service接口无法跳转实现类,排查后并不是注解问题,是idea缓存问题。
解决方案:
1.注解问题请添加相应注解
2.File–Invalidate caches/restart 就好了,重启后报错解除,就可以从接口service跳转到下面实现类了
假如Keepalived有10个VIP,怎么查看每个VIP的流量呢?
这里就可以使用sar命令查看网卡流量了。前提是你Keepalived监听网卡时。设置网卡时子接口。
也就是说你网卡绑定子接口上。这样eth0:0,eth0:1,每个网卡流量都可以看了
在工作中,我们经常需要查看服务器的实时网卡流量。通常,我们会通过这几种方式查看Linux服务器的实时网卡流量。
1. sar -n DEV 1 2
sar命令包含在sysstat工具包中,提供系统的众多统计数据。其在不同的系统上命令有些差异,某些系统提供的sar支持基于网络接口的数据统计,也可以查看设备上每秒收发包的个数和流量。
sar –n DEV 1 2 DEV显示网络接口信息命令后面1 2 意思是:每一秒钟取1次值,取2次。
另外,-n参数很有用,他有6个不同的开关:DEV | EDEV | NFS | NFSD | SOCK | ALL ,其代表的含义如下:
DEV显示网络接口信息。EDEV显示关于网络错误的统计数据。NFS统计活动的NFS客户端的信息。NFSD统计NFS服务器的信息SOCK显示套接字信息ALL显示所有5个开关 [sre@CDVM-213017031 ~]$ sar -n DEV 1 2 Linux 2.6.32-431.el6.x86_64 (CDVM-213017031) 05/04/2017 _x86_64_ (4 CPU) 08:05:30 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s 08:05:31 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:05:31 PM eth0 1788.
一、顺序表的初始化
算法步骤:
(1)为顺序表L动态分配一个预定大小的数组空间,使elem指向这段空间的基地址。
(2)将表的当前长度设为0。
typedef int ElemType; typedef struct { ElemType *elem; int length; } SqList; //顺序表的初始化 void InitList(SqList &L) { L.elem=new ElemType[MAXSIZE]; if(!L.elem) { cout<<"存储分配失败!"<<endl; } L.length=0; cout<<"顺序表初始化成功!"<<endl; } 二、顺序表的取值
算法步骤:
(1)判断指定序号i的值是否合理(1<=i<=L.length)。
(2)若i值合理,则将第i个元素L.elem[i-1]赋给参数e,通过e返回第i个数据元素的值。
//顺序表的取值 int GetElem(SqList L,int i,ElemType &e) { if(i<1||i>L.length)//判断i值是否合理,若不合理,返回ERROR -1 { cout<<"i值不合法!"<<endl; return -1; } e=L.elem[i-1];//elem[i-1]单元储存第i个数据元素,把第i个元素数据赋值给e cout<<"取值成功!"<<endl; return e;//通过e返回第i个元素数据 } 三、顺序表的查找
算法步骤:
(1)从第一个元素起,依次和e比较,若找到与e相等的元素L.elem[i],则查找成功,返回该元素的序号i+1。
(2)若查遍整个顺序表都没有找到,则查找失败,返回0。
//顺序表的查找 int LocateElem(SqList L,ElemType e) { //在顺序表L中查找值为e的数据元素,返回其序号 for(int i=0; i<L.length; i++) { if(L.
1、安装 Vscode; 2、在 Vscode 中安装 Remote Development 扩展; 3、把远程资源管理器修改为:SSH Targets;
4、点击 SSH TARGETS 后面的配置按钮 ,如下图所示; 选择第一个默认路径即可;
第二行 Host 后面的名字可以随便起;第三行 HostName 后面的是 Ubuntu 主机地址,可在 Ubuntu 中输入 ifconfig 获取;
第四行 User 是 Ubuntu 用户名;最后保存,如下图所示;
5、连接完之后需要检查 Ubuntu 中是否安装了 openssh-server ; 如果没有安装,则输入 sudo apt-get install openssh-server 进行安装;安装完之后右击 Ubuntu64 进行连接;
然后根据提示点击 Linux、continue、输入 ubuntu 的密码,最后按 ENTER 就可连接上了;
如果 Ubuntu 没有安装 openssh-server ,而直接右击 Ubuntu64 进行连接,在点击完
Linux 后不会出现 continue 和让输入 ubuntu 密码的提示,自然而然最终就会出现安装失败!
注:如果在 Ubuntu 中安装 openssh-server 时出现了一系列问题,很有可能是你在安装 Ubuntu 时使用了不合适的源,推荐使用 阿里源 !!!
本期主题:
ARM流水线
往期地址:
ARMv7架构学习 ARM流水线 1.流水线概念2.指令的分解步骤 1.流水线概念 硬件资源总是有限的,有一个明显的方法能改善硬件资源的利用率,这就是pipeline(流水线)技术,其实就是在当前指令结束之前就开始执行下一条指令。
ARM中的流水线是这么做的:
当一条指令刚执行完步骤1,准备转向步骤2时,下一条条指令开始执行步骤1。
2.指令的分解步骤 一条指令在被处理器运行时,实际上会被拆解成很多步骤,典型的计算机系统步骤如下:
首先,处理器需要从存储器中取指令(fetch)译码器对这条指令进行翻译(decode)从指令中提取指令的操作数,这些数一般都存在寄存器中,所以一般都从寄存器中取出(reg)取到操作数之后,进行组合得到结果(ALU)如果需要,则访问存储器以存储数据(mem)将结果写回到寄存器堆(res) 使用流水线,可在取下一条指令的同时译码和执行其他指令,从而加快执行的速度。可以把流水线看做是汽车生产线,每个阶段只完成专门的处理器任务。
简单的登录界面 登录表单主界面 login.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>session登录测试</title> </head> <body> <form action="1.php" method="post"> 用户名:<input type="text" name="name2"> 密码:<input type="password" name="pwd2"> <input type="submit" value="登录" /> </form> </body> </html> 表单通过post方法把用户名密码交予1.php判断
若正确则创建session并跳转到2.php
<?php // header("Content-type:text/html;charset=utf-8"); session_start(); if(empty($_POST)){ echo "请输入密码后登录<br/>"; echo "<a href='login.html'>请登录</a>"; } else { $name=$_POST["name2"]; $pwd=$_POST["pwd2"]; if ($name=="bob"&&$pwd=="asdsaad") { $_SESSION["name"]="bob"; header("Location:2.php"); } else { echo "wrong password or username<br/>"; echo "<a href='login.html'>请登录</a>"; } } 登录成功跳转到的最终页面 2.php*
必须要有session才能访问
<?php // header("Content-type:text/html;charset=utf-8"); session_start(); if(empty($_SESSION)){ echo "
看来迟早有一天还是要学习数据分析的
快速填充ctrl+e(功能包括提取括号中内容、拆分重组、数据拆分、),要求填充列左侧必须有数据(只要有一个即可,比如第一行)。ctrl+shift+下,选中下面所有单元格。快速分析ctrl+q。tab(向右)+enter(向下)+shift(反)键进行输入,enter可以自动识别有效数据的新一行(前提是前面都用tab键输入)。日期有效数据为2021/9/1(最标准)或2021-9-1,别的输入方法系统都识别不出来。ctrl+:会显示现在的日期,ctrl+shift+;会显示现在的时间。输入分数之前要先输入0和空格,但如果批量输入的话先输入小数然后格式转化为分数较为方便。excel数据精度默认最长15位。左上角的小三角代表本单元格为文本形式,叫做错误指示器。文本格式可以直接设定也可以在数据最开始添加一个英文状态下的单引号。原位填充ctrl+enter,主要用途在于一大批错乱单元格里输入同样内容。全选表格后ctrl+t(也可以在原表上点插入表格),创建超级表(多了一个表格设计的选项卡),设计选项卡中点击转化为区域变为普通区域。power query的作用在于记录步骤,哪一步不想要随时可以取消。换句话说对数据源本身是无损的。所以我们通常用power query去冲洗数据。冲量检查?文本默认左对齐,数字默认右对齐,逻辑值默认居中对齐。清除格式有另外的选项卡,在开始选项卡中编辑中有个清除的选项。选项卡里每个组右下角的方形箭头叫启动器。不建议使用合并后居中,因为无法定位到里面的任意一个单元格,也无法对其进行筛选和透视。使用单元格格式对齐方式中的跨列居中代替。网格线不同于边框线,是一种辅助工具,打印时不会显示,可以在页面布局选项卡中关掉。打印时若想显示网格线,文件-打印右下角页面设置的工作表中有一个打印网格线,选中即可。ctrl+1:打开单元格格式。单元格中出现########,是列宽不够,开始-格式中选择自动调整列宽。常规数字格式(默认数字格式)会根据其单元格长度对带有小数点的数字进行四舍五入,系统会自己判断字符展现为何种形式。日期默认情况下会将1900年1月1号当成序列号1,因为excel本质上是将日期储存为数字(序列)。时间0点为序列号1。数字格式代码: 数字占位符有0、#、?三种; 0的作用是强制的占位符,不够位数的地方都会用0去凑满;#的作用是相比于0,只显示有意义的值;?的作用是相比于0,用空格去代替0。 文本占位符只有@一种,他代表对应的文本本身,可以多次重复或者共同加入别的文本;区域定义通过英文的封号分开(😉,0正数-0复数0零@文本,区域隔开后可以在其中添加汉字;颜色设置:在每个区域最前面输入[颜色]这样的格式;条件运算格式:[条件1]0;[条件2]0;0 ;日期格式,有多种格式,如下:
;总结:先分区域,再设条件,再设颜色,再设格式。 数据验证时,对于未知的数据,无效数据不会录入;对于已知的数据,可以圈释无效数据,但圈释无效数据对复制过来的数据无效(连同格式一块粘贴)。当然也可以直接将验证粘贴到别的地方。条件格式最大的优点就是会根据你内容的改变,利用上不同的条件规则。找出不重复值(唯一值),通过条件格式中重复项中的唯一值选取,最终通过颜色筛选可以剔除掉不需要的值。查找功能的限制用定位代替。定位中的常量是指没有公式且不是空值和对象的地方。粘贴不带隐藏的行,先定位选中,再复制,粘贴。ctrl+enter————全部填充,将公示规则全部填充至所选单元格。定位条件快捷键:ctrl+G。每一个excel文件是工作簿,工作簿中的每一个sheet表是工作表。ctrl+n————新建工作簿。可以同时选中多个工作表,一个操作运用到多个工作表上,这叫做工作表组。shift选择单元格,选择到当前位置的单元格,这叫做连选。快速到最上/下/左/右一行的方法:任意点击一个单元格,双击单元格的上/下/左/右边框;或者用ctrl+上/下/左/右键。与此同时,加上shift的连选,ctrl+shift+上/下/左/右可以快速选中一整列或一整行。视图下面的冻结窗格也是一个实用的技巧。打印时如果所有列放不在一张纸上,调成最窄边距还不够,那就需要使用缩放功能了。打印标题行只能在选项卡的页面设置中确定。进入函数需要按tab键或鼠标双击。选中表格后用alt+=,对整张表求和。输入函数时可以适当使用参数面板(快捷键ctrl+a),避免格式错误。绝对引用,就是指在函数中将变量变成常量的方法,变量中哪一项需要固定就在前面添加一个$符号。两个都需要加的话也可以使用f4。九九乘法表固定规则:纵向拉的时候锁定固定值的行,横向拉的时候锁定固定值的列。行列都锁定叫绝对引用,只锁定一个叫混合引用,都不锁定叫相对引用。count()计数数字,counta()计数非空值。countif输入条件时<>是不等于,输入小于某个单元格内容时,由于单元格代号并非文本,而小于号是文本,所以需要用文本连接符&连接,具体格式为[ “>”&F11 ]。输入函数时若遮挡到了左边的单元格,则将当前单元格左对齐即可解决。求平均成绩时,空值不等于0,文本和空值不会参与计算,而0会。函数对于文本值/删除的不必要数据时会直接跳过,而不是像不用函数时候的报错。函数同时也会自动添加插入的数据,不用函数就不会自动添加。sumif函数第一个参数为区域范围,若求值范围和区域范围一样,则可以忽略求值范围。选中表格中一个单元格,ctrl+a选中单元格所在的整个表格。sumproduct函数内部使用参数必须是一个数组,可以进行数组运算,但本身不是数组函数。多函数嵌套只有最外层函数加=号。替换快捷键ctrl+h。查找范围也可以为整个工作簿。查找时一般来说查找的是包含关系(任何包含查找目标的项),如果只想查找值,令其完全相等,那需要勾选单元格匹配选项。也可以查找格式,在查找框的"选项"卡中。查找还可以用于分组命名,先在分组框中全部查找,全选选中后在左上角对选中项进行重新命名,之后在函数中可以直接对分组名进行操作,该分组名代表整个分组数据。通配符*————任意多个字符、?————任意单个字符、~————输入波浪号后可以输入符号。分列只能分一列数据而不能多列。分列过程中自定义的分隔符只有一个,如果有多个需要分隔,则需要分列多次,待分列的列必须标注为文本格式,否则系统会默认将其忽略。分列时候通过选择"不导入此列"对列进行选择性导入。排序的目标是选出最值,筛选的目标是剔除无用信息。普通排序直接选到某一单元格上即可对其所在列进行扩展区域的排列(方便)。选择排序表格的时候,一般是选中属性栏的,然后"数据包含标题"项默认勾选。排序时候在次序选项中有自定义序列,可以自定义排序规则。筛选快捷键ctrl+shift+l。筛选的时候默认是不会去排序的,只会选出。筛选过的表格还可以二次筛选,上面有一个漏斗型标志,筛选出来的内容只不过是一个视图,并未改变源数据;二次筛选的内容若想包含在一次筛选内,则点击添加到筛选器。排序还可以用rank()函数,通常用于出单个单元格的排名而非整体。Vlookup()函数:vlookup(查找值,查找区域,返回值所在列,精确0/模糊1查找),通常用于查找和引用数据。
注意点: 精确查找查找值必须在第一列中,否则报错;返回值所在列是相对于当前表格而非整体表格,若隐藏后位置也是使用隐藏前的;精确查找是找到某一具体值,模糊查找是找某一范围内的值;无论模糊还是精确查找,都分为素材表和查找目标表,返回值所在列也是基于素材表而非查找目标表的;使用模糊查找时的素材表必须是升序,而且范围不重叠,模糊查找这里有个比较厉害的算法,可以自己判断在那个范围内从而做出选择;对于精确查找查找值只能在第一列的局限性,引进第二个参数的格式:[ if({1,0},应该是第一列的列,当前第一列) ],这样就可以使查找值可以不仅限于第一列,此时返回值所在列为调换后的列。
SpringBoot中devtool热部署
1.1 引言
为了进一步提高开发效率,springboot为我们提供了全局项目热部署,日后在开发过程中修改了部分代码以及相关配置文件后,不需要每次重启使修改生效,在项目中开启了springboot全局部署之后只需要在修改之后等待几秒即可使修改生效。 1.2 开启热部署
1.2.1项目中引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 1.2.2 IDEA中配置
当我们修改了类文件后,idea不会自动编译,得修改idea设置。
(1)
File > Settings > Compiler > Build Project automatically (2)
ctrl + shift + alt + / , 选择Registry , 勾上Compiler autoMake allow when app running
1.运行代码后,报错:地址 localhost:8080 已在使用中
2.查看8080端口,是否被占用。Windows+R,弹出运行窗口,输入cmd,然后Enter键,如下图进入运行窗口。
3.在运行窗口,输入:netstat -ano,然后Enter,如下图1。弹出下图2,发现TCP 0.0.0.0:8080,说明8080窗口已经被占用,进程PID是11572
图1
图2 4.输入tasklist,然后Enter键,弹出如下图3:找到8080对应的11572,就可以知道那个程序占用8080端口。
图3
如下图4,所示ApplicationWebServer.exe,占用了8080端口。
图4
或者输入:netstat -aon|findstr 端口号 查看端口号是否被占用;
输入:tasklist|findstr “PID数字” 可以直接查询那个程序占用了端口号。
5.进入任务管理器,找到ApplicationWebServer.exe,终止此任务程序。就可以重新运行程序代码,并进入8080端口。
运行结果如下图,可以进入Tomcat的8080端口:
1. 消息队列 1.1 MQ 的相关概念 1.1.1 什么是 MQ MQ,从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的信息内容是 message 而已,还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ 是一种非常常见的上下游”逻辑解耦+物理解耦“的消息通信服务。使用了MQ之后,消息发送上游只需要依赖MQ,不用依赖其他服务
1.1.2 为什么要用MQ 1、流量消峰
举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段,我们下单一秒后就能返回结果,但是高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。使用消息队列做缓冲,我们可以取消这个限制,把下一秒内下的订单分散成一段时间来处理,这是有些用户可能在下单好几秒之后才能受到下单成功,但是比不能下单的体验要好。
2、应用解耦
以电商应用为例,应用中有订单系统,库存系统,物流系统,支付系统给。用户创建订单后,如果耦合调用库存系统,物流系统,支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成,当物流系统恢复后,继续处理订单信息即可,中间用户感受不到物流系统的故障,提升系统的可用性。
1.2 RabbitMQ 1.2.1四大核心概念 生产者
产生数据发送消息的程序是生产者
交换机
交换机是 RabbitMQ 非常重要的一个部件,一方面它接收来自生产者的消息,另一方面它将消息推送到队列中。交换机必须确切知道如何处理它接收到的消息,是将这些消息推送到特定队列还是推动到多个队列,或者是把消息丢弃,这个由交换机类型决定
队列
队列是 RabbitMQ 内部使用的一种数据结构,尽管消息经 RabbitMQ 和应用程序,但是它们只能存储在队列中。队列仅受主机和磁盘限制的约束,本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据。这就是我们使用队列的方式。
消费者
消费与接收具有相似的含义。消费者大多时候是一个等待接收消息的程序。==注意:==生产者,消费者和消息中间件有很多时候并不在同一机器上。同一个应用程序既可以是生产者又可以是消费者
一个交换机可以对应多个队列
2. Hello World 在下图中,”P“ 是生产者,”C“ 是消费者,中间的框是一个队列——RabbitMQ 代表使用者保留的消息缓冲区。
3. Work Queue 工作队列的主要思想是避开立即执行资源密集型任务,而不得不等待它完成。相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务
3. 确认发布 3.1 发布确认的策略 3.1.1 开启确认的方法 发布确认默认是没有开启的,如果要开启需要调用方法 confirmSelect,每当你想要使用发布确认,都需要在 channel 上调用该方法
Channel channel = connection.createChannel()
channel.confirmSelect()
3.1.2 单个确认发布 这是一种简单的确认方式,它是一种同步确认发布的方式,也就是发布一个消息之后只有它被确认发布,后序的消息才能继续发布,waitForConfirmsOrdie(long) 这个方法只有在消息被确认的时候才返回,如果在指定时间范围内这个消息没有被确认那么它将抛出异常。
格式化输入输出 格式化输入输出,也叫做标准输入输出,即从键盘输入,输出到屏幕上。
头文件是stdio.h,以下3种方法都可以导入:
1
#include <stdio.h>
1
#include <cstdio>
1
#include <bits/stdc++.h>
输出函数 printf,print就是打印,表示打印到屏幕上,f则是format、function的首字母,你可以理解成格式化输出、输出函数等。
例一:输出Hello World: 1
2
3
4
5
6
#include <bits/stdc++.h>
using namespace std;
int main(){
printf("Hello World\n");
return 0;
}
例二:输出变量的值 格式化输出函数,你需要输出什么,直接写在双引号里面,如果里面包含变量,只需要用格式符替换。
如输出“I'm 12 years old.”,
1
2
3
4
5
6
7
8
9
10
#include <bits/stdc++.h>
using namespace std;
int main(){
int a;
cin >> a;
printf("I'm 12 years old.\n");
printf("I'm a years old.
背景 公司内个别 pod 因为特殊环境使用的 host 网络,最近无意中发现,有一个 host 网络的 pod 无法解析 k8s 的 service,于是展开了后面的排查
排查步骤 进入 pod 内 ping svc,发现无法解析 svc,初步怀疑是 dns 的搜索域或者 dns 有问题
$ kubectl exec ht-deployment-7d4b886c7b-mf6pq ping test-service ping: ht-service: Name or service not known $ kubectl exec ht-deployment-7d4b886c7b-mf6pq cat /etc/resolv.conf # 发现 pod 的 dns 地址和搜索域不太正常,不是集群内的 dns地址 search dns.com nameserver 10.10.10.10 nameserver 10.10.10.20 options timeout:2 options rotate $ kubectl exec ab-deployment--mf6pq-xas1w cat /etc/resolv.conf # 正常的是这样 nameserver 169.
一、文本编辑器 vi vim gedit gvim vim 可高度自定义,适合单个软件开发
二、编译器 gcc
三、库
四、调试器 gdb 资源占有少,免费开源,缺少图像显示,适合小程序开发
五、工程管理器 make(批量处理)自动化编译,提高开发效率
为什么使用要学Linux工具,它的优势和作用?
1、可定制 2、开源 3、便携 4、体积小 5、提高开发效率
其他开发环境和IDE
vs code 相对其他IDE(集成开发环境)小,便捷,功能没有VS 2019 Qt强大
vs 2019 功能强大,体积大,响应慢
Qt
1、文本编译器 vim(单体文件编辑,可高度定制)
三种模式 命令行模式 esc
插入模式 a或I
底行模式 命令行模式下 ”:“ wq 保存退出 q!不保存退出
2、编译器 gcc
编译过程:1、预处理 头文件展开,宏定义替换,条件编译 编译选项 -E
2、编译 检查错误,生成汇编文件后缀名.s 编译选项 -s
3.汇编 编译成二进制 后缀名.o 编译选项 -c
4、链接 编译成了执行文件 后缀名.elf .elf特点:
ELF:可执行连接文件格式。
ELF文件优点:
1. 支持不同平台上的交叉编译和交叉链接,可移植性性强
2. 在执行时支持动态链接共享库
一、洪秀全与金田起义(兴起) 1.背景 鸦片战争的失败,进一步加深了清政府的统治危机。随着剥削的加重,统治阶级与劳动群众之间的矛盾日益尖锐。农民的反抗斗争不断在各地发生,大风暴即将来临。
2.准备 洪秀全于1843年创立“拜上帝会”,并和同学冯云山前往广西传教。他们在两年多的时间里,在山区贫苦农民中发展会众两千多人,其中包括杨秀清、萧朝贵、韦昌辉、石达开等骨干。
3.开始一金田起义 (1)时间: 1851年1月11日。
(2)地点: 广西桂平县金田村。
(3)领导人: 洪秀全
(4)政权名称: 建号太平天国,起义军称“太平军”。
4.永安建制 (1)时间: 1851年,攻克永安(位于广西)后
(2)内容: 上图
(3)意义: 太平天国初步建立起政权组织
二、定都天京(逐步进入全盛) 1.定都天京 1852年春,太平军从永安突围北上,先后围困桂林、长沙,攻克武昌。虽然遇云山、萧朝贵在进军途中牺牲,但队伍发展至50万人。1853年春,太平军放弃武昌,分水陆两路,沿长江东下。1853年3月,攻占南京,将南京改名为天京,作为都城。
2.颁布《天朝田亩制度》 颁布时间太平天国定都天京后(1853年)内容规定不分男女,按人口和年龄平均分配土地目标建立“有田同耕,有饭同食,有衣同穿,有钱同使,无处不均匀,无人不饱暖”的理想社会评价进步的革命性:它反映了千百年来农民要求得到土地的强烈愿望,对于发动和鼓舞广大农民起来参加反封建斗争起了积极的作用落后的空想性:绝对的平均主义因带有很大的空想色彩而在实践中难以实施 3.北伐和西征(1853——1856年) (1)开始时间: 1853年
(2)目的: 为了推翻清朝统治和巩固政权
(3)结果 ①北伐军曾逼近天津,最后全军覆没;西征战场则取得大胜利
②经过3年多的征战,太平天国控制了从湖北武昌到江苏镇江的长红沿岸城镇,掌握了安徽、江西、湖北东部和江苏部分地区,军事上进入全盛时期
三、天京陷落(失败) 1.天京事变 原因 定都天京后,太平天国在军事征战和制度建设上取得了重大成就,但领导人开始享乐腐化,争权夺利
概况 1856年秋,杨秀清逼洪秀全封他为“万岁”,意图篡位。结果杨秀清被杀,韦昌辉被处死,石达开率部出走
影响太平军损失惨重,人心士气受到严重影响,太平天国由盛转衰 2.重建领导集团 还是直接上图
3.安庆陷落 1860年,曾国藩的湘军包围安庆。陈玉成和李秀成率部救援失败,安庆陷落。后来,陈玉成被停就义。李秀成率太平军攻克杭州,进逼上海,遭到华尔率领的洋枪队和李鸿章率领的淮军的抵抗和反扑。
4.天京陷落 (1)经过: 1862年,湘军围困天京。李秀成从浙江、上海回师救援。太平军与敌军激战40多天,最终未能解除湘军对天京的威助。1864年夏,洪秀全病逝。湘军轰塌城墙,冲入城内。守城将士与敌人展开巷战,大部分战死,其余突围。
(2)影响: 天京的陷落,标志着轰轰烈烈的太平天国农民运动的失败
四、太平天国运动的评价 1.地位和性质 太平天国起义是中国历史上規模最宏大的一次农民战争(地位)。
2.局限性 由于农民阶级的局限性,太平天国无法提出切合实际的革命纲领,无法制止和克服领导集团的腐败,也无法长期保持领导集团的团结。
3.历史意义 太平天国起义是中国历史上规模最宏大的一次农民战争。它坚持斗争14年,转战大半个中国,沉重地打击了清朝的统治和外国侵略势力,谱写了中国近代史上壮烈的一章,也将农民起义推到了历史的最高峰。
重要提醒 1.太平军在定都天京之前进展顺利的原因: (1)准备充分。洪秀全创立“上帝会”,使组织和发动人民有了统一的思想,发展了大量的会众和重要骨干
(2)适逢其时。鸦片战争的失败,进一步加深了清政府的统治危机。随着剥削的加重,统治阶级与劳动群众之间的矛日益尖锐
(3)策略正确,起义军建号太平天国,昭示了建立平等社会的斗争目标,迎合了当时民众的理想,得到了广泛响应,及时分封诸王,建立领导集团,成为顺利进军的组织保障
(4)战斗力强。太平军将士大多出生贫苦阶层,斗志坚定,军纪严明
(5)清朝腐败不堪,清军缺乏斗志
2.太平天国全盛时期在军事征战和制度设上取得的重大成就: (1)军事征战: 定都天京,北伐、西征后军事上入全盛时期
(2)制度建设: 颁布《天朝田亩制度》
照我这个速度下去感觉要来不及啊……得加快速度了
知识梳理 一、英法再次发动侵略战争(第二次鸦片战争) 1.根本原因 西方列强不满足既得利益,企图进一步打开中国市场,扩大優略权益。
2.借口/导火线 “亚罗号事件”和“马神甫事件”(又称“西林教案”)。
3.国家 英、法两国发动战争(主凶),俄、美两国支持(帮凶)
4.时间 1856-1860年。
5.经过 上张大图
6.《天津条约》和《通商章程善后条约》 (1)《天津条约》(清政府被迫与俄、美、英、法四国分别签订):
项目条约内容危害公使外国公使可以进驻北京政治上控制清政府,获取更多利益通商增开汉口、南京等十处为通商口岸列强侵略势力深入到长江中下游地区。(军舰自由航行还破坏了领土主权)通航外国商船和军舰可以在长江各口岸自由航行 (2)《通商章程善后条约》:
随后,清政府在与英、法、美签订的《通商章善后条约》中,又被迫承认了鸦片贸易的合法化。
二、火烧圆明园与《北京条约》的签订 1.火烧圆明园 (1)背景:《天津条约》并没有使侵略者满足。1860年,英、法两国借口换约受阻,再次出兵占领天津,进必北京。咸丰帝让他的弟弟奕䜣担任议和大臣,留守北京,自己逃往承德避暑山庄。(感觉这个咸丰帝好窝囊的样子)
(2)概况:10月,英法联军对北京西北郊著名的皇家园林一一圆明园进行了大肆抢劫,之后又放火烧毁。
2.签订《北京条约》 英法联军占安定门,控制北京城,并扬言要直捣皇宫。奕䜣被迫与英、法交换了《天津条约》批准书,并签订了中英、中法《北京条约》。《北京条约》内容及危害见下表:
项目内容危害前约有效清政府承认《天津条约》继续有效确保了列强的侵略权益,破坏了中国的主权增开商埠增开天津为商埠列强的势力向北方地区扩展割地割九龙司地方一区给英国进一步破坏了中国领土主权的完整赔款赔款额大幅增加给中国人民带来沉重负担 三、沙侵占中国北方大片领土 1.时间 第二次鸦片战争前后。
2.地域 中国东北和西北部
3.条约 沙俄强迫清政府签订一系列割占领土的不平等条约:
(1)1858年《现珲条约》
(2)1860年《北京条约》
(3)1864年《分西北界约记》
(4)1881年《改订条约》
4.面积 共割占150多万平方千米。
沙俄侵占中国北方领土示意图 四、第二次鸦片战争的影响 第二次鸦片战争使中国丧失更多主权,英国、法国、美国等西方侵略势力由东南沿海一带深入到长江中下游地区,沙俄占领中国北方大片领土。中国的半殖民地化程度进一步加深。
重要提醒 1、第二次鸡片战争是鸦片战争的延续: 项目鸦片战争第二次鸦片战争根本原因打开中国市场,进行殖民主义扩张进一步打开中国市场,扩大侵略权益战争性质非正义的侵略战争侵略国家英国英、法两国(俄美支持)侵略历史两年四年开埠割地五口通商、割香港岛增开十一口通商、割九龙司地方一区给英国侵略范围主要在长江以南沿海地区由东南沿海一带深入到长江中下游地区对中国社会性质的影响丧失完整独立的主权,开始从封建社会变为半殖民地半封建社会丧失更多主权,中国半殖民地化程度进一步加深 2.第二次鸦片战争期间列强的罪行: 英法联军对圆明园进行大肆抢劫,并火烧圆明园(洗劫空前);英国割占九龙司地方一区,沙俄割占了中国东北、西北150多万平方千米领土(割地最多)。
3.沙俄侵占中国北方大片领土的过程: 时间条约名称割占领土范围割占领土面积1858年中俄《瑷珲条约》中国东北外兴安岭以南、黑龙江以北60多万平方千米1860年中俄《北京条约》中国乌苏里江以东(包括库页岛在内)约40多万平方千米 1860年
1864年
中俄《北京条约》
中俄《勘分西北界约记》
中国巴勒喀什池以东、以南44万多平方千米19世纪80年代中俄《改订条约》及以后五个勘界协定书中国西北部一带7万多平方千米 4.总理衙门: 第二次鸦片战争后,为适应形势的变化,清政府于1861年设立了总理各国事务衙门,简称“总理衙门”,它负责办理对外交涉以及通商、海关等事务,是清政府一个权力很大的中枢机构。
5.英、俄觊觎西藏: 1870-1909年,沙俄先后派出13批“考察队”入藏探情报,与当地民众冲突不断。英国为与沙俄争夺势力范围,于1888年和1903年先后两次发动侵略西藏的战争,获取了一些非法权益。
6葡萄牙逐步占据澳门: 1553年,萄牙殖民者攫取了在我国广东澳门的居住权;鸦片战争后,葡萄牙企图夺取对澳门的管辖权,从居留者变为管治者,先后自设立“海外省”(1844年)、宣布澳门为自由港(1845年)葡牙人亚马喇就任澳门总督(1846年)、关闭澳门的中国海关(1849年);为巩国和扩大侵略权益,1887年签订《中葡和好通商条约》,确认萄萄牙“永居管理澳门”的权利使中国失对澳门的管理权。但是,澳门的主权仍属中国。
dict to json import json # json.dumps() 是把python对象转换成json对象的一个过程,生成的是字符串。 s理解为 str # json.dump() 是把python对象转换成json对象生成一个fp的文件流,和文件相关。 dict_1 = {'a': 1, 'b': 2} # {'a': 1, 'b': 2} type(dict_1) --> <class 'dict'> json_1 = json.dumps(dict_1) # {"a": 1, "b": 2} type(json_1) --> <class 'str'> json to dict import json # json.loads() 操作字符串,生成dict # json.laod() 和文件相关 json_2 = '{"c": 3, "d": 4}' # <class 'str'> dict_2 = json.loads(json_2) # {'c': 3, 'd': 4} <class 'dict'> dict to yaml import yaml # pip3 install pyyaml dict_3 = { "
文章目录 前言1.vtp1.1 vtp的工作原理1.2 vtp 域1.3 vtp模式1.4 vtp通告1.4.1 vlan通告概述1.4.2 vtp通告类型 1.5 vtp修剪1.6 vtp 配置实例 总结 前言 在大型的企业网中,交换机的数量非常多,而各个交换机的VLAN配置基本相同,因此,在企业交换网络的配置和管理过程中存在很多重复劳动,而且会由此产生一些配置错误,使网络出现故障。为了方便配置与管理,在单个控制点上管理整个网络,Cisco 公司开发了VTP (VLAN Tunking Protocol.虚拟局域网中继协议),通过使用VTP协议,交换机之间能够互相传递VLAN信息,从而实现了VLAN的统一配置和统一管理。
1.vtp 1.1 vtp的工作原理 VTP是-种消息协议,它使用第二层帧,在交换机之间传递VLAN信息,被称为VTP通告。有了VTP.就可以在一台交换机上集中修改VLAN配置,所做的修改会被自动传播到网络中的其他交换机上,从而实现VLAN配置的一致性。
且实现此功能的前提是这些交换机属于同一个VTP域。
1.2 vtp 域 VTP域也称为VLAN管理域,由一一个以上共享VTP域名的相互连接的交换机组成。也就是说,VTP域是一组VTP域名相同并通过中继链路相互连接的交换机。
要使用VTP.首先必须建立-一个VTP域,在同一管理域中的交换机共享它们的VLAN信息,并且一个交换机只能参加一个VTP域。不同域中的交换机不能共享VTP信息。
下面是VTP域的要求。
➢域内的每台 交换机都必须使用相同的VTP域名,无论是通过配置实现,还是由交换机自动学到。
➢Catalyst交换机必须是相邻的,即相邻的交换机需要具有相同的域名。
➢在所有的Catalyst交换机之间,必须配置为中继链路。
如果上述条件中的任何一项不满足,则VTP域不能连通,信息也就无法跨越分离部分进行传送
1.3 vtp模式 vtp模式决定了交换机处理和通告vtp信息的方式。vtp模式有三种,分别是服务器模式,客户机模式和透明模式。
(1)服务器模式(server)
充当vtp服务器的交换机负责它所在域中vlan信息的管理工作。vtp服务器可以创建,删除或修改vlan,并向外发送vtp通告,同时,vtp服务器也会学习域名相同的vtp通告信息。默认情况下,交换机处于vtp服务器模式。
每个vtp域至少有一个服务器,以便创建,删除或修改vlan及提供vlan信息。
(2)客户机模式(client)
处于此模式的交换机不允许管理员创建,删除或修改vlan。它们监听本域中其他交换机的vtp通告,并相应修改自己的vtp配置
(3)透光模式(transparent)
vtp透光模式中的交换机不参与vtp。当交换机处于透明模式是,它可以创建,删除或修改本地的vlan,但它不向外通告自己的vlan配置信息,对收到的vtp通告只转发而不会学习与更改自己的vlan信息
1.4 vtp通告 1.4.1 vlan通告概述 使用vtp时,加入vtp域的每台交换机在其中继口上通告如下信息
(1)管理域
(2)版本号
(3)配置修改编号
(4)它所知道的vlan
(5)每个已知vlan的某些参数
1.4.2 vtp通告类型 (1)汇总通告:当交换机收到汇总通告时,会进行如下操作
1.如果域名不同,就忽略此通告
2.如果域名相同,则进一步对比配置修改编号
3.如果交换机自身的配置修改编号更高或与之前相等,就忽略此通告。如果更小,就发送通告请求
(2)子集通告
如果在vtp服务器上增加,删除或修改vlan,配置修改编号就会增加,交换机会首先发送汇总通告,然后发送一个或多个子集通告。
子集通告中包括vlan列表和相应的vlan信息。如果有多个vlan,为了通告所有的信息,可能需要发送多个子集通告。
(3)通告请求
交换机在下列情况会发出vtp通告请求
1 交换机重启后
一、Mybatis概述 Mybatis是一款优秀的持久层框架。
支持自定义SQL、存储过程以及高级映射。
免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
可以通过简单的XML或者注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Object,普通老式Java对象)为数据库中的记录。
二、项目构建 Mybatis的依赖需自行在Meven仓库下载。
1.编写Mybatis的核心配置文件
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的,Mybatis核心配置文件就是来用帮助我们构建SqlSessionFactory的。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--【外部资源】 -引入配置连接字段的文件 db.properties --> <properties resource="db.properties"/> <!--【设置】 -添加日志文件,查看执行的SQL语句信息 logImpl = STDOUT_LOGGING (Mybatis自带标准日志功能) logImpl = log4j (自定义日志功能,需要编写log4j.properties配置文件,灵活多变,功能更加强大。) Mybatis官网日志配置 https://mybatis.org/mybatis-3/zh/logging.html -开启驼峰命名自动映射 设置为true,可以将数据库经典下划线命名字段a_name对应实体类以驼峰命名的属性aName。 --> <settings> <!-- <setting name="logImpl" value="log4j"/>--> <setting name="logImpl" value="STDOUT_LOGGING"/> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!--【别名】使用缩写词来代替冗余的类全限定名,仅用于XML文件中。 -typeAlias元素给个别类添加别名 -package元素给指定包下的类添加别名,默认为首字母小写的类名。也可在类的上方添加@Alias注解自定别名。 --> <typeAliases> <!-- <typeAlias alias="
文章目录 **1.Anr的基础知识****2.编写一个Anr的案例****3. 借用 logcat日志和trace文件分析Anr****获取logcat的日志文件****获取Trace.txt 文件** 1.Anr的基础知识 在开发中,遇到anr 的原因会有:
主线程频繁进行耗时的IO操作:如数据库读写多线程操作的死锁,主线程被block;主线程被Binder 对端block;System Server中WatchDog出现ANR;service binder的连接达到上线无法和和System Server通信系统资源已耗尽(管道、CPU、IO) 当发生Anr时,系统会记录以下信息:
各个进程的cpu使用情况cpu的负载IO Waittraces文件。 接下来,通过一个输入事件没有响应的案例来,借用loagcat和trace 文件 分析。
2.编写一个Anr的案例 通过Studio编写以下代码:(来源网络)
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private TextView testText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); Log.d(TAG, "onCreate start"); } @Override protected void onPause() { super.onPause(); try { Log.d(TAG, "onPause 准备sleep9秒"); Thread.sleep(9000); Log.d(TAG, "onPause sleep9秒完成"); } catch (InterruptedException e) { e.
1.首先要配置SSHKey
2.在组内新建一个project,(里面可以设置项目的存储路径以及项目名称)
3.选中上传文件夹右键选择Git Bash Here
4.git设置
5.项目上传
git init git remote add origin git@gitlab.com:mizyy/test1.git(自己的git地址) git add . git commit -m "Initial commit" git push -u origin master
一、对比
java发送Http post请求,一般在java中我们使用 httpcilent 包中的额 HttpPost 类;需要手动设置 setContentType 和 setContentEncoding;
代码书写看起来非常low 如下代码所示,而 spring 提供的 RestTemplate 提供的额方法则看起来就比较高大上一点:
public static String httpPostWithjson(String url, String json) throws IOException { String result = ""; HttpPost httpPost = new HttpPost(url); CloseableHttpClient httpClient = HttpClients.createDefault(); try { BasicResponseHandler handler = new BasicResponseHandler(); StringEntity entity = new StringEntity(json, "utf-8");//解决中文乱码问题 entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); result = httpClient.execute(httpPost, handler); return result; } catch (Exception e) { e.printStackTrace(); } finally { try { httpClient.
使用npm安装依赖包的时候,显示成功了,但是使用 vue -V的时候,总是显示
vue: command not found
包括使用npm安装yarn时
也会显示
Command 'yarn' not found, but can be installed with: sudo apt install cmdtest 如果按照提示进行安装会出现其他问题
网上有攻略增加系统环境变量,实测在ubuntu系统下并没有用。
CSDN和stackoverflow上也没有很多很好的回复。
实际上建立软连接即可。
vue
sudo ln -s /usr/local/node-v10.19.0-linux-x64/bin/vue /usr/bin/vue yarn
sudo ln -s /usr/local/node-v10.19.0-linux-x64/bin/yarn /usr/bin/yarn sudo ln -s /usr/local/node-v10.19.0-linux-x64/bin/yarn /usr/bin/yarn
例子:
6个顶点,10条边,假设U子集中只有一个顶点v1,那么剩下的差集V-U,在所有的顶点中减去v1,在、这5个顶点就在V-U集合中
从u到v有边,有哪几条边?v1到v2的,v1到v3,v1到v4的三条边,其中v1到v3是最小的,这条边的权值是1,即存在权值最小的边,必然包含在最小生成树里头;反过来,我们把权值最小的边包含在最小生成树里头,构造问题就解决了
接下来,详细看MST性质的解释:
n个顶点即V集合,可以分成两个集合,一个是U,已经在生成树上的集合;另一个是V-U
接下来就选权值最小的边
原始论文:https://arxiv.org/pdf/1611.07004.pdf
原始pytorch版本的代码:GitHub - junyanz/pytorch-CycleGAN-and-pix2pix: Image-to-Image Translation in PyTorch
我的复现代码:
pix2pix就是用cGAN(Conditional GAN)实现成对的图像转换。例如下图
具体方法和网络结构 pix2pix与传统的GAN方法有一定区别(读者最好先了解一下传统GAN),它运用了cGAN的方法:
在生成器(G)上,通过随机噪声z和真实图像x生成图像y, 在判别器上与传统的GAN一样;
在loss上,与传统的GAN_Loss不同,pix2pix的loss除了加上了conditional特性,还增加了L1_Loss让目标域的图像更加接近源域的图像:
传统的GAN_Loss: cGAN_Loss: x是指原始图像(上图的左边),y是指目标真实图像(上图的右边),G(x,z)是指根据噪声和原始图像生成的图像(fake);D(x,y)代表通过判别器得到的真实图片是否真实的概率,同理D(x,G(x,z))代表生成的图像是否真实的概率;判别器的最终目的是D(x,y)尽可能的接近于1,判别器的能力越强D(x,y)越大,D(x,G(x,z))越小,1-D(x,G(x,z))越大,因此 越大,这也解释了为什么要 ;生成器的最终目的是使G(x,z)越像真实图片,即D(x,G(x,z))越大,此时1-D(x,G(x,z))越小,同理这也说明了为什么要 再加上L1约束,最终的需要优化的目标函数如下:
网络结构 pix2pix在网络结构上的亮点主要是在生成器上运用了U-net的网络结构,同时加入跳链接(skip connections),第i层与第n-i层直接连接,具体细节可以参考U-net原论文。除此之外,pix2pix还运用了dropout操作。
PatchGAN L1_Loss有利于对于低频信息建模,pix2pix使用L1_Loss作为辅助loss加入总loss中会使生成的图像更加清晰,论文中作者也进行了对比实验:
对于高频信息,作者提出了一种PatchGAN对高频信息进行建模,就是针对同一个图像中不同N*N大小的区域进行真伪鉴别,最后将他们平均值作为输出。N*N的区域可以比整个图像小的多,但是任然能得到高质量的结果。使用PatchGAN能减少参数量,加快训练速度,同时能应用于任意大尺度的图像。经过作者的探索,当N=70时,得到的结果最好。
上述就是pix2pix这篇论文的核心方法以及一些setting,论文中有更加详细的网络结构和PatchGAN的分析,有兴趣可以去阅读原论文。最后附上一些我自己复现的代码训出来的一些例子(代码我就先不放了,后面还会讲一下cycleGAN,到时一起放出来),部分还没训好(太费时了,懒得训了),从左到右:input,label,gen_image
《《《《《正文》》》》》
《前言》
本文主要介绍128x64点阵液晶屏的开发,本文是基于拓普微LM6029AC液晶模块显示屏开发的,兼容12864cog HFG12864-438液晶屏,驱动芯片为ST7565R ;通信串口采用4SPI;
《液晶模块》
首先来区别液晶模块和驱动芯片;
驱动芯片:其实我在《数码管是如何亮起来的?跟液晶屏又有什么关系?》这篇文章提过,因为128x64的com口以及seg口过多,如果使用单片机IO口直接驱动太费IO资源,二来IO口驱动能力也未必够;因此设计一款专门驱动128x64的芯片,这样使用spi等串口由单片机控制来实现对液晶屏的控制;
而液晶屏加驱动芯片以及一些必要的外围电路,留出单片机与驱动芯片的通信口的组合模块我们称为液晶模块;
《开发手册获取》
对于软件开发来讲,我们一般不太需要过多了解驱动芯片的手册,驱动芯片的手册更全面,也因此很多不是软件的知识,当然多了解总没错,往往只需要了解模块的开发手册,其实模块手册往往包含在驱动芯片手册里;只是模块手册写得已经足够软件开发的;
而模块手册,个人觉得只需了解下面几部分:
1、模块对外的接口定义
2、模块的命令
3、通信方式
驱动芯片手册 和 模块手册资源在最后下载;
1)通信方式:一般通信方式会有多种选择,往往通过硬件的IO电平组合来实现,我选择4SPI,需要P/S脚拉低;
对应实际模块需要焊接如下图:
传输时序:
黑色箭头的意思就是SCL由低拉高的时候,传输数据;
2)接口定义:这里唯一需要注意的就是当使用4SPI时,SCL为D6引脚,SI为D7引脚;RES是用来复位操作的,就是拉低一段时间,一般10ms,在驱动手册里有;CS1是片选;RS是控制传输的是命令数据还是显示数据;还有BLA背光控制脚;
3)模块命令:这个一般模块手册有;没有去找驱动手册;这个是总的命令表格,详细的我们在后面开发介绍;
《硬件接口》
使用stm32f103c8t6芯片,引脚接线如下:
《软件开发》
1)开发环境:这个自己解决!可参考以下文章
《STM32F103软件环境搭建(KEIL)》
2)SysTick延时函数:(网上到处都是)
《一文透析SYSTICK的寄存器》参考本文;
void Delay_Init(void);void Delay_us(uint32_t nus);void Delay_ms(uint32_t nms); 3)LCD驱动口初始化函数:
/**********硬件接口:BAL CS1 RST SID SCLK RS PA0 PA3 PA4 PA2 PA1 PA5********************/ /******************************************************************************* 函 数:* 功 能:LCD12864引脚初始化* 参 数:无* 返回值:无* 备 注:无*******************************************************************************/void LCD_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_1|GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStruct.
我们在使用 input 输入框时,大多不希望用户在前后输入空格,有没有简单的校验方法呢,当然是有的。
<el-form :rules="rules" :model="form" label-width="80px"> <el-form-item label="活动名称" prop="name"> <el-input v-model="form.name"></el-input> </el-form-item> </el-form> <script> export default { data() { return { form: { name: '' }, rules: { name: [ { required: true, message: '请输入活动名称', trigger: 'blur'}, { pattern: /^(?!\s+).*(?<!\s)$/, message: '首尾不能为空格', trigger: 'blur' } ] } } } } </script> 效果如下:
对于一般接口测试和开发来说经常需要调试接口,对接口数据拦截修改来查看页面变化。一般会选用Fiddler或Fiddler everwhere来拦截接口调试,Fiddler和Fiddler everwhere都可以拦截电脑的各种应用的请求,Fiddler界面太丑了,而Fiddler everwhere只有30天试用期,所以很不方便。
如果你只想拦截浏览器的请求或修改参数响应,那么一款优秀的拦截url请求的插件你必须拥有:
Requestly: Redirect Url, Modify Headers etc
1.安装 谷歌插件市场搜索:Requestly: Redirect Url, Modify Headers etc 然后直接安装。
如果你的网络无法访问谷歌插件市场,可以百度云下载 :
链接:https://pan.baidu.com/s/1bFwEm4PWtC9vRgo96fR_uw
提取码:2qu6
下载后离线安装请参考:谷歌浏览器(Chrome)如何安装crx插件
2.使用 安装后打开插件点击Open app
打开后界面如下:
翻译成中文:
如果你想自动拦截接口并修改响应返回,可以先起个规则名,要拦截的接口包含的url,以及要返回的响应,最后点击右上角的创建规则就可以了。
你可以在我的规则里管理所有刚才新建的规则,以及控制开关。
如图,在重定向页面时发生了地址循环的现象,错误是重定向次数过多
通过排查,发现是重定向时的url的地址有问题
要注意url地址在写的过程中最前面一定要加上 / 错误代码:response.sendRedirect("smbsm/error.jsp"); 正确代码:response.sendRedirect("/smbsm/error.jsp");
88,n个人围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数, 数到m的人再出圈,……依次类推,
直到所有的人都出圈,请输出依次出圈人的编号.
输入
n m
输出
出圈的编号
样例输入 10 3
样例输出 3 6 9 2 7 1 8 5 10 4
‘’’
n,m=map(int,input().split()) l=[0]*n k=0 count=0 while count !=n: for i in range(n): if l[i]==0: k+=1 if k==m: print (i+1,end=' ') k=0 l[i]=1 count+=1
一、简介 spring-boot-actuator-logview是简单的日志文件查看器作为 Spring Boot 执行器端,允许快速访问 spring-boot web 应用程序日志文件。 二、漏洞复现
项目地址:
链接: https://pan.baidu.com/s/1lm4AZfvLlP-x0GfrdMBKeA 提取码: juq3 下载该项目,并使用idea运行该项目。
打开网页便能查看日志情况
该漏洞存在LogViewEndpoint中,
只对filename进行了检验,并未对base进行检验,
filename检验函数
构造poc如下
http://localhost:8887/manage/log/view?filename=etc/group&base=../../../../../../
页面访问
修复建议
升级到0.2.13版本
在0.2.13版本对base进行了检验。
private void securityCheck(Path base, String filename) {
try {
String canonicalLoggingPath = (filename != null ? new File(base.toFile().toString(), filename) : new File(base.toFile().toString())).getCanonicalPath();
String baseCanonicalPath = (new File(this.loggingPath)).getCanonicalPath();
String errorMessage = "File " + base.toString() + "/" + filename + " may not be located outside base path "
雷达利用多普勒频率来提取目标的径向速度(距离变化率),以及区分运动和静止目标与物体,如杂波。多普勒现象。。。
考虑一个宽度为t脉冲入射到一个以速度v向雷达运动的目标上,如图1.6。定义d为在间隔△t内目标在脉冲内运动的距离(米),即
d=v△t 其中,△t等于脉冲前沿碰到目标到脉冲后沿碰到目标之间的时间。因为脉冲以光速运动,后沿运动的距离为ct-d,所以
Ct=c△t+v△t Ct’=c△t-v△t t’=(c-v)*t/(c+v) 实际上,因子(c-v)/(c+v)通常称为时间膨胀因子。如果v=0,那么t’=t。
为了推到多普勒频率表达式,考虑图1.7所示的图例。脉冲2的前沿花费△t秒的时间走过(c/fr)-d的距离撞到目标。在相同的时间间隔内,脉冲1前沿走过相同的距离c△t。更加准确的表达式如下:
d=v△t C/fr-d=c△t 根据多普勒效应:
Fd=f0’-f0=(c+v)/(c-v)*f0-f0=2v/(c-v)*f0 因为v<<c且c=λf0,所以
Fd=2v/c*f0=2v/λ 上式表明多普勒频率与目标速度成正比,可以从目标距离变化率提取fd,反之亦然。
以上推导都建立在相对于目标的径向速度等于v,但并不是总是如此。实际上,多普勒频移的大小取决于雷达方向上目标的速度分量(径向速度)。因此,考虑到与目标之间的总角度,fd的一般表达式为:
Fd=2v*cosθ/λ 对于远离的目标,有
Fd=-2v*cosθ/λ 其中,cosθ=cose*cosa。角度e和a分别表示俯仰角和方位角。
cdh集群有官方卸载文档链接(博客下方): Uninstalling Cloudera Manager and Managed Software | 6.2.x | Cloudera Documentation
一、ambari-web 页面停服务
进入维护模式,免报警
Host--->All Host-->Hosts-->Turn on Maintance Mode
Dashboard---> Stop all
ambari-web卸载前确保集群所有服务进程已经停止:所有组件,包括ranger以及disable keberos,停止keberos进程
二、后台停止ambari进程
①停止所有主机的ambari-agent:ambari-agent stop ②停止主服务器的ambari-server:ambari-server stop
#!/bin/bash #卸载组件安装包 for i in `rpm -qa|egrep "ambari|hadoop|hdfs|yarn|ranger|hdp|spark|bigtop|smartsense|zookeeper|mapre|sqoop|flume|storm|tez|slider|hcat|pig"`;do rpm -e --nodeps $i;done #检查是否还有组件的安装包 rpm -qa|egrep "ambari|hadoop|hdfs|yarn|ranger|hdp|spark|bigtop|smartsense|zookeeper|mapre|sqoop|flume|storm|tez|slider|hcat|pig" if [ ! $? -eq 0 ]; then echo "卸载安装包完毕" fi #清理yum数据源 yum clean all #删除组件的用户和用户组 for u in sentry phoenix kudu hive zookeeper infra-solr ams tez spark ambari-qa hdfs yarn mapred hbase hcat slider ranger sqoop impala storm flume sqoop2; do sudo userdel $u;done for g in hadoop sentry hive spark phoenix hdfs zookeeper yarn mapred hbase slider ranger ambari-qa sqoop impala storm flume sqoop2 ; do sudo groupdel $g ; done #有些应用卸载时需要与依赖应用一起卸载 #删除安装路径下的相关文件及目录,大部分在卸载的时候已经自动删除 #找到并删除残留文件及目录,全部卸载完成后删除集群数据文件 #delete install_dir。可根据最后的检查组件安装路径语句,通过ansible执行命令,返回文件结果,然后sort加上uniq筛选出需要删除的路径 rm -rf /hadoop rm -rf /etc/ambari-agent rm -rf /etc/ambari-metrics-grafana rm -rf /etc/ambari-metrics-monitor rm -rf /etc/ambari-server rm -rf /etc/ams-hbase rm -rf /etc/hadoop rm -rf /etc/hive rm -rf /etc/hive2 rm -rf /etc/hive-hcatalog rm -rf /etc/hive-webhcat rm -rf /etc/hst rm -rf /etc/pig rm -rf /etc/ranger rm -rf /etc/ranger-admin rm -rf /etc/ranger-kms rm -rf /etc/ranger-tagsync rm -rf /etc/ranger-usersync rm -rf /etc/slider rm -rf /etc/spark2/ rm -rf /etc/sqoop/ rm -rf /etc/storm-slider-client rm -rf /etc/tez rm -rf /etc/tez_hive2 rm -rf /etc/zookeeper rm -rf /var/run/agent_update.
elementUI本身输入框el-input自带了disabled属性,但是当你需要覆盖其样式或者自己写一个自己的my-el-input时,不妨用下面的代码,注意opacity 1表示不透明,cursor:表示滑动过去鼠标为禁止样式
/deep/ input[disabled],input:disabled,input.disabled{ -webkit-text-fill-color:#C0C4CC; background: #F5F7FA; -webkit-opacity:1; opacity: 1; cursor: not-allowed; }
idea启动时不直接打开项目 图片 点击file --》 settings --》 Appearance&Behavior --》System Settings --》Reopen last project on startup
图片
QEMU copy-on-write format with a range of special features, including the ability to take multiple snapshots, smaller images on filesystems that don’t support sparse files, optional AES encryption, and optional zlib compression
现在比较主流的一种虚拟化镜像格式,经过一代的优化,目前qcow2的性能上接近raw裸格式的性能
QCOW2镜像格式是Qemu支持的磁盘镜像格式之一。它可以使用一个文件来表示一个固定大小的块设备。与Raw镜像格式相比,QCOW2具有如下优点:
更小的文件大小,即便不支持holes(稀疏文件)的文件系统同样适用支持写时拷贝(COW, Copy-on-write),QCOW2镜像只反映底层磁盘镜像所做的修改支持快照,QCOW2镜像可以包含镜像历史的多重快照支持基于zlib的数据压缩支持AES加密 qemu-img是管理镜像文件文件最常用的命令,使用方法如下:
# 创建一个名为test.qcow2,大小为4G的qcow2镜像
$ qemu-img create -f qcow2 test.qcow2 4G
# 将QCOW2格式的test.qcow2文件转换成raw格式的test.img文件
$ qemu-img convert test.qcow2 -O raw test.img
QCOW2头
每一个QCOW2文件均以一个大端(big endian)格式的头开始,其格式如下:
typedef struct QCowHeader {
uint32_t magic;
uint32_t version;
uint64_t backing_file_offset;
uint32_t backing_file_size;
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
语法:
Object.assign(target, ...sources) 实例:
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } 如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。
String类型和 Symbol 类型的属性都会被拷贝。
在出现错误的情况下,例如,如果属性不可写,会引发TypeError,如果在引发错误之前添加了任何属性,则可以更改target对象。
注意,Object.assign 不会跳过那些值为 null 或 undefined 的源对象。
function test() { 'use strict'; let obj1 = { a: 0 , b: { c: 0}}; let obj2 = Object.assign({}, obj1); console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj1.a = 1; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} console.
import os import subprocess def json_to_folder(input_json): output_folder = input_json.replace(".","_") cmd = ["labelme_json_to_dataset", input_json, "-o", output_folder] subprocess.call(cmd)
“ 大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。
” 前几天做了个功能,需求是使用利用element ui如何给下拉列表分页,经过网上查找,自己摸索,已经完成,今天来记录一下吧。
实现的效果 image-20211103160459223 当时因为下拉框中的数据过多,所以想到使用分页的方式来实现。
现在来看看具体的实现吧。
准备分页的组件 分页组件的代码是从网上拼凑的,代码如下:
<template> <el-select v-model="childSelectedValue" :filterable="remote" multiple :loading="loading" :remote="remote" :size="size" :remote-method="remoteMethod" :clearable="clearable" @change="handleChange" @clear="handleClear" @focus="handleFocus" :style="{width: '93%'}" :placeholder="placeholder"> <el-option v-for="item in optionSource" :key="item[valueKey]" :label="item[labelKey]" :value="item[valueKey]"> </el-option> <el-pagination small layout="prev, pager, next" @current-change="changeNumber" :hide-on-single-page="true" :page-size="paginationOption.pageSize" :current-page="paginationOption.currentPage" :pager-count="paginationOption.pagerCount" :total="paginationOption.total"> </el-pagination> </el-select> </template> <script> export default { name: 'PaginationSelect', props: { //此参数只是为了父组件实现 v-model指令接受参数用,子组件中无实际意义 // 在子组件中通过监听childSelectedValue值,来触发 input 事件,实现子父组件数据绑定 value:{ type:String, default: '' }, valueKey:{//传入的option数组中,要作为最终选择项的键值名称 type:String }, labelKey:{//传入的option数组中,要作为显示项的键值名称 type:String }, clearable :{//是否支持清除,默认支持 type:Boolean, default:true }, remote:{//是否支持远程搜索,默认支持 type:Boolean, default:false }, size:{//组件尺寸,配置项同select String | medium/small/mini type:String, default:'medium' }, loading:{//远程数据加载状态显示 type:Boolean, default:false }, placeholder :{ type:String, default:'给谁用' }, optionSource:{//下拉框组件数据源 type:Array, required:true }, paginationOption:{//分页配置项 type:Object, default:function () { return { pageSize:5,//每页显示条数 6条刚好 currentPage:1,//当前页 pagerCount:5,//按钮数,超过时会折叠 total:10 //总条数 } } } }, data () { return { childSelectedValue:this.
1.项目分析 2.项目目标 AI的基础应用算法的设计和实现C语言的图形界面程序开发 3.项目准备 VS/VC++(任意版本)easyx图形库(直接双击即可安装)领取素材(图片、音效)传送门 4.创建项目 创建空项目。把素材拷贝到项目目录下 5.画棋盘 画棋盘,播放开局提示、播放背景音乐
#include <graphics.h> //easyx图像库的头文件
#include <windows.h>
#include <mmsystem.h> //播放音乐的头文件
#pragma comment(lib, "winmm.lib")
void init() {
initgraph(897, 895);
loadimage(0, "res/棋盘.jpg");
mciSendString("play res/start.wav", 0, 0, 0);
mciSendString("play res/bg.mp3 repeat", 0, 0, 0);
}
int main(void) {
init();
system("pause");
return 0;
}
6.画棋子 鼠标点击后,在点击位置画棋子
IMAGE chessBlackImg;
IMAGE chessWhiteImg;
const float BLOCK_SIZE = 67.4; // 格子的大小
void init() {
......
loadimage(&chessBlackImg, "res/black.png", BLOCK_SIZE, BLOCK_SIZE, true);
方法一:lsof -i:端口号 用于查看某一端口的占用情况,比如查看9092端口使用情况,lsof -i:9095
可以看到9095端口已经被nginx占用
方法二:netstat -tunlp |grep 端口号,用于查看指定的端口号的进程情况,如查看5050端口的情况,netstat -tunlp | grep 5050
-t (tcp) 仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化为数字
-l 仅列出在Listen(监听)的服务状态
-p 显示建立相关链接的程序名
原文链接:https://blog.csdn.net/wade3015/article/details/90270214
文章目录 0 前言1 网络整体框架2 Patch Merging详解3 W-MSA详解MSA模块计算量W-MSA模块计算量 4 SW-MSA详解5 Relative Position Bias详解6 模型详细配置参数 0 前言 Swin Transformer是2021年微软研究院发表在ICCV上的一篇文章,并且已经获得ICCV 2021 best paper的荣誉称号。Swin Transformer网络是Transformer模型在视觉领域的又一次碰撞。该论文一经发表就已在多项视觉任务中霸榜。该论文是在2021年3月发表的,现在是2021年11月了,根据官方提供的信息可以看到,现在还在COCO数据集的目标检测以及实例分割任务中是第一名(见下图State of the Art表示第一)。
论文名称:Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
原论文地址: https://arxiv.org/abs/2103.14030
官方开源代码地址:https://github.com/microsoft/Swin-Transformer
Pytorch实现代码: pytorch_classification/swin_transformer
Tensorflow2实现代码:tensorflow_classification/swin_transformer
不想看文章的可以看下我在bilibili上讲的视频: https://www.bilibili.com/video/BV1pL4y1v7jC
1 网络整体框架 在正文开始之前,先来简单对比下Swin Transformer和之前的Vision Transformer(如果不了解Vision Transformer的建议先去看下我之前的文章)。下图是Swin Transformer文章中给出的图1,左边是本文要讲的Swin Transformer,右边边是之前讲的Vision Transformer。通过对比至少可以看出两点不同:
Swin Transformer使用了类似卷积神经网络中的层次化构建方法(Hierarchical feature maps),比如特征图尺寸中有对图像下采样4倍的,8倍的以及16倍的,这样的backbone有助于在此基础上构建目标检测,实例分割等任务。而在之前的Vision Transformer中是一开始就直接下采样16倍,后面的特征图也是维持这个下采样率不变。在Swin Transformer中使用了Windows Multi-Head Self-Attention(W-MSA)的概念,比如在下图的4倍下采样和8倍下采样中,将特征图划分成了多个不相交的区域(Window),并且Multi-Head Self-Attention只在每个窗口(Window)内进行。相对于Vision Transformer中直接对整个(Global)特征图进行Multi-Head Self-Attention,这样做的目的是能够减少计算量的,尤其是在浅层特征图很大的时候。这样做虽然减少了计算量但也会隔绝不同窗口之间的信息传递,所以在论文中作者又提出了 Shifted Windows Multi-Head Self-Attention(SW-MSA)的概念,通过此方法能够让信息在相邻的窗口中进行传递,后面会细讲。 接下来,简单看下原论文中给出的关于Swin Transformer(Swin-T)网络的架构图。通过图(a)可以看出整个框架的基本流程如下:
首先将图片输入到Patch Partition模块中进行分块,即每4x4相邻的像素为一个Patch,然后在channel方向展平(flatten)。假设输入的是RGB三通道图片,那么每个patch就有4x4=16个像素,然后每个像素有R、G、B三个值所以展平后是16x3=48,所以通过Patch Partition后图像shape由 [H, W, 3]变成了 [H/4, W/4, 48]。然后在通过Linear Embeding层对每个像素的channel数据做线性变换,由48变成C,即图像shape再由 [H/4, W/4, 48]变成了 [H/4, W/4, C]。其实在源码中Patch Partition和Linear Embeding就是直接通过一个卷积层实现的,和之前Vision Transformer中讲的 Embedding层结构一模一样。
手把手教你solidworks保留镜向零件删除原零件## ` 在设计过程中有些零件往往是对称的,如果画完一个零件后,再出个对称零件,如果是简单零件还好,但如果零件比较复杂,再出张图就显得浪费时间得不偿失了。我们可以通过镜向以及保留/删除命令,提高效率。接下来,我说说具体步骤。
1.首先打开一张零件。
2.建立一张基准面后,点击镜向命令。在出现的页面中,选择要镜向的实体,同时把合并实体选项的勾去掉。
3.要镜向的实体选择当前的零件。然后点击勾,即可。如下图所示,出现了对称的两个零件。
4.点击插入菜单下的特征选项,在特征右侧选择删除/保留实体选项。如下图所示。在出现的对话框中类型选择删除实体,要删除的实体选择原零件,然后点击勾即可。如下图所示,留下了与原零件对成的零件。
下面标签嵌套正确的是
A.ul只能紧挨着li
B.a中不能再嵌套a
C.dl dt
D.ol li是有序排列下面哪些是HTML5 新增的表单元素?
在HTML中,( )可以在网页上通过链接直接打开邮件客户端发送邮件。
mailto 后面加发送邮件地址请选出所有的置换元素()
a) 置换元素:浏览器根据元素的标签和属性,来决定元素的具体显示内容。
例如:浏览器会根据标签的src属性的 值来读取图片信息并显示出来,而如果查看(x)html代码,则看不到图片的实际内容;标签的type属性来决定是显示输入 框,还是单选按钮等。 (x)html中 的、、、、 都是置换元素。这些元素往往没有实际的内容,即是一个空元素。
置换元素在其显示中生成了框,这也就是有的内联元素能够设置宽高的原因。
b) 不可替换元素:(x)html 的大多数元素是不可替换元素,即其内容直接表现给用户端(如浏览器)。
例如: label中的内容 标签是一个非置换元素,文字label中的内容”将全被显示。下面哪条声明能固定背景图片()
下列说法正确的是()
以下关于盒子模型描述正确的是:
下面哪个属性不会让 div 脱离文档流(normal flow)?
英文字母全部转为大写正确的是()
假设在今日头条里面,有很多工作人员检查新闻是不是属于虚假新闻,所有新闻真实率到达了98%,工作人员在检验一个真实的新闻把它检验为一个虚假的新闻的概率为2%,而一个虚假的新闻被检验为真实的新闻的概率为5%.那么,一个被检验为真实的新闻确实是真实的新闻的概率是多大? 现在有两堆石子,小今与小条玩游戏,2个人都足够聪明,两个人规定:每次每人只能从其中一堆中取走1个或2个或3个石子,后将石子全部取完的人胜利。现在两堆石子的个数为8和9,请问如何安排才能让小今必胜?
以下描述正确的: 13. 表toutiao_tb
查询title中包含cv且type是1的记录
下列关于操作系统进程与线程的区别正确的是:
下面那个页面调度算法,当进程分配到的页面数增加时,缺页中断的次数可能增加也可能减少
下列排序算法不稳定的有? 不稳定:快选堆希
稳 定:插冒归基
运行以下程序
y和z的最终结果为:
这段代码运行后的输出是:
页面有一个id为 button1的按钮,如何通过原生的js禁用?(IE 考虑IE 8.0以上版本)
页面有一个id为 button1的按钮,通过原生的js设置背景色为红色?
现在有一个字符串,你要对这个字符串进行 n 次操作,每次操作给出两个数字:(p, l) 表示当前字符串中从下标为 p 的字符开始的长度为 l 的一个子串。你要将这个子串左右翻转后插在这个子串原来位置的正后方,求最后得到的字符串是什么。字符串的下标是从 0 开始的,你可以从样例中得到更多信息。 var line = readline(); var n = readline(); for(var i=0;i<n;i++){ var line2 = readline().
今天给大家分享一个利用python写的简单小游戏程序。猜词语。
下面看代码段
import time num = int(input('有多少组玩家\n')) guessWord = [] correct = [] #定义列表,num+10是不想让guessWord下标不合法 for i in range(0,num+10): guessWord.append(0) correct.append(0) wordNum=10 guessWord[0] = ['打情骂俏','海绵宝宝','娇媚','金鸡独立','狼吞虎咽','睡眼朦胧','鹤立鸡群','手舞足蹈','卓别林','穿越火线'] guessWord[1] = ['眉飞色舞','英雄联盟','扭秧歌','偷看美女','大摇大摆','回眸一笑','市场营销','大眼瞪小眼','自恋','处女座'] guessWord[2] = ['狗急跳墙','捧腹大笑','目不转睛','愁眉苦脸','左顾右盼','宫保鸡丁','升国旗','暗恋','臭袜子','趁火打劫'] flag='n ' for i in range(0,num): start = time.time() for k in range(0,wordNum): #显示词语 print (('%d.%s')%(k+1,guessWord[i][k])) flag = input('请答题,答对请输入y,跳过请输入任意键') end = time.time() #计算两个时间点之间的间隔 sec = end-start #统计用时 if (110<=sec<=120): print ('还有10秒钟') if (sec>=120): print ('时间到!游戏结束') break if (flag=='y'): correct[i]=correct[i]+1 continue else: continue str_temp=('第%d组答对数目:%d') % (i+1,correct[i]) print (str_temp) 看一下运行效果
实测有效
#include<io.h> void getFiles(std::string path, std::vector<std::string>& files) { //文件句柄 long long hFile = 0; //文件信息 struct _finddata_t fileinfo; std::string p; if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) { do { //如果是目录,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) getFiles(p.assign(path).append("\\").append(fileinfo.name), files); } else { files.push_back(p.assign(path).append("\\").append(fileinfo.name)); } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } } std::string filePath = ""; std::vector<std::string> files; getFiles(filePath, files); for (int i = 0; i < files.
Openvswitch,顾名思义,Open,开源的,v,virtual,虚拟的,switch交换机。
通俗的讲就是一款开源的软件,可以创建虚拟的交换机。
为啥需要个虚拟的交换机呢?
这还要从一个概念SDN说起,全称Software Defined Network,软件定义网络。
软件定义有啥好处呢?
想象你有一个大的数据中心,里面有很多的网络设备,光交换机就有很多,你希望在交换机上配置一些网络的策略,例如某个口应该属于某个VLAN。
怎么配置呢?登到这台交换机上去,敲几行命令就搞定了。
如果要配置100台交换机呢?头大了吧,难不成登陆100台?
想不想有一个集中的地方,能看到整个网络的拓扑图,统一配置一下,然后一回车,配置的策略就通过管理网络平面下发到100台交换机上。
这样整个网络的拓扑结构就不是硬的了,也即不是通过插线,拔线,登陆盒子配置的,而是变成了软的,也即通过软件统一控制,这个统一控制的地方我们称为SDN Controller控制器,这样的网络拓扑结构,我们称为软件定义的网络。
控制器控制网络设备的协议是啥呢?对于硬件设备来讲,由于利益纠葛,大家谁也不肯完全统一协议,所以各家用各家的。
但是还是有了一个子集的协议OpenFlow,虽然功能不如各家的协议强大,总算达成了部分共识。
OpenFlow的架构如图所示,和SDN的定义是一样的,要求交换机支持OpenFlow的协议。
有些物理的交换机是遵守这个协议的,将物理机连接起来。
也有些虚拟的交换机是遵守这个协议的,可以将虚拟机连接起来。
因为有了虚拟机,虚拟机的创建,删除,迁移比物理机灵活的多,所以很难像物理的交换机一样,用网线将交换机和物理机连接起来,就不怎么变了。虚拟机就不一样了,所以需要虚拟交换机,也即通过软件模拟一个交换机,用软件模拟一根网线,一头插在虚拟机上,一头插在虚拟交换机上,一会儿创建五个虚拟机,要插到一个交换机上,一会儿其中两个虚拟机迁移到了另外的物理机上,则他们两个的网口要从上一台交换机上拔下来,插到新的虚拟交换机上,这样做没有问题,因为都是软件实现的,很灵活。
Openvswitch就是虚拟交换机的一种实现。
在一台Linux机器上安装了Openvswitch之后,就可以用手机号转让命令行不费吹灰之力创建虚拟交换机了。
ovs-vsctl add-br ubuntu_br
一个虚拟交换机就创建出来了,名字叫ubuntu_br,不信你ifconfig就能看到了。
ip link add first_br type veth peer name first_if
ip link add second_br type veth peer name second_if
ip link add third_br type veth peer name third_if
创建三根虚拟的网线,一头叫first_br,second_br和third_br,对应的另一头叫first_if, second_if和third_if。
ovs-vsctl add-port ubuntu_br first_br
ovs-vsctl add-port ubuntu_br second_br
ovs-vsctl add-port ubuntu_br third_br
将三根网线的一头插到虚拟交换机上,就形成了下面的图
看你不用买硬件,就能创建复杂的网络拓扑图。
例如你想做TCP/IP详解里面如此复杂的图,本来你应该有一个实验室的,但是用Openvswitch和容器,就能够很容易的模拟了。
我是前端工程师,因为用了很多浏览器默认起始页,要么广告太多,要么呆板无趣,都满足不了我对美观和实用兼顾的需求,所以就自己动手做了一个。前后我一个人从设计产品到前后端开发连着熬夜肝了一个多月上架了这个iTab新标签页,没想到意外收获了非常多用户喜欢,稳定版上线10天下载就超四千。说实话,我完全没想到会有这么多人跟我一样,苦浏览器起始页不好用久矣。
也许你在用Infinity new tab,但我还是建议你快速浏览一下 iTab标签页web版,你不会后悔的。
iTab标签页是什么? iTab标签页是一款浏览器插件。支持CHROME,EDEG, BING, FIREFOX。这个标签页除了具备基本的搜索,常用网站图标,书签等功能外,还可以更换壁纸,重新设置图标样式,图标分组,多端同步,快速翻译,深色模式等等功能。是一个将美观和实用完美结合的产品。
有什么亮点? 1. iOS卡片式小组件应用 iTab标签页是目前市面上第一个将ios小组件设计运用在桌面浏览器标签页中的产品。内置了翻译/天气/书签/万年历/备忘录/壁纸/一言/IP查询/每日热点/待办事项/音乐播放器等原创应用。这些轻量级应用基本覆盖了常用的小工具,使用起来非常方便。比如翻译功能,只要你在搜索框输入,下拉框会自动联想翻译,点击即可翻译。不用再额外下载或搜索在线翻译工具了。
2. 简洁优美无广告 产品设计秉持极简主义,追求纯净无干扰的用户体验。没有花里胡哨的广告,没有你不需要关注的八卦新闻,在电脑前你只需要专注于你自己的世界。
3. 极简模式 极简模式下,只有一张你喜欢的壁纸和一个搜索框,没有任何多余的信息干扰。你只需要完全沉浸在你的工作里,或者你的网络世界里。
4. 高度自由化的自定义 搜索引擎可以一键切换,搜索框大小和颜色可以自己调,图标大小和样式可以调,图标可以自由拖动,可以无限切换壁纸和设置毛玻璃效果,可以将图标按照功能或使用场景分组,界面布局样式可以自己设置。
5. 深色模式和跟随系统 iTab标签页有深色和浅色两种模式,并且也可以选择跟随浏览器的规则变化。深色模式可以带来更强的沉浸感。
6. 账号多端同步 目前支持新浪微博和GitHub第三方登录和邮箱登录。只要注册并登录账号,在标签页内所做的改动,备忘录的文本,壁纸等都可以同步给服务器。这样不管公司电脑还是家里电脑都可以使用,不担心数据丢失。
7. 适配移动端 移动端也可以使用,而且移动端的标签页看起来更整洁优美。只不过因为手机上界面太小,所以不支持移动端图标自定义。界面效果可以看下图:
有什么使用价值? 1. 界面看着赏心悦目 iTab标签页在卡片设计风格,配色和壁纸三个方面让你的标签页变成一种美和赏心悦目的存在。
2. 方便管理信息 iTab标签页支持添加图标,将常用图标从网站库中一键添加;同时支持图标分组,比如可以根据场景分成上班和娱乐,一键切换。
3. 集中注意力,高效办公 全界面没有一个广告和多余信息干扰,可以为你节省多少时间啊
4. 多端使用,信息无丢失 多端数据同步,不担心更换设备数据丢失。
如何安装iTab标签页? 目前支持Chrome,Edge, Bing和Firefox,可以直接从商店下载。但国内百度,360,QQ和猎豹浏览器暂时只能安装离线版或从网页版访问。可以从官方网站下载。
写在最后 以前我都是面向B端开发,很少跟用户直接接触。现在我可以直接听到用户的声音。这种感觉实在太棒啦!你们的肯定和鼓励让我充满了继续开发的动力,管他赚不赚钱,喜欢就干!
做标签页的很多,最知名的Infinity已经做了十年,但我还是试图从另一个角度去创造更符合现在办公场景的产品。希望这次自我挑战能够走的远一些。
上一篇最后说道默认打印级别是info,这一篇我们就来讲解如何修改这个打印级别。
dlt-daemon 设置初始应用程序日志级别 有一个配置参数(参见 /etc/dlt.conf)ContextLogLevel。当新应用程序在守护程序中注册自己时,守护程序会将应用程序的日志级别设置为参数定义的值。
当应用程序使用 DLT_REGISTER_CONTEXT() 或 dlt_register_context() 注册自己时会发生这种情况。
环境变量 DLT_INITIAL_LOG_LEVEL
有一个名为 DLT_INITIAL_LOG_LEVEL 的环境变量。它允许设置每个应用程序上下文的日志级别。有关更多详细信息,请参阅初始日志级别。
应用程序在具有自定义日志级别的守护进程中注册自己。
当应用程序使用 DLT_REGISTER_CONTEXT_LL_TS() 或 dlt_register_context_ll_ts() 注册自己时会定义自己的打印级别。
客户端(例如 dlt_viewer)在运行时更改特定应用程序上下文的日志级别。
上下文的初始日志级别由上述几种方法之一设置。
DLT 库运行时配置 通过设置不同的环境变量,可以在运行时配置 DLT 库——全局或针对特定进程。下面描述了这些环境变量:
初始日志级别 DLT 用户库的默认日志级别为 DLT_LOG_INFO(使用宏 DLT_REGISTER_CONTEXT 或 dlt_register_context() api 时)。这可以使用 DLT 客户端应用程序(例如 DLT Viewer)进行更改。但在 DLT 守护程序更新用户库之前,可能存在需要 DEBUG 或 VERBOSE 消息的情况。
在 DLT 库启动阶段有多种方法可以初始化日志级别。
可以通过导出环境变量 DLT_INITIAL_LOG_LEVEL 来做到这一点。通过这种方式,用户可以为上下文指定日志级别。
例如,应用程序“EXA1”具有两个上下文“CON1”和“CON2”。对于“CON1”日志级别 DEBUG 和“CON2”日志级别 VERBOSE 应使用。必须导出以下内容以配置库:
export DLT_INITIAL_LOG_LEVEL="EXA1:CON1:5;EXA1:CON2:6" 如果所有应用程序和上下文的日志级别都应该被初始化,那么:
导出 DLT_INITIAL_LOG_LEVEL="::2"
如果应初始化应用程序“EXA1”的所有上下文的日志级别,则:
导出 DLT_INITIAL_LOG_LEVEL="EXA1::2"
如果应初始化上下文“CON1”的日志级别,则:
导出 DLT_INITIAL_LOG_LEVEL="
DLT 示例应用 要在应用程序中使用 DLT,它必须链接到 DLT 库。在系统上安装 DLT 守护程序后,将有一个名为 libdlt.so 的共享库,它为应用程序提供接口以获取与 DLT 守护程序的连接。在使用共享 dlt 库构建程序之前,必须在构建环境中设置库路径和包含路径。默认情况下,头文件“dlt.h”位于标准包含目录中名为“dlt/”的目录中。
此示例通过使用最少的代码示例概述了应用程序内部的 DLT 使用情况。
#include <dlt/dlt.h> DLT_DECLARE_CONTEXT(ctx); /* declare context */ int main() { DLT_REGISTER_APP("TAPP", "Test Application for Logging"); DLT_REGISTER_CONTEXT(ctx, "TES1", "Test Context for Logging"); /* … */ DLT_LOG(ctx, DLT_LOG_ERROR, DLT_CSTRING("This is an error")); /* … */ DLT_UNREGISTER_CONTEXT(ctx); DLT_UNREGISTER_APP(); return 0; } DLT 非常易于使用。开发人员必须做的第一件事是包含 dlt 头文件。可以使用下一行中显示的宏静态声明 DLT 上下文。首先,必须在主函数内注册一个 DLT 应用程序。为此,必须指定应用程序标识符 APID 和应用程序描述。之后,可以指定一个或多个 DLT 上下文。要以详细模式记录消息,可以使用 DLT_LOG 宏。作为参数,必须指定日志上下文、日志级别和参数变量列表。 DLT 要求使用 DLT 类型宏对每个参数进行强类型化。在本例中,DLT_CSTRING 用于指定一个常量字符串。在应用程序清理时,所有 DLT 上下文以及 DLT 应用程序都必须注销。
在使用GPU进行雪花制作的时候,雪花总是在镜头旋转的时候,一会有,一会无的情况。
问题在于要给粒子加上边界,具体解决方法如下图:
一:使用Canvas时 EventSystem(系统事件)会和Canvas一起出现
1.Screen Space - Overlay(屏幕空间-覆盖)
这种渲染模式表示 Canvas 下的所有的 UI 控件永远位于屏幕的前面 , 不管有没有相机 , UI元素永远在屏幕最前面 ,主要是2D效果。类似手机膜贴在手机屏幕的最上面,若是屏幕尺寸或屏幕分辨率发生变化,Canvas也会自动和当前屏幕尺寸相适应,这也就很好的解决了屏幕自适应问题。
2. Screen Space - Camera(摄像机空间)
这种渲染模式 Canvas 和 摄像机之间有一定的距离 , 可以在摄像机和 Canvas 之间播放一些粒子特效,主要是3D效果。利用这种渲染模式时需要设定一个摄像机并将其绑定到Canvas组件下的Rander Camera处,改变Camera则UI元素的渲染效果也会发生变化。
plus:
勾选"Pixel Perfect",在Canvas中的模糊效果消失,变得相对清晰。
3. World Space(世界空间)
这种模式下 Canvas 就和普通的 3D 物体一样了 , 可以控制它的大小,旋转,缩放等 。这种渲染模式使得UI元素和3D世界中的物体产生遮挡效果。 一般用来做血条。
Constant Pixer Size —— 恒定像素
这种模式下 UI以像素为大小,同样的像素在不同的分辨率下尺寸不一样 Scale With Screen Size —— 屏幕尺寸比例
这种缩放模式下的UI位置是根据屏幕的分辨率和设置的宽高比来调整UI的位置的,通常做屏幕UI自适应的时候都需要调整到这个缩放模式下。 Constant Physical Size —— 恒定尺寸
这种模式下 UI以像素为大小,在不同的分辨率下尺寸不一样
Graphic Raycaster:控制是否让UI响应射线点击 EventStystem 二:Text
AF_UNIX和AF_LOCAL意义相同。AF_UNIX的socket,与AF_INET的socket类比,有以下不同: SOCK_DGRAM类型的数据传输也是可靠的。客户端socket在没有绑定的情况下,如果做connect和sendto操作,不会自动绑定地址。 除了以上不同,使用socketpair和socket接口的调用类似。 SOCK_STREAM server同时支持多连接。
[localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 [localhost-startStop-1] liquibase.lockservice.null Waiting for changelog lock.... [localhost-startStop-1] liquibase.lockservice.null Waiting for changelog lock.... [localhost-startStop-1] liquibase.lockservice.null Waiting for changelog lock.... 严重 [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start: org.apache.catalina.LifecycleException: 无法启动组件[StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] tomcat在启动过程中出现了锁
数据库被锁住,无法正常访问页面
运行SELECT * FROM DATABASECHANGELOGLOCK;
解锁,locked=0, lockgranted=null, lockedby=null
重新启动tomcat
SELECT * FROM DATABASECHANGELOGLOCK; UPDATE DATABASECHANGELOGLOCK SET locked=0, lockgranted=null, lockedby=null WHERE id=1
实验四 Java Web编程 一.实验目的
1.掌握Java Web服务器Tomcat的安装、配置。
2.学会简单的HTML表单设计,表单提交。
3.掌握JSP中的request对象、session对象的使用。
二.实验内容
1.下载安装Tomcat8,对其进行配置。启动Tomcat服务器,在浏览器输入 http://127.0.0.1:8080/,查看浏览器输出界面;
2. 定制配置:
(1)修改Tomcat的服务端口为88(默认安装为8080);
(2)修改HTTP GET方式的字符编码为UTF-8(默认为ISO-8859-1);
3.编写一个用户注册模块,功能如下:
(1)设计用户注册表单页面register.jsp,包含:用户名(文本框)、密码(密码框)、性别(下拉框);
(2)设计用户注册数据保存页面doRegister.jsp,用以保存用户数据至user.txt文件。
user.txt中每行保存一个用户,格式为:“用户名,密码,性别”;
(3)如果user.txt已包含同名的用户,提示用户已存在;否则提示注册成功。
4.编写用户登录模块,功能如下:
(1)设计用户登录表单页面login.jsp,包含:用户名(文本框)、密码(密码框);
(2)设计登录验证文件doLogin.jsp,获取客户端提交的用户名、密码,然后从user.txt中验证是否存在该用户,登录密码是否正确;
(3)将登录验证结果反馈给用户。
三.思考题(本文章讲的)
1. 对整个实验进行总结,写出实验心得;
2. 学有余力的同学,将实验中注册、登录功能的数据源user.txt换成数据库的user表(自行设计字段),采用JDBC访问数据库; 前期工作 首先安装Apache Tomcat 8以上的版本并启动本地服务器
当然jsp页面不一定要Eclipse那些IDE才可以启动,其实可以记事本启动的
具体的应该是http://localhost:配置文件里的端口,一般是8080/需要访问的jsp的目录+名字
比如说http://localhost:88/test/1.jsp,指的是tomcat中test文件夹下的1.jsp文件
安装教程:
Tomcat安装及配置教程 - 全栈开发者社区 - 博客园
我选用的是Eclipse IDE for java developers,想在里面创建web项目需要先下载对应的插件,教程:
Eclipse下找不到“新建Web项目”_tangju7086的博客-CSDN博客_eclipse没有web
数据库选用的是MySQL 8.0.25版本,安装教程:
超详细MySQL安装及基本使用教程_bobo553443的博客-CSDN博客_mysql安装教程
这里不建议大家使用命令行操作数据库,可以选择下载Mysql Workbench,安装教程:
MySQL Workbench使用教程
注意:如果想要在web项目中使用MySQL,那么一定不要忘了把mysql的驱动jar包重新放置在Tomcat的lib目录下面,否则会疯狂报错;
还有,现在版本的mysql驱动名字已经变成了“com.mysql.cj.jdbc.Driver”,不是以前的“com.mysql.jdbc.Driver”,这里尤其要注意!
mysql-connector-java各种版本下载地址_Bruce_Json的博客-CSDN博客_mysql-connector-java
随后在mysql中创建名为user1的数据库,包含一个user表:
使用MySQL Workbench建立数据库,建立新的表,向表中添加数据 - 星朝 - 博客园
java配置文件读取教程:
Java Properties 类 | 菜鸟教程
实例需求:待处理字符串如下,需要提取其中包含“电子”的部分,即:电子计算机、微型电子管、新创电子
-电脑-电脑硬盘-电子计算机-晶体管-微型电子管-新创电子-
示例代码如下。
Sub Demo1() Dim strWord As String Dim objRegExp As Object, objMH As Object Set objRegExp = CreateObject("VBSCRIPT.REGEXP") strWord = "-电脑-电脑硬盘-电子计算机-晶体管-微型电子管-新创电子-" With objRegExp .Global = True .ignoreCase = True .Pattern = "[一-龥]*电子[一-龥]*" Set objMatch = .Execute(strWord) If objMatch.Count > 0 Then For Each objMH In objMatch Debug.Print objMH Next End If End With Set objRegExp = Nothing End Sub 运行代码结果如下。
电子计算机
微型电子管
新创电子
【代码解析】
第4行代码创建正则表达式对象。
第5行代码设置字符串变量,从A1单元格读取文本。
第8行代码设置正则匹配忽略大小写。
写在前面 几乎在所有的前端UI中,Table组件都有着不可或缺的作用,Table组件对于数据展示,有着天然的优势。
Ant-Design官网上,对于Table组件,有着非常详细的API和Demo,比如自带可编辑单元格、可编辑行功能,是其他部分UI中所没有的。但是对于Table组件数据为空时的渲染样式,却没有直接的文档说明。本人之前从事Vue+ElementUI进行开发,ElementUI中Table组件,可以直接通过empty-text属性,或者slot="empty"进行配置。效果如下图:
ConfigProvider全局化配置 关于ConfigProvider组件,官方API文档链接在此:ConfigProvider API。
Ant Design官网对ConfigProvider的解释是:
为组件提供统一的全局化配置。
ConfigProvider 使用 React 的 context 特性,只需在应用外围包裹一次即可全局生效。
比如ConfigProvider提供了autoInsertSpaceInButton参数,可以全局移除按钮中2个汉字之间的空格;提供了参数componentSize,可以配置全局ant design组件大小。当然还包括其他一系列参数可以对全局进行配置。
众多参数中,其中一个参数是renderEmpty,可以自定义组件空状态,类型为function(componentName: string): ReactNode,只需要将Table组件外面包一层ConfigProvider,并设置renderEmpty参数,即可实现Table组件的空状态。实例代码如下:
renderEmpty = () => ( <Empty imageStyle={{ height: 60, }} description={ <span> 未添加明细 </span> } > <Button type='primary' onClick={() => data.push({id: 123, field: 'aaa', fieldName: 'aaaaaa'})}>添加</Button> </Empty> ) render() { return ( <Form ref={this.formRef} initialValues={this.state.editRow} component={false}> <ConfigProvider renderEmpty={this.renderEmpty}> <Table rowKey={record => record.id} components={{ body: { cell: EditableCell, }, }} bordered dataSource={data} columns={this.
Java 基础学习 第六章 方法
带团子宝贝的时间,较为忙碌,也是懒惰了,没那么自律,抽点玩耍的时间学习吧。
文章目录 Java 基础学习前言一、 方法1. 方法概述2. 方法的定义和调用1. 无参数方法定义和调用:2. 带参数方法定义和调用:3. 形参和实参:4. 带返回值方法定义和调用5. 方法的注意事项6. 方法的通用格式 2. 方法重载 前言 毕业到工作,没有系统的对知识进行过整理与记录,许多知识认识自己,自己却感到陌生了,学而不思则罔,所以还是决定对知识进行一个系统化的整理。
提示:以下是本篇文章正文内容
一、 方法 1. 方法概述 理解:方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集
注意:
a. 方法必须先创建才可以使用,该过程称为方法定义;
b. 方法创建后并不是直接可以运行的,需要手动使用后,才执
2. 方法的定义和调用 1. 无参数方法定义和调用: 定义格式:public static void 方法名 ( ) { // 方法体; } 范例:public static void method ( ) { // 方法体; } 调用范例:method(); 注意:方法必须先定义,后调用,否则程序将报错 2. 带参数方法定义和调用: 定义格式:public static void 方法名 (参数1) { 方法体; } public static void 方法名 (参数1, 参数2, 参数3.
occview窗口类继承于Qwideget,用过Qt的QGraphicsview和Scene视图-场景架构的可以将occview窗口类看作是view和Scene的结合体。对3D环境中视图的平移、旋转、放缩等等全是通过occview类的鼠标事件实现的;而且生成的3D图元都是经过occview的交互式上下文来显示。下面是occview窗口类的代码。
一.h文件
#ifndef OCCVIEW_H #define OCCVIEW_H #include <QWidget> #include <QWidget> #include<QDebug> #include<QVector> #include<AIS_InteractiveContext.hxx> #include<OpenGl_GraphicDriver.hxx> #include<V3d_View.hxx> #include<V3d_Viewer.hxx> #include<WNT_Window.hxx> #include<Quantity_NameOfColor.hxx> #include<gp_Pnt2d.hxx> #include<QpointF> #include<TopoDS_Shape.hxx> #include<ProjLib.hxx> #include<ElSLib.hxx> #include <AIS_Manipulator.hxx> #include<TopoDS_Face.hxx> #include<BRepBuilderAPI_MakeFace.hxx> #include<AIS_Shape.hxx> namespace Ui { class OccView; } class OccView : public QWidget { Q_OBJECT public: explicit OccView(QWidget *parent = 0); QPaintEngine *paintEngine() const; ~OccView(); Handle(V3d_View) m_view; private: Ui::OccView *ui; private: Handle(AIS_InteractiveContext) m_context; Handle(V3d_Viewer) m_viewer; Handle(Graphic3d_GraphicDriver) m_graphic_driver; protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); }; #endif // OCCVIEW_H 二.