Spring Boot - 不使用嵌入式Tomcat的Rest调用客户端

14

我一直在努力解决与Spring Boot相关的问题,由于我对Spring不太熟悉,所以我想在这里寻求一些帮助。

我有一个基于Spring Boot的Java应用程序,它作为守护程序运行,并向远程服务器发出一些GET请求(只充当客户端)。

但是,我的Spring Boot应用程序在内部启动了一个嵌入式Tomcat容器。我的理解是,如果Java应用程序充当服务器,则需要Tomcat。但是,我的应用程序仅作为远程机器的GET API的消费者,为什么需要嵌入式Tomcat?

在我的POM文件中,我指定了spring-boot-starter-web,假设即使进行GET调用也需要它。

但是,在禁用嵌入式Tomcat方面进行了一些研究后,我找到了一个解决方案。

要进行以下更改:

@SpringBootApplication(exclude = {EmbeddedServletContainerAutoConfiguration.class, 
WebMvcAutoConfiguration.class})

在application.yml中使用&

spring:
   main:
      web-environment: false

应用程序.yml更改后,我的jar文件没有启动,直接中止,甚至没有在logback日志中记录任何内容。

现在,如果我删除应用程序.yml更改,我的jar文件就会启动(只有在@SpringBoot应用程序注释的第一次更改时),但会发生某些异常。

 [main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

我的疑问如下:

1)对于仅向远程机器发出GET API调用的应用程序,是否真的需要使用Tomcat(无论是独立还是嵌入式)?

2)我该如何克服这个异常并安全地删除嵌入式Tomcat,同时仍能执行GET API调用?


我认为在进行HTTP调用时不需要使用 spring-boot-starter-web,只需使用基本的 spring-boot-starter 并添加 spring-web 依赖即可。 - Paul Grime
5个回答

14

你似乎完全走错了方向,从一个Web应用程序模板开始,然后试图关闭Web应用程序方面是不正确的。

最好从普通的命令行客户端模板开始,并按照 相关Spring指南 中详细说明的步骤进行操作。

基本上该应用程序可以简化为:

@SpringBootApplication
public class Application {

private static final Logger log = LoggerFactory.getLogger(Application.class);

public static void main(String args[]) {
    SpringApplication.run(Application.class);
}

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
    return args -> {
        Quote quote = restTemplate.getForObject(
                "http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
    };
}
}

并将POM文件打包

    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

1
移除spring-boot-starter-web并添加spring-boot-starter和spring-web即可解决问题。非常感谢。 - Deepak Selvakumar
这并不是一个网页应用程序模板,而是一个高级通用网页模板。如果您不需要网页服务器部分,可以将其禁用:https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-disable-web-server - Tristan
1
FYI,相关的Spring指南链接中的pom文件确实包含了spring-boot-starter-web,使用它将会产生与OP遇到的相同问题。不过,你在答案中提供的pom是正确的。 - matt forsythe
需要类似处理HTTP请求但不使用HTTP服务器的方法。使用标志spring.main.web-application-type=none会引发异常"No ServletContext set"。 - Martin P.

5

我遇到了这个问题。我只是想要一个客户端来进行REST请求。不幸的是,我的依赖项嵌入了Jetty,而且Jetty总是在启动。

为了禁用Jetty,我只需要在applications.properties文件中添加以下条目:

spring.main.web-application-type=none

那样做就解决了。

3
这是我最简单的解决方案,将Spring Boot应用程序仅作为RESTful API消费者。 更换依赖项。
implementation("org.springframework.boot:spring-boot-starter-web")

使用

implementation("org.springframework.boot:spring-boot-starter-json")

RestTemplatejackson 在没有嵌入式 Tomcat 的项目中可用。


0
回答您的问题:
1)默认嵌入 - 不需要为客户端HTTP请求;
2)您可以在没有任何Web的情况下使用CommandLineRunner来运行Spring Boot应用程序:
@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

    public static void main(String[] args) {            
        SpringApplication.run(SpringBootConsoleApplication.class, args);
    }

    @Override
    public void run(String... args) {
        // TODO: start you thread here to execute client HTTP REST requests (or any other job you need)
    }
}

这将完全禁用Web - 不会出现手动错误配置的问题。

以下是一些文档: http://www.baeldung.com/spring-boot-console-app

您还需要使用spring-boot-starter替换spring-boot-starter-web依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

1
依赖项spring-boot-starter不带有REST客户端(即RestTemplate),因此要使用它,必须在pom.xml中指定spring-web + jackson依赖项。依赖项spring-boot-starter-web也具有它,但会使您的应用程序成为Web服务器,并默认在端口8080上启动。 - Lotzy

-1
从你的问题来看,我假设你想让你的应用程序在后台持续运行,并在其生命周期中进行一些获取调用。如果是这种情况,那么:
  1. 回答你的第一个问题,是的,你需要一个嵌入式Tomcat或Jetty,或者需要将你的应用程序部署到外部应用服务器上。
  2. 第二,为了摆脱你面临的异常,请不要排除EmbeddedServletContainerAutoConfiguration和WebMvcAutoConfiguration类,因为它是默认嵌入式Tomcat自动配置所需的。

这个问题并未提及必须服务HTTP请求,因此不需要Web服务器。 - Paul Grime

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接