spring boot整合netty的实现方法

网友投稿 477 2022-12-30


spring boot整合netty的实现方法

之前花了几天去研究怎么使用netty做一个网关服务器,虽然最后还是没能用上我做的网关,但是呢netty是会用了,总结一下netty和spring boot整合。感觉不用spring boot都不会写代码了。哈哈哈

在pom文件中添加相关的依赖,这里主要的就是netty的依赖,spring boot的相关依赖本文不提

io.netty

netty-all

4.1.19.Final

SpringBoot-Netty

SpringBoot-Netty

1.0-SNAPSHOT

在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, Object> tcpChannelOptions = tcpChannelOptions()http://;

Set> 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, Object> tcpChannelOptions() {

Map, Object> options = new HashMap, 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 {

@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("tcpSNponmBocketAddress")

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 {

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实战时候画的思维导图


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微服务网关中实现的功能(微服务架构中服务网关的作用)
下一篇:类实现接口(类实现接口时必须实现其中的方法)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~