Allow configuration of custom redirect patterns

This change enables the ability to configure
ViewNameMethodReturnValueHandler & ModelAndViewMethodReturnValueHandler
with patterns to use to test for a custom redirect view name.

Issue: SPR-12054
master
Rossen Stoyanchev 10 years ago
parent 2a0765e76d
commit 8f715a8547
  1. 46
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandler.java
  2. 33
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandler.java
  3. 23
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandlerTests.java
  4. 45
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandlerTests.java

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@
package org.springframework.web.servlet.mvc.method.annotation;
import org.springframework.core.MethodParameter;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
@ -42,6 +43,32 @@ import org.springframework.web.servlet.View;
*/
public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
private String[] redirectPatterns;
/**
* Configure one more simple patterns (as described in
* {@link org.springframework.util.PatternMatchUtils#simpleMatch}) to use in order to recognize
* custom redirect prefixes in addition to "redirect:".
*
* <p>Note that simply configuring this property will not make a custom
* redirect prefix work. There must be a custom View that recognizes the
* prefix as well.
*
* @since 4.1
*/
public void setRedirectPatterns(String... redirectPatterns) {
this.redirectPatterns = redirectPatterns;
}
/**
* The configured redirect patterns, if any.
*/
public String[] getRedirectPatterns() {
return this.redirectPatterns;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
@ -62,7 +89,7 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
if (mav.isReference()) {
String viewName = mav.getViewName();
mavContainer.setViewName(viewName);
if (viewName != null && viewName.startsWith("redirect:")) {
if (viewName != null && isRedirectViewName(viewName)) {
mavContainer.setRedirectModelScenario(true);
}
}
@ -78,4 +105,19 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
mavContainer.addAllAttributes(mav.getModel());
}
/**
* Whether the given view name is a redirect view reference.
* The default implementation checks the configured redirect patterns and
* also if the view name starts with the "redirect:" prefix.
* @param viewName the view name to check, never {@code null}
* @return "true" if the given view name is recognized as a redirect view
* reference; "false" otherwise.
*/
protected boolean isRedirectViewName(String viewName) {
if (PatternMatchUtils.simpleMatch(this.redirectPatterns, viewName)) {
return true;
}
return viewName.startsWith("redirect:");
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@
package org.springframework.web.servlet.mvc.method.annotation;
import org.springframework.core.MethodParameter;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
@ -40,6 +41,31 @@ import org.springframework.web.servlet.RequestToViewNameTranslator;
*/
public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
private String[] redirectPatterns;
/**
* Configure one more simple patterns (as described in
* {@link PatternMatchUtils#simpleMatch}) to use in order to recognize
* custom redirect prefixes in addition to "redirect:".
*
* <p>Note that simply configuring this property will not make a custom
* redirect prefix work. There must be a custom View that recognizes the
* prefix as well.
*
* @since 4.1
*/
public void setRedirectPatterns(String... redirectPatterns) {
this.redirectPatterns = redirectPatterns;
}
/**
* The configured redirect patterns, if any.
*/
public String[] getRedirectPatterns() {
return this.redirectPatterns;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
Class<?> paramType = returnType.getParameterType();
@ -71,11 +97,16 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
/**
* Whether the given view name is a redirect view reference.
* The default implementation checks the configured redirect patterns and
* also if the view name starts with the "redirect:" prefix.
* @param viewName the view name to check, never {@code null}
* @return "true" if the given view name is recognized as a redirect view
* reference; "false" otherwise.
*/
protected boolean isRedirectViewName(String viewName) {
if (PatternMatchUtils.simpleMatch(this.redirectPatterns, viewName)) {
return true;
}
return viewName.startsWith("redirect:");
}

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -104,7 +104,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
}
@Test
public void handleRedirectAttributesWithViewInstance() throws Exception {
public void handleRedirectAttributesWithViewName() throws Exception {
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
mavContainer.setRedirectModel(redirectAttributes);
@ -114,7 +114,22 @@ public class ModelAndViewMethodReturnValueHandlerTests {
ModelMap model = mavContainer.getModel();
assertEquals("redirect:viewName", mavContainer.getViewName());
assertEquals("attrValue", model.get("attrName"));
assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes, model);
assertSame(redirectAttributes, model);
}
@Test
public void handleRedirectAttributesWithCustomPrefix() throws Exception {
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
mavContainer.setRedirectModel(redirectAttributes);
ModelAndView mav = new ModelAndView("myRedirect:viewName", "attrName", "attrValue");
handler.setRedirectPatterns("myRedirect:*");
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
ModelMap model = mavContainer.getModel();
assertEquals("myRedirect:viewName", mavContainer.getViewName());
assertEquals("attrValue", model.get("attrName"));
assertSame(redirectAttributes, model);
}
@Test
@ -137,10 +152,12 @@ public class ModelAndViewMethodReturnValueHandlerTests {
return new MethodParameter(method, -1);
}
@SuppressWarnings("unused")
ModelAndView modelAndView() {
return null;
}
@SuppressWarnings("unused")
String viewName() {
return null;
}

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
@ -29,7 +28,6 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;
/**
@ -45,23 +43,25 @@ public class ViewNameMethodReturnValueHandlerTests {
private ServletWebRequest webRequest;
private MethodParameter param;
@Before
public void setUp() {
public void setUp() throws NoSuchMethodException {
this.handler = new ViewNameMethodReturnValueHandler();
this.mavContainer = new ModelAndViewContainer();
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
this.param = new MethodParameter(getClass().getDeclaredMethod("viewName"), -1);
}
@Test
public void supportsReturnType() throws Exception {
assertTrue(this.handler.supportsReturnType(createReturnValueParam("viewName")));
assertTrue(this.handler.supportsReturnType(this.param));
}
@Test
public void returnViewName() throws Exception {
MethodParameter param = createReturnValueParam("viewName");
this.handler.handleReturnValue("testView", param, this.mavContainer, this.webRequest);
this.handler.handleReturnValue("testView", this.param, this.mavContainer, this.webRequest);
assertEquals("testView", this.mavContainer.getViewName());
}
@ -69,18 +69,33 @@ public class ViewNameMethodReturnValueHandlerTests {
public void returnViewNameRedirect() throws Exception {
ModelMap redirectModel = new RedirectAttributesModelMap();
this.mavContainer.setRedirectModel(redirectModel);
MethodParameter param = createReturnValueParam("viewName");
this.handler.handleReturnValue("redirect:testView", param, this.mavContainer, this.webRequest);
this.handler.handleReturnValue("redirect:testView", this.param, this.mavContainer, this.webRequest);
assertEquals("redirect:testView", this.mavContainer.getViewName());
assertSame("Should have switched to the RedirectModel", redirectModel, this.mavContainer.getModel());
assertSame(redirectModel, this.mavContainer.getModel());
}
@Test
public void returnViewCustomRedirect() throws Exception {
ModelMap redirectModel = new RedirectAttributesModelMap();
this.mavContainer.setRedirectModel(redirectModel);
this.handler.setRedirectPatterns("myRedirect:*");
this.handler.handleReturnValue("myRedirect:testView", this.param, this.mavContainer, this.webRequest);
assertEquals("myRedirect:testView", this.mavContainer.getViewName());
assertSame(redirectModel, this.mavContainer.getModel());
}
private MethodParameter createReturnValueParam(String methodName) throws Exception {
Method method = getClass().getDeclaredMethod(methodName);
return new MethodParameter(method, -1);
@Test
public void returnViewRedirectWithCustomRedirectPattern() throws Exception {
ModelMap redirectModel = new RedirectAttributesModelMap();
this.mavContainer.setRedirectModel(redirectModel);
this.handler.setRedirectPatterns("myRedirect:*");
this.handler.handleReturnValue("redirect:testView", this.param, this.mavContainer, this.webRequest);
assertEquals("redirect:testView", this.mavContainer.getViewName());
assertSame(redirectModel, this.mavContainer.getModel());
}
@SuppressWarnings("unused")
String viewName() {
return null;
}

Loading…
Cancel
Save