spring boot整合netty的实现方法
作者:三不猴子 发布时间:2021-11-17 04:28:03
标签:spring,boot,netty
之前花了几天去研究怎么使用netty做一个网关服务器,虽然最后还是没能用上我做的网关,但是呢netty是会用了,总结一下netty和spring boot整合。感觉不用spring boot都不会写代码了。哈哈哈
在pom文件中添加相关的依赖,这里主要的就是netty的依赖,spring boot的相关依赖本文不提
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.19.Final</version>
</dependency>
<dependency>
<groupId>SpringBoot-Netty</groupId>
<artifactId>SpringBoot-Netty</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在application.yml文件中配置
#不能用localhost,否则启动报异常:Unresolved address
#tcp监听的端口
tcp:
port: 8090
# bossGroup的线程数
boss:
thread:
count: 2
# worker的线程数
worker:
thread:
count: 2
#是否使用长连接
so:
keepalive: true
backlog: 100
3.编写NettyConfig netty的配置。
package com.advsun.netty.config;
import com.advsun.netty.handlers.StringProtocolInitalizer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author 杨红星
* @version 1.0.0
*/
@Configuration
public class NettyConfig {
//读取yml中配置
@Value("${boss.thread.count}")
private int bossCount;
@Value("${worker.thread.count}")
private int workerCount;
@Value("${tcp.port}")
private int tcpPort;
@Value("${so.keepalive}")
private boolean keepAlive;
@Value("${so.backlog}")
private int backlog;
@Autowired
@Qualifier("springProtocolInitializer")
private StringProtocolInitalizer protocolInitalizer;
//bootstrap配置
@SuppressWarnings("unchecked")
@Bean(name = "serverBootstrap")
public ServerBootstrap bootstrap() {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup(), workerGroup())
.channel(NioServerSocketChannel.class)
.childHandler(protocolInitalizer);
Map<ChannelOption<?>, Object> tcpChannelOptions = tcpChannelOptions();
Set<ChannelOption<?>> keySet = tcpChannelOptions.keySet();
for (@SuppressWarnings("rawtypes")
ChannelOption option : keySet) {
b.option(option, tcpChannelOptions.get(option));
}
return b;
}
@Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
public NioEventLoopGroup bossGroup() {
return new NioEventLoopGroup(bossCount);
}
@Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
public NioEventLoopGroup workerGroup() {
return new NioEventLoopGroup(workerCount);
}
@Bean(name = "tcpSocketAddress")
public InetSocketAddress tcpPort() {
return new InetSocketAddress(tcpPort);
}
@Bean(name = "tcpChannelOptions")
public Map<ChannelOption<?>, Object> tcpChannelOptions() {
Map<ChannelOption<?>, Object> options = new HashMap<ChannelOption<?>, Object>();
options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
options.put(ChannelOption.SO_BACKLOG, backlog);
return options;
}
@Bean(name = "stringEncoder")
public StringEncoder stringEncoder() {
return new StringEncoder();
}
@Bean(name = "stringDecoder")
public StringDecoder stringDecoder() {
return new StringDecoder();
}
/**
* Necessary to make the Value annotations work.
*
* @return
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
4.初始化的相关配置
package com.advsun.netty.handlers;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* @author 杨红星
* @version 1.0.0
*/
@Component
@Qualifier("springProtocolInitializer")
public class StringProtocolInitalizer extends ChannelInitializer<SocketChannel> {
@Autowired
StringDecoder stringDecoder;
@Autowired
StringEncoder stringEncoder;
@Autowired
ServerHandler serverHandler;
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", stringDecoder);
pipeline.addLast("handler", serverHandler);
pipeline.addLast("encoder", stringEncoder);
}
public StringDecoder getStringDecoder() {
return stringDecoder;
}
public void setStringDecoder(StringDecoder stringDecoder) {
this.stringDecoder = stringDecoder;
}
public StringEncoder getStringEncoder() {
return stringEncoder;
}
public void setStringEncoder(StringEncoder stringEncoder) {
this.stringEncoder = stringEncoder;
}
public ServerHandler getServerHandler() {
return serverHandler;
}
public void setServerHandler(ServerHandler serverHandler) {
this.serverHandler = serverHandler;
}
}
5.tcp服务的配置
package com.advsun.netty.config;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;
/**
* @author 杨红星
* @version 1.0.0
*/
@Component
public class TCPServer {
@Autowired
@Qualifier("serverBootstrap")
private ServerBootstrap b;
@Autowired
@Qualifier("tcpSocketAddress")
private InetSocketAddress tcpPort;
private ChannelFuture serverChannelFuture;
@PostConstruct
public void start() throws Exception {
System.out.println("Starting server at " + tcpPort);
serverChannelFuture = b.bind(tcpPort).sync();
}
@PreDestroy
public void stop() throws Exception {
serverChannelFuture.channel().closeFuture().sync();
}
public ServerBootstrap getB() {
return b;
}
public void setB(ServerBootstrap b) {
this.b = b;
}
public InetSocketAddress getTcpPort() {
return tcpPort;
}
public void setTcpPort(InetSocketAddress tcpPort) {
this.tcpPort = tcpPort;
}
}
6.serverHandler配置这里是实现业务逻辑的地方
package com.advsun.netty.handlers;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
/**
* @author 杨红星
* @version 1.0.0
*/
@Component
@Qualifier("serverHandler")
@ChannelHandler.Sharable
public class ServerHandler extends SimpleChannelInboundHandler<String> {
private static final Logger log = LoggerFactory.getLogger(ServerHandler.class);
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg)
throws Exception {
log.info("client msg:"+msg);
String clientIdToLong= ctx.channel().id().asLongText();
log.info("client long id:"+clientIdToLong);
String clientIdToShort= ctx.channel().id().asShortText();
log.info("client short id:"+clientIdToShort);
if(msg.indexOf("bye")!=-1){
//close
ctx.channel().close();
}else{
//send to client
ctx.channel().writeAndFlush("Yoru msg is:"+msg);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("RamoteAddress : " + ctx.channel().remoteAddress() + " active !");
ctx.channel().writeAndFlush( "Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n");
super.channelActive(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("\nChannel is disconnected");
super.channelInactive(ctx);
}
}
这里的 channelRead0(ChannelHandlerContext ctx, String msg)当客户机有消息发送过来时会调用这个方法,这个方法的名字叫的是真的差,所以netty5.0之后取消了这个名字, 5.0之后叫messageReceived。官方都说这名字叫的 *
channelRead0() → messageReceived()
I know. It was a silly mistake. If you are using SimpleChannelInboundHandler, you have to rename channelRead0() to messageReceived().
最后在贴一张自己在看netty实战时候画的思维导图
来源:https://www.jianshu.com/p/222fe9f2a564


猜你喜欢
- 本文实例为大家分享了WPF实现平面三角形3D运动效果的具体代码,供大家参考,具体内容如下实现效果如下:思路:封装三角形三个顶点和路径的三角形
- 本文实例讲述了Android开发使用Handler的PostDelayed方法实现图片轮播功能。分享给大家供大家参考,具体如下:第一步:创建
- 到现在为止,笔者不敢给流下定义,从概念来讲他应该也是一种数据元素才是。可是在我们前面的代码例子中我们可以看到他更多的好像在表示他是一组处理数
- 本文实例总结了C#遍历DataSet控件的方法。分享给大家供大家参考。具体方法如下:DataSet控件在.net主要是用来存储数据的,它更像
- 本文实例为大家分享了Android实现歌词滚动效果的具体代码,供大家参考,具体内容如下自定义TextViewpublic class Ver
- 自定义View分为继承自View和ViewGroup,继承ViewGroup相比继承View在事件分发上ViewGroup多dispatch
- 今天给大家带来一篇简单易懂的微技巧文章,并没有什么高深的技术点,但重点是在细节,相信可以给不少朋友带来帮助。Dialog和Toast所有人肯
- 本周的谷歌I/O大会带来了很多关于Android的振奋人心的消息。可能我们需要较长的时间来消化Android L引入的新东西。这些天我一直在
- springboot pom文件project报错问题如下 解决方案情况1:maven版本要和课程保持一致,网盘直接下载。情况2:
- 目前网上流行着很多对“时间对话框TimePickerDialog”的讲解文章,但感觉都不是很详细。所以浣熊在这里详细对该方面的知识进行介绍,
- 北京时间 2018 年 3 月 1 日早上,如约发布的 Spring Boot 2.0 在同步至 Maven 仓库时出现问题,导致在 Git
- 本文实例讲述了Android编程实现自定义ProgressBar样式。分享给大家供大家参考,具体如下:效果图如下,本例中设置了第一级进度条和
- 同步是一种只允许一个线程在特定时间访问某些资源的技术。没有其他线程可以中断,直到所分配的线程或当前访问线程访问数据完成其任务。在多线程程序中
- 前言Java克隆(Clone)是Java语言的特性之一,但在实际中应用比较少见。但有时候用克隆会更方便更有效率。对于克隆(Clone),Ja
- 1、简介单例模式使⽤场景:业务系统全局只需要⼀个对象实例,⽐如发号器、 redis 连接对象等。Spring IOC容器中的 Bean 默认
- 快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一
- 初学线程时,总是将 run 方法和 start 方法搞混,虽然二者是完全不同的两个方法,但刚开始使用时很难分清,原因就是因为初次使用时效果貌
- 本文实例讲述了C#实现在图像中绘制文字图形的方法。分享给大家供大家参考。具体实现方法如下:using System;using System
- 方法一、使用系统控件ViewFlipper方式:布局文件:<ViewFlipper andro
- 一、实验目的(1)掌握应用黑盒测试技术进行测试用例设计。(2)掌握对测试用例进行优化设计方法。二、实验内容日期问题测试以下程序:该程序有三个