Можно отправить более одного типа объекта из JSP в Spring Controller?

1

Я кодирую представление 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. Большое спасибо!

Теги:
jsp
spring
spring-mvc

2 ответа

1
Лучший ответ

Вы можете решить эту проблему, поместив собственный HandlerMethodArgumentResolver чтобы привязать параметры запроса, отправленные из вашей формы, в аргумент model. Например:

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

Экземпляр этого класса можно добавить в аргумент resolver, чтобы отобразить конфигурацию вашего приложения.

@Override
public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(new RequestToModelBindingArgumentResolver());
}

Однако есть проблема. Аргументы, аннотированные с помощью @ModelAttribute будут разрешаться с помощью ModelAttributeMethodProcessor и поскольку не ModelAttributeMethodProcessor упорядочение HandlerMethodArgumentResolver он всегда будет первым, кто разрешит это значение. Это означает, что если вы добавите настраиваемый аргумент аргумента, он никогда не будет достигнут. Это означает, что нам нужно найти способ сортировки коллекции резольверов (вот почему resolver реализует Ordered).

Одним из простых способов сортировки коллекции резольвера является RequestmappingHandlerAdapter параметра 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().

Но эй! Я думаю, что намного проще просто изменить подпись обработчиков :)

  • 0
    Ваа, отличный аргумент, разрешающий урок :) Это способ сделать это. Это тяжело и некрасиво, но это решает вопрос. Большое спасибо за ваше время ^^
1

Вы можете создать форму, имеющую поля, соответствующие полям формы, и затем получить эту форму следующим образом:

 @RequestMapping(method= RequestMethod.POST)
        public Response add(@RequestBody Form form, HttpServletRequest request){
    //The form element fields must match with fields in your form. Especially the names and types.
    }

Помимо этих двух параметров, которые передаются в add(), вы можете передать еще много

  • 0
    Большое спасибо ... Я тоже думал об этом. Дело в том, что я не могу изменить параметры контроллера, поэтому я должен найти способ передать два разных объекта, не заключая их в один объект> __ <
  • 0
    Почему вы не можете изменить метод обработчика? Он принимает только ModelMap который не имеет ничего общего с отправкой данных формы. Также странно иметь @ModelAttribute на самой модели. Ваша настройка не имеет смысла.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню