概要
在實際需求中,客戶想通過不同的域名顯示不同的登錄界面,比如輸入 manage.aps.cn 顯示運維管理登錄,business.aps.cn 顯示業務管理登錄。
實現方法
1.准備兩套登錄UI
在cas目錄 WEB-INF/view/jsp目錄下整兩份UI。
增加兩個屬性文件,這些屬性文件和UI有關系。
查看一下 business.properties
cas 默認顯示界面是在cas.properties 文件中配置,配置完成后,不能再變更了,因此需要能夠實現切換UI。
2.代碼實現
我的思路是通過根據域名動態改變 這個basename。在過濾器中獲取域名,並動態改變basename。
實現方式在過濾器中,判斷當前的訪問域名,判定需要訪問哪個UI並進行切換。
修改源碼:
org.springframework.web.servlet.view.ResourceBundleViewResolver,
這個代碼原本是不能實現UI切換的。
package org.springframework.web.servlet.view; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.servlet.View; public class ResourceBundleViewResolver extends AbstractCachingViewResolver implements Ordered, InitializingBean, DisposableBean { public static final String DEFAULT_BASENAME = "views"; private int order = 2147483647; private ThreadLocal<String> baseNameLocal= new ThreadLocal<>(); private ClassLoader bundleClassLoader = Thread.currentThread().getContextClassLoader(); private String defaultParentView; private Locale[] localesToInitialize; private final Map<Locale, BeanFactory> localeCache = new HashMap(); private final Map<List<ResourceBundle>, ConfigurableApplicationContext> bundleCache = new HashMap(); public void setOrder(int order) { this.order = order; } public int getOrder() { return this.order; } public void setBasename(String basename) { this.baseNameLocal.set(basename); } public void setBundleClassLoader(ClassLoader classLoader) { this.bundleClassLoader = classLoader; } protected ClassLoader getBundleClassLoader() { return this.bundleClassLoader; } public void setDefaultParentView(String defaultParentView) { this.defaultParentView = defaultParentView; } public void setLocalesToInitialize(Locale[] localesToInitialize) { this.localesToInitialize = localesToInitialize; } public void afterPropertiesSet() throws BeansException { if (this.localesToInitialize != null) for (Locale locale : this.localesToInitialize) initFactory(locale); } protected View loadView(String viewName, Locale locale) throws Exception { BeanFactory factory = initFactory(locale); try { return (View)factory.getBean(viewName, View.class); } catch (NoSuchBeanDefinitionException ex) { } return null; } protected synchronized BeanFactory initFactory(Locale locale) throws BeansException { List<ResourceBundle> bundles = new LinkedList(); String baseName="manage"; if(this.baseNameLocal.get()!=null){ baseName=this.baseNameLocal.get(); } ResourceBundle bundle = getBundle(baseName, locale); bundles.add(bundle); GenericWebApplicationContext factory = new GenericWebApplicationContext(); factory.setParent(getApplicationContext()); factory.setServletContext(getServletContext()); PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(factory); reader.setDefaultParentBean(this.defaultParentView); reader.registerBeanDefinitions(bundle); factory.refresh(); return factory; } protected ResourceBundle getBundle(String basename, Locale locale) throws MissingResourceException { return ResourceBundle.getBundle(basename, locale, getBundleClassLoader()); } public void destroy() throws BeansException { for (ConfigurableApplicationContext factory : this.bundleCache.values()) { factory.close(); } this.localeCache.clear(); this.bundleCache.clear(); } }
增加一個過濾器,根據域名修改 頁面視圖目錄。
package com.redxun.cas; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.springframework.web.servlet.view.ResourceBundleViewResolver; public class ViewSelectFilter implements Filter{ @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)req; ResourceBundleViewResolver resolver=(ResourceBundleViewResolver) SpringContextHolder.getBean("viewResolver"); String serverName=request.getServerName(); String pre=serverName.substring(0,serverName.indexOf(".")); resolver.setBasename(pre); chain.doFilter(req, res); } @Override public void init(FilterConfig arg0) throws ServletException { } }
修改 cas-servlet.xml配置。
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:order="0"> <property name="basename" value="${cas.viewResolver.basename}" /> <property name="cache" value="false"></property> </bean>
配置過濾器
<filter> <filter-name>ViewSelectFilter</filter-name> <filter-class>com.redxun.cas.ViewSelectFilter</filter-class> </filter> <filter-mapping> <filter-name>ViewSelectFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
測試效果
在host添加域名映射
192.168.1.77 manage.aps.cn
192.168.1.77 business.aps.cn
測試效果如下:
訪問:manage.aps.cn
business.aps.cn
另外一個知識點,我們在過濾器中需要獲取,spring mvc的上下文。
我們需要實現一個獲取上下文的類。實現接口:ApplicationContextAware
package com.redxun.cas; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext _ctx; @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { _ctx=ctx; } public static Object getBean(String beanId){ return _ctx.getBean(beanId); } public static Object getBean(Class cls){ return _ctx.getBean(cls); } }
這里配置也是有要求的需要配置 cas-servlet.xml配置文件中。
配置如下:
<bean id="springContextHolder" class="com.redxun.cas.SpringContextHolder"></bean>