Springboot+Netty

目录

一、netty入门

二、启动方式

三、netty服务启动类

四、handler链

五、具体业务

六、 线程或者非spring管理的bean中获取spring管理的bean

七、效果


一、netty入门

                   Netty-导学_哔哩哔哩_bilibili

                   入门视频量比较大,最主要是了解netty的架构

netty官网:

    Netty.docs: User guide for 4.x

对springboot有入门级别会启动项目设置bean基本就可以完成了

maven依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/>
    </parent>    
<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.95.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>

</project>

二、启动方式

   以web方式启动,tomcat占用80端口    netty占用9002端口

import com.xnetty.config.NettyServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

/**
 * description: 以web的方式进行项目启动
 */
@SpringBootApplication
@Slf4j
public class XNettyApplication {
    public static void main(String[] args) throws Exception {
        ApplicationContext context = SpringApplication.run(XNettyApplication.class, args);
        NettyServer nettyServer = context.getBean(NettyServer.class);
        nettyServer.start();
        log.info("XNettyApplication finish start....");
    }
}

属性配置文件application.properties中配置

server.port=80
netty.server.port=9002

三、netty服务启动类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * description:
 */
@Component
@Slf4j
public class NettyServer {


    public void start() throws Exception {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(200);
        executor.setQueueCapacity(10000);
        executor.setKeepAliveSeconds(60);
        executor.setRejectedExecutionHandler((r, executor1) -> {
            try {
                executor1.getQueue().put(r);
                log.info("执行了拒绝策略.....");
            } catch (InterruptedException e) {
                log.error("加入队列异常:{}", e.getMessage());
            }
        });
        executor.setThreadGroupName("netty_request");
        executor.initialize();

        NioEventLoopGroup bossGroup = new NioEventLoopGroup(16);
        NioEventLoopGroup workGroup = new NioEventLoopGroup(16);

        try {
            ChannelFuture channelFuture = new ServerBootstrap().group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)
                    .childHandler(new ServerInit(executor))
                    .bind("0.0.0.0", port)
                    .sync();
            Channel channel = channelFuture.channel();
            channel.closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

    @Value("${netty.server.port}")
    private int port;

}

四、handler链

import com.xnetty.service.ReadRequestHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * description:
 */
@Service
public class ServerInit extends ChannelInitializer<NioSocketChannel> {
    private ThreadPoolTaskExecutor executor;

    public ServerInit(ThreadPoolTaskExecutor executor) {
        this.executor = executor;
    }

    @Override
    protected void initChannel(NioSocketChannel ch) throws Exception {
        ch.pipeline()
                .addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS))
                .addLast(new HttpServerCodec())
                .addLast(new HttpObjectAggregator(5 * 1024 * 1024)) //大小为10M
                .addLast(new MpHandler(executor));

    }
}

五、具体业务

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * description:
 */
public class MpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    ThreadPoolTaskExecutor executor;

    public MpHandler(ThreadPoolTaskExecutor executor) {
        this.executor = executor;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
        String uri = request.uri();
        if (uri.equals("/hello")) {
            executor.execute(()->{
                FullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.OK, Unpooled.copiedBuffer("hello word", CharsetUtil.UTF_8));   //  Unpooled.wrappedBuffer(responseJson)
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=UTF-8");       // HttpHeaderValues.TEXT_PLAIN.toString()
                response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
                if (HttpUtil.isKeepAlive(request)) {
                    response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                }
                ctx.writeAndFlush(response);
            });

        } else {
            executor.execute(() -> {
                FullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.OK, Unpooled.copiedBuffer("请求成功....", CharsetUtil.UTF_8));   //  Unpooled.wrappedBuffer(responseJson)
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=UTF-8");       // HttpHeaderValues.TEXT_PLAIN.toString()
                response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
                if (HttpUtil.isKeepAlive(request)) {
                    response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                }
                ctx.writeAndFlush(response);
            });

        }
    }
}

六、 线程或者非spring管理的bean中获取spring管理的bean

至于如何在非spring管理的bean中获取spring管理的对象或者在线程中获取spring管理的bean,则自定义一个beanutils获取

如下

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringBeanUtils implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static Object getBean(String name) {
        return context.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }

    public static <T> T getBeanByName(String beanName, Class<T> clazz) {
        return context.getBean(beanName, clazz);
    }


}

七、效果

七http://localhost:9002/hello

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值