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

Micronaut POST接口无法接收请求体,获取到Optional.empty问题排查

问题描述

使用Micronaut构建POST接口时,通过Postman或curl调用API,服务器端始终获取到请求体为Optional.empty。GET请求正常,能接收所有请求头,仅请求体存在问题。

控制器代码

import io.micronaut.core.annotation.NonNull;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.*;
import jakarta.inject.Inject;
import lombok.extern.log4j.Log4j2;

import java.util.Objects;

@Controller("/abc/v1")
@Log4j2
public class AbcController {
      @Post("/get-new-user-referral-code")
      @Produces(MediaType.APPLICATION_JSON)
      @Consumes(MediaType.TEXT_PLAIN)
      @WithSpan
      public GetReferralCodeResponse getNewUserReferralCode(HttpRequest<?> request) {
        String body = request.getBody().toString();
        HttpHeaders headers = request.getHeaders();

        log.info("Body = {}", body);

    return apiResponse;
  }
}

build.gradle配置

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
    id("com.github.johnrengelman.shadow") version "8.1.1"
    id("io.micronaut.application") version "4.4.0"
    id("io.micronaut.aot") version "4.4.0"
    id("groovy")
    id("jacoco")
}

version = "0.1"
group = "com.abc"

repositories {
    mavenCentral()
}

dependencies {
    annotationProcessor("io.micronaut:micronaut-http-validation")
    annotationProcessor("io.micronaut.serde:micronaut-serde-processor")
    implementation("io.micronaut.serde:micronaut-serde-jackson")
    implementation("io.micronaut:micronaut-management")
    implementation("io.micronaut:micronaut-http-client")


    implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
    implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'

    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
    testCompileOnly 'org.projectlombok:lombok:1.18.30'

    implementation 'software.amazon.awssdk:bom'
    implementation 'software.amazon.awssdk:appconfigdata'
    implementation 'software.amazon.awssdk:sts'
    implementation 'software.amazon.awssdk:netty-nio-client:2.24.3'
    implementation 'io.netty:netty-codec-http:4.1.108.Final'
    implementation 'com.github.luben:zstd-jni:1.5.6-6'
    implementation 'software.amazon.awssdk:apache-client:2.20.69'
    implementation("software.amazon.awssdk:url-connection-client:2.17+")

    implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
    implementation 'software.amazon.awssdk:lambda:2.17.206'

    implementation 'software.amazon.awssdk:dynamodb'
    implementation 'software.amazon.awssdk:dynamodb-enhanced'

    implementation 'software.amazon.awssdk:sns'
    implementation 'software.amazon.awssdk:sqs'

    implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
    implementation 'org.apache.logging.log4j:log4j-core:2.20.0'

    implementation 'org.json:json:20231013'
    implementation 'org.jsonschema2pojo:jsonschema2pojo-core:1.2.1'

    // opentelemetry
    implementation("io.opentelemetry:opentelemetry-exporter-otlp")
    implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.3.0')
    implementation("io.opentelemetry:opentelemetry-exporter-logging")
    implementation("io.opentelemetry:opentelemetry-sdk")
    implementation("io.reactivex.rxjava2:rxjava:2.2.21")


    testAnnotationProcessor 'io.micronaut:micronaut-inject-java'

    implementation("io.micronaut.kafka:micronaut-kafka")

    developmentOnly("io.micronaut.controlpanel:micronaut-control-panel-ui")
    developmentOnly("io.micronaut.controlpanel:micronaut-control-panel-management")

    implementation("io.micronaut.objectstorage:micronaut-object-storage-aws")

    testImplementation 'org.mockito:mockito-core:3.12.4'

}


application {
    mainClass = "com.abc.Application"
}
java {
    sourceCompatibility = JavaVersion.toVersion("21")
    targetCompatibility = JavaVersion.toVersion("21")
}


graalvmNative.toolchainDetection = false
micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("com.abc.*")
    }
    aot {
        // Please review carefully the optimizations enabled below
        // Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details
        optimizeServiceLoading = false
        convertYamlToJava = false
        precomputeOperations = true
        cacheEnvironment = true
        optimizeClassLoading = true
        deduceEnvironment = true
        optimizeNetty = true
        replaceLogbackXml = true
    }
}


tasks.named("dockerfileNative") {
    jdkVersion = "21.0.4"
}

日志信息

"Unrecognized token 'Optional': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled)

Curl请求

curl --location 'http://localhost:8080/abc/v1/get-new-user-referral-code' \
--header 'Content-Length: 1000' \
--header 'Content-Type: text/plain' \
--data 'abc'

问题分析与解决方案

核心问题1:请求体获取方式错误

当前代码调用request.getBody().toString(),但getBody()返回的是Optional<Object>,直接调用toString()会输出Optional.empty或Optional[abc]这类字符串,而非真正的请求体内容。这也是日志中出现Unrecognized token 'Optional'错误的原因——后续代码将该字符串当作JSON解析,自然失败。

正确的获取方式:

// 明确指定类型为String,让Micronaut正确解析文本请求体
Optional<String> bodyOpt = request.getBody(String.class);
String body = bodyOpt.orElse(""); // 处理空请求体场景
log.info("Body = {}", body);

核心问题2:请求头Content-Length不匹配

curl请求中设置了Content-Length: 1000,但实际发送的数据仅3个字符(abc),服务器端读取请求体时会因长度不符触发异常,直接放弃读取,导致请求体为空。

移除错误的Content-Length头即可,curl会自动计算并设置正确长度:

curl --location 'http://localhost:8080/abc/v1/get-new-user-referral-code' \
--header 'Content-Type: text/plain' \
--data 'abc'

额外优化:直接通过方法参数接收请求体

Micronaut支持将请求体直接绑定到方法参数,无需手动从HttpRequest中获取,代码更简洁且不易出错:

@Post("/get-new-user-referral-code")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.TEXT_PLAIN)
@WithSpan
public GetReferralCodeResponse getNewUserReferralCode(@Body String body, HttpHeaders headers) {
    log.info("Body = {}", body);
    return apiResponse;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:22:34