spring控制器-线程安全和存储资源

nhn9ugyo  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(378)

我有一个关于springmvc和线程安全的问题。
我们正在开发将存储在tomcat上的web应用程序。如果我理解正确的话,tomcat会为每个请求创建线程,并且它有一些线程池。现在,dispatcherservlet在请求之间共享,可能是线程安全的。
但当我创建这样的控制器时:

@Controller
@RequestMapping("/manage")
public class QuestionManagementController {

他有 Singleton 所以来自每个用户的每个请求都使用相同的控制器。
我想知道这个问题通常是如何解决的:
1:控制器是用 Session 范围(但我认为,如果一个用户快速地做一些可能导致控制器中出现竞争状况的事情,也可能会出现问题。
2:控制器的作用域为 request 3:创建无状态控制器,这些控制器在类级别不共享任何变量,或者使它们处于只读模式
或者有更好的“最佳实践”来解决这类问题。
我问这个问题,因为现在我们把他们当作 Singleton 有一个问题是,在大多数方法中,我们都是在数据库中查询用户,由于作用域的原因,我们不能将这些信息存储在类级变量中。我们可以尝试使用线程安全的集合,但稍后可能会有其他资源需要同步访问。

mwecs4sa

mwecs4sa1#

可以向控制器方法添加许多参数,如请求、会话、主体等,以避免出现问题。
通常有三层体系结构: @Controller (他们代表服务) @Service (他们使用dao或存储库进行工作) @Repository (或daos,它们不访问数据库)
因此,根据您在db中查询的内容,我建议使用一个服务,如果命中db的代价很高,则由spring注入一个缓存,并且每次需要db中的内容时都调用该服务(即,控制器类级别中没有存储任何内容)
举个简单的例子,假设我们支持spring安全,所有的东西都需要一个完全登录的用户。我们有一个 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来确保这是当前用户。
参考文献: @Cachable 另请参见SpringFramework3MVC中的初始化单例
请注意,如果这个答案完全符合您的担心

相关问题