詭異事情描述:A用戶端通過feign調用 服務端接口報錯feign.FeignException$BadRequest: status 400 reading。B用戶端通過feign調用服務端接口 又是正常的傳回。 A和B 項目中導入的相關feign版本都一樣。
代碼調整前如下:
用戶端代碼:
@Data
public class ControlRequestDto implements Serializable {
private static final long serialVersionUID = -5082851597684307746L;
//裝置點位名對應的水務集團的編碼
private String mappingId;
//裝置點位名
private String tag;
//控制指令下發時間
private Date controlTime;
//控制指令值
private String controlValue;
}
/**
* @author wangtingsong
* @date 2022/5/9 16:15
* @description 這裡的注解FeignClient中的name屬性值必須是 你調用的接口子產品的spring.application.name 的值
*/
@FeignClient(name = "controlcenter")
public interface ControlCenterClient {
@PostMapping("/controlcenter/control/controlDevice")
String controlDevice(@RequestBody ControlRequestDto controlRequestDto);
}
服務端代碼:
@RestController
@RequestMapping("/control")
@Slf4j
public class ControlCenterController {
@Autowired
private ControlCenterService controlCenterService;
@PostMapping("/controlDevice")
public BaseResult<Boolean> controlDevice(@RequestBody ControlRequestDto dto){
log.info("控制裝置入參:{}", JSONObject.toJSONString(dto));
try {
return controlCenterService.controlDevice(dto);
}catch (Exception e){
log.error("控制裝置異常:{}", dto.getTag(),e);
return BaseResult.<Boolean>builder().message("控制裝置異常").code("500").build();
}
}
}
問題查找:根據A和B斷點來一步步看,最終是哪裡調用不一樣。發現一個是A調用的是RetryableFeignLoadBalancer中的execute方法 而B調用的是FeignLoadBalancer 中的execute方法。
最後發現參數中的時間controlTime字段在兩個方法中顯示有點不一樣,然後就想到估計是兩個類中對 參數的時間類型處理有點不同。(這裡到底為什麼同樣的用戶端調用 服務端代碼 會走兩個不同的LoadBalancer,還在繼續研究中)。
解決辦法:最終解決是給時間字段加上 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//控制指令下發時間
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date controlTime;
總結:這種400錯誤有時候需要注意字段的類型