SPR-8770 Ensure RequestDataValueProcessor is invoked from RedirectView.
This commit is contained in:
parent
2980ef4c75
commit
fd97c8d7a4
|
|
@ -38,6 +38,8 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.context.ContextLoader;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.servlet.FlashMap;
|
import org.springframework.web.servlet.FlashMap;
|
||||||
import org.springframework.web.servlet.HandlerMapping;
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
import org.springframework.web.servlet.SmartView;
|
import org.springframework.web.servlet.SmartView;
|
||||||
|
|
@ -250,13 +252,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
||||||
|
|
||||||
String targetUrl = createTargetUrl(model, request);
|
String targetUrl = createTargetUrl(model, request);
|
||||||
|
|
||||||
if (getWebApplicationContext() != null) {
|
targetUrl = updateTargetUrl(targetUrl, model, request, response);
|
||||||
RequestContext requestContext = createRequestContext(request, response, model);
|
|
||||||
RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
|
|
||||||
if (processor != null) {
|
|
||||||
targetUrl = processor.processUrl(request, targetUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
||||||
if (!CollectionUtils.isEmpty(flashMap)) {
|
if (!CollectionUtils.isEmpty(flashMap)) {
|
||||||
|
|
@ -489,6 +485,35 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
||||||
return (input != null ? URLEncoder.encode(input, encodingScheme) : null);
|
return (input != null ? URLEncoder.encode(input, encodingScheme) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the registered {@link RequestDataValueProcessor}, if any, and allow
|
||||||
|
* it to update the redirect target URL.
|
||||||
|
* @return the updated URL or the same as URL as the one passed in
|
||||||
|
*/
|
||||||
|
protected String updateTargetUrl(String targetUrl, Map<String, Object> model,
|
||||||
|
HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
|
||||||
|
RequestContext requestContext = null;
|
||||||
|
if (getWebApplicationContext() != null) {
|
||||||
|
requestContext = createRequestContext(request, response, model);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
|
||||||
|
if (wac != null && wac.getServletContext() != null) {
|
||||||
|
requestContext = new RequestContext(request, response, wac.getServletContext(), model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestContext != null) {
|
||||||
|
RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
|
||||||
|
if (processor != null) {
|
||||||
|
targetUrl = processor.processUrl(request, targetUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetUrl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a redirect back to the HTTP client
|
* Send a redirect back to the HTTP client
|
||||||
* @param request current HTTP request (allows for reacting to request method)
|
* @param request current HTTP request (allows for reacting to request method)
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,8 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
||||||
// Check for special "redirect:" prefix.
|
// Check for special "redirect:" prefix.
|
||||||
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
|
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
|
||||||
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
|
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
|
||||||
return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
|
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
|
||||||
|
return applyLifecycleMethods(viewName, view);
|
||||||
}
|
}
|
||||||
// Check for special "forward:" prefix.
|
// Check for special "forward:" prefix.
|
||||||
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
|
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
|
||||||
|
|
@ -433,10 +434,14 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
||||||
@Override
|
@Override
|
||||||
protected View loadView(String viewName, Locale locale) throws Exception {
|
protected View loadView(String viewName, Locale locale) throws Exception {
|
||||||
AbstractUrlBasedView view = buildView(viewName);
|
AbstractUrlBasedView view = buildView(viewName);
|
||||||
View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
|
View result = applyLifecycleMethods(viewName, view);
|
||||||
return (view.checkResource(locale) ? result : null);
|
return (view.checkResource(locale) ? result : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View applyLifecycleMethods(String viewName, AbstractView view) {
|
||||||
|
return (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new View instance of the specified view class and configures it.
|
* Creates a new View instance of the specified view class and configures it.
|
||||||
* Does <i>not</i> perform any lookup for pre-defined View instances.
|
* Does <i>not</i> perform any lookup for pre-defined View instances.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.servlet.tags.form;
|
package org.springframework.web.servlet.support;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||||
|
|
||||||
class DelegatingRequestDataValueProcessor implements RequestDataValueProcessor {
|
public class RequestDataValueProcessorWrapper implements RequestDataValueProcessor {
|
||||||
|
|
||||||
private RequestDataValueProcessor processor;
|
private RequestDataValueProcessor processor;
|
||||||
|
|
||||||
|
|
@ -32,6 +32,7 @@ import org.springframework.mock.web.MockPageContext;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||||
|
import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper;
|
||||||
import org.springframework.web.servlet.support.JspAwareRequestContext;
|
import org.springframework.web.servlet.support.JspAwareRequestContext;
|
||||||
import org.springframework.web.servlet.support.RequestContext;
|
import org.springframework.web.servlet.support.RequestContext;
|
||||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||||
|
|
@ -66,7 +67,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
|
||||||
MockPageContext pageContext = createPageContext();
|
MockPageContext pageContext = createPageContext();
|
||||||
MockHttpServletRequest request = (MockHttpServletRequest) pageContext.getRequest();
|
MockHttpServletRequest request = (MockHttpServletRequest) pageContext.getRequest();
|
||||||
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
||||||
wac.registerSingleton("requestDataValueProcessor", DelegatingRequestDataValueProcessor.class);
|
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
|
||||||
extendRequest(request);
|
extendRequest(request);
|
||||||
extendPageContext(pageContext);
|
extendPageContext(pageContext);
|
||||||
RequestContext requestContext = new JspAwareRequestContext(pageContext);
|
RequestContext requestContext = new JspAwareRequestContext(pageContext);
|
||||||
|
|
@ -103,7 +104,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
|
||||||
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
|
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
|
||||||
ServletRequest request = getPageContext().getRequest();
|
ServletRequest request = getPageContext().getRequest();
|
||||||
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
||||||
wac.getBean(DelegatingRequestDataValueProcessor.class).setRequestDataValueProcessor(mockProcessor);
|
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
|
||||||
return mockProcessor;
|
return mockProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,16 @@
|
||||||
|
|
||||||
package org.springframework.web.servlet.view;
|
package org.springframework.web.servlet.view;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.replay;
|
||||||
|
import static org.easymock.EasyMock.verify;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -28,7 +38,6 @@ import java.util.Set;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
|
@ -40,9 +49,6 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
import org.springframework.web.servlet.ViewResolver;
|
import org.springframework.web.servlet.ViewResolver;
|
||||||
|
|
||||||
import static org.easymock.EasyMock.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
*/
|
*/
|
||||||
|
|
@ -418,8 +424,14 @@ public class ContentNegotiatingViewResolverTests {
|
||||||
request.addHeader("Accept", "application/json");
|
request.addHeader("Accept", "application/json");
|
||||||
request.setRequestURI("/test");
|
request.setRequestURI("/test");
|
||||||
|
|
||||||
|
StaticWebApplicationContext webAppContext = new StaticWebApplicationContext();
|
||||||
|
webAppContext.setServletContext(new MockServletContext());
|
||||||
|
webAppContext.refresh();
|
||||||
|
|
||||||
|
UrlBasedViewResolver urlViewResolver = new InternalResourceViewResolver();
|
||||||
|
urlViewResolver.setApplicationContext(webAppContext);
|
||||||
ViewResolver xmlViewResolver = createMock(ViewResolver.class);
|
ViewResolver xmlViewResolver = createMock(ViewResolver.class);
|
||||||
viewResolver.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, new UrlBasedViewResolver()));
|
viewResolver.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, urlViewResolver));
|
||||||
|
|
||||||
View xmlView = createMock("application_xml", View.class);
|
View xmlView = createMock("application_xml", View.class);
|
||||||
View jsonView = createMock("application_json", View.class);
|
View jsonView = createMock("application_json", View.class);
|
||||||
|
|
@ -491,15 +503,14 @@ public class ContentNegotiatingViewResolverTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nestedViewResolverIsNotSpringBean() throws Exception {
|
public void nestedViewResolverIsNotSpringBean() throws Exception {
|
||||||
|
StaticWebApplicationContext webAppContext = new StaticWebApplicationContext();
|
||||||
|
webAppContext.setServletContext(new MockServletContext());
|
||||||
|
webAppContext.refresh();
|
||||||
|
|
||||||
InternalResourceViewResolver nestedResolver = new InternalResourceViewResolver();
|
InternalResourceViewResolver nestedResolver = new InternalResourceViewResolver();
|
||||||
|
nestedResolver.setApplicationContext(webAppContext);
|
||||||
nestedResolver.setViewClass(InternalResourceView.class);
|
nestedResolver.setViewClass(InternalResourceView.class);
|
||||||
viewResolver.setViewResolvers(new ArrayList<ViewResolver>(Arrays.asList(nestedResolver)));
|
viewResolver.setViewResolvers(new ArrayList<ViewResolver>(Arrays.asList(nestedResolver)));
|
||||||
|
|
||||||
StaticWebApplicationContext appContext = new StaticWebApplicationContext();
|
|
||||||
appContext.setServletContext(new MockServletContext());
|
|
||||||
appContext.refresh();
|
|
||||||
viewResolver.setApplicationContext(appContext);
|
|
||||||
|
|
||||||
viewResolver.setDefaultContentType(MediaType.TEXT_HTML);
|
viewResolver.setDefaultContentType(MediaType.TEXT_HTML);
|
||||||
|
|
||||||
String viewName = "view";
|
String viewName = "view";
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,22 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
|
import org.easymock.EasyMock;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.TestBean;
|
import org.springframework.beans.TestBean;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.context.ContextLoader;
|
||||||
|
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||||
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
import org.springframework.web.servlet.FlashMap;
|
import org.springframework.web.servlet.FlashMap;
|
||||||
import org.springframework.web.servlet.FlashMapManager;
|
import org.springframework.web.servlet.FlashMapManager;
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
|
import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper;
|
||||||
|
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -118,8 +125,8 @@ public class RedirectViewTests {
|
||||||
RedirectView rv = new RedirectView();
|
RedirectView rv = new RedirectView();
|
||||||
rv.setUrl("http://url.somewhere.com/path");
|
rv.setUrl("http://url.somewhere.com/path");
|
||||||
rv.setHttp10Compatible(false);
|
rv.setHttp10Compatible(false);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
HttpServletResponse response = new MockHttpServletResponse();
|
||||||
FlashMap flashMap = new FlashMap();
|
FlashMap flashMap = new FlashMap();
|
||||||
flashMap.put("successMessage", "yay!");
|
flashMap.put("successMessage", "yay!");
|
||||||
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||||
|
|
@ -132,6 +139,64 @@ public class RedirectViewTests {
|
||||||
assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap());
|
assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateTargetUrl() throws Exception {
|
||||||
|
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||||
|
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
|
||||||
|
wac.setServletContext(new MockServletContext());
|
||||||
|
wac.refresh();
|
||||||
|
|
||||||
|
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
|
||||||
|
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
|
||||||
|
|
||||||
|
RedirectView rv = new RedirectView();
|
||||||
|
rv.setApplicationContext(wac); // Init RedirectView with WebAppCxt
|
||||||
|
rv.setUrl("/path");
|
||||||
|
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||||
|
HttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123");
|
||||||
|
EasyMock.replay(mockProcessor);
|
||||||
|
|
||||||
|
rv.render(new ModelMap(), request, response);
|
||||||
|
|
||||||
|
EasyMock.verify(mockProcessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateTargetUrlWithContextLoader() throws Exception {
|
||||||
|
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||||
|
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
|
||||||
|
|
||||||
|
MockServletContext servletContext = new MockServletContext();
|
||||||
|
ContextLoader contextLoader = new ContextLoader(wac);
|
||||||
|
contextLoader.initWebApplicationContext(servletContext);
|
||||||
|
|
||||||
|
try {
|
||||||
|
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
|
||||||
|
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
|
||||||
|
|
||||||
|
RedirectView rv = new RedirectView();
|
||||||
|
rv.setUrl("/path");
|
||||||
|
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
HttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123");
|
||||||
|
EasyMock.replay(mockProcessor);
|
||||||
|
|
||||||
|
rv.render(new ModelMap(), request, response);
|
||||||
|
|
||||||
|
EasyMock.verify(mockProcessor);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
contextLoader.closeWebApplicationContext(servletContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptyMap() throws Exception {
|
public void emptyMap() throws Exception {
|
||||||
String url = "/myUrl";
|
String url = "/myUrl";
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ public class ViewResolverTests {
|
||||||
view = vr.resolveViewName("redirect:myUrl", Locale.getDefault());
|
view = vr.resolveViewName("redirect:myUrl", Locale.getDefault());
|
||||||
assertEquals("Correct view class", RedirectView.class, view.getClass());
|
assertEquals("Correct view class", RedirectView.class, view.getClass());
|
||||||
assertEquals("Correct URL", "myUrl", ((RedirectView) view).getUrl());
|
assertEquals("Correct URL", "myUrl", ((RedirectView) view).getUrl());
|
||||||
|
assertSame("View not initialized as bean", wac, ((RedirectView) view).getApplicationContext());
|
||||||
|
|
||||||
view = vr.resolveViewName("forward:myUrl", Locale.getDefault());
|
view = vr.resolveViewName("forward:myUrl", Locale.getDefault());
|
||||||
assertEquals("Correct view class", InternalResourceView.class, view.getClass());
|
assertEquals("Correct view class", InternalResourceView.class, view.getClass());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue