在众多的编程语言和网络库中,拿来介绍网络编程的例子,echo服务器和客户端恐怕是最多的一个例子。netty作为一个在java语言中应用非常广泛、非常优秀的网络编程框架,echo服务器和客户端程序往往是大家第一个接触的实例程序。很多工程师正是通过echo服务器和客户端跨入netty的大门。
我们先看一个echo服务器的完整实例代码:
/**
* Echoes back any received data from a client.
*/
public final class EchoServer {
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
} else {
sslCtx = null;
}
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
// 把ServerBootstrap的channelfactory设置为ReflectiveChannelFactory
// 当执行channelfactory的newChannel方法时,会创建NioServerSocketChannel实例
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
// 处理server Socket事件
.handler(new LoggingHandler(LogLevel.INFO))
// 处理client socket事件
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
//p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new EchoServerHandler());
}
});
// Start the server.
ChannelFuture f = b.bind(PORT).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
代码中前面一段跟SSL相关的代码我们先跳过,从这两行代码开始:
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
这里创建了两个EventLoopGroup
对象bossGroup
和workerGroup
,bossGroup
主要用来处理server socket监听client socket的连接请求,server socket接收了新建连接后,会把connection socket放到workerGroup
中进行处理,也就是说workerGroup
主要用来处理connection socket的网络IO和相关的业务逻辑。netty支持很多种线程模型,这种bossGroup
和workerGroup
的组合是比较典型的。
netty作为一个异步的事件驱动(event drivern)的网络应用程序框架,采用非阻塞的多路复用的网络io模型。连接建立、连接关闭、socket可读、socket可写这些状态的改变称为一个个“事件(event)”,当然事件也可以是应用程序添加的一个任务。而处理这些event的线程就是一个无限循环(for or while loop),没有事件发生时,线程一直等待事件的产生。当有事件发生时,则处理所有的事件,处理完后则开始下一个循环,继续等待新的事件的发生。所以这种处理逻辑叫做eventloop,eventloop与线程是一一对应的,一个eventloop对应一个线程,一个线程也只有一个eventloop。而eventloopgroup主要包含了一组eventloop(线程池),当然还有许多线程任务分发等管理功能。
eventloopgroup/eventloop是netty的核心部件之一,可以说是netty三大核心部件之一,另外两个是channel和pipeline。eventloopgroup/eventloop定义了netty的线程模型,包括channel对socket的操作、pipeline的业务处理、用户提交的任务在内的所有任务的分发调度和执行都是在eventloopgroup/eventloop中进行。
这里为eventloopgroup
接口实例化的是类NioEventLoopGroup
,NioEventLoopGroup基于java nio进行网络操作。
我们跟踪一下NioEventLoopGroup
的构造函数,
NioEventLoopGroup
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
public NioEventLoopGroup(int nThreads, Executor executor) {
this(nThreads, executor, SelectorProvider.provider());
}
public NioEventLoopGroup(
int nThreads, Executor executor, final SelectorProvider selectorProvider) {
this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
然后进入他的父类:
MultithreadEventLoopGroup
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
继续进入上一级父类:
MultithreadEventExecutorGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
}
这里进入了一个有实质内容的构造函数,在分析这个函数之前,我们先根据构造函数的调用链梳理一下构造函数的入参的值。
nThreads = (nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads);
executor = null;
chooserFactory = DefaultEventExecutorChooserFactory.INSTANCE;
args = [SelectorProvider SelectorProvider.provider(),
SelectStrategyFactory DefaultSelectStrategyFactory.INSTANCE,
RejectedExecutionHandler RejectedExecutionHandlers.reject()]
可见如果NioEventLoopGroup
的构造函数如果nThreads为非0值,则为传入的实际值,如果为0或没有参数,则为DEFAULT_EVENT_LOOP_THREADS
,我们看下DEFAULT_EVENT_LOOP_THREADS
的定义,
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
继续跟下去,可以知道NettyRuntime.availableProcessors()
默认值为Runtime.getRuntime().availableProcessors()
,也就是说nThreads值默认为CPU核心数的2倍
接下来我们分析构造函数:
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args)
首先为executor
重新赋值:
if (executor == null) {
// DefaultThreadFactory设置: 非daemon、线程优先级5、线程名字、线程组为当前线程所属组
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
因为executor
入参值为null,所以executor
重新赋值为ThreadPerTaskExecutor
类的一个新建实例,ThreadPerTaskExecutor
就是eventloop的执行器,eventloop的所有任务都是通过调用ThreadPerTaskExecutor
的execute()
函数,从而创建一个线程,进而执行提交的任务的。ThreadPerTaskExecutor
只有一个成员,线程工厂DefaultThreadFactory
,这个线程工厂创建的线程实例设置的线程属性为:非daemon、线程优先级5、线程名的前缀、所属的线程组与当前线程相同,一句话,创建的是一个普通线程,其中线程名的前缀为: nioEventLoopGroup-poolId-
, poolId初始值为0,每创建一个DefaultThreadFactory
实例值加1。
然后初始化EventLoopGroup的线程池,具体代码如下:
// 创建一个数组,数组大小为线程的个数
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
// 初始化线程executor
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// TODO: Think about if this is a good exception type
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
// 如果初始化一个线程executor时抛出异常,则执行这一段代码:关闭前面创建的所有executor,并等待所有线程退出运行
if (!success) {
for (int j = 0; j < i; j ++) {
children[j].shutdownGracefully();
}
for (int j = 0; j < i; j ++) {
EventExecutor e = children[j];
try {
while (!e.isTerminated()) {
e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
} catch (InterruptedException interrupted) {
// Let the caller handle the interruption.
Thread.currentThread().interrupt();
break;
}
}
}
}
}
初始化过程,在代码注释中已经说明了,关键语句children[i] = newChild(executor, args);
我们先放下,待会再详细分析。
线程选择器初始化:
chooser = chooserFactory.newChooser(children);
chooser实现了eventloopgroup的任务分派,当需要向线程池提交一个新的任务时,如注册一个新的服务端socket到eventloop,则通过chooser选择一个具体的executor。从前面分析得知,chooserFactory是DefaultEventExecutorChooserFactory
的一个实例,它的executor选择逻辑代码如下:
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
// executor数是2的n次方,用与来计算,改善性能
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
// executor数不是2的n次方,用除法求余的方式计算
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
}
可见,线程池中的个数是2的n次方与不是2的n次方,具体的计算方法不一样,但效果都是round-robin的选择方法。
最后,为线程池的每一个EventExcutor注册一个结束后的回调函数,并把所有的EventExcutor保存到一个不可修改的Set中。具体代码如下:
// 线程结束时的回调函数
final FutureListener terminationListener = new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
// 注册回调函数
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
Set childrenSet = new LinkedHashSet(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
这个构造函数分析完了,下面分析eventloop以及它的初始化,也就是前面遗留没有分析的children[i] = newChild(executor, args);
newChild
是一个抽象函数:
protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;
我们先看看类NioEventLoopGroup的继承体系:
NioEventLoopGroup的继承体系.png
然后从NioEventLoopGroup开始往上找哪个最底层的类实现了newChild()函数。
然后在类NioEventLoopGroup中找到了它的实现,
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
可见EventExecutor是NioEventLoop的一个实例,按照分析NioEventLoopGroup一样的分析过程,这里我不在粘贴具体代码了,只列出NioEventLoop的关键域的初始值, NioEventLoop的继承体系:
关键域的初始值及说明:
SelectorProvider provider = SelectorProvider.provider() Selector selector = provider.openSelector() SelectStrategy selectStrategy = DefaultSelectStrategyFactory.INSTANCE boolean addTaskWakesUp = false // 添加任务时不wakeup线程eventloop int maxPendingTasks = Math.max(16, SystemPropertyUtil.getInt("io.netty.eventLoop.maxPendingTasks", Integer.MAX_VALUE)); // 最小值为16,默认值为Integer.MAX_VALUE Queue tailTasks = new LinkedBlockingQueue(maxPendingTasks) Queue taskQueue = new LinkedBlockingQueue(maxPendingTasks) EventExecutorGroup parent = 执行newChild函数的NioEventLoopGroup实例 Executor executor = ThreadPerTaskExecutor的实例
这里特别说明一下provider
和selector
。 provider
在不同的操作系统平台下有不同的实现,windowns平台是WindowsSelectorProvider。在linux平台下,如果内核版本>=2.6则,具体的实现为EPollSelectorProvider,否则为默认的PollSelectorProvider。MAC平台下则是KQueueSelectorProvider。 selector
是netty的一个核心概念,封装了不同平台的多路复用网络io模式,eventloop正是通过向selector注册感兴趣的事件(event),然后等待事件发生,从而实现非阻塞异步处理事件的目的。在linux平台下,底层通过epoll实现,执行provider.openSelector()可以理解为执行了epoll_init()系统调用,会返回一个epoll句柄给selector,然后通过selector可以向epoll注册感兴趣的事件,并在事件发生时获取发生的事件,然后对事件进行相应的处理。
你可能感兴趣的:(netty服务端源码分析之eventloop和eventloopgroup)
智邦国际ERP生产排产缩短生产周期
baidu_38202126
生产排产 生产排产缩短生产周期 智邦国际生产排产
智邦国际ERP生产排产缩短生产周期生产排产是指将生产任务分配至生产资源的过程。在考虑能力和设备的前提下,在物料数量一定的情况下,安排各生产任务的生产顺序,优化生产顺序,优化选择生产设备,使得减少等待时间,平衡各机器和工人的生产负荷。从而优化产能,提高生产效率,缩短生产周期.在智邦国际ERP中,审批通过后的合同和生产预测单,生成生产计划,可以按照生产计划单的紧急程度和先后顺序来安排生产排产。步骤如下
《C# using关键字全面解析:资源管理 × 命名空间 × 避坑指南》
Ro小陌
C# 数据库 开发语言 c# 数据库 开发语言
在C#中,using是一个多功能的关键字,主要用于资源管理和命名空间引用。以下是它的两种核心用法和扩展特性:一、using指令(命名空间引用)作用:简化代码中对其他命名空间下类型的访问,避免写冗长的完全限定名。1.基本用法csharpusingSystem;//引入System命名空间usingSystem.IO;//引入文件操作相关类classProgram{staticvoidMain(){C
Arc 浏览器内显示全链接
江梦寻
macos edge浏览器 前端 javascript 经验分享 网络 windows
前言arc浏览器由于其优秀的UI和交互效果获得了一批忠实用户,其分享下载的营销方式抓住用户想尝新的事物。用了好几个月后发现这个浏览器真的不错,方便的小窗方式,简单快速的网页优化方案(boost)等,都让我慢慢放弃了chrome浏览器。目前唯一不爽的一点就是没法显示fullURL。有时候在测试环境和正式环境的相同开发工具中不断切换,会把环境搞乱,因此每次都要从sidebar中检查一遍URL再开始操作
解密网易云音乐Web端的请求参数params与encSecKey
江梦寻
javascript 前端 网络 算法 经验分享
网易云音乐作为一款功能强大的音乐流媒体平台,为用户提供了丰富的音乐体验和社区互动。然而,当用户希望批量下载音乐资源,尤其是整个歌单或某位歌手的全部歌曲时,受限于版权保护和平台策略,官方渠道通常无法直接实现这一需求。在这种情况下,一些技术爱好者或开发者可能会转向使用爬虫技术来获取所需资源。对于像网易云音乐这样通过加密请求参数(如params和encSecKey)来保护数据的平台,逆向工程成为解析这些
HarmonyOS实战开发-高性能ArkUI组件复用实践案例
「已注销」
前端 华为 鸿蒙 harmonyos 华为 鸿蒙 安卓 前端
概述若开发者的应用中存在以下场景,并成为UI线程的帧率瓶颈,应该考虑使用组件复用机制提升应用性能:●列表滚动(本例中的场景):当应用需要展示大量数据的列表,并且用户进行滚动操作时,频繁创建和销毁列表项的视图可能导致卡顿和性能问题。在这种情况下,使用列表组件的组件复用机制可以重用已经创建的列表项视图,提高滚动的流畅度。●动态布局更新:如果应用中的界面需要频繁地进行布局更新,例如根据用户的操作或数据变
基于 MATLAB仿真卡尔曼滤波原理及应用
资深码侬
matlab matlab 开发语言
基于MATLAB仿真卡尔曼滤波原理及应用简介:《卡尔曼滤波原理及应用:MATLAB仿真》主要介绍数字信号处理中的卡尔曼(Kalman)滤波算法及在相关领域应用。《卡尔曼滤波原理及应用:MATLAB仿真》共7章。第1章为绪论。第2章介绍MATLAB算法仿真的编程基础。第3章介绍线性Kalman滤波。第4章讨论扩展Kalman滤波,并介绍其在目标跟踪和制导领域的应用和算法仿真。第5章介绍UKF滤波算法
PTA团体程序设计天梯赛-练习集16-20题
β添砖java
算法 c++ c语言 数据结构
L1-016查验身份证一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:Z:012345678910M:10X98765432现在给定一些身份证号码,请你验证校验码的有
【C++】类和对象(3)(默认成员函数--拷贝构造&赋值重载)
小白要加油努力
C++ c++
引言前文介绍了C++中默认成员函数中的构造函数和析构函数,相信已经对它们的功能与用法有了基本认识,本文接着介绍也很常见的拷贝构造函数和赋值重载函数,便于对C++进一步的学习。拷贝构造函数补充知识:深浅拷贝深拷贝和浅拷贝是C++中对象拷贝的两种不同方式。浅拷贝是指将一个对象的数据成员的值复制到另一个对象中,这样两个对象将共享相同的数据。当其中一个对象修改了数据,另一个对象也会受到影响。深拷贝是指创建
与指针相关的知识点简介(1)
小白要加油努力
C语言 算法 数据结构 c语言
1.字符指针chars1[]="helloworld";chars2[]="helloworld";constchar*s3="helloworld";constchar*s4="helloworld";对于常量字符串来说,会开辟一块独立的空间来存放该常量,字符指针指向的是该空间,故s3和s4指向的空间相同,而s1,s2变量指向的空间不同。2.数组指针数组指针是指向数组的指针。intarr[5]=
山海经——AI思路
Cool_(wly)_Dino
deepseek c++
好的,我需要帮助用户解决这个关于《山海经》的问题。根据用户的问题描述,老师希望找到从第a座山到第b座山之间的某段路径(i,j),使得这段路径上的喜恶度之和最大。用户之前已经得到过一个使用分块算法处理区间最大值查询的C++代码,但现在的问题似乎有所不同,因为这里需要的是最大子数组和,而不是简单的区间最大值。首先,我要确认用户的具体需求。用户提到每座山只能到达下一座山,也就是路径是连续的,所以问题转化
11 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar组件深度剖析(二)
全栈若城
harmonyos从入门到进阶 uv ui ubuntu HarmonyOS NEXT
温馨提示:本篇博客的详细代码已发布到git:https://gitcode.com/nutpi/HarmonyosNext可以下载运行哦!第二篇:探秘Avatar组件的核心实现机制1.组件结构设计2.状态管理2.1组件状态定义@ComponentexportstructAvatar{//私有属性privateprops:AvatarProps={shape:AvatarShape.CIRCLE,s
RTC实时时钟M41T00M6F国产替代FRTC4100S
NYFEA
实时音视频
FRTC4100S是NYFEA徕飞公司推出的一种低功耗的串行实时时钟(RTC)。32.768kHz振荡器由外部晶体控制)和RAM的前8个字节用于时钟/日历功能,并以二进制编码十进制(BCD)格式配置。地址和数据通过双向总线以串行方式传输。内置的地址寄存器在每个写或读数据字节后自动递增。FRTC4100S时钟内置电源检测电路,可在电源故障期间检测到电源故障并自动切换到电池供电。维持时钟运行所需的能量
EasyRTC嵌入式音视频通话SDK:基于ICE与STUN/TURN的实时音视频通信解决方案
EasyCVR
RTC 音视频 实时音视频 h.265 人工智能 webrtc
在当今数字化时代,实时音视频通信技术已成为人们生活和工作中不可或缺的一部分。无论是家庭中的远程看护、办公场景中的远程协作,还是工业领域的远程巡检和智能设备的互联互通,高效、稳定的通信技术都是实现这些功能的核心。EasyRTC嵌入式音视频通话SDK支持多种类型的网络环境,能够适应不同的网络条件,确保在各种场景下都能实现高效、稳定的实时音视频通信。以下是EasyRTC支持的主要网络环境类型:1、有线网
WebRTC简介
小柒的博客
5.linux webrtc
WebRTC简介WebRTC(WebReal-TimeCommunication)是一种支持浏览器之间进行实时音视频通信和数据传输的开放标准和技术。它由Google发起,现已成为W3C和IETF的标准。WebRTC允许开发者在不依赖第三方插件或软件的情况下,直接在网页中实现点对点(P2P)的实时通信。直接在浏览器中运行,无需安装额外的插件或软件。WebRTC是开源技术,并且是W3C和IETF的标准
提升Web可访问性的10个关键实践
zsy_1991
前端 javascript html
在当今互联网时代,确保网站的可访问性(Accessibility)已经成为开发者和设计师的重要任务之一。Web可访问性不仅有助于残障用户更好地访问和使用网站,还能提升整体用户体验。本文将介绍10个关键的Web可访问性实践,帮助你构建更加友好和包容的网站。1.使用语义化的HTML标签语义化的HTML标签不仅有助于搜索引擎优化(SEO),还能提升屏幕阅读器等辅助技术的理解能力。以下是一些常用的语义化标
网络编程之java简易聊天室实现
宏远十一冠王
java基础语法 java 网络
最近浅学习了一些关于网络编程方面的知识,视频是跟着狂神学习的,可能学习的不是很深说到网络,相信大家都对TCP、UDP和HTTP协议这些都不是很陌生,学习这部分应该先对端口、Ip地址这些基础知识有一定了解,后面我们都是直接上demo来解释代码文件传输Tcp方式这里我们指的是C/S架构的文件传输,需要涉及一个客户端Client和服务器端(Server),这里采用的是TCP协议进行传输的,TCP需要经过
C++Primer学习(5.4和5.5 迭代语句和跳转语句)
黑果果的思考
零基础学习C++ c++
5.4迭代语句迭代语句通常称为循环,它重复执行操作直到满足某个条件才停下来。while和for语句在执行循环体之前检查条件,dowhile语句先执行循环体,然后再检查条件。5.4.1while语句只要条件为真,while语句(whilestatement)就重复地执行循环体,它的语法形式是while(condition)statement;在while结构中,只要condition的求值结果为真就
C++Primer学习(5.1和5.2 简单语句和语句作用域)
黑果果的思考
零基础学习C++ c++ 学习
通常情况下,语句是顺序执行的。但除非是最简单的程序,否则仅有顺序执行远远不够。因此,C++语言提供了一组控制流(fow-of-control)语句以支持更复杂的执行路径。5.1简单语句C++语言中的大多数语句都以分号结束,一个表达式,比如iva1+5,末尾加上分号就变成了表达式语句(expressionstatement)。表达式语句的作用是执行表达式并丢弃掉求值结果:ival+5;//一条没什么
C++11新特性—std:function模板类
BeyondESH
算法 C++ 数据结构 c++ java 前端
std::function模板类1.定义std::function是C++11引入的一个模板类,位于头文件中。它是一个通用的可调用对象包装器(functionobjectwrapper),能够存储、复制和调用任何可以调用的目标(Callabletarget),这些目标包括普通函数、Lambda表达式、函数对象(仿函数)、绑定表达式(通过std::bind创建的)以及其他函数对象等。2.特点std:
swagger-01-swagger介绍
褚师子书
swagger java spring boot restful
swagger1.学习目标:了解前后端分离了解Swagger的作用和概念在SpringBoot中集成Swagger1.1swagger由来前后端分离,当前流行的开发模式Vue+SpringBoot早先的后端时代:前端只用管理静态页面;后端将html用模板引擎JSP进行开发前后端分离式时代:后端:后端控制层,服务层,数据访问层【后端团队】前端:前端控制层,视图层【前端团队】mock后端数据json,
深入理解 Python 中的 copy 与 deepcopy 的使用
web安全工具库
python 开发语言
各类资料学习下载合集https://pan.quark.cn/s/8c91ccb5a474在Python中,数据的复制是一个重要的操作,尤其是在处理复杂数据结构(如列表、字典、集合等)时。copy和deepcopy是Python标准库copy模块提供的两种复制方法。它们之间有着明显的区别,理解这些区别对于避免潜在的错误和数据问题至关重要。本文将详细介绍copy和deepcopy的用法,包括代码示例
就在刚刚!马斯克决定将“地球上最聪明的人工智能”Grok-3免费了!
源代码杀手
AI技术快讯 人工智能 python
Grok-3概述与关键功能Grok-3是由xAI开发的先进AI模型,于2025年2月19日发布,旨在提升推理能力、计算能力和适应性,特别适用于数学、科学和编程问题。作为xAI系列模型的最新版本,Grok-3延续了公司对构建强大且安全的AI系统的承诺,并推动人工智能在多个领域的应用。Grok-3的核心优势在于其大规模强化学习(RL)优化,能够在几秒到几分钟内进行深度推理,适应复杂任务的需求。配备的D
python前景和待遇-Python就业前景怎么样?薪资待遇多少
weixin_37988176
Python就业前景怎么样?薪资待遇多少?Python上手容易,入门简单Python是一门面向对象的编程语言,编译速度超快。它具有丰富和强大的库,常被称为"胶水语言”,能够把用其他语言编写的各种模块(尤其是C/C)很轻松地联结在一起。其特点在于灵活运用,因为其拥有大量第三方库,所以开发人员不必重复造轮子,就像搭积木一样,只要擅于利用这些库就可以完成绝大部分工作。如果你想选择一种语言来入门编程,那么
没有最好的,只有最合适的:重新认识测试工具的价值
测试者家园
软件测试 测试开发和测试 质量效能 测试工具 软件测试 人工智能 智能化测试 自动化测试 自主化测试
用ChatGPT做软件测试在软件测试领域,关于“测试工具是否有好坏之分”的问题常常引发热议。一方面,经验丰富的测试专家通常有自己偏爱的工具和方法,另一方面,新手常困惑于琳琅满目的测试工具库,渴望寻找“最好”的工具。然而,测试工具真的有绝对的好坏之分吗?本文将从多维度剖析这个问题,旨在帮助读者开阔视野,重新思考测试工具的选择与价值。一、工具好坏的判断标准:适用性胜于绝对性1.1目标导向性:工具的价值
DeepSeek这么火,一文教你本地部署DeepSeek!
入职啦
python python deepseek 部署 持续部署 AI 人工智能
要说年假最火的是什么,DeepSeek绝对在话题榜上,公众号几乎都是关于他的,今天入职啦也来和大家聊一聊我们AI领域的新星–DeepSeek,顺便也教大家部署一套属于自己的本地搜索服务。为什么DeepSeek这么火?一、技术架构优势DeepSeek采用创新的混合模型架构,将传统机器学习与深度学习有机结合。这种架构既保留了传统方法的可解释性,又具备深度学习的强大表征能力。通过自适应学习机制,Deep
Adobe InCopy[IC2024]文本编辑软件下载安装与使用(附win/mac安装包)
sdbaerhz
html css 前端 adobe macos windows
安装包https://pan.baidu.com/s/1CfATbRzYK6nh4e2qzo0mXw?pwd=faf3一、功能介绍1.1文本编辑功能AdobeInCopy提供强大的文本编辑功能,使用户可以方便地进行文本排版、格式调整和样式应用。它支持基本的文字处理功能,如拼写检查、查找与替换、段落和字符样式的创建与应用,帮助编辑在工作中保持内容的一致性和专业性。用户还可以通过使用文本框和文本流,来
Nginx给Vue和Java后端做代理
入职啦
实战项目知识 vue.js nginx java
本文发表于入职啦(公众号:ruzhila)可以访问入职啦查看更多技术文章网站架构入职啦采用了Nuxt.js、Vue3、Go的混合架构开发,包括了官网、简历工具、职位搜索、简历搜索等功能。为三个部分:官网:采用Nuxt.js+Vue3+TailwindCSS开发,属于SSR渲染简历工具:采用Vue3+TailwindCSS开发,属于SPA渲染后端:采用Gin+Gorm+MySQL开发,提供API接口
Python开发行业薪资多少?
Java大师兄-威哥
Python 编程 IT技术 程序员 IT
大家都知道,人工智能越来越受欢迎了。而Python由于简单易用,是人工智能领域中使用最广泛的编程语言之一,它可以无缝地与数据结构和其他常用的AI算法一起使用。Python开发行业薪资多少?我们看看图片就能知道个大概。无论是国内还是国外对于编程语言的热度调查中,Python都是数得上名的。Python热度的持续升温,自然也引起了开源团队的项目。由于OSI认可的开放源码许可,程序员可以使用Python
JDK 17 和JDK 8 相比增加了哪些新特性
阿好程序
Java基础篇 java jvm 开发语言
JDK17新特性JDK17和JDK8相比增加了哪些新特性文章目录JDK17新特性前言一、JDK17的新特性有哪些?二、新特性Java代码演示1.Sealedclasses2.Patternmatchingforinstanceof3Records4Textblocks5Switchexpressions6StrongencapsulationofJDKinternals7Foreignfuncti
TouchGFX之图像
Stone_lu。
STM32 arm开发
touchgfx提供的几种图像控件1.Image(图像)TouchGFX中的图像会绘制关联图像文件中的像素数据。使用图像文件前,必须将其导入到项目中。图像大小是由关联的图像文件定义的,不能在运行时改动。如果需要将图像显示为不同大小,需要调整关联的导入图像的大小。这一要求是出于性能原因。图像位于TouchGFXDesigner中的图像控件组中。
集合框架
天子之骄
java 数据结构 集合框架
集合框架
集合框架可以理解为一个容器,该容器主要指映射(map)、集合(set)、数组(array)和列表(list)等抽象数据结构。
从本质上来说,Java集合框架的主要组成是用来操作对象的接口。不同接口描述不同的数据类型。
简单介绍:
Collection接口是最基本的接口,它定义了List和Set,List又定义了LinkLi
Table Driven(表驱动)方法实例
bijian1013
java enum Table Driven 表驱动
实例一:
/**
* 驾驶人年龄段
* 保险行业,会对驾驶人的年龄做年龄段的区分判断
* 驾驶人年龄段:01-[18,25);02-[25,30);03-[30-35);04-[35,40);05-[40,45);06-[45,50);07-[50-55);08-[55,+∞)
*/
public class AgePeriodTest {
//if...el
Jquery 总结
cuishikuan
java jquery Ajax Web jquery方法
1.$.trim方法用于移除字符串头部和尾部多余的空格。如:$.trim(' Hello ') // Hello2.$.contains方法返回一个布尔值,表示某个DOM元素(第二个参数)是否为另一个DOM元素(第一个参数)的下级元素。如:$.contains(document.documentElement, document.body); 3.$
面向对象概念的提出
麦田的设计者
java 面向对象 面向过程
面向对象中,一切都是由对象展开的,组织代码,封装数据。
在台湾面向对象被翻译为了面向物件编程,这充分说明了,这种编程强调实体。
下面就结合编程语言的发展史,聊一聊面向过程和面向对象。
c语言由贝尔实
linux网口绑定
被触发
linux
刚在一台IBM Xserver服务器上装了RedHat Linux Enterprise AS 4,为了提高网络的可靠性配置双网卡绑定。
一、环境描述
我的RedHat Linux Enterprise AS 4安装双口的Intel千兆网卡,通过ifconfig -a命令看到eth0和eth1两张网卡。
二、双网卡绑定步骤:
2.1 修改/etc/sysconfig/network
XML基础语法
肆无忌惮_
xml
一、什么是XML?
XML全称是Extensible Markup Language,可扩展标记语言。很类似HTML。XML的目的是传输数据而非显示数据。XML的标签没有被预定义,你需要自行定义标签。XML被设计为具有自我描述性。是W3C的推荐标准。
二、为什么学习XML?
用来解决程序间数据传输的格式问题
做配置文件
充当小型数据库
三、XML与HTM
为网页添加自己喜欢的字体
知了ing
字体 秒表 css
@font-face {
font-family: miaobiao;//定义字体名字
font-style: normal;
font-weight: 400;
src: url('font/DS-DIGI-e.eot');//字体文件
}
使用:
<label style="font-size:18px;font-famil
redis范围查询应用-查找IP所在城市
矮蛋蛋
redis
原文地址:
http://www.tuicool.com/articles/BrURbqV
需求
根据IP找到对应的城市
原来的解决方案
oracle表(ip_country):
查询IP对应的城市:
1.把a.b.c.d这样格式的IP转为一个数字,例如为把210.21.224.34转为3524648994
2. select city from ip_
输入两个整数, 计算百分比
alleni123
java
public static String getPercent(int x, int total){
double result=(x*1.0)/(total*1.0);
System.out.println(result);
DecimalFormat df1=new DecimalFormat("0.0000%");
百合——————>怎么学习计算机语言
百合不是茶
java 移动开发
对于一个从没有接触过计算机语言的人来说,一上来就学面向对象,就算是心里上面接受的了,灵魂我觉得也应该是跟不上的,学不好是很正常的现象,计算机语言老师讲的再多,你在课堂上面跟着老师听的再多,我觉得你应该还是学不会的,最主要的原因是你根本没有想过该怎么来学习计算机编程语言,记得大一的时候金山网络公司在湖大招聘我们学校一个才来大学几天的被金山网络录取,一个刚到大学的就能够去和
linux下tomcat开机自启动
bijian1013
tomcat
方法一:
修改Tomcat/bin/startup.sh 为:
export JAVA_HOME=/home/java1.6.0_27
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export PATH=$JAVA_HOME/bin:$PATH
export CATALINA_H
spring aop实例
bijian1013
java spring AOP
1.AdviceMethods.java
package com.bijian.study.spring.aop.schema;
public class AdviceMethods {
public void preGreeting() {
System.out.println("--how are you!--");
}
}
2.beans.x
[Gson八]GsonBuilder序列化和反序列化选项enableComplexMapKeySerialization
bit1129
serialization
enableComplexMapKeySerialization配置项的含义
Gson在序列化Map时,默认情况下,是调用Key的toString方法得到它的JSON字符串的Key,对于简单类型和字符串类型,这没有问题,但是对于复杂数据对象,如果对象没有覆写toString方法,那么默认的toString方法将得到这个对象的Hash地址。
GsonBuilder用于
【Spark九十一】Spark Streaming整合Kafka一些值得关注的问题
bit1129
Stream
包括Spark Streaming在内的实时计算数据可靠性指的是三种级别:
1. At most once,数据最多只能接受一次,有可能接收不到
2. At least once, 数据至少接受一次,有可能重复接收
3. Exactly once 数据保证被处理并且只被处理一次,
具体的多读几遍http://spark.apache.org/docs/lates
shell脚本批量检测端口是否被占用脚本
ronin47
#!/bin/bash
cat ports |while read line
do#nc -z -w 10 $line
nc -z -w 2 $line 58422>/dev/null2>&1if[ $?-eq 0]then
echo $line:ok
else
echo $line:fail
fi
done
这里的ports 既可以是文件
java-2.设计包含min函数的栈
bylijinnan
java
具体思路参见:http://zhedahht.blog.163.com/blog/static/25411174200712895228171/
import java.util.ArrayList;
import java.util.List;
public class MinStack {
//maybe we can use origin array rathe
Netty源码学习-ChannelHandler
bylijinnan
java netty
一般来说,“有状态”的ChannelHandler不应该是“共享”的,“无状态”的ChannelHandler则可“共享”
例如ObjectEncoder是“共享”的, 但 ObjectDecoder 不是
因为每一次调用decode方法时,可能数据未接收完全(incomplete),
它与上一次decode时接收到的数据“累计”起来才有可能是完整的数据,是“有状态”的
p
java生成随机数
cngolon
java
方法一:
/**
* 生成随机数
* @author cngolon@126.com
* @return
*/
public synchronized static String getChargeSequenceNum(String pre){
StringBuffer sequenceNum = new StringBuffer();
Date dateTime = new D
POI读写海量数据
ctrain
海量数据
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming
mysql 日期格式化date_format详细使用
daizj
mysql date_format 日期格式转换 日期格式化
日期转换函数的详细使用说明
DATE_FORMAT(date,format) Formats the date value according to the format string. The following specifiers may be used in the format string. The&n
一个程序员分享8年的开发经验
dcj3sjt126com
程序员
在中国有很多人都认为IT行为是吃青春饭的,如果过了30岁就很难有机会再发展下去!其实现实并不是这样子的,在下从事.NET及JAVA方面的开发的也有8年的时间了,在这里在下想凭借自己的亲身经历,与大家一起探讨一下。
明确入行的目的
很多人干IT这一行都冲着“收入高”这一点的,因为只要学会一点HTML, DIV+CSS,要做一个页面开发人员并不是一件难事,而且做一个页面开发人员更容
android欢迎界面淡入淡出效果
dcj3sjt126com
android
很多Android应用一开始都会有一个欢迎界面,淡入淡出效果也是用得非常多的,下面来实现一下。
主要代码如下:
package com.myaibang.activity;
import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.CountDown
linux 复习笔记之常见压缩命令
eksliang
tar解压 linux系统常见压缩命令 linux压缩命令 tar压缩
转载请出自出处:http://eksliang.iteye.com/blog/2109693
linux中常见压缩文件的拓展名
*.gz gzip程序压缩的文件
*.bz2 bzip程序压缩的文件
*.tar tar程序打包的数据,没有经过压缩
*.tar.gz tar程序打包后,并经过gzip程序压缩
*.tar.bz2 tar程序打包后,并经过bzip程序压缩
*.zi
Android 应用程序发送shell命令
gqdy365
android
项目中需要直接在APP中通过发送shell指令来控制lcd灯,其实按理说应该是方案公司在调好lcd灯驱动之后直接通过service送接口上来给APP,APP调用就可以控制了,这是正规流程,但我们项目的方案商用的mtk方案,方案公司又没人会改,只调好了驱动,让应用程序自己实现灯的控制,这不蛋疼嘛!!!!
发就发吧!
一、关于shell指令:
我们知道,shell指令是Linux里面带的
java 无损读取文本文件
hw1287789687
读取文件 无损读取 读取文本文件 charset
java 如何无损读取文本文件呢?
以下是有损的
@Deprecated
public static String getFullContent(File file, String charset) {
BufferedReader reader = null;
if (!file.exists()) {
System.out.println("getFull
Firebase 相关文章索引
justjavac
firebase
Awesome Firebase
最近谷歌收购Firebase的新闻又将Firebase拉入了人们的视野,于是我做了这个 github 项目。
Firebase 是一个数据同步的云服务,不同于 Dropbox 的「文件」,Firebase 同步的是「数据」,服务对象是网站开发者,帮助他们开发具有「实时」(Real-Time)特性的应用。
开发者只需引用一个 API 库文件就可以使用标准 RE
C++学习重点
lx.asymmetric
C++ 笔记
1.c++面向对象的三个特性:封装性,继承性以及多态性。
2.标识符的命名规则:由字母和下划线开头,同时由字母、数字或下划线组成;不能与系统关键字重名。
3.c++语言常量包括整型常量、浮点型常量、布尔常量、字符型常量和字符串性常量。
4.运算符按其功能开以分为六类:算术运算符、位运算符、关系运算符、逻辑运算符、赋值运算符和条件运算符。
&n
java bean和xml相互转换
q821424508
java bean xml xml和bean转换 java bean和xml转换
这几天在做微信公众号
做的过程中想找个java bean转xml的工具,找了几个用着不知道是配置不好还是怎么回事,都会有一些问题,
然后脑子一热谢了一个javabean和xml的转换的工具里,自己用着还行,虽然有一些约束吧 ,
还是贴出来记录一下
顺便你提一下下,这个转换工具支持属性为集合、数组和非基本属性的对象。
packag
C 语言初级 位运算
1140566087
位运算 c
第十章 位运算 1、位运算对象只能是整形或字符型数据,在VC6.0中int型数据占4个字节 2、位运算符: 运算符 作用 ~ 按位求反 << 左移 >> 右移 & 按位与 ^ 按位异或 | 按位或 他们的优先级从高到低; 3、位运算符的运算功能: a、按位取反: ~01001101 = 101
14点睛Spring4.1-脚本编程
wiselyman
spring4
14.1 Scripting脚本编程
脚本语言和java这类静态的语言的主要区别是:脚本语言无需编译,源码直接可运行;
如果我们经常需要修改的某些代码,每一次我们至少要进行编译,打包,重新部署的操作,步骤相当麻烦;
如果我们的应用不允许重启,这在现实的情况中也是很常见的;
在spring中使用脚本编程给上述的应用场景提供了解决方案,即动态加载bean;
spring支持脚本