首页 > 解决方案 > 春季清除会话范围bean

问题描述

我创建了一个会话范围的bean,如下所示:

@Bean
@Scope(
    value = WebApplicationContext.SCOPE_SESSION,
    proxyMode = ScopedProxyMode.TARGET_CLASS)
public TodoList todos() {
    return new TodoList();
}

我已将 bean 添加为模型属性,并且可以跨多个页面显示 bean。

@GetMapping("/todos.html")
public String list(Model model) {
    model.addAttribute("todos", todos);
    return "scopedproxytodos";
}

但我不确定如何清除会话中的属性。

@PostMapping("/end")
public ModelAndView endSession(SessionStatus sessionStatus, Model model) {
    model.addAttribute("todos", new TodoList());
    sessionStatus.setComplete();
    return new ModelAndView("redirect:/");
}

标签: javaspringspring-mvc

解决方案


我已将 bean 添加为模型属性,并且可以跨多个页面显示 bean:

...

`model.addAttribute("todos", todos);`

...

并不真地。这仅在当前视图中添加属性。

要实现这一点,您应该使用以下方式注释您的TodoList@SessionScope

@SessionScope
@Component
public class TodoList {
    // ...
}

然后注释你的控制器需要有一个对话范围的todoswith@SessionAttributes并注入它@ModelAttribute。未经测试,但类似的东西:

@Controller
@SessionAttributes("todos")
public class FooController { 

  @GetMapping("/todos.html")
  public String list(@ModelAttribute TodoList todos) {
    // set the todos value
    return "scopedproxytodos";
  }

}

您可以在任何其他带有注释的控制器中使用它@SessionAttributes("todos")

并且要删除todos当前的会话会话, status.setComplete()请照常使用。
在您的情况下,您可以删除它:

@PostMapping("/end")
public ModelAndView endSession(SessionStatus sessionStatus, Model model) {
    sessionStatus.setComplete();
    return new ModelAndView("redirect:/");
}

并让具有会话范围的控制器根据需要重新初始化它(FooController实际上是这样做的)。
另一种方法是重新初始化它而不是删除它。
例如 :

@PostMapping("/end")
public ModelAndView endSession(@ModelAttribute TodoList todos) {
    todos.clear();
    return new ModelAndView("redirect:/");
}

此解决方案的优点:

  • 更整洁/更简洁
  • 不需要为每个会话创建 bean。就开销而言,Bean 比存储在会话中的值更昂贵。

这里有更多关于操作对话属性的方式的信息。


该类SessionStatus管理弹簧会话的属性:

可以注入处理程序方法的简单接口,允许它们发出会话处理完成的信号。处理程序调用程序随后可以进行适当的清理,例如在处理程序处理期间隐式创建的会话属性

这意味着它清除了存储在 Spring 处理程序会话中的属性(不同于经典的 http 会话),而不是存储在 http 请求中的属性,实际上您没有在 spring 会话属性中添加任何内容。
所以这是没用的。


推荐阅读