requestmapping que mvc example ejemplo spring jsp dependency-injection jsp-tags custom-tag

example - spring mvc que es



Cómo resolver mediante programación el marcador de posición de propiedad en Spring (5)

Creo que en lugar de centrarse en el funcionamiento interno del contenedor de contexto, simplemente puede definir una nueva utilidad: propiedades como esta:

<util:properties id="appProperties" location="classpath:app.properties" />

y en tu código, úsalo así:

Properties props = appContext.getBean("appProperties", Properties.class);

O como este donde sea que puedas hacer DI:

@Value("#{appProperties[''app.resources.path'']}")

Actualmente trabajo en una aplicación web basada en Spring 3.1.0.M1, basada en anotaciones, y tengo un problema para resolver los marcadores de posición de propiedad en un lugar específico de mi aplicación.

Aquí está la historia.

1) En mi contexto de aplicación web (cargado por DispatcherServlet), tengo

mvc-config.xml:

<!-- Handles HTTP GET requests for /resources/version/** --> <resources mapping="/${app.resources.path}/**" location="/static/" cache-period="31556926"/> ... <!-- Web properties --> <context:property-placeholder location=" classpath:app.properties "/>

2) Inside app.properties, hay 2 propiedades, entre otras:

app.properties:

# Properties provided (filtered) by Maven itself app.version: 0.1-SNAPSHOT ... # Static resources mapping app.resources.path: resources/${app.version}

3) Tengo una etiqueta personalizada JSP en mis plantillas JSP 2.1. Esta etiqueta es responsable de la construcción completa de rutas de recursos dependiendo de la configuración del entorno, la versión de la aplicación, la selección del tema de primavera, etc. La clase de etiqueta personalizada extiende la clase de implementación de spring: url, por lo que puede considerarse una etiqueta url habitual pero con algunos conocimientos adicionales.

Mi problema es que no puedo resolver $ {app.resources.path} correctamente en la implementación de mi etiqueta personalizada JSP. Las etiquetas personalizadas de JSP son administradas por el contenedor de servlets, no por Spring, y por lo tanto no participan en DI. Así que no puedo usar el @Value habitual ("$ {app.resources.path}") y Spring lo resuelve automáticamente.

Todo lo que tengo allí es la instancia de contexto de la aplicación web, así que tengo que resolver mi propiedad mediante programación.

Hasta ahora probé:

ResourceTag.java:

// returns null PropertyResolver resolver = getRequestContext().getWebApplicationContext().getBean(PropertyResolver.class); resolver.getProperty("app.resources.path"); // returns null, its the same web context instance (as expected) PropertyResolver resolver2 = WebApplicationContextUtils.getRequiredWebApplicationContext(pageContext.getServletContext()).getBean(PropertyResolver.class); resolver2.getProperty("app.resources.path"); // throws NPE, resolver3 is null as StringValueResolver is not bound StringValueResolver resolver3 = getRequestContext().getWebApplicationContext().getBean(StringValueResolver.class); resolver3.resolveStringValue("app.resources.path"); // null, since context: property-placeholder does not register itself as PropertySource Environment env = getRequestContext().getWebApplicationContext().getEnvironment(); env.getProperty("app.resources.path");

Así que ahora estoy un poco atrapado con eso. Sé que la capacidad de resolver mi marcador de posición está en algún lugar del contexto, simplemente no sé la forma correcta de hacerlo.
Cualquier ayuda o ideas para verificar son muy apreciadas.


Desde Spring 3.0.3 hay EmbeddedValueResolverAware que funcionará de la misma manera que lo mencionó otra publicación que usa la appContext.getBeanFactory().resolveEmbeddedValue("${prop}") .

Para resolver el problema:

  1. Haga que su clase implemente la interfaz EmbeddedValueResolverAware y obtendrá la solución de resolución para usted

  2. Luego, donde podrá recuperar las propiedades como se muestra en un fragmento de código:

    String propertyValue = resolver.resolveStringValue("${your.property.name}");

Entonces su bean no necesita depender de ApplicationContext para recuperar las propiedades que necesita.


Desde la versión 3.0, Spring mantiene una lista de resolución de cadenas en beanFactory. Puedes usarlo así:

String value = appContext.getBeanFactory().resolveEmbeddedValue("${prop}");

El javadoc establece este método en cuanto a la resolución de valores incrustados, como los atributos de anotación, así que tal vez estamos eludiendo su uso, pero funciona.


Hay una solución más posible: crear clases de etiquetas @Configurable a través de AspectJ y habilitar el entrelazado en tiempo de compilación o tiempo de carga. Entonces, podría usar las anotaciones Spring @Value habituales en mis etiquetas personalizadas. Pero, realmente, no quiero configurar infraestructura de tejido solo por un par de clases. Sigue buscando una forma de resolver el marcador de posición mediante ApplicationContext.


Una opción es agregar un PropertySource (aquí MapPropertySource para ejemplificar una configuración en memoria) a un MapPropertySource ConfigurableEnvironment y pedirle que resuelva las propiedades por usted.

public class Foo { @Autowired private ConfigurableEnvironment env; @PostConstruct public void setup() { env.getPropertySources() .addFirst(new MapPropertySource("my-propertysource", ImmutableMap.<String, Object>of("your.property.name", "the value"))); env.resolvePlaceholders("your.property.name"); } }

Opcionalmente anote la clase Foo con @Configuration para disfrutar del poder de la configuración programática a favor de XML .