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

Java中RegisterRestClient传参遇400错误,求助正确传参方式

问题:MicroProfile REST Client调用Spring Boot DELETE接口报400 BAD_REQUEST

问题场景

我编写了基于MicroProfile的REST客户端,调用Spring Boot服务端的DELETE接口时,请求能到达服务端但始终返回400错误。尝试移除注解、修改Content-Type、传递JSON字符串等操作均无效,且无法修改服务端代码。

客户端代码

import jakarta.ws.rs.*;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import a.b.c.TransferClientHeaders;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

@RegisterRestClient(configKey = "personkey")
@RegisterClientHeaders(TransferClientHeaders.class)
@ApplicationScoped
public interface PersonClient {

    @Path("/person/deletePersonBySKey")
    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    Response deletePersonBySKey(String personSKey);

}

public class TransferClientHeaders implements ClientHeadersFactory {

    private static final Logger logger = LoggerFactory.getLogger(EntityService.class);

    @Override
    public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders, MultivaluedMap<String, String> outgoingHeaders) {
        MultivaluedMap transferredHeaders = new MultivaluedHashMap<>();
        transferredHeaders.putAll(outgoingHeaders);
        transferredHeaders.put("ofs_remote_user", incomingHeaders.get("remote_user"));
        logger.debug("modified headers {}", incomingHeaders.get("remote_user"));
        return transferredHeaders;
    }
}

服务端代码

@FunctionsAllowed("F1,F2")
@DeleteMapping(value = "/deletePersonBySKey")
public ResponseEntity deletePersonBySKey(@RequestBody String personSKey) throws Exception {

    logger.debug("Inside The Person Controller");
    try {
        // 业务逻辑
    } catch (Exception e) {
        logger.error("Exception occurred ", e);

        try {
            responseJson.put("STATUS", "FAILED");
            responseJson.put("MESSAGE", "Person Services delete failed with exception: " + e.getMessage());
        } catch (JSONException e1) {
            logger.error("Exception occurred ", e1);
        }
        return new ResponseEntity(responseJson.toString(), HttpStatus.OK);
    }
    return ResponseEntity.ok("200");
}

调用代码

@Inject
@RestClient
PersonClient personClient;

personClient.deletePersonBySKey("1234");

问题原因

服务端通过@RequestBody从请求体中获取参数,但当前客户端的String personSKey参数会被JAX-RS默认解析为URL查询参数(拼在?personSKey=1234位置),服务端无法从请求体中拿到数据,因此返回400错误。此外,部分MicroProfile REST Client实现默认禁止DELETE方法携带请求体,进一步导致参数无法传递。

解决方案

1. 修正客户端参数映射

修改PersonClient接口,确保参数被作为请求体发送,并匹配服务端支持的媒体类型:

@RegisterRestClient(configKey = "personkey")
@RegisterClientHeaders(TransferClientHeaders.class)
@ApplicationScoped
public interface PersonClient {

    @Path("/person/deletePersonBySKey")
    @DELETE
    @Consumes(MediaType.TEXT_PLAIN) // 服务端接收纯文本字符串,对应@RequestBody String
    Response deletePersonBySKey(String personSKey);

}

如果服务端实际期望JSON格式的字符串(需要带引号的"1234"),则将@Consumes改为MediaType.APPLICATION_JSON,调用时传递带引号的字符串:

personClient.deletePersonBySKey("\"1234\"");

2. 启用DELETE方法携带请求体

在应用配置文件(如application.properties)中添加配置,允许MicroProfile REST Client为DELETE方法发送请求体:

mp.rest.client.enable-delete-with-body=true

3. 确认请求头正确性

检查TransferClientHeaders是否保留了Content-Type头,当前代码中transferredHeaders.putAll(outgoingHeaders)会保留默认生成的Content-Type,可添加日志确认:

logger.debug("outgoing headers {}", transferredHeaders);

验证测试

修改后重新调用客户端,服务端即可正确获取到personSKey参数,解决400错误。

内容的提问来源于stack exchange,提问作者Shanij P.S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:08:08