Spring RestTemplate向邮件API发送byte[]数据异常问题解决
解决RestTemplate调用邮件API时byte[]字段序列化问题
问题场景
调用邮件API时,使用Spring的RestTemplate发送请求始终失败,但将HttpEntity的body内容复制到Postman中却能正常请求。尝试自定义实体类的toString方法匹配Postman的请求格式,仍然无效,最终定位问题出在content字段的byte[]数据序列化上。
相关代码
实体类CreateAndQueueMailRq
@Builder public class CreateAndQueueMailRq { private String application; private String bcc; private String body; private String cc; private String creationDate; private String creationUser; private String from; private String fromName; private String id; private String market; private String subject; private String system; private String to; private String language; private String type; private String attachmentType; private String attachmentFileName; private byte[] content; @Override public String toString() { return "{\"application\":\"" + application + "\"," + "\"bcc\":\"" + bcc + "\"," + "\"body\":\"" + body + "\"," + "\"cc\":\"" + cc + "\"," + "\"creationDate\":\"" + creationDate + "\"," + "\"creationUser\":\"" + creationUser + "\"," + "\"from\":\"" + from + "\"," + "\"fromName\":\"" + fromName + "\"," + "\"id\":\"" + id + "\"," + "\"market\":\"" + market + "\"," + "\"subject\":\"" + subject + "\"," + "\"system\":\"" + system + "\"," + "\"to\":\"" + to + "\"," + "\"language\":\"" + language + "\"," + "\"type\":\"" + type + "\"," + "\"attachmentType\":\"" + attachmentType + "\"," + "\"attachmentFileName\":\"" + attachmentFileName + "\"," + "\"content\":" + Arrays.toString(content) + "}"; } }
请求调用代码
public boolean sendMailWithAttachment(String body, String from, String fromName, String id, String subject, String to, String language, String filename, byte[] content, String cc, String bcc){ CreateAndQueueMailRq createAndQueueMailRq = CreateAndQueueMailRq.builder() .application("appname") .bcc("") .body(body) .cc("samplemail@gmail.com") .creationDate(LocalDateTime.now().format(FORMATTER)) .creationUser(MailManagerConstants.COMING2) .from(from) .fromName(fromName) .id(id) .market("market_default") .subject(subject) .system("system_default") .to("samplemail@gmail.com") .language("ES") .type(DEFAULT_TYPE) .attachmentType(MailManagerConstants.TYPE_PDF) .attachmentFileName(filename) .content(content) .build(); return generateRequest(createAndQueueMailRq, API_MAIL_MANAGER_WITH_ATTACHMENT); } private boolean generateRequest(CreateAndQueueMailRq createAndQueueMailRq, String api) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); try { HttpEntity<CreateAndQueueMailRq> request = new HttpEntity<>(createAndQueueMailRq, headers); System.out.println("Request: "+request.getBody()); ResponseEntity<?> response = restTemplate.exchange(api, HttpMethod.POST, request, String.class); LOGGER.info(SUCCESS_MESSAGE); return true; }catch (HttpClientErrorException e){ LOGGER.info("STATUS CODE: "+e.getStatusCode()); LOGGER.info("RESPONSE BODY: "+e.getResponseBodyAsString()); LOGGER.info(ERROR_MESSAGE); return false; } }
问题分析
默认的序列化逻辑会将byte[]类型的content字段转换为带双引号的字符串格式(如"content":"[37,40,30...]"),但目标API需要的是不带引号的纯数组格式(如"content":[37,40,30...]),这就导致RestTemplate发送的请求格式不符合API要求,而Postman中使用的是正确格式,因此可以成功调用。
解决方案:自定义HttpMessageConverter
通过继承GsonHttpMessageConverter并自定义序列化逻辑,对byte[]类型单独处理,输出API需要的格式:
public class MailManagerCustomConverter extends GsonHttpMessageConverter { @Override protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { if (object instanceof byte[]) { byte[] bytes = (byte[]) object; StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < bytes.length; i++) { if (i > 0) { sb.append(","); } sb.append(bytes[i]); } sb.append("]"); outputMessage.getBody().write("\"content\":".getBytes()); outputMessage.getBody().write(sb.toString().getBytes()); } else { super.writeInternal(object, outputMessage); } } }
该转换器会将content字段输出为"content":[37,40,30...]格式,而非默认的带引号字符串格式,从而符合API的请求要求。
内容的提问来源于stack exchange,提问作者Codepressed
相关产品推荐
相关产品推荐

