我正在构建一个应该在Tomcat和WebSphere上运行的webapp,并且我已经设法将几乎所有差异都用于默认值,我可以覆盖它们以便在Tomcat服务器上进行部署。
我需要对身份验证提供程序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")
,但有更好的方法吗?
答案 0 :(得分:1)
ServletContext包含一个方法getServerInfo()
,对于我的tomcat,它返回“Apache Tomcat / 6.0.13”。我假设webSphere将返回一些同样可区分的东西。
您唯一的问题是如何获取ServletContext。如果你在getServletConfig()下查找APIdoc索引,你会发现它可以从很多地方获得。如果您的servlet是由bean工厂创建的bean,那么您可以调用servletBean.getServletConfig().getServerInfo()
。
如果您创建的bean都没有为您提供访问权限,那么您可以创建一个纯粹用于执行此检测的虚拟servlet - 不是最好的,但它应该可以工作。
答案 1 :(得分: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>