2013-07-29 53 views
1

是否存在可以從服務(或其他非Controller方法)引發的異常或其他內容,這些異常或異常會中斷當前響應處理並向用戶返回404?服務是否可以返回404響應?

在Django的世界中,有get_object_or_404,它引發了一個Http404異常,它具有這種效果。我在寫服務;如果該服務確定所請求的對象對用戶不可訪問(在這種情況下,它尚未發佈),我希望它觸發一個404並停止剩餘的執行。目標是控制器呼叫該服務是DRY,並不總是重複def obj = someService.getSomething(); if (obj) {} else { render status: 404}呼叫。

摘要:
在Django中,我可以在任何時候提出一個Http404停止請求處理並返回一個404是否有一個相當於或一種從控制器做到這一點Grails中

+3

我不知道爲什麼你不想從控制器返回狀態代碼?我的意思是,自從我第一次開始使用Java/Groovy以來,我被教導說它是實現的正確方法(服務拋出異常,控制器捕獲並返回狀態碼)。服務不應該知道請求處理的任何內容,控制器也不知道任何有關業務邏輯的知識? –

回答

4

創建一個類com.my.ResourceNotFoundException的Exception類,然後從任何你想要的地方(控制器或服務)拋出它。

類似下面創建一個控制器:

class ErrorController { 

    def error404() { 
     response.status = HttpStatus.NOT_FOUND.value() 
     render([errors: [[message: "The resource you are looking for could not be found"]]] as JSON) 
    } 
} 

然後添加到您的UrlMappings.groovy配置文件,將處理該類型與此控制器動作異常的條目。指定「500」作爲模式意味着它將捕獲500個錯誤(如拋出的ResourceNotFoundException將導致的錯誤),並且如果異常匹配該類型,它將使用指定的控制器和操作。

"500"(controller: "error", action: "error404", exception: ResourceNotFoundException) 
3

在控制器中,您可以將響應的狀態設置爲您喜歡的任何代碼。

response.status = 404 

您還可以使用renderstatus - from the docs

// render with status code 
render(status: 503, text: 'Failed to update book ${b.id}') 

你可以有你的控制器,委託給服務調用服務的方法做到這一點之前,或者你可以有你的服務將狀態碼返回給控制器。

+1

我寧願建議使用'org.springframework.http.HttpStatus.NOT_FOUND.value'而不是404硬編碼。 – dmahapatro

+0

是的,這就是你如何在控制器內部做到這一點,但我的問題是如何不在控制器中做到這一點。即,從服務。我試圖幹掉,而不是在每個控制器中重複檢查並渲染404。 – smacintyre

0

@doelleri已經提到了可以爲渲染狀態代碼準確完成的工作。如下所示,您可以在控制器中實現DRYness的「不那麼groovier」方式。但是,如果您想將try catch塊移到實用程序中,您可以再實現一些功能。

//Custom Exception 
class CustomException extends Exception{ 
    Map errorMap 

    CustomeException(Map map, String message){ 
     super(message) 
     this.errorMap = map 
    } 
    .... 
} 

//service 
def getSomethingGood(){ 
    .... 
    .... 
    if(something bad happened){ 
     throw new CustomException([status: HttpStatus.NOT_FOUND.value, 
            message: "Something really got messed up"], 
            "This is a custom Exception") 
     //or just return back from here with bad status code 
     //and least required data 
    } 
    ...... 
    return goodObj 
} 

def getSomething(){ 
    def status = HttpStatus.OK.value 
    def message 
    try{ 
     def obj = getSomethingGood() 
     message = "success value from obj" 
     //or can also be anything got from obj etc 
    } catch(CustomException c){ 
     status = c.errorMap.status 
     message = c.errorMap.message 
    } 

    [status: status, message: message] 
} 

//controller 
def obj = someService.getSomething() 
render(status: obj.status, text: obj.message) 

另請注意,處理選中的異常時,事務不會在服務層中回滾。還有其他事情要做,我認爲這超出了這個問題的範圍。

+2

是的,我很想知道投票的理由。 :) – dmahapatro