Spring mvc Spring MVC:请求作用域,尝试使用binder.setDisallowedFields更新命令对象

Spring mvc Spring MVC:请求作用域,尝试使用binder.setDisallowedFields更新命令对象,spring-mvc,spring-3,spring-4,spring-mvc-initbinders,Spring Mvc,Spring 3,Spring 4,Spring Mvc Initbinders,我有这个东西 public class Deportista implements Serializable { private static final long serialVersionUID = 6229604242306465153L; private String id; ... @NotNull(message="{field.null}") public String getId() { return id;

我有这个东西

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)一个新的命令对象,
验证
代码运行良好

问题在于更新

我有以下资料:

@InitBinder(value="deportistaActualizar")
public void actualizarInitBinder(WebDataBinder binder) {
    logger.info(">>>>>>>> actualizarInitBinder >>>>>>>>>>>>>");
    binder.setDisallowedFields("id");
}
@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);
}
@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);
}
注意我有
活页夹。设置不允许的字段(“id”)

问题是:

  • 当表单或命令出现任何错误时,控制器将重新呈现视图,表单将显示错误消息,显示预期的错误信息,但没有ID值

  • 如果我尝试更新对象,当然保留id值,并且没有任何错误地继续更新,那么它将失败
控制台中将显示以下内容:

- -------- 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]
id为空。如何解决此问题,保持请求范围

我有一个备用控制器,它正在与
@SessionAttributes
一起工作,所有的工作都很完美。但是,如果用户在同一个web浏览器中打开了多个选项卡,一个用于创建,另一个用于更新,这将是一个巨大的风险,所有这些都将是非常错误的。根据,应该使用请求范围而不是会话范围。这是有道理的

遗憾的是,Spring似乎无法解决这一问题:

添加

根据你的建议,我有以下几点:

@InitBinder(value="deportistaActualizar")
public void actualizarInitBinder(WebDataBinder binder) {
    logger.info(">>>>>>>> actualizarInitBinder >>>>>>>>>>>>>");
    binder.setDisallowedFields("id");
}
@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);
}
@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);
}
观察使用
@RequestParam
的方法,我的问题是当要更新的URL具有以下样式时,如何更新该方法
http://localhost:8080/spring-实用程序/Parkalista/1/actualizar.htm
。URL中没有参数,因此
@RequestParam
现在是无用的

我已经阅读了Spring参考文档:

第二次添加

是的,你是对的,我昨天也这么做了,但我忘了分享以下内容:

@InitBinder(value="deportistaActualizar")
public void actualizarInitBinder(WebDataBinder binder) {
    logger.info(">>>>>>>> actualizarInitBinder >>>>>>>>>>>>>");
    binder.setDisallowedFields("id");
}
@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);
}
@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);
}
由于任何
处理程序
方法总是在前面调用
@modeldattribute
,因此以下URL失败
http://localhost:8080/spring-utility/lakelista/registrator.htm
,页面上显示以下内容

HTTP Status 400 -
type Status report
message
description The request sent by the client was syntactically incorrect.
当然,因为URL不包含预期的
id
。因此,我无法创建新记录以供以后编辑/查看

我可以确认,对于以下工作:

  • http://localhost:8080/spring-实用程序/Parkalista/1/detalle.htm
  • http://localhost:8080/spring-实用程序/Parkalista/1/actualizar.htm
检索id(1)

我怎样才能解决这个问题


谢谢

问题在于,您使用的两种方法基本上是对同一对象进行操作的。但是,它们不共享对象。正如我在另一个问题中所回答的那样,添加一个用
@ModelAttribtue
注释的方法,该方法根据id检索所需的对象。基本上从get方法中删除对对象的检索,并将其放在一个用
@modeldattribute
注释的方法中。理解,但请参见
添加
部分。谢谢。只需在其上放置一个
@PathVariable
@RequestMapping
方法上几乎所有可用的注释都适用于
@modeldattribute
方法。请检查
第二次添加
部分,好吗?谢谢。目前无法定义默认或可选路径变量。作为一种解决方法,您可以创建两个控制器,一个用于创建新控制器,另一个用于更新现有控制器。