[英]Will I have any collisions coming from the @ControllerAdvice if I use it to populate a @ModelAttribute
這是 web 入口點的主控制器
@Controller
@RequestMapping("/webapp")
public class WebAppController {
@RequestMapping(value = "/home/{authKey}",method = RequestMethod.GET)
String index(@ModelAttribute MyMeta myMeta, Model model){
System.out.println("Token: "+myMeta.getAccessToken());
return "index";
}
@RequestMapping(value = "/config/{authKey}",method = RequestMethod.GET)
String config(@ModelAttribute MyMeta myMeta, Model model){
return "configure";
}
}
現在,如果您查看攔截器,您可以看到我是如何創建@ModelAttribute 的,並查看實現
@Component
@ControllerAdvice
public class SessionInterceptor implements AsyncHandlerInterceptor {
MyMeta myMeta;
...
@ModelAttribute
public MyMeta getTest() {
return this.myMeta;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
...
// parse the key from the request
...
MetaMagicKey metaMagicKey = metaMagicKeyRepo.findKeyByMagicKey(key);
// do work here query my DB and build stuff
...
// assign the queried data built into object
this.myMeta = metaMagicKey.getId().getMyMeta();
return true;
}
我的問題是,我不知道 Springboot 的真正交互方式,所以我擔心如果執行此操作的人太多,我可能會發生一些對象交換或某種碰撞? 確實沒有一種干凈的方法可以做到這一點,我所做的所有研究都在使用 HttpServletRequest#setAttribute() 和使用 @ModelAttribute 之間徘徊,我喜歡上面選擇的路線,因為它很容易在我的方法中實現.
Springboot 1.4.2 - Java 8
我最終嘗試的是這個,基於我讀過的幾頁。
我創建了一個新組件:
@Component
@RequestScope
public class HWRequest implements Serializable {
private MyMeta myMeta;
public MyMeta getMyMeta() {
return myMeta;
}
public void setMyMeta(MyMeta myMeta) {
this.myMeta = myMeta;
}
}
然后我的配置類
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
UserSessionInterceptor userSessionInterceptor;
@Autowired
public AppConfig(UserSessionInterceptor userSessionInterceptor) {
this.userSessionInterceptor = userSessionInterceptor;
}
@Bean
@RequestScope
public HWRequest hwRequest() {
return new HWRequest();
}
@Bean
public UserSessionInterceptor createUserSessionInterceptor() {
return userSessionInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(createUserSessionInterceptor()).addPathPatterns("/user/**");
}
}
這是我修改的攔截器
@Component
@ControllerAdvice
public class SessionInterceptor implements AsyncHandlerInterceptor {
@Resource
HWRequest hwRequest;
...
@ModelAttribute
public HWRequest getTest() {
return this.hwRequest;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
...
// parse the key from the request
...
MetaMagicKey metaMagicKey = metaMagicKeyRepo.findKeyByMagicKey(key);
// do work here query my DB and build stuff
...
// assign the queried data built into object
this.hwRequest.setMyMeta(metaMagicKey.getId().getMyMeta());
return true;
}
當然還有適合我需要的修改過的控制器
@Controller
@RequestMapping("/user")
public class WebAppUserController {
@RequestMapping(value = "/home/{authKey}",method = RequestMethod.GET)
String index(@ModelAttribute HWRequest request, Model model){
return "index";
}
@RequestMapping(value = "/config/{authKey}",method = RequestMethod.GET)
String config(@ModelAttribute HWRequest request, Model model){
return "configure";
}
}
基於我讀過的所有文檔,這應該可以工作,但也許我錯過了一些東西,因為攔截器仍然是一個單身人士。 也許我錯過了什么?
myMeta
變量表示單例 bean 中的狀態。 當然它不是線程安全的,各種用戶都會發生沖突。 永遠不要將任何應用程序狀態存儲在單例 bean 中。
如果您想為每個請求存儲一些狀態,請使用 Spring 的請求范圍。 這意味着創建單獨的 bean 僅用於存儲用@RequestScope
注釋注釋的狀態
對編輯的反應:
這個 bean 注冊可以被刪除,因為它已經用@Component
注解注冊到 Spring IoC 容器中:
@Bean
@RequestScope
public HWRequest hwRequest() {
return new HWRequest();
}
AppConfig 中不需要的另一部分是自動裝配UserSessionInterceptor
bean 並將其再次注冊為 bean。 刪除那個。 由於該 bean 正在自動裝配,它顯然已經在 IoC 容器中,因此無需再次注冊它。
另一個令人困惑的部分是命名中的工作session
。 當您處理@RequestScope
而不是@SessionScope
我建議將您的類的命名更改為request
(例如RequestInterceptor
)。 Session 和 Request 是非常不同的野獸。
否則它看起來可以工作並且應該是線程安全的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.