I have something like this:
@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>
What I want is that the Servlet Controller is session scoped, but each request needs to instantiate a new QueryRunner
as to not have any interference if multiple requests are sent at once.
How do I configure Spring to do this?
The tempting solution is to just go:
@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);
}
[...] but each request needs to instantiate a new QueryRunner as to not have any interference if multiple requests are sent at once
Your setup already does that. Your QueryRunner
bean is declared as
<bean id="queryRunner"
class="com.myproject.QueryRunner"
scope="prototype">
<aop:scoped-proxy />
This means that Spring will inject a proxy wherever such a bean is requested, for example
@Autowired
private QueryRunner queryRunner;
and the proxy will, internally, delegate all calls to newly initialized beans every time. Note that this means that if you do something like
Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));
each of those runQuery
calls are, underneath it all, invoked on different QueryRunner
instances.
If you want to have a single QueryRunner
bean that spans the entire lifecycle of a request, just declare the bean to have the request scope
<bean id="queryRunner"
class="com.myproject.QueryRunner"
scope="request">
<aop:scoped-proxy />
Behind the scenes (assuming the default MVC configuration), Spring will store a reference to the HttpServletRequest
in a ThreadLocal
context accessible through a static
utility class. It will store the actual bean in the HttpServletRequest
attributes.
When you eventually invoke runQuery
on the proxy (which is stored in the `@Autowired field), Spring will first check the context for a existing bean. If it finds one, it will use it to invoke your method. If it doesn't, it will initialize a new instance, store it in the context, then use it. This way, the previous example
Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));
is actually invoking runQuery
on the same QueryRunner
instance.
Since HttpServletRequest
attributes are cleared after each request, so will your request-scoped bean instances.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.