3

我有两个控制器继承自一个,MainController。每个控制器的范围都是“会话”。在 MainController 我有一个变量:索引,只需遵循:

@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(如定义)。

是否可以将索引的当前值“注入”到 C2?

4

4 回答 4

4

如果要计算用户访问该站点的次数,有几种方法。一种简单的方法是创建一个映射到所有请求的 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
    }
}
于 2013-03-25T21:41:47.813 回答
1

虽然 C1 和 C2 是 MainController 的子类,但是当 spring 启动时,它会为每个创建一个实例,因此你有两个变量的副本Index

最简单的方法是使 Index 变量静态,使其属于类实例,而不是对象

尝试在每个 C1 和 C2 的构造函数上打印一些调试语句,当弹簧启动时,您会看到它们都是不同的对象实例

于 2013-03-25T21:51:36.440 回答
1

我不会将控制器本身放入会话范围。

而是在 sessionscope 中实现保存 index 变量的 sessionobject 并将其连接到您的控制器中。

我看到至少三个优点:

  • 较小的会议
  • 不需要静态
  • 更容易扩展:如果你突然在另一个地方需要这个索引,而不是继承你的基础的控制器
于 2013-03-26T06:24:39.760 回答
0

我像 Martin Frey 写的那样解决了我的问题。我已经将索引创建为会话 bean,控制器可以是 Scope 请求。

解决问题的主要标签是:bean XML 中的 scope="session" 和 aop:scoped-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;
    }

}

以及 xml 中的 Bean 定义:

<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>

它就像我想要的那样工作。

于 2013-03-26T20:07:17.687 回答