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



我有两个控制器继承自一个,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>

就像我想的那样

最新更新