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.ObjectUtils;
|
||||
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.HandlerMapping;
|
||||
import org.springframework.web.servlet.SmartView;
|
||||
|
|
@ -250,13 +252,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
|||
|
||||
String targetUrl = createTargetUrl(model, request);
|
||||
|
||||
if (getWebApplicationContext() != null) {
|
||||
RequestContext requestContext = createRequestContext(request, response, model);
|
||||
RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
|
||||
if (processor != null) {
|
||||
targetUrl = processor.processUrl(request, targetUrl);
|
||||
}
|
||||
}
|
||||
targetUrl = updateTargetUrl(targetUrl, model, request, response);
|
||||
|
||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
||||
if (!CollectionUtils.isEmpty(flashMap)) {
|
||||
|
|
@ -489,6 +485,35 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
|||
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
|
||||
* @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.
|
||||
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
|
||||
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.
|
||||
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
|
||||
|
|
@ -433,10 +434,14 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
|||
@Override
|
||||
protected View loadView(String viewName, Locale locale) throws Exception {
|
||||
AbstractUrlBasedView view = buildView(viewName);
|
||||
View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
|
||||
View result = applyLifecycleMethods(viewName, view);
|
||||
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.
|
||||
* Does <i>not</i> perform any lookup for pre-defined View instances.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.tags.form;
|
||||
package org.springframework.web.servlet.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
class DelegatingRequestDataValueProcessor implements RequestDataValueProcessor {
|
||||
public class RequestDataValueProcessorWrapper implements RequestDataValueProcessor {
|
||||
|
||||
private RequestDataValueProcessor processor;
|
||||
|
||||
|
|
@ -32,6 +32,7 @@ import org.springframework.mock.web.MockPageContext;
|
|||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
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.RequestContext;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
|
|
@ -66,7 +67,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
|
|||
MockPageContext pageContext = createPageContext();
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) pageContext.getRequest();
|
||||
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
||||
wac.registerSingleton("requestDataValueProcessor", DelegatingRequestDataValueProcessor.class);
|
||||
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
|
||||
extendRequest(request);
|
||||
extendPageContext(pageContext);
|
||||
RequestContext requestContext = new JspAwareRequestContext(pageContext);
|
||||
|
|
@ -103,7 +104,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
|
|||
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
|
||||
ServletRequest request = getPageContext().getRequest();
|
||||
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
|
||||
wac.getBean(DelegatingRequestDataValueProcessor.class).setRequestDataValueProcessor(mockProcessor);
|
||||
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
|
||||
return mockProcessor;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,16 @@
|
|||
|
||||
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.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -28,7 +38,6 @@ import java.util.Set;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
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.ViewResolver;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
|
|
@ -418,8 +424,14 @@ public class ContentNegotiatingViewResolverTests {
|
|||
request.addHeader("Accept", "application/json");
|
||||
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.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, new UrlBasedViewResolver()));
|
||||
viewResolver.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, urlViewResolver));
|
||||
|
||||
View xmlView = createMock("application_xml", View.class);
|
||||
View jsonView = createMock("application_json", View.class);
|
||||
|
|
@ -491,15 +503,14 @@ public class ContentNegotiatingViewResolverTests {
|
|||
|
||||
@Test
|
||||
public void nestedViewResolverIsNotSpringBean() throws Exception {
|
||||
StaticWebApplicationContext webAppContext = new StaticWebApplicationContext();
|
||||
webAppContext.setServletContext(new MockServletContext());
|
||||
webAppContext.refresh();
|
||||
|
||||
InternalResourceViewResolver nestedResolver = new InternalResourceViewResolver();
|
||||
nestedResolver.setApplicationContext(webAppContext);
|
||||
nestedResolver.setViewClass(InternalResourceView.class);
|
||||
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);
|
||||
|
||||
String viewName = "view";
|
||||
|
|
|
|||
|
|
@ -34,15 +34,22 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
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.FlashMapManager;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
@ -118,8 +125,8 @@ public class RedirectViewTests {
|
|||
RedirectView rv = new RedirectView();
|
||||
rv.setUrl("http://url.somewhere.com/path");
|
||||
rv.setHttp10Compatible(false);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
HttpServletResponse response = new MockHttpServletResponse();
|
||||
FlashMap flashMap = new FlashMap();
|
||||
flashMap.put("successMessage", "yay!");
|
||||
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||
|
|
@ -131,6 +138,64 @@ public class RedirectViewTests {
|
|||
assertEquals("/path", flashMap.getTargetRequestPath());
|
||||
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
|
||||
public void emptyMap() throws Exception {
|
||||
|
|
@ -296,7 +361,7 @@ public class RedirectViewTests {
|
|||
expectedUrlForEncoding = "/context" + expectedUrlForEncoding;
|
||||
expect(request.getContextPath()).andReturn("/context");
|
||||
}
|
||||
|
||||
|
||||
HttpServletResponse response = createMock("response", HttpServletResponse.class);
|
||||
expect(response.encodeRedirectURL(expectedUrlForEncoding)).andReturn(expectedUrlForEncoding);
|
||||
response.sendRedirect(expectedUrlForEncoding);
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ public class ViewResolverTests {
|
|||
view = vr.resolveViewName("redirect:myUrl", Locale.getDefault());
|
||||
assertEquals("Correct view class", RedirectView.class, view.getClass());
|
||||
assertEquals("Correct URL", "myUrl", ((RedirectView) view).getUrl());
|
||||
assertSame("View not initialized as bean", wac, ((RedirectView) view).getApplicationContext());
|
||||
|
||||
view = vr.resolveViewName("forward:myUrl", Locale.getDefault());
|
||||
assertEquals("Correct view class", InternalResourceView.class, view.getClass());
|
||||
|
|
|
|||
Loading…
Reference in New Issue