当前位置: 首页 > 知识库问答 >
问题:

使用嵌入式tomcat服务器进行JUnit测试,如何为超文本传输协议和https连接器指定自动端口?

麹耘豪
2023-03-14

描述

我做了一个JUnit测试,重点是尝试测试对SOAP Web服务的调用。

我使用嵌入式tomcat服务器进行测试,以便使用模拟服务器运行测试。

我还使用http和https连接器。

我需要为这两个连接器使用自动端口,因为测试正在Jenkins服务器上运行,我不能只使用端口443或8443,因为它们已经被占用了。

我知道使用端口0作为标准端口将导致tomcat使用自动端口分配,但我无法将其与两个连接器一起使用。

预期行为

我想为我的自定义ssl连接器使用自动端口分配。

有没有可能以某种方式做到这一点?

示例代码

下面是我的tomcat实例的代码:

@Before
public void setup() throws Throwable {

    File tomcatWorkingDir = new File(mWorkingDir);

    //Empty the target/tomcat-working-dir directory if it exist
    //Create the directory otherwise
    if(tomcatWorkingDir.exists() && tomcatWorkingDir.isDirectory()){
        LOGGER.info("cleaning tomcat-working-dir directory");
        FileUtils.cleanDirectory(new File(mWorkingDir)); 
    } else {
        LOGGER.info("create tomcat-working-dir directory");
        tomcatWorkingDir.mkdir();
    }

    LOGGER.info("disabling ssl certification validation");
    //Disable JVM ssl sockets connection
    disableJVMCertificate();

    //Add server certificate
    createServerCertificate();

    //Custom SSL Connector
    Connector SSLConnector = getSSLConnector();

    mTomcat = new Tomcat();

    //Standard http startup port
    mTomcat.setPort(0);

    //Set up base directory 
    //Otherwise, tomcat would use the current directory
    mTomcat.setBaseDir(mWorkingDir);

    LOGGER.info("setting the ssl connector in TOMCAT");
    Service service = mTomcat.getService();
    service.addConnector(SSLConnector);

    //Redirect current port
    Connector defaultConnector = mTomcat.getConnector();
    defaultConnector.setRedirectPort(SERVER_HTTPS_PORT);

    //Configure the way WAR are managed by the engine
    mTomcat.getHost().setAutoDeploy(true);
    mTomcat.getHost().setDeployOnStartup(true);

    //Add mock server into our webApp
    String servletName = "/server";
    File webApp = new File(mWorkingDir,"../../../ws-mock-server/src/main/webapp");

    mTomcat.addWebapp(mTomcat.getHost(), servletName, webApp.getAbsolutePath());

    //start tomcat
    LOGGER.info("starting TOMCAT");

    mTomcat.start();
  }

这里是我的自定义ssl连接器。

    private static Connector getSSLConnector(){
    Connector connector = new Connector();
    connector.setPort(SERVER_HTTPS_PORT);
    connector.setSecure(true);

    //Http protocol Http11AprProtocol
    connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol");

    //Maximum threads allowedd on this instance of tomcat
    connector.setAttribute("maxThreads","200");
    connector.setAttribute("SSLEnabled", true);

    //No client Authentification is required in order to connect
    connector.setAttribute("clientAuth", false);

    //SSL TLSv1 protocol
    connector.setAttribute("sslProtocol","TLS");

    //Ciphers configuration describing how server will encrypt his messages
    //A common cipher suite need to exist between server and client in an ssl
    //communication in order for the handshake to succeed
    connector.setAttribute("ciphers","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");

    LOGGER.info("setting keystore file");
    //Here an absolute file path is needed in order to properly set up the keystore attribute
    connector.setAttribute("keystoreFile",new File(".").getAbsolutePath().replace("\\", "/")+"/"+mWorkingDir+"/server.jks");

    LOGGER.info("setting keystore pass");
    connector.setAttribute("keystorePass","changeit");

    return connector;
}

共有2个答案

红明德
2023-03-14

我没试过但从代码来看

>

  • 您可以在服务器启动后设置重定向端口

    您可以使用Connector.getLocalPort获取实际端口

    所以我想你可以尝试添加一些

    mTomcat.start(); // <-- your existing code
    defaultConnector.setRedirectPort(SSLConnector.getLocalPort())
    

  • 施刚毅
    2023-03-14

    对于这个问题,我有两种解决方案:

    ServerSocket(0)构造函数会自动选择一个空闲端口。Tomcat也使用这种方法。

    try (ServerSocket testSocket = new ServerSocket(0)) {
        int randomFreePort = testSocket.getLocalPort(); 
        sslConnector.setPort(randomFreePort);
        defaultConnector.setRedirectPort( randomFreePort);
    } // At this point the testSocket.close() called
    tomcat.start();
    

    我知道,有一种可能性,另一个进程在testSocket之间分配相同的端口。close()tomcat。start(),但您可以使用LifecycleState检测这种情况。失败。等于(sslConnector.getState())test。

    Tomcat连接器具有生命周期意识,因此会在“启动前”和“启动后”事件中通知您。Tomcat按照您将连接器添加到服务中的顺序初始化连接器。

    1. 添加ssl连接器。
    2. 添加超文本传输协议连接器。(这将是默认的连接器。不要调用mTomcat.getConnector(),因为它获取第一个或创建一个新连接器。)
    3. 当ssl连接器初始化完成时,您可以通过getLocalPort()调用获得所选的端口。
    4. 在超文本传输协议连接器初始化之前,调用setReDirectPort

    完整示例:

        Tomcat mTomcat = new Tomcat();
        Connector sslConnector = getSSLConnector(); 
        mTomcat.getService().addConnector(sslConnector);    
        Connector defaultConnector = new Connector();
        defaultConnector.setPort(0);
        mTomcat.getService().addConnector(defaultConnector);
    
        // Do the rest of the Tomcat setup
    
        AtomicInteger sslPort = new AtomicInteger();
        sslConnector.addLifecycleListener(event->{
            if( "after_init".equals(event.getType()) )
                sslPort.set(sslConnector.getLocalPort());
        });
        defaultConnector.addLifecycleListener(event->{
            if( "before_init".equals(event.getType()) )
                defaultConnector.setRedirectPort(sslPort.get());
        });
    
        mTomcat.start();
    
     类似资料:
    • 我想测试一个连接到Github api的应用程序,下载一些记录并对其进行处理。我想要一个模拟对象,我做了如下操作: 看起来不错吧?我应该在thenReturn中输入什么(它需要HttpResponse,但我不知道如何创建)。谢谢你的回答。如果你有更好的想法,我将不胜感激。 更新:字符串响应是一个示例响应

    • httpd是Apache超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程,它会建立一个处理请求的子进程或线程的池。 通常,httpd不应该被直接调用,而应该在类Unix系统中由apachectl调用,在Windows NT/2000/XP/2003中作为服务运行和在Windows 95/98/ME中作为控制台程序运行. 语法 httpd [ -d serverroot ]

    • 我已经设置了一个ec2实例,其中一个java web应用程序运行在tomcat服务器上,另一个aws应用程序负载平衡器将端口80和443定向到ec2实例上的端口8080。 我已更改服务器。tomcat上的xml配置如下 现在我可以连接到“sub.mydomain.com”和“https://sub.mydomain.com”。但是如何将所有“http://sub.mydomain.com”请求重定

    • 我正在使用oauth签名生成我的oauth签名,以便与woocommerce api连接。我遵循了woocommerce rest api文档中所述的所有步骤: 所需的参数是:oauth_consumer_密钥、oauth_时间戳、oauth_nonce、oauth_签名和oauth_签名方法。oauth_版本不是必需的,应该省略。OAuth nonce可以是消费者密钥唯一的任意随机生成的32个字

    • 为了更好的重现性,我在我的中定义了以下系统。 工具jmstool是部署在Tomcat 9上的Spring应用程序,用于通过JMS与不同队列通信。我可以让它与独立的activeMQ一起工作。 启动这些容器后,我向运行JBoss的消息传递子系统添加了一个应用程序用户和两个队列: 的内容 看起来不错,与[另一个例子][2]非常相似。 现在我尝试在。我(遗憾地)不得不使用协议,而不是通过连接。 jmsto

    • (我知道这是一个重复的问题,但楼主问的原因是错误的。我不是在暗示我问的原因是正确的,但让我们看看。) 我们有一个在非标准端口号上运行的web服务。尽管用户似乎能够记住端口号,但有时他们会错误地键入http:而不是https:。有人问我们是否可以在该端口上提供HTTP服务,然后将它们重定向到同一端口上的HTTPS。听起来很邪恶。。。我喜欢它的可用性,但感觉也许这应该是浏览器的工作? 我看到的一个解决