记录使用java调用hugegraph图数据库过程中出现的一些问题及整体流程。(代码示例贴在最下边)
官方网址:https://hugegraph.apache.org/docs/clients/restful-api/propertykey/
java可以通过两种方式调用
1、一种是官方提供的API接口,可以直接调用restful接口;
下面是postman调用示例:注意需要验证图数据库(hugegraph)账号密码;
2、可以通过hugegraph提供的java客户端工具调用:并且官网提供了调用示例;
过程中遇到的问题:
1、hugegraph引用的jar包与fastJSon jar包冲突问题,可以降低fastJSon版本到1.1.x处理;如果不想修改jar包版本可以加入代码,将autoDiscover 设置为false:
private static final com.alibaba.fastjson.support.jaxrs.FastJsonAutoDiscoverable FastJsonAutoDiscoverable = null;
static {
FastJsonAutoDiscoverable.autoDiscover = false;
}
2、 hugegraph很多情况会返回异常信息字符串,无法解析返回的信息。
解决方法:自定义异常信息类ReturnErrorJsonHandler,重新message信息。
整体代码demo贴在下边:
1、HugeGraphUtils(图数据库接口API)
package net.beidousky.web.app.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import net.beidousky.web.app.domain.Result;
import net.beidousky.web.app.entity.HugeClientVo;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
/**
* 图数据库接口API(hugegraph)
*/
public class HugeGraphUtils {
//解决fastJSon与Jersey冲突问题
private static final com.alibaba.fastjson.support.jaxrs.FastJsonAutoDiscoverable FastJsonAutoDiscoverable = null;
static {
FastJsonAutoDiscoverable.autoDiscover = false;
}
/**
* 获取hugeGraph客户端操作对象
* @param key
* @return
* @throws IOException
*/
private static HugeClientVo getHugeGraph(String key) throws IOException {
//读取配置文件hugeGraph连接信息
ClassPathResource classPathResource = new ClassPathResource("hugeGraph.properties");
Properties properties = new Properties();
properties.load(classPathResource.getInputStream());
//读取配置文件中key对应的value值
String json = new String (properties.getProperty(key).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) ;
HugeClientVo hugeClientVo =JSON.parseObject(json,HugeClientVo.class);
return hugeClientVo;
}
/**
* 属性操作--创建属性
* @param falg
* @return
* @throws IOException
*/
public static Result createPropertyKey(String falg,String json) throws IOException{
HugeClientVo hugeClientVo = getHugeGraph(falg);
String ip = hugeClientVo.getIp();
String userName =hugeClientVo.getUserName();
String password =hugeClientVo.getPassword();
String url = ip+ "/graphs/hugegraph/schema/propertykeys" ;
String res = "";
try{
res = RestTemplateUtil.hugeGraphRest(json,url,userName,password);
}catch(Exception e){
String message = JSONPath.read(e.getMessage(),"$.message",String.class);
Result result = Result.success(message);
return result;
}
int id = JSONPath.read(res,"$.id",int.class);
JSONObject jsonObject = new JSONObject();
jsonObject.put("id",id);
Result result = new Result(10000,"属性创建成功",jsonObject);
return result;
}
/**
* 属性操作--检查属性信息是否存在
* @param falg
* @return
* @throws IOException
*/
public static Result getPropertyKey(String falg,String name) throws IOException{
HugeClientVo hugeClientVo = getHugeGraph(falg);
String ip = hugeClientVo.getIp();
String userName =hugeClientVo.getUserName();
String password =hugeClientVo.getPassword();
String url = ip+ "/graphs/hugegraph/schema/propertykeys/"+name;
String res = RestTemplateUtil.hugeGraphGet(url,userName,password);
int id = JSONPath.read(res,"$.id",int.class);
JSONObject jsonObject = new JSONObject();
jsonObject.put("id",id);
Result result = new Result(10000,"属性创建成功",jsonObject);
return result;
}
/**
* 获取所有顶点标签
* @param falg
* @return
* @throws IOException
*/
/* public static String getAllLabel(String falg) throws IOException, SQLException, JSONException {
HugeClient hugeClient = getHugeClient(falg);
GremlinManager gremlin = hugeClient.gremlin();
ResultSet resultSet = gremlin.gremlin("g.V()").execute();
List<Object> list = resultSet.data();
System.out.print(resultSet);
JSONArray jsonarray = JSONArray.fromObject(list);
return jsonarray.toString();
}
*/
}
2、HugeClientUtils(java操作图数据库客户端)
package net.beidousky.web.app.utils;
import com.alibaba.fastjson.JSON;
import com.baidu.hugegraph.driver.GremlinManager;
import com.baidu.hugegraph.driver.HugeClient;
import com.baidu.hugegraph.driver.SchemaManager;
import com.baidu.hugegraph.structure.gremlin.ResultSet;
import com.baidu.hugegraph.structure.schema.PropertyKey;
import net.beidousky.web.app.entity.HugeClientVo;
import net.beidousky.web.app.entity.hugegraph.Property;
import net.sf.json.JSONArray;
import org.json.JSONException;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
/**
* java操作图数据库(hugeGraph)
*/
public class HugeClientUtils {
//解决fastJSon与Jersey冲突问题
private static final com.alibaba.fastjson.support.jaxrs.FastJsonAutoDiscoverable FastJsonAutoDiscoverable = null;
static {
FastJsonAutoDiscoverable.autoDiscover = false;
}
/**
* 获取hugeGraph客户端操作对象
* @param key
* @return
* @throws IOException
*/
private static HugeClient getHugeClient(String key) throws IOException {
//读取配置文件hugeGraph连接信息
ClassPathResource classPathResource = new ClassPathResource("hugeGraph.properties");
Properties properties = new Properties();
properties.load(classPathResource.getInputStream());
//读取配置文件中key对应的value值
String json = new String (properties.getProperty(key).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) ;
HugeClientVo hugeClientVo =JSON.parseObject(json,HugeClientVo.class);
HugeClient hugeClient = null;
if(hugeClientVo!=null){
//获取操作客户端
System.out.print("ip:"+hugeClientVo.getIp()+",name:"+hugeClientVo.getHugegraphGraphName()+",username:"+hugeClientVo.getUserName()+",password:"+hugeClientVo.getPassword());
hugeClient = HugeClient.builder(hugeClientVo.getIp(),hugeClientVo.getHugegraphGraphName())
.configUser(hugeClientVo.getUserName(),hugeClientVo.getPassword())
.build();
}
return hugeClient;
}
/**
* 属性操作--创建属性
* @param falg
* @return
* @throws IOException
*/
public static String createPropertyKey(String falg, Property property) throws IOException, SQLException, JSONException {
HugeClient hugeClient = getHugeClient(falg);
SchemaManager schema = hugeClient.schema();
PropertyKey res = null;
switch (property.getData_type()){
case "STRING" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asText().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asText().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asText().valueSet().ifNotExist().create();
}
break;
case "INT" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asInt().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asInt().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asInt().valueSet().ifNotExist().create();
}
break;
case "FLOAT" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asFloat().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asFloat().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asFloat().valueSet().ifNotExist().create();
}
break;
case "DATE" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asDate().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asDate().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asDate().valueSet().ifNotExist().create();
}
break;
case "BOOLEAN" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asBoolean().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asBoolean().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asBoolean().valueSet().ifNotExist().create();
}
break;
case "BLOB" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asBlob().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asBlob().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asBlob().valueSet().ifNotExist().create();
}
case "Double" :
switch (property.getCardinality()){
case "SINGLE" :
res = schema.propertyKey(property.getName()).asDouble().valueSingle().ifNotExist().create();
case "LIST" :
res = schema.propertyKey(property.getName()).asDouble().valueList().ifNotExist().create();
case "SET" :
res = schema.propertyKey(property.getName()).asDouble().valueSet().ifNotExist().create();
}
break;
}
return res.toString();
}
/**
* 获取所有顶点标签
* @param falg
* @return
* @throws IOException
*/
public static String getAllLabel(String falg) throws IOException{
HugeClient hugeClient = getHugeClient(falg);
GremlinManager gremlin = hugeClient.gremlin();
ResultSet resultSet = gremlin.gremlin("g.V()").execute();
List<Object> list = resultSet.data();
System.out.print(resultSet);
JSONArray jsonarray = JSONArray.fromObject(list);
return jsonarray.toString();
}
}
3、RestTemplateUtil (接口调用工具类)
package net.beidousky.web.app.utils;
import net.beidousky.web.app.component.ReturnErrorJsonHandler;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import java.util.*;
/**
* 接口工具类
*
* @author jwb
*/
public class RestTemplateUtil {
/**
* 图数据库调用post方法
* @param json
* @param url
* @return
*/
public static String hugeGraphRest(String json, String url, String userName, String password) {
RestTemplate template =new RestTemplate();
//自定义异常处理用于解决调用hugeGraph返回异常结果读取message信息
template.setErrorHandler(new ReturnErrorJsonHandler());
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
//添加账号密码验证
headers.add("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((userName + ":" + password).getBytes()));
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> formEntity = new HttpEntity<String>(json, headers);
String result= template.postForEntity(url,formEntity,String.class).getBody();
return result;
}
/**
* 图数据库调用get方法
* @param
* @param url
* @return
*/
public static String hugeGraphGet(String url, String userName, String password) {
RestTemplate template =new RestTemplate();
//自定义异常处理用于解决调用hugeGraph返回异常结果读取message信息
template.setErrorHandler(new ReturnErrorJsonHandler());
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
//添加账号密码验证
headers.add("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((userName + ":" + password).getBytes()));
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
String result= template.getForEntity(url,String.class,headers).getBody();
return result;
}
}
4、ReturnErrorJsonHandler(自定义异常处理用于解决调用hugeGraph返回异常结果读取message信息)
package net.beidousky.web.app.component;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.UnknownHttpStatusCodeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 自定义异常处理用于解决调用hugeGraph返回异常结果读取message信息
*/
public class ReturnErrorJsonHandler extends DefaultResponseErrorHandler {
//调用父类方法就行
public boolean hasError(ClientHttpResponse response) throws IOException {
return super.hasError(response);
}
//重写该方法调用重写的getErrorMessage方法
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
if (statusCode == null) {
byte[] body = this.getResponseBody(response);
String message = this.getErrorMessage( body, this.getCharset(response));
throw new UnknownHttpStatusCodeException(message, response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), body, this.getCharset(response));
} else {
this.handleError(response, statusCode);
}
}
//重写该方法,让它返回我们要的格式
private String getErrorMessage(@Nullable byte[] responseBody, @Nullable Charset charset) {
if (ObjectUtils.isEmpty(responseBody)) {
return "[no body]";
} else {
charset = charset == null ? StandardCharsets.UTF_8 : charset;
int maxChars = 200;
if (responseBody.length < maxChars * 2) {
//主要是这里
String message= new String(responseBody, charset);
//Unicode 转换为汉字
return UnicodeToString(message);
} else {
try {
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseBody), charset);
CharBuffer buffer = CharBuffer.allocate(maxChars);
reader.read(buffer);
reader.close();
buffer.flip();
return buffer.toString() + "... (" + responseBody.length + " bytes)";
} catch (IOException var9) {
throw new IllegalStateException(var9);
}
}
}
}
/**
* 将 Unicode 转换为汉字
* */
public String UnicodeToString(String str) {
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
Matcher matcher = pattern.matcher(str);
char ch;
while (matcher.find()) {
ch = (char) Integer.parseInt(matcher.group(2), 16);
str = str.replace(matcher.group(1), ch + "");
}
return str;
}
//重写该方法调用重写的getErrorMessage方法
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
String statusText = response.getStatusText();
HttpHeaders headers = response.getHeaders();
byte[] body = this.getResponseBody(response);
Charset charset = this.getCharset(response);
String message = this.getErrorMessage(body, charset);
switch(statusCode.series()) {
case CLIENT_ERROR:
throw HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
case SERVER_ERROR:
throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
default:
throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
}
}
}
5、hugeGraph.properties(配置文件,由于业务需要,配置的是多个图数据库,所以配置文件中会有多个配置图数据库连接信息,动态读取)
NINTH = {"ip":"http://ip:端口","hugegraph_graph_name":"图数据库名称","userName":"账号","password":"密码"}
SECOND = {"ip":"http://ip:端口2","hugegraph_graph_name":"图数据库名称","userName":"账号","password":"密码"}
6、HugegraphTest(测试类)
package net.beidousky.web.app.controller;
import com.alibaba.fastjson.JSON;
import net.beidousky.web.app.domain.Result;
import net.beidousky.web.app.entity.hugegraph.Property;
import net.beidousky.web.app.utils.HugeGraphUtils;
import java.io.IOException;
public class HugegraphTest {
/**
* 属性操作--创建属性
* @throws IOException
*/
@org.junit.jupiter.api.Test
public void createPropertyKey() throws IOException{
Property property = new Property();
property.setName("测试7");
property.setData_type("TEXT");
property.setCardinality("SINGLE");
String json = JSON.toJSONString(property);
Result resultSet = HugeGraphUtils.createPropertyKey("NINTH",json);
String jsons = JSON.toJSONString(resultSet);
System.out.print(jsons);
}
}
7、HugeClientVo(图数据库连接实体)
package net.beidousky.web.app.entity;
import lombok.Data;
/**
* hugegraph连接实体
*/
@Data
public class HugeClientVo {
//hugegraph连接地址
private String ip;
//hugegraph名称
private String hugegraphGraphName;
//hugegraph用户名
private String userName;
//hugegraph密码
private String password;
}
8、Property (属性参数实体)
package net.beidousky.web.app.entity.hugegraph;
import lombok.Data;
@Data
public class Property {
//属性名称
private String name;
//属性类型只支持–STRING|INT|FLOAT|DATE|BOOLEAN|BLOB
private String data_type;
//属性基数
private String cardinality;
}
最后贴一下代码目录
创作不易,大家帮忙关注一下公众号,感谢。