1. 概述

本文带你快速掌握 Apache 开源项目 Meecrowave 的核心用法。

Meecrowave 是 Apache 推出的一个轻量级微服务框架,天生支持 CDI、JAX-RS 和 JSON-P/JSON-B,开箱即用。
它最大的优势是——无需再折腾 Tomcat、WildFly 等重型应用服务器,一个 jar 包就能跑起来,部署简单粗暴。

适合快速搭建 REST 微服务原型或轻量级服务,尤其适合对启动速度和资源占用敏感的场景。


2. Maven 依赖

使用 Meecrowave,只需引入核心依赖。在 pom.xml 中添加:

<dependency>
    <groupId>org.apache.meecrowave</groupId>
    <artifactId>meecrowave-core</artifactId>
    <version>1.2.15</version>
    <classifier>jakarta</classifier>
    <exclusions>
      <exclusion>
        <groupId>*</groupId>
        <artifactId>*</artifactId>
      </exclusion>
    </exclusions>
</dependency>

📌 建议前往 Maven Central 查看最新版本。

⚠️ 注意:classifier 使用 jakarta 表示支持 Jakarta EE 9+,如果你还在用 Java EE 8,请根据实际情况调整。


3. 启动一个简单服务

启动 Meecrowave 服务非常简单,只需要一个 main 方法:

public static void main(String[] args) {
    try (Meecrowave meecrowave = new Meecrowave()) {
        meecrowave.bake().await();
    }
}

解释一下关键操作:

  • bake():形象地表示“烘烤”,即启动服务器。
  • await():阻塞主线程,防止 JVM 退出。
  • 使用 try-with-resources:确保服务关闭时资源被正确释放。

自定义配置

默认配置可能不够用,可以通过 Meecrowave.Builder 灵活定制:

Meecrowave.Builder builder = new Meecrowave.Builder();
builder.setHttpPort(8080);
builder.setScanningPackageIncludes("com.example.api");
builder.setJaxrsMapping("/api/*");
builder.setJsonpPrettify(true);

然后传入 Builder 启动:

try (Meecrowave meecrowave = new Meecrowave(builder)) { 
    meecrowave.bake().await();
}

常用配置项包括:

  • setHttpPort():设置 HTTP 端口
  • setScanningPackageIncludes():指定组件扫描包路径
  • setJaxrsMapping():设置 JAX-RS 接口前缀
  • setJsonpPrettify():开启 JSON 格式化输出

📌 完整配置参考:官方文档 - Configuration

💡 开发建议:在 IDE 中运行 main 方法时,Meecrowave 支持热加载(配合 JRebel 或 devtools),改代码不用反复重启,效率提升明显。

⚠️ Java 9+ 用户注意:如果遇到 JAXB 相关报错,启动时加上:

--add-modules java.xml.bind

4. 定义 REST 接口

服务启动后,就可以定义 REST 接口了。Meecrowave 基于 JAX-RS 实现,所以直接用标准注解即可:

@RequestScoped
@Path("article")
public class ArticleEndpoints {
    
    @GET
    public Response getArticle() {
        return Response.ok().entity(new Article("Java Guide", "Alice")).build();      
    }
    
    @POST 
    public Response createArticle(Article article) { 
        return Response.status(Status.CREATED).entity(article).build(); 
    }
}

关键点:

  • ✅ 使用 @Path@GET@POST 等 JAX-RS 注解定义接口
  • @RequestScoped 表示该类在每次请求时创建实例
  • ✅ 返回 Response 对象,灵活控制状态码和响应体

📌 JAX-RS 详细用法可参考相关规范文档。


5. 接口测试

Meecrowave 提供了强大的测试支持,通过 meecrowave-junit 插件可以轻松编写集成测试。

添加测试依赖

<dependency>
    <groupId>org.apache.meecrowave</groupId>
    <artifactId>meecrowave-junit</artifactId>
    <version>1.2.15</version>
    <scope>test</scope>
</dependency>

<!-- HTTP 客户端 -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
    <scope>test</scope>
</dependency>

最新版本参考:meecrowave-junitOkHttp

编写测试用例

@RunWith(MonoMeecrowave.Runner.class)
public class ArticleEndpointsIntegrationTest {
    
    @ConfigurationInject
    private Meecrowave.Builder config;
    
    private static OkHttpClient client;
    
    @BeforeClass
    public static void setup() {
        client = new OkHttpClient();
    }
    
    @Test
    public void whenRetunedArticle_thenCorrect() {
        String base = "http://localhost:" + config.getHttpPort();
        
        Request request = new Request.Builder()
          .url(base + "/article")
          .build();
          
        Response response = client.newCall(request).execute();
        assertEquals(200, response.code());
    }
}

关键注解说明:

  • @RunWith(MonoMeecrowave.Runner.class):启动嵌入式 Meecrowave 服务器
  • @ConfigurationInject:注入配置对象,可用于获取随机端口(测试时常用)

这样测试时会自动启动服务,测试完自动关闭,无需手动管理生命周期。


6. 依赖注入(CDI)

Meecrowave 内置 CDI(Contexts and Dependency Injection),可以直接使用注解实现依赖注入。

定义服务类

@ApplicationScoped
public class ArticleService {
    public Article createArticle(Article article) {
        return article;
    }
}
  • @ApplicationScoped:应用级单例,整个生命周期只创建一次

注入使用

@Path("article")
public class ArticleEndpoints {
    
    @Inject
    ArticleService articleService;

    @POST 
    public Response createArticle(Article article) { 
        Article saved = articleService.createArticle(article);
        return Response.status(Status.CREATED).entity(saved).build(); 
    }
}
  • ✅ 使用 @Inject 即可完成注入
  • 支持 RequestScoped、SessionScoped、ApplicationScoped 等多种作用域

CDI 是 Jakarta EE 的核心特性之一,Meecrowave 对其支持非常完整。


7. 打包与部署

开发完成之后,可以用 Meecrowave 的 Maven 插件一键打包成可分发的部署包。

添加插件

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.meecrowave</groupId>
            <artifactId>meecrowave-maven-plugin</artifactId>
            <version>1.2.15</version>
        </plugin>
    </plugins>
</build>

打包命令

mvn meecrowave:bundle

执行后会在 target/ 目录生成一个 zip 包:

meecrowave-meecrowave-distribution.zip

解压后目录结构如下:

|____meecrowave-distribution
| |____bin
| | |____meecrowave.sh
| |____logs
| | |____you_can_safely_delete.txt
| |____lib
| |____conf
| | |____log4j2.xml
| | |____meecrowave.properties

启动与停止

进入 bin 目录,使用脚本控制服务:

# 启动
./meecrowave.sh start

# 停止
./meecrowave.sh stop

📦 这个打包方式非常适合部署到生产环境或 CI/CD 流程中,结构清晰,操作简单。


8. 总结

本文带你实战了如何使用 Apache Meecrowave 快速构建一个轻量级微服务,涵盖了:

  • ✅ 核心依赖引入
  • ✅ 服务启动与配置
  • ✅ JAX-RS 接口定义
  • ✅ 集成测试编写
  • ✅ CDI 依赖注入
  • ✅ 生产级打包部署

Meecrowave 的设计理念就是“极简 + 标准化”,基于 Jakarta EE 规范,不造轮子,却能极大简化微服务开发流程。

如果你厌倦了 Spring Boot 的臃肿,又想保持企业级开发的规范性,Meecrowave 是一个非常值得尝试的替代方案

📌 所有示例代码已上传至 GitHub:https://github.com/baeldung-tutorials/apache-meecrowave-demo


原始标题:Building a Microservice with Apache Meecrowave | Baeldung