Java,Spring框架MVC-重定向

Java,Spring框架MVC-重定向,java,forms,spring,frameworks,Java,Forms,Spring,Frameworks,我使用的是SpringFramework 3。 我有一个在文章中发表评论的表格。提交表单时,将检查是否存在任何错误。 若并没有错误,控制器将返回字符串 "redirect:entryView/"+comment.getEntryId(); 一切都很好 但当出现一些错误时,如果控制器返回 "redirect:entryView/"+comment.getEntryId(); 错误应显示在带有spring-form.tld标记的表单附近: <form:errors path="author

我使用的是SpringFramework 3。 我有一个在文章中发表评论的表格。提交表单时,将检查是否存在任何错误。 若并没有错误,控制器将返回字符串

"redirect:entryView/"+comment.getEntryId();
一切都很好

但当出现一些错误时,如果控制器返回

"redirect:entryView/"+comment.getEntryId();
错误应显示在带有spring-form.tld标记的表单附近:

<form:errors path="author"/>
如果没有redirect:prefix,那么它将转到/rus/WEB-INF/jsp/entryView/8.jsp,并且有HTTP状态404。但它必须转到,即文章和评论表单所在的页面

这是视图解析程序:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
</bean>
错误的显示方式如下所示:

在验证/绑定期间,错误将保存为HttpServletResponse对象中的属性 此JSP标记的实现调用response.getAttributename来查找要显示的错误实例 当您使用redirect:url时,您指示Spring将找到的302发送到客户端浏览器,以强制浏览器向新url发出第二个请求

由于重定向到页面使用的是一组不同的请求/响应对象,因此原始错误将丢失

将错误传递到要重定向到的页面以使新页面显示它的最简单方法是,通过向第二个页面的控制器可以查看的会话对象添加消息,或通过在URL中传递参数,自己处理错误。

错误的显示方式如下:

在验证/绑定期间,错误将保存为HttpServletResponse对象中的属性 此JSP标记的实现调用response.getAttributename来查找要显示的错误实例 当您使用redirect:url时,您指示Spring将找到的302发送到客户端浏览器,以强制浏览器向新url发出第二个请求

由于重定向到页面使用的是一组不同的请求/响应对象,因此原始错误将丢失


为了让新页面显示错误,将错误传递到要重定向到的页面的最简单方法是自己处理错误,通过向会话对象添加第二个页面的控制器可以查看的消息或在URL中传递参数。

尝试使用添加注释表单的页面视图,而不是重定向到显示新注释的视图:

if(result.hasErrors()) {
    return "commentForm";
}

您可能还必须在方法签名中添加@modeldattribute Comment…

尝试使用添加注释表单页面的视图,而不是重定向到显示新注释的视图:

if(result.hasErrors()) {
    return "commentForm";
}
您可能还需要在方法签名中添加@ModelAttribute注释…

bkent314是正确的:

看看这两种方法,这是一种有效的防御方法。 我将域对象与表单gui对象FolderCreateCommand分开,但这是我的风格。在本例中,我使用ModelAndView作为返回,而不是字符串,因为这样我就可以完全控制模型

@RequestMapping(method = RequestMethod.GET, params = "form")
public ModelAndView createForm() {
    return modelAndViewForCreate(new FolderCreateCommand(..default values..));
}

@RequestMapping(method = RequestMethod.POST)
public ModelAndView create(@Valid FolderCreateCommand folderCreateCommand,
          BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
        return modelAndViewForCreate(folderCreateCommand);
    }
    Folder folder = this.folderService.createFolder(folderCreateCommand);
    return redirectToShow(folder);
}


private ModelAndView modelAndViewForCreate(FolderCreateCommand folderCreateCommand) {
    ModelMap uiModel = new ModelMap();
    uiModel.addAttribute("folderCreateCommand", folderCreateCommand);
    uiModel.addAttribute("parentFolders", this.folderDao.readAll());
    return new ModelAndView("folders/create", uiModel);
}

private ModelAndView redirectToShow(Folder folder) {
    return new ModelAndView(new RedirectView("/folders/" + folder.getId(), true));
}
bkent314是正确的:

看看这两种方法,这是一种有效的防御方法。 我将域对象与表单gui对象FolderCreateCommand分开,但这是我的风格。在本例中,我使用ModelAndView作为返回,而不是字符串,因为这样我就可以完全控制模型

@RequestMapping(method = RequestMethod.GET, params = "form")
public ModelAndView createForm() {
    return modelAndViewForCreate(new FolderCreateCommand(..default values..));
}

@RequestMapping(method = RequestMethod.POST)
public ModelAndView create(@Valid FolderCreateCommand folderCreateCommand,
          BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
        return modelAndViewForCreate(folderCreateCommand);
    }
    Folder folder = this.folderService.createFolder(folderCreateCommand);
    return redirectToShow(folder);
}


private ModelAndView modelAndViewForCreate(FolderCreateCommand folderCreateCommand) {
    ModelMap uiModel = new ModelMap();
    uiModel.addAttribute("folderCreateCommand", folderCreateCommand);
    uiModel.addAttribute("parentFolders", this.folderDao.readAll());
    return new ModelAndView("folders/create", uiModel);
}

private ModelAndView redirectToShow(Folder folder) {
    return new ModelAndView(new RedirectView("/folders/" + folder.getId(), true));
}

控制器方法的其余部分是如何定义的?控制器方法的其余部分是如何定义的?嗯,但是如果我更改控制器,使其返回ModelAndView并在其中键入:ModelAndView mav=new ModelAndView;mav.addObjecterrors、result.getAllErrors;mav.setViewNameredirect:entryView/+comment.getEntryId;返回mav;行吗?你试过了吗?我的观点是,从本质上讲,向客户端浏览器发送302重定向与在响应对象中嵌入对象的想法相冲突,这正是ModelAndView和Errors对象所做的。Hm,但是如果我更改控制器,使其返回ModelAndView并在其中键入:ModelAndView mav=new ModelAndView;mav.addObjecterrors、result.getAllErrors;mav.setViewNameredirect:entryView/+comment.getEntryId;返回mav;行吗?你试过了吗?我的观点是,从本质上讲,向客户端浏览器发送302重定向与在响应对象中嵌入对象的想法相冲突,这正是ModelAndView和Errors对象所做的。