Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果我使用@ControllerAdvice来填充@ModelAttribute,是否会产生任何来自@ControllerAdvice的冲突_Java_Spring_Spring Mvc_Spring Boot_Spring Data - Fatal编程技术网

Java 如果我使用@ControllerAdvice来填充@ModelAttribute,是否会产生任何来自@ControllerAdvice的冲突

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

这是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";
}
}
现在,如果您查看拦截器,您可以看到我是如何创建@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容器中,所以无需再次注册它

另一个令人困惑的问题是命名中的workd
session
。当您处理的是
@RequestScope
而不是
@SessionScope
时,我建议将类的命名更改为
request
(例如
RequestInterceptor
)。会话和请求是非常不同的


否则它看起来可以工作,并且应该是线程安全的

谢谢你的评论。我添加了一个编辑,并根据我在文档中读到的内容和我找到的几个示例提出了解决方案。你觉得这可行吗?再次感谢。对于意外的否决票,非常抱歉,出于某种原因,它不会让我更改它。NP,它应该允许您在编辑我的答案后重新查看您的否决票。