【发布时间】:2014-02-23 08:08:45
【问题描述】:
我试图在我的 Spring MVC 应用程序中实现 P/R/G (POST/Redirect/GET) 模式以避免重复的表单提交,而不是显示一些成功视图 (GET),我正在重定向到另一个 URL (redirect:/essays/main/student/{studentId}/activity/add/existing),我也需要为其传递 complete 模型。 org.springframework.web.servlet.view.RedirectView 的 Spring 文档说:
“重定向到绝对、上下文相对或当前请求相对 URL 的视图,将所有模型属性公开为 HTTP 查询参数。”
所以我可以从请求中检索序列化的对象,它适用于字符串,但如果我想传递更复杂的对象,它就不起作用,比如在我的例子中,几个对象列表(activityList,@987654325 @, teacherList)。
这就是它的工作原理:
首先我展示了我的searchActivity 视图,这很好用:
@RequestMapping(value="/{studentId}/activity/search", method = RequestMethod.GET)
public String getSearchActivity(@PathVariable Integer studentId, Model model) {
StudentActivityDTO studentActivityDTO = new StudentActivityDTO();
Student student = studentService.get(studentId);
studentActivityDTO.setStudent(student);
model.addAttribute("studentActivityDTO", studentActivityDTO);
return "searchActivity";
}
这是我searchActivity 观点的重要部分:
<c:url var="studentUrl" value="/essays/main/student/${studentActivityDTO.student.studentId}/activity/search" />
<form:form modelAttribute="studentActivityDTO" id="myForm" method="POST" action="${studentUrl}">
...
<label for="activityDescription">Eneter search string:</label>
<input type="text" id="activityDescription" name="activityDescription">
<input type="submit" value="Submit" id="submit"/>
...
</form:form>
然后我输入一个搜索字符串(activityDescription)并提交我的表单以进行实际搜索(POST),除了最后一行代码(重定向部分)之外,它也可以正常工作:
@RequestMapping(value="/{studentId}/activity/search", method = RequestMethod.POST)
public String postSearchActivity(@PathVariable Integer studentId,
@RequestParam(value="activityDescription") String activityDescription,
@ModelAttribute("studentActivityDTO") StudentActivityDTO studentActivityDTO,
Model model) {
List<Activity> activityList = activityService.search(activityDescription);
model.addAttribute("activityList", activityList);
Student student = studentService.get(studentId);
studentActivityDTO.setStudent(student);
model.addAttribute("studentActivityDTO", studentActivityDTO);
model.addAttribute("activityDescription", activityDescription);
model.addAttribute("courseList", courseService.getAll());
model.addAttribute("teacherList", teacherService.getAll());
return "redirect:/essays/main/student/{studentId}/activity/add/existing";
// return "addExistingActivity"; <-- If I use this it works fine!
}
现在我需要将模型传递给一些控制器的 GET 方法:
@RequestMapping(value="/{studentId}/activity/add/existing", method = RequestMethod.GET)
public String getAddExistingActivity(@PathVariable Integer studentId, Model model) {
// some stuff
return "addExistingActivity";
}
addExistingActivity视图的重要部分:
<c:url var="studentUrl" value="/essays/main/student/${studentActivityDTO.student.studentId}/activity/add/existing" />
<form:form modelAttribute="studentActivityDTO" id="myForm" method="POST" action="${studentUrl}">
...
<label for="activityId">Activity Id:</label>
<input type="text" id="activityId" name="activityId">
<input type="submit" id="submit" value="Submit"/>
<c:if test="${!empty activityList}">
...
</c:if>
<c:if test="${empty activityList}">
<div style="color: #ff0000">No results!</div>
</c:if>
...
</form:form>
但我的列表(activityList、courseList、teacherList)不存在,而且我总是收到消息“没有结果!”。我只在我的堆栈跟踪中得到这个:
[DEBUG] [http-bio-8080-exec-7 08:32:44] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'studentId' of type [java.lang.Integer] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-7 08:32:44] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'studentActivityDTO' of type [rs.ac.uns.tfzr.zpupin.dto.StudentActivityDTO] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-7 08:32:44] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'org.springframework.validation.BindingResult.studentActivityDTO' of type [org.springframework.validation.BeanPropertyBindingResult] to request in view with name 'addExistingActivity'
但如果我使用 return "addExistingActivity" 而不是 redirect:... 一切正常,我的堆栈跟踪中有这个:
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'studentId' of type [java.lang.Integer] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'studentActivityDTO' of type [rs.ac.uns.tfzr.zpupin.dto.StudentActivityDTO] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'org.springframework.validation.BindingResult.studentActivityDTO' of type [org.springframework.validation.BeanPropertyBindingResult] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'activityList' of type [java.util.Collections$CheckedRandomAccessList] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'activityDescription' of type [java.lang.String] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'courseList' of type [java.util.Collections$CheckedRandomAccessList] to request in view with name 'addExistingActivity'
[DEBUG] [http-bio-8080-exec-6 07:42:25] (AbstractView.java:exposeModelAsRequestAttributes:373) Added model object 'teacherList' of type [java.util.Collections$CheckedRandomAccessList] to request in view with name 'addExistingActivity'
所有列表都存在并说明!
我需要什么样的自定义实现才能使其正常工作?任何帮助将不胜感激!
另外,我知道我可以为此使用 flash 属性,但按 F5 后它们不会消失吗?
【问题讨论】:
-
如果我没记错的话,你必须在 Spring MVC 中添加任何模型属性作为“flash 属性”,以使用重定向在控制器之间传递模型属性。这可能会对您有所帮助:stackoverflow.com/questions/7429649/…
-
@CodeChimp 是的,但是在页面上按 F5 后,flash 属性就没有了,不是吗?我不希望这种情况发生......
-
如果您要重定向到另一个控制器或应用程序服务器,该控制器或应用程序服务器不与执行重定向的人共享会话数据,那么除了将数据放在“共同”的地方之外真的没有其他方法.例如,您可以修改重定向的接收者以查找某个 ID,将数据写入具有该 ID 的文件共享/数据库,然后重定向传递该 ID。现在另一端知道去哪里找了。不过,这需要能够在两端修改代码。
-
@CodeChimp 我正在重定向到同一个控制器类。我想我可以使用
@SessionAttributes,但是我根本不需要flash属性... -
是的,如果您的重定向是到同一个控制器,那么
@SessionAttributes是要走的路。我的假设是您正在重定向到一个单独的位置。出于好奇,如果它是同一个控制器,为什么还要使用重定向?
标签: spring-mvc redirect