当前位置: 首页 > news >正文

理解io/nio/netty

一、io

io即input/output,输入和输出

1.1 分类

输入流、输出流(按数据流向)
字节流(InputStream/OutputStream(细分File/Buffered))、字符流(Reader/Writer(细分File/Buffered/put))(按数据处理方式)
字节缓存流:避免频繁的io操作,缓冲区的大小默认为 8192 字节

二、字节

  • 字节:存储数据的单元
    1byte=8bit
    一个英文字母=1byte,一个汉字=2byte
  • 字符:1字符=2byte

三、nio

3.1 基本概念

  • 同步:当前任务完成前,不能做其他操作(单线程)
  • 异步:当前任务完成前,可以做其他操作(多线程)
  • 阻塞:当前任务挂起,不能做其他操作的状态(等待)
  • 非阻塞:当前任务进行中,无需挂起,可以做其他操作的状态(一心二用)

3.2 定义

bio为同步阻塞模式
nio为同步非阻塞模式,一个线程管理多个输入输出通道,涉及轮询、多路复用(一个线程不断轮询多个socket的状态,当socket有读写事件时调用io事件)

核心:channel(双向)、buffer、selector(监听通道事件)

3.3 流程

服务器端(pool)
属性:线程池、选择器selector

  • 创建一个PoolServer,
  • 初始化,并指定端口
    开通渠道ServerSocketChannel
    设置非阻塞
    绑定端口
    开通选择器
    将渠道注册到选择器
  • 监听事件
    轮询访问选择器
    处理对应的通道事件
    如果事件key状态为可接收:注册通道到选择器,设置状态为可读
    如果事件key状态为可读:将key对应通道设置为可读,线程池执行key对应的继承Thread的handler方法,重写run方法(通过key拿到通道;分配缓冲区,分配输出流;将通道读取的缓冲区内容写入输出流;将服务端回执写入通道;将通道设置可读;唤醒选择器)

3.4 应用

客户端:

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class Client {public static void main(String[] args) throws IOException {Socket s = new Socket("127.0.0.1", 8888);s.getOutputStream().write("HelloServer".getBytes());s.getOutputStream().flush();System.out.println("write over, waiting for msg back...");byte[] bytes = new byte[1024];int len = s.getInputStream().read(bytes);System.out.println(new String(bytes, 0, len));s.close();}
}

