Selectively Binding a Property in Spring MVC

2019-09-04 12:11发布

问题:

I have a page that has a form on it where the user can save or delete a bean. The form backing object has a bean as its property. When the user chooses to delete a bean, there's no need to bind the bean since JPA only requires the id of the bean to be deleted.

Is there anyway to tell the Spring MVC not to bind some of the properties of a form backing object under certain conditions? I'd like to skip the binding of its bean property if the request is for delete.

EDIT: I'm using Spring 3. Here's the psuedo code.

@Controller
public class FormController {
    @RequestMapping(method = RequestMethod.POST)
    public void process(HttpServletRequest request) {
        String action = request.getParameter("action");

        if (action.equals("SAVE")) {
            // bind all parameters to the bean property of the FormObject
        }
        else if (action.equals("DELETE")) {
            // skip the binding. manually read the bean.id parameter.
            int id = Integer.valueOf(request.getParameter("bean.id"));
            EntityManager entityManager = ...
            Bean bean = entityManager.getReference(Bean.class, id);
            entityManager.remove(bean);
        }
    }

    public class Bean {
        private int id;
    }

    public class FormObject {
        private Bean bean;
    }
}

回答1:

You can distinguish between different submit buttons using their name attribute and route requests initiated by these buttons to different handler methods using params attributes of @RequestMapping. For example, in Spring 3:

<input type = "submit" name = "saveRequest" value = "Save" />
<input type = "submit" name = "deleteRequest" value = "Delete" />

.

@RequestMapping(value = "/foo", method = RequestMethod.POST, 
    params = {"saveRequest"})
public String saveFoo(@ModelAttribte Foo foo, BindingResult result) { ... }

// Only "id" field is bound for delete request
@RequestMapping(value = "/foo", method = RequestMethod.POST, 
    params = {"deleteRequest"})
public String deleteFoo(@RequestParam("id") long id) { ... }

A more "RESTful" approach would be to put different submit buttons into different forms with method = "PUT" and method = "DELETE" and distinguish requests by method (though it requires a workaround with HiddenHttpMethodFilter).



回答2:

You can use @InitBinder.

@InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }

see here and here.