@@ -111,6 +111,8 @@ public class FormTag extends AbstractHtmlElementTag {
111111
112112 private String action ;
113113
114+ private String servletRelativeAction ;
115+
114116 private String method = DEFAULT_METHOD ;
115117
116118 private String target ;
@@ -196,6 +198,21 @@ protected String getAction() {
196198 return this .action ;
197199 }
198200
201+ /**
202+ * Set the value of the '{@code action}' attribute.
203+ * <p>May be a runtime expression.
204+ */
205+ public void setServletRelativeAction (String servletRelativeaction ) {
206+ this .servletRelativeAction = (servletRelativeaction != null ? servletRelativeaction : "" );
207+ }
208+
209+ /**
210+ * Get the value of the '{@code action}' attribute.
211+ */
212+ protected String getServletRelativeAction () {
213+ return this .servletRelativeAction ;
214+ }
215+
199216 /**
200217 * Set the value of the '{@code method}' attribute.
201218 * <p>May be a runtime expression.
@@ -403,22 +420,30 @@ protected String resolveModelAttribute() throws JspException {
403420
404421 /**
405422 * Resolve the value of the '{@code action}' attribute.
406- * <p>If the user configured an '{@code action}' value then
407- * the result of evaluating this value is used. Otherwise, the
408- * {@link org.springframework.web.servlet.support.RequestContext#getRequestUri() originating URI}
409- * is used.
423+ * <p>If the user configured an '{@code action}' value then the result of
424+ * evaluating this value is used. If the user configured an
425+ * '{@code servletRelativeAction}' value then the value is prepended
426+ * with the context and servlet paths, and the result is used. Otherwise, the
427+ * {@link org.springframework.web.servlet.support.RequestContext#getRequestUri()
428+ * originating URI} is used.
429+ *
410430 * @return the value that is to be used for the '{@code action}' attribute
411431 */
412432 protected String resolveAction () throws JspException {
413433 String action = getAction ();
434+ String servletRelativeAction = getServletRelativeAction ();
414435 if (StringUtils .hasText (action )) {
415- String pathToServlet = getRequestContext ().getPathToServlet ();
416- if (action .startsWith ("/" ) && !action .startsWith (getRequestContext ().getContextPath ())) {
417- action = pathToServlet + action ;
418- }
419436 action = getDisplayString (evaluate (ACTION_ATTRIBUTE , action ));
420437 return processAction (action );
421438 }
439+ else if (StringUtils .hasText (servletRelativeAction )) {
440+ String pathToServlet = getRequestContext ().getPathToServlet ();
441+ if (servletRelativeAction .startsWith ("/" ) && !servletRelativeAction .startsWith (getRequestContext ().getContextPath ())) {
442+ servletRelativeAction = pathToServlet + servletRelativeAction ;
443+ }
444+ servletRelativeAction = getDisplayString (evaluate (ACTION_ATTRIBUTE , servletRelativeAction ));
445+ return processAction (servletRelativeAction );
446+ }
422447 else {
423448 String requestUri = getRequestContext ().getRequestUri ();
424449 ServletResponse response = this .pageContext .getResponse ();
0 commit comments