通过删除不需要的依赖项或替换启动器来减小 Java Spring 应用程序的大小

the*_*ter 2 java spring gradle spring-data-jpa spring-boot

我正在使用 Spring 和 Gradle 来构建一个宁静的 API。由于此 API 与 PostgreSQL 数据库配合使用,因此我还使用 JPA 连接此数据库并与之交互。我使用这个 spring.io 指南来开发基本应用程序并能够使用 JPA,我添加了一些更多的依赖项。该应用程序现在总共有 29MB 大小,这对我来说有点太大了。到目前为止,API 功能没有什么比一些基本的 CRUD 操作更复杂,因此我尝试通过以下方式减小整体大小:

  • 使用gradle lint 插件自动处理我未使用的依赖项,但运行gradle buildJava fixGradleLint返回

    任务 :fixGradleLint 通过 lint 检查 0 次违规;无需更正 更正了 0 个棉绒问题

  • 在 gradle 构建文件中,我添加了一个配置块,我在未使用的依赖项上使用了排除组或模块,例如:

    configurations {
        implementation {
            exclude group: 'org.yaml', module: 'snakeyaml'
            exclude group: 'net.bytebuddy'
            exclude group: 'org.objenesis', module: 'objenesis'
            exclude group: 'org.mockito'
           // exclude module: 'spring-boot-starter-logging'
        }
     }
    
    Run Code Online (Sandbox Code Playgroud)

这产生的效果是,例如Mockito从提供的依赖项列表中消失,gradle dependiencies但它们的排除项根本没有减少应用程序的大小。

如何有效地减小应用程序的大小?也许我可以摆脱弹簧启动器,因为它们似乎可以拉入包括我的咖啡杯在内的所有东西;)。但是,我没有找到如何执行此操作的方法。我会为每一个消失的 MB 感到高兴。

下面我发布了我的build.gradle文件以供澄清:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
    classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE'
    classpath 'com.netflix.nebula:gradle-lint-plugin:latest.release'
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'
apply plugin: 'nebula.lint'

gradleLint.rules =  ['dependency-parentheses','unused-dependency']

bootJar { baseName = 'name' version =  '0.1.0' }
repositories {mavenCentral()}

sourceCompatibility = 1.8
targetCompatibility = 1.8

configurations {
    implementation {
        exclude group: 'org.yaml', module: 'snakeyaml'
        exclude group: 'net.bytebuddy'
        exclude group: 'org.objenesis', module: 'objenesis'
        exclude group: 'org.mockito'
        //exclude module: 'spring-boot-starter-logging'
     }
 }
dependencies {
    compile 'org.springframework:spring-beans:5.0.6.RELEASE'
    compile 'org.springframework.boot:spring-boot-autoconfigure:2.0.2.RELEASE'
    compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
    compile 'org.springframework.boot:spring-boot:2.0.2.RELEASE'
    compile 'org.springframework.data:spring-data-commons:2.0.7.RELEASE'
    compile 'org.springframework:spring-web:5.0.6.RELEASE'
    compile 'org.springframework:spring-context:5.0.6.RELEASE'

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'
    implementation 'org.postgresql:postgresql:42.2.0'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
 }
Run Code Online (Sandbox Code Playgroud)

g00*_*00b 6

如果您查看生成的 JAR 文件的内部结构,您会发现大多数依赖项都是必需的。

更改 servlet 容器

但是有一些选择,虽然 Tomcat 是轻量级的,但 Jetty 和 Undertow 更轻量级,而 Undertow 是最小的。虽然这只会让您赢得 100 KB,但您可以通过排除以下内容(使用 Maven)来替换它们:

<exclusion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

之后,您可以包含以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

但是,在我的系统上,这将 JAR 大小减少了约0,2MB,实际上差别不大。

删除日志记录

虽然 Logback 框架包含在 中spring-boot-starter-logging,但它不是强制性的。对于科学,我们可以通过向所有 Spring boot starter 添加以下排除项:

 <exclusion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这将 JAR 大小减少了大约1MB

删除 Tomcat 的 WebSocket 支持

如果您决定继续使用 Tomcat,并且不需要 WebSocket 支持,则可以删除它。您可以通过添加以下排除项来做到这一点:

 <exclusion>
     <groupId>org.apache.tomcat.embed</groupId>
     <artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这将 JAR 大小减少了大约0,3MB

删除对 bean 验证的支持 (JSR-380)

如果您不打算在 API 中使用 bean 验证,则可以使用以下排除项将其从 Web Starter 中排除:

<exclusion>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

这将在我的系统上将 JAR 大小再减少1MB

YAML 支持

如果您不打算使用application.yml,您可以通过向所有启动项添加以下排除项来额外删除snakeyaml 依赖项:

<exclusion>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

这会将 JAR 大小再减少0,3MB

去除Tomcat的表达语言

开发简单 REST API 时可能不需要的另一个依赖项是 Tomcat 的表达式语言。您可以使用以下方法从 web starter 中排除它:

<exclusion>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-el</artifactId>
</exclusion>
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这将 JAR 大小减少了大约0,2MB


概括

总而言之,这些库包含的所有依赖项都是使它们正常工作所必需的。如果没有,他们通常将它们作为可选的依赖项提供,并且有很好的文档记录。

可能只是您不需要该功能。然而,这是一条有风险的道路,因为没有官方指导方针告诉您是否需要此依赖项,并且它可能会随着时间的推移而改变,或者您可能需要该功能。

通常,收益很小,因为大型 JARS(hibernate-core、tomcat-embed-core、jackson-databind、spring-web、spring-core 等)都是强制性的。

  • 你不能没有日志记录......排除`spring-boot-starter-logging`仍然会做日志记录,但最终要么回退到System.out或Java.util.logging。 (2认同)