英文:
How to serve different Autowired model to different users
问题
我刚开始学习Spring。我对一些简单的并发概念感到困惑。
我有一个只包含一个字段uid
的类:
@Service("Class1")
@Data
public class Class1 {
private String uid;
}
然后我有一个请求映射器,其中在其中自动装配了Class1
。
@RestController
@RequestMapping("/web")
@Scope("session")
public class Web {
@Autowired
Class1 class1;
@GetMapping("/hello")
public String sayHello(@RequestParam(value = "myName", defaultValue = "World") String name) {
class1.setUid(name);
try{
Thread.sleep(5000);
}
catch (InterruptedException e){
}
return String.format("Hello %s and uid %s!", name,class1.getUid());
}
}
现在,如果我同时使用两个不同的参数myName=name1
和myName=name2
发送两个请求,那么uid在两个请求中显示相同。但我认为它应该等于传递的特定名称。
我希望将uid
分配给传递的名称。为什么两个请求中不能有两个不同的Class1
实例?为什么会发生这种并发情况?
我知道Spring通过生成2个不同的线程来处理2个不同的会话。但我的担忧是两个线程都使用同一个bean。但我希望不同的会话有不同的实例。如何正确做到这一点?
英文:
I have just started learning Spring. I am confused with some simple concept of concurrency.
I have a class containing only 1 field uid
:
@Service("Class1")
@Data
public class Class1 {
private String uid;
}
And I have request mapper with Class1
Autowired in it.
@RestController
@RequestMapping("/web")
@Scope("session")
public class Web {
@Autowired
Class1 class1;
@GetMapping("/hello")
public String sayHello(@RequestParam(value = "myName", defaultValue = "World") String name) {
class1.setUid(name);
try{
Thread.sleep(5000);
}
catch (InterruptedException e){
}
return String.format("Hello %s and uid %s!", name,class1.getUid());
}
}
Now if I hit two request at the same time with two different parameters say, myName=name1
and myName=name2
, the uid is shown same in both the requests. But i think it should be equal to that particular name which is being passed.
I want to assign uid
equal to the name which is being passed. How cannot be there 2 different instances of Class1
in both the request? Why is this concurrency happening?
I know Spring handle 2 different sessions by generating 2 different threads. But my concern is that both the threads use same bean. But i want different instance for different sessions. What is the proper way to do so?
答案1
得分: 1
我不确定这是否是问题,但乍一看我可以将其与默认(隐式使用的)范围为Singleton相关联,这意味着只有一个bean实例(在您的情况下是服务bean)。通常,要在bean内部处理状态,最好为服务类使用@RequestScope(如果要在那里存储状态),这将为每个特定请求创建bean实例。
英文:
I'm not sure if this is the issue, but at first glance I could relate this to the fact that the default(implicitly used) scope is Singleton, which means there is only one instance of bean (in your case the service bean). Usually, to handle state inside of the beans it is better to use @RequestScope for the service class (if you want to store the state there), which will create bean instance exactly for each particular request.
答案2
得分: 0
不确定,但您在类级别上使用了 @Service
,因此它在所有会话之间共享。因此最终结果取决于稍后处理的请求。
所以
R1 -> "string1"
R2 -> "string2"
在调用
return String.format("Hello %s and uid %s!", name,class1.getUid());
时,它会获取设置的最新值。
根据我的理解,数据类不应该是一个共享组件(@Component
或其派生类),因为默认范围是单例,您需要更改范围(原型或其他)。这样它就会在每个请求时被实例化,获取更多详情,您可以阅读 https://www.geeksforgeeks.org/singleton-and-prototype-bean-scopes-in-java-spring。
英文:
No sure but u are using @Service
at the class level so its shared between all sessions. so the final result depends on which request is served later.
So
R1 -> "string1"
R2 -> "string2"
at the time when u call
return String.format("Hello %s and uid %s!", name,class1.getUid());
it will fetch the latest value which was set
as per my understanding the data class should not be a shared component(@Component
or its derivatives) as by default scope is singleton u need to change the scope(prototype or other). so that it get instantiated at every request for more detail u can read https://www.geeksforgeeks.org/singleton-and-prototype-bean-scopes-in-java-spring.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论