java开发岗位面试
java开发岗位面试
技术栈:springboot框架+redis
个人笔试/技术面问题整理
1、SpringBoot有什么组件?
举例说几个:
①auto-configuration组件:核心特征。其约定大于配置思想,赋予了SpringBoot开箱即用的强大能力。
②starter组件:将复杂配置统一集成进starter,maven导入starter后,SpringBoot就自动扫描加载配置。
③springboot cli 组件:命令行工具,通过springboot cli,可通过Groovy脚本快速构建SpringBoot应用,并可通过命令行方式运行。
④actuator 组件:用来对应用系统进行自省和监控的功能模块,是SpringBoot的监控插件,本身提供了很多接口可以获取当前项目的各项运行状态指标。借助于Actuator开发者可以很方便地对应用系统某些监控指标进行查看、统计等。
2、@Service和@Autowired的区别?
@Service根据名称
@Autowired默认按类型配置
3、SpringBoot是基于什么服务器启动的?启动的原理是什么 ?
Tomcat
启动原理:
SpringBoot因内置了tomcat或者jetty服务器,不需要直接部署war文件,所以SpringBoot的程序起点是一个普通的主函数。
主函数:
@SpringBootApplication
public class DemoApplication{public static void main (string[] args){springApplication.run(DemoApplication.class,args);}}
SpringBoot的启动过程都是通过@SpringBootApplication注解和SpringApplication.run方法来实现。
Curl localhost:8080/hello
Curl:验证接口
4、定义一个post接口使用的注解?
注解@PostMapping定义一个post接口
@RequestBody:把前端传过来的Json转换成Java对象(将Json对象映射成后台Java实体)。例:(@RequestBody User user)
5、Long型跟long型的区别,Long型中equals和“==”的区别?
long是基本数据类型,没有属性方法,只能进行数学运算;而Long是long相对应的引用数据类型,也是包装类,它有方法和属性。
类里面有方法和属性,而基本数据类型里面没有方法和属性。
long a = 1 ;
Long a1 = new Long(1);
Long a2 = new Long(1);
以上:a与a1相等,a与a2相等,a1与a2 equals相等。
由此可见,
Long定义的变量为一个Long类型对象;对应的是对象的引用地址;
long定义的变量为一个长整型数值的数值变量。
到底是选择Long还是long这个还得看具体环境,如果你认为这个属性不能为null,那就用long,因为它默认值为0;如果这个字段可以为null,那就应该选择Long。
long可以用“>”,“=”,“<”作比较,Long是一个对象,使用.equals方法进行相等比较,大小比较时使用“>”“<”对Long对象longValue()。例 : L1.longValue()>L2.longValue()
6、开发过程中错误代码,文件找不到的错误代码:404,服务器内部失败:500,内部网络故障或设置问题的状态:502,请求失败(错误的请求 400);
7、SpringBoot中如何处理事务?使用的任务注解?
SpringBoot提供了一个名为“@Transational”的注解来管理事务。
假设一个场景,需要在一个service中处理数据,并通过Rest调用将数据发送到另一个service。如若另一个服务器突然停止,如果在向另一个service服务发送Api调用之前将数据信息保存在自己的数据库中,那么将来会发生差异,因为另一个service正在丢失该记录。
为了避免这种情况,我们可以将“@Transactional”注解放入另一个service的方法中,然后从那里开始,如果调用另一个service时出现故障,正在进行的流程中的所有数据都将回滚!
@Transational
public A a(B b,Double c)
{
//数据处理
//向另一个service发送Rest调用
}
8、MySQL数据库有自增序主键,Oracle有UUID主键来辨别唯一,但是无序,Oracle怎么实现自增长主键?
Oracle数据库自增长没有Mysql数据库简单,mysql可以在建表的时候设置auto_increment就好了,但Oracle这样不行,Oracle数据库必须建立序列,然后再mybatis插入id时,使用这个序列后,才能实现Oracle id 的子增长。
序列创建语句:
create sequence TBAL_OA_HOLIDAY_TYPE //序列名称
increment by 1 //以1倍的速度增长,也可以设置其他数字
start with 1 //从id=1开始 开始增长
maxvalue 9999 //最大值为9999,根据情况
minvalue 1 //最小值为1
nocycle //不循环,也就一直增长
cache 20 //设置缓存cache个序列,如果系统down掉或者有其他情况不连续,也可以设置为 ---NOCACHE
noorder ;
建立了Oracle序列之后,我们就可以再mybatis中插入这样使用,来插入id了;
insert into TBAL_OA_HOLIDAY_TYPE(ID,TYPE_NAME,REMARK) values(TBAL_OA_HOLIDAY_TYPE.NEXTVAL,#{typename},#{remark})
我们在mybatis插入id的位置用(序列名称+.NEXTVAL)的形式代替这个id
(若是uuid作为主键,Oracle中有有sys_guid函数可以产生uuid)
例:
select sys_guid() from dual
mysql中使用uuid的话,建议在Java中生成uuid再存库
( 引入java.util.UUID包。String uuid = UUID.randomUUID().toString().replace(“_”,“”) )
9、Vue前端若多次对后端进行点击响应,后端怎么能减少这个冗余?
后端:(数据库+索引)
10、Arraylist、Linkedlist和Vector三者区别
①从存储结构来看:
Arraylist和Vector是由数组构成,其默认的初始容量为10。而Linkedlist是由双向链表构成。
②从线程安全来看:
Arraylist和Linkedlist是线程不安全的,如果需要在并发的环境下使用它们,可以用Collections类中的静态方法synchronizedlist()对Arraylist和Linkedlist进行调用即可。
而Vector是线程安全的,它的源码中大部分方法中都包含关键字synchronized,但Vector的效率没有Arraylist高。
③从扩容机制来看:
Linkedlist是没有扩容的,因为是链表实现的。
Arraylist和Vector的扩容机制:(1)Arraylist扩容之后的容量是之前的1.5倍(默认);(2)Vector扩容之后的容量是之前的两倍(默认);(3)Vector可设置容量增量,Arraylist不可以。
④从增删查改的效率来看:
Arraylist和Vector:如果是在指定位置检查,或者是在集后尾部进行插入和删除的话,时间复杂度是O(1),但如果是其他地方插入或者删除的话,时间复杂度就变成了O(n)。
注意:可变长度数组的原理:当元素哥个数超过数组长度时,会产生一个新的数组,将原数组的数据复制到新数组,再将新的元素添加到新数组中。
11、equals和“= =”的区别?
“= =”是比较两个变量或实例是否指向同一个内存空间,而equals是比较两个变量或实例所指向的内存空间的值是否相等。
对于基本数据类型的变量,如Byte,short,char,int,float,long,double和boolean,“==”直接对其值进行比较;
对于引用数据类型的变量,则是对其内存地址的比较。
因此,“= =”比较的是值,只是引用类型变量存的是对象的地址。
而equals方法是Object类的方法,比较的是字符串中所包含的内容是否相同。
12、使用过的关系型数据库以及非关系型数据库,它们之间的区别
关系型数据库:mysql、Oracle
非关系型数据库:redis --是一个key-value的nosql数据库
Oracle与mysql区别:
mysql开源免费的中小型,关系数据库管理系统(RDBMS);
Oracle收费的大型、对象关系数据库管理系统(ORDMS);
mysql使用三(用户名、密码、位置)验证客户;
Oracle有用户名、密码、配置文件、本地身份验证、外部身份验证等;
mysql事务是自动提交;
Oracle需要手动,写commit或点提交按钮;
mysql没有Oracle的表空间、角色管理、快照、同义词、包、自动存储管理。
字符类型:
mysql:char(0-255)、varchar(0-65,535)
Oracle:char、nchar(1-2000),varchar2、nvarchar2(0-4000)
mysql:like ‘%字符串%’
oracle:也有li’ke ‘%字符串%’,使用字符串比较数instr(字符串,‘字符串’)>0更精确
mysql有Date、Time日期类型
Oracle只有Date
mysql非空字段也有空的内容
Oracle定义非空字段就不允许有空的内容
(所以,将mysql数据传过来Oracle,要注意导数据时要对空字符进行判断,如果为null或者空字符、需要把它转换成一个空格的字符串)
oracle与redis的区别:
①数据模型
Oracle和MySQL都是关系型数据库,数据以表格形式存储,每个表格由若干个列组成,每列定义了数据的类型和约束条件。表格之间可以建立关系,例一对多,多对多等,这些关系需要使用外键进行定义。
redis是一种键值型数据库,数据以键值对的形式存储的,其中键是一个字符串,值可以是字符串、哈希、列表、集合或有序集合等。
②查询语句
Oracle和MySQL都是使用sql查询语言来查询数据。sql是一种标准的关系型数据库查询语言。
redis使用一种类似于命令的语言来查询和操作数据,其中每个命令都对应一个具体的操作,例如set用于设置键值对,get用于获取键值对应的值等。
③扩展性
mysql和Oracle支持分布式和扩展性,但需额外配置且复杂。
redis支持分布式,可在多台服务器上分布数据,以提高性能和可用性。
④适用场景
mysql和Oracle使用于处理结构化数据的场景,支持高度优化的查询引擎,可处理复杂的查询和聚合操作
redis适用于高速读写的场景,例如缓存、消息队列等,redis读写速度非常快,可以在短时间内处理大量的请求
13、mao集合取并集、差集、交集
map1、map2
map是一个key和value的键值对的集合
①map并集:
public static Map<String,Object> getUnion( Map<String,Object> map1, Map<String,Object> map2){Set<String> bigMapKey = map1.keySet();Set<String> smallMapKey = map2.keySet();Set<String> differenceSet = Sets.union(bigMapKey,smallMapKey);Map<String,Object> result = Maps.newHashMap();for(String key : differenceSet){if(map1.containsKey(key)){result.put(key,map1.get(key));}else{result.put(key,map2.get(key));}}return result ;
}
.containsKey:判断是否有key
.get():获取对应的value
Guava的union():返回两个集合的不可修改的视图
②差集
bigmap、smallmap
public static Map<String,Object> getDifference( Map<String,Object> bigMap, Map<String,Object> smallMap){Set<String> bigMapKey = bigMap.keySet();Set<String> smallMapKey = smallMap.keySet();Set<String> differenceSet = Sets.difference(bigMapKey,smallMapKey);Map<String,Object> result = Maps.newHashMap();for(String key : differenceSet){result.put(key,bigMapKey.get(key)); }return result ;
}
difference():函数返回两个集合的差集、即返回的在第一个集合但不在第二个集合中的元素。
③map交集:
map1、map2
public static Map<String,Object> getInter( Map<String,Object> map1, Map<String,Object> map2){Set<String> bigMapKey = map1.keySet();Set<String> smallMapKey = map2.keySet();Set<String> differenceSet = Sets.intersection(bigMapKey,smallMapKey);Map<String,Object> result = Maps.newHashMap();for(String key : differenceSet){result.put(key,map1.get(key)); }return result ;
}
intersection():方法用于返回两个或者更多集合中包含的元素,即交集。
14、String、StringBuffer和StringBuilder的区别
string:
①String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低,且浪费优先的内存空间。
②不可变
③
④
StringBuffer:
①StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象,每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动分配容量。
②可变
③线程安全
④多线程操作字符串
StringBuilder:
①可变类,速度更快。
②可变
③线程不安全
④单线程操作字符串
StringBuffer对象是一个字符序列可变的字符串,没有重新生成一个对象,而是在原来的对象中可以连接新的字符串。
StringBuilder类也代表可变字符串对象。StringBuffer和StringBuilder基本相似。不同的是:StringBuffer是线程安全的,而StringBuilder没有实现线程安全功能。
执行速度:
StringBuilder>StringBuffer>String
操作少量数据用String;多线程操作字符串缓冲区下操作大量数据用StringBuffer;单线程操作字符串缓冲区下操作大量数据用StringBuilder。
15、Java常用包、集合、线程、io、数据库索引
java常用包:
java.io包:通过文件系统,数据流和序列化提供系统的输入与输出
java.lang包:提供了java语言进行程序设计的基础类
java.util包:集合类。日期等各种实用工具类
java.sql包:Java访问并处理存储数据源中的数据api
java.net包:提供实现网络应用与开发的类
集合:
Java集合大致可分为:List、Set、queue和Map四种体系;
其中List代表有序、重复的集合;Set代表无序、不可重复的集合;Queue代表一种队列集合实现;Map接口中键和值一一映射。
线程:
java语言主要提供了两种实现线程的方式:
①继承Thread类创建线程类
②实现Runable接口创建线程类
①:
(1)定义继承Thread类,并重写Thread类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run()方法称为线程执行体。
(2)创建Thread子类的实例,即创建子线程对象。
(3)调用线程对象的start()方法来启动该线程。
②:
(1)定义实现Runable接口,并重写Runable接口的run()方法,该run()方法的方法体就代表了线程需要完成的任务。
(2)创建Runable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
(3)调用该Thread对象的start()方法来启动该线程。
16、空指针异常怎么避免?
①加判断:if(status.equals(success)){}
②初始化默认值
③返回空集合:return list ==null ? new ArrayList() : list;
17、怎么通过内部循环结束整体循环
break跳出循环、结束循环(如果是内层循环,仅终止内层循环,外层循环不会终止)
continue跳出本次循环、继续下次循环
return程序返回到调用某方法的地方
break+标签:跳出循环到标签处,结束标签内的循环,在多重循环的最外层设置标签,配合break可终止整个循环
(设置a for循环外加“a:” break a;)
continue+标签:跳出循环到标签处,结束此次循环,从此标签处开始下一次循环
18、MVC模型
M-model模型是指模型表示业务规则
V-view试图是指用户看到并与之交互的界面
C-controller控制器是指控制器接受用户的输入并调用模型和试图去完成用户的需求,控制器本身不输出任何东西和做任何处理
19、面向对象是什么
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事件在整个解决问题的步骤中的行为。
面向过程:就是分析出解决问题所需的步骤,然后用函数把这些步骤一步步实现,使用的时候一个个依次调用就可以了。
20、Java线程池、Java的jvm、 数据库sql优化、spring特征
Java的线程池通过Executor框架来实现
用到Executor、ExecutorService
ThreadPoolExecutor、Future、FutureTask等几个大类
21、什么是三次握手?
22、什么是依赖注入?
23、GC是什么?原理?(垃圾回收)
24、REST接口用到的注解?以及注解的作用?
相关文章:
java开发岗位面试
java开发岗位面试 技术栈:springboot框架+redis 个人笔试/技术面问题整理 1、SpringBoot有什么组件? 举例说几个: ①auto-configuration组件:核心特征。其约定大于配置思想,赋予了SpringBoot开箱即用的强…...
坠落防护 挂点装置
声明 本文是学习GB 30862-2014 坠落防护 挂点装置. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了高处坠落防护挂点装置的技术要求、检验方法、检验规则及标识。 本标准适用于防护高处坠落的挂点装置。 本标准不适用于体育及消…...
关于 自定义的RabbitMQ的RabbitMessageContainer注解-实现原理
概述 RabbitMessageContainer注解 的主要作用就是 替换掉Configuration配置类中的各种Bean配置; 采用注解的方式可以让我们 固化配置,降低代码编写复杂度、减少配置错误情况的发生,提升编码调试的效率、提高业务的可用性。 为什么说“降低…...
uniapp快速入门系列(1)- 概述与基础知识
章节三:抖音小程序页面开发 第1章:概述与基础知识1.1 uniapp简介1.1.1 什么是uniapp?1.1.2 为什么选择uniapp?1.1.3 uniapp与微信小程序的关系 1.2 HBuilderX介绍与安装1.2.1 什么是HBuilderX?1.2.2 HBuilderX的安装1.…...
国密国际SSL双证书解决方案,满足企事业单位国产国密SSL证书要求
近年来,为了摆脱对国外技术和产品的依赖,建设安全的网络环境,以及加强我国对网络信息的安全可控能力,我国推出了国密算法。同时,为保护网络通信信息安全,更高级别的安全加密数字证书—国密SSL证书应运而生。…...
LabVIEW开发虚拟与现实融合的数字电子技术渐进式实验系统
LabVIEW开发虚拟与现实融合的数字电子技术渐进式实验系统 数字电子技术是所有电气专业的重要学科基础,具有很强的理论性和实践性。其实验是提高学生分析、设计和调试数字电路能力,培养学生解决实际问题的工程实践能力,激发学生创新意识&…...
机器学习之单层神经网络的训练:增量规则(Delta Rule)
文章目录 权重的调整单层神经网络使用delta规则的训练过程 神经网络以权值的形式存储信息,根据给定的信息来修改权值的系统方法称为学习规则。由于训练是神经网络系统地存储信息的唯一途径,因此学习规则是神经网络研究中的一个重要组成部分 权重的调整 (…...
C# Task任务详解
文章目录 前言Task返回值无参返回有参返回 async和await返回值await搭配使用Main async改造 Task进阶Task线程取消测试用例超时设置 线程暂停和继续测试用例 多任务等最快多任务全等待 结论 前言 Task是对于Thread的封装,是极其优化的设计,更加方便了我…...
百度网盘的扩容
百度网盘的扩容怎么扩 百度网盘的扩容通常需要购买额外的存储空间。以下是扩容百度网盘存储空间的一般步骤: 登录百度网盘:首先,在您的计算机或移动设备上打开百度网盘,并使用您的百度账号登录。 选择扩容选项:一旦登…...
Android 悬浮窗
本文参考文章地址:https://juejin.cn/post/7009180088310693919 一、申请权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />二、创建悬浮窗service <serviceandroid:name".FloatingWindowService"an…...
3.物联网射频识别,(高频)RFID应用ISO14443-2协议
一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 (1)14443协议组成(下面的协议简介会详细介绍) 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 (分为Type A、Type B两种接口&…...
数据分析笔记1
数据分析概述:数据获取--探索分析与可视化--预处理--分析建模--模型评估 数据分析含义:利用统计与概率的分析方法提取有用的信息,最后进行总结与概括 一、数据获取 实用网站:kaggle 阿里云天池 数据仓库:将所有业务数据…...
paramiko 3
import paramiko import concurrent.futuresdef execute_remote_command(hostname, username, password, command):try:# 创建SSH客户端client paramiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 使用密码认证连接远程主机client.connect(h…...
基于Dlib训练自已的人脸数据集提高人脸识别的准确率
前言 由于图像的质量、光线、角度等因素影响。这时如果使用官方提供的模型做人脸识别,就会导至识别率不是很理想。人脸识别的准确率与图像的清晰度和质量有关。如果图像模糊、光线不足或者有其他干扰因素,Dlib 可能无法正确地识别人脸。为了确保图像质量…...
Git 详细安装教程(详解 Git 安装过程的每一个步骤
Git 详细安装教程(详解 Git 安装过程的每一个步骤) 该文章详细具体,值得收藏学习...
kafka伪集群部署,使用KRAFT模式
1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:kafka-1:container_name: kafka1image: bitnami/kafka ports:- "19092:19092"- "19093:19093&quo…...
【双指针遍历】N数之和问题
文章目录 二数之和LC1三数之和LC15四数之和LC18最接近的三数之和LC16 二数之和LC1 题目链接 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对…...
Qt的QObject类
文章目录 QObject类如何在Qt中使用QObject的信号与槽机制?如何在Qt中使用QObject的属性系统?QObject的元对象系统如何实现对象的反射功能? QObject类 Qt的QObject类是Qt框架中的基类,它是所有Qt对象的父类。QObject提供了一些常用…...
【图论C++】链式前向星(图(树)的存储)
/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记:转载需获得博主本人…...
16.PWM输入捕获示例程序(输入捕获模式测频率PWMI模式测频率和占空比)
目录 输入捕获相关库函数 输入捕获模式测频率 PWMI模式测频率和占空比 两个代码的接线图都一样,如下 测量信号的输入引脚是PA6,信号从PA6进来,待测的PWM信号也是STM32自己生成的,输出引脚是PA0。 需要配置电路连接图示如下&…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
