最近在学习《springmvc学习指南》上的内容,在学习到通过路径进行请求映射时会出现问题,具体是,在一个请求中通过路径变量传递参数,跳转到了一个jsp界面,然后在该界面再次进行请求时会出现404Bad Request。而后台Controller中是有该映射请求的处理函数的。
首页界面如下:
其中url:http://localhost:9080/tag-demo/list-book中tag-demo是项目名,list-book是一个请求映射,Controller类中有方法对该请求进行处理然后跳转到FormList.jsp界面。请求形式:http://domain/context/list-book,其中context为tag-demo。当我们点击“Edit”按钮时,会通过路径变量传递参数:<td><a href="edit-book/${book.id}">Edit</a></td>,其中${book.id}就是我们要传递的路径变量。此时跳转到如下界面:
这时我们可以看到地址栏的地址为:localhost:9080/tag-demo/edit-book/1,edit-book是请求,1是传递的路径变量。代码:
@RequestMapping(value="/edit-book/{id}")
public String editBook(Model model,@PathVariable long id) {
List<Category> categories = bookService.getAllCategories();
model.addAttribute("categories",categories);
Book book = bookService.get(id);
model.addAttribute("book",book);
return "BookEditForm";
}
当我们点击“Update Book”按钮时会发现请求处理失败:
这是由于浏览器会错误的把 tag-demo/edit-book 当成应用上下文,把1当成具体动作。然后当我们点击"Update Book" 按钮时(这是表单的提交方式<form:form commandName="book" action="update-book" method="post">,浏览器会按http://domain/context/action来进行url拼接。其中domain是localhost:9080。context是tag-demo/edit-book。action是update-book。所以最终链接是http://localhost:9080/tag-demo/edit-book/update-book。因此我们的应用是处理不了该请求的。因为我们的应用是tag-demo而不是tag-demo/edit-book。解决办法是在跳转过程中重新定义应用上下文路径context。我们可以把BookEditForm界面的表单属性中的action改成action="/tag-demo/update-book",/tag-demo代表根路径。因此该action会跳转到根路径下面的update-book。这时我们有方法对其进行处理。
此外还可以通过 <c:url/>进行路径的调整。如:
<c:url var="formAction" value="/update-book"/>
<form:form commandName="book" action="${formAction}" method="post">。这样访问路径也会是http://localhost:9080/tag-demo/update-book。其中:
<c:url var="formAction" value="/update-book"/> 如果是默认上下文,即没有context也就是tag-demo,会被解析成
<c:url var="formAction" value="/update-book"/>如果不是默认上下文,会被翻译成 <c:url var="formAction" value="/tag-demo/update-book"/>。<c:url/>是springmvc引用的标签库。详细信息可以去自行百度。
此时链接会被Controller类中的方法正确处理,然后返回到BookList.jsp界面,如下:
可以看到List中的数据多了一条,虽然内容是重复的,但是book.id不一样。