假设我有一个像这样的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";
}
我想像下面那样重写它,但是定义我自己的请求参数映射,而不是让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的数据绑定。
答案 0 :(得分:3)
我解决的解决方案是使用实现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请求位于解析器类中。
答案 1 :(得分:1)
一个选项可以是实现一个实用程序类(每个实体需要映射一个),它将请求参数解析为自定义对象。像这样:
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";
}
答案 2 :(得分:0)
Spring应该自动为你做这件事。关键是将表单字段与“Foo”对象的属性相匹配。
下一步是数据绑定。 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 Class:
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 + "]";
}
}