JSP EvalTag resolves "@myBeanName" references in expressions against the WebApplicationContext (SPR-7312); for consistency, expressions in an ApplicationContext support the same syntax against the local BeanFactory
This commit is contained in:
parent
d1d5e2d52a
commit
263fabb0fc
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2010 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.context.expression;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.expression.AccessException;
|
||||||
|
import org.springframework.expression.BeanResolver;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EL bean resolver that operates against a Spring
|
||||||
|
* {@link org.springframework.beans.factory.BeanFactory}.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0.4
|
||||||
|
*/
|
||||||
|
public class BeanFactoryResolver implements BeanResolver {
|
||||||
|
|
||||||
|
private final BeanFactory beanFactory;
|
||||||
|
|
||||||
|
public BeanFactoryResolver(BeanFactory beanFactory) {
|
||||||
|
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||||
|
this.beanFactory = beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
|
||||||
|
try {
|
||||||
|
return this.beanFactory.getBean(beanName);
|
||||||
|
}
|
||||||
|
catch (BeansException ex) {
|
||||||
|
throw new AccessException("Could not resolve bean reference against BeanFactory", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 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.
|
||||||
|
|
@ -126,6 +126,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
|
||||||
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
|
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
|
||||||
sec.addPropertyAccessor(new BeanFactoryAccessor());
|
sec.addPropertyAccessor(new BeanFactoryAccessor());
|
||||||
sec.addPropertyAccessor(new MapAccessor());
|
sec.addPropertyAccessor(new MapAccessor());
|
||||||
|
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
|
||||||
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
|
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
|
||||||
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
|
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
|
||||||
if (conversionService != null) {
|
if (conversionService != null) {
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,22 @@
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bean resolver can be registered with the evaluation context and will
|
* A bean resolver can be registered with the evaluation context
|
||||||
|
* and will kick in for <code>@myBeanName</code> still expressions.
|
||||||
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
* @since 3.0.3
|
* @since 3.0.3
|
||||||
*/
|
*/
|
||||||
public interface BeanResolver {
|
public interface BeanResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup the named bean and return it.
|
* Look up the named bean and return it.
|
||||||
* @param context the current evaluation context
|
* @param context the current evaluation context
|
||||||
* @param beanname the name of the bean to lookup
|
* @param beanName the name of the bean to lookup
|
||||||
* @return a object representing the bean
|
* @return an object representing the bean
|
||||||
* @throws AccessException if there is an unexpected problem resolving the named bean
|
* @throws AccessException if there is an unexpected problem resolving the named bean
|
||||||
*/
|
*/
|
||||||
Object resolve(EvaluationContext context, String beanname) throws AccessException;
|
Object resolve(EvaluationContext context, String beanName) throws AccessException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 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.
|
||||||
|
|
@ -33,7 +33,8 @@ import java.util.List;
|
||||||
public interface EvaluationContext {
|
public interface EvaluationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the default root context object against which unqualified properties/methods/etc should be resolved. This can be overridden when evaluating an expression.
|
* @return the default root context object against which unqualified properties/methods/etc
|
||||||
|
* should be resolved. This can be overridden when evaluating an expression.
|
||||||
*/
|
*/
|
||||||
TypedValue getRootObject();
|
TypedValue getRootObject();
|
||||||
|
|
||||||
|
|
@ -68,13 +69,13 @@ public interface EvaluationContext {
|
||||||
TypeComparator getTypeComparator();
|
TypeComparator getTypeComparator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an operator overloader that may support mathematical operations between more than the standard set of
|
* @return an operator overloader that may support mathematical operations
|
||||||
* types
|
* between more than the standard set of types
|
||||||
*/
|
*/
|
||||||
OperatorOverloader getOperatorOverloader();
|
OperatorOverloader getOperatorOverloader();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a bean resolver that can lookup named beans
|
* @return a bean resolver that can look up beans by name
|
||||||
*/
|
*/
|
||||||
BeanResolver getBeanResolver();
|
BeanResolver getBeanResolver();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import javax.servlet.jsp.JspException;
|
||||||
import javax.servlet.jsp.PageContext;
|
import javax.servlet.jsp.PageContext;
|
||||||
import javax.servlet.jsp.el.VariableResolver;
|
import javax.servlet.jsp.el.VariableResolver;
|
||||||
|
|
||||||
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
|
@ -59,12 +60,6 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||||
private boolean javaScriptEscape = false;
|
private boolean javaScriptEscape = false;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPageContext(PageContext pageContext) {
|
|
||||||
super.setPageContext(pageContext);
|
|
||||||
this.evaluationContext = createEvaluationContext(pageContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the expression to evaluate.
|
* Set the expression to evaluate.
|
||||||
*/
|
*/
|
||||||
|
|
@ -105,6 +100,9 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int doEndTag() throws JspException {
|
public int doEndTag() throws JspException {
|
||||||
|
if (this.evaluationContext == null) {
|
||||||
|
this.evaluationContext = createEvaluationContext(pageContext);
|
||||||
|
}
|
||||||
if (this.var == null) {
|
if (this.var == null) {
|
||||||
try {
|
try {
|
||||||
String result = this.expression.getValue(this.evaluationContext, String.class);
|
String result = this.expression.getValue(this.evaluationContext, String.class);
|
||||||
|
|
@ -123,10 +121,10 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||||
return EVAL_PAGE;
|
return EVAL_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private EvaluationContext createEvaluationContext(PageContext pageContext) {
|
private EvaluationContext createEvaluationContext(PageContext pageContext) {
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
context.addPropertyAccessor(new JspPropertyAccessor(pageContext));
|
context.addPropertyAccessor(new JspPropertyAccessor(pageContext));
|
||||||
|
context.setBeanResolver(new BeanFactoryResolver(getRequestContext().getWebApplicationContext()));
|
||||||
ConversionService conversionService = getConversionService(pageContext);
|
ConversionService conversionService = getConversionService(pageContext);
|
||||||
if (conversionService != null) {
|
if (conversionService != null) {
|
||||||
context.setTypeConverter(new StandardTypeConverter(conversionService));
|
context.setTypeConverter(new StandardTypeConverter(conversionService));
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,13 @@ package org.springframework.web.servlet.tags;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import javax.servlet.jsp.tagext.Tag;
|
import javax.servlet.jsp.tagext.Tag;
|
||||||
|
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.format.annotation.NumberFormat;
|
import org.springframework.format.annotation.NumberFormat;
|
||||||
import org.springframework.format.annotation.NumberFormat.Style;
|
import org.springframework.format.annotation.NumberFormat.Style;
|
||||||
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.mock.web.MockPageContext;
|
import org.springframework.mock.web.MockPageContext;
|
||||||
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
|
@ -103,6 +105,19 @@ public class EvalTagTests extends AbstractTagTests {
|
||||||
assertEquals("not the bean object", context.getAttribute("foo"));
|
assertEquals("not the bean object", context.getAttribute("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAccessUsingBeanSyntax() throws Exception {
|
||||||
|
GenericApplicationContext wac = (GenericApplicationContext)
|
||||||
|
context.getRequest().getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
|
||||||
|
wac.getDefaultListableBeanFactory().registerSingleton("bean2", context.getRequest().getAttribute("bean"));
|
||||||
|
tag.setExpression("@bean2.bean");
|
||||||
|
tag.setVar("foo");
|
||||||
|
int action = tag.doStartTag();
|
||||||
|
assertEquals(Tag.EVAL_BODY_INCLUDE, action);
|
||||||
|
action = tag.doEndTag();
|
||||||
|
assertEquals(Tag.EVAL_PAGE, action);
|
||||||
|
assertEquals("not the bean object", context.getAttribute("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Bean {
|
public static class Bean {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue