Spring MVC: запрос объема, пытается обновить объект команды с помощью binder.setDisallowedFields
У меня есть этот объект
public class Deportista implements Serializable {
private static final long serialVersionUID = 6229604242306465153L;
private String id;
...
@NotNull(message="{field.null}")
public String getId() {
return id;
}
...
}
У меня есть следующие методы контроллера
@InitBinder(value="deportistaRegistrar")
public void registrarInitBinder(WebDataBinder binder) {
logger.info(">>>>>>>> registrarInitBinder >>>>>>>>>>>>>");
}
@RequestMapping(value="/registrar.htm", method=RequestMethod.GET)
public String crearRegistrarFormulario(Model model){
logger.info("crearRegistrarFormulario GET");
Deportista deportista = new Deportista();
model.addAttribute("deportistaRegistrar", deportista);
return "deportista.formulario.registro";
}
@RequestMapping(value="/registrar.htm", method=RequestMethod.POST)
public String registrarPerson(@Validated @ModelAttribute("deportistaRegistrar") Deportista deportista,
BindingResult result){
logger.info("registrarPerson POST");
logger.info("{}", deportista.toString());
if(result.hasErrors()){
logger.error("There are errors!!!!");
for(ObjectError objectError : result.getAllErrors()){
logger.error("Error {}", objectError);
}
return "deportista.formulario.registro";
}
logger.info("All fine!!!!");
this.fakeMultipleRepository.insertDeportista(deportista);
return "redirect:/manolo.htm";
}
До этого момента Контроллер может создавать форму (GET) и отправлять (POST) новый объекткоманды, Validation
код работает хорошо.
Проблема с обновлением.
У меня есть следующее:
@InitBinder(value="deportistaActualizar")
public void actualizarInitBinder(WebDataBinder binder) {
logger.info(">>>>>>>> actualizarInitBinder >>>>>>>>>>>>>");
binder.setDisallowedFields("id");
}
Соблюдай у меня binder.setDisallowedFields("id")
public String crearActualizarFormulario(@PathVariable("id") String id, Model model){
logger.info("crearActualizarFormulario GET");
Deportista deportista = this.fakeMultipleRepository.findDeportista(id);
model.addAttribute("deportistaActualizar", deportista);
return "deportista.formulario.actualizacion";
}
@RequestMapping(value="/{id}/actualizar.htm", method=RequestMethod.POST)
public String actualizarPerson(@Validated @ModelAttribute("deportistaActualizar") Deportista deportista,
BindingResult result){
logger.info("actualizarPerson POST");
logger.info("{}", deportista.toString());
if(result.hasErrors()){
logger.error("There are errors!!!!");
for(ObjectError objectError : result.getAllErrors()){
logger.error("Error {}", objectError);
}
return "deportista.formulario.actualizacion";
}
logger.info("All fine!!!!");
this.fakeMultipleRepository.updateDeportista(deportista);
return "redirect:/manolo.htm";
}
Проблема в:
- когда у формы или команды есть какая-либо ошибка, контроллер повторно отображает представление, и появляется форма, показывающая сообщения об ошибках, как ожидается, но без значения идентификатора
или же
- если я пытаюсь обновить объект, конечно, сохраняя значение идентификатора, и безо всякой ошибки просто перейти к обновлению, это не удастся
В консоли появится следующее:
- -------- createCollections ---------------
- >>>>>>>> actualizarInitBinder >>>>>>>>>>>>>
- Skipping URI variable 'id' since the request contains a bind value with the same name.
- actualizarPerson POST
- Deportista [id=null, nombre=Manuel, ...]
- There are errors!!!!
- Error Field error in object 'deportistaActualizar' on field 'id': rejected value [null]; codes [NotNull.deportistaActualizar.id,NotNull.id,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [deportistaActualizar.id,id]; arguments []; default message [id]]; default message [The field must be not empty]
Идентификатор является нулевым. Как я могу обойти эту проблему, сохраняя объем запроса?
У меня есть альтернативный контроллер, который работает с @SessionAttributes
и все работает отлично. Но поскольку существует огромный риск, если у пользователя будет открыто много вкладок в одном и том же веб-браузере, одна для создания, а другая для обновления, все будет очень неправильно. Согласно атрибутам Spring MVC + Session и нескольким вкладкам, область действия запроса должна использоваться вместо области сеанса. Это имеет смысл.
К сожалению , Spring не собирается это исправлять: @SessionAttributes не работает с просмотром вкладок
прибавление
По вашему предложению у меня есть следующее:
@ModelAttribute("deportistaActualizar")
public Deportista populateActualizarFormulario(@RequestParam(defaultValue="") String id){
logger.info("populateActualizarFormulario - id: {}", id);
if(id.equals(""))
return null;
else
return this.fakeMultipleRepository.findDeportista(id);
}
Соблюдайте метод использует @RequestParam
моя проблема в том, как обновить этот метод, чтобы работать, когда URL для обновления имеет следующий стильhttp://localhost:8080/spring-utility/deportista/1/actualizar.htm
, Там нет параметров в URL, поэтому @RequestParam
сейчас бесполезно.
Я уже прочитал справочную документацию Spring: Использование @ModelAttribute для метода
Второе дополнение
Да, вы были правы, и я сделал это вчера, но я забыл поделиться следующим:
@ModelAttribute("deportistaActualizar")
public Deportista populateActualizarFormulario(@PathVariable(value="id") String id){
logger.info("populateActualizarFormulario - id: {}", id);
if(id.equals(""))
return null;
else
return this.fakeMultipleRepository.findDeportista(id);
}
Так как @ModelAttribute
всегда вызывается любым handler
метод, следующий URL не удается http://localhost:8080/spring-utility/deportista/registrar.htm
на странице появится следующее
HTTP Status 400 -
type Status report
message
description The request sent by the client was syntactically incorrect.
Конечно, потому что URL не содержит ожидаемого id
, Поэтому я не могу создавать новые записи для последующего редактирования / просмотра.
Я могу подтвердить, что для следующей работы:
http://localhost:8080/spring-utility/deportista/1/detalle.htm
http://localhost:8080/spring-utility/deportista/1/actualizar.htm
Идентификатор (1) получен.
Как я мог решить это?
Благодарю вас