您好,登錄后才能下訂單哦!
之前花了幾天去研究怎么使用netty做一個網(wǎng)關(guān)服務(wù)器,雖然最后還是沒能用上我做的網(wǎng)關(guān),但是呢netty是會用了,總結(jié)一下netty和spring boot整合。感覺不用spring boot都不會寫代碼了。哈哈哈
在pom文件中添加相關(guān)的依賴,這里主要的就是netty的依賴,spring boot的相關(guān)依賴本文不提
<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監(jiān)聽的端口 tcp: port: 8090 # bossGroup的線程數(shù) boss: thread: count: 2 # worker的線程數(shù) 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.初始化的相關(guān)配置
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服務(wù)的配置
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配置這里是實現(xiàn)業(yè)務(wù)邏輯的地方
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)當(dāng)客戶機有消息發(fā)送過來時會調(diào)用這個方法,這個方法的名字叫的是真的差,所以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實戰(zhàn)時候畫的思維導(dǎo)圖
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。