Spring MVC ModelAttribute as Interface

两盒软妹~` 提交于 2021-01-28 02:12:18

问题


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.)


回答1:


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.




回答2:


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();
    }
}


来源:https://stackoverflow.com/questions/35164774/spring-mvc-modelattribute-as-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!