Я думаю, что с точки зрения REST, идентификатор должен быть помещен в URL, что-то вроде:
https://example.com/module/[ID]
, а затем я вызываю GET, PUT, DELETE для этого URL.Это вроде ясно, я думаю.В контроллерах Spring MVC я получал бы идентификатор с помощью @PathVariable.Работает.
Теперь моя практическая проблема с Spring MVC заключается в том, что если я сделаю это, мне НЕ нужно включать идентификатор как часть формы (также), Spring выдает предупреждения типа
Skipping URI variable 'id' since the request contains a bind value with the same name.
в противном случае.И также имеет смысл отправлять его только один раз, верно?Что бы вы сделали, если они не совпадают?
Это было бы хорошо, но у меня есть собственный валидатор для компонента поддержки формы, который должен знать идентификатор!(Необходимо проверить, используется ли определенное уникальное имя для другого экземпляра объекта, но не может, не зная идентификатора отправленной формы).
Я не нашел хорошего способа сообщить валидаторуэтот идентификатор из @PathVariable, так как проверка происходит еще до того, как код в моем методе контроллера выполняется.
Как бы вы решили эту дилемму?
Это мой контроллер (изменен):
@Controller
@RequestMapping("/channels")
@RoleRestricted(resource = RoleResource.CHANNEL_ADMIN)
public class ChannelAdminController
{
protected ChannelService channelService;
protected ChannelEditFormValidator formValidator;
@Autowired
public ChannelAdminController(ChannelService channelService, ChannelEditFormValidator formValidator)
{
this.channelService = channelService;
this.formValidator = formValidator;
}
@RequestMapping(value = "/{channelId}/admin", method = RequestMethod.GET)
public String editChannel(@PathVariable Long channelId, @ModelAttribute("channelForm") ChannelEditForm channelEditForm, Model model)
{
if (channelId > 0)
{
// Populate from persistent entity
}
else
{
// Prepare form with default values
}
return "channel/admin/channel-edit";
}
@RequestMapping(value = "/{channelId}/admin", method = RequestMethod.PUT)
public String saveChannel(@PathVariable Long channelId, @ModelAttribute("channelForm") @Valid ChannelEditForm channelEditForm, BindingResult result, Model model, RedirectAttributes redirectAttributes)
{
try
{
// Has to validate in controller if the name is already used by another channel, since in the validator, we don't know the channelId
Long nameChannelId = channelService.getChannelIdByName(channelEditForm.getName());
if (nameChannelId != null && !nameChannelId.equals(channelId))
result.rejectValue("name", "channel:admin.f1.error.name");
}
catch (EmptyResultDataAccessException e)
{
// That's fine, new valid unique name (not so fine using an exception for this, but you know...)
}
if (result.hasErrors())
{
return "channel/admin/channel-edit";
}
// Copy properties from form to ChannelEditRequest DTO
// ...
// Save
// ...
redirectAttributes.addFlashAttribute("successMessage", new SuccessMessage.Builder("channel:admin.f1.success", "Success!").build());
// POST-REDIRECT-GET
return "redirect:/channels/" + channelId + "/admin";
}
@InitBinder("channelForm")
protected void initBinder(WebDataBinder binder)
{
binder.setValidator(formValidator);
}
}