2015-09-24 26 views
1

在春天,我有一個端點的控制,像這樣:春讀取請求時身中兩刀

@RequestMapping(method = RequestMethod.POST) 
@ResponseStatus(HttpStatus.CREATED) 
@ResponseBody 
public OutputStuff createStuff(@RequestBody Stuff stuff) { 
    //my logic here 
} 

如果這樣做對這個端點的POST,在請求主體的JSON會自動反序列化到我的模型( Stuff)。問題是,我剛剛獲得了登錄原始JSON的要求,因爲它正在進入!我嘗試了不同的方法。

  1. 進樣HttpServletRequestcreateStuff,看身體有和日誌:

代碼:

@RequestMapping(method = RequestMethod.POST) 
@ResponseStatus(HttpStatus.CREATED) 
@ResponseBody 
public OutputStuff createStuff(@RequestBody Stuff stuff, HttpServletRequest req) { 
    StringBuilder sb = new StringBuilder(); 
    req.getReader().getLines().forEach(line -> { 
     sb.append(line); 
    }); 
    //log sb.toString(); 
    //my logic here 
} 

這樣做的問題是,到時候我執行此,讀者的InputStream會已經被執行以將JSON反序列化爲Stuff。所以我會得到一個錯誤,因爲我無法兩次讀取相同的輸入流。

  1. 使用自定義HandlerInterceptorAdapter可以在調用實際處理程序之前記錄原始JSON。

代碼(一部分):

public class RawRequestLoggerInterceptor extends HandlerInterceptorAdapter { 

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 
     StringBuilder sb = new StringBuilder(); 
     req.getReader().getLines().forEach(line -> { 
      sb.append(line); 
     }); 
     //log sb.toString(); 

     return true; 
    } 
} 

本壽的問題是,通過反序列化到stuff發生的時間,從請求中的InputStream本來已經閱讀!所以我會再次遇到異常。

  • 另一種選擇我考慮過,但還沒有實現,會以某種方式強迫Spring使用我的HttpServletRequest自定義實現,將緩存輸入流,並允許它的多個讀取。我不知道這是否可行,我找不到任何文檔或例子!

  • 另一種選擇是不是我的終點閱讀Stuff,而是讀取請求身體String,記錄它,然後使用ObjectMapper或類似的東西,它反序列化Stuff。我不喜歡這個想法。

  • 有沒有更好的解決方案,我沒有提及和/或我不知道?我會很感激幫助。我正在使用SpringBoot的最新版本。

    回答

    3

    在本文中引用:How to Log HttpRequest and HttpResponse in a file?,spring提供了可用於記錄請求的AbstractRequestLoggingFilter。

    AbstractRequestLoggingFilter API文檔,found here

    +0

    謝謝,這看起來很有希望,我給它一個去! –

    +0

    它工作嗎?:-) – Nate

    +0

    是的,我們確實使用Logging Filter,謝謝:) –