【问题标题】:Modify and return ModelAttribute object if validation fails如果验证失败,修改并返回 ModelAttribute 对象
【发布时间】:2020-08-17 11:17:54
【问题描述】:

我有简单的实体...

@Entity
public class WatchedDirectory {
    @Column(nullable=false)
    @NotBlank(message="Filesystem path CANNOT be empty")
    String filesystemPath;
}

... 和 GET 端点用于创建一个 ...

    @GetMapping("/add")
    public String add(@ModelAttribute WatchedDirectory watchedDirectory) {
        return "mng-dir-add";
    }

... 显示在 Thymeleaf 中制作的表单,带有错误验证等。一旦你点击 sumbmit 按钮,数据就会进入 POST 端点......

    @PostMapping("/add")
    public String addExecute(@Valid @ModelAttribute WatchedDirectory watchedDirectory, BindingResult result, RedirectAttributes redirect, Model model) {
        if(result.hasErrors()) {
            // here I want to iterate through
            // errors and clean erroneous fields
            return "mng-dir-add";
        }
        watchedDirectory = fs.persistDirectory(watchedDirectory);
        redirect.addFlashAttribute("added", watchedDirectory);
        return "redirect:/list";
    }

...一切都很好,花花公子。当数据有效时,它会被持久化并重定向到列表(POST/Redirect/GET)。当数据无效时,thymeleaf 的错误字段会被填充,我会在相应字段下方列出错误消息。

我唯一想改变但不知道怎么做的就是从模型中清除一些数据。

到目前为止我尝试过的事情:修改@ModelAttribute参数,在Model中设置属性,在RedirectAttributes中设置属性。每次我得到相同的数据用户提供的输出形式没有任何变化时,出于某种原因,我无法改变任何事情。我也尝试重定向到 GET 方法,但似乎它清除了我不想要的 slate clean。

如果有人感兴趣,这就是 thymeleaf 中的形式:

        <form id="content" action="#" th:action="@{/add}" th:object="${watchedDirectory}" method="post" class="was-validated">
            <div class="form-group has-feedback has-error">
                <label for="filesystemPath">Filesystem path:</label>
                <input th:field="*{filesystemPath}" type="text" id="filesystemPath" name="filesystemPath" class="form-control" placeholder="~/" required />
                <label th:if="${#fields.hasErrors('filesystemPath')}" th:errors="*{filesystemPath}"></label>
            </div>          
            <button type="submit" class="btn btn-outline-success">Save</button>
        </form>

required 输入字段上的属性在提供空格时将关闭,但 Spring 验证会出现错误消息。清除此字段并将其返回给用户将使事情比显示混合信号更加一致,例如:

任何帮助将不胜感激。

【问题讨论】:

    标签: spring spring-boot spring-mvc spring-data-jpa spring-data


    【解决方案1】:

    您需要定义一个BeanPropertyBindingResult 对象,该对象提供有错误的字段。然后用这个结果做一个模型,

    @PostMapping( "/add" )
    public String addExecute( @Valid @ModelAttribute WatchedDirectory watchedDirectory, BindingResult result, RedirectAttributes redirect, Model model )
    {
        if( result.hasErrors() )
        {
            BeanPropertyBindingResult result2 = new BeanPropertyBindingResult( watchedDirectory, theBindingResult.getObjectName() );
            for( ObjectError error : theBindingResult.getGlobalErrors() )
            {
                result2.addError( error );
            }
            for( FieldError error : theBindingResult.getFieldErrors() )
            {
                result2.addError( new FieldError( error.getObjectName(), error.getField(), null, error.isBindingFailure(), error.getCodes(), error.getArguments(), error.getDefaultMessage() ) );
            }
    
            model.addAllAttributes( result2.getModel() );
            return "mng-dir-add";
        }
        watchedDirectory = fs.persistDirectory( watchedDirectory );
        redirect.addFlashAttribute( "added", watchedDirectory );
        return "redirect:/list";
    }
    

    【讨论】:

    【解决方案2】:

    根据 Spring 框架文档中的Validation by Using Spring’s Validator Interface

    Validator 接口通过使用Errors 对象来工作,因此, 在验证时,验证者可以向验证者报告验证失败 Errors 对象。

    validate(Object, org.springframework.validation.Errors): 验证 给定的对象,并在验证错误的情况下注册那些 使用给定的Errors 对象。

    并且Errors 接口不提供任何用于取消注册绑定错误的 API。

    所以,似乎没有Spring 提供的方式来实现你想要的。

    【讨论】:

    • 不要误会我的意思,但我绝不想注销错误-相反-我想保留它们。不幸的是,虽然您可以修改@Valid对象的正确参数,但您不能对验证阶段失败的参数执行此操作,Spring 只是恢复对它们所做的所有更改并推送它返回查看。
    猜你喜欢
    • 2014-06-20
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多