使用自定义标签在 JSP 中访问 Spring Profile






3.75/5 (3投票s)
这篇文章解释了如何根据激活的 Spring 配置来限制对某个区域的访问。
Spring MVC - 在 JSP 中访问 Spring 配置
这篇文章解释了如何根据激活的 Spring 配置来限制对某个区域的访问。通过阅读本文,你将能够访问 JSP 中的 Spring 配置,从而实现此功能。
<qcm:profile value="dev">
<form action="login-as-admin" method="POST">
<input type="submit" value="login as admin"/>
</form>
</qcm:profile>
Spring 配置
Spring 配置允许为每个环境创建和运行单独的配置。一个常见的用例是根据环境声明多个数据源配置 bean(例如,开发目的使用 h2,生产环境中使用 PostgreSQL)。
要为给定的配置启用任何类/方法,只需使用 @Profile(“…”)
注解该类/bean 方法即可。
@Profile(value = {QcmProfile.HEROKU, QcmProfile.PROD})
@Bean
public DataSource dataSource() {
final HikariDataSource dataSource = new HikariDataSource();
dataSource.setMaximumPoolSize(properties.getMaximumPoolSize());
dataSource.setDataSourceClassName(properties.getDataSourceClassName());
dataSource.setDataSourceProperties(dataSourceProperties());
return dataSource;
}
@Profile(QcmProfile.TEST)
@Bean
public DataSource testDataSource() {
final HikariDataSource dataSource = new HikariDataSource();
dataSource.setMaximumPoolSize(properties.getMaximumPoolSize());
dataSource.setDataSourceClassName(properties.getDataSourceClassName());
dataSource.setDataSourceProperties(testDataSourceProperties());
return dataSource;
}
你可以在 这里 查看完整的配置类。
如果启用了给定的配置,则带有 @Profile(“…”)
注解的任何组件(@Component
/ @Configuration
)都将被加载。
这种行为是通过在 @Profile
注解本身上使用 @Conditional(ProfileCondition.class)
实现的。
如你所见,ProfileCondition
只是将给定的值与当前环境配置进行检查。
/**
* {@link Condition} that matches based on the value of a {@link Profile @Profile}
* annotation.
*
* @author Chris Beams
* @author Phillip Webb
* @author Juergen Hoeller
* @since 4.0
*/
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs =
metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
return true;
}
}
在 JSP 中使用 Spring 配置
根据特定的环境配置,在 JSP 文件中显示一段内容可能很有用。
在我的用例中,我希望在开发阶段(开发配置)显示一个 admin-login
按钮,以便于测试。
我发现实现这种行为的最佳方法是开发一个自定义 JSP 标签,因为 Servlet
类提供了显示/隐藏文本片段的辅助工具。
主要问题是如何在标签中访问 Spring 配置。幸运的是,Spring 提供了一个有用的标签类:RequestContextAwareTag
。
在标签中访问 Spring 配置
要获得对 Spring 上下文的访问权限,你的标签需要扩展 RequestContextAware
类,该类根据 JavaDoc 暴露当前的“RequestContext
”。
/**
* Superclass for all tags that require a {@link RequestContext}.
*
* <p>The {@code RequestContext} instance provides easy access
* to current state like the
* {@link org.springframework.web.context.WebApplicationContext},
* the {@link java.util.Locale}, the
* {@link org.springframework.ui.context.Theme}, etc.
*
* <p>Mainly intended for
* {@link org.springframework.web.servlet.DispatcherServlet} requests;
* will use fallbacks when used outside {@code DispatcherServlet}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.web.servlet.support.RequestContext
* @see org.springframework.web.servlet.DispatcherServlet
*/
这个类扩展了 TagSupport
Servlet 类,并重写了 main
方法 doStartTag()
以注入 RequestContext
。
/**
* Create and expose the current RequestContext.
* Delegates to {@link #doStartTagInternal()} for actual work.
* @see #REQUEST_CONTEXT_PAGE_ATTRIBUTE
* @see org.springframework.web.servlet.support.JspAwareRequestContext
*/
@Override
public final int doStartTag() throws JspException {
try {
this.requestContext = (RequestContext) this.pageContext.getAttribute
(REQUEST_CONTEXT_PAGE_ATTRIBUTE);
if (this.requestContext == null) {
this.requestContext = new JspAwareRequestContext(this.pageContext);
this.pageContext.setAttribute(REQUEST_CONTEXT_PAGE_ATTRIBUTE, this.requestContext);
}
return doStartTagInternal();
}
catch (JspException ex) {
logger.error(ex.getMessage(), ex);
throw ex;
}
catch (RuntimeException ex) {
logger.error(ex.getMessage(), ex);
throw ex;
}
catch (Exception ex) {
logger.error(ex.getMessage(), ex);
throw new JspTagException(ex.getMessage());
}
}
通过扩展 Spring RequestContextAwareTag
并重写 doStartTagInternal()
方法,你的标签将能够访问检索 Spring 配置所需的 RequestContext
。
有了这个上下文,很容易检索环境配置。
/**
* Created by lopes_f on 6/3/2015.
* <florian.lopes@outlook.com>
* Custom tag evaluating current profile before rendering body
*/
public class ProfileConditionTag extends RequestContextAwareTag {
private String profile;
@Override
protected int doStartTagInternal() throws Exception {
final Environment environment =
this.getRequestContext().getWebApplicationContext().getEnvironment();
if (environment != null) {
final String[] profiles = environment.getActiveProfiles();
if (ArrayUtils.contains(profiles, this.profile)) {
return EVAL_BODY_INCLUDE;
}
}
return SKIP_BODY;
}
public String getValue() {
return profile;
}
public void setValue(String profile) {
this.profile = profile;
}
}
用法
创建 taglib
描述符并将其放置在 WEB-INF/taglibs/ 目录中。
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>Conditional profile Tag</description>
<tlib-version>2.1</tlib-version>
<short-name>ProfileConditionTag</short-name>
<uri></uri>
<tag>
<name>profile</name>
<tag-class>com.ingesup.java.qcm.taglib.ProfileConditionTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>value</name>
<required>true</required>
</attribute>
</tag>
</taglib>
使用这个标签非常简单。
<qcm:profile value="dev">
<form action="login-as-admin" method="POST">
<input type="submit" value="login as admin"/>
</form>
</qcm:profile>
你可以前往 这个网址,你会看到 admin-login
按钮没有出现,因为应用程序的活动配置是“heroku
”。
应用程序代码
你可以在我的 GitHub 项目 中查看完整的应用程序代码。
文章 使用自定义标签访问 JSP 中的 Spring 配置 最先发表在 Florian Lopes 的博客 上。