Introduce alias for 'value' attribute in @SessionAttributes

Issue: SPR-11393
This commit is contained in:
Sam Brannen 2015-05-31 17:21:03 +02:00
parent 6a5b2672e7
commit 9ce7485237
6 changed files with 43 additions and 35 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,11 +23,14 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/** /**
* Annotation that indicates the session attributes that a specific handler * Annotation that indicates the session attributes that a specific handler uses.
* uses. This will typically list the names of model attributes which should be *
* <p>This will typically list the names of model attributes which should be
* transparently stored in the session or some conversational storage, * transparently stored in the session or some conversational storage,
* serving as form-backing beans. <b>Declared at the type level,</b> applying * serving as form-backing beans. <b>Declared at the type level</b>, applying
* to the model attributes that the annotated handler class operates on. * to the model attributes that the annotated handler class operates on.
* *
* <p><b>NOTE:</b> Session attributes as indicated using this annotation * <p><b>NOTE:</b> Session attributes as indicated using this annotation
@ -44,11 +47,12 @@ import java.lang.annotation.Target;
* generic {@link org.springframework.web.context.request.WebRequest} interface. * generic {@link org.springframework.web.context.request.WebRequest} interface.
* *
* <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying), * <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying),
* make sure to consistently put <i>all</i> your mapping annotations - such as * make sure to consistently put <i>all</i> your mapping annotations &mdash;
* {@code @RequestMapping} and {@code @SessionAttributes} - on * such as {@code @RequestMapping} and {@code @SessionAttributes} &mdash; on
* the controller <i>interface</i> rather than on the implementation class. * the controller <i>interface</i> rather than on the implementation class.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen
* @since 2.5 * @since 2.5
*/ */
@Target({ElementType.TYPE}) @Target({ElementType.TYPE})
@ -58,18 +62,28 @@ import java.lang.annotation.Target;
public @interface SessionAttributes { public @interface SessionAttributes {
/** /**
* The names of session attributes in the model, to be stored in the * Alias for {@link #names}.
* session or some conversational storage.
* <p>Note: This indicates the model attribute names. The session attribute
* names may or may not match the model attribute names; applications should
* not rely on the session attribute names but rather operate on the model only.
*/ */
@AliasFor(attribute = "names")
String[] value() default {}; String[] value() default {};
/** /**
* The types of session attributes in the model, to be stored in the * The names of session attributes in the model that should be stored in the
* session or some conversational storage. All model attributes of this * session or some conversational storage.
* type will be stored in the session, regardless of attribute name. * <p><strong>Note</strong>: This indicates the <em>model attribute names</em>.
* The <em>session attribute names</em> may or may not match the model attribute
* names. Applications should therefore not rely on the session attribute
* names but rather operate on the model only.
* @since 4.2
*/
@AliasFor(attribute = "value")
String[] names() default {};
/**
* The types of session attributes in the model that should be stored in the
* session or some conversational storage.
* <p>All model attributes of these types will be stored in the session,
* regardless of attribute name.
*/ */
Class<?>[] types() default {}; Class<?>[] types() default {};

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -107,7 +107,7 @@ public class HandlerMethodResolver {
SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class); SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class);
this.sessionAttributesFound = (sessionAttributes != null); this.sessionAttributesFound = (sessionAttributes != null);
if (this.sessionAttributesFound) { if (this.sessionAttributesFound) {
this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.value())); this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.names()));
this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types())); this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types()));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -70,8 +70,8 @@ public class SessionAttributesHandler {
SessionAttributes annotation = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class); SessionAttributes annotation = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class);
if (annotation != null) { if (annotation != null) {
this.attributeNames.addAll(Arrays.asList(annotation.value())); this.attributeNames.addAll(Arrays.asList(annotation.names()));
this.attributeTypes.addAll(Arrays.<Class<?>>asList(annotation.types())); this.attributeTypes.addAll(Arrays.asList(annotation.types()));
} }
for (String attributeName : this.attributeNames) { for (String attributeName : this.attributeNames) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,9 +16,9 @@
package org.springframework.web.method.annotation; package org.springframework.web.method.annotation;
import java.util.HashSet; import java.util.HashSet;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletRequest;
@ -40,20 +40,13 @@ import static org.junit.Assert.*;
*/ */
public class SessionAttributesHandlerTests { public class SessionAttributesHandlerTests {
private Class<?> handlerType = SessionAttributeHandler.class; private final SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
private SessionAttributesHandler sessionAttributesHandler; private final SessionAttributesHandler sessionAttributesHandler = new SessionAttributesHandler(
SessionAttributeHandler.class, sessionAttributeStore);
private SessionAttributeStore sessionAttributeStore; private final NativeWebRequest request = new ServletWebRequest(new MockHttpServletRequest());
private NativeWebRequest request;
@Before
public void setUp() {
this.sessionAttributeStore = new DefaultSessionAttributeStore();
this.sessionAttributesHandler = new SessionAttributesHandler(handlerType, sessionAttributeStore);
this.request = new ServletWebRequest(new MockHttpServletRequest());
}
@Test @Test
public void isSessionAttribute() throws Exception { public void isSessionAttribute() throws Exception {
@ -115,7 +108,8 @@ public class SessionAttributesHandlerTests {
assertTrue(sessionAttributeStore.retrieveAttribute(request, "attr3") instanceof TestBean); assertTrue(sessionAttributeStore.retrieveAttribute(request, "attr3") instanceof TestBean);
} }
@SessionAttributes(value = { "attr1", "attr2" }, types = { TestBean.class })
@SessionAttributes(names = { "attr1", "attr2" }, types = { TestBean.class })
private static class SessionAttributeHandler { private static class SessionAttributeHandler {
} }

View File

@ -2163,7 +2163,7 @@ public class ServletAnnotationControllerTests {
@Controller @Controller
@RequestMapping("/myPage") @RequestMapping("/myPage")
@SessionAttributes({"object1", "object2"}) @SessionAttributes(names = { "object1", "object2" })
public static class MySessionAttributesController { public static class MySessionAttributesController {
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)

View File

@ -1774,7 +1774,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Controller @Controller
@RequestMapping("/myPage") @RequestMapping("/myPage")
@SessionAttributes({"object1", "object2"}) @SessionAttributes(names = { "object1", "object2" })
public static class MySessionAttributesController { public static class MySessionAttributesController {
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)