天天看點

feign.FeignException$BadRequest: status 400 reading 詭異錯誤記錄

詭異事情描述: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錯誤有時候需要注意字段的類型