当前位置: 代码网 > it编程>编程语言>Java > 详解如何通过Java实现类似Nginx代理

详解如何通过Java实现类似Nginx代理

2024年08月05日 Java 我要评论
proxy-spring-boot-starter最近遇到一个问题,在内网环境中部署的项目需要调用外网完成一些应用,一般情况我们可以通过增加一台机器,部署到可以访问外网的服务器上,然后内网直接连接该机

proxy-spring-boot-starter

最近遇到一个问题,在内网环境中部署的项目需要调用外网完成一些应用,一般情况我们可以通过增加一台机器,部署到可以访问外网的服务器上,然后内网直接连接该机器通过nginx进行代理即可。但是出于安全考虑以及各个服务都是由多个微服务组成,需要接入sso实现认证后才能访问

实现过程

  • 定义一个配置文件,后面可以在application.yml中通过配置实现代理不同网站

@getter
@setter
@configurationproperties(prefix = "proxy")
public class proxyproperties {

    /**
     * 需要代理的服务列表
     */
    private map<string,server> servers;

    /**
     *
     */
    @getter@setter
    public static class server{

        private string path;

        private string target;

        private string name;

    }

}
  • 引入spring依赖,在编写配置时可以自动提示

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-autoconfigure-processor</artifactid>
    <optional>true</optional>
</dependency> 
  • 该功能实现的主要依赖

<dependency>
    <groupid>org.mitre.dsmiley.httpproxy</groupid>
    <artifactid>smiley-http-proxy-servlet</artifactid>
    <version>2.0</version>
</dependency>
  • 增加autoconfiguration,包含两个步骤

a) 定义一个proxyservletconfiguration配置 这里我们基于importbeandefinitionregistrar接口,动态读取代理服务列表,然后通过servletregistrationbean创建servlet代码

public static class proxyservleimportbeandefinitionregistrar implements importbeandefinitionregistrar, environmentaware {

        private proxyproperties properties;

        @override
        public void registerbeandefinitions(annotationmetadata importingclassmetadata, beandefinitionregistry registry) {
            map<string, proxyproperties.server> servers = properties.getservers();
            if( !collectionutils.isempty( servers ) ){
                for(map.entry<string, proxyproperties.server> entry : servers.entryset()){
                    proxyproperties.server server = entry.getvalue();
                    logger.info("开始注册服务代理:{} ( {} => {})", server.getname(), server.getpath(), server.gettarget());
                    beandefinitionbuilder builder = beandefinitionbuilder.genericbeandefinition(servletregistrationbean.class);
//                    builder.addconstructorargvalue(new proxyservlet() ).addconstructorargvalue(server.getpath());
                    builder.setfactorymethodonbean("getservletregistrationbean", "proxyservletfactory");
                    builder.addconstructorargvalue(entry.getkey()).addconstructorargvalue(entry.getvalue());
                    registry.registerbeandefinition(entry.getkey()+"servletregistrationbean", builder.getbeandefinition());
                }
            }
        }

        @override
        public void setenvironment(environment environment) {
            string prefix = objects.requirenonnull(annotationutils.getannotation(proxyproperties.class, configurationproperties.class)).prefix();
            properties = binder.get(environment).bind(prefix, proxyproperties.class).get();
        }

    }
  public static servletregistrationbean createservletregistrationbean(string key, proxyproperties.server server){
        servletregistrationbean servletregistrationbean = new servletregistrationbean(new proxyservlet(), server.getpath());
        servletregistrationbean.setname(server.getname());
        servletregistrationbean.addinitparameter(proxyservlet.p_target_uri, server.gettarget());
        servletregistrationbean.addinitparameter(proxyservlet.p_log, string.valueof(true));
        // 自动处理重定向
//        servletregistrationbean.addinitparameter(proxyservlet.p_handleredirects, string.valueof(false));
//        // 保持 cookies 不变
        servletregistrationbean.addinitparameter(proxyservlet.p_preservecookies, string.valueof(true));
//        // set-cookie 服务器响应标头中保持 cookie 路径不变
        servletregistrationbean.addinitparameter(proxyservlet.p_preservecookiepath, string.valueof(true));
//        // 保持 host 参数不变
//        servletregistrationbean.addinitparameter(proxyservlet.p_preservehost, string.valueof(true));
        return servletregistrationbean;
    }

b) 通过在src/main/resources/meta-inf/spring/org.springframework.boot.autoconfigure.autoconfiguration.imports中引入上面的配置,这样其他模块只需要引入该jar则会由spring自动注入 configuration

cn.cycad.proxy.config.proxyservletconfiguration

使用方法

使用方式非常简单,在配置文件中添加代理的配置,启动服务即可

  • 修改配置文件application.yml

proxy:
  servers:
    baidu:
      path: /baidu/*
      target: 'https://www.baidu.com'
      name: 百度
    shici:
      path: /shici/*
      target: 'https://v1.jinrishici.com'
      name: 诗词
  • 启动服务

  • 示例 http://localhost:8080/shici

可以看到返回的内容与https://v1.jinrishici.com相同

{
  "welcome": "欢迎使用古诗词·一言",
  "api-document": "下面为本api可用的所有类型,使用时,在链接最后面加上 .svg / .txt / .json / .png 可以获得不同格式的输出",
  "help": "具体安装方法请访问项目首页 https://gushi.ci/",
  "list": [
    {
      "全部": "https://v1.jinrishici.com/all"
    },
    {
      "抒情": "https://v1.jinrishici.com/shuqing"
    },
    {
      "四季": "https://v1.jinrishici.com/siji"
    },
    {
      "山水": "https://v1.jinrishici.com/shanshui"
    },
    {
      "天气": "https://v1.jinrishici.com/tianqi"
    }
  ]
}

优缺点

  • 通过该方式实现首先需要有一个可以访问外网的服务器,同时该服务器和内网环境互通

  • 如果需要添加认证模块,直接引入即可

  • 如果代理的网站需要更多的信息才能访问,则需要进一步扩展

写在最后

到此这篇关于详解如何通过java实现类似nginx代理的文章就介绍到这了,更多相关java实现nginx代理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com