Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring mvc 在异常发生后,建议以什么方式重新显示包含用户输入数据的表单?_Spring Mvc_Exception Handling_User Input - Fatal编程技术网

Spring mvc 在异常发生后,建议以什么方式重新显示包含用户输入数据的表单?

Spring mvc 在异常发生后,建议以什么方式重新显示包含用户输入数据的表单?,spring-mvc,exception-handling,user-input,Spring Mvc,Exception Handling,User Input,为了学习Java和web开发,我正在编写一个个人应用程序,该应用程序有一个表单,用于输入包含配料、说明和各种其他字段的配方。主要工具集是: Spring3.6.4与JSP表单 休眠4.3.10 完成表单可能需要5-10分钟,因此如果存在任何类型的DataAccessException,我希望能够重新显示表单及其以前的条目 SO和其他地方的大多数帖子都建议只显示SQL错误的错误页面,但没有提到用户重新在表单上输入数据的不便(由于表单上使用的数据结构的特殊性,在错误页面上点击后退按钮将不会显示所

为了学习Java和web开发,我正在编写一个个人应用程序,该应用程序有一个表单,用于输入包含配料、说明和各种其他字段的配方。主要工具集是:

  • Spring3.6.4与JSP表单
  • 休眠4.3.10
完成表单可能需要5-10分钟,因此如果存在任何类型的DataAccessException,我希望能够重新显示表单及其以前的条目

SO和其他地方的大多数帖子都建议只显示SQL错误的错误页面,但没有提到用户重新在表单上输入数据的不便(由于表单上使用的数据结构的特殊性,在错误页面上点击后退按钮将不会显示所有输入的数据)

一种有效的简单方法是捕获控制器POST方法中的错误,如下所示:

    try {
        recipeService.addRecipe(recipe);
    }
    catch (DataAccessException ex)
    {
        model.addAttribute("dataError", "DataAccessException caught");
        model.addAttribute("ingredientList", recipeService.getIngredients(recipe));         
        return "recipe/addRecipe";
    }
@SessionAttribute("recipe")
public class RecipeController {

    @ModelAttribute
    public Recipe initializeRecipe () {
        return new Recipe();
    }

....
dataError消息仅用于开发,稍后将替换为更有意义的消息

我认为这种方法存在的问题是,该方法最终必须深入挖掘实际错误,并确定重新显示表单是否有意义,例如,约束冲突=“修复导致错误的这段数据”与数据库连接丢失=“抱歉,无法与数据库对话-稍后再试”。无论我如何彻底地试图识别“重新显示”异常,我怀疑我是否能抓住它们(双关语)

如果取而代之的是删除try/catch并显示一个错误页面,那么我不知道如何使用错误页面中输入的数据返回表单,因为“recipe”model属性对此方法不可用:

    @ExceptionHandler(DataAccessException.class)
    public ModelAndView handleDataAccessException(DataAccessException ex) {
    ModelAndView view = new ModelAndView("/common/error");

    logger.info("Recipe: DataAccessException exception!");

    String errorMsg = ExceptionUtils.getRootCauseMessage(ex);

    view.addObject("errorMessage", errorMsg);
    return view;
}
我还没有尝试过这种方法,但是将表单数据序列化到服务器上的文件是一种可以接受的方法吗?在错误页面上,我可以添加一条类似“单击此处重新显示您的配方并重试”的消息。redisplay方法必须有一种方法来知道要检索并发送到表单的序列化数据集,这可能是不可能的(对序列化还不够熟悉)

我找到了关于在客户端上保存表单数据的帖子:。这是一个不同于我尝试做的内容的上下文,但它提到了localStorage和IndexedDB,这可能是一个更好的解决方案

我为这篇文章的篇幅提前表示歉意,如果这篇文章在其他地方得到了回答,我找不到任何能解决这个特定问题的问题(或者任何博客)。任何帮助都将不胜感激

编辑:

我相信我可以向控制器添加ModelAttribute和SessionAttribute,如下所示:

    try {
        recipeService.addRecipe(recipe);
    }
    catch (DataAccessException ex)
    {
        model.addAttribute("dataError", "DataAccessException caught");
        model.addAttribute("ingredientList", recipeService.getIngredients(recipe));         
        return "recipe/addRecipe";
    }
@SessionAttribute("recipe")
public class RecipeController {

    @ModelAttribute
    public Recipe initializeRecipe () {
        return new Recipe();
    }

....

但是,如果我正确理解这些注释的话,这只在会话期间有效(?)。如果输入的数据可以在以后的会话中检索(例如,数据库备份后)会更好。

最佳实践方法如您在编辑中所建议的,第一次将
@SessionAttributes
@modeldattribute
组合在一起,将调用用
@ModelAttribute
注释的方法。而不是在所有后续调用中,该值将从会话中获取。它非常适合您的案例和wizzard式的对话操作。确保在最后一步中,如果一切正常,则在
SessionStatus
对象上调用
setComplete
(只需在处理程序方法的参数列表中的SessionStatus中列出,它就会被注入)。这将从会话中清除
@SessionAttributes
下列出的变量

如果用户在填写表单时已经登录,那么最好在每次尝试时保存草稿。这是一个额外的努力,但真的很好的可用性

关于存储在客户端的问题,是的,我认为您有一个有效的案例,但您应该是这方面的法官。在客户端存储的缺点是:

  • 用户可以轻松地更改数据
  • 它们特别小
  • 您已绑定到浏览器

  • 如果这些都不困扰您,那么在我看来,使用客户端存储是很好的。使用localeStorage就足够了。IndexDB提供了我认为您不需要的更高级别的操作,但请检查以更好地理解它

    使用post redirect get。请看,我一直在致力于实现
    @modeldattribute
    @SessionAttributes
    ,这看起来非常有希望。一旦我解决了剩下的两个问题并进行了更多的测试,我将接受你的答案。这应该可以处理从会话中的错误恢复(如果合适的话)-接下来我将检查LocalStorage以进行跨会话检索。谢谢你的帮助!我已经能够让
    @modeldattribute/@SessionAttribute
    在我最初描述的场景中工作,也就是说,从错误页面我可以返回到条目页面,并填充用户输入的数据。不过,有一个问题。在addRecipe(POST)方法中,我在对象成功添加到数据库后从模型和会话中删除该对象,然后重定向到displayRecipe页面以显示刚刚输入的配方。由于这两种方法都在同一个控制器中,显示它会将其添加回会话,以便在导航到“添加配方”菜单时再次显示。希望上面的注释有意义。我总是可以将displayRecipe方法移动到不同的控制器上,我可能会这样做——我需要仔细考虑一下。不管怎样,谢谢你的帮助。