Java 如果我使用@ControllerAdvice来填充@ModelAttribute,是否会产生任何来自@ControllerAdvice的冲突
这是web入口点的主控制器Java 如果我使用@ControllerAdvice来填充@ModelAttribute,是否会产生任何来自@ControllerAdvice的冲突,java,spring,spring-mvc,spring-boot,spring-data,Java,Spring,Spring Mvc,Spring Boot,Spring Data,这是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: "+my
@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";
}
}
现在,如果您查看拦截器,您可以看到我是如何创建@modeldattribute的,并可以看到实现
@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注册,因为它已使用@Component
注释注册到Spring IoC容器中:
@Bean
@RequestScope
public HWRequest hwRequest() {
return new HWRequest();
}
AppConfig中不需要的另一项功能是自动连接UserSessionInterceptor
bean并将其再次注册为bean。删除那个。由于该bean正在自动连接,它显然已经在IoC容器中,所以无需再次注册它
另一个令人困惑的问题是命名中的workdsession
。当您处理的是@RequestScope
而不是@SessionScope
时,我建议将类的命名更改为request
(例如RequestInterceptor
)。会话和请求是非常不同的
否则它看起来可以工作,并且应该是线程安全的 谢谢你的评论。我添加了一个编辑,并根据我在文档中读到的内容和我找到的几个示例提出了解决方案。你觉得这可行吗?再次感谢。对于意外的否决票,非常抱歉,出于某种原因,它不会让我更改它。NP,它应该允许您在编辑我的答案后重新查看您的否决票。