【问题标题】:Possible to modify @ModelAttribute before @Validated is run可以在运行 @Validated 之前修改 @ModelAttribute
【发布时间】:2013-08-05 00:51:48
【问题描述】:

可以在通过@Validated 验证@ModelAttribute 之前对其进行修改。

@RequestMapping(value = "/doSomething", method = RequestMethod.POST)
public final ModelAndView save(
        @Validated(value = {myGroup.class}) @ModelAttribute("myObject") MyObject myObject)

我需要在执行@Validated 之前更改myObject 的状态

【问题讨论】:

    标签: spring-mvc hibernate-validator


    【解决方案1】:

    添加一个 ModelAttribute 填充方法怎么样?

    @ModelAttribute("myObject")
    public MyObject modifyBeforeValidate(
            @ModelAttribute("myObject") MyObject myObject) {
        //modify it here
        return myObject;
    }
    

    如果我没记错的话,这个方法会在每个 @RequestMapping 方法之前被调用。

    更新1:示例

    @ModelAttribute("command")
    public ChangeOrderCommand fillinUser(
            @ModelAttribute("command") ChangeOrderCommand command,
            HttpServletRequest request) {
        command.setUser(securityGateway.getUserFrom(request));
        return command;
    }
    
    @RequestMapping(value = "/foo/bar", method = RequestMethod.POST)
    public String change(@ModelAttribute("command") ChangeOrderCommand command,
            BindingResult bindingResult, Model model, Locale locale) {
    }
    

    【讨论】:

    • 我的印象是这只会发生在 RequestMethod.GET 请求中
    • @jax 我在之前的项目中找到了一个示例。查看更新的答案。
    【解决方案2】:

    @Validated触发前修改模型属性对象有两种方式:

    1. 删除@Validated并自动连接验证器并手动触发验证器:
    class MyController {
    
      private final Validator validator;
    
      class MyController(Validator validator) {
        this.validator = validator;
      }
    
      @PostMapping("/doSomething")
      public final ModelAndView save(
            @ModelAttribute("myObject") MyObject myObject, BindingResult result) {
        // edit MyObject here
    
        validator.validate(myObject, result)
    
        // original method body here
    }
    
    
    1. 装饰默认验证器并在装饰的验证器内预处理myObject 对象。
    class MyController {
    
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.setValidator(new PreProcessMyObjectValidator(binder.getValidator()));
        }
    
    @PostMapping("/doSomething")
      public final ModelAndView save(
            @Validated(value = {myGroup.class}) @ModelAttribute("myObject") MyObject myObject, BindingResult result) {
        ...
      } 
    
    private static class PreProcessMyObjectValidator implements Validator {
            private final Validator validator;
    
            public PreProcessMyObjectValidator(Validator validator) {
                this.validator = validator;
            }
    
            @Override
            public boolean supports(@Nonnull Class<?> clazz) {
                return validator.supports(clazz);
            }
    
            @Override
            public void validate(@Nonnull Object target, @Nonnull Errors errors) {
                if (target instanceof MyObject) {
                    MyObject myObject = (MyObject) target;
                    // manipulate myObject here
    
                }
    
                validator.validate(target, errors);
            }
        }
    
    }
    

    (第二个提示是我从https://github.com/spring-projects/spring-framework/issues/11103 那里得到的)

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 2023-04-02
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      • 2011-07-16
      • 2018-02-18
      相关资源
      最近更新 更多