Spring Boot 整合 Netty和Protobuf
前言
本篇文章主要介绍的是SpringBoot整合Netty以及使用Protobuf进行数据传输的相关内容。Protobuf会简单的介绍下用法。
介绍
protocol buffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和python,每一种实现都包含了相应语言的编译器以及库文件。
由于它是一种二进制的格式,比使用 xml进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
官方地址:https://github.com/google/protobuf
使用
这里的使用就只介绍Java相关的使用。首先我们需要建立一个proto文件,在该文件定义我们需要传输的文件。
例如我们需要定义一个用户的信息,包含的字段主要有编号、名称、年龄。
那么该protobuf文件的格式如下:
syntax = "proto3";
// 生成的包名
option java_package="com.pancm.protobuf";
//生成的java名
option java_outer_classname = "UserInfo";message UserMsg {// IDint32 id = 1;// 姓名string name = 2;// 年龄int32 age = 3;// 状态int32 state = 4;
}
注:这里使用的是proto3,相关的注释我已写了,这里便不再过多讲述了。需要注意一点的是proto文件和生成的Java文件名称不能一致!
创建好该文件之后,我们把该文件和protoc.exe(生成Java文件的软件)放到E盘目录下的protobuf文件夹下,然后再到该目录的dos界面下输入:protoc.exe --java_out=文件绝对路径名称。
例如:
protoc.exe --java_out=E:\protobuf User.proto
Java文件生成好之后,我们再来看怎么使用。
这里我就直接贴代码了,并且将注释写在代码中,应该更容易理解些。
代码示例:
// 按照定义的数据结构,创建一个对象UserInfo.UserMsg.Builder userInfo = UserInfo.UserMsg.newBuilder();userInfo.setId(1);userInfo.setName("xuwujing");userInfo.setAge(18);UserInfo.UserMsg userMsg = userInfo.build();// 将数据写到输出流ByteArrayOutputStream output = new ByteArrayOutputStream();userMsg.writeTo(output);// 将数据序列化后发送byte[] byteArray = output.toByteArray();// 接收到流并读取ByteArrayInputStream input = new ByteArrayInputStream(byteArray);// 反序列化UserInfo.UserMsg userInfo2 = UserInfo.UserMsg.parseFrom(input);System.out.println("id:" + userInfo2.getId());System.out.println("name:" + userInfo2.getName());System.out.println("age:" + userInfo2.getAge());
注:这里说明一点,因为protobuf是通过二进制进行传输,所以需要注意下相应的编码。还有使用protobuf也需要注意一下一次传输的最大字节长度。
输出结果:
id:1
name:xuwujing
age:18
SpringBoot整合Netty
说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码。
开发准备
环境要求
JDK:1.8
Netty: 4.0或以上(不包括5)
Protobuf:3.0或以上
如果对Netty不熟的话,可以看看这些文章。大神请无视~。~
https://blog.csdn.net/column/details/17640.html
1、首先还Maven的相关依赖
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><netty.version>4.1.22.Final</netty.version><protobuf.version>3.5.1</protobuf.version><springboot>1.5.9.RELEASE</springboot><fastjson>1.2.41</fastjson><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${springboot}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${springboot}</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><version>${springboot}</version><optional>true</optional></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>${netty.version}</version></dependency><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>${protobuf.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>
添加了相应的maven依赖之后,配置文件这块暂时没有什么可以添加的,因为暂时就一个监听的端口而已。
2、代码实现
代码模块主要分为服务端和客户端。
主要实现的业务逻辑:
服务端启动成功之后,客户端也启动成功,这时服务端会发送一条protobuf格式的信息给客户端,然后客户端给予相应的应答。客户端与服务端连接成功之后,客户端每个一段时间会发送心跳指令给服务端,告诉服务端该客户端还存过中,如果客户端没有在指定的时间发送信息,服务端会关闭与该客户端的连接。当客户端无法连接到服务端之后,会每隔一段时间去尝试重连,只到重连成功!
2.1 服务端
首先是编写服务端的启动类,相应的注释在代码中写得很详细了,这里也不再过多讲述了。不过需要注意的是,在之前的我写的Netty文章中,是通过main方法直接启动服务端,因此是直接new一个对象的。而在和SpringBoot整合之后,我们需要将Netty交给springBoot去管理,所以这里就用了相应的注解。
代码如下:
@Service("nettyServer")
public class NettyServer {private static final int port = 9876; // 设置服务端端口private static EventLoopGroup boss = new NioEventLoopGroup(); // 通过nio方式来接收连接和处理连接private static EventLoopGroup work = new NioEventLoopGroup(); // 通过nio方式来接收连接和处理连接private static ServerBootstrap b = new ServerBootstrap();@Autowiredprivate NettyServerFilter nettyServerFilter;public void run() {try {b.group(boss, work);b.channel(NioServerSocketChannel.class);b.childHandler(nettyServerFilter); // 设置过滤器// 服务器绑定端口监听ChannelFuture f = b.bind(port).sync();System.out.println("服务端启动成功,端口是:" + port);// 监听服务器关闭监听f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {// 关闭EventLoopGroup,释放掉所有资源包括创建的线程work.shutdownGracefully();boss.shutdownGracefully();}}
}
服务端主类编写完毕之后,我们再来设置下相应的过滤条件。
这里需要继承Netty中ChannelInitializer类,然后重写initChannel该方法,进行添加相应的设置,如心跳超时设置,传输协议设置,以及相应的业务实现类。
代码如下
@Componentpublic class NettyServerFilter extends ChannelInitializer<SocketChannel> {@Autowiredprivate NettyServerHandler nettyServerHandler;@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline ph = ch.pipeline();//入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式ph.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));// 解码和编码,应和客户端一致//传输的协议 Protobufph.addLast(new ProtobufVarint32FrameDecoder());ph.addLast(new ProtobufDecoder(UserMsg.getDefaultInstance()));ph.addLast(new ProtobufVarint32LengthFieldPrepender());ph.addLast(new ProtobufEncoder());//业务逻辑实现类ph.addLast("nettyServerHandler", nettyServerHandler);}}
服务相关的设置的代码写完之后,我们再来编写主要的业务代码。
使用Netty编写业务层的代码,我们需要继承ChannelInboundHandlerAdapter 或SimpleChannelInboundHandler类,在这里顺便说下它们两的区别吧。
继承SimpleChannelInboundHandler类之后,会在接收到数据后会自动release掉数据占用的Bytebuffer资源。并且继承该类需要指定数据格式。
而继承ChannelInboundHandlerAdapter则不会自动释放,需要手动调用ReferenceCountUtil.release()等方法进行释放。继承该类不需要指定数据格式。所以在这里,个人推荐服务端继承ChannelInboundHandlerAdapter,手动进行释放,防止数据未处理完就自动释放了。而且服务端可能有多个客户端进行连接,并且每一个客户端请求的数据格式都不一致,这时便可以进行相应的处理。
客户端根据情况可以继承SimpleChannelInboundHandler类。好处是直接指定好传输的数据格式,就不需要再进行格式的转换了。
代码如下:
@Service("nettyServerHandler")
public class NettyServerHandler extends ChannelInboundHandlerAdapter {/** 空闲次数 */private int idle_count = 1;/** 发送次数 */private int count = 1;/*** 建立连接时,发送一条消息*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("连接的客户端地址:" + ctx.channel().remoteAddress());UserInfo.UserMsg userMsg = UserInfo.UserMsg.newBuilder().setId(1).setAge(18).setName("xuwujing").setState(0).build();ctx.writeAndFlush(userMsg);super.channelActive(ctx);}/*** 超时处理 如果5秒没有接受客户端的心跳,就触发; 如果超过两次,则直接关闭;*/@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {if (obj instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) obj;if (IdleState.READER_IDLE.equals(event.state())) { // 如果读通道处于空闲状态,说明没有接收到心跳命令System.out.println("已经5秒没有接收到客户端的信息了");if (idle_count > 1) {System.out.println("关闭这个不活跃的channel");ctx.channel().close();}idle_count++;}} else {super.userEventTriggered(ctx, obj);}}/*** 业务逻辑处理*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("第" + count + "次" + ",服务端接受的消息:" + msg);try {// 如果是protobuf类型的数据if (msg instanceof UserMsg) {UserInfo.UserMsg userState = (UserInfo.UserMsg) msg;if (userState.getState() == 1) {System.out.println("客户端业务处理成功!");} else if(userState.getState() == 2){System.out.println("接受到客户端发送的心跳!");}else{System.out.println("未知命令!");}} else {System.out.println("未知数据!" + msg);return;}} catch (Exception e) {e.printStackTrace();} finally {ReferenceCountUtil.release(msg);}count++;}/*** 异常处理*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
到这里服务端相应的代码就编写完毕了。
2.2 客户端
客户端这边的代码和服务端的很多地方都类似,我就不再过多细说了,主要将一些不同的代码拿出来简单的讲述下。
首先是客户端的主类,基本和服务端的差不多,也就是多了监听的端口和一个监听器(用来监听是否和服务端断开连接,用于重连)。
主要实现的代码逻辑如下
public void doConnect(Bootstrap bootstrap, EventLoopGroup eventLoopGroup) {ChannelFuture f = null;try {if (bootstrap != null) {bootstrap.group(eventLoopGroup);bootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_KEEPALIVE, true);bootstrap.handler(nettyClientFilter);bootstrap.remoteAddress(host, port);f = bootstrap.connect().addListener((ChannelFuture futureListener) -> {final EventLoop eventLoop = futureListener.channel().eventLoop();if (!futureListener.isSuccess()) {System.out.println("与服务端断开连接!在10s之后准备尝试重连!");eventLoop.schedule(() -> doConnect(new Bootstrap(), eventLoop), 10, TimeUnit.SECONDS);}});if(initFalg){System.out.println("Netty客户端启动成功!");initFalg=false;}// 阻塞f.channel().closeFuture().sync();}} catch (Exception e) {System.out.println("客户端连接失败!"+e.getMessage());}}
注:监听器这块的实现用的是JDK1.8的写法。
客户端过滤其这块基本和服务端一直。不过需要注意的是,传输协议、编码和解码应该一致,还有心跳的读写时间应该小于服务端所设置的时间。
改动的代码如下:
ChannelPipeline ph = ch.pipeline();/** 解码和编码,应和服务端一致* *///入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式ph.addLast(new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS));
客户端的业务代码逻辑。
主要实现的几点逻辑是心跳按时发送以及解析服务发送的protobuf格式的数据。
这里比服务端多个个注解, 该注解Sharable主要是为了多个handler可以被多个channel安全地共享,也就是保证线程安全。
废话就不多说了,代码如下:
@Service("nettyClientHandler")@ChannelHandler.Sharablepublic class NettyClientHandler extends ChannelInboundHandlerAdapter {@Autowiredprivate NettyClient nettyClient;/** 循环次数 */private int fcount = 1;/*** 建立连接时*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("建立连接时:" + new Date());ctx.fireChannelActive();}/*** 关闭连接时*/@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println("关闭连接时:" + new Date());final EventLoop eventLoop = ctx.channel().eventLoop();nettyClient.doConnect(new Bootstrap(), eventLoop);super.channelInactive(ctx);}/*** 心跳请求处理 每4秒发送一次心跳请求;**/@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {System.out.println("循环请求的时间:" + new Date() + ",次数" + fcount);if (obj instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) obj;if (IdleState.WRITER_IDLE.equals(event.state())) { // 如果写通道处于空闲状态,就发送心跳命令UserMsg.Builder userState = UserMsg.newBuilder().setState(2);ctx.channel().writeAndFlush(userState);fcount++;}}}/*** 业务逻辑处理*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 如果不是protobuf类型的数据if (!(msg instanceof UserMsg)) {System.out.println("未知数据!" + msg);return;}try {// 得到protobuf的数据UserInfo.UserMsg userMsg = (UserInfo.UserMsg) msg;// 进行相应的业务处理。。。// 这里就从简了,只是打印而已System.out.println("客户端接受到的用户信息。编号:" + userMsg.getId() + ",姓名:" + userMsg.getName() + ",年龄:" + userMsg.getAge());// 这里返回一个已经接受到数据的状态UserMsg.Builder userState = UserMsg.newBuilder().setState(1);ctx.writeAndFlush(userState);System.out.println("成功发送给服务端!");} catch (Exception e) {e.printStackTrace();} finally {ReferenceCountUtil.release(msg);}}}
3、 功能测试
首先启动服务端,然后再启动客户端。
我们来看看结果是否如上述所说。
服务端输出结果:
服务端启动成功,端口是:9876
连接的客户端地址:/127.0.0.1:53319
第1次,服务端接受的消息:state: 1客户端业务处理成功!
第2次,服务端接受的消息:state: 2接受到客户端发送的心跳!
第3次,服务端接受的消息:state: 2接受到客户端发送的心跳!
第4次,服务端接受的消息:state: 2接受到客户端发送的心跳!
客户端输入结果:
Netty客户端启动成功!
建立连接时:Mon Jul 16 23:31:58 CST 2018
客户端接受到的用户信息。编号:1,姓名:xuwujing,年龄:18
成功发送给服务端!
循环请求的时间:Mon Jul 16 23:32:02 CST 2018,次数1
循环请求的时间:Mon Jul 16 23:32:06 CST 2018,次数2
循环请求的时间:Mon Jul 16 23:32:10 CST 2018,次数3
循环请求的时间:Mon Jul 16 23:32:14 CST 2018,次数4
通过打印信息可以看出如上述所说。
接下来我们再来看看客户端是否能够实现重连。
先启动客户端,再启动服务端。
客户端输入结果:
Netty客户端启动成功!
与服务端断开连接!在10s之后准备尝试重连!
客户端连接失败!AbstractChannel$CloseFuture@1fbaa3ac(incomplete)
建立连接时:Mon Jul 16 23:41:33 CST 2018
客户端接受到的用户信息。编号:1,姓名:xuwujing,年龄:18
成功发送给服务端!
循环请求的时间:Mon Jul 16 23:41:38 CST 2018,次数1
循环请求的时间:Mon Jul 16 23:41:42 CST 2018,次数2
循环请求的时间:Mon Jul 16 23:41:46 CST 2018,次数3
服务端输出结果:
服务端启动成功,端口是:9876
连接的客户端地址:/127.0.0.1:53492
第1次,服务端接受的消息:state: 1客户端业务处理成功!
第2次,服务端接受的消息:state: 2接受到客户端发送的心跳!
第3次,服务端接受的消息:state: 2接受到客户端发送的心跳!
第4次,服务端接受的消息:state: 2
结果也如上述所说!
转:https://mp.weixin.qq.com/s/Tx0hAa9ua-BNxy5-6X52fg
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 网络层(ip地址划分以及路由)
文章目录网络层IP 地址分为五类特殊的IP地址路由 网络层 IP 地址分为五类A类 0.0.0.0到127.255.255.255 B类 128.0.0.0到191.255.255.255 C类 192.0.0.0到223.255.255.255 D类 224.0.0.0到239.255.255.255 E类 240.0.0.0到247.255.255.255 这种划分方案的局限性很快显现出来,大…...
2024/5/2 16:02:24 - NAT(Network Address Translation,网络地址转换)
地址转换的基本原理是在转发网络包时对 IP 头部中的 IP 地址和端口号进行改写。可能这样说会比较模糊,还是用例子说明一下吧。找了张图从图上可以看出,198.18.8.31就是这个内网的惟一的公网IP地址了。具备地址转换功能的设备不仅有路由器,有些防火墙也有地址转换功能, 它的…...
2024/4/20 17:41:58 - 前端常见跨域解决方案
什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。 广义的跨域: 1.) 资源跳转: A链接、重定向、表单提交 2.) 资源嵌入: 、什么是同源策略? 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是…...
2024/4/17 6:29:46 - 【Linux】CentOS-7下安装tomcat
Tomcat 启动依赖 jdk的环境,所有我们先安装的是Java的 jdk的环境 1.把tomcat 上传到你的服务器2.解压的指令: tar -zxvf apache-tomcat-8.5.54.tar.gz3.测试一下:启动tomcat ,进入 tomcat的bin目录下 cd tomcat名字/bin/ 启动tomcat指令:./startup.sh (确定成功后,去外网…...
2024/4/23 14:41:00 - 自卑与超越
自卑与超越简述 “一个人在五岁之前,其生活经验已经决定了他(她)成年后解释自身遭遇和回应的方式,对于“对这个世界和自己应该期待些什么”有了基本的答案。” ——阿尔弗雷德•阿德勒 阿尔弗雷德•阿德勒是著名的奥地利心理学家,个体心理学派的创始人。他在思想最成熟的1…...
2024/5/2 8:48:58 - 飞桨深度学习学院-Python小白逆袭大神Day(5)笔记
Day5-综合大作业 作业: 1.完成爱奇艺《青春有你2》评论数据爬取爬取任意一期正片视频下评论,评论条数不少于1000条 2、词频统计并可视化展示 3、绘制词云 4、结合PaddleHub,对评论进行内容审核 作业结果展示:步骤一 安装必要的模块,字体等并导入 下边的代码主要是图片中所…...
2024/4/23 14:41:04 - RabbitMQ,RocketMQ和Kafka三种消息队列的对比
前言 正如我们通常所说的,没有最好的技术,只有最合适的技术。同样,还有一个说法“没有银弹”,银弹是指能轻松杀死狼人,用白银做的子弹。在软件工程中,不存在像“银弹”这样可以解决一切问题的设计,架构或软件,每个软件系统,都是独一无二的,不可能用一套方法去解决所有…...
2024/4/23 14:40:59 - 嵌入式8
(1)信号: 信号是一种向进程发送通知,告诉其某件事情发生了的一种简单通信机制。 (2)信号的产生: ①另一个进程发送信号; ②内核发送信号; ③底层硬件发送信号。 (3)信号列表:常用信号。 信号宏名 信号编号 说明系统 默认处理方式 SIGABRT 6 终止进程,调abort函数是…...
2024/4/23 14:40:55 - 电脑桌面图标变白恢复方法
进入 cmd【win+R】 窗口 逐句执行一下命令 taskkill /im explorer.exe /f cd /d %userprofile%\appdata\local del iconcache.db /a start explorer.exe exitqq_33776323原创文章 7获赞 0访问量 2229关注私信展开阅读全文$.get("https://blog.csdn.net/qq_33776323/articl…...
2024/4/23 14:41:03 - php变量入门(二)
变量入门(二) 纯php代码文件可以去掉结束 ?>可以加快输出速度没去掉去掉后1.引入外部php文件 require ./user.php 2.定义两种常量方式 define("GREETING", "欢迎访问 Runoob.com");//加引号为变量,不加为常量 const GREETING="欢迎访问 Runoob.c…...
2024/4/23 14:40:54 - 详解robots协议、UA检测、封禁IP的反反爬策略
文章目录robots协议反爬机制反反爬策略UA检测反爬机制反反爬策略 UA伪装 UA池封禁IP反爬机制反反爬策略 代理IP 代理IP池 环境: Python3.7 工具: Pycharm robots协议 反爬机制 在域名后面加上robots.txt指的是一个纯文本的协议,指的是一个纯文本的协议,协议中规定了该网站中…...
2024/4/23 14:40:55 - 奥运五环及奥迪标志
SVG继续基础玩法。知识点一:style属性可以快速填写部分对应的值,但不是所有值都可以这样写。知识点二:fill属性用来表示填充色,transparent表示透明,这可以实现空心圆。<svg xmlns="http://www.w3.org/2000/svg" enable-background="gray"><…...
2024/4/23 14:40:51 - 复习ajax的三种跨域方式
ajx请求 跨域的方式1, 服务器代理方式1,找到配置文件,设定代理内容,必须按照固定的语法格式location = /dt {proxy_pass https://www.duitang.com/napi/blog/list/by_filter_id/;}location = /dt 代理名称/名称 是固定语法形式proxy_pass 代理的跨域请求地址 必须以分号结束…...
2024/4/23 14:40:53 - 5.最长回文子串
5.最长回文子串 给定一个字符串s,找到s中最长的回文子串。你可以假设s的最大长度为1000. 示例1: 输入:“babad” 输出:“bab” 注意:"aba"也是一个有效的答案 示例2: 输入:“cbbd” 输出:“bb” package com.likou;/*** 5.最长回文子串* 给定一个字符串s,找到s中最…...
2024/4/23 14:40:50 - 【智能手机步态识别】Deep Learning-Based Gait Recognition Using Smartphones in the Wild
【智能手机步态识别】Deep Learning-Based Gait Recognition Using Smartphones in the Wild解决什么问题本文创新点/贡献方法方法概述数据准备数据采集步态-非步态数据分割数据集神经网络设计Identificationauthentication实验ExtractionIdentificationauthentication总结 解决…...
2024/4/23 14:40:48 - 【Java互联网架构学习----001--15】SynchronousQueue
SynchronousQueue:一个不存储元素的阻塞队列。每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。内部没有容器,一个生产线程,当它生产产品(即put的时候),如果当前没有人想要消费产品(即当前没有线程执行take),此生产线程必须阻塞,等待一个消费线程调用tak…...
2024/4/23 14:40:47 - spring clude ---服务网关组件Netflix Zuul
介绍:服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。 Zuul是Netflix开源的微服务网关,他可以和Eureka,Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系列的…...
2024/4/23 14:40:49 - 手把手带你入门spring boot整合redis缓存
一、为什么要缓存1、原因2、问题二、Spring boot的缓存机制1、SpringCache概述2、缓存注解三、spring boot整合mysql+redis缓存项目1、准备数据源2、数据库查询并缓存四、结论 一、为什么要缓存 1、原因 用缓存,主要有两个用途:高性能、高并发。高性能 非实时变化的数据-查询…...
2024/4/23 14:40:52 - 一个浮点数引发的惨案,printf("%d\n", 8.0); 为什么输出 0 ?——小端存储 & 浮点数格式 & 格式化输出 | bitset的使用 与 二进制原码分析
这里引用浮点数在计算机中的存储方式一文。数据在计算机中的表示 | 进制转换、浮点数表示 如题,为什么 printf("%d\n", 8.0); 输出结果为 0 。 文章目录一、一些废话..数据类型与存储之类的..二、使用 bitset 输出二进制原码三、计算机的小端存储方式四、分析二进制…...
2024/4/23 14:40:52 - 重拾算法竞赛之路 day#2 (“纯新手”的入门经历)(一些入门题目的题解代码)
重拾算法竞赛之路 day#2(C++)写在开头计划今天完成的事情基础知识下面是代码 看这标题为什么是从第二天开始,是因为从昨天开始刷的题。 写在开头 从高中的noip水了俩年,每年都混个省三开始。现在到了大学,却发现这个学校没有去参加各大算法竞赛的方向,但还是心心念念着打…...
2024/4/17 6:30:58
最新文章
- 万兆以太网MAC设计(11)完整UDP协议栈仿真
文章目录 前言一、模块接口二、IP模块与ARP模块之间的联系三、整体协议栈仿真总结: 前言 目前除了巨帧处理逻辑之外,所有的准备工作都已经结束了,先进行整体的功能验证。 一、模块接口 所有模块接口皆采用AXIS数据流的形式,其中…...
2024/5/2 17:02:41 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 【APUE】网络socket编程温度采集智能存储与上报项目技术------多路复用
作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 作者主页:一个平凡而乐于分享的小比特的个人主页…...
2024/5/1 13:52:04 - docker进行jenkins接口自动化测试持续集成实战
文章目录 一、接口功能自动化测试项目源码讲解二、接口功能自动化测试运行环境配置1、下载jdk,maven,git,allure并配置对应的环境变量2、使用docker安装jenkins3、配置接口测试的运行时环境选择对应节点4、jenkins下载插件5、jenkins配置环境…...
2024/5/1 13:12:35 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/1 17:30:59 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/2 16:16:39 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/29 2:29:43 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/2 9:28:15 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/30 9:43:09 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/2 15:04:34 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/29 20:46:55 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/30 22:21:04 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/1 4:32:01 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/27 23:24:42 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/30 9:42:22 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/2 9:07:46 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/30 9:42:49 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57