弹簧控制器 - 线程安全和存储资源 [英] Spring controllers - thread safety and storing resources

查看:133
本文介绍了弹簧控制器 - 线程安全和存储资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对spring mvc和线程安全有疑问。

I have a question about spring mvc and thread safety.

我们正在开发将存储在tomcat上的Web应用程序。如果我理解正确,Tomcat会根据请求创建线程并且它有一些线程池。现在,调度程序servlet在请求之间共享,可能是线程安全的。

We are developing web application that will be stored on tomcat. If I understand right, Tomcat creates thread per request and it has some thread pool. Now, dispatcher servlet is shared between requests and probably is thread safe.

但是当我创建这样的控制器时:

But when I create controller like this:

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

他有 Singleton 范围,因此来自每个用户的每个请求都使用相同的控制器。

he has Singleton scope so the same controller is used by every request that comes from every user.

我想知道这是怎么回事问题通常得到解决:

I am wondering how this problem is usually solved:

1:是否使用 Session 范围创建控制器? (但我认为如果一个用户快速做一些可能导致控制器中竞争条件的事情,也可能会出现问题。)

1: are controllers created with Session scope? (but I think that there also could be problems if one user quickly do some things that may lead to race conditions in the controller).

2:控制器的作用域为 request

2: controllers are scoped as request

3:创建不在类级别共享任何变量的无状态控制器,或者将它们设置为只读模式

3: creating stateless controllers that don't share any variables at class level, or have them in read only mode

或者可能有更好的最佳实践来解决这类问题。

or maybe there is some better "best practice" that solves this kind of problem.

我是问这个问题,因为现在我们将它们作为 Singleton 作用域,并且存在一个问题,在大多数方法中我们都在查询数据库中的用户,而我们不能由于范围,将此信息存储在类级变量中。我们可以尝试使用一些线程安全集合,但稍后可能还有其他资源需要同步访问。

I am asking this question, because now we have them as Singleton scoped, and there is a problem, that in most methods we are querying for user in the database , and we can't store this information in class level variable because of the scope. We could try to use some thread safe collection but later there could be other resources needing synchronized access.

推荐答案

A 可以添加很多参数到控制器方法,如请求,会话,校长等,以避免您的问题。

A lot of parameters can be added to the controller methods like request, session, principal etc to avoid your problem.

通常有3层架构:


  • @Controller (他们委托服务)

  • @Service (他们使用DAO或存储库完成工作)

  • @Repository (或DAO,他们进行数据库访问)

  • @Controller (they delegates to services)
  • @Service (they do the work using DAOs or Repositories)
  • @Repository (or DAOs, they do DB access)

因此,根据您在数据库中查询的内容,我建议您使用Spring注入的服务使用缓存如果命中数据库是昂贵的,每次你需要从DB调用服务的东西(即没有存储在c中ontroller类级别)

So depending on what you are querying for in the DB, I would advise having a service, injected by Spring with a cache if hitting the DB is costly and everytime you need the stuff from the DB call the service (i.e. nothing stored in the controller class level)

一个简短的例子,假设我们落后于spring-security,一切都需要一个完全登录的用户。我们有一个 userData 表,其中密钥是用户登录,我们有一个网址 / data 来显示一个页面我的用户数据:

A short example, let's say we are behind spring-security and everything need a fully logged-in user. We have an userData table where the key is the user login, we have an url /data to get a page showing my user 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确保这是当前的用户一。

Here I use principal and spring ensure that this is current user one.

参考:

  • @Cachable
  • see also Initialize Singletons in Spring Framework 3 MVC

请注意这个问题是否完全解决了您的问题

这篇关于弹簧控制器 - 线程安全和存储资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