javaweb->tomcat个人部署错误及总结

目录 1.在浏览器中按F12可以看见post的元素啥玩意 2.要启动tomcat上的网页得跳到这个页面 3.关于8080端口 4.还需要把你的那个web1包部署到服务器 5.应用程序上下文可以改 7.关于上下文进入 8.SDK个人理解就是JDK版本 9.小心这个问题,IDEA自动提示项目结构报错和一键调整 10.lib的部署 1.在浏览器中按F12可以看见post的元素啥玩意 具体过程:F12-》网络 2.要启动tomcat上的网页得跳到这个页面 然后选url 在启动 3.关于8080端口 必须要8080端口才可以tomcat传requeset 则需要把工件模块加进去,才能URL改成8080成功访问 4.还需要把你的那个web1包部署到服务器 5.应用程序上下文可以改 这玩意就是出现在网址URL中的哪个 7.关于上下文进入 进入方式:我推荐手动修改 当我把应用程序上下文改为/ Localhost:8080/是index Localhost:8080/add.html是add.html 8.SDK个人理解就是JDK版本 SDK是编程语言提供的库 9.小心这个问题,IDEA自动提示项目结构报错和一键调整 10.lib的部署 工件部署artifacts下的Web-INF应该有lib文件夹 lib的jar包也要部署到工件里面 就是说工件要部署到tomcat,然后你的jar包啥也得提前放到工件里面 要把右边可用元素比如mysql.jar全部放左边进去 之前我是外部库里面有, 现在是 你在本地单独开运行,需要把lib放进Web1模块里 想要放在tomcat,还得把lib再单独放在要部署的we1:war工件里 11.db.properties放在resource里面

切换node版本的方法

卸载到安装 卸载node 打开控制面板== 》 选择卸载程序 》选择node》 右键删除 2.检查是否卸载完成 打开cmd ==》 输入node -v ==》控制台显示找不到该路径就可以 3.到官网的历史版本下载你需要的node版本 官网网址:https://nodejs.org/zh-cn/download/releases/ ===》找到你需要的版本 点击下载 在下面这个页面中我们选择msi安装包 4.安装node ==》双击下载完成的安装包 ,无脑点下一步就行【建议不要修改node默认的安装地址,这样我们不需要做任何配置,装完即用】 5.检查是否安装完成,和检查当前node和npm版本号 ==》在cmd中输入 node -v 和 npm -v 出现以下返回值,我们就可以使用当前的npm愉快的进行开发了

ArcGIS批量按协变量掩膜提取数据,并导入matlab制作箱线图

背景:有八张分层的土壤有机碳含量图,要按土地利用/坡向/海拔的分类图分别制作每一种协变量下每一张图层的箱线图——先在ArcGIS里提取四分位数,再导入matlab制作箱线图。 一、ArcGIS使用的python代码 import arcpy import numpy as np import matplotlib.pyplot as plt from arcpy.sa import * # 设置工作空间 arcpy.env.workspace = "C:\\工作空间的文件夹名" # 设置掩膜和地图的名称列表 mask_names = ["mask1", "mask2", "mask3"] #输入需要提取的多张掩膜名字,需要注意,在这之前需要先在arcgis里把掩膜分好 map_names = ["map1","map2"] #输入需要提取的多张地图名字 # 存储结果的列表 results = [] # 循环遍历掩膜和地图名称列表 for mask_name in mask_names: mask_path = mask_name + ".tif" for map_name in map_names: map_path = map_name + ".tif" # 使用按掩膜提取工具进行栅格提取 outExtractByMask = ExtractByMask(map_path, mask_path) # 将提取的栅格数据转换为NumPy数组,并用 np.nan 替换 NoData 值

RabbitMq 的消息可靠性问题(二)---MQ的消息丢失和consumer消费问题

