Spring MVC:Request Scope,尝试使用binder.setDisallowedFields更新命令对象

时间:2014-09-17 21:54:51

标签: 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;
    }
    ...

}

我有以下Controller的方法

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

在此之前,Controller可以创建表单(GET)并提交(POST) 命令对象,Validation代码运行良好。< / p>

问题在于更新。

我有以下内容:

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

问题是:

  • 当表单或命令出现任何错误时,控制器会重新呈现视图,并且表单会显示错误消息的预期结果,但没有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浏览器中打开了许多选项卡,一个用于创建,另一个用于更新,则风险很大,所有这些都将是非常错误的。根据{{​​3}},应使用请求范围而不是会话范围。它有道理。

可悲的是似乎 Spring不会解决这个问题: Spring MVC + Session attributes and multiple tabs

加成

根据您的建议,我有以下内容:

@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。网址中没有 param ,因此@RequestParam现在没用了。

我已经阅读过Spring Reference文档: @SessionAttributes doesn't work with tabbed browsing

第二次加法

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

@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,因此以下网址失败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.

当然因为网址不包含预期的id。因此我无法创建新记录以便以后编辑/查看。

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

  • http://localhost:8080/spring-utility/deportista/1/detalle.htm
  • http://localhost:8080/spring-utility/deportista/1/actualizar.htm

检索到id(1)。

我怎么解决这个问题?

谢谢

0 个答案:

没有答案