2017-08-11 77 views
1

我一直在開發使用spring引導的rest api服務。 這是我的休息控制器日誌http請求正文,如果發生異常

@RequestMapping(value = "owner/login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8") 
    @ResponseBody 
    public ResponseEntity<String> login(@RequestBody Owner owner) throws TimeoutException, SocketTimeoutException, SocketException { 
     controller.login(owner); 
     return ResponseEntity.ok("\"error\": 0"); 
    } 

這是控制器

public JsonObject login(Owner loginOwner){ 
     Map<String,String> params = new HashMap<String,String>(); 
     params.put("email", loginOwner.getEmail()); 
     params.put("password", loginOwner.getPassword()); 
     if(GMoikaStringUtils.isEmpty(loginOwner.getEmail()) || !GMoikaStringUtils.isValidEmail(loginOwner.getEmail())){ 
      throw new InvalidUserInputException("Wrong email format", CLASS_NAME, "login", params, "owners/owner/login POST"); 
     } 
     else{ 
      someLogic... 
     } 
    } 

是,採用這種結構我應該創建地圖的每個method.How內PARAMS避免每次方法內部地圖的創建中的問題並把所有參數放入這張地圖?如果發生異常,我需要「MAP」在日誌中顯示參數。 也許春季引導可以做到這一點,但我無法在官方文檔中找到我的案例。在此先感謝

回答

0

如果你只想要一個InvalidUserInputException拋出之後,要做到這一點,你可以寫一個異常處理程序:

@ExceptionHandler(InvalidUserInputException.class) 
@ResponseBody 
public ValidationError getError(InvalidUserInputException ex) { 
    // ... 
} 

由於InvalidUserInputException是一個自定義異常,您可以添加一個類型爲Object的字段,您可以在其中傳遞請求正文,例如:

throw new InvalidUserInputException("Wrong email format", loginOwner); 

現在您可以使用Owner對象的toString()方法來記錄它。如果你想獲得它在一個JSON風格,你可以使用Apache commons及其ToStringBuilder

@Override 
public String toString() { 
    return new ToStringBuilder(this, ToStringStyle.JSON_STYLE) 
     .append("email", email) 
     .append("password", password) 
     .toString(); 
} 

另外,如果你不希望依賴於使用的toString()方法,只是想要回簡單的請求正文,您還可以將HttpServletRequest作爲參數添加到異常處理程序。

在你這樣做之前,你必須包裝它,因爲請求主體只能被讀取一次,爲了克服這個問題,你應該在讀取請求主體後「緩存」它。要做到這一點,你可以使用Spring的ContentCachingRequestWrapper

要包裝它,你應該寫你自己的Filter。您可以通過從春天他們OncePerRequestFilter延長這樣做:

ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; 
wrapper.getContentAsByteArray(); 

@Component 
public class RequestWrapperFilter extends OncePerRequestFilter { 

    @Override 
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { 
     filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse); 
    } 
} 

現在,您可以通過調用getContentAsByteArray()方法得到的異常處理程序請求主體。要獲取請求主體爲字符串,您可以使用IOUtils從Apache的百科全書:

ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; 
logger.warn("Input validation failed, request body: {}", IOUtils.toString(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding())); 

這將記錄整個請求主體爲一個字符串。儘管如此,請注意記錄敏感信息。

1

您可以使用任何記錄器,像Log4j的並登錄其他聲明:

遵循的步驟:
1.下載最新的log4j發行。
2.將log4j的jar庫添加到程序的類路徑中。
3.創建log4j的配置。
4.用配置初始化log4j。
5.創建一個記錄器。
6.將日誌記錄放入代碼中。

Logger logger = Logger.getLogger(MyClass.class); 

public JsonObject login(Owner loginOwner){ 
    Map<String,String> params = new HashMap<String,String>(); 
    params.put("email", loginOwner.getEmail()); 
    params.put("password", loginOwner.getPassword()); 
    if(GMoikaStringUtils.isEmpty(loginOwner.getEmail()) || !GMoikaStringUtils.isValidEmail(loginOwner.getEmail())){ 
     throw new InvalidUserInputException("Wrong email format", CLASS_NAME, "login", params, "owners/owner/login POST"); 
    } 
    else{ 
     logger.info("Log this event"); 
    } 
} 

參考這裏:http://www.codejava.net/coding/how-to-configure-log4j-as-logging-mechanism-in-java

+0

感謝您的迴應,但這不是我要找的。在我的情況下,當我拋出InvalidUserInputException(這是我的自定義異常)我登錄MAP內的MAP,以顯示前端哪個params無效。我正在尋找結構,將所有參數替換我的地圖到更舒適的形式 –

+0

@АлмасАбдразак你在這裏重溫什麼「我登錄MAP內的參數」 –

+0

是的。記錄並顯示來自請求正文的參數 –