diff --git a/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java b/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java index f641c3e581b74904a219f180c66e566b6431c58b..325b23720a7a42dc023a0705b2ca1f09fce4b837 100644 --- a/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java +++ b/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java @@ -57,8 +57,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria return parseCacheAnnotations(defaultConfig, method); } - protected Collection parseCacheAnnotations(DefaultCacheConfig cachingConfig, - AnnotatedElement ae) { + protected Collection parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) { Collection ops = null; Collection cacheables = getAnnotations(ae, Cacheable.class); @@ -71,24 +70,25 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria Collection evicts = getAnnotations(ae, CacheEvict.class); if (evicts != null) { ops = lazyInit(ops); - for (CacheEvict e : evicts) { - ops.add(parseEvictAnnotation(ae, cachingConfig, e)); + for (CacheEvict evict : evicts) { + ops.add(parseEvictAnnotation(ae, cachingConfig, evict)); } } - Collection updates = getAnnotations(ae, CachePut.class); - if (updates != null) { + Collection puts = getAnnotations(ae, CachePut.class); + if (puts != null) { ops = lazyInit(ops); - for (CachePut p : updates) { - ops.add(parseUpdateAnnotation(ae, cachingConfig, p)); + for (CachePut put : puts) { + ops.add(parsePutAnnotation(ae, cachingConfig, put)); } } - Collection caching = getAnnotations(ae, Caching.class); - if (caching != null) { + Collection cachings = getAnnotations(ae, Caching.class); + if (cachings != null) { ops = lazyInit(ops); - for (Caching c : caching) { - ops.addAll(parseCachingAnnotation(ae, cachingConfig, c)); + for (Caching caching : cachings) { + ops.addAll(parseCachingAnnotation(ae, cachingConfig, caching)); } } + return ops; } @@ -96,63 +96,62 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria return (ops != null ? ops : new ArrayList(1)); } - CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, - DefaultCacheConfig defaultConfig, Cacheable caching) { - CacheableOperation cuo = new CacheableOperation(); - cuo.setCacheNames(caching.value()); - cuo.setCondition(caching.condition()); - cuo.setUnless(caching.unless()); - cuo.setKey(caching.key()); - cuo.setKeyGenerator(caching.keyGenerator()); - cuo.setCacheManager(caching.cacheManager()); - cuo.setCacheResolver(caching.cacheResolver()); - cuo.setName(ae.toString()); - - defaultConfig.applyDefault(cuo); - - validateCacheOperation(ae, cuo); - return cuo; + CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Cacheable caching) { + CacheableOperation op = new CacheableOperation(); + + op.setCacheNames(caching.value()); + op.setCondition(caching.condition()); + op.setUnless(caching.unless()); + op.setKey(caching.key()); + op.setKeyGenerator(caching.keyGenerator()); + op.setCacheManager(caching.cacheManager()); + op.setCacheResolver(caching.cacheResolver()); + op.setName(ae.toString()); + + defaultConfig.applyDefault(op); + validateCacheOperation(ae, op); + + return op; } - CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, - DefaultCacheConfig defaultConfig, CacheEvict caching) { - CacheEvictOperation ceo = new CacheEvictOperation(); - ceo.setCacheNames(caching.value()); - ceo.setCondition(caching.condition()); - ceo.setKey(caching.key()); - ceo.setKeyGenerator(caching.keyGenerator()); - ceo.setCacheManager(caching.cacheManager()); - ceo.setCacheResolver(caching.cacheResolver()); - ceo.setCacheWide(caching.allEntries()); - ceo.setBeforeInvocation(caching.beforeInvocation()); - ceo.setName(ae.toString()); - - defaultConfig.applyDefault(ceo); - - validateCacheOperation(ae, ceo); - return ceo; + CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, CacheEvict caching) { + CacheEvictOperation op = new CacheEvictOperation(); + + op.setCacheNames(caching.value()); + op.setCondition(caching.condition()); + op.setKey(caching.key()); + op.setKeyGenerator(caching.keyGenerator()); + op.setCacheManager(caching.cacheManager()); + op.setCacheResolver(caching.cacheResolver()); + op.setCacheWide(caching.allEntries()); + op.setBeforeInvocation(caching.beforeInvocation()); + op.setName(ae.toString()); + + defaultConfig.applyDefault(op); + validateCacheOperation(ae, op); + + return op; } - CacheOperation parseUpdateAnnotation(AnnotatedElement ae, - DefaultCacheConfig defaultConfig, CachePut caching) { - CachePutOperation cuo = new CachePutOperation(); - cuo.setCacheNames(caching.value()); - cuo.setCondition(caching.condition()); - cuo.setUnless(caching.unless()); - cuo.setKey(caching.key()); - cuo.setKeyGenerator(caching.keyGenerator()); - cuo.setCacheManager(caching.cacheManager()); - cuo.setCacheResolver(caching.cacheResolver()); - cuo.setName(ae.toString()); - - defaultConfig.applyDefault(cuo); - - validateCacheOperation(ae, cuo); - return cuo; + CacheOperation parsePutAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, CachePut caching) { + CachePutOperation op = new CachePutOperation(); + + op.setCacheNames(caching.value()); + op.setCondition(caching.condition()); + op.setUnless(caching.unless()); + op.setKey(caching.key()); + op.setKeyGenerator(caching.keyGenerator()); + op.setCacheManager(caching.cacheManager()); + op.setCacheResolver(caching.cacheResolver()); + op.setName(ae.toString()); + + defaultConfig.applyDefault(op); + validateCacheOperation(ae, op); + + return op; } - Collection parseCachingAnnotation(AnnotatedElement ae, - DefaultCacheConfig defaultConfig, Caching caching) { + Collection parseCachingAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Caching caching) { Collection ops = null; Cacheable[] cacheables = caching.cacheable(); @@ -173,7 +172,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria if (!ObjectUtils.isEmpty(updates)) { ops = lazyInit(ops); for (CachePut update : updates) { - ops.add(parseUpdateAnnotation(ae, defaultConfig, update)); + ops.add(parsePutAnnotation(ae, defaultConfig, update)); } } @@ -182,12 +181,11 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria /** * Provides the {@link DefaultCacheConfig} instance for the specified {@link Class}. - * * @param target the class-level to handle * @return the default config (never {@code null}) */ DefaultCacheConfig getDefaultCacheConfig(Class target) { - final CacheConfig annotation = AnnotationUtils.getAnnotation(target, CacheConfig.class); + CacheConfig annotation = AnnotationUtils.getAnnotation(target, CacheConfig.class); if (annotation != null) { return new DefaultCacheConfig(annotation.cacheNames(), annotation.keyGenerator(), annotation.cacheManager(), annotation.cacheResolver()); @@ -220,27 +218,26 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria *

Throws an {@link IllegalStateException} if the state of the operation is * invalid. As there might be multiple sources for default values, this ensure * that the operation is in a proper state before being returned. - * * @param ae the annotated element of the cache operation * @param operation the {@link CacheOperation} to validate */ private void validateCacheOperation(AnnotatedElement ae, CacheOperation operation) { if (StringUtils.hasText(operation.getKey()) && StringUtils.hasText(operation.getKeyGenerator())) { - throw new IllegalStateException("Invalid cache annotation configuration on '" - + ae.toString() + "'. Both 'key' and 'keyGenerator' attributes have been set. " + + throw new IllegalStateException("Invalid cache annotation configuration on '" + + ae.toString() + "'. Both 'key' and 'keyGenerator' attributes have been set. " + "These attributes are mutually exclusive: either set the SpEL expression used to" + "compute the key at runtime or set the name of the KeyGenerator bean to use."); } if (StringUtils.hasText(operation.getCacheManager()) && StringUtils.hasText(operation.getCacheResolver())) { - throw new IllegalStateException("Invalid cache annotation configuration on '" - + ae.toString() + "'. Both 'cacheManager' and 'cacheResolver' attributes have been set. " + + throw new IllegalStateException("Invalid cache annotation configuration on '" + + ae.toString() + "'. Both 'cacheManager' and 'cacheResolver' attributes have been set. " + "These attributes are mutually exclusive: the cache manager is used to configure a" + "default cache resolver if none is set. If a cache resolver is set, the cache manager" + "won't be used."); } if (operation.getCacheNames().isEmpty()) { - throw new IllegalStateException("No cache names could be detected on '" - + ae.toString() + "'. Make sure to set the value parameter on the annotation or " + + throw new IllegalStateException("No cache names could be detected on '" + + ae.toString() + "'. Make sure to set the value parameter on the annotation or " + "declare a @CacheConfig at the class-level with the default cache name(s) to use."); } } @@ -260,6 +257,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria * Provides default settings for a given set of cache operations. */ static class DefaultCacheConfig { + private final String[] cacheNames; private final String keyGenerator; @@ -268,47 +266,41 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria private final String cacheResolver; - private DefaultCacheConfig(String[] cacheNames, String keyGenerator, - String cacheManager, String cacheResolver) { + public DefaultCacheConfig() { + this(null, null, null, null); + } + + private DefaultCacheConfig(String[] cacheNames, String keyGenerator, String cacheManager, String cacheResolver) { this.cacheNames = cacheNames; this.keyGenerator = keyGenerator; this.cacheManager = cacheManager; this.cacheResolver = cacheResolver; } - public DefaultCacheConfig() { - this(null, null, null, null); - } - /** * Apply the defaults to the specified {@link CacheOperation}. - * * @param operation the operation to update */ public void applyDefault(CacheOperation operation) { - if (operation.getCacheNames().isEmpty() && cacheNames != null) { - operation.setCacheNames(cacheNames); + if (operation.getCacheNames().isEmpty() && this.cacheNames != null) { + operation.setCacheNames(this.cacheNames); } - if (!StringUtils.hasText(operation.getKey()) && !StringUtils.hasText(operation.getKeyGenerator()) - && StringUtils.hasText(keyGenerator)) { - operation.setKeyGenerator(keyGenerator); + if (!StringUtils.hasText(operation.getKey()) && !StringUtils.hasText(operation.getKeyGenerator()) && + StringUtils.hasText(this.keyGenerator)) { + operation.setKeyGenerator(this.keyGenerator); } - if (isSet(operation.getCacheManager()) || isSet(operation.getCacheResolver())) { + if (StringUtils.hasText(operation.getCacheManager()) || StringUtils.hasText(operation.getCacheResolver())) { // One of these is set so we should not inherit anything } - else if (isSet(cacheResolver)) { - operation.setCacheResolver(cacheResolver); + else if (StringUtils.hasText(this.cacheResolver)) { + operation.setCacheResolver(this.cacheResolver); } - else if (isSet(cacheManager)) { - operation.setCacheManager(cacheManager); + else if (StringUtils.hasText(this.cacheManager)) { + operation.setCacheManager(this.cacheManager); } } - private boolean isSet(String s) { - return StringUtils.hasText(s); - } - } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java index 6020f58da019c41aa6f221f3b8aafc267db9383f..cf54d3d677337ce459a45669061137b48c233336 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java @@ -227,7 +227,7 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement } /** - * Whether to add path variables in the model or not. + * Specify whether to add path variables to the model or not. *

Path variables are commonly bound to URI template variables through the {@code @PathVariable} * annotation. They're are effectively URI template variables with type conversion applied to * them to derive typed Object values. Such values are frequently needed in views for @@ -235,14 +235,14 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement *

Path variables added to the model override static attributes (see {@link #setAttributes(Properties)}) * but not attributes already present in the model. *

By default this flag is set to {@code true}. Concrete view types can override this. - * @param exposePathVariables {@code true} to expose path variables, and {@code false} otherwise. + * @param exposePathVariables {@code true} to expose path variables, and {@code false} otherwise */ public void setExposePathVariables(boolean exposePathVariables) { this.exposePathVariables = exposePathVariables; } /** - * Returns the value of the flag indicating whether path variables should be added to the model or not. + * Return whether to add path variables to the model or not. */ public boolean isExposePathVariables() { return this.exposePathVariables; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.java index 580536ca539b6e5eb7d8ed8e7ab2e73cdb599302..7139a74ea4e1b2a24cda167d02f4d648863e25b1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.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. @@ -141,7 +141,7 @@ public class InternalResourceView extends AbstractUrlBasedView { * the {@link #setExposeContextBeansAsAttributes "exposeContextBeansAsAttributes"} * flag on but do not list specific bean names for this property. */ - public void setExposedContextBeanNames(String[] exposedContextBeanNames) { + public void setExposedContextBeanNames(String... exposedContextBeanNames) { this.exposedContextBeanNames = new HashSet(Arrays.asList(exposedContextBeanNames)); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java index b25ba680a53d5c39b0caa40d4bd49c05afd78e05..e1866649a725e50be42610dea43d63b19aa13360 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java @@ -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. @@ -70,6 +70,7 @@ public class InternalResourceViewResolver extends UrlBasedViewResolver { setViewClass(viewClass); } + /** * This resolver requires {@link InternalResourceView}. */ @@ -78,7 +79,6 @@ public class InternalResourceViewResolver extends UrlBasedViewResolver { return InternalResourceView.class; } - /** * Specify whether to always include the view rather than forward to it. *

Default is "false". Switch this flag on to enforce the use of a @@ -86,7 +86,7 @@ public class InternalResourceViewResolver extends UrlBasedViewResolver { * @see InternalResourceView#setAlwaysInclude */ public void setAlwaysInclude(boolean alwaysInclude) { - this.alwaysInclude = Boolean.valueOf(alwaysInclude); + this.alwaysInclude = alwaysInclude; } /** @@ -108,7 +108,7 @@ public class InternalResourceViewResolver extends UrlBasedViewResolver { * attributes. * @see InternalResourceView#setExposedContextBeanNames */ - public void setExposedContextBeanNames(String[] exposedContextBeanNames) { + public void setExposedContextBeanNames(String... exposedContextBeanNames) { this.exposedContextBeanNames = exposedContextBeanNames; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java index edb4a02be86161c3b3bc904b7a0616f2c1cdb41c..fa2dda373dbdd54e09cdf98db5e7178dac04fb72 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java @@ -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. @@ -106,8 +106,6 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements private String suffix = ""; - private String[] viewNames = null; - private String contentType; private boolean redirectContextRelative = true; @@ -116,13 +114,16 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements private String requestContextAttribute; - private int order = Integer.MAX_VALUE; - /** Map of static attributes, keyed by attribute name (String) */ private final Map staticAttributes = new HashMap(); private Boolean exposePathVariables; + private String[] viewNames; + + private int order = Integer.MAX_VALUE; + + /** * Set the view class that should be used to create views. * @param viewClass class that is assignable to the required view class @@ -303,6 +304,29 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements return this.staticAttributes; } + /** + * Specify whether views resolved by this resolver should add path variables to the model or not. + *

>The default setting is to let each View decide (see {@link AbstractView#setExposePathVariables}. + * However, you can use this property to override that. + * @param exposePathVariables + *

    + *
  • {@code true} - all Views resolved by this resolver will expose path variables + *
  • {@code false} - no Views resolved by this resolver will expose path variables + *
  • {@code null} - individual Views can decide for themselves (this is used by the default) + *
      + * @see AbstractView#setExposePathVariables + */ + public void setExposePathVariables(Boolean exposePathVariables) { + this.exposePathVariables = exposePathVariables; + } + + /** + * Return whether views resolved by this resolver should add path variables to the model or not. + */ + protected Boolean getExposePathVariables() { + return this.exposePathVariables; + } + /** * Set the view names (or name patterns) that can be handled by this * {@link org.springframework.web.servlet.ViewResolver}. View names can contain @@ -310,7 +334,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements * view name 'myReport'. * @see #canHandle */ - public void setViewNames(String[] viewNames) { + public void setViewNames(String... viewNames) { this.viewNames = viewNames; } @@ -339,22 +363,6 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements return this.order; } - /** - * Whether views resolved by this resolver should add path variables the model or not. - * The default setting is to allow each View decide (see {@link AbstractView#setExposePathVariables(boolean)}. - * However, you can use this property to override that. - * @param exposePathVariables - *
        - *
      • {@code true} - all Views resolved by this resolver will expose path variables - *
      • {@code false} - no Views resolved by this resolver will expose path variables - *
      • {@code null} - individual Views can decide for themselves (this is used by the default) - *
          - * @see AbstractView#setExposePathVariables(boolean) - */ - public void setExposePathVariables(Boolean exposePathVariables) { - this.exposePathVariables = exposePathVariables; - } - @Override protected void initApplicationContext() { super.initApplicationContext(); @@ -363,6 +371,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements } } + /** * This implementation returns just the view name, * as this ViewResolver doesn't support localized resolution. @@ -460,15 +469,20 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements protected AbstractUrlBasedView buildView(String viewName) throws Exception { AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass()); view.setUrl(getPrefix() + viewName + getSuffix()); + String contentType = getContentType(); if (contentType != null) { view.setContentType(contentType); } + view.setRequestContextAttribute(getRequestContextAttribute()); view.setAttributesMap(getAttributesMap()); - if (this.exposePathVariables != null) { + + Boolean exposePathVariables = getExposePathVariables(); + if (exposePathVariables != null) { view.setExposePathVariables(exposePathVariables); } + return view; }