服务端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class Server {public static void main(String[] args) throws IOException {ServerSocketChannel ssc = ServerSocketChannel.open();ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8888));ssc.configureBlocking(false);System.out.println("server started, listening on :" + ssc.getLocalAddress());Selector selector = Selector.open();ssc.register(selector, SelectionKey.OP_ACCEPT);while(true) {selector.select();Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> it = keys.iterator();while(it.hasNext()) {SelectionKey key = it.next();it.remove();handle(key);}}}private static void handle(SelectionKey key) {if(key.isAcceptable()) {try {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(key.selector(), SelectionKey.OP_READ );} catch (IOException e) {e.printStackTrace();} finally {}} else if (key.isReadable()) { //flipSocketChannel sc = null;try {sc = (SocketChannel)key.channel();ByteBuffer buffer = ByteBuffer.allocate(512);buffer.clear();int len = sc.read(buffer);if(len != -1) {System.out.println(new String(buffer.array(), 0, len));}ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes());sc.write(bufferToWrite);} catch (IOException e) {e.printStackTrace();} finally {if(sc != null) {try {sc.close();} catch (IOException e) {e.printStackTrace();}}}}}
}

服务端:pool

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class PoolServer {ExecutorService pool = Executors.newFixedThreadPool(50);private Selector selector;/**** @throws IOException*/public static void main(String[] args) throws IOException {PoolServer server = new PoolServer();server.initServer(8000);server.listen();}/**** @param port* @throws IOException*/public void initServer(int port) throws IOException {//ServerSocketChannel serverChannel = ServerSocketChannel.open();//serverChannel.configureBlocking(false);//serverChannel.socket().bind(new InetSocketAddress(port));//this.selector = Selector.open();serverChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务端启动成功!");}/**** @throws IOException*/@SuppressWarnings("unchecked")public void listen() throws IOException {// 轮询访问selector  while (true) {//selector.select();//Iterator ite = this.selector.selectedKeys().iterator();while (ite.hasNext()) {SelectionKey key = (SelectionKey) ite.next();//ite.remove();//if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();//SocketChannel channel = server.accept();//channel.configureBlocking(false);//channel.register(this.selector, SelectionKey.OP_READ);//} else if (key.isReadable()) {//key.interestOps(key.interestOps()&(~SelectionKey.OP_READ));//pool.execute(new ThreadHandlerChannel(key));}}}}
}/**** @param* @throws IOException*/
class ThreadHandlerChannel extends Thread{private SelectionKey key;ThreadHandlerChannel(SelectionKey key){this.key=key;}@Overridepublic void run() {//SocketChannel channel = (SocketChannel) key.channel();//ByteBuffer buffer = ByteBuffer.allocate(1024);//ByteArrayOutputStream baos = new ByteArrayOutputStream();try {int size = 0;while ((size = channel.read(buffer)) > 0) {buffer.flip();baos.write(buffer.array(),0,size);buffer.clear();}baos.close();//byte[] content=baos.toByteArray();ByteBuffer writeBuf = ByteBuffer.allocate(content.length);writeBuf.put(content);writeBuf.flip();channel.write(writeBuf);//if(size==-1){channel.close();}else{//key.interestOps(key.interestOps()|SelectionKey.OP_READ);key.selector().wakeup();}}catch (Exception e) {System.out.println(e.getMessage());}}
}

四、netty

netty是JBoss提供的开源网络编程框架,提供异步的、基于事件驱动的网络应用程序框架和工具。

架构
三层网络架构,Reactor 通信调度层 -> 职责链 PipeLine -> 业务逻辑处理层

为什么选择netty

  • API使用简单,开发门槛低
  • 功能强大,预置了多种编解码功能,支持多种主流协议
  • 定制能力强,可以通过ChannelHandler对通信框架进行灵活的扩展
  • 性能高,通过与其他业界主流的nio框架对比,netty的综合性能最优
  • 成熟、稳定,netty修复了已经发现的所有的JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦恼
  • 社区活跃,版本迭代周期短,发现的BUGkey倍及时修复,同时更多的新功能会被加入
  • 经历了大规模的商业应用考验,质量已经得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它可以完全满足不同行业的商业应用。

4.1 流程

在这里插入图片描述
netty的接收和发送ByteBuffer采用direct buffers,使用堆外直接内存进行socket读写,不需要进行字节缓冲区的二次拷贝。(如果使用传统的堆内存进行socket读写,JVM会将堆内存buffer拷贝一份到直接内存中,然后才写入socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。)

  • 服务端:

创建服务端并指定端口,启动服务端
创建boss和worker事件组
绑定事件组到通道,并指定子处理器,初始化通道,将处理器(继承ChannelHandlerContext,重写读方法(获取信息,将信息写入上下文,关闭上下文)以及异常捕获方法(关闭上下文))加到管道的最后
绑定端口获取future

  • 客户端:

创建客户端,启动客户端
创建workers事件组
绑定事件组到通道,并指定处理器,初始化通道,将定义的客户端处理器(继承ChannelInboundHandlerAdapter,重写通道激活方法(将信息写入上下文,获取future,添加监听器,当服务端收到信息时输出提示信息)以及读方法(读取信息,最后释放信息))添加到管道的后面
绑定端口,获取future

4.2 应用

服务端

import com.mashibing.io.aio.Server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.CharsetUtil;public class HelloNetty {public static void main(String[] args) {new NettyServer(8888).serverStart();}
}class NettyServer {int port = 8888;public NettyServer(int port) {this.port = port;}public void serverStart() {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new Handler());}});try {ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}class Handler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//super.channelRead(ctx, msg);System.out.println("server: channel read");// ByteBuf是netty的一个字节容器ByteBuf buf = (ByteBuf)msg;System.out.println(buf.toString(CharsetUtil.UTF_8));ctx.writeAndFlush(msg);ctx.close();//buf.release();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {//super.exceptionCaught(ctx, cause);cause.printStackTrace();ctx.close();}
}

