springboot自带的http服务功能由于功能较多,导致打包后的jar包比较大,由于我们业务以及环境的特殊性因此决定自己实现一个http服务器,主要原理是由一个启动器去扫描系统包下的类注解、方法注解等,生成http接口容器,然后通过url等方式定位到接口,最后进行反射调用
最终的效果:
通过指定包名启动http服务、初始化配置信息以及容器信息
定义接口方式如下:
1、maven依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.1.86.Final</version>
</dependency>
2、HttpServerStarter.class
package com.ctrip.hotel.octopus.crawler.http.starter;
import com.ctrip.hotel.octopus.commons.base.utils.JsonUtils;
import com.ctrip.hotel.octopus.commons.base.utils.RetryMonitor;
import com.ctrip.hotel.octopus.crawler.common.config.PropertiesLoader;
import com.ctrip.hotel.octopus.crawler.http.container.HttpServerContainer;
import com.ctrip.hotel.octopus.crawler.http.initializer.HttpInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.util.Properties;
/**
* @author ZhaoXu
* @date 2024/1/10 19:09
*/
@Slf4j
public class HttpServerStarter {
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private final ServerBootstrap serverBootstrap = new ServerBootstrap();
private final String[] basePackages;
public HttpServerStarter(String[] basePackages) {
this.basePackages = basePackages;
}
public static void start(String... basePackages) {
// 失败自动重试
RetryMonitor.registry(() -> {
try {
HttpServerStarter httpServerStarter = new HttpServerStarter(basePackages);
httpServerStarter.init();
httpServerStarter.start();
} catch (Exception e) {
log.error("服务启动失败!", e);
throw new RuntimeException(e);
}
}, Integer.MAX_VALUE);
}
private void init() {
// 初始化http服务
initHttpServer();
// 初始化http容器
initHttpContainer(basePackages);
}
private void start() throws InterruptedException {
String port = PropertiesLoader.getProperty("server.port", "8080");
ChannelFuture channelFuture = serverBootstrap.bind("0.0.0.0", Integer.parseInt(port)).sync();
log.info("http服务启动成功,监听本地端口:" + port);
channelFuture.channel().closeFuture().sync();
}
private void initHttpContainer(String[] basePackages) {
log.info("初始化http容器");
HttpServerContainer httpServerContainer = new HttpServerContainer(basePackages);
httpServerContainer.start();
}
private void initHttpServer() {
log.info("初始化http服务信息");
serverBootstrap.group(bossGroup, workerGroup);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);