@ModelAttribute用于复杂对象

Mah*_*zad 5 java spring spring-mvc thymeleaf spring-boot

我有一个具有许多属性的用户实体(此处未显示某些字段):

@Entity
public class User {

    @OneToOne(cascade = ALL, orphanRemoval = true)
    private File avatar; // File is a custom class I have created

    @NotEmpty
    @NaturalId
    private String name;

    @Size(min = 6)
    private String password;

    @Enumerated(EnumType.STRING)
    private Role role;
}
Run Code Online (Sandbox Code Playgroud)

在我的thymeleaf模板中,我有一个提交用户名,密码头像(MultipartFile)的表单.现在在我的控制器而不是这些参数......

@PostMapping("/register")
public String register(@RequestParam String username,
                       @RequestParam String password,
                       @RequestParam MultipartFile avatar) { ...
Run Code Online (Sandbox Code Playgroud)

......我想用@ModelAttribute @Valid User user.我的问题是:

  1. 密码首先应加密然后传递给用户实体,
  2. MultipartFile应该提取bytes [] from 然后存储在用户实体中(作为自定义File对象),
  3. 其他一些字段Role应该在服务类中手动设置.

我该如何利用@ModelAttribute

M. *_*num 6

不要试图将所有东西都塞进你的User班级,而是写一个UserDto或者UserForm你可以转换为/ User.该UserForm会专门网页和转换为User以后.

您正在谈论的转换应该在您的控制器中完成(因为在实际与您的业务服务交谈之前,理想情况下这只是一个转换层).

public class UserForm {

    private MultipartFile avatar; 

    @NotEmpty
    private String username;

    @Size(min = 6)
    @NotEmpty
    private String password;

    public UserForm() {}

    public UserForm(String username) {
         this.username = username;
    }

    static UserForm of(User user) {
        return new UserForm(user.getUsername());
    }

    // getters/setters omitted for brevity
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中做你想做的事情(类似这样):

@PostMapping("/register")
public String register(@ModelAttribute("user") UserForm userForm, BindingResult bindingResult) {
    if (!bindingResult.hasErrors()) {
      User user = new User();
      user.setName(userForm.getUsername());
      user.setPassword(encrypt(userForm.getPassword());
      user.setAvataor(createFile(userForm.getAvatar());
      userService.register(user);
      return "success";
    } else {
      return "register";
    }
} 
Run Code Online (Sandbox Code Playgroud)

这样,您就可以使用专门的对象来修复基于Web的用例,同时保持实际User对象的清洁.