You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS Lambda中不依赖Spring Boot与Tomcat使用Spring Data REST

在AWS Lambda中使用Spring Data REST(无重型Spring Boot依赖)

这个需求我刚好折腾过,要在Lambda里用Spring Data REST又要轻量化,核心就是砍掉Spring Boot的嵌入式容器和自动配置冗余,只保留最核心的组件。下面一步步来帮你实现:

1. 依赖选型:只挑必要的

绝对不能用spring-boot-starter-web或spring-boot-starter-data-rest(前者带Tomcat,后者依赖前者)。直接引入核心组件,确保依赖极简:

Maven pom.xml示例

<dependencies>
    <!-- Spring Data REST核心(不带容器) -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-rest-webmvc</artifactId>
        <version>3.5.12</version> <!-- 注意和Spring版本对齐 -->
    </dependency>
    <!-- Spring JPA持久层支持 -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.5.12</version>
    </dependency>
    <!-- Spring核心上下文 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.27</version>
    </dependency>
    <!-- Spring Web核心(提供Servlet API,不带容器) -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.27</version>
    </dependency>
    <!-- AWS Lambda核心依赖 -->
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-core</artifactId>
        <version>1.2.21</version>
    </dependency>
    <!-- API Gateway事件处理 -->
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-events</artifactId>
        <version>3.11.1</version>
    </dependency>
    <!-- 简化Lambda与Spring MVC的适配 -->
    <dependency>
        <groupId>com.amazonaws.serverless</groupId>
        <artifactId>aws-serverless-java-container-spring</artifactId>
        <version>2.0.11</version>
    </dependency>
    <!-- 数据库驱动(按需选择,这里用H2做示例) -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.2.224</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

注意:所有Spring相关组件版本必须对齐,避免兼容性问题。

2. 手动配置Spring上下文(拒绝自动配置冗余)

不用@SpringBootApplication,而是用纯@Configuration手动组装组件,只加载你需要的功能:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableWebMvc // 启用Spring MVC核心(无嵌入式容器)
@EnableJpaRepositories(basePackages = "com.yourpackage.repositories")
@EnableRestRepositories(basePackages = "com.yourpackage.repositories")
public class AppConfig implements RepositoryRestConfigurer {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        // 配置REST基础路径和HATEOAS支持
        config.setBasePath("/api"); // 所有REST端点前缀
        config.exposeIdsFor(Product.class); // 可选:暴露实体ID在响应中
        // 默认已开启HATEOAS,会自动生成HAL格式的链接
    }

    // 手动配置数据源
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        return dataSource;
    }

    // 手动配置JPA实体管理器
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.yourpackage.entities");
        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        em.setJpaProperties(hibernateProperties());
        return em;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        return properties;
    }
}

3. Lambda入口:连接API Gateway与Spring MVC

用AWS官方的aws-serverless-java-container-spring库自动处理请求转换,不用自己写Servlet包装类:

import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.spring.SpringLambdaContainerHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class LambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    // 冷启动时初始化一次Spring上下文
    private static final SpringLambdaContainerHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> handler;

    static {
        try {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            handler = SpringLambdaContainerHandler.getAwsProxyHandler(context);
        } catch (ContainerInitializationException e) {
            e.printStackTrace();
            throw new RuntimeException("Spring容器初始化失败", e);
        }
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
        // 直接转发请求给Spring MVC处理
        return handler.proxy(input, context);
    }
}

4. 实现Entity和Repository

写一个简单的实体和Repository,Spring Data REST会自动生成CRUD端点并支持HATEOAS:

实体类

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Product {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private Double price;

    // Getters & Setters
}

Repository接口

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(collectionResourceRel = "products", path = "products")
public interface ProductRepository extends JpaRepository<Product, Long> {
}

现在你已经拥有了完整的CRUD端点,比如:

  • GET /api/products:获取所有产品(带HATEOAS链接)
  • POST /api/products:创建产品
  • GET /api/products/{id}:获取单个产品
  • PUT /api/products/{id}:更新产品
  • DELETE /api/products/{id}:删除产品

5. 优化启动速度与包大小

  • 开启Lambda SnapStart:把冷启动时间压缩到几百毫秒,非常适合Spring应用
  • 依赖分层:把Spring相关重型依赖打包到Lambda层,业务代码包只保留自己的代码
  • 排除冗余依赖:用mvn dependency:tree检查依赖树,排除不需要的组件
  • 可选:GraalVM原生镜像:追求极致启动速度的话,可以编译成原生镜像(注意Spring Data REST的兼容性)

6. 本地测试

用AWS SAM CLI本地测试:

  1. 编写template.yaml定义API Gateway和Lambda
  2. 执行sam build构建项目
  3. 执行sam local start-api启动本地服务,用curl测试端点:curl http://localhost:3000/api/products

内容的提问来源于stack exchange,提问作者Abdeali Chandanwala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:03:17