Часто, при разработке веб-приложений на Spring возникает ситуация, когда приходится объеденять сразу несколько действий в один контроллер. Для этого Бог и создал MultiActionController. Однако, Бог не предусмотрел прямой возможности обрабатывать одним таким контроллером сразу несколько форм. Вот как раз о вмешательстве простого человека в дела Божьи и пойдет речь в этой статье.Итак, братья и сестры, нам понадобятся:
- SimpleFormController
- MethodNameResovler
Первое, что нужно сделать – это реализовать собственный GodMethodNameResovler, который будет имплементировать стандартный интерфейс MethodNameResolver и поместить туда примерно такой код:
public class GodMethodNameResolver implements MethodNameResolver { private Properties mapping; private String defaultMethodName; public void setMappings(Properties mappings) { this.mappings = mappings; } public void setDefaultMethodName(String defaultMethodName) { this.defaultMethodName = defaultMethodName; } public void afterPropertiesSet() { if (mapping == null) { throw new IllegalArgumentException("Methods mapping property required."); } } public String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException { for (Iterator it = this.mappings.keySet().iterator(); it.hasNext();) { String submitParamter = (String)it.next(); if (WebUtils.hasSubmitParameter(request, submitParamter)) { return (String)mapping.get(submitParamter); } } return defaultMethodName; }}
Когда с этим покончено, создадим абстрактный контроллер, который в последствии будут наследовать все остальные MultiActionController’ы:
public abstract class AbstractMultiActionFormController extends SimpleFormController { private MethodNameResolver methodNameResolver; protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { if (errors.hasErrors() || isFormChangeRequest(request)) { return showForm(request, response, errors); } else { String methodName = getMethodNameResolver().getHandlerMethodName(request); Method m = (Method)this.getClass().getMethod(methodName, new Class[] {HttpServletRequest.class, Object.class, BindException.class}); if (m == null) { throw new NoSuchRequestHandlingMethodException(methodName, getClass()); } List params = new ArrayList(3); params.add(request); params.add(command); params.add(errors); return (ModelAndView) m.invoke(this, params.toArray(new Object[params.size()])); } } public void setMethodNameResolver(MethodNameResolver methodNameResolver) { methodNameResolver = methodNameResolver; } public MethodNameResolver getMethodNameResolver() { return methodNameResolver; }}
Также, потребуется описать все это в конфиге спринга:
<bean id="godMethodNameResolver" class="com.myapp.GodMethodNameResolver"> <property name="mappings"> <props> <prop key="testAction">testAction</prop> </props> </property> <property name="defaultMethodName"><value>testAction</value></property></bean><bean id="blessMultiFormController" class="com.myapp.BlessMultiFormController"> <property name="methodNameResolver"><ref bean="godMethodNameResolver"/></property> <property name="sessionForm"><value>true</value></property> <property name="successView"><value>someformview</value></property> <property name="commandName"><value>somecommand</value></property> <property name="formView"><value>someformview</value></property></bean>
И последний шаг – создание контроллера:
public class BlessMultiFormController extends AbstractMultiActionFormController { public ModelAndView testAction(HttpServletRequest request, Object command, BindException errors) throws Exception { // do something with form return showForm(request, errors, getFormView()); }}
Алилуя!