Java 编写控制器的正确方法

Java 编写控制器的正确方法,java,spring,spring-mvc,controller,Java,Spring,Spring Mvc,Controller,我想知道基于服务结果在控制器中构建消息到前端的最佳方法是什么。我考虑在java/spring环境中使用rest控制器,但它也反映了MVC模型。很明显,我在互联网上看到的例子很容易理解在现实世界应用程序中什么是最佳实践。 因此,对于这种情况,让我们假设以下场景: 我们有一个控制器CalculateController和一个方法doMath(intA,intB) 我们有一个服务计算器服务,它在doMath(inta,intb)方法中自己执行数学运算 我们希望对输入参数执行附加验证。该方法称为vali

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

  • 我们有一个控制器CalculateController和一个方法doMath(intA,intB)
  • 我们有一个服务计算器服务,它在doMath(inta,intb)方法中自己执行数学运算
  • 我们希望对输入参数执行附加验证。该方法称为validateInput(inta,intb)
  • 我们想发送一个响应计算结果,或一个特定的信息,说明它失败的原因

  • 那么现在的问题是:

  • 作为控制器方法执行的结果,我将重新生成一个对象映射,该映射将被解析为JSON。可能的实体包括:

    { “结果”:“12” }

    { “错误代码”:“参数不正确” }

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

  • validateInput方法应该放在哪里、控制器中还是服务中
  • 在validateInput方法中,我想检查两个简化的条件
  • a) 是a b) 是a*a==b,然后用消息通知用户“a的平方不能等于b”

    我应该如何根据结果提供附加消息? 我可以想出两种解决办法:

    • 返回映射,在验证结果为正的情况下,返回结果为真,在验证结果为负的情况下返回结果为假,返回带有相应消息的错误代码
    • 返回指示验证结果的布尔值,并对负结果使用异常。(奖金问题,在这种情况下,是否应检查或取消检查异常?)

    • 对于服务方法,它应该以相同的方式处理吗

    关于您的问题2和3,您可能需要查看验证程序界面:

    这篇文章展示了如何使用:

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


    另外,在我看来,在这种情况下,您不应该使用HTTP故障代码,因为用户输入错误实际上不是一个错误,而是应用程序中的一个正常用例。

    关于问题2和3,您可能希望查看验证程序界面:

    这篇文章展示了如何使用:

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


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

    Spring支持自定义验证。有一个批注
    @Valid
    。您可以将其添加到控制器中的参数之前。我将在示例中显示它。首先,使用实现验证器接口创建类:

    @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.
        }
    }
    
    并添加此方法和注释,以显示spring应该验证的表单。注释中的名称是控制器方法中参数的名称

    @InitBinder("request")
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(routeValidator);
    }
    
    让我们关注控制器方法。我们在这里用@Valid注释了参数。Spring将从您已经实现的类中调用validate方法。必须有第二个参数:
    绑定结果

    @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.
            }  
    

    另外,spring中还有另一个有趣的工具。它是注释
    @ExceptionHandler
    。使用此注释,您可以将从控制器或服务引发的异常映射到http请求。阅读有关此主题的更多信息

    Spring支持自定义验证。有一个批注
    @Valid
    。您可以将其添加到控制器中的参数之前。我将在示例中显示它。首先,使用实现验证器接口创建类:

    @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.
        }
    }
    
    并添加此方法和注释,以显示spring应该验证的表单。注释中的名称是控制器方法中参数的名称

    @InitBinder("request")
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(routeValidator);
    }
    
    让我们关注控制器方法。我们在这里用@Valid注释了参数。Spring将从您已经实现的类中调用validate方法。必须有第二个参数:
    绑定结果

    @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.
            }  
    

    另外,spring中还有另一个有趣的工具。它是注释
    @ExceptionHandler
    。使用此注释,您可以将从控制器或服务引发的异常映射到http请求。阅读有关此主题的更多信息

    这非常有用,谢谢!特别是exceptionHandler,从我所读到的,我相信人们甚至可以创建本地化的响应作为响应。这真的很有帮助,谢谢!特别是exceptionHandler,从我所读到的,我相信人们甚至可以创建本地化的响应作为响应。