1

最初的问题

如果您有不同的方法,基本上只有一行不同,是否有一种方法可以通过创建一种方法使其干燥。

例子:

def showA( ) {
   def instance

    try {
        instance = A.findById( params.id )
    } catch ( Exception e ) {
        def message = "Error while retrieving details for the given id ${ params.id }, $e"
        log.error message
        responseAsJson( 400, "Invalid id", message )
        return false
    }

    return checkAndRender(instance,  params.id);
}

def showB( ) {

       def instance

        try {
            instance = B.findByBId( params.BId )
        } catch ( Exception e ) {
            def message = "Error while retrieving details for the given id ${ params.id }, $e"
            log.error message
            responseAsJson( 400, "Invalid id", message )
            return false
        }

        return checkAndRender(instance,  params.id);
    }

那么,是否有一种方法可以制作一个方法并简单地作为参数传递:

  • 领域类
  • 要搜索的 ID

还是改为传递 SQL 语句会更好?

更新

根据@dmahapatro 评论,我提出以下建议:

def showA( ) {
        def clos = {id -> A.findByAId( id ) }
        return findAndShow(clos, params.AId, params )
    }

def showB( ) {
        def clos = {id -> B.findByBId( id ) }
        return findAndShow(clos, params.BId, params )
    }

 def findAndShow(Closure closure, def id, def p)
    {
        def instance
        try {
            instance = closure(id)
        }
        catch ( Exception e ) {
            def message = "Error while retrieving instance details for the given id ${ id }, $e"
            log.error message
            responseAsJson( 400, "Invalid Id", message )
            return false
        }

        return checkAndRender(instance,  id);
    }

剩下的问题只有:

  • 如何进一步清理/使其更清洁。
  • 如何绕过警告:

    [ApiController] 中的 [findAndShow] 操作接受 [groovy.lang.Closure] 类型的参数。不支持接口类型和抽象类类型作为命令对象。该参数将被忽略。

       def findAndShow(Closure closure, def id, def p)
    
4

1 回答 1

1

如果你想要一个 DRY 代码,你应该担心的第一件事是定义更好的异常处理。尝试在任何地方捕获您的代码以处理对客户端的响应并不是很干燥,如果您将数据访问代码放在服务中,您可以从它们中抛出异常并使用全局控制器来捕获错误并处理响应。例如:

class ErrorController {

    def serverError() {
         if (request.format == 'json') {
            //Code for handling errors in json request, request.exception stores the data about the exception. 
        } else {
            //Code for handling errors in non-json request, e.g:
            render(view: 'error', model: [msg: 'Something went wrong']) //add an error view for this
        }
    }
}

如果您愿意,还可以为其他类型的错误(403、404 等)添加处理程序

添加到 UrlMappings.groovy

    "500"(controller: "error", action: "serverError")

现在您可以使用新的错误处理和反射重构代码:

控制器:

   class MyController {

        def myService

        def show() {
            def result = myService.myFind(params.className,params.id)
            render result as JSON //Render stuff
        }
    }

服务:

       import grails.util.Holders

       class MyService {

            def myFind(String className, Long id) {
                def result = Holders.getGrailsApplication().getDomainClass('com.mypack.'+ className).findById(id)
                if(!result) {
                    throw new ServiceException('really descriptive and usefull error msg')
                }
            }
        }

我定义了一个 ServiceException 类,因此我可以使用 instanceOf 运算符在我的 ErrorController 中为其添加自定义逻辑。

于 2014-12-03T18:07:25.630 回答