Spring boot - 没有嵌入式 tomcat 的 Rest Call 客户端

Posted

技术标签:

【中文标题】Spring boot - 没有嵌入式 tomcat 的 Rest Call 客户端【英文标题】:Spring boot - Rest Call client without embedded tomcat 【发布时间】:2018-12-31 20:27:16 【问题描述】:

我一直在尝试解决 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

随着 application.yml 的变化,我的 jar 甚至没有启动,直接中止,甚至没有在 logback 日志中记录任何内容。

现在,如果我删除 application.yml 更改,我的 jar 将启动(仅在 @SpringBootApplication anno 中进行第一次更改。)但会出现一些异常。

 [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 调用?

【问题讨论】:

我认为您不需要 spring-boot-starter-web 来进行 HTTP 调用。使用基本的spring-boot-starter 并使用spring-web 依赖项。 【参考方案1】:

对我来说这是最简单的解决方案,让 spring boot 应用程序只是一个安静的 api 使用者。

替换依赖

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

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

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

【讨论】:

【参考方案2】:

我遇到了这个问题。我想要的只是让客户端发出 REST 请求。不幸的是,我有一个嵌入 Jetty 的依赖项,并且 Jetty 总是启动。

为了禁用 Jetty,我需要做的就是在 applications.properties 中添加以下条目:

spring.main.web-application-type=none

这样就解决了。

【讨论】:

【参考方案3】:

回答你的问题:

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)
    

这将完全禁用网络 - 手动错误配置没有问题。

这里有一些文档: 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>

【讨论】:

依赖 spring-boot-starter 不附带 REST 客户端(即 RestTemplate),因此必须在 pom.xml 中指定 spring-web + jackson 依赖。依赖 spring-boot-starter-web 也有它,但是会让你的应用程序也成为一个 web 服务器,默认从端口 8080 开始。【参考方案4】:

您似乎完全走错了路,从 Web 应用程序模板开始,然后尝试关闭 Web 应用程序方面。

最好从常规命令行客户端模板开始并从那里开始,如relevant Spring Guide 中所述。

基本上应用程序简化为

@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 to

    <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>

【讨论】:

删除 spring-boot-starter-web 并添加 spring-boot-starter 并添加 spring-web 完成了工作。非常感谢。 它并不是一个 Web 应用程序模板,而是一个高级通用 Web 模板。如果您不需要 Web 服务器部分,您可以禁用它:docs.spring.io/spring-boot/docs/current/reference/html/… 仅供参考,相关 Spring Guide 的链接在 pom 中有 spring-boot-starter-web ,使用它会产生与 OP 相同的问题。不过,您在答案中找到了正确的 pom。【参考方案5】:

根据您的问题,我假设您希望您的应用程序继续在后台运行,并在其生命周期中进行一些 get 调用。如果是这样的话,那么

    回答您的第一个问题,是的,您需要嵌入式 tomcat 或 码头或需要将您的应用程序部署到外部应用程序 服务器。 第二,摆脱你面临的异常,不要排除 EmbeddedServletContainerAutoConfiguration 和 WebMvcAutoConfiguration 类,因为它是默认嵌入所需的 tomcat 自动配置。

【讨论】:

该问题没有提及必须服务 HTTP 请求,因此不需要 Web 服务器。

以上是关于Spring boot - 没有嵌入式 tomcat 的 Rest Call 客户端的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot - 没有嵌入式 tomcat 的 Rest Call 客户端

Elastic Beanstalk 工作层上的 Spring Boot

如何在嵌入式 tomcat 服务器上部署 Spring Boot Web 应用程序,来自 Spring Boot 本身

使用 IntelliJ 部署启用嵌入式 tomcat 的 spring-boot 应用程序

嵌入式 Jetty 环境中的 Spring Boot 和 Spring Security 集成

如何禁用嵌入式数据库 Spring-boot spring-data-jpa