Java中将POJO转换为application/x-www-form-urlencoded表单数据
把BaseRequest转成form-urlencoded格式调用服务的解决方案
刚好碰到过类似的场景,给你两种实用的实现方式,都是适配Spring RestTemplate的:
方式一:手动构建表单键值对
这种方式最直观,完全可控,适合对参数格式有明确要求的场景:
public String getInvoice(BaseRequest req, String url) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 用LinkedMultiValueMap来存表单数据,它是Spring专门用于form请求的容器 MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); // 添加type字段 if (req.getType() != null) { formData.add("type", req.getType()); } // 遍历details里的所有键值对,转成表单参数 if (req.getDetails() != null) { req.getDetails().forEach((key, value) -> { // 这里用details[key]的命名是为了让服务端能识别属于details的参数,可按需调整 formData.add("details[" + key + "]", value != null ? value.toString() : ""); }); } // 同样处理signature字段 if (req.getSignature() != null) { req.getSignature().forEach((key, value) -> { formData.add("signature[" + key + "]", value != null ? value.toString() : ""); }); } // 组装请求实体 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers); // 调用服务并返回结果 return restTemplate.postForObject(url, requestEntity, String.class); }
方式二:借助Spring工具类自动转换
如果不想手动逐个处理字段,可以用Spring的BeanUtils来自动遍历并扁平化对象,代码更简洁:
import org.springframework.beans.BeanUtils; import org.springframework.beans.PropertyAccessor; import org.springframework.beans.PropertyAccessorFactory; public String getInvoice(BaseRequest req, String url) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); PropertyAccessor accessor = PropertyAccessorFactory.forBeanPropertyAccess(req); // 遍历BaseRequest的所有字段 BeanUtils.getPropertyDescriptors(BaseRequest.class).forEach(descriptor -> { String propertyName = descriptor.getName(); // 跳过class字段 if (!"class".equals(propertyName)) { try { Object value = accessor.getPropertyValue(propertyName); if (value != null) { if (value instanceof Map) { // 处理Map类型字段,拆成单个键值对 ((Map<?, ?>) value).forEach((k, v) -> { formData.add(propertyName + "[" + k + "]", v != null ? v.toString() : ""); }); } else { // 普通字段直接添加 formData.add(propertyName, value.toString()); } } } catch (Exception e) { // 这里可以根据业务做异常处理,比如打日志或者抛出自定义异常 e.printStackTrace(); } } }); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers); return restTemplate.postForObject(url, requestEntity, String.class); }
几个要注意的点
- 所有
Object类型的值都要转成String,如果有复杂自定义对象,得提前序列化(比如转成JSON字符串)再存到表单里。 - 参数命名格式(比如
details[key])可以根据服务端的接收要求调整,比如服务端直接要键名的话,就把details[" + key + "]改成key就行。 - 如果项目里有很多这类场景,也可以自定义一个
HttpMessageConverter来自动处理POJO到form数据的转换,但上面两种方式更轻量,适合快速落地。
内容的提问来源于stack exchange,提问作者Qawls
相关产品推荐
相关产品推荐

