[英]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.