2016-08-01 47 views
0

我有一個場景,我需要在每個Web請求的開始運行幾個數據庫檢查,並在成功的情況下,我需要存儲對象以供使用稍後在控制器的請求中,或者在失敗的情況下,我需要呈現錯誤頁面。春季開機 - 運行檢查每個請求和存儲對象的生命週期

一個非常類似的現實世界的例子是一個SaaS應用程序檢查和加載基於虛榮URL的帳戶,然後存儲供控制器使用的帳戶以避免多個數據庫請求。

在Spring啓動應用程序中實現此目的的最佳方法是什麼?我已經嘗試使用過濾器,但我認爲攔截器可能會更好地完成任務,包括運行檢查,但是如何存儲對象以備後用?是否存在某種我可以存儲的請求生命週期上下文?

回答

1

以我的經驗,我做過類似工作的最好方法是通過HandlerMethodArgumentResolver

基本上可以想象你有一個自定義類型,我們稱之爲UserContext,其中存儲了請求所需的信息。假設你有一個UserContextService,假設它有一個方法getUserContext(HttServletRequest),用於根據請求檢索上下文,從中可以根據任何請求參數/頭/路徑變量等來調用數據庫。您可以改進如你所需。但是,在此基礎上簡單的假設,你可以有一個控制器,它看起來像這樣:

@RequestMapping("/some/url") 
public SomeResponse someMethod(UserContext userContext, ...) { 
    //do something here with UserContext 
} 

Spring框架將注入這個的UserContext到您的控制器將與自定義HandlerMethodArgumentResolver這樣的方式:

@Component 
public class UserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { 

    @Autowired 
    UserContextService 

    @Override 
    public boolean supportsParameter(MethodParameter parameter) { 
     return parameter.getParameterType().equals(UserContext.class); 
    } 

    @Override 
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 
     HttpServletRequest req = (HttpServletRequest)webRequest.getNativeRequest(); 
     UserContext userContext = userContextService.getUserContext(req); 
     if (userContext != null) { 
      return userContext; 
     } else { 
      return WebArgumentResolver.UNRESOLVED; 
      //Or throw exception 
     } 
    } 
} 

您將通過覆蓋您的WebMvcConfigurer bean/config-class中的WebMvcConfigurer.addArgumentResolvers方法進行註冊。

這個機制是通過@PathVariable@RequestParam等使用相同的...

+0

感謝您的建議,我有點反對儘管我承認這可能最終會更具表現力和可測試性......我採取的方法是將其存儲在請求bean中,並將輔助方法添加到我的基本控制器,其中所有其他控制器都從其繼承。 – matthewrk

+0

它只會發生在需要發生的地方(即聲明參數的地方),就像任何其他url參數或路徑變量一樣,加上Spring已經充滿了注入和反射。你的解決方案似乎沒問題,雖然有一些耦合和鍋爐板可以通過這種方法避免。 – Ulises