前言 RabbitMq 消息可靠性问题(一) — publisher发送时丢失 前面我们从publisher的方向出发解决了发送时丢失的问题,那么我们在发送消息到exchange, 再由exchange转存到queue的过程中。如果MQ宕机了,那么我们的消息是如何确保可靠性的呢?当消息由队列发到对应的消费者处理时,consumer 接受到消息未消费就宕机,这时消息又如何确保可靠性呢? 消息可靠性问题及其对应的解决方案: 场景publisher发送时丢失MQ消息丢失consumer消费问题解决方案生产者确认机制消息持久化消费者消息确认&&失败重试机制 消息持久化 MQ 默认是内存存储信息, 开启持久化功能可以确保缓存在 MQ 中的消息不丢失 交换机持久化 @Bean public DirectExchange simpleDirect(){ // 三个参数:交换机名称, 是否持久化, 当没有queue 与其绑定时是否自动删除 return new DirectExchange("simple.direct", true, false); } 队列持久化 @Bean public Queue simpleQueue(){ // 使用QueueBuilder构建队列,durable就是持久化的 return QueueBuilder.durable("simple.queue").build(); } 消息持久化,SpringAMQP 中的消息默认是持久化, 可以通过MessagePropertie中的DeliveryMode 来指定的 @Test public void testDurableMessage(){ // 1. 准备消息 Message message = MessageBuilder.withBody("hello,spring".getBytes(StandardCharsets.UTF_8)) .setDeliveryMode(MessageDeliveryMode.PERSISTENT) .build(); // 2. 发送消息 rabbitTemplate.convertAndSend("simple.queue", message); } 其实,默认情况下 SpringAMQP 中的交换机,队列,消息都是持久化的 (所以上诉的持久化参数和代码只需要了解即可)

thinkphp+mysql家政管理系统vue

运行环境:phpstudy/wamp/xammp等 开发语言:php 后端框架:Thinkphp5 前端框架:vue.js 服务器:apache 数据库:mysql 数据库工具:Navicat/phpmyadmin如果是客户可以实现以下功能: 个人信息管理:个人信息的查看、添加、修改、删除 雇用信息管理:雇员信息的查看、雇用合适的服务人员 合同管理:合同的查看,添加,修改,删除合同条例或者要求。 评价管理:添加、修改、删除对完成工作服务人员的评价 如果是服务人员可以实现以下功能:|-application 应用目录 是整个网站的核心 |---|---index 前台目录 |---|-----|---controller 控制器 |---|-----|---model 数据模型 |---|-----|---view 页面 |---|---admin 后台目录 |-extend 扩展类库目录 |-public 静态资源和入口文件 |---|---static 存放静态资源 css、js、img |---|---index.php 入口文件 |-runtime 网站运行临时目录 |-tests 测试目录 |-thinkphp TP框架的核心文件 |---|---lang 语言包 |---|---library TP核心文件里面的核心文件 |---|---tpl 模板页面 个人信息管理:个人信息的查看、添加、修改、删除 雇用信息管理:客户信息及要求的查看、接受合适的工作 合同管理:合同的查看,添加,修改,删除合同条例或者要求。 评价管理:查看客户的评价基本要求:要求此系统能较完善的实现服务人员及客户信息的管理等功能。 主界面:分为用户登陆和管理员登陆,用户登陆包含客户登录和服务人员登陆。 用户注册:注册时可选择身份(客户或者服务人员)。 后台管理: 判断新用户的身份,如果是管理员可以实现以下功能: 管理员信息管理:管理员信息的查询、添加、修改和删除。 服务人员信息管理:员工信息的查询、添加、修改和删除 客户信息管理:客户信息的查询、添加、修改和删除 合同管理:合同的创建、查询、修改和删除 评论管理:对客户的评论可以进行删除 用户管理:对注册的用户可以进行查询、添加、修改和删除 系统安全:修改密码 人们生活水平日渐提高,家政服务行业在国内蓬勃发展,而Internet正是当代的潮流。主动上门去家政公司寻找合适的服务人员已经不是最便捷的方式了,人们对网上招聘的信息十分关注,而本系统的目的就在于将计算机技术与家政服务管理相结合进而设计并制作出可以让公司管理员在网上就可以完成对服务人员和客户信息的管理以及客户直接通过本系统进行聘用所需要的服务人员。同时客户还可以通过本系统查询每一个服务员工的工作历史及其以往工作的评价从而挑选出最优的员工,待其完成工作后依旧可以进行评价。

Anaconda安装到Win系统及其使用

一、选择合适的anaconda版本 这里我选择的是对应Python3.8版本的anaconda 地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 这里我下载的是Python3.8版本的。 具体版本对应关系,请参考:参考链接 二、安装 1、双击 2、next 3、agree 4、电脑单个用户点击just me,多个用户All users。 这里我选择just me。 5、选择位置,建议修改到容量大的磁盘 6、第一个是添加环境变量,建议勾选,这样就不用手动添加环境变量 7、安装完成 三、使用anaconda 添加清华源: conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/win-64/ 1、进入

JSON、JSON字符串和List、Map之间的转换

JSON、JSON字符串和List、Map之间的转换 一、JSON字符串转List<实体类> List<实体类> pojoList = JSONArray.parseArray(jsonStr,实体类.class); 1、前端传的参数: String jsonStr1 = "[{"ifCheck":2,"questOptionContentByOne":"答案1","optSort":"A"},{"ifCheck":2,"questOptionContentByOne":"答案1","optSort":"B"}]"; 2、后台转换: String jsonStr1 = "[{\"ifCheck\":2,\"questOptionContentByOne\":\"答案1\",\"optSort\":\"A\"},{\"ifCheck\":2,\"questOptionContentByOne\":\"答案5\",\"optSort\":\"B\"}]"; List<QuestionOptionExam> questionOptionList = JSONArray.parseArray(jsonStr1 ,QuestionOptionExam.class); 二、Json字符串转List<Map<String,Object>> 1、前端参数: String jsonStr = [{"id":"1","sort":"1"},{"id":"2","sort":"2"}] 2、后台 String jsonStr = "[{\"id\":\"1\",\"sort\":\"1\"},{\"id\":\"2\",\"sort\":\"2\"}]"; List<Map<String,Object>> strList = (List<Map<String, Object>>) JSONArray.parse(jsonStr); JSON字符串转Map 1、qia 三、Map转实体类 1、后台代码: public static void main(String[] args){ Map<String,Object> map = new HashMap<>(); map.put("questOptionId","1"); map.put("optSort","2"); map.put("questOptionContentByOne","3"); map.put("ifCheck","4"); QuestionOptionExam questionOptionExam = JSON.parseObject(JSON.toJSONString(map),QuestionOptionExam .class); System.out.println(questionOptionExam ); } 三、总结测试main方法 public static void main(String[] args){ Map<String,Object> map = new HashMap<>(); map.

面试知识点梳理及相关面试题(十)-- rabbitmq

1. 什么是消息队列? 队列中存放的内容是 message ,是一种跨进程的通信机制,用于上下游传递消息。 在互联网架构中,MQ 是一种非常常见的上下游 “逻辑解耦 + 物理解耦” 的消息通信服务。 2. 为什么使用消息队列? 在分布式系统下具备异步,削峰,负载均衡等一系列高级功能;拥有持久化的机制,进程消息,队列中的信息也可以保存下来。实现消费者和生产者之间的解耦。对于高并发场景下,利用消息队列可以使得同步访问变为串行访问达到一定量的限流,利于数据库的操作。可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单。 2.1 流量削峰 比如某一时刻开放购买的场景,消费者不能一下子消费那么多订单,可以让订单在队列中排队,过几秒钟再处理,总比不能处理的体验要好。 2.2 应用解耦 可以实现消费者和生产者之间的解耦。比如说下单的动作需要多个服务配合,如果一个服务出现了问题,下单都无法完成,但是如果是基于消息队列,前一个服务可以将请求发送到队列,继续去做自己的事情。 2.3 异步处理 有些服务间调用是异步的,例如 A 调用 B,B 需要花费很长时间执行,但是 A 需要知道 B 什么时候可以执行完。 这时候只需要在A调用完B,A去做自己的事情,B处理完成后,发送一条消息到MQ,MQ再将次消息转发给A。 3. Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点? 4. 你们公司用的什么消息队列?为什么选择rabbitmq作为你们的消息队列 4.1 Kafka Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务。大型公司建议可以选用,如果有日志采集功能,肯定是首选 kafka 了。 4.2 RocketMQ 天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RoketMQ 在稳定性上可能更值得信赖,这些业务场景在阿里双 11 已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择 RocketMQ。 4.3 RabbitMQ 结合 erlang 语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,管理界面用起来十分方便,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的 RabbitMQ 对于我的业务来说就是 数据量没有那么大,并且使用场景比较简单同时rabbitmq本身可以支撑高并发、高吞吐、性能很高同时有非常完善便捷的后台管理界面可以使用,还可以支持集群社区活跃,有问题能够及时得到解决 所以rabbitMQ就足够了。 5. 使用rabbitmq的场景。 服务间异步通信顺序消费定时任务请求削峰消息推送 6. rabbitmq四大核心概念 生产者:产生数据发送消息的程序。交换机:是 RabbitMQ 非常重要的一个部件,一方面它接收来自生产者的消息,另一方面它将消息推送到队列中。交换机必须确切知道如何处理它接收到的消息,是将这些消息推送到特定队列还是推送到多个队列,亦或者是把消息丢弃,这个得有交换机类型决定。队列:队列是 RabbitMQ 内部使用的一种数据结构,尽管消息流经 RabbitMQ 和应用程序,但它们只能存储在队列中。队列仅受主机的内存和磁盘限制的约束,本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据。消费者:大多时候是一个等待接收消息的程序。请注意生产者,消费者和消息中间件很多时候并不在同一机器上。同一个应用程序既可以是生产者又是可以是消费者。 7.

java将集合/数组平均分割成多个数组

public static void main(String[] args) { // 业务数据 List<MinappBr> minappBrs = minappBrService.getMinappBySemih(); // 创建一个Map用于存放平均分割后的数组 Map<String, List<MinappBr>> map = new HashMap<>(); // 计算每个部分的大小 ,这里是平均分成3份,根据自己业务决定 int size = minappBrs.size(); int partSize = size / 3; int remainder = size % 3; // 分割数组并存入Map int startIndex = 0; for (int i = 1; i <= 3; i++) { int endIndex = startIndex + partSize + (remainder > 0 ? 1 : 0); String key = "

CentOS7安装及配置nginx

安装nginx 添加 nginx 官方提供的 yum 源(需要联网且时间较长) rpm -Uvh http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.14.2-1.el7_4.ngx.x86_64.rpm 使用 yum 安装 nginx yum install nginx 查看版本 rpm -qa | grep nginx #我这里是nginx-1.20.1-10.el7.x86_64 yum方式安装nginx,它的安装根目录为/etc/nginx 静态资源由Nginx托管,外网必须通过正确的Url才能访问到服务器上的静态资源,而url路径跟文件的存放路径有关,可以通过修改nginx的配置文件实现自定义文件路径配置。 配置nginx nginx的配置文件路径(以本文安装方式): /etc/nginx/nginx.conf 默认的root节点配置: /usr/share/nginx/html 编辑配置文件 有两个关键点 1、修改配置文件中的端口(自己开放的端口是哪个就用哪个,比如8088) 2、配置文件资源访问节点,root和alias root:root指定的目录是上级目录,path匹配的整个路径会追加,即root+path; alias:alias指定的目录必须带/,path匹配后面的内容会在alias指定的目录下查找,即alias+匹配到path路径后面的部分。 例:访问/usr/test/index.html的两种写法 location / { root /usr/test; index index.html; } location /test { alias /usr/test/; index index.html; } vi /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.

Python+selenium自动化元素定位防踩坑

在自动化UI测试过程中常常会在元素定位阶段就踩坑,碰到困扰已久的问题。 以下是个人整理元素定位报错原因和解决方法。 踩坑一:StaleElementReferenceException selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document 异常原因: 意思是,引用的元素已过期。原因是页面刷新了,此时当然找不到之前页面的元素,就算是后退回来的页面也是不一样的。 在编写脚本时一直报这个错,使用显示等待都不行,在一顿百度操作后才知道是元素被刷新了 我们发现,仅仅是刷新了一下页面,两次的element id是不同的,这就说明这是两个不同的元素,如果用之前的element,自然会报错 原因很明显,你用别人的身份证id去找现在的人,哪怕这两个人长的很像,他也会告诉你,对不起,你找错人啦。 解决方法: 有时我们无法避免,不确定什么时候元素就会被刷新。页面刷新后重新获取元素的思路不变,这时可以使用python的异常处理语句:try…except…,异常出现时重新执行,关键代码如下 如下图:我在实际工作当中编写脚本时使用异常try捕获异常后,页面刷新后重新获取元素,可以成功找到元素了 踩坑二:ElementClickInterceptedException(元素点击交互异常) 具体报错:selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted is not clickable at point (1421, 283). Other element would receive the click: E (Session info: chrome=104.0.5112.102) 意思是,元素定位相互覆盖,元素已经找到,但是无法点击 解决方法: 方法一:使用强制等待,但是每次都有类似的元素无法点击使用强制等待的话会延长脚本执行时间 time.sleep() 前言:之前便遇到过很多次该问题的报错,就没有管它,但是随着越来越多的元素报该错,每次使用强制等待会大大延长脚本的执行时间,于是便网上找各种方法解决该问题,最终发现是自己使用显示等待的方法错了 如下是显示等待的用法和区别 方法二:显性等待 element_to_be_clickable--元素是否可点击 vibility of element_ located--元素是否可见 presence_of_element_located--元素是否存在 如上:三种等待方法,最开始我一直使用的是presence_of_element_located,判断元素是否存在,最终还是报错,提示元素元素点击拦截异常 element_to_be_clickable--等待元素出现可以点击,便可以元素定位成功 需要先导包: from selenium.webdriver.support import expected_conditions as EC from selenium.

C语言之 数据结构入门——顺序表的构造

文章目录 一、顺序表是什么?二、构建顺序表的结构体2.1静态和动态顺序表 三.构造顺序表的函数接口3.1功能要求3.2功能实现3.2.1初始化顺序表3.2.2扩容顺序表3.2.3顺序表的打印3.2.4顺序表的尾插3.2.5顺序表的尾删3.2.6顺序表的头插3.2.7查找元素,返回位置3.2.8删除顺序表的某个下标位置数据3.2.9插入一个元素到指定下标位置前 4.构造顺序表所需要的库函数5.代码全篇 一、顺序表是什么? -谈论顺序表前,谈谈线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 顺序表是数据结构的线性表的其中一小类,线性表是指n个具有相同性质的数据元素的有限序列 顺序表(SeqList):顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构(连续存储数据,不能跳跃)。 二、构建顺序表的结构体 2.1静态和动态顺序表 静态顺序表: #define N 100 typedef int SLDataType; typedef struct Seqlist { int arr[N]; //定义数组的长度 int size; //数组元素个数 }sl; 动态顺序表: typedef int data; typedef struct Seqlist { data* a;//指向动态开辟的数组 int size; //数组元素的个数 int capacity;//数组的长度 }sl; 结构体的定义是必不可少的,一般都是采用动态顺序表 ,更好调整顺序表的大小。接下来也是根据动态顺序表来讲述。 三.构造顺序表的函数接口 3.1功能要求 函数接口是实现功能必不可少的环节,将需要实现的功能先放在.h头文件里 //初始化顺序表 void seqlistinit(sl* ps); //扩容顺序表 void CheckCapacity(sl* ps); //顺序表的尾插 void seqlistpushback(sl* ps,data x); //顺序表的尾删 void seqlistpopback(sl* ps); //顺序表的头插 void seqlistpushfront(sl* ps,data x); //顺序表的头删 void seqlistpopfront(sl* ps); //查找顺序表对应值的下标 int seqlistfind(sl* ps, data x); //打印顺序表结果 void seqlistprintf(sl* ps); //删除某个节点 void seqlistdetel(sl* ps, data x); //插入x元素到y节点前 void seqlistinsert(sl* ps, data x, data y); 3.

代码随想录day2|| 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵

977.有序数组的平方 209.长度最小的子数组 59. 螺旋矩阵 II 977、有序数组的平方 解题思路: 一、利用双指针 数组是有序的,但平方之后不一定有序了,那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间,此时可以使用双指针,left指向起始位置,right指向终止位置。定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。 如果A[left] * A[left] < A[right] * A[right] 那么result[k–] = A[right] * A[right]。 如果A[left] * A[left] >= A[right] * A[right] 那么result[k–] = A[left] * A[left];。 时间复杂度为O(n) class Solution { public: vector<int> sortedSquares(vector<int>& A) { vector<int>s; int k = A.size() - 1; int left = 0; vector<int> result(A.size(), 0); int right = A.size()-1; for(int i = 0, j = A.size() - 1; i <= j;){ if(A[i]*A[i] <= A[j]*A[j]){ result[k--] = A[j] * A[j]; j--; } else{ result[k--] = A[i]*A[i]; i++; } } return result; } }; 二、暴力法 // // Created by hcy on 2023/4/7.

LeetCode 新手村刷题(GO)

新手村 P1480 一维数组的动态和 题目描述 给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。请返回 nums 的动态和。 示例 1: 输入:nums = [1,2,3,4] 输出:[1,3,6,10] 解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。 示例 2: 输入:nums = [1,1,1,1,1] 输出:[1,2,3,4,5] 解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。 示例 3: 输入:nums = [3,1,2,10,1] 输出:[3,4,6,16,17] 代码 func runningSum(nums []int) []int { for i :=1;i<len(nums);i++{ nums[i]=nums[i-1]+nums[i]; } return nums; } P1342 将数字变成 0 的操作次数 题目描述 给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

Android:启动流程

Android启动流程 第一步:启动电源以及系统启动 当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后 执行 第二步:引导程序 引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针 对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运 营商加锁和限制的地方。 引导程序分两个阶段执行。 第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序; 第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程 序可以根据配置参数或者输入数据设置内核。 Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。传统的加载器包含两个文件, 需要在这里说明: init.s初始化堆栈,清零BBS段,调用main.c的_main()函数; main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签 第三步:内核 Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表, 加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第 一个进程 第四步:init进程 (搭建环境+启动zygote) init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进程,并调用init中的main()方法执行init进程的职责。 创建和挂载启动所需的文件目录初始化和启动属性服务解析init.rc配置文件并 启动zygote进程 3.1 ----》SystemServers—》开启一系列服务(AMS、WMS、PKMS、PMS、、、、) 3.2 ----》Launcher --> app —> 从 zygote fork 子进程 app 第五步:启动Lancher App fork函数 pid_t fork(void) 返回值分两种情况: 返回0表示成功创建子进程,并且接下来进入子进程执行流程返回PID(>0),成功创建子进程,并且继续执行父进程流程代码返回非正数(<0),创建子进程失败,失败原因主要有: 进程数超过系统所能创建的上限,errno会被设置为EAGAIN系统内存不足,errno会被设置为 ENOMEM 使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空 间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控 制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信 息)。因此,使用 fork() 函数的代价是很大的 子进程与父进程的区别: 除了文件锁以外,其他的锁都会被继承各自的进程ID和父进程ID不同子进程的未决告警被清除;子进程的未决信号集设置为空集。 相关面试题 你了解Android启动流程吗 当按电源键触发开机,首先会从ROM中预定义的地方加载引导程序BootLoader到RAM中,并执行BootLoader程序启动Linux kernel,然后启动用户级别的第一个进程:init进程。init进程会解析init.rc脚本并做一些初始化工作,包括挂载文件系统、创建工作目录以及启动系统服务进程等,其中系统服务进程包括Zygote、system manger、media等。在zygote中会进一步启动system_server进程,并启动AMS、WMS、PMS等服务,等这些服务启动后AMS就会打开Launcher应用的home activity,然后看到了手机的“桌面” system_server为什么要在zygote中启动,而不是由init启动 zygote作为孵化器可以提前加载一些资源,这样fork()时基于Copy_On_Write 机制创建的其他进程就能直接使用这些资源而不用重新加载。比如system_server可以直接使用Zygote中的JNI函数、共享库、常用的类、以及主题资源 zygote为什么不用Binder机制进行IPC通信 Binder 机制中存在 Binder 线程池,是多线程的,如果 Zygote 采用 Binder 的话就存在上面说的fork() 与 多线程的问题了。其实严格来说,Binder 机制不一定要多线程,所谓的 Binder 线程只不过是在循环读取 Binder 驱动的消息而已,只注册一个 Binder 线程也是可以工作的,比如 service manager就是这样的。实际上 Zygote 尽管没有采取 Binder 机制,它也不是单线程的,但它在 fork() 前主动停止了其他线程,fork() 后重新启动了。

Windows 10怎样安装.msi文件?三分钟解决问题

我在百度网盘上下载mysql的.msi文件后发现双击以后无法打开,会出现下图情况。 我在网上查了很多相关的资料,试了很多的方法,也浪费不少时间才解决的问题。为了让大家少走歪路,节约大家的时间。解决方法如下: 第一步:按Windows + R 键,电脑左下方会弹出如图所示的框。然后在框中输入 services.msc 命令。点击确定按钮进入。 进入如下图所示的页面,然后找到Windows Installer服务,点击鼠标右键,点击启动。 如果显示"正在..."则说明第一步完成了。 第二步:按Windows + R 键,输入下图所示的cmd命令,必须以管理员的身份打开:按Ctrl+Shift+Enter快捷键打开。就是要以管理员身份运行命令提示符。 第三步:在命令行输入msiexec /package 文件路径和文件名 。 (注意:路径中不要出现中文) 我这里的路径:D:\class 文件名: mysql-5.5.49-win32.msi 然后键盘点Enter键。 如图所示: 然后退出命令行后,双击就可以打开该.msi文件了。进行安装了。 在这里如果安装成功的话留下一个免费的赞再走呗。。。

SQL server 脚本自动转换成适合MySQL脚本的方法

本人新手小白一枚。刚实习两个星期,目前接触到的东西,比较迷茫,在此将自己实习过程学到的东西,简单做个总结,希望有路过的大佬,也可以指点指点。(其实这就是俺的一些笔记,应该叫做菜鸟实习第一天) 好了,开始代码。 第一步,先在IServices写上接口: Task<string> release();//release为方法名 第二步,先在服务层Services写上方法: 此方法是将SQL server的列名、表数据分别查出来。再赋值给不同的参数。最后将数据拼接成适应MySQL的sql语句。 public List<string> DataTableToInsertSql(DataTable dt, string table) { List<string> result = new List<string>(); string cols = string.Join(",", dt.Columns.Cast<DataColumn>().Select(x => $"{x.ColumnName}").ToArray());//提取出列名 foreach (DataRow dr in dt.Rows) { var vals = string.Join(",", dr.ItemArray.Select(x =>//提取出表中数据(连接字符串) { if (DBNull.Value.GetType() == x.GetType())//判断是否为空,为空插入null值 { return "null"; } else { return $"'{x}'"; } }).ToArray()); result.Add($"insert into {table} ({cols}) values({vals})");//将表名和数据拼接为mysql的语法 } return result; } var sql = "select * from base_menu"

闲鱼关键词搜索列表数据

#闲鱼关键词搜索接口 描述:闲鱼关键词搜索列表数据 方式: GET 传参说明:keyword: 搜索词;page: 页数; 返回说明: { "api": "cdy.xy.keyword.search.info", "data": { "appBar": {}, "filterBar": { "hidden": "false", "showFilterBarWithCpv": "false", "showWantBuy": "false" ... ... ... }], "v": "1.0", "left_num": 40 }

一文详解像素、DPI、分辨率之间的关系

1.像素 像素:是指在由一个数字序列表示的图像中的一个最小单位,称为像素。 像素可以用一个数表示,比如一个“0.3兆像素”数码相机,它有额定30万像素;也可以用一对数字表示,例如“640x480显示器”,它表示横向640像素和纵向480像素(就像VGA显示器),因此其总数为640 × 480 = 307,200像素。 数字化图像的彩色采样点(例如网页中常用的JPG文件)也称为像素。由于计算机显示器的类型不同,这些可能和屏幕像素有些区域不是一一对应的。在这种区别很明显的区域,图像文件中的点更接近纹理元素。 在计算机编程中,像素组成的图像叫位图或者光栅图像。光栅一词源于模拟电视技术,位图化图像可用于编码数字影像和某些类型的计算机生成艺术。简单说起来,像素就是图像的点的数值,点画成线,线画成面。当然,图片的清晰度不仅仅是由像素决定的。 当图片尺寸以像素为单位时,我们需要指定其固定的分辨率,才能将图片尺寸与现实中的实际尺寸相互转换。例如大多数网页制作常用图片分辨率为72,即每英寸像素为72,1英寸等于2.54厘米,那么通过换算可以得出每厘米等于28像素;又如15x15厘米长度的图片,等于420*420像素的长度。 pt (point,磅):是一个物理长度单位,指的是72分之一英寸。 pt = px * dpi / 72 px (pixel,像素):是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精度DPI(Dots Per Inch,每英寸像素数),在扫描打印时一般都有DPI可选。Windows系统默认是96dpi,Apple系统默认是72dpi。 em(相对长度单位,相对于当前对象内文本的字体尺寸):是一个相对长度单位,最初是指字母M的宽度,故名em。现指的是字符宽度的倍数,用法类似百分比,如:0.8em, 1.2em,2em等。通常1em=16px。 字号:是中文字库中特有的一种单位,以中文代号表示特定的磅值pt,便于记忆、表述。 2. 分辨率 分辨率(resolution):指给定的距离(或面积)内“点”或“像素”的数量。有时被称为“解析度”。可分为显示分辨率、图像分辨率、打印分辨率和扫描分辨率等。分辨率可以理解为点或像素的密度(dot / pixel density)。 常用的描述分辨率的单位有: PPI(像素/英寸)和DPI(点每英寸)。还有一些其他单位,比如px/cm(像素每厘米, dpcm)、LPI(线每英寸)等。 描述分辨率的单位: PPI:pixels per inch,电子显示设备从打印设备中借鉴了 DPI 的概念,产生了 PPI的概念。即显示器每英寸(对角线长度)上像素点的数量,指像素密度。 DPI:dots per inch,表示每英寸(对角线长度)能打印上的墨滴数量。最初应用于打印技术中。打印设备多在 300 至 3600 DPI 之间。 在实际中,分辨率泛指量测或显示系统对细节的分辨能力,分辨率越高代表影像质量越好,越能表现出更多的细节;但相对的,因为纪录的信息越多,文件也就会越大。分辨率也经常被用来表达一些别的概念,例如谈论显示器分辨率时经常看到“1024×768”这种表示,这个更准确的说应该是屏幕的“像素尺寸”,或者说“图像像素尺寸”。 3. 像素的实际意义 图像像素是数字图像的基本单元,一幅点阵图像由许多像素点组成。位图图像在高度和宽度方向上的像素总量称为图像的像素大小。同一幅图像像素的大小是固定的,像素越多,图像呈现越细腻、自然,但图像也会越大。图像像素是一个抽象的概念,属于 逻辑尺寸。图像像素的意义在于它是图像编辑的最小单元,而不在于它具有多大的实际尺寸它只是一个逻辑单元和功能单元,没有确定的物理尺寸。 逻辑尺寸属于抽象的图象尺寸描述,但恰恰是像素尺寸决定一数字图象的实质特性。而实际 (物理 )尺寸只是表象仅仅是把一个图象看得“大一点或者小一点 ”那种比例调整的结果。决定这个调整比例 的就是分辨率,分辨率根本不属于图象内容本身只是一附加的 “缩放器 ”并不影响数字图像的实质内 容。在图像输出到介质时‚一个像素表示为多大的实际边长和面积‚那是任意的‚也就是人为任意指定——想多大就多大。只有在图像输出到介质时才需要为像素这种逻辑单元指定一个实际对应的物理 尺寸,指定如何对应实际尺寸的那个量就是分辨率。 4. 像素、分辨率和物理尺寸的关系 当一张图像以像素表示时,我们需要指定其分辨率(PPI/DPI),才能将图片的“像素尺寸”与现实中的物理尺寸(屏幕显示大小或打印出来的尺寸)相互转换。可以理解为,像素是像素尺寸(以宽像素数x高像素数表示)、分辨率(PPI或DPI)和物理尺寸之间关系的一部分。 分辨率=像素尺寸/物理尺寸 Resolution(PPI或DPI)=Pixels/Unit

电池串联和并联的区别有哪些

蓄电池串联时,电流处处相等,电压是各个蓄电池电压之和。 蓄电池并联时,电压处处相等,电流是各个蓄电池电流之和。 串联并联区别 电池串联:指电池首尾相联。即第一节电池的正极接第二节电池的负极,第二节电池的正极接第三节电池的负极依次类推。 串联电压等于电池电压之和,电流等于流过每个电池的电流。 电池组当中的一节损坏会造成整个电池组不能使用或是电压降低。 串联可以提升总电压。 电池并联: 指电池首首相联、尾尾相联。即所有电池的正极相联接,所有电池的负极相联接。 并联电压等于单个电池电压,电流等于电池电流之和。 电池组的续航能力虽然增强了,但短路电流造成的破坏更加严重。 并联可以提高总电流。 串联电路的特点 1.串联电路电流处处相等。 2.串联电路总电压等于各处电压之和。 3.串联电阻的等效电阻等于各电阻之和。 4.串联电路总功率等于各功率之和。 5.串联电容器的等效电容量的倒数等于各个电容器的电容量的倒数之和。 6.串联电路中,除电流处处相等以外,其余各物理量之间均成正比。 7.开关在任何位置控制整个电路,即其作用与所在的位置无关。电流只有一条通路,经过一盏灯的电流一定经过另一盏灯。如果熄灭一盏灯,另一盏灯一定熄灭。 并联中电流电压电阻特点 1.在并联电路中总电流等于各支路电流之和。 2.在并联电路中电压都相等。 3.在并联电路中总电阻的倒数等于各支路电阻的倒数之和。 4.在并联电路中电流的分配跟电阻成反比。