2010-03-15 79 views
1

我正在構建一個應該在Tomcat和WebSphere上運行的Web應用程序,並且我設法將幾乎所有的差異都變成了具有默認值的屬性, Tomcat服務器。如何覆蓋基於Web服務器的Spring bean

我需要爲驗證提供豆做的另一個替代...

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
    if(isWebSphere()){ 
     LOG.warn("Running on WebSphere... not overriding default authentication mechanism."); 
     return; 
    } 
    LOG.info("Running on Tomcat... overriding authentication provider bean ("+AUTHENTICATION_PROVIDER_BEAN+")"); 
    if (beanFactory.containsBean(AUTHENTICATOR_BEAN) && beanFactory.containsBean(POPULATOR_BEAN) && beanFactory.containsBean(USERDETAIL_PROVIDER_BEAN)){ 
     LdapAuthenticator authenticator = (LdapAuthenticator) beanFactory.getBean(AUTHENTICATOR_BEAN); 
     LdapAuthoritiesPopulator populator = (LdapAuthoritiesPopulator) beanFactory.getBean(POPULATOR_BEAN); 
     UserDetailProvider userDetailProvider = (UserDetailProvider) beanFactory.getBean(USERDETAIL_PROVIDER_BEAN); 
     ExtendedLdapAuthenticationProvider override = new ExtendedLdapAuthenticationProvider(authenticator, populator); 
     override.setUserDetailProvider(userDetailProvider); 

     beanFactory.registerSingleton(AUTHENTICATION_PROVIDER_BEAN, override); 
    } else { 
     throw new BeanCreationException("Could not find required beans to assemble overriding object for authentication..."); 
    } 
} 

現在我的問題是如何實現isWebSphere()方法。我在想Class.forName("someWebSphereSpecific"),但是有沒有更好的方法?

回答

1

ServletContext包含一個方法getServerInfo(),對於我的tomcat,它返回「Apache Tomcat/6.0.13」。我假設webSphere將返回一些同樣可區分的內容。

然後你唯一的問題是如何獲得ServletContext。如果你在getServletConfig()下查找APIdoc索引,你會發現它可以從很多地方獲得。如果您的servlet是由您的bean工廠創建的bean,那麼您可以致電servletBean.getServletConfig().getServerInfo()

如果您創建的bean都不允許訪問,您可以創建一個純粹用於執行此檢測的虛擬servlet - 不是最簡單的,但它應該可以工作。

0

這是我的最終解決方案基於約翰的建議:

public class ServerInfoBeanOverrider implements BeanFactoryPostProcessor, ServletContextAware { 
    private static final Log LOG = LogFactory.getLog(ServerInfoBeanOverrider.class); 

    private String test; 
    private Object overrideBean; 
    private String overrideName; 

    private String serverInfo; 

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
     if(LOG.isDebugEnabled()){ 
      LOG.debug("Testing if overriding is needed for server '"+serverInfo+"' with test pattern: " + test); 
     } 
     if(Pattern.matches(test, serverInfo)){ 
      if(LOG.isDebugEnabled()){ 
       LOG.debug("Overriding matched... replacing bean with name: " + overrideName); 
      } 
      beanFactory.registerSingleton(overrideName, overrideBean); 
      LOG.info("Replaced bean with name: "+ overrideName + " for server: " + serverInfo); 
     } 
    } 

    public void setServletContext(ServletContext servletContext) { 
     this.serverInfo = servletContext.getServerInfo(); 
    } 

    public void setOverrideBean(Object overrideBean) { 
     this.overrideBean = overrideBean; 
    } 

    public void setOverrideName(String overrideName) { 
     this.overrideName = overrideName; 
    } 

    public void setTest(String test) { 
     this.test = test; 
    } 
} 

這將允許覆蓋基於服務器的信息字符串匹配或沒有正則表達式的bean。

它這樣使用:

<!-- Replace with Tomcat's version if not running on WebSphere --> 
    <bean class="some.company.web.util.ServerInfoBeanOverrider"> 
    <property name="test" value="Apache Tomcat/.*" /> 
    <property name="overrideName" value="authenticationProvider" /> 
    <property name="overrideBean"> 
     <bean class="some.company.providers.ExtendedLdapAuthenticationProvider" lazy-init="true"> 
     <constructor-arg ref="ldapAuthenticator" /> 
     <constructor-arg ref="ldapAuthoritiesPopulator" /> 
     <property name="userDetailProvider" ref="someUserDetailProvider" /> 
     </bean> 
    </property> 
    </bean>