从零手写实现 nginx-22-modules 模块配置加载

前言

大家好,我是老马。很高兴遇到你。

我们为 java 开发者实现了 java 版本的 nginx

github.com/houbb/nginx...

如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

手写从零实现简易版 tomcat minicat

手写 nginx 系列

如果你对 nginx 原理感兴趣,可以阅读:

从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

从零手写实现 nginx-02-nginx 的核心能力

从零手写实现 nginx-03-nginx 基于 Netty 实现

从零手写实现 nginx-04-基于 netty http 出入参优化处理

从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

从零手写实现 nginx-06-文件夹自动索引

从零手写实现 nginx-07-大文件下载

从零手写实现 nginx-08-范围查询

从零手写实现 nginx-09-文件压缩

从零手写实现 nginx-10-sendfile 零拷贝

从零手写实现 nginx-11-file+range 合并

从零手写实现 nginx-12-keep-alive 连接复用

从零手写实现 nginx-13-nginx.conf 配置文件介绍

从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?

从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?

从零手写实现 nginx-16-nginx 支持配置多个 server

从零手写实现 nginx-17-nginx 默认配置优化

从零手写实现 nginx-18-nginx 请求头+响应头操作

从零手写实现 nginx-19-nginx cors

从零手写实现 nginx-20-nginx 占位符 placeholder

从零手写实现 nginx-21-nginx modules 模块信息概览

从零手写实现 nginx-22-nginx modules 分模块加载优化

从零手写实现 nginx-23-nginx cookie 的操作处理

从零手写实现 nginx-24-nginx IF 指令

前言

大家好,我是老马。

这一节我们将配置的加载,拆分为不同的模块加载处理,便于后续拓展。

核心实现

java 复制代码
/**
 * 细化为不同的组件读取
 *
 * @since 0.18.0
 * @author 老马啸西风
 */
public  class NginxUserConfigLoaderConfigComponentFile extends AbstractNginxUserConfigLoader {

    private final String filePath;

    public NginxUserConfigLoaderConfigComponentFile(String filePath) {
        this.filePath = filePath;
    }