客户端

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.ReferenceCountUtil;public class Client {public static void main(String[] args) {new Client().clientStart();}private void clientStart() {EventLoopGroup workers = new NioEventLoopGroup();Bootstrap b = new Bootstrap();b.group(workers).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {System.out.println("channel initialized!");ch.pipeline().addLast(new ClientHandler());}});try {System.out.println("start to connect...");ChannelFuture f = b.connect("127.0.0.1", 8888).sync();f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {workers.shutdownGracefully();}}}class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("channel is activated.");final ChannelFuture f = ctx.writeAndFlush(Unpooled.copiedBuffer("HelloNetty".getBytes()));f.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {System.out.println("msg send!");//ctx.close();}});}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {try {ByteBuf buf = (ByteBuf)msg;System.out.println(buf.toString());} finally {ReferenceCountUtil.release(msg);}}
}

场景

  • 构建高性能、低时延的各种Java中间件,
    例如MQ、分布式服务框架、ESB消息总线,netty主要作为基础框架提供高性能、低时延的通信服务
  • 共有或者私有协议栈的基础通信框架,
    例如可以基于netty构建异步、高性能的websocket协议栈
  • 各领域应用,netty作为高性能的通信框架用于内部各模块的数据分发、传输和汇总等,实现模块之间高性能通信
    例如大数据、游戏等

4.3 拆包器

TCP拆包粘包

发送的数据出现断开接收或者多个包数据发生粘连

  • 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包
  • 待发送数据大于MSS最大报文长度,TCP在传输前将进行拆包
  • 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包
  • 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包

解决方法

  • 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度 了
  • 发送端将每个数据包封装为固定长度,这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开
  • 可以在数据包之间设置边界,如添加特殊符号,这样接收端通过这个边界就可以将不同的数据包拆分开

netty提供了封装的拆包器:

  • 固定长度
  • 分隔符
  • 基于长度域(最通用)

4.4 零拷贝

传统拷贝:需要4次数据拷贝和4次上下文切换
磁盘->内核缓冲区的read buffer->用户缓冲区->内核的socket buffer->网卡接口(硬件)的缓冲区

零拷贝:省略中间的2步,不需要CPU的参与
磁盘->内核缓冲区的read buffer->网卡接口(硬件)的缓冲区
零拷贝是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。而它通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间,而直接在内核空间中传输到网络的方式。

相关文章:

理解io/nio/netty

一、io io即input/output&#xff0c;输入和输出 1.1 分类 输入流、输出流&#xff08;按数据流向&#xff09; 字节流&#xff08;InputStream/OutputStream&#xff08;细分File/Buffered&#xff09;&#xff09;、字符流(Reader/Writer&#xff08;细分File/Buffered/pu…...

旅游品牌网站搭建的作用是什么

我国旅游业规模非常高&#xff0c;各地大小旅游景区也是非常多&#xff0c;尤其节假日更是可以达到峰值&#xff0c;无论周边游还是外地游对所要去的景区&#xff0c;消费者总是需要来回了解很多&#xff0c;浏览器查或旅行社咨询等。 对旅游企业而言&#xff0c;传统线下方式…...

Linux操作系统——进程(五)环境变量

环境变量 有了我们前面的命令行参数的理解基础呢&#xff0c;我们下面进入环境变量这一个部分的内容的学习。 一般在我们安装一些开发工具尤其是有解释器的开发工具的时候&#xff0c;我们呢一般都要配置环境变量&#xff0c;可能都不太清楚自己为什么要配置环境变量&#xf…...

西门子博途怎么使用PID_Compact做pid调试

到目前为止&#xff0c;我已经在S7-1200中创建了一个可运行的PLC程序&#xff0c;并在Basic Panel中创建了一个HMI项目来操纵和操作该程序。 引文&#xff1a;博途工控人平时在哪里技术交流博途工控人社群 现在&#xff0c;我们该如何深入的让程序开始逐渐智能化呢&#xff0c…...

