先上代码:
主要是控制器:
@Controller
public class AccountController {
private Map<Long, Account> accounts = new ConcurrentHashMap<Long, Account>();
private static Logger log = LoggerFactory
.getLogger(AccountController.class);
// value = "createForm",
@RequestMapping(method = RequestMethod.GET)
public String getCreateForm(Model model) {
log.info("createForm method is running");
model.addAttribute(new Account());
return "account/createForm";
}
// value = "account",
@RequestMapping(method = RequestMethod.POST)
public String create(@Valid Account account, BindingResult result) {
log.info("account method is running");
if (result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
for (ObjectError error : errors) {
log.info(error.getDefaultMessage());
}
return "account/createForm";
}
this.accounts.put(account.assignId(), account);
return "redirect:/account/" + account.getId();
}
// account
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String getView(@PathVariable Long id, Model model) {
log.info("getView method is running");
Account account = this.accounts.get(id);
if (account == null) {
throw new ResourceNotFoundException(id);
}
model.addAttribute(account);
return "account/view";
}
}
在mvc中配置了一个首页:
<!-- Forwards requests to the "/" resource to the "welcome" view --> <mvc:view-controller path="/" view-name="welcome"/>
在使用3.0.5版本时,只能welcome。而在使用3.1.4版本能访问到:getCreateForm 和create,但是不能访问到getView方法。而且不能进入首页。
后来发现,在3.0.5版本中,使用的是AbstractUrlHandlerMapping,而在3.1的版本中使用的是AbstractHandlerMethodMapping、这是3.1版本中新加的类。
根据日志信息分析一下:
先来看3.0.5版本中的:AbstractUrlHandlerMapping:
Mapped URL path [/{id}] onto handler 'accountController'
Mapped URL path [/{id}.*] onto handler 'accountController'
Mapped URL path [/{id}/] onto handler 'accountController'
控制器中的三个方法都不能匹配上,只有首页“/”能匹配上。所以只能访问首页。
再来看3.1.4版本中的:AbstractHandlerMethodMapping
Mapped "{[],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}"
Mapped "{[],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}"
Mapped "{[/{id}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}"
可以看到,第一个方法和第二个方法只是get/和post的区别。而且匹配“/” 所以,直接通过Url访问时,匹配上了getCreateForm方法。跳转到account/createForm。在createFrom中提交的时候使用的是post,则匹配上第二个方法。而第三个则无法匹配(其实是前面两个把第三个覆盖了。)
解决办法:在控制器上加上:@RequestMapping(value = "/account")
首页可以直接访问。
account。
在3.1.5中:
1:Mapped "{[/account],methods=[POST],
2:Mapped "{[/account/{id}],methods=[GET]
3:Mapped "{[/account],methods=[GET],
首页,上面三种都不能匹配,所以会显示welcome。
访问/account。会匹配3. 提交表单会匹配1。查看表单内容可匹配3.
在3.0.5版本中:
[/account/{id}]
[/account/{id}.*]
[/account/{id}/]
[/account]
[/account.*]
[/account/]
好吧,由于我对Spring源码不熟悉,不知道怎么会是这样。但是通过观察还是可以看出都是可以匹配上的。
留待以后深入源码级别的时候去了解了解,当然大神能告诉我也行。
可以看出来,3.0和3.1的mvc是有区别的,以前一直没有关注。当然以前都是直接声明映射方式的。