我有一个关于 spring mvc 和线程安全的问题。
我们正在开发将存储在 tomcat 上的 Web 应用程序。如果我理解正确的话,Tomcat 会为每个请求创建线程,并且它有一些线程池。现在,调度程序 servlet 在请求之间共享并且可能是线程安全的。
但是当我这样创建 Controller 时:
@Controller
@RequestMapping("/manage")
public class QuestionManagementController {
他有 Singleton
作用域,因此来自每个用户的每个请求都使用同一个 Controller 。
我想知道这个问题通常是如何解决的:
1: Controller 是在 Session
范围内创建的吗? (但我认为,如果一个用户快速执行某些可能导致 Controller 出现竞争条件的操作,也可能会出现问题)。
2: Controller 的作用域为request
3:创建在类级别不共享任何变量的无状态 Controller ,或者让它们处于只读模式
或者也许有一些更好的“最佳实践”可以解决这类问题。
我问这个问题,因为现在我们将它们作为 Singleton
作用域,并且有一个问题,在大多数方法中我们在数据库中查询用户,我们无法存储由于范围的原因,此信息在类级别变量中。我们可以尝试使用一些线程安全的集合,但稍后可能会有其他资源需要同步访问。
最佳答案
A lot of parameters can be added请求、 session 、委托(delegate)人等 Controller 方法以避免您的问题。
通常有一个三层架构:
@Controller
(他们委托(delegate)服务)@Service
(他们使用 DAO 或存储库完成工作)@Repository
(或 DAO,它们进行数据库访问)
因此,根据您在数据库中查询的内容,我建议提供一项服务,如果访问数据库的成本很高,则由 Spring 注入(inject)缓存,并且每次您需要数据库中的内容时都调用该服务(即没有存储任何内容)在 Controller 类级别)
一个简短的例子,假设我们支持 spring-security,一切都需要一个完全登录的用户。我们有一个 userData
表,其中的键是用户登录,我们有一个 url /data
来获取显示我的用户数据的页面:
@Controller
@RequestMapping("/data")
public class UserDataController
{
@Autowired
private UserService userService;
@RequestMapping(value = "", method = RequestMethod.GET)
public ModelAndView data(final Principal principal) {
Assert.notNull(principal); // throw if assertion fails
Assert.hasText(principal.getName());
final UserData userData = this.userService.findByUserName(principal.getName());
Assert.notNull(userData, "userData not found");
return new ModelAndView("userData", "userData", userData);
}
}
@Service("userService")
public class userService
{
private static final String USERDATA_CACHE = "com.acme.foo.UserData";
@Autowired
private UserDataRepository userDataRepository;
@Cacheable(USERDATA_CACHE)
public UserData findByUserName(final String userName) {
return this.userDataRepository.findByUserName(userName);
}
}
@Repository
public class UserDataRepository
{
// or use spring-data-jpa
public UserData findByUserName(final String userName) {
// query table userData and create an UserData from results.
}
}
这里我使用 principal 和 spring 确保这是当前用户一。
引用:
请注意这个答案是否完全解决了您的问题
关于java - Spring Controller - 线程安全和存储资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12121519/