29

从Tomcat到Spring Boot

 6 years ago
source link: https://segmentfault.com/a/1190000016152932?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

暮夏八月是一年中最好的时节,近近地看到了凉爽的希望,却还能享用暖热的余温。距离 Phil Webb 发布 Spring Boot 已经 4 年有余,我们尝试在这个夏天把这只已经独自在外游荡了 19 年的野猫 Tomcat 装入春天的长靴。

从零开始安装 Spring Boot 项目,使用内嵌的 Tomcat 引擎是比较容易的事情,各种中文教程已经数不胜数,那不是我们要谈论的话题。在这里我们要做的是以最小的代价把一个已有的 Tomcat 项目改造为 Spring Boot 项目,以实现我们微服务改造的第一步。

对pom.xml的修改

添加spring-boot-maven-plugin

一般来说,在每一个 pom.xml 的结尾,都会有一个 build 段落,在这里添加 spring-boot-maven-plugin 是必经的第一个步骤,添加完之后的完整段落如下:

<build>
        <finalName>my-app</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>-Xmx64m</jvmArguments>
                </configuration>
            </plugin>
        </plugins>
    </build>

在这里,我们特别添加了一个 configuration 段落,设置 -Xmx64m ,这是因为 Tomcat 缺省会分配物理内存的 1/4 为堆内存,这样我们一台电脑最多只能运行 4Tomcat 服务,内存就不够用了。在这里我们把 heap size 的最大尺寸设置为只用 64m ,可以有效节省内存,最多会引起垃圾回收频繁一些而已,这之间的平衡可以自己掌握。

添加spring-boot-starter-parent

Spring Boot 是一个非常独立的父母,它认为所有与 spring 有关的依赖都是它的孩子,所以我们必须引入 spring-boot-starter-parent ,让它来管理所有姓 spring 的孩子。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>

由于 Spring Boot 自己管理所有 spring 依赖,你还需要把原先加在 pom.xml 里的所有与 spring 有关的依赖(以及所有 spring 想要管理的依赖,例如 com.fasterxml.jackson.core )全部删掉,否则会造成版本冲突。比如这样:

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.1.RELEASE</version> </dependency>

添加spring-boot-starter-web

Spring Boot 唯一需要我们手工添加的依赖只有一个:

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

有了这个依赖以后, Spring Boot 项目启动的时候就会内嵌一个 Tomcat 服务器。同时 Spring Boot 带来的另外一个好处是:我们从此不必再依赖 Tomcat ,如果我们想换成其它引擎,只需要加上新引擎,排除掉 Tomcat 就可以了,假设我们想换成 Undertow ,只需要这样设置:

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

主程序入口

Application.java

传统的 Tomcat 应用是让 Tomcat 先启动,然后加载我们的 war 文件,改造之后是 Spring Boot 先启动,由 Spring Boot 来加载 Tomcat ,所以我们需要给我们的应用里增加一个 Application.java 文件:

package com.domain.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

application.properties

传统的 Tomcat 是把所有配置项放在 webapp/WEB-INF/web.xml 里来管理的, Spring Boot 不使用 web.xml 文件,它把所有配置项都放在 resources/application.properties 文件中,例如:

server.port=8090
server.servlet.context-path=/app

运行

至此为止,就已经完成了从 TomcatSpring Boot 的迁移。我们可以通过 maven 运行 Spring Boot 来看一下效果:

mvn spring-boot:run

添加dubbo

如果以前的项目是由 dubbo 完成的,暂时还不想破坏原有架构,可以把 dubbo 集成到 Spring Boot 中来。

pom.xml

pom.xml 中添加 dubbo-spring-boot-starter 依赖:

<dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>1.0.2</version>
        </dependency>

这个 dubbo-spring-boot-starter 的最高版本是 2.0.0 ,并且即便这个 2.0.0已经被废弃 ,更高的版本迁移到了 incubator-dubbo-spring-boot-project 上,但是由于我用的是 dubbo 较低的版本 2.5.3 ,使用了比较方便的 <dubbo:annotation> 方式,所以不可能采用它的 2.0.0 版本,更加不可能使用 incubator-dubbo-spring-boot-project (这个 incubator-dubbo-spring-boot-project 项目甚至不支持在 application.properties 文件中对 dubbo 做配置)。

Dubbo2.5.7 以后 废弃了<dubbo:annotation>方式 ,改采 @DubboComponentScan 方式,我个人认为这种新方式远远不如旧的 <dubbo:annotation> 方式简便,所以目前或者以后也不准备迁移到更高版本的 dubbo 了。

Application.java

pom.xml 中添加对 dubbo 的依赖后,还需要在 Application.java 中添加 dubbo 的自动配置功能:

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;

@SpringBootApplication
@EnableDubboConfiguration

application.properties

然后在 application.properties 文件中添加 dubbo 的配置项:

spring.dubbo.appname=my-app
spring.dubbo.registry=zookeeper://myip.mydomain.com:2181

这个配置项功能很弱,但勉强够用。虽然它会造成一些 很难看的日志

[2018-08-26 12:21:25] WARN  -  [DUBBO] ReferenceConfig(null) is not DESTROYED when FINALIZE, dubbo version: 2.5.3, current host: 192.168.1.2

但是鉴于这个插件已经被废弃了,不会有人来解决这个问题,只能勉强这么用了。

总结

以上就是从 Tomcat 迁移到 Spring Boot 所需要的所有改动。总计只是修改了 pom.xml 一个文件,新增了 Application.javaapplication.properties 两个文件,新增代码行数不超过 20 行,整个迁移过程还是比较简便的。

当然,仅仅在代码层面迁移到 Spring Boot 不是最终目的,我们还需要在 pom.xml 文件中把 <packaging>war</packaging> 改为 <packaging>jar</packaging> ,这样我们在执行 mvn package 之后,就可以 java -jar myapp.jar 来在服务器端进行部署。

更进一步,当以 Spring Boot 方式启动的微服务越来越多的时候,服务治理将成为一个难题,这时候就需要考虑引入 Eureka 或者甚至 Kubernetes 进行服务治理,那将是另外一个大话题了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK