Java中RegisterRestClient传参遇400错误,求助正确传参方式
问题场景
我编写了基于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

