简体   繁体   中英

Spring MVC ModelAttribute as Interface

Using a Spring MVC @Controller, how do I have a @RequestMapping endpoint have a @ModelAttribute declared as an interface?

I want to have three different forms being posted to the mapping that the underlying classes are all of an interface type.

So for example, I can have three different form objects with the action to the following:

@RequestMapping(path="/doSomething", method=RequestMethod.POST)
public String doSomething(ObjectInterface formInfo) {
   ...
}

(Where ObjectInterface is an interface, not a concrete class.)

Figured it out. It is to write and register a custom HandlerMethodArgumentResolver. Below is the core code. You just need to figure out which concrete bean class to pass into the webDataBinderFactory. Your controller can then be written to accept an interface and you will be provided the concrete implementing bean behind the interface.

public class MessageResolverTest implements HandlerMethodArgumentResolver {

    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().equals(<Interface>.class);
    }

    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) throws Exception {

        String name = ModelFactory.getNameForParameter(methodParameter);
        WebDataBinder webDataBinder = webDataBinderFactory.createBinder(nativeWebRequest, new <ConcreteBean>(), name);
        MutablePropertyValues mutablePropertyValues = new MutablePropertyValues(nativeWebRequest.getParameterMap());
        webDataBinder.bind(mutablePropertyValues);

        return webDataBinder.getBindingResult().getTarget();
    }
}

It can be done using request level model attributes as follows:

Suppose There is ObjectInterace is an interface with three implementation classes as ObjectA, ObjectB and ObjectC. then Controller method declaration is:

@RequestMapping(path="/doSomething", method=RequestMethod.POST)
public String doSomething(@ModelAttribute("object") ObjectInterface formInfo) {
   ...
}

Add Method to populate modelattribute in the controller class:

    @ModelAttribute("object")
    public ObjectInterface getModelObject(HttpServletRequest request) {
     ObjectInterface object = null;
     String type = request.getParameter("type");
      if (StringUtils.equals("A", type)) {
        object= new objectA();
      } else if (StringUtils.equals("B", type)){
        object= new objectB();
      }else if (StringUtils.equals("C", type)){
        object= new objectC();
       }else{
          //object=any default object.
       }
     return object ;
   }

the value returned by getModelObject is added to the Model and it will be populated with the values from the view to the controller method.

Before invoking the handler method, Spring invokes all the methods that have @ModelAttribute annotation. It adds the data returned by these methods to a temporary Map object. The data from this Map would be added to the final Model after the execution of the handler method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM