【发布时间】:2018-11-20 17:12:43
【问题描述】:
为了学习 Spring,我正在玩一些非常简单的页面来理解 Spring 的一般注释和行为。准确地说,我创建了一个页面来显示Task 的列表和另一个页面来添加一个新的Task。我使用@SessionAttibutes 将任务列表保存在会话中,而不是在每次访问任务列表页面时调用服务来检索Task 的完整列表。
这是我的TaskService
@Service
public class TaskService {
private List<Task> taskCache = new ArrayList<Task>();
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
public Task addTask(String title, String desc, Date targetDate) {
Task newTask = new Task(title, desc, targetDate);
taskCache.add(newTask);
return newTask;
}
}
这是我的TaskController
@Controller
@SessionAttributes("taskList")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/task-view")
public String showTaskList() {
return "task/view";
}
@GetMapping("/task-add")
public String showAddTaskForm(@ModelAttribute("task") Task newTask) {
return "task/add";
}
@PostMapping("/task-add")
public String addTask(ModelMap model, @ModelAttribute("task") Task newTask, @ModelAttribute("taskList") List<Task> taskList) {
System.out.println("ADDING NEW TASK: " + taskList.size());
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
System.out.println("DONE ADDING NEW TASK: " + taskList.size());
return "redirect:/task-view";
}
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
}
这是我的view.jsp
<html>
<head>
<title>Task Page</title>
</head>
<body>
This is your task list:
${taskList}
<div>
<a href="task-add">Add a task</a>
</div>
</body>
</html>
这是我的add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Task Page</title>
</head>
<body>
<form:form method="POST" action="/task-add" modelAttribute="task">
<div>
<form:label path="title">Title</form:label>
<form:input path="title" />
</div>
<div>
<form:label path="desc">Description</form:label>
<form:input path="desc" />
</div>
<div>
<input type="submit" value="Add">
</div>
</form:form>
</body>
</html>
就会话范围的属性而言,它按我的预期工作。 TaskService.retrieveTasks() 函数仅在我第一次访问 view.jsp 时被调用。随后,从 Session 中提取相同的任务列表。
问题是当我尝试在add.jsp 页面上添加两个新的Task 时,我在控制台中看到了以下几行。
CALLING TASK SERVICE TO GET LIST OF TASKS
GETTING TASK LIST FOR THE FIRST TIME
ADDING NEW TASK: 0
DONE ADDING NEW TASK: 2
ADDING NEW TASK: 2
DONE ADDING NEW TASK: 4
当我第一次访问view.jsp 时,打印了第一两行,这是正确的。但是,我不知道ADDING NEW TASK 和DONE ADDING NEW TASK 行之间发生了什么。如果有人能向我解释为什么下面的行在我的 Task 列表中添加重复项,我将不胜感激
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
我还尝试删除taskList.add() 部分,只对taskService.addTask() 进行了服务调用。在这种情况下,没有重复,我的 taskList 更新为一条新记录。但是,当TaskService 类中没有注入时,我不明白taskService 如何间接修改我的taskList。
我错过了什么吗?
【问题讨论】:
-
您引用同一个列表两次,因此将
Task两次添加到同一个列表中。缓存的危险...与其尝试同步缓存,不如在服务中添加一次,然后刷新缓存列表。而不是尝试手动使它们保持最新... -
@M.Deinum 感谢您指出我的错误。我试图实现一个简单的例子来学习 Spring。我以为我在某种程度上误解了 Spring,但我从来没有意识到我犯了这样一个基本的 Java 错误。
标签: java spring spring-mvc spring-boot session