客户端期望octet-stream时,如何返回FaultDto异常响应?
解决octet-stream类型响应下的FaultDto返回问题
当客户端请求的Accept头为application/octet-stream时,无法直接返回序列化后的JSON/XML格式FaultDto——因为服务端约定该类型下返回的是Resource包装的二进制流。可以通过以下几种方式处理:
方案1:将FaultDto序列化为字节流包装进Resource
复用现有FaultDto的序列化逻辑(JSON/XML),把序列化后的内容转为字节数组,再用ByteArrayResource包装返回,同时保持错误状态码。
@ExceptionHandler({IOException.class}) public ResponseEntity<?> ioExceptionHandler(IOException exception, WebRequest webRequest) { FaultDto dto = buildFaultDto(exception, webRequest); String acceptHeader = webRequest.getHeader(HttpHeaders.ACCEPT); if (MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(acceptHeader)) { // 这里用JSON序列化,也可替换为XML序列化逻辑 byte[] faultBytes; try { faultBytes = new ObjectMapper().writeValueAsBytes(dto); } catch (JsonProcessingException e) { // 序列化失败时返回兜底错误字节流 faultBytes = "Internal server error".getBytes(StandardCharsets.UTF_8); } Resource resource = new ByteArrayResource(faultBytes); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(resource); } else { // 非二进制流请求,正常返回JSON/XML格式的FaultDto return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(dto); } }
注意:需要提前和客户端约定二进制流中的序列化格式(比如JSON),确保客户端能正确解析字节流还原FaultDto。
方案2:自定义错误二进制格式
如果对传输格式有特殊要求,可以定义专属的二进制错误结构(比如固定长度的错误码+消息内容),再转为字节数组包装返回。
@ExceptionHandler({IOException.class}) public ResponseEntity<?> ioExceptionHandler(IOException exception, WebRequest webRequest) { FaultDto dto = buildFaultDto(exception, webRequest); String acceptHeader = webRequest.getHeader(HttpHeaders.ACCEPT); if (MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(acceptHeader)) { byte[] faultBytes = convertFaultToBinary(dto); Resource resource = new ByteArrayResource(faultBytes); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(resource); } else { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(dto); } } // 自定义二进制错误转换逻辑 private byte[] convertFaultToBinary(FaultDto dto) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos)) { // 写入错误码(4字节整数) dos.writeInt(dto.getErrorCode()); // 写入消息字节长度(4字节整数) byte[] msgBytes = dto.getMessage().getBytes(StandardCharsets.UTF_8); dos.writeInt(msgBytes.length); // 写入消息内容 dos.write(msgBytes); return baos.toByteArray(); } catch (IOException e) { throw new RuntimeException("Failed to convert fault to binary", e); } }
这种方式需要客户端和服务端严格对齐二进制格式,适合对传输效率要求较高的场景。
方案3:返回兜底错误二进制资源(不推荐)
如果不需要传递具体错误信息,可返回一个预定义的兜底二进制资源(比如空字节流、固定错误标识文件),但这种方式会丢失错误详情,仅适用于对错误信息无要求的场景。
内容的提问来源于stack exchange,提问作者Five
相关产品推荐
相关产品推荐

