【问题标题】:grails 3: is there a way to extract the duplicate boilerplate code in this API example?grails 3:有没有办法在这个 API 示例中提取重复的样板代码?
【发布时间】:2017-07-16 19:08:59
【问题描述】:

我们必须在 grails 3.3 Web 应用程序中实现大量 JSON API 调用。

不幸的是,每个方法的构建都是错误处理,目前我们在每个方法中复制这段代码,这是一个令人头疼的维护问题(如果我们改进错误处理,我们必须更新 70 多个方法)。有没有更好的方法来减少重复的错误代码?一些可以将错误检查代码提取到一个地方的模式?

仅供参考,我们使用超级简单有效的对象编组器以我们需要的方式呈现 json。不幸的是,render(){...} 模式忽略了对象编组器,所以在这种情况下我们需要使用 JSONBuilder。

正确的登录会给出这样的结果:

{"result":"0","user":{"username":"bob","userId":"123"},"accounts":[{"balance":"0.00","currencyIso":"USD","id":1}]}

错误如下所示:

{"result":"9999","message":"exception in xxx"}

我们有一长串结果代码(大约 70 个),因此客户端可以确切地知道错误是什么(我们不为此使用 HTTP 状态代码,因为它们根本不映射)

class LoginCommand implements grails.validation.Validateable {
    String username
    String password
    static constraints = {
        username    nullable:false, blank: false, size: 3..32
        password    nullable:false, blank: false, size: 3..32
    }

}

class UserApiController {
 def login(LoginCommand cmd) {
    try {
        if (cmd.hasErrors()) {
            log.error("invalid parameters")
            render(status: 400, contentType: 'application/json') {
                    result 10
                    message "errors in parameters"
            return
            }
        } else {
            User user = User.findByUsernameAndPassword(cmd.username, cmd.password)
            def userAccounts = Account.findAllByUser(user)

            if (user == null) {
                render(status: 404, contentType: 'application/json') {
                    result 100
                    message "could not find user with that username and pass"
                }
            } else {

                def builder = new JSONBuilder()
                def json = builder.build {
                    result= "0"
                    user= {
                      username=user.username
                      userId=user.id
                    }
                    accounts=playerAccounts
                }
                render(status: 200, contentType: 'application/json', text: json)                
            } // else all good
        } // else params ok

    } catch (Exception e) {
        log.error("Caught Exception in UserApiController.login()", e)
        render(status: 500, contentType: 'application/json') {
                result 9999
                message e.toString()
        }
    }
}

我们简要地查看了 json 视图,但我们认为这对我们没有帮助,增加了复杂性,并且由于我们的项目不是使用 rest-api 构建的,因此我们无权访问它。

【问题讨论】:

    标签: api grails3


    【解决方案1】:

    一些可能对您有所帮助的注意事项:

    • 如果您希望多个应用程序重复使用整个登录功能,请考虑创建一个 Grails 插件。插件是特定于 Grails 的 JAR 项目,它可以托管可重用的工件,例如控制器和服务。

    http://docs.grails.org/latest/guide/plugins.html

    • 您应该设置一个全局错误处理程序,而不是在整个控制器方法中执行通用try...catch()。请参阅:

    Exception handling in Grails controllers

    • 如果您需要 JSON 视图,您可以将其安装在现有应用程序上,即使该应用程序不是使用 REST 配置文件构建的。如果您想自定义输出,但您还希望分离控制器和视图之间的关注点,JSON 视图非常有用。

    http://views.grails.org/latest/#_installation

    • 对于这个特定的用例,您可能还想看看 Spring Security Grails 插件。

    https://plugins.grails.org/q/spring-security

    • 要清理控制器代码,请考虑将业务逻辑提取到服务方法中。您可以为输出创建标准化命令对象,也可以使用自定义 RuntimeException 子类型 (MyLoginFailureException) 来表示登录失败,并返回原因和结果代码。

    【讨论】:

      猜你喜欢
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      相关资源
      最近更新 更多