繁体   English   中英

Spring Controller覆盖@ModelAttribute请求参数映射

[英]Spring Controller override @ModelAttribute request param mapping

假设我有一个像这样的Spring Controller:

    @Controller
    public class FooController {

        @RequestMapping(value = "/foo", method = RequestMethod.GET)
        public String update (Model model,
                          @RequestParam (value="id") String id,
                          @RequestParam (value="description") String description) {

                Foo foo = new Foo(id, description);

                fooService.create(update);

        return "foo";
    }

我想像下面那样重写它,但是定义我自己的请求param映射,而不是让Spring的@ModelAttribute定义它:

    @Controller
    public class FooController {

        @RequestMapping(value = "/foo", method = RequestMethod.GET)
        public String update(Model model,
                          @ModelAttribute("foo") Foo foo) {

        fooService.update(foo);

        return "foo";
    }

有谁知道我会怎么做? 我看过转换器,PropertyEditors和使用@RequestBody,但我不认为这些都是正确的。 我似乎需要以某种方式覆盖Spring的数据绑定。

我解决的解决方案是使用实现Spring的HandlerMethodArgumentResolver类来检测Object并从HttpServletRequest构造它。 注意 - 这与@ daviooh的答案非常相似。 这里的主要区别是这个解决方案是特定于Spring的,它可以“自动”检测对象类。

添加到spring context.xml

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="your.package.name.FooResolver" />   
    </mvc:argument-resolvers>
</mvc:annotation-driven>

创建FooResolver:

public class FooResolver implements HandlerMethodArgumentResolver {

public static final String ID = "id";
public static final String DESCRIPTION = "description";

@Override
public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterType().equals(Foo.class);
}

@Override
public Object resolveArgument(MethodParameter parameter,
                              ModelAndViewContainer mavContainer, 
                              NativeWebRequest webRequest,
                              WebDataBinderFactory binderFactory) throws Exception {

    Foo foo = null;

    if(parameter.getParameterType().equals(Foo.class)) {

        foo = new Foo();

        if (webRequest.getParameter(ID) != null) tag.setId((String) webRequest.getParameter(ID));
        if (webRequest.getParameter(DESCRIPTION) != null) tag.setDescription((String) webRequest.getParameter(DESCRIPTION));
    }

    return foo;
}

}

然后控制器方法变为:

    @RequestMapping(value = "/foo", method = RequestMethod.GET)
    public String update (Model model, Foo foo) {
        fooService.update(foo);
        return "foo";
    }

这个解决方案允许我从我的模型对象上的getter和setter方法名称中解析http请求参数名称,并将这个逻辑从我的控制器中拉出来,以使其保持整洁,更容易理解。 因此,控制器逻辑位于控制器中,对对象映射逻辑的http请求位于解析器类中。

一个选项可以是实现一个实用程序类(每个实体需要映射一个),它将请求参数解析为自定义对象。 像这样的东西:

public class FooParser{

    public static final String ID = "id";
    public static final String DESCRIPTION = "description";

    public static Foo parse(HttpServletRequest req){
        Foo foo = null;
        if (request.getParameter(ID) != null
            && request.getParameter(DESCRIPTION) != null) {
            foo = new Foo(request.getParameter(ID), request.getParameter(DESCRIPTION));
        }
        return foo;
    }
}

并将其用于您的控制器方法。

@Controller
public class FooController {

    @RequestMapping(value = "/foo", method = RequestMethod.GET)
    public String update(Model model,
                      HttpServletRequest req) {

    Foo foo = FooParser.parse(req);
    fooService.update(foo);

    return "foo";
}

Spring应该自动为你做这件事。 关键是将表单字段与“Foo”对象的属性相匹配。

这里有一些文档: http//docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#mvc-ann-modelattrib-methods

下一步是数据绑定。 WebDataBinder类将请求参数名称(包括查询字符串参数和表单 字段 )与名称模型属性字段进行匹配。 在必要时应用类型转换(从String到目标字段类型)后填充匹配字段。

这个请求的另一面是什么样的? 提交表单的HTML是什么?

编辑

我刚刚创建了一个可能有帮助的演示。 下面是代码,包括表单,控制器和foo类。 让我知道您遇到的任何问题。

形成:

<form method="POST" action="/fooAction">
<input type="text" name="bar" id="bar"/></form>

控制器:

@Controller
public class GreetingController {

      @RequestMapping(value = "/fooAction", method = RequestMethod.POST)
      public String fooAction(Model m, Foo foo) {
        System.out.println("foo is: " + foo);
        m.addAttribute(foo);
        return "fooAction";
      }

    }

Foo类:

public class Foo {
  private String bar;

  public String getBar() { return bar; }

  public void setBar(String bar) { this.bar = bar; }

  @Override
  public String toString() {
    return "Foo[" + bar + "]";
  }      
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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