【问题标题】:Handle empty RequestBody in Spring在 Spring 中处理空的 RequestBody
【发布时间】:2019-06-04 01:32:09
【问题描述】:

我目前正在使用 Spring Boot 开发应用程序,并且我有一个 API 端点(带有 @RequestBody 的 POST 方法),它根据请求参数执行不同类型的操作。 例如,如果我收到这样的对象:

{
"field1":["value1"],
"field2":["value2"]
}

我需要根据field1field2做一些转换。所以,当我发送这样的对象时:

{}

Jackson 将 JSON obj 转换为我的模型,但是因为这个 obj 是空的,所以模型设置中的所有字段都为 null。 那么,Spring 是否包含一些避免这种情况的方法?

这样做:

if(allFieldsAreEmpty(requestObj)){
 throw new RuntimeException("All fields are empty.");    
 }

附: Swagger 生成的模型类,我无法修改。

【问题讨论】:

  • 你是如何定义你的端点的?
  • 看看这个tutorial。首先使用@Valid 进行验证(最好在您的模型上使用@NotNull 之类的注释),然后使用BindingResult 查看错误。请注意,您也可以写您的own validating annotations
  • 可以使用bean验证。您可以在 bean 中注释您的必填字段并使用 @Valid spring 注释。此外,swagger 允许您指示应该需要哪个字段
  • 我无法更改模型对象,我只能以某种方式验证请求对象。
  • 那么,您当然需要关注@Adam 的评论。

标签: java spring spring-boot spring-mvc jackson


【解决方案1】:

您可以根据您想要执行的模型和验证来实现“org.springframework.validation.Validator”。您可以在控制器中使用 InitBinder 来验证请求对象。下面是我使用我的一个项目的一个例子:

@Component(value = "fromToDateValidator")
public class FromToDateValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return (InventorySearchRequestByDate.class.equals(clazz) || OrderRequestDetails.class.equals(clazz));
    }

    @Override
    public void validate(Object target, Errors errors) {
        if (!errors.hasErrors()) {
            Date fromDate = null;
            Date toDate = null;
            if (target instanceof InventorySearchRequestByDate) {
                fromDate = ((InventorySearchRequestByDate) target).getFromDate();
                toDate = ((InventorySearchRequestByDate) target).getToDate();
            } else if (target instanceof OrderRequestDetails) {
                fromDate = ((OrderRequestDetails) target).getFromDate();
                toDate = ((OrderRequestDetails) target).getToDate();
            }
            if (fromDate.compareTo(toDate) > 0) {
                errors.rejectValue("toDate", null, "To Date is prior to From Date");
            }
        }
    }
}

所以,支持方法取类参数,检查类验证是否适用于模型。所以就像在我的示例中,我必须检查 InventorySearchRequestByDate 请求对象或 OrderRequestDetails 请求对象,所以我根据日期执行了检查。

现在在 validate 方法中包含用于验证模型和添加错误的核心逻辑。

你可以像下面这样在你的控制器中绑定这个验证器并使用它:

@RestController
public class ItemInventoryController extends BaseController {

    @Autowired
    @Qualifier("fromToDateValidator")
    private Validator fromToDateValidator;

    @Autowired
    private ItemInventoryService itemInventoryService;

    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.addValidators(fromToDateValidator);
    }

    @RequestMapping(value = WebServiceEndPoints.INVENTORY_AVAILABILITY_BY_DATE, method = RequestMethod.POST)
    public Map<String, Set<ItemDetails>> getAvailableItems(@RequestBody @Validated InventorySearchRequestByDate
                                                       inventorySearchRequestByDate, BindingResult bindingResult) throws InvalidFieldException {
        validRequest(bindingResult);
        return itemInventoryService.searchItemsByDateAvailablity(inventorySearchRequestByDate.getFromDate()
                , inventorySearchRequestByDate.getToDate());
    }

    public void validRequest(BindingResult bindingResult) throws InvalidFieldException {
        if (bindingResult.hasErrors()) {
            throw new InvalidFieldException(bindingResult.getFieldErrors());
        }
    }

}

所以上面的代码会根据你的全局处理程序验证模型并抛出异常体。

【讨论】:

  • 非常有趣的方法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 2016-03-09
  • 2018-10-07
  • 2019-02-21
  • 2011-08-13
  • 2017-08-22
相关资源
最近更新 更多