我编写了一个JSP视图,一旦提交就必须将多个对象发送到Spring @Controller。
控制器的处理程序具有以下签名:
public ModelAndView handlerX(@ModelAttribute ModelMap model){
我在JSP中尝试过类似的东西:
<form method="post" action="action">
<spring:bind path="objectX.name">
<input type="text" name="${status.expression}" value="${status.value}" readonly="readonly" />
</spring:bind>
但是当调试器到达控制器时,模型对象不包含任何形式的值。
有人可以就如何设计表格提出一些建议吗?我想我不能将两个不同的对象包装在Command-type-object中,因为控制器的处理程序只接受ModelMap。非常感谢你!
答案 0 :(得分:1)
您可以创建一个包含与表单字段匹配的字段的表单,然后像这样获取该表单:
@RequestMapping(method= RequestMethod.POST)
public Response add(@RequestBody Form form, HttpServletRequest request){
//The form element's fields must match with fields in your form. Especially the names and types.
}
除了在add()中传递的这两个参数之外,您还可以传递更多
答案 1 :(得分:1)
您可以通过定制自己的HandlerMethodArgumentResolver
来绑定从表单发送到模型参数的请求参数来解决此问题。例如:
public class RequestToModelBindingArgumentResolver implements HandlerMethodArgumentResolver, Ordered {
@Override
public boolean supportsParameter(final MethodParameter parameter) {
return parameter.hasParameterAnnotation(ModelAttribute.class) &&
parameter.getParameterType() == ModelMap.class;
}
@Override
public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer, final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) throws Exception {
ModelMap model = mavContainer.getModel();
Map<String, String[]> requestParameters = webRequest.getParameterMap();
// Bind all request parameters to the model
for (String param : requestParameters.keySet()) {
String[] values = requestParameters.get(param);
if (values.length == 1) {
model.addAttribute(param, values[0]);
} else {
model.addAttribute(param, values);
}
}
return model;
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}
可以将此类的实例添加到参数解析程序列表中的应用程序配置。
@Override
public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new RequestToModelBindingArgumentResolver());
}
但是有一个问题。使用@ModelAttribute
注释的参数将由ModelAttributeMethodProcessor
解析,由于没有HandlerMethodArgumentResolver
的排序,因此它始终是第一个解析该值的。这意味着如果您要添加自定义参数解析器,则永远不会到达它。这意味着我们需要找到一种方法来对解析器集合进行排序(这就是解析器实现Ordered
)的原因。
对解析器集合进行排序的一种简单方法是将RequestmappingHandlerAdapter
注入配置中。
@Autowired
private RequestMappingHandlerAdapter adapter;
现在我们需要在构造配置之后调用一个方法,这样我们就有机会对解析器集合进行排序。
@PostConstruct
public void orderArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(adapter.getArgumentResolvers());
Collections.sort(resolvers, new OrderComparator());
adapter.setArgumentResolvers(resolvers);
}
由于adapter.getArgumentResolvers()
将返回一个不可修改的列表,我们需要在排序开始前跳到这里。排序后,RequestToModelBindingArgumentResolver
实例将位于列表顶部,第一个实例将响应support()
调用。
但是嘿!我认为改变处理程序签名要容易得多:)