最初,设计RMI Service主要是基于三个目的。第一,解决Neo4j嵌入式图数据库单例模式的境况,实现多个客户端可同时操作同一数据库。第二,为图数据库添加安全认证机制,保证数据库访问的安全性。第三,提供轻量级的数据访问接口文件(Neo4j本身提供的Java API Jar文件合计有40多MB),而封装后的RMI Client Jar文件只有300KB左右。
3.1. RMI Client(客户端)
首先介绍下RMI Client(客户端),因为RMI服务中的绝大部分公共对象都在Client包里面,在项目关系上,也是RMI Server端引用RMI Client客户端。项目目录结构图如下所示:
3.1.1 客户端示例
在开始介绍RMI客户端实现原理之前,我们先来浏览下客户端调用方面的代码示例。
3.1.1.1 初始化RMI服务部署地址信息
利用RMI客户端调用RMI服务的第一步,是先初始化RMI服务部署的地址和端口信息,否则,客户端将无法定位到远程服务。示例代码如下。
String hostAddress = “10.230.9.145”; String hostPort = “1099”; for(String serviceName : RemoteServiceUtil.getRemoteServiceList().keySet()) { RemoteClientFactory.initRemoteServiceOption(serviceName, hostAddress, hostPort); }
3.1.1.2 初始化RMI客户端用户信息
由客户端将用户名称和密码传递到服务端,在服务端进行用户权限认证(登录用户详细资料以及权限配置信息都由服务端配置管理)。示例代码如下所示:
RemoteClientFactory.setLoginName(loginName);
RemoteClientFactory.setLoginPassword(password);
3.1.1.3 获取远程服务实例
其实,用户登录认证工作是在获取远程服务实例的时候进行的,如果认证成功,则返回对应的服务实例,否则将抛出异常信息。
private IGraphNodeService graphNodeService = null; this.graphNodeService = RemoteClientFactory.getGraphNodeService(selectedGraphName); GNode startNode = this.graphNodeService.findNodeByID(10);
3.1.2 远程服务实体类
对Neo4j Java API中的关键实体对象进行封装处理,保证其可实现完全意义上的序列化。封装完成后,Client端将不会出现Neo4j Java API中原生的接口类对象,所有的数据都将在RMI Server(服务端)通过解析,自动转换成RMI Client(客户端)认可的类对象。其封装映射关系如下图所示:
3.1.2.1 GNode
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Description: Neo4j图数据库节点实体信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GNode implements Serializable { private static final long serialVersionUID = 1L; private long id = -1; private int degree = 0; private Map<String,Object> propertyList = new HashMap<String,Object>(); private List<String> labelNameList = new ArrayList<String>(); private List<Long> relationshipList = new ArrayList<Long>(); private Map<String,ArrayList<Long>> relationshipTypeList = new HashMap<String,ArrayList<Long>>(); private Map<String,ArrayList<Long>> relationshipDirectionList = new HashMap<String,ArrayList<Long>>(); /** * 获取节点编码 * @return */ public long getId() { return id; } /** * 设置节点编码 * @param id */ public void setId(long id) { this.id = id; } /** * 获取节点深度 * @return */ public int getDegree() { return degree; } /** * 设置节点深度 * @param degree */ public void setDegree(int degree) { this.degree = degree; } /** * 获取节点属性集合 * @return */ public Map<String, Object> getPropertyList() { return propertyList; } /** * 获取节点标签集合 * @return */ public List<String> getLabelNameList() { return labelNameList; } /** * 获取节点关联关系编码集合 * @return */ public List<Long> getRelationshipList() { return relationshipList; } /** * 获取节点的关联关系类型分组集合 * @return */ public Map<String,ArrayList<Long>> getRelationshipTypeList() { return relationshipTypeList; } /** * 获取节点的关联关系方向分组集合 * @return */ public Map<String,ArrayList<Long>> getRelationshipDirectionList() { return relationshipDirectionList; } /** * 根据关系类型获取对应关系编码集合。 * @param relationshipType * @return */ public List<Long> getRelationships(String relationshipType) { if(this.relationshipTypeList.containsKey(relationshipType)) { return this.relationshipTypeList.get(relationshipType); } return new ArrayList<Long>(); } /** * 根据关系方向获取对应关系编码集合。 * @param direction * @return */ public List<Long> getRelationships(GDirection direction) { if(this.relationshipDirectionList.containsKey(direction.getName())) { return this.relationshipDirectionList.get(direction.getName()); } return new ArrayList<Long>(); } /** * 根据关系类型和方向检索出关系编码集合。 * @param relationshipType * @param direction * @return */ public List<Long> getRelationships(String relationshipType, GDirection direction) { List<Long> listByType = this.getRelationships(relationshipType); List<Long> listByDirection = this.getRelationships(direction); List<Long> list = new ArrayList<Long>(); for(long id : listByType) { if(listByDirection.contains(id)) { list.add(id); } } return list; } }
3.1.2.2 GRelationship
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * Description: Neo4j图数据库连接关系实体信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GRelationship implements Serializable { private static final long serialVersionUID = 1L; private long id = -1; private String relationshipType = ""; private long startNodeID = -1; private long endNodeID = -1; private Map<String,Object> propertyList = new HashMap<String,Object>(); /** * 获取关系编码 * @return */ public long getId() { return id; } /** * 设置关系编码 * @param id */ public void setId(long id) { this.id = id; } /** * 获取关系类型 * @return */ public String getRelationshipType() { return relationshipType; } /** * 设置关系类型 * @param relationshipType */ public void setRelationshipType(String relationshipType) { this.relationshipType = relationshipType; } /** * 获取起始节点编码 * @return */ public long getStartNodeID() { return startNodeID; } /** * 设置起始节点编码 * @param startNodeID */ public void setStartNodeID(long startNodeID) { this.startNodeID = startNodeID; } /** * 获取结束节点编码 * @return */ public long getEndNodeID() { return endNodeID; } /** * 设置结束节点编码 * @param endNodeID */ public void setEndNodeID(long endNodeID) { this.endNodeID = endNodeID; } /** * 获取关系属性信息集合 * @return */ public Map<String, Object> getPropertyList() { return propertyList; } /** * 设置关系属性信息集合 * @param propertyList */ public void setPropertyList(Map<String, Object> propertyList) { this.propertyList = propertyList; } }
3.1.2.3 GPath
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Description: Neo4j图数据库路径实体信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GPath implements Serializable { private static final long serialVersionUID = 1L; private GNode beginNode = null; private GNode endNode = null; private List<GNode> nodes = new ArrayList<GNode>(); private List<GNode> reverseNodes = new ArrayList<GNode>(); private List<GRelationship> relationships = new ArrayList<GRelationship>(); private List<GRelationship> reverseRelationships = new ArrayList<GRelationship>(); private GRelationship lastRelationship = null; /** * 获取路径中包含的Node对象集合。 * @return */ public List<GNode> getNodes() { return nodes; } /** * 获取路径中包含的Relationship对象集合。 * @return */ public List<GRelationship> getRelationships() { return relationships; } /** * 获取路径的起始节点对象。 * @return */ public GNode getBeginNode() { if(this.nodes.size() > 0) { this.beginNode = this.nodes.get(0); } return beginNode; } /** * 获取路径的结束节点对象。 * @return */ public GNode getEndNode() { if(this.nodes.size() > 0) { this.endNode = this.nodes.get(this.nodes.size() - 1); } return endNode; } /** * 获取路径中包含的Node对象集合(反向)。 * @return */ public List<GNode> getReverseNodes() { if(this.nodes.size() > 0) { this.reverseNodes.clear(); for(int i=this.nodes.size() - 1; i>=0; i--) { this.reverseNodes.add(this.nodes.get(i)); } } return reverseNodes; } /** * 获取获取路径中包含的Relationship对象集合(反向)。 * @return */ public List<GRelationship> getReverseRelationships() { if(this.relationships.size() > 0) { this.reverseRelationships.clear(); for(int i=this.relationships.size() - 1; i>=0; i--) { this.reverseRelationships.add(this.relationships.get(i)); } } return reverseRelationships; } /** * 获取获取路径中最后一个Relationship对象。 * @return */ public GRelationship getLastRelationship() { if(this.relationships.size() > 0) { this.lastRelationship = this.relationships.get(this.relationships.size() - 1); } return lastRelationship; } }
3.1.2.4 GDirection
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; /** * Description: Neo4j图数据库关系方向类型信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GDirection implements Serializable { private static final long serialVersionUID = 1L; /** * 包含两种方向。 */ public static final String BOTH = "BOTH"; /** * incoming方向。 */ public static final String INCOMING = "INCOMING"; /** * outgoing方向。 */ public static final String OUTGOING = "OUTGOING"; private String name; /** * 获取关系方向名称。 * @return */ public String getName() { return name; } private GDirection(String name) { this.name = name; } /** * 生成BOTH类型的GDirection对象 * @return */ public static GDirection both() { GDirection direction = new GDirection(BOTH); return direction; } /** * 生成INCOMING类型的GDirection对象 * @return */ public static GDirection incoming() { GDirection direction = new GDirection(INCOMING); return direction; } /** * 生成OUTGOING类型的GDirection对象 * @return */ public static GDirection outgoing() { GDirection direction = new GDirection(OUTGOING); return direction; } }
3.1.2.5 GOrderBy
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; /** * Description: Neo4j图数据库排序信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GOrderBy implements Serializable { private static final long serialVersionUID = 1L; /** * 排序类型字符串:升序 */ public static final String ORDER_TYPE_ASC = "ASC"; /** * 排序类型字符串:降序 */ public static final String ORDER_TYPE_DESC = "DESC"; private String propertyName; private String orderType; /** * 获取参与排序的属性名称 * @return */ public String getPropertyName() { return propertyName; } /** * 获取排序类型 * @return */ public String getOrderType() { return this.orderType; } /** * 构造函数 * @param propertyName 排序属性名称 * @param orderType 排序类型 */ private GOrderBy(String propertyName, String orderType) { this.propertyName = propertyName; this.orderType = orderType; } /** * 构建升序排序信息对象 * @param propertyName * @return */ public static GOrderBy asc(String propertyName) { return new GOrderBy(propertyName, ORDER_TYPE_ASC); } /** * 构建降序排序信息对象 * @param propertyName * @return */ public static GOrderBy desc(String propertyName) { return new GOrderBy(propertyName, ORDER_TYPE_DESC); } }
3.1.2.6 GPage
package com.hnepri.neo4j.client.rmi.bean; import java.io.Serializable; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import com.hnepri.common.util.LogInfoUtil; /** * Description: 图数据库数据分页模型类。<br> * 利用此类可分页管理Node数据和Relationship数据等。 * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class GPage implements Serializable { private static final long serialVersionUID = 330410716100946538L; private int pageSize = 10; private int pageIndex = 1; private int prevPageIndex = 1; private int nextPageIndex = 1; private int pageCount = 0; private int pageFirstRowIndex = 1; private boolean hasNextPage = true; private int totalCount = 0; private long startTime = System.currentTimeMillis(); private long endTime = System.currentTimeMillis(); private List<GNode> nodeList = new ArrayList<GNode>(); private List<GRelationship> relationshipList = new ArrayList<GRelationship>(); /** * 分页对象构造函数 * @param pageSize 每页记录数 */ public GPage(int pageSize) { this.pageSize = pageSize; } /** * 获取分页记录数量 * @return */ public int getPageSize() { return pageSize; } /** * 获取当前页序号 * @return */ public int getPageIndex() { return pageIndex; } /** * 设置当前页序号 * @param pageIndex */ public void setPageIndex(int pageIndex) { if(pageIndex <= 0) { pageIndex = 1; } this.pageIndex = pageIndex; } /** * 获取分页总数 * @return */ public int getPageCount() { if(this.getTotalCount() == 0) { this.pageCount = 0; } else { int shang = this.getTotalCount() / this.getPageSize(); int yu = this.getTotalCount() % this.getPageSize(); if(yu > 0) { shang += 1; } this.pageCount = shang; } return pageCount; } /** * 获取每页的第一行序号 * @return */ public int getPageFirstRowIndex() { this.pageFirstRowIndex = (this.pageIndex - 1) * this.getPageSize() + 1; return pageFirstRowIndex; } /** * 获取上一页序号 * @return */ public int getPrevPageIndex() { if(this.pageIndex > 1) { this.prevPageIndex = this.pageIndex - 1; } else { this.prevPageIndex = 1; } return prevPageIndex; } /** * 获取下一页序号 * @return */ public int getNextPageIndex() { if(this.pageIndex < this.pageCount) { this.nextPageIndex = this.pageIndex + 1; } else { this.nextPageIndex = this.pageCount; } return nextPageIndex; } /** * 跳转到下一页 */ public void nextPage() { if(this.totalCount == 0 || this.getPageCount() == 0) { this.pageIndex = 1; } else { if(this.pageIndex < this.pageCount) { this.pageIndex = this.pageIndex + 1; } else { this.pageIndex = this.pageCount; } } } /** * 跳转到上一页 */ public void prevPage() { if(this.pageIndex > 1) { this.pageIndex = this.pageIndex - 1; } else { this.pageIndex = 1; } } /** * 获取是否有下一页 * @return */ public boolean isHasNextPage() { if(this.pageIndex < this.getPageCount()) { this.hasNextPage = true; } else { this.hasNextPage = false; } return hasNextPage; } /** * 获取总记录数 */ public int getTotalCount() { return totalCount; } /** * 获取总记录数 * @param totalCount */ public void setTotalCount(int totalCount) { this.totalCount = totalCount; } /** * 初始化起始时间(毫秒) */ public void initStartTime() { this.startTime = System.currentTimeMillis(); } /** * 初始化截止时间(毫秒) */ public void initEndTime() { this.endTime = System.currentTimeMillis(); } /** * 获取毫秒格式的耗时信息 * @return */ public String getTimeIntervalByMilli() { return String.valueOf(this.endTime - this.startTime) + "毫秒"; } /** * 获取秒格式的耗时信息 * @return */ public String getTimeIntervalBySecond() { double interval = (this.endTime - this.startTime)/1000.0; DecimalFormat df = new DecimalFormat("#.##"); return df.format(interval) + "秒"; } /** * 打印时间信息 */ public void printTimeInfo() { LogInfoUtil.printLog("起始时间:" + this.startTime); LogInfoUtil.printLog("截止时间:" + this.endTime); LogInfoUtil.printLog("耗费时间:" + this.getTimeIntervalBySecond()); } /** * 获取Node检索结果列表 * @return */ public List<GNode> getNodeList() { return nodeList; } /** * 获取Relationship检索结果列表 * @return */ public List<GRelationship> getRelationshipList() { return relationshipList; } }
3.1.3 远程服务接口类
这里着重介绍下远程服务基础接口IBaseRemoteService,主要有两个方法,分别进行用户登录验证和传递图数据库名称等。用户登录验证,是RMI安全机制的第一步,决定RMI客户端是否有权使用RMI服务。
package com.hnepri.neo4j.client.rmi.service; import java.rmi.Remote; import java.rmi.RemoteException; /** * Description: 远程服务基类接口类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IBaseRemoteService extends Remote { /** * Remote连接测试,正常情况会返回大写的SUCCESS。 * @return * @throws RemoteException */ public String remoteTest() throws RemoteException; /** * 验证RMI服务用户信息 * @param loginName 用户名称 * @param password 用户密码 * @return 返回状态值。<br> * 0:表示验证通过。<br> * 1:表示未设置用户或者密码。<br> * 2:表示用户不存在。<br> * 3:表示密码错误。<br> * 4:表示用户无权访问此服务。<br> * 5:表示IP无权访问此服务。 * @throws RemoteException */ public int login(String loginName, String password) throws RemoteException; /** * 初始化设置图数据库名称 * @param graphName 图数据库名称(与Server端保持一致) * @throws RemoteException */ public void initGraphName(String graphName) throws RemoteException; /** * 初始化设置图数据库路径 * @param graphPath 图数据库路径(与Server端保持一致) * @throws RemoteException */ public void initGraphPath(String graphPath) throws RemoteException; }
由于每个接口文件中的方法过多,这里不再一一罗列,开发人员可以根据自己的需要创建相关的接口文件和接口中的方法。其他几个服务接口类如下所示:
package com.hnepri.neo4j.client.rmi.service; import java.rmi.RemoteException; import java.util.HashMap; import java.util.List; import java.util.Map; import com.hnepri.neo4j.client.form.graph.bean.GraphConfigOption; import com.hnepri.neo4j.client.form.graph.bean.GraphModelOption; /** * Description: Neo4j图数据库管理操作接口<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IGraphManageService extends IBaseRemoteService package com.hnepri.neo4j.client.rmi.service; import java.rmi.RemoteException; import java.util.List; import java.util.Map; import com.hnepri.neo4j.client.rmi.bean.GNode; import com.hnepri.neo4j.client.rmi.bean.GRelationship; /** * Description: Neo4j图数据库Node操作接口<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IGraphNodeService extends IBaseRemoteService package com.hnepri.neo4j.client.rmi.service; import java.rmi.RemoteException; import java.util.HashMap; import java.util.List; import com.hnepri.neo4j.client.rmi.bean.GNode; import com.hnepri.neo4j.client.rmi.bean.GRelationship; /** * Description: Neo4j图数据库Index操作接口<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IGraphIndexService extends IBaseRemoteService package com.hnepri.neo4j.client.rmi.service; import java.rmi.RemoteException; import java.util.List; import com.hnepri.neo4j.client.rmi.bean.GDirection; import com.hnepri.neo4j.client.rmi.bean.GPath; /** * Description: Neo4j图数据库Path操作接口<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IGraphPathService extends IBaseRemoteService package com.hnepri.neo4j.client.rmi.service; import java.rmi.RemoteException; import java.util.List; import java.util.Map; import java.util.Properties; import com.hnepri.neo4j.client.rmi.bean.GDirection; import com.hnepri.neo4j.client.rmi.bean.GNode; import com.hnepri.neo4j.client.rmi.bean.GOrderBy; import com.hnepri.neo4j.client.rmi.bean.GPage; import com.hnepri.neo4j.client.rmi.bean.GPath; import com.hnepri.neo4j.client.rmi.bean.GRelationship; /** * Description: Neo4j图数据库Cypher操作接口<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public interface IGraphCypherService extends IBaseRemoteService
3.1.4 远程服务工具类
远程服务工具类包括客户端调用工厂Factory类(主要是对远程服务接口类的调用进行组织管理,同时提供安全认证机制,确保调用者为认证和授权用户)、远程登录状态工具类、远程服务信息工具类等。
3.1.4.1 RemoteClientFactory
package com.hnepri.neo4j.client.rmi.util; import java.io.Serializable; import java.net.InetAddress; import java.net.UnknownHostException; import java.rmi.Naming; import java.util.HashMap; import com.hnepri.common.util.LogInfoUtil; import com.hnepri.neo4j.client.rmi.service.IGraphCypherService; import com.hnepri.neo4j.client.rmi.service.IGraphIndexService; import com.hnepri.neo4j.client.rmi.service.IGraphManageService; import com.hnepri.neo4j.client.rmi.service.IGraphNodeService; import com.hnepri.neo4j.client.rmi.service.IGraphPathService; /** * Description: Hadoop集群相关rmi服务客户端工厂类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class RemoteClientFactory { /** * 远程服务调用成功返回值 */ public static final String REMOTE_CALL_STATUS_SUCCESS = "SUCCESS"; /** * 远程服务调用失败返回值 */ public static final String REMOTE_CALL_STATUS_FAILURE = "FAILURE"; /** * RMI服务默认部署主机IP地址 */ public static final String DEFAULT_HOST_ADDRESS = "10.231.45.34"; /** * RMI服务默认部署主机端口号 */ public static final String DEFAULT_HOST_PORT = "1099"; private static String loginName = ""; private static String loginPassword = ""; /** * 获取登录用户名称 * @return */ public static String getLoginName() { return loginName; } /** * 设置登录用户名称 * @param loginName */ public static void setLoginName(String loginName) { RemoteClientFactory.loginName = loginName; remoteServiceLoginStatusList.clear(); } /** * 获取登录用户密码 * @return */ public static String getLoginPassword() { return loginPassword; } /** * 设置登录用户密码 * @param loginPassword */ public static void setLoginPassword(String loginPassword) { RemoteClientFactory.loginPassword = loginPassword; remoteServiceLoginStatusList.clear(); } /** * 远程服务登录验证状态列表 */ private static HashMap<String,Integer> remoteServiceLoginStatusList = new HashMap<String,Integer>(); private static HashMap<String,RemoteServiceOption> remoteServiceOptionList = new HashMap<String,RemoteServiceOption>(); /** * 获取远程服务选项配置对象 * @param serviceName * @return */ private static RemoteServiceOption getRemoteServiceOption(String serviceName) { if(remoteServiceOptionList.containsKey(serviceName)) { return remoteServiceOptionList.get(serviceName); } else { RemoteServiceOption option = new RemoteServiceOption(); option.setName(serviceName); option.setTitle(RemoteServiceUtil.getRemoteServiceList().get(serviceName)); option.setHostAddress(DEFAULT_HOST_ADDRESS); option.setHostPort(DEFAULT_HOST_PORT); option.setServiceGroup(RemoteServiceGroupUtil.getRemoteServiceMappingGroupList().get(serviceName)); remoteServiceOptionList.put(option.getName(), option); return option; } } /** * 获取客户端IP地址 * @return */ public static String getClientAddress() { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { return "127.0.0.1"; } } /** * 初始化远程服务配置信息(当RMI服务端IP地址和端口发生变更时,可调用此方法更新初始化客户端配置)。 * @param serviceName 远程服务名称 * @param hostAddress 主机IP地址 * @param hostPort 主机端口号 */ public static void initRemoteServiceOption(String serviceName, String hostAddress, String hostPort) { if(serviceName == null || serviceName == "") return; if(RemoteServiceUtil.getRemoteServiceList().containsKey(serviceName) == false) { LogInfoUtil.printLog(String.format("警告:您要调用的远程服务【%】是不存在的!", serviceName));; return; } RemoteServiceOption option = getRemoteServiceOption(serviceName); if(hostAddress != null && hostAddress != "") { option.setHostAddress(hostAddress); } if(hostPort != null && hostPort != "") { option.setHostPort(hostPort); } } /** * 解析用户登录返回状态值。 * @param statusValue * @return */ public static String parseLoginStatusValue(int statusValue) { String baseMessage = "警告:未通过RMI服务用户信息验证,您不能访问相关服务!异常原因:"; String msg = "未知的异常错误"; if(RemoteLoginStatusUtil.getRemoteLoginStatusList().containsKey(statusValue)) { msg = RemoteLoginStatusUtil.getRemoteLoginStatusList().get(statusValue); } return baseMessage + msg + "!"; } /** * <b>获取Neo4j图数据库信息管理操作服务接口。</b><br><br> * 接口功能包括:<br> * 1、图数据库信息管理:创建、编辑、删除数据库信息等。<br> * 2、图数据库模型管理等。<br> * @return */ public static IGraphManageService getGraphManageService() { IGraphManageService service = null; try { RemoteServiceOption option = getRemoteServiceOption(RemoteServiceUtil.NEO4J_GRAPH_MANAGE_SERVICE); String path = option.getRemoteServiceCallPath(); service = (IGraphManageService)Naming.lookup(path); } catch (Exception e) { e.printStackTrace(); } return service; } /** * <b>获取Neo4j图数据库Node操作服务接口。</b><br><br> * 接口功能包括:<br> * 1、Node信息管理:创建、编辑、删除节点信息等。<br> * 2、Relationship信息管理:创建、编辑、删除关系信息等。<br> * @param graphName 图数据库名称。 * @return */ public static IGraphNodeService getGraphNodeService(String graphName) { IGraphNodeService service = null; try { RemoteServiceOption option = getRemoteServiceOption(RemoteServiceUtil.NEO4J_GRAPH_NODE_SERVICE); String path = option.getRemoteServiceCallPath(); service = (IGraphNodeService)Naming.lookup(path); int loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; if(remoteServiceLoginStatusList.containsKey(RemoteServiceUtil.NEO4J_GRAPH_NODE_SERVICE)) { loginStatusValue = remoteServiceLoginStatusList.get(RemoteServiceUtil.NEO4J_GRAPH_NODE_SERVICE); } else { loginStatusValue = service.login(loginName, loginPassword); if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { remoteServiceLoginStatusList.put(RemoteServiceUtil.NEO4J_GRAPH_NODE_SERVICE, RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS); } } if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { service.initGraphName(graphName); return service; } else { throw new Exception(parseLoginStatusValue(loginStatusValue)); } } catch (Exception e) { e.printStackTrace(); } return service; } /** * <b>获取Neo4j图数据库Index操作服务接口。</b><br><br> * 接口功能包括:<br> * 1、管理Node和Relationship相关的索引信息。<br> * 2、根据索引查询Node和Relationship信息。<br> * @param graphName 图数据库名称。 * @return */ public static IGraphIndexService getGraphIndexService(String graphName) { IGraphIndexService service = null; try { RemoteServiceOption option = getRemoteServiceOption(RemoteServiceUtil.NEO4J_GRAPH_INDEX_SERVICE); String path = option.getRemoteServiceCallPath(); service = (IGraphIndexService)Naming.lookup(path); int loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; if(remoteServiceLoginStatusList.containsKey(RemoteServiceUtil.NEO4J_GRAPH_INDEX_SERVICE)) { loginStatusValue = remoteServiceLoginStatusList.get(RemoteServiceUtil.NEO4J_GRAPH_INDEX_SERVICE); } else { loginStatusValue = service.login(loginName, loginPassword); if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { remoteServiceLoginStatusList.put(RemoteServiceUtil.NEO4J_GRAPH_INDEX_SERVICE, RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS); } } if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { service.initGraphName(graphName); return service; } else { throw new Exception(parseLoginStatusValue(loginStatusValue)); } } catch (Exception e) { e.printStackTrace(); } return service; } /** * <b>获取Neo4j图数据库Path操作服务接口。</b><br><br> * 接口功能包括:<br> * 1、基于路径等进行的遍历操作。<br> * @param graphName 图数据库名称。 * @return */ public static IGraphPathService getGraphPathService(String graphName) { IGraphPathService service = null; try { RemoteServiceOption option = getRemoteServiceOption(RemoteServiceUtil.NEO4J_GRAPH_PATH_SERVICE); String path = option.getRemoteServiceCallPath(); service = (IGraphPathService)Naming.lookup(path); int loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; if(remoteServiceLoginStatusList.containsKey(RemoteServiceUtil.NEO4J_GRAPH_PATH_SERVICE)) { loginStatusValue = remoteServiceLoginStatusList.get(RemoteServiceUtil.NEO4J_GRAPH_PATH_SERVICE); } else { loginStatusValue = service.login(loginName, loginPassword); if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { remoteServiceLoginStatusList.put(RemoteServiceUtil.NEO4J_GRAPH_PATH_SERVICE, RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS); } } if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { service.initGraphName(graphName); return service; } else { throw new Exception(parseLoginStatusValue(loginStatusValue)); } } catch (Exception e) { e.printStackTrace(); } return service; } /** * <b>获取Neo4j图数据库Cypher操作服务接口。</b><br><br> * 接口功能包括:<br> * 1、基于Cypher进行的查询服务。<br> * @param graphName 图数据库名称。 * @return */ public static IGraphCypherService getGraphCypherService(String graphName) { IGraphCypherService service = null; try { //根据服务名称,获取对应的远程服务配置选项实体对象。 RemoteServiceOption option = getRemoteServiceOption(RemoteServiceUtil.NEO4J_GRAPH_CYPHER_SERVICE); //获取RMI远程服务调用路径,格式如:rmi://127.0.0.1:1099/group/neo4j_cypher_service String path = option.getRemoteServiceCallPath(); //根据调用路径进行反射处理。 service = (IGraphCypherService)Naming.lookup(path); //验证用户的登录状态。 int loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; //并非每次都需要重新登录验证,系统会自动记录上次登录成功的状态。 if(remoteServiceLoginStatusList.containsKey(RemoteServiceUtil.NEO4J_GRAPH_CYPHER_SERVICE)) { loginStatusValue = remoteServiceLoginStatusList.get(RemoteServiceUtil.NEO4J_GRAPH_CYPHER_SERVICE); } else { loginStatusValue = service.login(loginName, loginPassword); if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { remoteServiceLoginStatusList.put(RemoteServiceUtil.NEO4J_GRAPH_CYPHER_SERVICE, RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS); } } if(loginStatusValue == RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS) { //如果登录成功,则初始化图数据库名称,并返回接口服务实例。 service.initGraphName(graphName); return service; } else { //如果登录失败,则将登录异常信息作为异常抛出。 throw new Exception(parseLoginStatusValue(loginStatusValue)); } } catch (Exception e) { e.printStackTrace(); } return service; } } /** * Description: 远程服务配置选项信息类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ class RemoteServiceOption implements Serializable { private static final long serialVersionUID = 2428254113523224078L; private String name; private String title; private String serviceGroup; private String hostAddress; private String hostPort; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getServiceGroup() { return serviceGroup; } public void setServiceGroup(String serviceGroup) { this.serviceGroup = serviceGroup; } public String getHostAddress() { return hostAddress; } public void setHostAddress(String hostAddress) { this.hostAddress = hostAddress; } public String getHostPort() { return hostPort; } public void setHostPort(String hostPort) { this.hostPort = hostPort; } public String getRemoteServiceCallPath() { String basePath = "rmi://%s:%s/%s/%s"; return String.format(basePath, this.getHostAddress(), this.getHostPort(), this.getServiceGroup(), this.getName()); } } /** * Description: 远程服务分组工具类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ class RemoteServiceGroupUtil { /** * 服务分组标示:neo4j服务 */ protected static final String SERVICE_GROUP_NEO4J = "9056a000-bdfc-4200-adf6-82d242469d88"; /** * 服务分组标示:公共服务 */ protected static final String SERVICE_GROUP_COMMON = "1f649bda-94e7-408d-8f17-7e7a59337f77"; private static HashMap<String,String> remoteServiceMappingGroupList = null; /** * 远程服务与服务组映射列表 * @return */ public static HashMap<String,String> getRemoteServiceMappingGroupList() { if(remoteServiceMappingGroupList == null) { remoteServiceMappingGroupList = new HashMap<String,String>(); remoteServiceMappingGroupList.put(RemoteServiceUtil.NEO4J_GRAPH_MANAGE_SERVICE, SERVICE_GROUP_NEO4J); remoteServiceMappingGroupList.put(RemoteServiceUtil.NEO4J_GRAPH_NODE_SERVICE, SERVICE_GROUP_NEO4J); remoteServiceMappingGroupList.put(RemoteServiceUtil.NEO4J_GRAPH_INDEX_SERVICE, SERVICE_GROUP_NEO4J); remoteServiceMappingGroupList.put(RemoteServiceUtil.NEO4J_GRAPH_PATH_SERVICE, SERVICE_GROUP_NEO4J); remoteServiceMappingGroupList.put(RemoteServiceUtil.NEO4J_GRAPH_CYPHER_SERVICE, SERVICE_GROUP_NEO4J); } return remoteServiceMappingGroupList; } }
3.1.4.2 RemoteLoginStatusUtil
package com.hnepri.neo4j.client.rmi.util; import java.util.HashMap; /** * Description: 远程登录状态工具类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-09-01编写 * @version 1.0 */ public class RemoteLoginStatusUtil { /** * 登录状态值:登录成功0 */ public static final int LOGIN_STATUS_SUCCESS = 0; /** * 登录状态值:用户或密码为空1 */ public static final int LOGIN_STATUS_USER_PASSWORD_EMPTY = 1; /** * 登录状态值:用户不存在2 */ public static final int LOGIN_STATUS_USER_ERROR = 2; /** * 登录状态值:密码错误3 */ public static final int LOGIN_STATUS_PASSWORD_ERROR = 3; /** * 登录状态值:用户无访问权限4 */ public static final int LOGIN_STATUS_USER_PERMISSION_ERROR = 4; /** * 登录状态值:IP无访问权限5 */ public static final int LOGIN_STATUS_IP_PERMISSION_ERROR = 5; private static HashMap<Integer,String> remoteLoginStatusList = null; public static HashMap<Integer,String> getRemoteLoginStatusList() { if(remoteLoginStatusList == null) { remoteLoginStatusList = new HashMap<Integer,String>(); remoteLoginStatusList.put(LOGIN_STATUS_SUCCESS, "登录验证通过"); remoteLoginStatusList.put(LOGIN_STATUS_USER_PASSWORD_EMPTY, "用户或者密码为空"); remoteLoginStatusList.put(LOGIN_STATUS_USER_ERROR, "用户不存在"); remoteLoginStatusList.put(LOGIN_STATUS_PASSWORD_ERROR, "用户密码错误"); remoteLoginStatusList.put(LOGIN_STATUS_USER_PERMISSION_ERROR, "用户无访问权限"); remoteLoginStatusList.put(LOGIN_STATUS_IP_PERMISSION_ERROR, "IP地址无访问权限"); } return remoteLoginStatusList; } }
3.1.4.3 RemoteServiceUtil
package com.hnepri.neo4j.client.rmi.util; import java.util.HashMap; /** * Description: 远程服务工具类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-11-01编写 * @version 1.0 */ public class RemoteServiceUtil { /** * Neo4j图数据库信息管理服务 */ public static final String NEO4J_GRAPH_MANAGE_SERVICE = "neo4j-graph-manage-service"; /** * Neo4j图数据库Node节点服务 */ public static final String NEO4J_GRAPH_NODE_SERVICE = "neo4j-graph-node-service"; /** * Neo4j图数据库Index索引服务 */ public static final String NEO4J_GRAPH_INDEX_SERVICE = "neo4j-graph-index-service"; /** * Neo4j图数据库Path路径服务 */ public static final String NEO4J_GRAPH_PATH_SERVICE = "neo4j-graph-path-service"; /** * Neo4j图数据库Cypher查询服务 */ public static final String NEO4J_GRAPH_CYPHER_SERVICE = "neo4j-graph-cypher-service"; private static HashMap<String,String> remoteServiceList = null; public static HashMap<String,String> getRemoteServiceList() { if(remoteServiceList == null) { remoteServiceList = new HashMap<String,String>(); remoteServiceList.put(NEO4J_GRAPH_MANAGE_SERVICE, "Neo4j图数据库信息管理服务"); remoteServiceList.put(NEO4J_GRAPH_NODE_SERVICE, "Neo4j图数据库Node节点服务"); remoteServiceList.put(NEO4J_GRAPH_INDEX_SERVICE, "Neo4j图数据库Index索引服务"); remoteServiceList.put(NEO4J_GRAPH_PATH_SERVICE, "Neo4j图数据库Path路径服务"); remoteServiceList.put(NEO4J_GRAPH_CYPHER_SERVICE, "Neo4j图数据库Cypher查询服务"); } return remoteServiceList; } }
【待续】