@ModelAttribute用于复杂对象

时间:2018-06-16 20:11:27

标签: java spring spring-mvc spring-boot thymeleaf

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

@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;
}

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

@PostMapping("/register")
public String register(@RequestParam String username,
                       @RequestParam String password,
                       @RequestParam MultipartFile avatar) { ...

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

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

3 个答案:

答案 0 :(得分:5)

写一个UserUserDto而不是试图将所有内容都塞进您的UserForm类中,您可以将它们转换成UserUserForm将专门用于Web,稍后将转换为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
}

然后在控制器中执行您打算做的事情(类似这样):

@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";
    }
} 

这样,您就可以拥有一个专门的对象来修复基于Web的用例,同时保持实际的User对象是干净的。

答案 1 :(得分:0)

也许您可以只使用设置器来执行所有这些操作。当Spring将数据映射到字段并且您在实体中有设置器时,它将使用它们来传递数据。您可以通过这种方式预处理数据并将最终值设置为字段。

答案 2 :(得分:0)

 @PostMapping("/register")
public String register(@ModelAttribute User user, Model model) { // remember if You have another name for parameter and backing bean You should type this one @ModelAttribute(name="userFromTemplate") User user
    encryptPassword(user.getPassword); //remember that is sample code, You can do it however You want to 
    extractBytes(user.getAvatar); //same here
    user.setRole(manuallySetRole);
    model.addAttribute("user", user);
        return "success"; // here u can redirect to ur another html which will contain info about ur user
    } else
        return "redirect:sorry";
}
encryptPassword(String password) { ... }
same for the rest methods

在这里,我给您示例代码如何在示例中使用@ModelAttribute。如果您有任何疑问,请随时发表评论。