Как переопределить бин Spring на основе веб-сервера - PullRequest
1 голос
/ 15 марта 2010

Я создаю веб-приложение, которое должно работать как на Tomcat, так и на WebSphere, и мне удалось почти все различия сделать в свойствах со значениями по умолчанию, которые я могу переопределить для развертывания на сервере Tomcat.

Мне нужно сделать еще одно переопределение для бина провайдера аутентификации ...

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"), но есть ли лучший способ?

Ответы [ 2 ]

1 голос
/ 15 марта 2010

ServletContext включает метод getServerInfo(), который для моего кота возвращает «Apache Tomcat / 6.0.13». Я предполагаю, что WebSphere вернет что-то одинаково различимое.

Единственный вопрос, который у вас возникает, это как получить ServletContext. Если вы посмотрите индекс APIdoc в getServletConfig (), вы увидите, что он доступен из многих мест. Если ваш сервлет - это боб, созданный вашей фабрикой бинов, вы можете позвонить servletBean.getServletConfig().getServerInfo().

Если ни один из созданных вами компонентов не дает вам доступа, вы можете создать фиктивный сервлет, который предназначен исключительно для этого обнаружения - не самый лучший, но он должен работать.

0 голосов
/ 15 марта 2010

Вот мое окончательное решение, основанное на рекомендации Джона:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...