我有两个控制器继承自一个,MainController。每个控制器的作用域都是"session"。在MainController中,我有一个变量:Index,只需遵循:
@Controller
public class C1 extends MainController {
@RequestMapping(value="/action1")
public void Action1() {
System.out.print(Index);
}
}
@Controller
public class C2 extends MainController {
@RequestMapping(value="/action2")
public void Action2() {
System.out.print(Index);
}
}
public class MainController {
protected int Index = 0;
@ModelAttribute("BeforeRequest")
public void BeforeRequest(HttpServletRequest request) {
if (request.getRequestURI().contains("action1")) {
Index++;
}
}
}
当"Action1"运行时,MainController中的Index增加1 (ModelAttribute注释)。在C1中,每个请求变量增加1,但在C2中仍然是0(如定义)。
是否可以将Index的当前值"注入"到C2?
如果你想计算用户访问网站的次数,有几种方法。一种简单的方法是创建一个servlet过滤器,该过滤器映射到所有请求,从而增加请求计数并将其放置在用户会话中。
在web.xml中:
<filter>
<filter-name>RequestCountFilter</filter-name>
<filter-class>com.mycompany.RequestCountFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestCountFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器的实现看起来像这样:
public class RequestCountFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession();
Integer requestCount = session.getAttribute("requestCount") == null 0 : session.getAttribute("requestCount");
session.setAttribute("requestCount", ++requestCount);
chain.doFilter(req, res);
}
public void init(FilterConfig config) throws ServletException {
// init code goes here
}
public void destroy() {
// clean up goes here
}
}
虽然C1和C2是MainController的子类,但当spring启动时,它将分别创建一个实例,因此您有变量Index
的两个副本。
最简单的方法是使Index变量静态,这样它就属于类实例,而不是对象
尝试在每个C1和C2的构造函数上打印一些调试语句,当spring启动时,您将看到它们都是不同的对象实例
我不会将控制器本身放入会话作用域。
不如实现你的sessionobject,在sessionscope中包含索引变量,并将其连接到你的控制器中。
我认为至少有三个优点:
- <
- 小会话/gh>
- 不需要静态
- 更容易扩展:如果你突然需要这个索引在另一个地方,而不是继承你的基础控制器
我像Martin Frey写的那样解决了我的问题。我已经创建了索引作为一个会话bean和控制器可以范围请求。
解决问题的主要标签是:scope ="session"和aop:scope -proxy
下面是改进后的代码:@Controller
@Scope("request")
public class C1 extends BaseController {
@RequestMapping(value="/action1")
public void Action1() {
System.out.println("Action1: " + Index.getIndex());
}
}
@Controller
@Scope("request")
public class C2 extends BaseController {
@RequestMapping(value="/action2")
public void Action2() {
System.out.println("Action2: " + Index.getIndex());
}
}
而BaseController是:
public class BaseController {
@Autowired
protected BeanSession Index;
@ModelAttribute("BeforeRequest")
public void BeforeRequest(HttpServletRequest request) {
if (request.getRequestURI().contains("action1")) {
Index.setIndex(Index.getIndex() + 1);
}
}
public BeanSession getIndex() {
return Index;
}
public void setIndex(BeanSession index) {
Index = index;
}
}
BeanSession类:
public class BeanSession {
private int Index;
public BeanSession() {
this.Index = 1;
}
public int getIndex() {
return Index;
}
public void setIndex(int index) {
Index = index;
}
}
和Bean在xml中的定义:
<bean id="BeanSession_Bean" class="controller.BeanSession" scope="session" >
<aop:scoped-proxy/>
</bean>
<bean id="BaseController_Bean" class="controller.BaseController">
<property name="Index" ref="BeanSession_Bean" />
</bean>
就像我想的那样