编写控制器的正确方法

时间:2016-08-26 17:20:10

标签: java spring spring-mvc controller

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

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

    1. 作为控制器方法执行的结果,我将重新调整一个对象Map,它将被解析为JSON。可能的实体是:

      {     “结果”: “12”  }

      {     “errorCode”:“参数不正确”  }

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

      1. 应该在控制器中还是在服务中放置validateInput方法?
      2. 在validateInput方法中,我想检查两个简化条件
      3. a)是< b然后通知消息“a不能小于b”

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

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

        • 返回Map,如果是肯定的验证结果,则result = true,如果是否定结果,则result = false,errorCode及相应的消息
        • 返回表示验证结果的布尔值,另外还使用负面结果的例外。 (奖金问题,在这种情况下应该检查或取消选中例外吗?)

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

2 个答案:

答案 0 :(得分: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失败代码,因为用户输入错误实际上不是错误,而是应用程序中的正常用例。

答案 1 :(得分:1)

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;

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

@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