结构型模式 | 适配器模式

一、适配器模式 1、原理 适配器模式&#xff08;Adapter&#xff09;&#xff0c;将一个类的接口转换成客户希望的另外一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式主要分为三类&#xff1a;类适配器模式、对象适配器模式、接口…...

基于Python的车牌识别系统实现

本文将以基于Python的车牌识别系统实现为方向&#xff0c;介绍车牌识别技术的基本原理、常用算法和方法&#xff0c;并详细讲解如何利用Python语言实现一个完整的车牌识别系统。 精彩专栏持续更新推荐订阅&#xff0c;收藏关注不迷路 微信小程序实战开发专栏 目录 引言车牌识别…...

时间序列预测模型介绍及使用经验总结

1. 时序预测背景 时序数据&#xff0c;就是序列随时间变化的数据。时间序列分析&#xff0c;一般有时域和频域两种分析方法。时序预测的本质是在时域和频域层面探索时间序列变化的内在规律。 下图描述的是时域&#xff08;temporal domain&#xff09;&#xff0c;横坐标是时…...

Docker知识总结

文章目录 Docker1 Docker简介1.1 什么是虚拟化1.2 什么是Docker1.3 容器与虚拟机比较1.4 Docker 组件1.4.1 Docker服务器与客户端1.4.2 Docker镜像与容器1.4.3 Registry&#xff08;注册中心&#xff09; 2 Docker安装与启动2.1 安装Docker2.2 设置ustc的镜像2.3 Docker的启动与…...

算法训练营Day25

#Java #回溯 开源学习资料 Feeling and experiences&#xff1a; 复原IP地址&#xff1a;力扣题目链接 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1…...

docker笔记2-docker 容器

docker 容器的运行 docker run 镜像名&#xff1a;版本标签&#xff1a; 创建 启动容器 docker run 镜像名 &#xff0c;如果镜像不存在&#xff0c;则会在线下载镜像。 注意事项&#xff1a; 容器内的进程必须处于前台运行状态&#xff0c;不能后台&#xff08;守护进程运行…...

redis 从0到1完整学习 (七):ZipList 数据结构

文章目录 1. 引言2. redis 源码下载3. zipList 数据结构3.1 整体3.2 entry 数据结构分析3.3 连锁更新 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1完整学习 &#xff08;二&am…...

2015年第四届数学建模国际赛小美赛C题科学能解决恐怖主义吗解题全过程文档及程序

2015年第四届数学建模国际赛小美赛 C题 科学能解决恐怖主义吗 原题再现&#xff1a; 为什么人们转向恐怖主义&#xff0c;特别是自杀性恐怖主义&#xff1f;主要原因是什么&#xff1f;这通常是大问题和小问题的结合&#xff0c;或者是一些人所说的“推拉”因素。更大的问题包…...

基于Java开发的微信约拍小程序

一、系统架构 前端&#xff1a;vue | element-ui 后端&#xff1a;springboot | mybatis 环境&#xff1a;jdk8 | mysql8 | maven | mysql 二、代码及数据库 三、功能说明 01. 首页 02. 授权登录 03. 我的 04. 我的-编辑个人资料 05. 我的-我的联系方式 06. …...

蓝桥杯的学习规划

c语言基础&#xff1a; Python语言基础 学习路径&#xff1a;画框的要着重学习...

EMC噪声的本质

01 频谱的含义 频谱是将电磁波分解为正弦波分量&#xff0c;并按波长顺序排列的波谱&#xff0c;就是将具有复杂组成的东西分解&#xff08;频谱分析仪&#xff09;为单纯成分&#xff0c;并把这些成分按其特征量的大小依序排列&#xff08;部分不计&#xff09;&#xff0c;…...

Redis遇到过的问题 (Could not get a resource from the pool )

生产上通过scan命令&#xff0c;查询一个大key耗时40s后&#xff0c;报 Could not get a resource from the pool&#xff0c;初步报错是连接池的连接数不够&#xff0c;从网上搜了一些解决方案。 排查过程&#xff1a; 一、首先需要先尝试连接redis&#xff0c;如果连接不上那…...

