【问题标题】:Alternative response spring boot api rest替代响应spring boot api rest
【发布时间】:2020-02-24 03:20:48
【问题描述】:

我是 REST API 和 Spring Boot 的初学者。我对如何处理请求可能具有的不同响应有疑问。例如,如果我发布信用卡数据

{
    "number": "3434 3434 3434 3434",
    "date_expiration": "09-19",
    "identification_card": 23232323
}

然后在@RestController

@PostMapping("/card")
public ResponseEntity<CreditCard> payCard(@Valid @RequestBody CreditCard creditCard){
      CreditCard creC = cardService.registerCard(creditCard);
      return new ResponseEntity<>(creC, HttpStatus.OK);    
}

在这种情况下,我返回一个 ResponseEntity 对象。 如果date_expiration 已过期或identification_card 与客户端不对应会怎样?它们是在服务中解析的逻辑验证,可以触发不同的响应。我应该如何处理它们?

【问题讨论】:

    标签: java rest api spring-boot


    【解决方案1】:

    在这里,您使用与请求正文和响应正文相同的对象。这不是标准做法。

    您应该有单独的请求/响应对象。在请求对象中,您应该只从用户那里获得您需要的信息。但是在响应对象中,您应该有您想要在响应中发送的信息以及验证信息,例如错误详细信息,其中包括错误代码和错误描述,您可以使用这些信息向用户显示验证错误。

    希望这会有所帮助。

    【讨论】:

    • 谢谢!我明白你的意思了。我知道 api rest 只消耗和产生 json,所以如果在另一边我有 Angular 作为前端,我应该使用什么类型的对象来响应?是否建议只返回一个 ResponseEntity?如果根据特定条件,返回对象的类型发生变化会怎样?再次感谢您的指导
    • 没有。我不建议在这里使用ResponseEntity&lt;String&gt;。我建议使用一个名为 CreditCardResponse 的新 pojo 对象并在该对象中定义一个属性,该属性将包含验证详细信息以及您的响应。因此,您可以在前端使用该对象并查看该对象是否包含验证错误。如果它包含验证错误,则将其显示给您的前端。
    • 完美!现在我更准确地理解了它应该如何工作。谢谢!
    • 太棒了。如果有帮助,请点赞我的回答。谢谢。
    【解决方案2】:

    好吧,如果date_expiration 已过期或identification_card 对客户不满意,这就是业务失败。

    我喜欢用HTTP 422 - Unprocessable Entity 表示业务错误。见here

    如果您想在控制器中返回不同的对象,您可以将返回对象从ResponseEntity&lt;CreditCard&gt; 更改为ResponseEntity&lt;Object&gt;,尽管如果目的是返回,我更喜欢在ControllerAdvice 注释方法中使用ExceptionHandler错误。

    正如我所说,这种情况是业务失败(信用卡已过期或对当前用户不起作用)。

    这是一个例子。会是这样的:

    CardService.java

    @Service
    public class CardService {
    
        // ..
    
        public CreditCard registerCard(CreditCard card) throws BusinessException {
            if(cardDoesntBehaveToUser(card, currentUser()))) // you have to get the current user
                throw new BusinessException("This card doesn't behave to the current user");
    
            if(isExpired(card)) // you have to do this logic. this is just an example
                throw new BusinessException("The card is expired");
    
            return cardRepository.save(card);
        }
    
    }
    

    CardController.java

    @PostMapping("/card")
    public ResponseEntity<Object> payCard(@Valid@RequestBody CreditCard creditCard) throws BusinessException {
        CreditCard creC = cardService.registerCard(creditCard);
        return ResponseEntity.ok(creC);
    }
    

    BusinessException.java

    public class BusinessException extends Exception {
    
        private BusinessError error;
    
        public BusinessError(String reason) {
            this.error = new BusinessError(reason, new Date());
        }
    
        // getters and setters..
    }
    

    BusinessError.java

    public class BusinessError {
    
        private Date timestamp
        private String reason;
    
        public BusinessError(String Reason, Date timestamp) {
            this.timestamp = timestamp;
            this.reason = reason;
        }
    
        // getters and setters..
    }
    

    MyExceptionHandler.java

    @ControllerAdvice
    public class MyExceptionHandler extends ResponseEntityExceptionHandler {
    
        // .. other handlers..
    
        @ExceptionHandler({ BusinessException.class })
        public ResponseEntity<Object> handleBusinessException(BusinessException ex) {
            return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(ex.getError());
        }
    
    }
    

    如果信用卡过期,JSON会呈现为:

    {
      "timestamp": "2019-10-29T00:00:00+00:00",
      "reason": "The card is expired"
    }
    

    【讨论】:

    • 谢谢!这很好地补充了日本的回应。我喜欢ControllerAdvise的方法,我以为它只用于nullpointer之类的异常,但我发现它可以用于这些情况
    猜你喜欢
    • 2022-01-23
    • 2021-08-06
    • 1970-01-01
    • 2020-11-09
    • 2018-02-23
    • 2015-11-09
    • 2022-02-03
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多