【问题标题】:Proper way to write a controller编写控制器的正确方法
【发布时间】:2017-01-03 10:34:20
【问题描述】:

我想知道根据服务结果在控制器中构建消息到前端的最佳方法是什么。我正在考虑使用 rest 控制器在 java/spring 上下文中,但它也反映了 MVC 模型。显然,我在互联网上看到的示例很容易理解实际应用中的最佳实践。 因此,对于这种情况,我们假设以下情况:

  1. 我们有一个带有单个方法 doMath(int a, int b) 的控制器 CalculateController
  2. 我们有一个服务 CalculatorService,它在 doMath(int a, int b) 方法中自行执行数学运算。
  3. 我们希望对输入参数执行额外的验证。该方法称为 validateInput(int a, int b)。
  4. 我们希望将计算结果或特定信息作为响应发送失败原因。

那么现在的问题:

  1. 作为控制器方法执行的结果,我将返回一个对象映射,该映射将被解析为 JSON。可能的实体是:

    { “结果”:“12” }

    { "errorCode":"参数不正确" }

这是正确的,还是我应该针对不同的错误处理? 我知道我可以另外使用 http 错误代码,例如 400 或 406 来指示输入参数不正确,但我个人不喜欢使用 http 错误代码来指示应用程序逻辑结果。 (我认为输入验证是应用逻辑)

  1. validateInput 方法应该放置在控制器中还是服务中?
  2. 在 validateInput 方法中我想检查两个简化条件

a) 是 a

b) 是 a*a == b,然后通过消息“a 平方不能等于 b”通知用户。

我应该如何根据结果提供附加消息? 我可以想到两个解决方案:

  • 返回Map,如果是肯定的验证结果有result = true,如果是否定的结果result = false,errorCode和相应的消息
  • 返回指示验证结果的布尔值,并另外使用异常来表示否定结果。 (额外的问题,在这种情况下应该检查还是不检查异常?)

    1. 对于服务方法是否应该以同样的方式处理?

【问题讨论】:

    标签: java spring spring-mvc controller


    【解决方案1】:

    关于您的问题 2 和 3,您可能需要查看 Validator 界面: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html

    这篇文章展示了如何使用:Spring MVC: How to perform validation?

    对于问题 1,您可以将 BindingResult 中的错误转换为 JSON,并在客户端使用它来向用户执行有用的反馈。

    另外,在我看来,您不应该在这种情况下使用 HTTP 失败代码,因为用户输入错误并不是真正的错误,而是您的应用程序中的正常用例。

    【讨论】:

      【解决方案2】:

      Spring 支持自定义验证。有一个注解@Valid。您可以在 Controller 中的参数之前添加它。我将在示例中展示它。首先,创建一个实现Validator接口的类:

      @Component
      public class MathValidator implements Validator {
      
          @Override
          public boolean supports(Class<?> aClass) {
              return MatchRequest.class.equals(aClass);
          }
      
          @Override
          public void validate(Object o, Errors errors) {
              MatchRequest request = (MatchRequest) o;
      
              if (request.getValue() == null) {
                  errors.rejectValue("value", "Value cannot be empty");
              }
             //add another validation logic here.
          }
      }
      

      然后,在您的控制器中,您可以像这样注入您的验证器:

      @Autowired
      private MathValidator validator;
      

      并使用注释添加此方法,以显示 spring 它应该验证哪种形式。注解中的名称是控制器方法中参数的名称。

      @InitBinder("request")
      private void initBinder(WebDataBinder binder) {
          binder.setValidator(routeValidator);
      }
      

      让我们专注于控制器方法。我们在这里使用@Valid 注释的参数。 Spring 将从您已经实现的类中调用 validate 方法。必须有第二个参数:Binding result

      @RequestMapping(value = "/math", method = RequestMethod.POST)
              public ResponseEntity calculate(@RequestBody @Valid MatchRequest request, BindingResult result) {
                  if (result.hasErrors()) {
                      return new ResponseEntity(result.getAllErrors(), HttpStatus.BAD_GATEWAY);
                  }
      
                  //call service,etc.
              }  
      

      此外,春天还有另一个有趣的工具。这是注释@ExceptionHandler。使用此注解,您可以将异常、从控制器或服务中抛出的异常映射到 http 请求。阅读有关此主题的更多信息on the official website

      【讨论】:

      • 这真的很有帮助,谢谢!尤其是 exceptionHandler,从我读过的内容来看,我相信甚至可以创建本地化响应作为响应。
      猜你喜欢
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 2012-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多