【问题标题】:Best practice to send Json response from Spring controller methods从 Spring 控制器方法发送 Json 响应的最佳实践
【发布时间】:2017-11-22 18:14:31
【问题描述】:

我想从 spring 控制器返回一个字符串(json 字符串)作为对它接收到的 AJAX 调用的响应,根据我是否提交了 @Valid 表单,响应可能会有所不同。这就是我处理它的方式,并想知道这是否被认为是最佳实践? 请注意我正在使用@RestController,所以@ResonseBody 应用所有方法。

    @RequestMapping(value = "/save" , method = RequestMethod.POST)
public String saveScheduledAlert(@Valid ScheduledAlertForm scheduledAlertForm, BindingResult bindingResult) {
    StringBuilder jsonString = new StringBuilder();
    if(bindingResult.hasErrors()){
        jsonString.append("{\"success\" : \"false\"");
        for(ObjectError error : bindingResult.getAllErrors())
            jsonString.append(",\"").append(((FieldError) error).getField()).append("\":\"").append(error.getDefaultMessage()).append("\"");
    } else {
        //save the data
        jsonString.append("{\"success\" : \"true\"");
    }

    jsonString.append("}");
    return jsonString.toString();


}

【问题讨论】:

标签: java json spring-mvc


【解决方案1】:

老问题,但对于其他需要帮助的人,我为此使用了自定义 ApiResponse 类。我的班级是这样的:

public class ApiResponse<T> {
    String message;
    int statusCode;
    T data

    //....getters and setters

这样,我可以使用“SUCCESS”或“ERROR”作为消息,适当的HttpStatus 代码,然后任何类型作为我要发送的数据。

然后,在控制器中,我只是这样做:

@PostMapping("/sign-up")
public ResponseEntity<String> signUp(@RequestBody Account account) {
  
  if (accountService.getAccountByEmail(account.getEmail()) != null) {
      ApiResponse<String> apiResponse = new ApiResponse<>("A user with that email  
          already exist", HttpStatus.CONFLICT.value(), null);
         return new ResponseEntity<String>(new Gson().toJson(apiResponse), HttpStatus.CONFLICT);
  }

 // ... rest of controller code 

如您所见,我使用 Gson 依赖项来创建我的 JSON 字符串。

【讨论】:

    【解决方案2】:

    所以基本上你想要做的是生成 2 个 pojos

    public class RestWrapperDTO {
        protected boolean success;
        public boolean isSuccess() {
            return success;
        }
        public void setSuccess(boolean value) {
            success = value
        }
    }
    

    还有另一个错误 DTO

    public class RestErrorDTO extends RestWrapperDTO {
        private Map<String, String> errors;
    
        public Map<String, String> getErrors() {
            return errors;
        }
        public void setErrors(Map<String, String> value) {
            errors = value
        }
    }
    

    和你的控制器

    @RequestMapping(value = "/save" , method = RequestMethod.POST)
    public RestWrapperDTO saveScheduledAlert(@Valid ScheduledAlertForm scheduledAlertForm, BindingResult bindingResult) {
        StringBuilder jsonString = new StringBuilder();
    
        if(bindingResult.hasErrors()){
            RestErrorDTO errorDTO = new RestErrorDTO();
            // fill map with errors here
            return errorDTO;
        } else {
            RestWrapperDTO wrapperDTO = new RestWrapperDTO();
            wrapperDTO.setSuccess(true);
            return wrapperDTO;
        }
    }
    

    这不是最充分的代码,但它应该可以帮助你:D

    如果你使用简单的@Controller 注解——你是什么 寻找的是@ResponseBody-annotation

    或者如果你使用@RestController 而不是它已经可用

    你可以简单地返回一个带有 Serializable 接口的对象——一个 简单的 POJO 和 spring 将处理其余部分。

    进一步阅读:

    【讨论】:

    • 我已经将 ResonseBody 应用于所有方法,因为我正在使用@RestController,此外,我想要做的只是返回成功:如果一切顺利,则返回 true 或发送成功:false,然后验证错误作为 json 中的键值对仅此而已。
    • 基本上我有解释和@nick savenia 代码示例
    • 我的建议,
    • 我之前想过 return Object 但想知道如何发送成功 : false 消息以在客户端发现出现问题?
    • 谢谢,这是有道理的,但为什么我不应该只使用一个带有布尔标志和 Map 的类来处理错误呢?这还不够简单吗?
    【解决方案3】:

    创建一个 POJO,如下所示:

    public class SuccessPOJO{
    private String success;
    
    .....
    getters and setters
    .....
    }
    

    现在您可以设置成功消息的值并返回此SuccessPOJO 对象。在浏览器中,您将收到带有成功消息的JSON 格式化对象!

    【讨论】:

    • 是的,但我也想发送数量可变的验证错误,我该如何发送?
    猜你喜欢
    • 2015-10-19
    • 2020-09-30
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多