Spring Boot 3.2 新特性之 HTTP Interface

SpringBoot 3.2引入了新的 HTTP interface 用于http接口调用&#xff0c;采用了类似 openfeign 的风格。 具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-http-interface 一、概述 HTTP Interface 是一个类似于 openfeign 的同步接口调…...

Flask+Mysql项目docker-compose部署(Pythondocker-compose详细步骤)

一、前言 环境&#xff1a; Linux、docker、docker-compose、python(Flask)、Mysql 简介&#xff1a; 简单使用Flask框架写的查询Mysql数据接口&#xff0c;使用docker部署&#xff0c;shell脚本启动 优势&#xff1a; 采用docker方式部署更加便于维护&#xff0c;更加简单快…...

DDOS攻击简介——什么是DDOS

DDoS是什么? DDoS是分布式拒绝服务攻击(Distributed denial of service attack)的简称。 分布式拒绝服务器攻击(以下均称作DDoS)是一种可以使很多计算机(或服务器)在同一时间遭受攻击&#xff0c;使被攻击的目标无法正常使用的一种网络攻击方式。DDoS攻击在互联网上已经出现过…...

龙蜥开源操作系统能解决CentOS 停服造成的空缺吗?

龙蜥开源操作系统能解决CentOS 停服造成的空缺吗&#xff1f; 本文图片来源于龙蜥&#xff0c;仅做介绍时引用用途&#xff0c;版权归属龙蜥和相关设计人员。 一、《国产服务器操作系统发展报告&#xff08;2023&#xff09;》称操作系统已步入 2.0 时代&#xff0c;服务器操作…...

『Linux升级路』基础开发工具——gdb篇

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、背景知识介绍 二、gdb指令介绍 一、背景知识介绍 在软件开发中&#xff0c…...

边缘计算云边端全览—边缘计算系统设计与实践【文末送书-10】

文章目录 一.边缘计算1.1边缘计算的典型应用 二.边缘计算 VS 云计算三.边缘计算系统设计与实践【文末送书-10】3.1 粉丝福利&#xff1a;文末推荐与福利免费包邮送书&#xff01; 一.边缘计算 边缘计算是指在靠近物或数据源头的一侧&#xff0c;采用网络、计算、存储、应用核心…...

使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错的问题

目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序&#xff0c;查看库与库的依赖关系&#xff0c;找出出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总&#xff08;专栏文章列表&…...

Servlet技术之Cookie对象与HttpSession对象

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 Servlet技术之Cookie对象与HttpSession对象 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前…...

winlogbeat收集Windows事件日志传给ELK

服务器部署winlogbeat后&#xff0c;修改winlogbeat.yml: ###################### Winlogbeat Configuration Example ######################### This file is an example configuration file highlighting only the most common # options. The winlogbeat.reference.yml fi…...

Gin框架之使用 go-ini 加载.ini 配置文件

首先,联想一个问题,我们在部署服务时,通常为了方便,对于需要迭代更新的代码进行修改,但是比对shell,可以搞一个变量将需要修改的,以及修改起来变动处多的,写在变量内,到时候如果需要变更,可以直接变更变量即可; 那么,golang有没有什么方式可以将需要变的东西保存起…...

SpringMVC:整合 SSM 上篇

文章目录 SpringMVC - 03整合 SSM 上篇一、准备工作二、MyBatis 层1. dao 层2. service 层 三、Spring 层四、SpringMVC 层五、执行六、说明 SpringMVC - 03 整合 SSM 上篇 用到的环境&#xff1a; IDEA 2019&#xff08;JDK 1.8&#xff09;MySQL 8.0.31Tomcat 8.5.85Maven…...

BFS解决多源最短路相关leetcode算法题

