All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alogic.remote.route.Route Maven / Gradle / Ivy

There is a newer version: 1.6.16
Show newest version
package com.alogic.remote.route;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.alogic.remote.backend.AppBackends;
import com.alogic.remote.backend.Backend;
import com.alogic.remote.backend.BackendProvider;
import com.anysoft.util.Configurable;
import com.anysoft.util.JsonTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Reportable;
import com.anysoft.util.XMLConfigurable;
import com.anysoft.util.XmlElementProperties;
import com.anysoft.util.XmlTools;

/**
 * 应用路由
 * @author duanyy
 * @since 1.6.8.12
 */
public interface Route extends Reportable,Configurable,XMLConfigurable,AutoCloseable{
	
	/**
	 * 获取id
	 * @return id
	 */
	public String id();
	
	/**
	 * 找到指定应用指定规则的路由
	 * 
	 * @param app 应用
	 * @param route 路由
	 * @return 后端节点列表
	 */
	public List select(String app,String route);
	
	/**
	 * 找到指定应用指定规则的路由
	 * @param app 应用
	 * @param p 变量集
	 * @return 后端节点列表
	 */
	public List select(String app,Properties p);
	
	/**
	 * 设置provider
	 * @param provider 提供者
	 */
	public void setBackendProvider(BackendProvider provider);
	
	/**
	 * 重构路由
	 * @param app 变更的应用的路由信息
	 */
	public void rebuild(AppBackends app);
	
	/**
	 * 虚基类
	 * 
	 * @author duanyy
	 *
	 */
	public abstract class Abstract implements Route{
		private String id;
		private BackendProvider provider = null;
		
		public Abstract(){
			
		}
		
		public Abstract(String id,BackendProvider provider){
			this.id = id;
			this.provider = provider;
		}
		
		@Override
		public String id(){
			return id;
		}
		
		@Override
		public void report(Element xml) {
			if (xml != null){
				XmlTools.setString(xml,"module",getClass().getName());
				XmlTools.setString(xml,"id",id());			
			}
		}

		@Override
		public void report(Map json) {
			if (json != null){
				JsonTools.setString(json,"module",getClass().getName());
				JsonTools.setString(json,"id",id());
			}
		}

		@Override
		public void configure(Element e, Properties p) {
			Properties props = new XmlElementProperties(e,p);		
			configure(props);
		}
		
		@Override
		public void configure(Properties p) {
			id = PropertiesConstants.getString(p,"id","",true);
		}	
		
		@Override
		public void close()  {
			// nothing to do
		}	
		
		public AppBackends get(String id){
			return provider.load(id);
		}
		
		@Override
		public void setBackendProvider(BackendProvider p){
			provider = p;
		}
	}
	
	/**
	 * 指定应用的路由
	 * @author duanyy
	 * @version 1.1.10.23 [20161118 duanyy] 
* - 支持超时,只能缓存30分钟
*/ public static class AppRoute implements Reportable{ protected Map> routes = new ConcurrentHashMap>(); protected long timestamp = System.currentTimeMillis(); public synchronized void add(String route,Backend backend){ List found = routes.get(route); if (found == null){ found = new ArrayList(); routes.put(route,found); } found.add(backend); } public void clear(){ routes.clear(); } public List get(String route){ return routes.get(route); } public boolean isExpired(){ return System.currentTimeMillis() - timestamp > 30 * 60 * 1000L; } @Override public void report(Element xml) { if (xml != null){ Document doc = xml.getOwnerDocument(); Iterator>> iter = routes.entrySet().iterator(); while (iter.hasNext()){ Entry> entry = iter.next(); Element item = doc.createElement("item"); XmlTools.setString(item,"id",entry.getKey()); List list = entry.getValue(); for (Backend b:list){ Element backend = doc.createElement("backend"); b.report(backend); item.appendChild(backend); } xml.appendChild(item); } } } @Override public void report(Map json) { if (json != null){ Iterator>> iter = routes.entrySet().iterator(); List items = new ArrayList(); while (iter.hasNext()){ Entry> entry = iter.next(); Map item = new HashMap(); JsonTools.setString(item,"id",entry.getKey()); List backends = new ArrayList(); List list = entry.getValue(); for (Backend b:list){ Map map = new HashMap(); b.report(map); backends.add(map); } item.put("backend", backends); items.add(item); } json.put("item", items); } } } /** * 基于二级索引的实现 * * @author duanyy * */ public abstract class Indexed extends Abstract{ /** * app的路由 */ protected Map routes = new ConcurrentHashMap(); public Indexed(){ } public Indexed(String id,BackendProvider provider){ super(id,provider); } @Override public List select(String app, String route) { AppRoute ar = routes.get(app); if (ar == null || ar.isExpired()){ synchronized(this){ if (ar == null){ ar = new AppRoute(); routes.put(app, ar); AppBackends appBackends = get(app); if (appBackends != null){ rebuild(ar,appBackends); } } } } return ar.get(route); } @Override public List select(String app, Properties p) { String route = getRoute(app,p); return select(app,route); } protected abstract String getRoute(String app, Properties p); @Override public synchronized void rebuild(AppBackends app) { if (app == null){ routes.clear(); }else{ String id = app.getId(); AppRoute ar = routes.get(id); if (ar == null){ ar = new AppRoute(); routes.put(id, ar); }else{ ar.clear(); } rebuild(ar,app); } } protected abstract void rebuild(AppRoute ar, AppBackends app); @Override public void report(Element xml) { if (xml != null){ super.report(xml); boolean detail = XmlTools.getBoolean(xml, "detail", false); if (detail){ String app = XmlTools.getString(xml, "app", ""); if (StringUtils.isNotEmpty(app)){ AppRoute ar = routes.get(app); if (ar != null){ ar.report(xml); } } } } } @Override public void report(Map json) { if (json != null){ super.report(json); boolean detail = JsonTools.getBoolean(json, "detail", false); if (detail){ String app = JsonTools.getString(json, "app", ""); if (StringUtils.isNotEmpty(app)){ AppRoute ar = routes.get(app); if (ar != null){ ar.report(json); } } } } } } }