diff --git a/open-anpr-client/pom.xml b/open-anpr-client/pom.xml
new file mode 100644
index 0000000..65001e1
--- /dev/null
+++ b/open-anpr-client/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+
+ com.visual.open.anpr
+ open-anpr-client
+ 1.0.0
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.58
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5
+
+
+
+
\ No newline at end of file
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/PlateRecognition.java b/open-anpr-client/src/main/java/com/visual/open/anpr/PlateRecognition.java
new file mode 100644
index 0000000..40d66ca
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/PlateRecognition.java
@@ -0,0 +1,47 @@
+package com.visual.open.anpr;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import com.visual.open.anpr.handle.RecognitionHandler;
+
+public class PlateRecognition {
+ /**服务地址**/
+ private String serverHost;
+ /**实例对象**/
+ private final static Map ins = new ConcurrentHashMap<>();
+
+ /**
+ * 构建集合对象
+ * @param serverHost 服务地址
+ * @return
+ */
+ private PlateRecognition(String serverHost){
+ this.serverHost = serverHost;
+ }
+
+ /**
+ * 构建集合对象
+ * @param serverHost 服务地址
+ * @return
+ */
+ public static PlateRecognition build (String serverHost){
+ String key = serverHost;
+ if(!ins.containsKey(key)){
+ synchronized (PlateRecognition.class){
+ if(!ins.containsKey(key)){
+ ins.put(key, new PlateRecognition(serverHost));
+ }
+ }
+ }
+ return ins.get(key);
+ }
+ /**
+ * 人脸比对操作对象
+ * @return CollectHandler
+ */
+ public RecognitionHandler detection(){
+ return RecognitionHandler.build(serverHost);
+ }
+
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/common/Api.java b/open-anpr-client/src/main/java/com/visual/open/anpr/common/Api.java
new file mode 100755
index 0000000..099938d
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/common/Api.java
@@ -0,0 +1,12 @@
+package com.visual.open.anpr.common;
+
+public class Api {
+
+ public static final String plate_recognition = "/visual/plate/recognition";
+
+ public static String getUrl(String host, String uri){
+ host = host.replaceAll ("/+$", "");
+ return host + uri;
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/handle/RecognitionHandler.java b/open-anpr-client/src/main/java/com/visual/open/anpr/handle/RecognitionHandler.java
new file mode 100644
index 0000000..28dc8b5
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/handle/RecognitionHandler.java
@@ -0,0 +1,63 @@
+package com.visual.open.anpr.handle;
+
+import com.alibaba.fastjson.TypeReference;
+import com.visual.open.anpr.common.Api;
+import com.visual.open.anpr.http.HttpClient;
+import com.visual.open.anpr.model.Recognition;
+import com.visual.open.anpr.model.RecognitionRep;
+import com.visual.open.anpr.model.RecognitionReq;
+import com.visual.open.anpr.model.Response;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class RecognitionHandler {
+
+ /**服务地址**/
+ protected String serverHost;
+ /**实例对象**/
+ private final static Map ins = new ConcurrentHashMap<>();
+
+ public String getServerHost() {
+ return serverHost;
+ }
+
+ public RecognitionHandler setServerHost(String serverHost) {
+ this.serverHost = serverHost;
+ return this;
+ }
+
+ /**
+ * 构建车牌检测对象
+ * @param serverHost 服务地址
+ * @return
+ */
+ public static RecognitionHandler build(String serverHost){
+ String key = serverHost;
+ if(!ins.containsKey(key)){
+ synchronized (RecognitionHandler.class){
+ if(!ins.containsKey(key)){
+ ins.put(key, new RecognitionHandler().setServerHost(serverHost));
+ }
+ }
+ }
+ return ins.get(key);
+ }
+
+ /**
+ * 车牌检测
+ * @param recognition 待检测的数据信息
+ * @return 车牌检测结果
+ */
+ public Response> recognition(Recognition recognition){
+ RecognitionReq compareReq = RecognitionReq.build()
+ .setImage(recognition.getImage())
+ .setLimit(recognition.getLimit());
+ return HttpClient.post(
+ Api.getUrl(this.serverHost, Api.plate_recognition),
+ compareReq,
+ new TypeReference>>() {});
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClient.java b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClient.java
new file mode 100755
index 0000000..1028324
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClient.java
@@ -0,0 +1,207 @@
+package com.visual.open.anpr.http;
+
+import com.alibaba.fastjson.TypeReference;
+
+import com.visual.open.anpr.model.MapParam;
+import com.visual.open.anpr.model.Response;
+import com.visual.open.anpr.utils.JsonUtil;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.LinkedList;
+import java.util.List;
+
+public class HttpClient {
+
+ /**编码方式*/
+ private static final String ENCODING = "UTF-8";
+ /**连接超时时间,10秒*/
+ public static final int DEFAULT_CONNECT_TIMEOUT = 10 * 1000;
+ /**socket连接超时时间,10秒*/
+ public static final int DEFAULT_READ_TIMEOUT = 10 * 000;
+ /**请求超时时间,60秒*/
+ public static final int DEFAULT_CONNECT_REQUEST_TIMEOUT = 30 * 000;
+ /**最大连接数,默认为2*/
+ private static final int MAX_TOTAL = 8;
+ /**设置指向特定路由的并发连接总数,默认为2*/
+ private static final int MAX_PER_ROUTE = 4;
+
+ private static RequestConfig requestConfig;
+ private static PoolingHttpClientConnectionManager connectionManager;
+ private static BasicCookieStore cookieStore;
+ private static HttpClientBuilder httpBuilder;
+ private static CloseableHttpClient httpClient;
+ private static CloseableHttpClient httpsClient;
+ private static SSLContext sslContext;
+
+ /**
+ * 创建SSLContext对象,用来绕过https证书认证实现访问。
+ */
+ static {
+ try {
+ sslContext = SSLContext.getInstance("TLS");
+ // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
+ X509TrustManager tm = new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ };
+ sslContext.init(null, new TrustManager[] {tm}, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 初始化httpclient对象,以及在创建httpclient对象之前的一些自定义配置。
+ */
+ static {
+ // 自定义配置信息
+ requestConfig = RequestConfig.custom()
+ .setSocketTimeout(DEFAULT_READ_TIMEOUT)
+ .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
+ .setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT)
+ .build();
+ //设置协议http和https对应的处理socket链接工厂的对象
+ Registry socketFactoryRegistry = RegistryBuilder. create()
+ .register("http", new PlainConnectionSocketFactory())
+ .register("https", new SSLConnectionSocketFactory(sslContext))
+ .build();
+ connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+ // 设置cookie存储对像,在需要获取cookie信息时,可以使用这个对象。
+ cookieStore = new BasicCookieStore();
+ // 设置最大连接数
+ connectionManager.setMaxTotal(MAX_TOTAL);
+ // 设置路由并发数
+ connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
+ httpBuilder = HttpClientBuilder.create();
+ httpBuilder.setDefaultRequestConfig(requestConfig);
+ httpBuilder.setConnectionManager(connectionManager);
+ httpBuilder.setDefaultCookieStore(cookieStore);
+ // 实例化http 和 https的对象。
+ httpClient = httpBuilder.build();
+ httpsClient = httpBuilder.build();
+ }
+
+ /**
+ * post请求
+ * @param url
+ * @param data
+ * @param
+ * @return
+ */
+ public static Response post(String url, Object data) {
+ return post(url, data, new TypeReference>() {});
+ }
+
+ /**
+ * post请求
+ * @param url
+ * @param data
+ * @param
+ * @return
+ */
+ public static Response post(String url, Object data, TypeReference> type) {
+ // 创建HTTP对象
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setConfig(requestConfig);
+ httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
+ // 设置请求头
+ if(null != data){
+ String json = data instanceof String ? String.valueOf(data) : JsonUtil.toString(data);
+ StringEntity stringEntity = new StringEntity(json, ENCODING);
+ stringEntity.setContentEncoding(ENCODING);
+ httpPost.setEntity(stringEntity);
+ }
+ // 创建httpResponse对象
+ CloseableHttpClient client = url.toLowerCase().startsWith("https") ? httpsClient : httpClient;
+ try {
+ CloseableHttpResponse httpResponse = client.execute(httpPost);
+ String content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
+ return JsonUtil.toEntity(content, type);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ /**
+ * get
+ * @param url
+ * @param param
+ * @param
+ * @return
+ */
+ public static Response get(String url, MapParam param) {
+ return get(url, param, new TypeReference>() {});
+ }
+
+ /**
+ * get
+ * @param url
+ * @param param
+ * @param
+ * @return
+ */
+ public static Response get(String url, MapParam param, TypeReference> type) {
+ try {
+ //参数构建
+ URIBuilder uriBuilder = new URIBuilder(url);
+ if(null != param && !param.isEmpty()){
+ List list = new LinkedList<>();
+ for(String key : param.keySet()){
+ Object value = param.get(key);
+ if(null == value){
+ list.add(new BasicNameValuePair(key, null));
+ }else{
+ list.add(new BasicNameValuePair(key, String.valueOf(value)));
+ }
+ }
+ uriBuilder.setParameters(list);
+ }
+ //构建请求
+ HttpGet httpGet = new HttpGet(uriBuilder.build());
+ httpGet.setConfig(requestConfig);
+ httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");
+ // 创建httpResponse对象
+ CloseableHttpClient client = url.toLowerCase().startsWith("https") ? httpsClient : httpClient;
+ CloseableHttpResponse httpResponse = client.execute(httpGet);
+ String content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
+ return JsonUtil.toEntity(content, type);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientResult.java b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientResult.java
new file mode 100755
index 0000000..ac4fe00
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientResult.java
@@ -0,0 +1,4 @@
+package com.visual.open.anpr.http;
+
+public class HttpClientResult {
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientUtils.java b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientUtils.java
new file mode 100755
index 0000000..fedf3f5
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientUtils.java
@@ -0,0 +1,455 @@
+package com.visual.open.anpr.http;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.*;
+
+/**
+ * @Description: httpclient常用方法封装,
+ * @Author: ggf
+ * @Date: 2020/06/06
+ */
+public class HttpClientUtils {
+ /**
+ * 编码方式
+ */
+ private static final String ENCODING = "UTF-8";
+ /**
+ * 连接超时时间,60秒
+ */
+ public static final int DEFAULT_CONNECT_TIMEOUT = 6000;
+ /**
+ * socket连接超时时间,60秒
+ */
+ public static final int DEFAULT_READ_TIMEOUT = 6000;
+ /**
+ * 请求超时时间,60秒
+ */
+ public static final int DEFAULT_CONNECT_REQUEST_TIMEOUT = 6000;
+ /**
+ * 最大连接数,默认为2
+ */
+ private static final int MAX_TOTAL = 64;
+ /**
+ * 设置指向特定路由的并发连接总数,默认为2
+ */
+ private static final int MAX_PER_ROUTE = 32;
+
+ private static RequestConfig requestConfig;
+ private static PoolingHttpClientConnectionManager connectionManager;
+ private static BasicCookieStore cookieStore;
+ private static HttpClientBuilder httpBuilder;
+ private static CloseableHttpClient httpClient;
+ private static CloseableHttpClient httpsClient;
+ private static SSLContext sslContext;
+
+ /**
+ * 创建SSLContext对象,用来绕过https证书认证实现访问。
+ */
+ static {
+ try {
+ sslContext = SSLContext.getInstance("TLS");
+ // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
+ X509TrustManager tm = new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ };
+ sslContext.init(null, new TrustManager[] {tm}, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 初始化httpclient对象,以及在创建httpclient对象之前的一些自定义配置。
+ */
+ static {
+ // 自定义配置信息
+ requestConfig = RequestConfig.custom()
+ .setSocketTimeout(DEFAULT_READ_TIMEOUT)
+ .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
+ .setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT)
+ .build();
+ //设置协议http和https对应的处理socket链接工厂的对象
+ Registry socketFactoryRegistry = RegistryBuilder. create()
+ .register("http", new PlainConnectionSocketFactory())
+ .register("https", new SSLConnectionSocketFactory(sslContext))
+ .build();
+ connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+ // 设置cookie存储对像,在需要获取cookie信息时,可以使用这个对象。
+ cookieStore = new BasicCookieStore();
+ // 设置最大连接数
+ connectionManager.setMaxTotal(MAX_TOTAL);
+ // 设置路由并发数
+ connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
+ httpBuilder = HttpClientBuilder.create();
+ httpBuilder.setDefaultRequestConfig(requestConfig);
+ httpBuilder.setConnectionManager(connectionManager);
+ httpBuilder.setDefaultCookieStore(cookieStore);
+ // 实例化http 和 https的对象。
+ httpClient = httpBuilder.build();
+ httpsClient = httpBuilder.build();
+ }
+
+ /**
+ * 封装无参数的get请求(http)
+ * @param url 请求url
+ * @return 返回对象HttpClientResult
+ */
+ public static HttpClientResult doGet(String url) {
+ return doGet(url, false);
+ }
+
+ /**
+ * 封装无参get请求,支持https协议
+ * @param url 请求url
+ * @param https 请求的是否是https协议,是:true 否false
+ * @return
+ */
+ public static HttpClientResult doGet(String url, boolean https){
+ return doGet(url, null, null, https);
+ }
+
+ /**
+ * 封装带参数的get请求,支持https协议
+ * @param url 请求url
+ * @param params 请求参数
+ * @param https 是否是https协议
+ */
+ public static HttpClientResult doGet(String url, Map params, boolean https){
+ return doGet(url, null, params, https);
+ }
+
+ /**
+ * 封装带参数和带请求头信息的GET方法,支持https协议请求
+ * @param url 请求url
+ * @param headers 请求头信息
+ * @param params 请求参数
+ * @param https 是否使用https协议
+ */
+ public static HttpClientResult doGet(String url, Map headers, Map params, boolean https){
+ // 创建HttpGet
+ HttpGet httpGet = null;
+ // 创建httpResponse对象
+ CloseableHttpResponse httpResponse = null;
+ try {
+ // 创建访问的地址
+ URIBuilder uriBuilder = new URIBuilder(url);
+ if (params != null) {
+ Set> entrySet = params.entrySet();
+ for (Map.Entry entry : entrySet) {
+ uriBuilder.setParameter(entry.getKey(), entry.getValue());
+ }
+ }
+ // 创建HTTP对象
+ httpGet = new HttpGet(uriBuilder.build());
+ httpGet.setConfig(requestConfig);
+ // 设置请求头
+ setHeader(headers, httpGet);
+ // 使用不同的协议进行请求,返回自定义的响应对象
+ if (https) {
+ return getHttpClientResult(httpResponse, httpsClient, httpGet);
+ } else {
+ return getHttpClientResult(httpResponse, httpClient, httpGet);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ // 释放资源
+ if (httpGet != null) {
+ httpGet.releaseConnection();
+ }
+ release(httpResponse);
+ }
+
+ return null;
+ }
+
+ /**
+ * POST不带参数,只支持http协议
+ * @param url 请求url
+ */
+ public static HttpClientResult doPost(String url) {
+ return doPost(url, Boolean.FALSE);
+ }
+
+ /**
+ * 封装不带参数的post请求,支持https协议
+ * @param url 请求url
+ * @param https 是否是https协议
+ */
+ public static HttpClientResult doPost(String url, boolean https) {
+ return doPost(url, null, (Map)null, https);
+ }
+
+ /**
+ * 带参数的post请求,支持https协议
+ * @param url 请求url
+ * @param params 请求参数
+ * @param https 是否是https协议
+ */
+ public static HttpClientResult doPost(String url, Map params, boolean https) {
+ return doPost(url, null, params, https);
+ }
+
+ /**
+ * 带参数和请求头的POST请求,支持https
+ *
+ * @param url 请求url
+ * @param headers 请求头
+ * @param params 请求参数,参数为K=V格式
+ * @param https 是否https协议
+ */
+ public static HttpClientResult doPost(String url, Map headers, Map params, boolean https) {
+ // 创建HTTP对象
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setConfig(requestConfig);
+ // 设置请求头
+ setHeader(headers, httpPost);
+ // 封装请求参数
+ setParam(params, httpPost);
+ // 创建httpResponse对象
+ CloseableHttpResponse httpResponse = null;
+ try {
+ if (https) {
+ return getHttpClientResult(httpResponse, httpsClient, httpPost);
+ } else {
+ return getHttpClientResult(httpResponse, httpClient, httpPost);
+ }
+ } finally {
+ httpPost.releaseConnection();
+ release(httpResponse);
+ }
+ }
+
+ /**
+ * 带参数、带请求头的POST请求,支持https协议
+ *
+ * @param url 请求url
+ * @param headers 请求头
+ * @param json 请求参数为json格式
+ * @param https 是否使用https协议
+ * @throws Exception
+ */
+ public static HttpClientResult doPost(String url, Map headers, String json, boolean https) {
+ // 创建HTTP对象
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setConfig(requestConfig);
+ // 设置请求头
+ setHeader(headers, httpPost);
+ StringEntity stringEntity = new StringEntity(json, ENCODING);
+ stringEntity.setContentEncoding(ENCODING);
+ httpPost.setEntity(stringEntity);
+ // 创建httpResponse对象
+ CloseableHttpResponse httpResponse = null;
+ try {
+ if (https) {
+ return getHttpClientResult(httpResponse, httpsClient, httpPost);
+ } else {
+ return getHttpClientResult(httpResponse, httpClient, httpPost);
+ }
+ } finally {
+ httpPost.releaseConnection();
+ release(httpResponse);
+ }
+ }
+
+
+ /**
+ * 发送put请求;不带请求参数
+ *
+ * @param url 请求地址
+ * @return
+ * @throws Exception
+ */
+ public static HttpClientResult doPut(String url) {
+ return doPut(url);
+ }
+
+ /**
+ * 发送put请求;带请求参数
+ *
+ * @param url 请求地址
+ * @param params 参数集合
+ * @return
+ * @throws Exception
+ */
+ public static HttpClientResult doPut(String url, Map params) {
+ HttpPut httpPut = new HttpPut(url);
+ httpPut.setConfig(requestConfig);
+ setParam(params, httpPut);
+ CloseableHttpResponse httpResponse = null;
+ try {
+ return getHttpClientResult(httpResponse, httpClient, httpPut);
+ } finally {
+ httpPut.releaseConnection();
+ release(httpResponse);
+ }
+ }
+
+ /**
+ * 发送delete请求,不带请求参数
+ *
+ * @param url 请求url
+ * @return
+ * @throws Exception
+ */
+ public static HttpClientResult doDelete(String url) {
+ HttpDelete httpDelete = new HttpDelete(url);
+ httpDelete.setConfig(requestConfig);
+ CloseableHttpResponse httpResponse = null;
+ try {
+ return getHttpClientResult(httpResponse, httpClient, httpDelete);
+ } finally {
+ httpDelete.releaseConnection();
+ release(httpResponse);
+ }
+ }
+
+ /**
+ * 发送delete请求,带请求参数, 支持https协议
+ *
+ * @param url 请求url
+ * @param params 请求参数
+ * @param https 是否https
+ * @return
+ * @throws Exception
+ */
+ public static HttpClientResult doDelete(String url, Map params, boolean https) {
+ if (params == null) {
+ params = new HashMap();
+ }
+ params.put("_method", "delete");
+ return doPost(url, params, https);
+ }
+
+ /**
+ * 获取cookie信息
+ * @return 返回所有cookie集合
+ */
+ public static List getCookies() {
+ return cookieStore.getCookies();
+ }
+
+
+ /**
+ * 设置封装请求头
+ *
+ * @param params 头信息
+ * @param httpMethod 请求对象
+ */
+ public static void setHeader(Map params, HttpRequestBase httpMethod) {
+ // 封装请求头
+ if (null != params && !params.isEmpty()) {
+ Set> entrySet = params.entrySet();
+ for (Map.Entry entry : entrySet) {
+ // 设置到请求头到HttpRequestBase对象中
+ httpMethod.setHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * 封装请求参数
+ *
+ * @param params 请求参数
+ * @param httpMethod 请求方法
+ */
+ public static void setParam(Map params, HttpEntityEnclosingRequestBase httpMethod) {
+ // 封装请求参数
+ if (null != params && !params.isEmpty()) {
+ List nvps = new ArrayList();
+ Set> entrySet = params.entrySet();
+ for (Map.Entry entry : entrySet) {
+ nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+
+ UrlEncodedFormEntity entity = null;
+ try {
+ entity = new UrlEncodedFormEntity(nvps, ENCODING);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ // 设置到请求的http对象中
+ httpMethod.setEntity(entity);
+ }
+ }
+
+ /**
+ * 获得响应结果
+ *
+ * @param httpResponse 响应对象
+ * @param httpClient httpclient对象
+ * @param httpMethod 请求方法
+ * @return
+ * @throws Exception
+ */
+ public static HttpClientResult getHttpClientResult(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient, HttpRequestBase httpMethod) {
+ try {
+ // 执行请求
+ httpResponse = httpClient.execute(httpMethod);
+ // 获取返回结果
+ if (httpResponse != null && httpResponse.getStatusLine() != null) {
+ String content = "";
+ if (httpResponse.getEntity() != null) {
+ content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
+ }
+// return new HttpClientResult(httpResponse.getStatusLine().getStatusCode(), content);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+// return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ return null;
+ }
+
+ /**
+ * 释放资源
+ *
+ * @param httpResponse 响应对象
+ */
+ public static void release(CloseableHttpResponse httpResponse) {
+ // 释放资源
+ if (httpResponse != null) {
+ try {
+ httpResponse.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/MapParam.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/MapParam.java
new file mode 100755
index 0000000..85b9a43
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/MapParam.java
@@ -0,0 +1,17 @@
+package com.visual.open.anpr.model;
+
+import java.util.HashMap;
+
+public class MapParam extends HashMap {
+
+ public static MapParam build(){
+ return new MapParam();
+ }
+
+
+ public MapParam put(String key, Object value){
+ super.put(key, value);
+ return this;
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateColor.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateColor.java
new file mode 100644
index 0000000..cabfffa
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateColor.java
@@ -0,0 +1,31 @@
+package com.visual.open.anpr.model;
+
+public enum PlateColor {
+
+ BLACK("黑色"),
+ BLUE("蓝色"),
+ GREEN("绿色"),
+ WHITE("白色"),
+ YELLOW("黄色"),
+ UNKNOWN("未知");
+
+ private String name;
+
+ PlateColor(String name){
+ this.name = name;
+ }
+
+ public String getName(){
+ return this.name;
+ }
+
+ public static PlateColor valueOfName(String name){
+ for (PlateColor item : PlateColor.values()){
+ if(item.name.equals(name)){
+ return item;
+ }
+ }
+ return UNKNOWN;
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLayout.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLayout.java
new file mode 100644
index 0000000..d5ea815
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLayout.java
@@ -0,0 +1,8 @@
+package com.visual.open.anpr.model;
+
+public enum PlateLayout {
+
+ SINGLE, //单排
+ DOUBLE, //双排
+ UNKNOWN; //未知
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLocation.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLocation.java
new file mode 100755
index 0000000..3078ba1
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLocation.java
@@ -0,0 +1,66 @@
+package com.visual.open.anpr.model;
+
+import java.io.Serializable;
+
+public class PlateLocation implements Serializable {
+ /**左上角x坐标**/
+ private int x;
+ /**左上角y坐标**/
+ private int y;
+ /**宽度**/
+ private int w;
+ /**高度**/
+ private int h;
+
+ /**
+ * 构建坐标
+ * @param x
+ * @param y
+ * @param w
+ * @param h
+ * @return
+ */
+ public static PlateLocation build(int x, int y, int w, int h){
+ return new PlateLocation().setX(x).setY(y).setW(w).setH(h);
+ }
+
+ public static PlateLocation build(float x, float y, float w, float h){
+ return new PlateLocation().setX((int) x).setY((int) y).setW((int) w).setH((int) h);
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public PlateLocation setX(int x) {
+ this.x = x;
+ return this;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public PlateLocation setY(int y) {
+ this.y = y;
+ return this;
+ }
+
+ public int getW() {
+ return w;
+ }
+
+ public PlateLocation setW(int w) {
+ this.w = w;
+ return this;
+ }
+
+ public int getH() {
+ return h;
+ }
+
+ public PlateLocation setH(int h) {
+ this.h = h;
+ return this;
+ }
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/Recognition.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/Recognition.java
new file mode 100644
index 0000000..3442660
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/Recognition.java
@@ -0,0 +1,40 @@
+package com.visual.open.anpr.model;
+
+import java.io.Serializable;
+
+public class Recognition> implements Serializable {
+
+ /**图像Base64编码值**/
+ private String image;
+
+ /**搜索条数:默认5**/
+ private Integer limit = 5;
+
+ /**
+ * 构建比对对象
+ * @return
+ */
+ public static Recognition build(){
+ return new Recognition();
+ }
+
+
+ public String getImage() {
+ return image;
+ }
+
+ public ExtendsVo setImage(String image) {
+ this.image = image;
+ return (ExtendsVo) this;
+ }
+
+ public Integer getLimit() {
+ return limit;
+ }
+
+ public ExtendsVo setLimit(Integer limit) {
+ this.limit = limit;
+ return (ExtendsVo) this;
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionInfo.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionInfo.java
new file mode 100644
index 0000000..d437812
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionInfo.java
@@ -0,0 +1,36 @@
+package com.visual.open.anpr.model;
+
+import java.io.Serializable;
+
+public class RecognitionInfo implements Serializable {
+ /**车牌布局,单排还是双排**/
+ private PlateLayout layout;
+ /**车牌文本信息**/
+ private String plateNo;
+ /**车牌的颜色信息**/
+ private PlateColor plateColor;
+
+ public PlateLayout getLayout() {
+ return layout;
+ }
+
+ public void setLayout(PlateLayout layout) {
+ this.layout = layout;
+ }
+
+ public String getPlateNo() {
+ return plateNo;
+ }
+
+ public void setPlateNo(String plateNo) {
+ this.plateNo = plateNo;
+ }
+
+ public PlateColor getPlateColor() {
+ return plateColor;
+ }
+
+ public void setPlateColor(PlateColor plateColor) {
+ this.plateColor = plateColor;
+ }
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionRep.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionRep.java
new file mode 100644
index 0000000..2643fec
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionRep.java
@@ -0,0 +1,40 @@
+package com.visual.open.anpr.model;
+
+import java.io.Serializable;
+
+public class RecognitionRep implements Serializable {
+
+ /**车牌置信分数**/
+ private Float score;
+
+ /**车牌位置信息**/
+ private PlateLocation location;
+
+ /**车牌识别信息**/
+ private RecognitionInfo recognition;
+
+ public Float getScore() {
+ return score;
+ }
+
+ public void setScore(Float score) {
+ this.score = score;
+ }
+
+ public PlateLocation getLocation() {
+ return location;
+ }
+
+ public void setLocation(PlateLocation location) {
+ this.location = location;
+ }
+
+ public RecognitionInfo getRecognition() {
+ return recognition;
+ }
+
+ public void setRecognition(RecognitionInfo recognition) {
+ this.recognition = recognition;
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionReq.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionReq.java
new file mode 100644
index 0000000..ae55fc2
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionReq.java
@@ -0,0 +1,13 @@
+package com.visual.open.anpr.model;
+
+public class RecognitionReq extends Recognition{
+
+ /**
+ * 构建比对对象
+ * @return
+ */
+ public static RecognitionReq build(){
+ return new RecognitionReq();
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/model/Response.java b/open-anpr-client/src/main/java/com/visual/open/anpr/model/Response.java
new file mode 100755
index 0000000..9be1c3d
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/model/Response.java
@@ -0,0 +1,62 @@
+package com.visual.open.anpr.model;
+
+import java.io.Serializable;
+
+/**
+ * des:接口返回对象
+ * @author diven
+ * @date 上午9:34 2018/7/12
+ */
+public class Response implements Serializable{
+
+ private static final long serialVersionUID = -6919611972884058300L;
+
+ private Integer code = -1;
+ private String message;
+ private T data;
+
+ public Response(){}
+
+ public Response(Integer code, String message, T data) {
+ if(null != code) {
+ this.code = code;
+ }
+ this.message = message;
+ this.data = data;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ if(null != code){
+ this.code = code;
+ }
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public boolean ok(){
+ return new Integer(0).equals(code);
+ }
+
+ @Override
+ public String toString() {
+ return "Response{" + "code=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
+ }
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/utils/Base64Util.java b/open-anpr-client/src/main/java/com/visual/open/anpr/utils/Base64Util.java
new file mode 100755
index 0000000..c4b4445
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/utils/Base64Util.java
@@ -0,0 +1,48 @@
+package com.visual.open.anpr.utils;
+
+import org.apache.commons.codec.binary.Base64;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class Base64Util {
+
+ public static String encode(byte[] binaryData) {
+ byte[] bytes = Base64.encodeBase64(binaryData);
+ return new String(bytes);
+ }
+
+ public static String encode(InputStream in) {
+ // 读取图片字节数组
+ try {
+ ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
+ byte[] buff = new byte[100];
+ int rc;
+ while ((rc = in.read(buff, 0, 100)) > 0) {
+ swapStream.write(buff, 0, rc);
+ }
+ return encode(swapStream.toByteArray());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static String encode(String filePath){
+ try {
+ return encode(new FileInputStream(filePath));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/open-anpr-client/src/main/java/com/visual/open/anpr/utils/JsonUtil.java b/open-anpr-client/src/main/java/com/visual/open/anpr/utils/JsonUtil.java
new file mode 100755
index 0000000..b6ba927
--- /dev/null
+++ b/open-anpr-client/src/main/java/com/visual/open/anpr/utils/JsonUtil.java
@@ -0,0 +1,128 @@
+package com.visual.open.anpr.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+
+import java.util.List;
+import java.util.Map;
+
+public class JsonUtil {
+
+ /**
+ * 将Bean转化为json字符串
+ *
+ * @param obj bean对象
+ * @return json
+ */
+ public static String toString(Object obj) {
+ return toString(obj, false, false);
+ }
+
+ public static String toSimpleString(Object obj) {
+ return toString(obj, false, true);
+ }
+
+ /**
+ * 将Bean转化为json字符串
+ *
+ * @param obj bean对象
+ * @param prettyFormat 是否格式化
+ * @return json
+ */
+ public static String toString(Object obj, boolean prettyFormat, boolean noNull) {
+ if (prettyFormat) {
+ if (noNull) {
+ return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
+ } else {
+ return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
+ }
+ } else {
+ if (noNull) {
+ return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
+ } else {
+ return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.DisableCircularReferenceDetect);
+ }
+ }
+ }
+
+
+ /**
+ * 将字符串转换为Entity
+ *
+ * @param json 数据字符串
+ * @param clazz Entity class
+ * @return
+ */
+ public static T toEntity(String json, Class clazz) {
+ return JSON.parseObject(json, clazz);
+ }
+
+ /**
+ * 将字符串转换为Entity
+ *
+ * @param json 数据字符串
+ * @param typeReference Entity class
+ * @return
+ */
+ public static T toEntity(String json, TypeReference typeReference) {
+ return JSON.parseObject(json, typeReference);
+ }
+
+ /**
+ * 将字符串转换为Map
+ *
+ * @param json 数据字符串
+ * @return Map
+ */
+ public static Map toMap(String json) {
+ return JSON.parseObject(json, new TypeReference