    @Override
    protected NginxUserConfig doLoad() {
        NgxConfig conf = null;
        try {
            conf = NgxConfig.read(filePath);

            NginxUserConfigBs configBs = NginxUserConfigBs.newInstance();

            //1. basic
            INginxUserMainConfigLoad mainConfigLoad = new NginxUserMainConfigLoadFile(conf);
            NginxUserMainConfig mainConfig = mainConfigLoad.load();
            configBs.mainConfig(mainConfig);

            //2. events
            INginxUserEventsConfigLoad eventsConfigLoad = new NginxUserEventsConfigLoadFile(conf);
            NginxUserEventsConfig eventsConfig = new NginxUserEventsConfig();
            configBs.eventsConfig(eventsConfig);

            //3. server 信息
            // 首先获取 block
            List<NgxEntry> servers = conf.findAll(NgxConfig.BLOCK, "http", "server"); // 示例3
            if(CollectionUtil.isNotEmpty(servers)) {
                for (NgxEntry entry : servers) {
                    // 每一个 server 的处理
                    NgxBlock ngxBlock = (NgxBlock) entry;

                    final INginxUserServerConfigLoad serverConfigLoad = new NginxUserServerConfigLoadFile(conf, ngxBlock);
                    NginxUserServerConfig serverConfig = serverConfigLoad.load();
                    configBs.addServerConfig(serverConfig);
                }
            }

            // 返回
            return configBs.build();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

然后每一个模块,都有对应的子实现。

我们以 server 为例。

NginxUserServerConfigLoadFile

java 复制代码
package com.github.houbb.nginx4j.config.load.component.impl;

import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.github.houbb.nginx4j.bs.NginxUserServerConfigBs;
import com.github.houbb.nginx4j.config.NginxCommonConfigParam;
import com.github.houbb.nginx4j.config.NginxUserServerConfig;
import com.github.houbb.nginx4j.config.NginxUserServerLocationConfig;
import com.github.houbb.nginx4j.config.load.component.INginxUserServerConfigLoad;
import com.github.houbb.nginx4j.config.load.component.INginxUserServerLocationConfigLoad;
import com.github.houbb.nginx4j.constant.NginxLocationPathTypeEnum;
import com.github.houbb.nginx4j.constant.NginxUserServerConfigDefaultConst;
import com.github.odiszapc.nginxparser.NgxBlock;
import com.github.odiszapc.nginxparser.NgxConfig;
import com.github.odiszapc.nginxparser.NgxEntry;
import com.github.odiszapc.nginxparser.NgxParam;

import java.util.*;

/**
 * @since 0.18.0
 */
public class NginxUserServerConfigLoadFile implements INginxUserServerConfigLoad {

    private final NgxConfig conf;

    private final NgxBlock serverBlock;


    public NginxUserServerConfigLoadFile(NgxConfig conf, NgxBlock serverBlock) {
        this.conf = conf;
        this.serverBlock = serverBlock;
    }

    @Override
    public NginxUserServerConfig load() {
        NginxUserServerConfigBs serverConfigBs = NginxUserServerConfigBs.newInstance();
        String name = serverBlock.getName();

        int httpServerPort = getHttpServerListen(conf, serverBlock);
        String httpServerName = getHttpServerName(conf, serverBlock);
        String httpServerRoot = getHttpServerRoot(conf, serverBlock);
        List<String> httpIndexList = getHttpServerIndexList(conf, serverBlock);

        // sendfile on;
        String sendFile = getHttpServerSendFile(conf, serverBlock);

        //gzip
        String gzip = getHttpServerGzip(conf, serverBlock);
        long gzipMinLen = getHttpServerGzipMinLen(conf, serverBlock);
        List<String> gzipTypes = getHttpServerGzipTypes(conf, serverBlock);

        // 添加 location
        List<NginxUserServerLocationConfig> locationConfigList = getHttpServerLocationList(conf, serverBlock);
        NginxUserServerLocationConfig defaultLocationConfig = getDefaultLocationConfig(locationConfigList);

        serverConfigBs.httpServerName(httpServerName)
                .httpServerListen(httpServerPort)
                .httpServerRoot(httpServerRoot)
                .httpServerIndexList(httpIndexList)
                .sendFile(sendFile)
                .gzip(gzip)
                .gzipMinLength(gzipMinLen)
                .gzipTypes(gzipTypes)
                .locationConfigList(locationConfigList)
                .defaultLocationConfig(defaultLocationConfig);

        return serverConfigBs.build();
    }

    // 各种实现

    private List<NginxUserServerLocationConfig> getHttpServerLocationList(final NgxConfig conf, final NgxBlock serverBlock) {
        List<NginxUserServerLocationConfig> resultList = new ArrayList<>();
        // value
        List<NgxEntry> entryList = serverBlock.findAll(NgxBlock.class, "location");
        if(CollectionUtil.isNotEmpty(entryList)) {
            for(NgxEntry entry : entryList) {
                NgxBlock ngxBlock = (NgxBlock) entry;
                // 参数

                // location 的处理
                final INginxUserServerLocationConfigLoad locationConfigLoad = new NginxUserServerLocationConfigLoadFile(conf, ngxBlock);
                NginxUserServerLocationConfig locationConfig = locationConfigLoad.load();
                resultList.add(locationConfig);
            }
        }

        // 排序。按照匹配的优先级,从高到底排序
        if(CollectionUtil.isNotEmpty(resultList)) {
            Collections.sort(resultList, new Comparator<NginxUserServerLocationConfig>() {
                @Override
                public int compare(NginxUserServerLocationConfig o1, NginxUserServerLocationConfig o2) {
                    return o1.getTypeEnum().getOrder() - o2.getTypeEnum().getOrder();
                }
            });
        }

        return resultList;
    }

}

因为 server 中,又涉及到 location 子模块,这里继续让 NginxUserServerLocationConfigLoadFile 来处理具体的逻辑。

小结

模块的加载拆分为不同的模块加载后,我们暂时实现了其中的部分。

后续有时间再实现更多的配置信息。

我是老马,期待与你的下次重逢。

开源地址

为了便于大家学习,已经将 nginx 开源

github.com/houbb/nginx...

相关推荐
Doris_LMS3 分钟前
接口、普通类和抽象类
java
重生之我是Java开发战士6 分钟前
【数据结构】优先级队列(堆)
java·数据结构·算法
菜鸟233号6 分钟前
力扣216 组合总和III java实现
java·数据结构·算法·leetcode
dodod201210 分钟前
Ubuntu24.04.3执行sudo apt install yarnpkg 命令失败的原因
java·服务器·前端
Evan芙11 分钟前
搭建 LNMT 架构并配置 Tomcat 日志管理与自动备份
java·架构·tomcat
青云交12 分钟前
Java 大视界 -- Java+Spark 构建企业级用户画像平台:从数据采集到标签输出全流程(437)
java·开发语言·spark·hbase 优化·企业级用户画像·标签计算·高并发查询
铉铉这波能秀17 分钟前
正则表达式从入门到精通(字符串模式匹配)
java·数据库·python·sql·正则表达式·模式匹配·表格处理
武子康26 分钟前
Java-202 RabbitMQ 生产安装与容器快速启动:Erlang 兼容、RPM 部署与常用命令
java·消息队列·rabbitmq·erlang·java-rabbitmq·mq
a程序小傲30 分钟前
米哈游Java后端面试被问:Spring Boot Starter的制作原理
java·spring boot·后端
Misnearch33 分钟前
Mock服务是什么?
java·后端·微服务·mock