Первая небольшая справочная информация. Получены довольно стандартные отношения «Роль пользователя», в которых у пользователя может быть много ролей. У меня есть роли, определенные как набор внутри класса пользователя. Теперь я знаю, что html-формы имеют все значения в виде строк и пытаются получить значения, поскольку мой пользовательский объект Role не работает. Я реализовал initbinder для преобразования идентификатора обратно в объект, чтобы я мог извлекать выбранные значения из моих флажков, эта часть работает.
Но я не могу вернуться в обратном направлении. Я извлекаю пользователя из базы данных, у которого уже есть роли, и хочу предварительно заполнить флажки ролей всеми ролями, которые есть у пользователя. На основе этого примера:
Они говорят, что:
form: checkboxes items = "$ {dynamic-list}" path = "property-to-store"
Для нескольких флажков, как пока значение «путь» или «свойство» равно равно любому из «значений флажков - $ {dynamic-list}», совпадающие флажок будет установлен автоматически.
Моя интерпретация заключается в том, что я должен иметь возможность передать ему Набор всех ролей и определить путь, который будет ролями из объекта Пользователь, и он должен соответствовать им, что приведет к тому, что флажок будет установлен предварительно заполнить.
Кажется, каждый пример имеет значение динамического списка как String []. Хорошо, это здорово, но как это работает для пользовательских объектов, которые мы определили как Set? Могу ли я по-прежнему использовать это однострочное определение для флажков, или мне также нужно сделать какой-то заголовок привязки данных в представлении?
Вот мой пользовательский dto, пользовательский контроллер, настраиваемая привязка формы и страница редактирования пользователя.
] User DTO
@Entity
@Table
public class User extends BaseDto
{
@Column(updatable = false) @NotBlank
private String username;
@Column(name = "encrypted_password") @Size(min = 6, message = "password must be at least 6 characters") @Pattern(regexp = "^\\S*$", message = "invalid character detected")
private String password;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column @NotNull
private boolean enabled;
@Column @Email @NotBlank
private String email;
@Transient
private String confirmPassword;
@ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER, cascade = CascadeType.REFRESH) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set roles;
public User()
{
}
public User(final String usernameIn, final String passwordIn, final String firstNameIn, final String lastNameIn, final String emailIn, final boolean enabledIn)
{
username = usernameIn;
password = passwordIn;
firstName = firstNameIn;
lastName = lastNameIn;
email = emailIn;
enabled = enabledIn;
}
public String getUsername()
{
return username;
}
public void setUsername(final String usernameIn)
{
username = usernameIn;
}
public String getPassword()
{
return password;
}
public void setPassword(final String passwordIn)
{
password = passwordIn;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(final String firstNameIn)
{
firstName = firstNameIn;
}
public String getLastName()
{
return lastName;
}
public void setLastName(final String lastNameIn)
{
lastName = lastNameIn;
}
public String getEmail()
{
return email;
}
public void setEmail(final String emailIn)
{
email = emailIn;
}
public String getConfirmPassword()
{
return confirmPassword;
}
public void setConfirmPassword(final String confirmPasswordIn)
{
confirmPassword = confirmPasswordIn;
}
public boolean isEnabled()
{
return enabled;
}
public void setEnabled(final boolean enabledIn)
{
enabled = enabledIn;
}
public Set getRoles()
{
return roles;
}
public void setRoles(final Set rolesIn)
{
roles = rolesIn;
}
}
User Controller
@Controller @RequestMapping("/user")
public class UserController
{
@Autowired private UserService userService;
@Autowired private UserDao userDao;
@Autowired private RoleDao roleDao;
@InitBinder
public void bindForm(final WebDataBinder binder)
{
binder.registerCustomEditor(Set.class, "roles", new CustomFormBinder(roleDao, Set.class));
}
@RequestMapping(method = RequestMethod.GET)
public String index(final ModelMap modelMap)
{
return "/user/index";
}
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String create(final ModelMap modelMap)
{
modelMap.addAttribute("userInstance", new User());
modelMap.addAttribute("validRoles", new HashSet(roleDao.findAll()));
return "/user/create";
}
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(final ModelMap modelMap, @Valid @ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
{
// TODO move to service validation
if (user.getPassword() == null || !user.getPassword().equals(user.getConfirmPassword()) )
{
bindingResult.addError(new FieldError("userInstance", "password", "password fields must match"));
bindingResult.addError(new FieldError("userInstance", "confirmPassword", "password fields must match"));
}
if (user.getRoles() == null || user.getRoles().isEmpty())
{
bindingResult.addError(new FieldError("userInstance", "roles", "Must select at least one role for a User"));
}
if (bindingResult.hasErrors())
{
modelMap.addAttribute("validRoles", new HashSet(roleDao.findAll()));
return "/user/create";
}
userService.save(user);
return "redirect:/user/list";
}
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public String edit(@PathVariable final Integer id, final ModelMap modelMap)
{
final User user = userDao.find(id);
if (user != null)
{
modelMap.addAttribute("userInstance", user);
modelMap.addAttribute("validRoles", new HashSet(roleDao.findAll()));
return "/user/edit";
}
return "redirect:/user/list";
}
@RequestMapping(value = "/edit", method = RequestMethod.GET)
public String editCurrent(final ModelMap modelMap)
{
return edit(userService.getLoggedInUser().getId(), modelMap);
}
@RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(@Valid @ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
{
if (bindingResult.hasErrors())
{
return "/user/edit";
}
userService.save(user);
return "redirect:/user/list";
}
@ModelAttribute("userInstances")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public List list()
{
return userDao.findAll();
}
}
Custom Form Binder
public class CustomFormBinder extends CustomCollectionEditor
{
private final T dao;
private static final Logger LOG = LoggerFactory.getLogger(CustomFormBinder.class);
public CustomFormBinder(final T daoIn, final Class collectionType)
{
super(collectionType, true);
dao = daoIn;
}
@Override
protected Object convertElement(final Object element)
{
try
{
// forms should return the id as the itemValue
return dao.find(Integer.valueOf(element.toString()));
}
catch (NumberFormatException e)
{
LOG.warn("Unable to convert " + element + " to an integer");
return null;
}
}
}
User Edit View
Create User
Edit User ${userInstance.username}
Username:
Password:
First Name:
Last Name:
Email:
**<%--Want to Pre Populate these checkboxed--%>
**