文章目录 1.01矩阵2.飞地的数量3.地图中的最高点4.地图分析 1.01矩阵 01矩阵 class Solution {int dx[4] {0,0,1,-1};int dy[4] {1,-1,0,0}; public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {//正难则反&#xff0c;找0…...

ARM GIC(四) gicv3架构基础

GICv3架构是GICv2架构的升级版&#xff0c;增加了很多东西。变化在于以下&#xff1a; 使用属性层次&#xff08;affinity hierarchies&#xff09;&#xff0c;来对core进行标识&#xff0c;使gic支持更多的core 将cpu interface独立出来&#xff0c;用户可以将其设计在core…...

Kafka日志

位置 server.properties配置文件中通过log.dir指定日志存储目录 log.dir/{topic}-{partition} 核心文件 .log 存储消息的日志文件&#xff0c;固定大小为1G&#xff0c;写满后会新增一个文件&#xff0c;文件名表示当前日志文件记录的第一条消息的偏移量。 .index 以偏移…...

gitattributes配置文件的作用

0 Preface/Foreword 0.1 基本概念 Git版本管控工具功能强大&#xff0c;在使用过程中&#xff0c;在多人合作的项目开发过程中&#xff0c;经常会遇到提交代码时出现的warning提醒&#xff0c;尤其是换行符。 Linux/Unix/Mac OS操作系统的换行符使用LF符号&#xff08;\n&am…...

【华为鸿蒙系统学习】- 如何利用鸿蒙系统进行App项目开发|自学篇

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 创建鸿蒙第一个App项目 项目创建 工程目录区 预览区 运行Hello World 基本工程目录 ws:工程…...

基于SpringBoot的足球社区管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的足球社区管理系统,java…...

ubuntu22.04上安装charles-proxy

在 Ubuntu 22.04 上安装 .tar.gz 格式的 Charles Proxy (charles-proxy-4.6.5_amd64.tar.gz) 需要解压缩文件并运行其中的安装脚本或可执行文件。以下是具体步骤&#xff1a; 1. 下载文件 假设你已经从 Charles Proxy 官网下载了 charles-proxy-4.6.5_amd64.tar.gz 文件。 2…...

(2021|CVPR,XMC-GAN,对比学习,注意力自调制)用于文本到图像生成的跨模态对比学习

Cross-Modal Contrastive Learning for Text-to-Image Generation 公众&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. 相关工作 3. 基础 4. 方法 4.1 用于文本到图像…...

【Linux基本命令】

文章目录 一. Linux基本命令第三回二. 结束语 一. Linux基本命令第三回 cal指令&#xff0c;命令格式&#xff1a;cal 【参数】【月份】【年份】 功能&#xff0c;用于查看日历等时间信息&#xff0c;如只有一个参数&#xff0c;则表示年份&#xff0c;有两个参数则表示月份和…...

Wi-Fi、蓝牙、ZigBee等多类型无线连接方式的安全物联网网关设计

随着物联网和云计算技术的飞速发展.物联网终端的数量越来越多&#xff0c;终端的连接方式也更趋多样化&#xff0c;比如 Wi-Fi蓝牙和 ZigBee 等。现有的物联网网关大多仅支持一种或者几种终端的接人方式。无法满足终端异构性的需求。同时&#xff0c;现有的物联网网关与终端设备…...

华清远见嵌入式学习——ARM——作业4

作业要求&#xff1a; 代码运行效果图&#xff1a; 代码&#xff1a; do_irq.c: #include "key_it.h" extern void printf(const char *fmt, ...); unsigned int i 0;//延时函数 void delay(int ms) {int i,j;for(i0;i<ms;i){for(j0;j<2000;j);} }void do_i…...

25. K 个一组翻转链表

题解参考&#xff1a;https://leetcode.cn/problems/reverse-nodes-in-k-group/solutions/10416/tu-jie-kge-yi-zu-fan-zhuan-lian-biao-by-user7208t/ 设置dummy虚拟头节点&#xff0c;pre为待翻转部分的前驱&#xff08;用于连接&#xff09;&#xff0c;end为待翻转部分中的…...

jQuery的事件-动画-AJAX和插件

一、jQuery事件处理 1.认识事件&#xff08;Event&#xff09; Web页面经常需要和用户之间进行交互&#xff0c;而交互的过程中我们可能想要捕捉这个交互的过程&#xff1a; 比如用户点击了某个按钮、用户在输入框里面输入了某个文本、用户鼠标经过了某个位置&#xff1b;浏…...

【开源】基于JAVA语言的企业项目合同信息系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 合同审批模块2.3 合同签订模块2.4 合同预警模块2.5 数据可视化模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 合同审批表3.2.2 合同签订表3.2.3 合同预警表 四、系统展示五、核心代码5.1 查询合同…...

遗传算法的应用——求解一元函数的极值

遗传算法的应用——求解一元函数的极值 1 基本概念2 预备知识3.1 模拟二进制转化为十进制的方法3.2 轮盘赌选择算法 3 问题4 Matlab代码5 运行效果6 总结 1 基本概念 遗传算法(Genetic Algorithm,GA)是模拟生物在自然环境中遗传和进化过程从而形成的随机全局搜索和优化方法&am…...

Power BI 学习

数据获取 数据清洗 对导入的数据进行数据整理的过程一般称为「数据清洗」&#xff0c;之所以称之为清洗&#xff0c;是因为在数据分析师眼中&#xff0c;杂乱的数据就是脏数据&#xff0c;只有被清洗成干净的数据后才可以进行分析使用。 数据丰富 操作 1.复制列 点击列名选…...

PPT中加入页码

PPT中加入页码 文章目录 简单版本样式更改 简单版本 PPT中插入页码&#xff0c;基础的就是在“插入”选项卡中单机“幻灯片编号”即可 样式更改 然而&#xff0c;就像我们做幻灯片不满足于白底黑字一样&#xff0c;页码也总不能是默认的样式。 比如&#xff0c;在页码下面…...

xxl-job使用笔记

文章目录 xxl-job配置文件新增XxlJobConfig类JobHandler例子xxl-job机制xxl-job-admin配置XxlJob 和 JobHandler(过时了) 其他报错 msg&#xff1a;job handler [demoJobHandler] not found.xxl-job报错 xxl-job registry fail, registryParam:RegistryParam{registryGroup‘EX…...

微短剧,会成为长视频的“救命稻草”吗?

职场社畜秒变霸道总裁&#xff0c;普通女孩穿越成为艳丽皇妃.......这样“狗血”的微短剧&#xff0c;最近不仅在国内各大视频平台上异常火爆&#xff0c;而且还直接火出了国外。 所谓微短剧&#xff0c;就是单集时长从几十秒到十几分钟的剧集&#xff0c;有着相对明确的主题和…...

web架构师编辑器内容-创建业务组件和编辑器基本行为

编辑器主要分为三部分&#xff0c;左侧是组件模板库&#xff0c;中间是画布区域&#xff0c;右侧是面板设置区域。 左侧是预设各种组件模板进行添加 中间是使用交互手段来更新元素的值 右侧是使用表单的方式来更新元素的值。 大致效果&#xff1a; 左侧组件模板库 最初的模板…...

力扣刷题记录(18)LeetCode:474、518、377、322

目录 474. 一和零 518. 零钱兑换 II 377. 组合总和 Ⅳ 322. 零钱兑换 总结&#xff1a; 474. 一和零 这道题和前面的思路一样&#xff0c;就是需要将背包扩展到二维。 class Solution { public:int findMaxForm(vector<string>& strs, int m, int n) {vector&l…...

MongoDB创建和查询视图(一)

目录 限制和注意事项 应用两种方式创建视图 本文整理mongodb的官方文档&#xff0c;介绍mongodb的视图创建和查询。 Mongodb中&#xff0c;允许使用两种方式来创建视图。 //使用db.createCollection()来创建视图 db.createCollection("<viewName>",{"…...

paddle 53 基于PaddleClas2.5训练自己的数据(训练|验证|推理|c++ 部署)

项目地址:https://github.com/PaddlePaddle/PaddleClas 文档地址:https://paddleclas.readthedocs.io/zh-cn/latest/tutorials/install.html paddleclas的最新项目已经不适应其官网的使用案例(训练、验证、推理命令均不适用),为此博主对其进行命令重新进行修改。同时padd…...