65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (3投票s)

2016年9月29日

CPOL

2分钟阅读

viewsIcon

13876

这篇文章解释了如何根据激活的 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 的博客 上。

使用自定义标签访问 JSP 中的 Spring 配置 - CodeProject - 代码之家
© . All rights reserved.