我有这样的事情:
@Controller
@Scope("session")
public class MyServletController {
@Autowired
private QueryRunner queryRunner;
HashMap<String, Result> resultsMap;
@RequestMapping("/submitQuery")
public ModelAndView submitQuery(HttpServletRequest request)
{
String sessionId = request.getParameter("sessionId");
Result r = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
resultsMap.put(sessionId, r);
}
@RequestMapping("/getResult")
@ResponseBody
public void saveTextLinks(HttpServletRequest request,
HttpServletResponse response) throws IOException
{
String sessionId = request.getParameter("sessionId");
//return sessionId result from resultsMap
}
}
<bean id="queryRunner"
class="com.myproject.QueryRunner"
scope="prototype">
<aop:scoped-proxy />
<property name="errorMessageA" value="${error.messagea}"></property>
<property name="errorMessageB" value="${error.messageb}"></property>
</bean>
我想要的是Servlet控制器是会话范围的,但是如果一次发送多个请求,每个请求都需要实例化一个新的QueryRunner
,以便没有任何干扰。
如何配置Spring来执行此操作?
诱人的解决方案就是:
@RequestMapping("/submitQuery")
public ModelAndView submitQuery(HttpServletRequest request)
{
queryRunner = new QueryRunner(); //<-----
String sessionId = request.getParameter("sessionId");
Result r = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
resultsMap.put(sessionId, r);
}
答案 0 :(得分:1)
[...]但是每个请求都需要实例化一个新的QueryRunner,以便在一次发送多个请求时没有任何干扰
您的设置已经这样做了。您的QueryRunner
bean被声明为
<bean id="queryRunner"
class="com.myproject.QueryRunner"
scope="prototype">
<aop:scoped-proxy />
这意味着Spring会在请求这样的bean的地方注入代理,例如
@Autowired
private QueryRunner queryRunner;
并且代理将在内部每次都将所有调用委托给新初始化的bean。请注意,这意味着如果您执行类似
的操作Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));
每个runQuery
次调用都在不同的QueryRunner
个实例上调用。
如果您想拥有一个跨越请求的整个生命周期的QueryRunner
bean,只需将bean声明为具有请求范围
<bean id="queryRunner"
class="com.myproject.QueryRunner"
scope="request">
<aop:scoped-proxy />
在幕后(假设默认的MVC配置),Spring将在HttpServletRequest
上下文中存储对ThreadLocal
的引用,该上下文可通过static
实用程序类访问。它会将实际的bean存储在HttpServletRequest
属性中。
当你最终在代理上调用runQuery
(存储在`@Autowired字段中)时,Spring将首先检查现有bean的上下文。如果找到一个,它将使用它来调用你的方法。如果它没有,它将初始化一个新实例,将其存储在上下文中,然后使用它。这样,前面的例子
Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));
实际上是在同一个runQuery
实例上调用QueryRunner
。
由于HttpServletRequest
属性在每次请求后被清除,因此请求范围的bean实例也将被清除。