Spring MVC - 跨控制器的继承变量值

时间:2013-03-25 21:33:44

标签: java spring spring-mvc

我有两个继承自MainController的控制器。每个控制器的范围是“会话”。在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”运行时,Index在MainController中增加1(ModelAttribute注释)。在C1变量每个请求增加1,但在C2中仍然是0(定义)。

可以将“当前值”注入“C2”

4 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

我不会将控制器自己放入会话镜。

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

我发现至少有三个优点:

  • 较小的会话
  • 不需要静态
  • 更容易扩展:如果你突然在另一个地方需要这个索引而不是继承你的基础的控制器

答案 3 :(得分:0)

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

解决问题的主要标签是:scope =“session”和aop:scoped-proxy 在bean XML中。

这是一个改进的代码:

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

它就像我想要的那样。