gitweixin
  • 首页
  • 小程序代码
    • 资讯读书
    • 工具类
    • O2O
    • 地图定位
    • 社交
    • 行业软件
    • 电商类
    • 互联网类
    • 企业类
    • UI控件
  • 大数据开发
    • Hadoop
    • Spark
    • Hbase
    • Elasticsearch
    • Kafka
    • Flink
    • 数据仓库
    • 数据挖掘
    • flume
    • Kafka
    • Hive
    • shardingsphere
    • solr
  • 开发博客
    • Android
    • php
    • python
    • 运维
    • 技术架构
    • 数据库
  • 程序员网赚
  • bug清单
  • 量化投资
  • 在线查询工具
    • 去行号
    • 在线时间戳转换工具
    • 免费图片批量修改尺寸在线工具
    • SVG转JPG在线工具

非spring容器下的配置工具类

精品微信小程序开发门户,代码全部亲测可用

  • 首页   /  
  • 作者: east
  • ( 页面71 )
Java 12月 7,2020

非spring容器下的配置工具类

1、按照spring boot的约定,配置文件名称默认是classpath根路径下的application.properties,并按其约定加载多个配置文件
2、按指定配置文件的路径及名称读取配置,一般是兼容旧工程没有按spring boot约定命名的配置文件 <br>
3、新增读取yml配置文件的功能,默认先读取properties文件,如果不存在再读取yml文件

public final class ConfigUtil {

    private static Logger log = LoggerFactory.getLogger(DataBaseUtil.class);

    /**
     * spring boot默认的配置文件名称
     */
    private static final String CONFIG_FILENAME = "application";

    private static final String DEFAULT_SUFFIX = ".properties";

    private static final String YML_SUFFIX = ".yml";

    /**
     * spring boot通过application.properties配置文件中的spring.profiles.active配置项值指定生效的配置文件名称<br>
     * 如spring.profiles.active=business,表示application-business.properties配置文件生效
     */
    private static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active";

    /**
     * spring boot约定命名格式"application-{profile}.properties"来定义多个配置文件,其中{profile}是可变部分
     */
    private static final String SPRING_BOOT_PROFILE_TEMPLATE = "application-{profile}";

    /**
     * 属性对象集合,注意这里是线程安全的
     */
    private static Map<String, Properties> props = new ConcurrentHashMap<>();

    /** 私有的构造函数 */
    private ConfigUtil() {

    }

    /**
     * 加载指定配置文件中的配置
     * 
     * @param fileName
     * @return
     */
    private static Properties loadPropFromFile(String fileName) {
        Properties prop = new Properties();

        try {
            prop.load(ConfigUtil.class.getClassLoader().getResourceAsStream(fileName));
        } catch (IOException e) {
            e.printStackTrace();
            String error = "配置文件工具类加载配置文件" + fileName + "出现异常!";
            log.error(e.getMessage()+":===:"+error);
            throw new RuntimeException(error);
        }
        return prop;
    }

    /**
     * 将yml格式文件加载到Properties中
     * 
     * @param fileName 文件名
     * @return
     */
    private static Properties loadYmlFromFile(String fileName) {
        Properties prop = new Properties();
        LoaderOptions options = new LoaderOptions();
        // 是否允许读取重复key值,默认为true
        options.setAllowDuplicateKeys(false);
        Yaml yaml = new Yaml(options);

        // 加载yml文件流
        InputStream inStream = ConfigUtil.class.getClassLoader().getResourceAsStream(fileName);
        // 按照文件编码读取流
        Reader reader = new UnicodeReader(inStream);
        Iterable<Object> it = yaml.loadAll(reader);
        Map<String, Object> result = new LinkedHashMap<>();

        for (Object object : it) {
            // 构建map类型数据
            buildFlattenedMap(result, asMap(object), null);
        }
        prop.putAll(result);
        return prop;
    }

    /**
     * 递归转换map源数据,将递归的key值用"."拼接成最终目标map的key值,最终的value为目标map的value值
     * 
     * @param result
     * @param source
     * @param path
     */
    @SuppressWarnings("unchecked")
    private static void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {
        source.forEach((key, value) -> {

            if (hasText(path)) {
                if (key.startsWith("[")) {
                    key = path + key;
                } else {
                    // 分层读取key值,使用"."拼接
                    key = path + '.' + key;
                }
            }

            if (value instanceof String) {
                result.put(key, value);
            } else if (value instanceof Map) {
                // Need a compound key
                Map<String, Object> map = (Map<String, Object>) value;
                // 递归构造map
                buildFlattenedMap(result, map, key);
            } else if (value instanceof Collection) {
                // Need a compound key
                Collection<Object> collection = (Collection<Object>) value;

                if (collection.isEmpty()) {
                    result.put(key, "");
                } else {
                    int count = 0;
                    for (Object object : collection) {
                        buildFlattenedMap(result, Collections.singletonMap("[" + (count++) + "]", object), key);
                    }
                }
            } else {
                result.put(key, (value != null ? value : ""));
            }
        });
    }

    /**
     * 将object数据转换为Map
     * 
     * @param object
     * @return
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> asMap(Object object) {
        // YAML can have numbers as keys
        Map<String, Object> result = new LinkedHashMap<>();

        if (!(object instanceof Map)) {
            // A document can be a text literal
            result.put("document", object);
            return result;
        }
        Map<Object, Object> map = (Map<Object, Object>) object;

        map.forEach((key, value) -> {

            if (value instanceof Map) {
                value = asMap(value);
            }

            if (key instanceof CharSequence) {
                result.put(key.toString(), value);
            } else {
                // It has to be a map key in this case
                result.put("[" + key.toString() + "]", value);
            }
        });
        return result;
    }

    // 判断字符串是否有值(不为空、不为null、必须包含字符串)
    private static boolean hasText(@Nullable String str) {
        return (str != null && !str.isEmpty() && containsText(str));
    }

    // 是否包含字符
    private static boolean containsText(CharSequence str) {
        int strLen = str.length();

        for (int i = 0; i < strLen; i++) {

            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据属性key得到对应的属性值<br>
     * 配置文件按spring boot的约定的配置文件命名规则进行加载<br>
     * <font color=red>注意: 暂不支持yml文件属性读取</font>
     * 
     * @param key 键名称
     * @return
     */
    public static String getPropsValueByKey(String key) {
        // TODO 暂时不支持读取yml格式文件,yml文件支持map和list格式数据,需要另写方法支持
        if (!props.containsKey(CONFIG_FILENAME)) {
            Properties prop = new Properties();
            prop = getPropertiesByFileName(CONFIG_FILENAME);

            if (prop.get(SPRING_PROFILES_ACTIVE) != null) {
                // 依次读取指定的配置文件
                for (String partName : prop.get(SPRING_PROFILES_ACTIVE).toString().split(",")) {
                    prop.putAll(getPropertiesByFileName(SPRING_BOOT_PROFILE_TEMPLATE.replace("{profile}", partName)));
                }
            }
            props.put(CONFIG_FILENAME, prop);
        }
        Object obj = props.get(CONFIG_FILENAME).get(key);
        if (obj == null) {
            return null;
        } else {
            return obj.toString();
        }
    }

    /**
     * 根据配置文件名称和属性key得到对应的属性值.<br>
     * 一般用于非spring boot约定的配置文件名称,比如集成其它系统的功能时,有固定名称的配置文件,或兼容旧系统<br>
     * <font color=red>注意: 暂不支持yml文件属性读取</font>
     * 
     * @param configFileName 配置文件名称
     * @param key 属性key值
     * @return
     * 
     */
    public static String getPropsValueByKey(String configFileName, String key) {
        // TODO 暂时不支持读取yml格式文件,yml文件支持map和list格式数据,需要另写方法支持
        if (!props.containsKey(configFileName)) {
            props.put(configFileName, loadPropFromFile(configFileName));
        }
        return props.get(configFileName).getProperty(key);
    }

    /**
     * 根据文件名称获取Properties
     * 
     * @param fileName 文件名
     * @return
     */
    private static Properties getPropertiesByFileName(String fileName) {
        String fileFullName = fileName + DEFAULT_SUFFIX;
        InputStream inputStream = ConfigUtil.class.getClassLoader().getResourceAsStream(fileFullName);

        if (inputStream == null) {
            fileFullName = fileName + YML_SUFFIX;
            // 读取yml配置文件
            inputStream = ConfigUtil.class.getClassLoader().getResourceAsStream(fileFullName);
            return loadYmlFromFile(fileFullName);
        } else {
            // 读取properties文件
            return loadPropFromFile(fileFullName);
        }
    }

    public static String getBody(String bodyName,JSONObject jsonObject) {
        String body = (String) jsonObject.get(bodyName);
        String reqBody = body;
        String pattern = "\\$\\{.*?\\}";
        Pattern r = Pattern.compile(pattern);
        Matcher matcher = r.matcher(body);
        while (matcher.find()) {
            String substring = body.substring(matcher.start(), matcher.end());
            String s = getPropsValueByKey(substring.substring(2, substring.length() - 1));
            reqBody = reqBody.replace(substring, s);
        }
        return reqBody;
    }

}
作者 east
Android 12月 7,2020

Android绘制饼图例子

public class MeFragment extends Fragment {
private View view;
private PieChartView pieChart;
PieChartData pieChardata;
List<SliceValue> values = new ArrayList<SliceValue>();
private int[] data = {21, 20, 9, 2, 8};
private int[] colorData = {Color.parseColor("#ec063d"),
Color.parseColor("#f1c704"),
Color.parseColor("#c9c9c9"),
Color.parseColor("#2bc208"),
Color.parseColor("#333333")};
private String[] stateChar = {"提示", "故障", "离线", "正常", "未激活"};

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_me, null);
setPieChartData();
initPieChart();
pieChart.setOnValueTouchListener(selectListener);//设置点击事件监听
return view;
}

public void initPieChart() {
pieChart = (PieChartView) view.findViewById(R.id.chart);
pieChardata = new PieChartData();
pieChardata.setHasLabels(false);//显示表情
pieChardata.setHasLabelsOnlyForSelected(false);//不用点击显示占的百分比
pieChardata.setHasLabelsOutside(false);//占的百分比是否显示在饼图外面
pieChardata.setHasCenterCircle(true);//是否是环形显示
pieChardata.setValues(values);//填充数据
pieChardata.setCenterCircleColor(Color.WHITE);//设置环形中间的颜色
pieChardata.setCenterCircleScale(0.7f);//设置环形的大小级别
pieChart.setPieChartData(pieChardata);
pieChart.setValueSelectionEnabled(true);//选择饼图某一块变大
pieChart.setAlpha(0.9f);//设置透明度
pieChart.setCircleFillRatio(1f);//设置饼图大小
}

private void setPieChartData() {
for (int i = 0; i < data.length; ++i) {
SliceValue sliceValue = new SliceValue((float) data[i], colorData[i]);
values.add(sliceValue);
}
}

private PieChartOnValueSelectListener selectListener = new PieChartOnValueSelectListener() {

@Override
public void onValueDeselected() {
// TODO Auto-generated method stub

}

@Override
public void onValueSelected(int arg0, SliceValue value) {
//选择对应图形后,在中间部分显示相应信息
pieChardata.setCenterText1(stateChar[arg0]);
pieChardata.setCenterText1Color(colorData[arg0]);
pieChardata.setCenterText1FontSize(10);
pieChardata.setCenterText2(value.getValue() + "(" + calPercent(arg0) + ")");
pieChardata.setCenterText2Color(colorData[arg0]);
pieChardata.setCenterText2FontSize(12);
Toast.makeText(getContext(), stateChar[arg0] + ":" + value.getValue(), Toast.LENGTH_SHORT).show();
}
};

private String calPercent(int i) {
String result = "";
int sum = 0;
for (int i1 = 0; i1 < data.length; i1++) {
sum += data[i1];
}
result = String.format("%.2f", (float) data[i] * 100 / sum) + "%";
return result;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/base"
android:gravity="center"
android:padding="10dp">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/me_title"
android:textColor="@color/white"
android:textSize="@dimen/title" />
</LinearLayout>

<LinearLayout
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<lecho.lib.hellocharts.view.PieChartView
android:id="@+id/chart"
android:layout_width="200dp"
android:layout_height="200dp" />
</LinearLayout>

</LinearLayout>
作者 east
Android 12月 7,2020

Android获取用户的地理位置工具类

public class GPSUtils {

private static GPSUtils instance;
private Context mContext;
private LocationManager locationManager;

private GPSUtils(Context context) {
this.mContext = context;
}

public static GPSUtils getInstance(Context context) {
if (instance == null) {
instance = new GPSUtils(context);
}
return instance;
}

/**
* 获取经纬度
*
* @return
*/
public String getLngAndLat(OnLocationResultListener onLocationResultListener) {
double latitude = 0.0;
double longitude = 0.0;

mOnLocationListener = onLocationResultListener;

String locationProvider = null;
locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//获取所有可用的位置提供器
List<String> providers = locationManager.getProviders(true);

if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS
locationProvider = LocationManager.GPS_PROVIDER;
} else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是Network
locationProvider = LocationManager.NETWORK_PROVIDER;
} else {
Intent i = new Intent();
i.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(i);
return null;
}

//获取Location
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location != null) {
//不为空,显示地理位置经纬度
if (mOnLocationListener != null) {
mOnLocationListener.onLocationResult(location);
}

}
//监视地理位置变化
locationManager.requestLocationUpdates(locationProvider, 3000, 1, locationListener);
return null;
}


public LocationListener locationListener = new LocationListener() {

// Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

// Provider被enable时触发此函数,比如GPS被打开
@Override
public void onProviderEnabled(String provider) {

}

// Provider被disable时触发此函数,比如GPS被关闭
@Override
public void onProviderDisabled(String provider) {

}

//当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
@Override
public void onLocationChanged(Location location) {
if (mOnLocationListener != null) {
mOnLocationListener.OnLocationChange(location);
}
}
};

public void removeListener() {
locationManager.removeUpdates(locationListener);
}

private OnLocationResultListener mOnLocationListener;

public interface OnLocationResultListener {
void onLocationResult(Location location);

void OnLocationChange(Location location);
}
}
作者 east
Android 12月 7,2020

Android下载工具类

如果要下载在外部存储空间,要看外部存储空间是否可用。

public class DownloadUtil {
private static DownloadUtil downloadUtil;
private final OkHttpClient okHttpClient;

public static DownloadUtil get() {
if (downloadUtil == null) {
downloadUtil = new DownloadUtil();
}
return downloadUtil;
}

private DownloadUtil() {
okHttpClient = new OkHttpClient();
}

/**
* @param url 下载连接
* @param destFileDir 下载的文件储存目录
* @param destFileName 下载文件名称
* @param listener 下载监听
*/
public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 下载失败监听回调
listener.onDownloadFailed(e);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
// 储存下载文件的目录
File dir = new File(getSDPath(destFileDir));
if (!dir.exists()) {
boolean b= dir.mkdirs();
}
File file = new File(dir, destFileName);
try {
is = response.body().byteStream();
long total = response.body().contentLength();
fos = new FileOutputStream(file);
long sum = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
// 下载中更新进度条
listener.onDownloading(progress);
}
fos.flush();
// 下载完成
listener.onDownloadSuccess(file);
} catch (Exception e) {
listener.onDownloadFailed(e);
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
});
}

public interface OnDownloadListener {
/**
* @param file 下载成功后的文件
*/
void onDownloadSuccess(File file);

/**
* @param progress 下载进度
*/
void onDownloading(int progress);

/**
* @param e 下载异常信息
*/
void onDownloadFailed(Exception e);
}

public String getSDPath(String dirName) {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED);
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();//获取根目录
Log.e("Test", "外部存储可用..." + sdDir.toString());
}
return sdDir.toString()+"/"+dirName;
}
}
作者 east
Java 12月 7,2020

Excel快速导入导出工具(仅提供excel2007以及更高版本的支持)

public class ExcelWriter {

/** 日志 */
private static Logger LOG = LoggerFactory.getLogger(ExcelWriter.class);

/** 原生HttpServletResponse对象 */
private HttpServletResponse response = null;

/**
* 用于导入excel的构造函数
*/
private ExcelWriter() {

}

/**
* 用于导出excel的构造函数 <br>
* List(Bean)格式
*
* @param clazz
* @param response
*/
private ExcelWriter(Class<?> clazz, HttpServletResponse response) {
// this.clazz == clazz;
this.response = response;
}

/**
* 用于导出excel的构造函数 <br>
* List(String[]) 格式
*
* @param response
*/
private ExcelWriter(HttpServletResponse response) {
this.response = response;
}

/**
* 用于浏览器导出excel的实例化
*
* @param clazz 实体Class对象
* @param response 原生HttpServletResponse对象
* @return ExcelUtils
*/
public static ExcelWriter exportInit(HttpServletResponse response) {
return new ExcelWriter(response);
}

/**
* 用于浏览器导出excel的实例化
*
* @param clazz 实体Class对象
* @param response 原生HttpServletResponse对象
* @return ExcelUtils
*/
public static ExcelWriter exportInit(Class<?> clazz, HttpServletResponse response) {
return new ExcelWriter(clazz, response);
}

/**
* 导出Excel,响应到浏览器下载(List<String[]>格式)
*
* @param headers 表头
* @param data 数据
* @param fileName 文件名称
* @param sheetName 工作表名
* @return
*/
public boolean writeExcel(List<String> headers, List<String[]> datas, String fileName, String sheetName) {
if (response == null) {
throw new IllegalArgumentException("请先使用exportInit(HttpServletResponse)初始化参数。");
}
long begin = System.currentTimeMillis();

if (ListUtils.isEmpty(datas)) {
LOG.error("没有检测到数据,不执行导出操作。");
return false;
}
int dataSize = datas.size();
LOG.info(String.format("即将导出excel数据 : %s条,请稍后...", dataSize));
try {
// 输出流
OutputStream outputStream = response.getOutputStream();
// 创建新的工作薄
SXSSFWorkbook wb = PoiUtils.newSXSSFWorkbook();
// 表头的样式
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
// 对齐
cellStyle.setAlignment(CellStyle.ALIGN_LEFT);
font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
// 字体大小
font.setFontHeightInPoints((short) 12);
font.setFontName("宋体");
// 应用标题字体到标题样式
cellStyle.setFont(font);
// 设置单元格文本形式
DataFormat dataFormat = wb.createDataFormat();
cellStyle.setDataFormat(dataFormat.getFormat("@"));

// 表头的值
String headerValue = null;
// 单元格的值
String cellValue = null;
// 创建sheet
SXSSFSheet sheet = PoiUtils.newSXSSFSheet(wb, sheetName);
// 创建行表头
SXSSFRow headerRow = PoiUtils.newSXSSFRow(sheet, 0);
for (int i = 0, size = headers.size(); i < size; i++) {
headerValue = headers.get(i);
SXSSFCell cell = PoiUtils.newSXSSFCell(headerRow, i);
cell.setCellValue(headerValue);
cell.setCellStyle(cellStyle);
}

// 明细行数组
String[] bodys = null;
for (int i = 0; i < dataSize; i++) {
// 创建行数据
SXSSFRow bodyRow = PoiUtils.newSXSSFRow(sheet, i + 1);
bodys = datas.get(i);
for (int j = 0, len = bodys.length; j < len; j++) {
cellValue = bodys[j];
if (StringUtils.isBlank(cellValue)) {
// FIXME: 当值为""时,当前index的cell会失效,这里设置为null
cellValue = null;
}

// 创建列
SXSSFCell cell = PoiUtils.newSXSSFCell(bodyRow, j);
cell.setCellValue(cellValue);
cell.setCellType(SXSSFCell.CELL_TYPE_STRING);
}
}

writeByBrowser(response, fileName, wb, outputStream);
LOG.info(String.format("excel处理完成,共生成数据 : %s行,耗时 : %s seconds.", dataSize,
(System.currentTimeMillis() - begin) / 1000.0));
} catch (Exception e) {
LOG.error("导出excel失败 : " + e.getMessage(), e);
}
return true;
}

/**
* 响应到浏览器下载
*
* @param response
* @param fileName
* @param wb
* @param out
* @throws Exception
*/
private static void writeByBrowser(HttpServletResponse response, String fileName, SXSSFWorkbook wb,
OutputStream out) throws Exception {
// response对象不为空,响应到浏览器下载
if (response != null) {
response.setContentType(ConstantUtils.CONTENT_TYPE);
response.setCharacterEncoding("UTF-8");
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1") + ConstantUtils.XLSX_SUFFIX;
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
if (out == null) {
out = response.getOutputStream();
}
}
wb.write(out);
out.flush();
out.close();
}

/**
* 保存文件到本地
*
* @param headers 表头
* @param datas 转换好的数据
* @param filePath 路径
* @param sheetName 工作表名
* @param type 类型 0-转换成功 1-转换失败
*/
public static void saveByLocal(List<String> headers, List<String[]> datas, String filePath, int type) {
long begin = System.currentTimeMillis();

if (ListUtils.isEmpty(datas)) {
LOG.error("没有检测到数据,不执行导出操作。");
return;
}
int dataSize = datas.size();
LOG.info(String.format("即将保存excel数据 : %s条,请稍后...", dataSize));
// 输出流
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
String sheetName = "";
if (type == 0) {
sheetName = PropertyUtils.getProperty("successConversion");
} else if (type == 1) {
sheetName = PropertyUtils.getProperty("failConversion");
}
// 创建新的工作薄
SXSSFWorkbook wb = PoiUtils.newSXSSFWorkbook();
// 表头的样式
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
// 对齐
cellStyle.setAlignment(CellStyle.ALIGN_LEFT);
font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
// 字体大小
font.setFontHeightInPoints((short) 12);
font.setFontName("宋体");
// 应用标题字体到标题样式
cellStyle.setFont(font);
// 设置单元格文本形式
DataFormat dataFormat = wb.createDataFormat();
cellStyle.setDataFormat(dataFormat.getFormat("@"));

// 表头的值
String headerValue = null;
// 单元格的值
String cellValue = null;
// 创建sheet
SXSSFSheet sheet = PoiUtils.newSXSSFSheet(wb, sheetName);
// 创建行表头
SXSSFRow headerRow = PoiUtils.newSXSSFRow(sheet, 0);
for (int i = 0, size = headers.size(); i < size; i++) {
headerValue = headers.get(i);
SXSSFCell cell = PoiUtils.newSXSSFCell(headerRow, i);
cell.setCellValue(headerValue);
cell.setCellStyle(cellStyle);
}

// 明细行数组
String[] bodys = null;
for (int i = 0; i < dataSize; i++) {
// 创建行数据
SXSSFRow bodyRow = PoiUtils.newSXSSFRow(sheet, i + 1);
bodys = datas.get(i);
for (int j = 0, len = bodys.length; j < len; j++) {
cellValue = bodys[j];
if (StringUtils.isBlank(cellValue)) {
// FIXME: 当值为""时,当前index的cell会失效,这里设置为null
cellValue = null;
}

// 创建列
SXSSFCell cell = PoiUtils.newSXSSFCell(bodyRow, j);
cell.setCellValue(cellValue);
cell.setCellType(SXSSFCell.CELL_TYPE_STRING);
}
}

wb.write(bufferedOutputStream);
LOG.info(String.format("excel处理完成,共生成数据 : %s行,耗时 : %s seconds.", dataSize,
(System.currentTimeMillis() - begin) / 1000.0));
} catch (Exception e) {
LOG.error("保存excel失败 : " + e.getMessage(), e);
} finally {
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
LOG.error("文件流关闭异常");
}
}
}
}

}
作者 east
Java 12月 7,2020

GAT1400视图库没有视图库账户对接遇到的坑

没有视图库账号对接视图库,把DeviceId没有写自己的视图库账号,错误写成要对接的视图库账号,一直返回“用户名错误”。后来才知道,只要按照GAT1400标准,20位的视图库账号可以自己按照标准进行编写一个,然后让要对接的视图库厂商后台配置一下。

作者 east
Java 12月 7,2020

用AOP写的日志管理工具

 使用AOP,将日志记录,异常报告等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。 
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Component
@Aspect
public class LogManageUtil {
private static Logger logger = LoggerFactory.getLogger(LogManageUtil.class);
private static final String serverName = "cloudsearch";
private static final Integer showRows = 5;

@Pointcut("execution(* com.funny.services.web..*.*(..))")
public void controllerLogProxy() {

}

@Before("controllerLogProxy()")
public void beforeLogInfo(JoinPoint joinPoint) {
Object[] params = joinPoint.getArgs();
String paramStr = "";
for (int i = 0; i < params.length; i++) {
Object param = params[i];
if (i == 0){
logger.info(param.getClass().getSimpleName());
if(param.getClass().getSimpleName().equals("SessionRepositoryRequestWrapper")) {
paramStr = "该接口无参数";
}else{
paramStr += JSONObject.toJSONString(param);
}
}

else
paramStr += "," + JSONObject.toJSONString(param);
}
logger.info("service:[" + serverName + "] -- API:[" + getApiUrl() + "] 请求参数:" + paramStr);
}

@AfterReturning(pointcut = "controllerLogProxy()", returning = "result")
public void afterLogInfo(Object result) {
if (result instanceof ResultData) {
ResultData tmpRs = (ResultData) result;
ResultData rs = new ResultData();
BeanUtils.copyProperties(tmpRs, rs);
if (rs.getCode()==ResultStatus.SUCCESS_CODE) {
if (rs.getData() instanceof List) {
List<Object> list = (List) rs.getData();
List<Object> tmpList = new ArrayList<>();
if (list != null && (list.size() > showRows)) {
for (int i = 0; i < showRows; i++) {
tmpList.add(list.get(i));
}
Object more = "more...";
tmpList.add(more);
rs.setData(tmpList);
}
}
}
logger.info("service:[" + serverName + "] -- API:[" + getApiUrl() + "] 返回结果:" + JSONObject.toJSONString(rs));
}
}

public static String getApiUrl() {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
String url = request.getRequestURL().toString();
int startIndex = url.indexOf(serverName);
String ApiUrl = url.substring(startIndex + serverName.length(), url.length());
return ApiUrl;
}

public static void serviceErrorPrint(Exception e) {
logger.error("service:[" + serverName + "] -- API:[" + getApiUrl() + "] 错误信息:" + e.getMessage());
}


}
作者 east
Spark, 数据挖掘 11月 17,2020

Spark新闻App点击率预估实践案例

import org.apache.spark.sql.{SparkSession}

//action:userid~ docid ~behaivor(label)~time~ip
//160520092238579653~160704235940001~0~20160705000040909~1.49.185.165
//160520092238579653~160704235859003~0~20160705000040909~1.49.185.165
//define case class for action data
case class Action(docid: String, label:Int)

//document:docid ~ channelname ~ source ~ keyword:score
//160705131650005~科技~偏执电商~支付宝:0.17621 医疗:0.14105 复星:0.07106 动作:0.05235 邮局:0.04428
//160705024106002~体育~平大爷的刺~阿杜:0.23158 杜兰特:0.09447 巨头:0.08470 拯救者:0.06638 勇士:0.05453
//define case class for document data
case class Dccument(docid: String, channal: String, source: String, tags: String)

object GenTrainingData {
  def main(args: Array[String]): Unit = {

    //2rd_data/ch09/action.txt 2rd_data/ch09/document.txt output/ch11 local[2]
    val Array(actionPath, documentPath, output, mode) = args
    // 创建Spark实例
    val spark = SparkSession.builder
      .master(mode)
      .appName(this.getClass.getName)
      .getOrCreate()

    import spark.implicits._
    val ActionDF = spark.sparkContext.textFile(actionPath).map(_.split("~"))
      .map(x => Action(x(1).trim.toString, x(2).trim.toInt))
      .toDF()
    // Register the DataFrame as a temporary view
    //ActionDF.createOrReplaceTempView("actiondf")

    val documentDF = spark.sparkContext.textFile(documentPath).map(_.split("~")).filter(_.length > 3)
      .map { case x =>
        val xtags = x(3).split(" ").filter(_.length > 0).map { b => b.substring(0, b.indexOf(":")) }.mkString("|")
        Dccument(x(0).trim.toString, x(1).trim.toString, x(2).trim.toString, xtags.toString)
      }
      .toDF()
    // Register the DataFrame as a temporary view
    //documentDF.createOrReplaceTempView("documentdf")

    // 将查询结果放到tempDF中,完成dataframe转化
    //val tempDF = spark.sql("select actiondf.docid,actiondf.label,documentdf.channal,documentdf.source,documentdf.tags from actiondf,documentdf where actiondf.docid = documentdf.docid")
    val tempDF = documentDF.join(ActionDF, documentDF("docid").equalTo(ActionDF("docid")))
    //tempDF.select($"tags").show(100)

    // 编码格式转换
    val minDF = tempDF.select($"tags").rdd
      .flatMap{ x => x.toString.replace("[","").replace("]","").split('|') }.distinct
    //minDF.coalesce(1).saveAsTextFile(output+"/tags")
    val indexes = minDF.collect().zipWithIndex.toMap
    println(indexes.toList.length) //23937
    //
    val libsvmDF = tempDF.select($"label", $"tags").map {
      x =>
        val label = x(0)
        val terms = x(1).toString.replace("[","").replace("]","")
          .split('|') //使用单引号
          .map(v => (indexes.get(v).getOrElse(-1)+1, 1)) //索引从0开始
          .sortBy(_._1) //libsvm 需要升序
          .map(x => x._1 + ":" + x._2)
          .mkString(" ")
        (label.toString + " " + terms)
    }
    libsvmDF.show(100)

    //保存模型时存在:Exception while deleting local spark dir,不影响结果生成,作为已知问题暂时搁置。
    //libsvmDF.coalesce(1).write.format("text").save(output+"/model")
    //libsvmDF.rdd.coalesce(1).saveAsTextFile(output+"/model")
    val Array(trainingdata, testdata) = libsvmDF.randomSplit(Array(0.7, 0.3))
    trainingdata.rdd.coalesce(1).saveAsTextFile(output+"/training")
    testdata.rdd.coalesce(1).saveAsTextFile(output+"/test")
    //
    //spark.stop()
  }
}
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.mllib.evaluation.BinaryClassificationMetrics

object LRTrainAndTest {

  def main(args: Array[String]) {

    if (args.length < 8) {
      System.err.println("Usage:LRTrainAndTest <trainingPath> <testPath> <output> <numFeatures> <partitions> <RegParam> <NumIterations> <NumCorrections>")
      System.exit(1)
    }

    //2rd_data/ch11/test/part-00000 2rd_data/ch11/training/part-00000 output/ch11/label 23937 50 0.01 100 10
    val conf = new SparkConf()
      .setMaster("local")
      .setAppName("ADTest with logistic regression")
    val sc = new SparkContext(conf)
    val numFeatures = args(3).toInt //特征数23937
    val partitions = args(4).toInt //一般50-1000

    //label channal source tags
    //依次为:类别(是否点击,点击为1,没有点击为0)、频道、来源、关键词
    //样例:1 娱乐 腾讯娱乐 曲妖精|棉袄|王子文|老大爷|黑色

    // 导入训练样本和测试样本
    val training = MLUtils.loadLibSVMFile(sc,args(0),numFeatures,partitions)
    val test = MLUtils.loadLibSVMFile(sc,args(1),numFeatures,partitions)

    val lr = new LogisticRegressionWithLBFGS()

    //训练参数设置
    lr.optimizer.setRegParam(args(5).toDouble) //0.01
      .setNumIterations(args(6).toInt) //100
      .setNumCorrections(args(7).toInt) //10

    //训练
    val lrModel = lr.setNumClasses(2).run(training)//2分类
    lrModel.clearThreshold()

    //预测打分
    val predictionAndLabel = test.map(p=>(lrModel.predict(p.features),p.label))
    predictionAndLabel.map(x=>x._1+"\t"+x._2).repartition(1)
      .saveAsTextFile(args(2))
    val metrics = new BinaryClassificationMetrics(predictionAndLabel)

    //计算AUC
    val str = s"the value of auc is ${metrics.areaUnderROC()}"
    println(str)
  }
}
作者 east
Spark, 数据挖掘 11月 17,2020

Spark企业法人建模案例

数据格式如下:

字段含义参考上一节。

样例如下:

package com.koala.ch12

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.DataFrame
import org.apache.spark.ml.feature.VectorAssembler
import org.apache.spark.ml.classification.LogisticRegression

object CreditModel {

  // 创建评分模型属性class,对字段进行命名
  // 0,1,37,10,0,3,18,7,4
  case class Credit(load_label:Double,gender:Double,age:Double,yearsmarried:Double,children:Double,housenumber:Double,captiallevel:Double,facarnumber:Double,pacarnumber:Double)

  def main(args: Array[String]) {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    if (args.length < 3){
      System.err.println("Usage:CreditModel <creaditInPath> <outPut> <model>")
      System.exit(1)
    }

    //2rd_data/ch12/creditdata.txt output/ch12/model local[2]
    val Array(creaditInPath,output,mode) = args

    // 创建Spark实例
    val spark = SparkSession.builder
      .master(mode)
      .appName("CreditModel Example")
      .getOrCreate()

    // 加载文本,并创建RDD数据源,将变量的名称赋予各个字段
    // Create an RDD of Credit objects from a text file, convert it to a Dataframe
    import spark.implicits._
    val creditDF = spark.sparkContext.textFile(creaditInPath).map(_.split(","))
      .map(attributes => Credit(attributes(0).trim.toDouble,attributes(1).trim.toDouble,attributes(2).trim.toDouble,attributes(3).trim.toDouble,attributes(4).trim.toDouble,attributes(5).trim.toDouble,attributes(6).trim.toDouble,attributes(7).trim.toDouble,attributes(8).trim.toDouble))
      .toDF()

    // Register the DataFrame as a temporary view
    // 创建临时视图
    creditDF.createOrReplaceTempView("creditdf")

    // 将查询结果放到sqlDF中,完成dataframe转化
    val sqlDF = spark.sql("select * from creditdf")
    sqlDF.show()

    // 自变量的列名
    val colArray2 = Array("gender","age","yearsmarried","children","housenumber","captiallevel","facarnumber","pacarnumber")
    // 设置DataFrame自变量集,并将这些变量统称为"features"
    val vecDF: DataFrame = new VectorAssembler().setInputCols(colArray2).setOutputCol("features").transform(sqlDF)

    // 按7:3划分成训练集和测试集,训练集为trainingDF,测试集为testDF
    val Array(trainingDF,testDF) = vecDF.randomSplit(Array(0.7, 0.3), seed=132) //seed随机算法从该数字开始生成随机数字

    // 建立逻辑回归模型,设置目标变量(标签)和自变量集,在训练集上训练
    val lrModel = new LogisticRegression().setLabelCol("load_label").setFeaturesCol("features").fit(trainingDF)
    // 输出逻辑回归的系数和截距
    println(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}")

    // 惩罚项,如果是0,是L2惩罚,如果是0-1之间是混合,如果是1,则是L1惩罚,默认是L2
    lrModel.getElasticNetParam
    // 正则化的参数,一般大于等于0,默认是0
    lrModel.getRegParam
    // 拟合之前是否需要标准化,默认是true
    lrModel.getStandardization
    // 二分类中设置阈值,范围为[0,1],如果类标签的1的概率大于该阈值,则会判定为1,默认是0.5
    lrModel.getThreshold
    // 设置迭代的收敛容限,默认值为1e-6
    lrModel.getTol

    // 使用测试集进行预测,包括原始的字段,在加上综合的自变量集字段features,预测的原始值,转化的概率值,预测的类别
    lrModel.transform(testDF).show

    //具体的查看features,预测的原始值,转化的概率值,预测的类别
    lrModel.transform(testDF).select("features","rawPrediction","probability","prediction").show(30,false)

    //查看模型训练过程中损失的迭代情况
    val trainingSummary = lrModel.summary
    val objectiveHistory = trainingSummary.objectiveHistory
    objectiveHistory.foreach(loss => println(loss))
    //保存模型
    lrModel.save(output)
    //
    spark.close()
  }
}
作者 east
Spark, 数据挖掘 11月 17,2020

Spark道路拥堵模式聚类案例

从基础的道路通行状态统计、分析、聚类等维度开展对某个城市道路拥堵情况的分析和研究。

13.3.2 数据预处理根据给定的某地图路况数据,首先进行数据预处理工作,清洗原始数据并去除缺失数据、错误数据,根据道路ID进行数据汇集,计算拥堵指数。1)清除缺失数据:清除字段为空记录;

2)清除错误数据:清除字段错误记录;

3)根据道路ID进行道路拥堵指数聚合;

4)根据时间进行道路拥堵指数排序。

13.3.3 特征构建仍然以半小时为最小时间粒度(每日24小时划分为48维时间片),并对道路拥堵指数按时间片进行聚合计算,同时按照48维时间片进行拥堵指数排列。具体处理过程以及代码如下:

package com.koala.ch13

import org.apache.spark.{SparkConf, SparkContext}
import java.text.SimpleDateFormat
import java.util.Calendar

import breeze.linalg.Counter
import org.apache.log4j.{Level, Logger}

object CrowdModel {

  def main(args: Array[String]){
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    if (args.length < 2) {
      System.err.println("Usage:CrowdModel <InPath> <OutPut> <Model>")
      System.exit(1)
    }

    // 2rd_data/ch13/user_location_sample.txt output/ch13/CrowdModel local[2]
    val Array(input,output,mode) = args

    //初始化SparkContext
    val conf = new SparkConf()
      .setMaster(mode)//.setMaster("local")
      .setAppName(this.getClass.getSimpleName)
    val sc = new SparkContext(conf)

    // 位置筛选
    // 清洗数据,通过split(",")切分数据,得到 User_id Time_stamp Cell_id三个维度的数据列表。
    // (Time_stamp,Cell_id,User_id)-> (User_id,Time_stamp,Cell_id)
    // 20160501055052,209059,898
    val data = sc.textFile(input).map(_.split(",")).map {
      x => (x(2), x(0), x(1))
    }
    //data.coalesce(1).saveAsTextFile(output)

    // 根据Time_stamp分析当前日期为工作日或节假日,并添加time标签标识HH:mm,work_flag标签标识工作日(work_falg=1)或节假日(work_flag=0)
    // 输出:(User_id,work_flag,date_time,Cell_id)
    val preData = data.map {
      case (preUser_id, preTime_stamp, preCell_id) => {

        //将日期转变成星期,获取工作日(星期一至星期五)和非工作日(星期六、星期日)
        // 20160501 055052
        val sdf = new SimpleDateFormat("yyyyMMddHHmmss") //24小时工作制
        val date = sdf.parse(preTime_stamp)
        val cal = Calendar.getInstance
        cal.setTime(date)
        var w = cal.get(Calendar.DAY_OF_WEEK) - 1
        // 工作日默认为1 非工作日默认为0
        var work_flag = 1
        if (w <= 0 || w >= 6) {
          work_flag = 0
        }

        // 按照30分钟间隔处理时间
        val time_ = preTime_stamp.substring(8, 12)
        // 截取指定位置的元素,前包括后不包括
        var minute_ = "00"
        if (time_.substring(2).toInt >= 30) {
          minute_ = "30"
        }
        val date_time = time_.toString.substring(0, 2) + minute_
        ((preUser_id, work_flag, date_time, preCell_id), 1)
      }
    }
    //preData.coalesce(1).saveAsTextFile(output)

    //使用reduceByKey(_+_)对(User_id,work_flag,date_time,Cell_id)访问次数进行聚合,根据聚合结果,选择用户某段时间在30分钟内划分访问次数最多的基站为标准访问地点。
    val aggData = preData.reduceByKey(_ + _)
      .map { x => ((x._1._1, x._1._2, x._1._3), (x._1._4, x._2)) }
      .reduceByKey((a, b) => if (a._2 > b._2) a else b)//选取访问次数最多的cell
    //aggData.coalesce(1).saveAsTextFile(output)

    //获取用户工作日24小时访问地点cell_id、节假日24小时访问地点cell_id,以30分钟为最小时间粒度划分时间片,得到user_id工作日48维时间片访问cell_id和节假日48维时间片访问cell_id,共计96维时间片。
    //(User_id,work_flag,date_time),(Cell_id,nums)->(User_id,work_flag),(date_time,Cell_id)

    val slotData = aggData.map { x => ((x._1._1, x._1._2), (x._1._3 + ":" + x._2._1)) }.reduceByKey(_ + ";" + _)
    //slotData.coalesce(1).saveAsTextFile(output)

    // 位置编码
    // 根据聚合结果,提取所有用户访问的基站进行重新编码,获得用户访问位置列表cell_id,并进行排序去重
    // (User_id,work_flag,date_time),(Cell_id,nums)
    val minCell = aggData.map(x => x._2._1).sortBy(x=>x.toLong,true).collect().distinct
    println(minCell.toList)
    //使用zip方法从1开始对用户访问地址进行编码,并将编码进行保存。
    val index_list = minCell.zip(Stream from 1).toMap
    println(index_list)
    //得到的index_list即是用户访问位置编码特征向量。
  }
}
import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}

object CleanCongestionData {

  def main(args: Array[String]) {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    if (args.length < 2) {
      System.err.println("Usage:CleanCongestionData <InPath> <OutPut> <Model>")
      System.exit(1)
    }

    // 2rd_data/ch13/road_congestion_sample.txt output/ch13/CongestionModel local[2]
    val Array(input,output,mode) = args

    // 初始化SparkContext
    val conf = new SparkConf()
      .setMaster(mode)//.setMaster("local")
      .setAppName(this.getClass.getSimpleName)
    val sc = new SparkContext(conf)

    // 计算link的拥堵情况,指定道路、工作日状态、时间片时,link拥堵指数的平均值(四舍五入)取整,
    // key (linkid, work_flag, hour) value (congestion)
    // 85349482;1;20.5;1
    val data = sc.textFile(input).map(_.split(";"))
      .map {x => ((x(0),x(1),x(2)),x(3))}
      .groupByKey().mapValues(x=>{
        val a = x.toList.reduceLeft((sum,i)=>sum +i)//拥堵指数求和
        val b = x.toList.length
        Math.round(a.toInt/b)//平均拥堵指数
      })
    //data.coalesce(1).saveAsTextFile(output)

    // 根据key聚合数据后,使用hour 进行排序 并删除hour数据
    // key (linkid,work_flag, hour) value (congestion)->(linkid) value(work_flag,congestion)
    val collectData = data.sortBy(x=>x._1._3).map(x => ((x._1._1),(x._1._2+":"+x._2))).reduceByKey(_ + ";" + _)
    collectData.coalesce(1).saveAsTextFile(output)
  }
}
作者 east
Java 11月 17,2020

GAT1400的注册流程RFC2617认证

此图像的alt属性为空;文件名为image.png


Authorization 请求头字段

  • response: 客户端根据算法算出的摘要值
  • username: 要认证的用户名
  • realm: 认证域,可取任意标识值
  • uri: 请求的资源位置
  • qop: 保护质量
  • nonce: 服务器密码随机数
  • nc: 16进制请求认证计数器,第一次 00000001
  • algorithm: 默认MD5算法
  • cnonce: 客户端密码随机数

Request-Digest 摘要计算过程

若算法是:MD5 或者是未指定
则 A1= <username>:<realm>:<passwd>

若 qop 未定义或者 auth:
则 A2= <request-method>:<digest-uri-value>

若 qop 为 auth
      response=MD5(MD5(A1):<nonce>:<nc>:<cnonce>:<qop>:MD5(A2)) 
若 qop 没有定义
      response=MD5(MD5(A1):<nonce>:MD5(A2)) 

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.Validate;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Random;

/**
 * Http Digest
 * @author zhouzhixiang
 * @date 2019-05-14
 */
public class Digests {

    private static SecureRandom random = new SecureRandom();
    /**
     * 加密遵循RFC2671规范 将相关参数加密生成一个MD5字符串,并返回
     */
    public static String http_da_calc_HA1(String username, String realm, String password,
                                          String nonce, String nc, String cnonce, String qop,
                                          String method, String uri, String algorithm) {
        String HA1, HA2;
        if ("MD5-sess".equals(algorithm)) {
            HA1 = HA1_MD5_sess(username, realm, password, nonce, cnonce);
        } else {
            HA1 = HA1_MD5(username, realm, password);
        }
        byte[] md5Byte = md5(HA1.getBytes());
        HA1 = new String(Hex.encodeHex(md5Byte));

        md5Byte = md5(HA2(method, uri).getBytes());
        HA2 = new String(Hex.encodeHex(md5Byte));

        String original = HA1 + ":" + (nonce + ":" + nc + ":" + cnonce + ":" + qop) + ":" + HA2;

        md5Byte = md5(original.getBytes());
        return new String(Hex.encodeHex(md5Byte));

    }

    /**
     * algorithm值为MD5时规则
     */
    private static String HA1_MD5(String username, String realm, String password) {
        return username + ":" + realm + ":" + password;
    }

    /**
     * algorithm值为MD5-sess时规则
     */
    private static String HA1_MD5_sess(String username, String realm, String password, String nonce, String cnonce) {
        //      MD5(username:realm:password):nonce:cnonce

        String s = HA1_MD5(username, realm, password);
        byte[] md5Byte = md5(s.getBytes());
        String smd5 = new String(Hex.encodeHex(md5Byte));

        return smd5 + ":" + nonce + ":" + cnonce;
    }

    private static String HA2(String method, String uri) {
        return method + ":" + uri;
    }

    /**
     * 对输入字符串进行md5散列.
     */
    public static byte[] md5(byte[] input) {
        return digest(input, "MD5", null, 1);
    }

    /**
     * 对字符串进行散列, 支持md5与sha1算法.
     */
    private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);

            if (salt != null) {
                digest.update(salt);
            }

            byte[] result = digest.digest(input);

            for (int i = 1; i < iterations; i++) {
                digest.reset();
                result = digest.digest(result);
            }
            return result;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 随机生成numBytes长度数组
     * @param numBytes
     * @return
     */
    public static byte[] generateSalt(int numBytes) {
        Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", (long)numBytes);
        byte[] bytes = new byte[numBytes];
        random.nextBytes(bytes);
        return bytes;
    }

    @Deprecated
    public static String generateSalt2(int length) {
        String val = "";
        Random random = new Random();
        //参数length,表示生成几位随机数
        for(int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if( "char".equalsIgnoreCase(charOrNum) ) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2)%2 == 0 ? 65 : 97;
                val += (char)(random.nextInt(26) + temp);
            } else if( "num".equalsIgnoreCase(charOrNum) ) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val.toLowerCase();
    }


    //测试
    public static void main(String[] args) throws UnsupportedEncodingException {
        // String s = http_da_calc_HA1("povodo", "realm@easycwmp", "povodo",
        //                             "c10c9897f05a9aee2e2c5fdebf03bb5b0001b1ef", "00000001", "d5324153548c43d8", "auth",
        //                             "GET", "/", "MD5");
        // System.out.println("加密后response为:" + s);

        // String s = new String(generateSalt(8),"UTF-8");

        // System.out.println(s);
    }
}

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**

  • Http Digest Request contains POST、GET、PUT
  • @author zhouzhixiang
  • @date 2019-05-14
    */
    public class HttpRequestUtils { private static final Logger logger = LoggerFactory.getLogger(HttpRequestUtils.class); public static void main(String[] args) {
    // String url = “http://192.168.200.117:8087/v2/servers/defaultServer/vhosts/defaultVHost/applications/live/publishers”;
    // String url = “http://192.168.200.117:8087/v2/servers/defaultServer/vhosts/defaultVHost/applications/Relay/streamfiles/1234566/actions/connect?&vhost=defaultVHost&appType=live&appName=Relay&appInstance=definst&connectAppName=Relay&connectAppInstance=definst&streamFile=1234566.stream&mediaCasterType=liverepeater”;
    String param = “”;
    String username = “xxxxxx”;
    String password = “xxxxxx”;
    // String json = “{ \”password\”: \”plmo13579123\”, \”publisherName\”: \”4\”, \”serverName\”: \”defaultServer\”, \”description\”: \”\”, \”saveFieldList\”: [ \”\” ], \”version\”: \”v1.0\” }”;
    // String s = sendPost(url, param, username, password, json); // String s = sendPost(url, param, username, password, json); // -----------------GET-success------------------ String getUrl = "http://192.168.200.117:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications"; // String s = sendGet(getUrl, param, username, password, null); // -----------------GET-success------------------ // -----------------PUT-success------------------ String putUrl = "http://192.168.200.117:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/Relay/streamfiles/6D07D7E7623B95889C33DC5901307461_0/actions/connect"; String putJson = "{ \"vhost\":\"_defaultVHost_\", \"mediaCasterType\":\"liverepeater\" }"; // String s = sendPUT(putUrl, param, username, password, putJson, null); // -----------------PUT-success------------------ // -----------------POST-success------------------ String postUrl = "http://192.168.200.117:8087/v2/servers/_defaultServer_/users"; String postJson = "{ \"password\": \"123456\", \"serverName\": \"_defaultServer_\", \"description\": \"\", \"groups\": [ \"\" ], \"saveFieldList\": [ \"\" ], \"userName\": \"test6\", \"version\": \"v1.0\" }"; // String s = sendPost(postUrl, param, username, password, postJson, null); // -----------------POST-success------------------ // -----------------POST-success------------------ String postUrl2 = "http://192.168.200.117:8087/v2/servers/_defaultServer_/publishers"; String postJson2 = "{ \"password\": \"1579655633@qq.com\", \"name\": \"test11\", \"serverName\": \"_defaultServer_\", \"description\": \"test\", \"saveFieldList\": [ \"\" ], \"version\": \"v1.0\" }"; // String s = sendPost(postUrl2, param, username, password, postJson2, null); // -----------------POST-success------------------ // -----------------DELETE-success------------------ String deleteUrl = "http://192.168.200.117:8087/v2/servers/_defaultServer_/users/test5"; // String deleteJson = "{ \"password\": \"1579655633@qq.com\", \"name\": \"test11\", \"serverName\": \"_defaultServer_\", \"description\": \"test\", \"saveFieldList\": [ \"\" ], \"version\": \"v1.0\" }"; String s = sendDelete(deleteUrl, param, username, password, null, null); // -----------------DELETE-success------------------ System.out.println(s); } static int nc = 0; //调用次数
    private static final String GET = “GET”;
    private static final String POST = “POST”;
    private static final String PUT = “PUT”;
    private static final String DELETE = “DELETE”; /**
    • 向指定URL发送DELETE方法的请求
    • @param url 发送请求的URL
    • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    • @param username 验证所需的用户名
    • @param password 验证所需的密码
    • @param json 请求json字符串
    • @param type 返回xml和json格式数据,默认xml,传入json返回json数据
    • @return URL 所代表远程资源的响应结果
      */
      public static String sendDelete(String url, String param, String username, String password, String json, String type) { StringBuilder result = new StringBuilder();
      BufferedReader in = null;
      try {
      String wwwAuth = sendGet(url, param); //发起一次授权请求
      if (wwwAuth.startsWith(“WWW-Authenticate:”)) {
      wwwAuth = wwwAuth.replaceFirst(“WWW-Authenticate:”, “”);
      } else {
      return wwwAuth;
      }
      nc ++;
      String urlNameString = url + (StringUtils.isNotEmpty(param) ? “?” + param : “”);
      URL realUrl = new URL(urlNameString);
      // 打开和URL之间的连接
      HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection(); // 设置是否向connection输出,因为这个是post请求,参数要放在 // http正文内,因此需要设为true connection.setDoOutput(true); // Read from the connection. Defaultis true. connection.setDoInput(true); // 默认是 GET方式 connection.setRequestMethod(DELETE); // 设置通用的请求属性 setRequestProperty(connection, wwwAuth, realUrl, username, password, DELETE, type); if (!StringUtils.isEmpty(json)) { byte[] writebytes =json.getBytes(); connection.setRequestProperty("Content-Length",String.valueOf(writebytes.length)); OutputStream outwritestream = connection.getOutputStream(); outwritestream.write(json.getBytes()); outwritestream.flush(); outwritestream.close(); } if (connection.getResponseCode() == 200) { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result.append(line); } } else { String errResult = formatResultInfo(connection, type); logger.info(errResult); return errResult; } nc = 0; } catch (Exception e) {
      nc = 0;
      throw new RuntimeException(e);
      } finally {
      try {
      if (in != null) in.close();
      } catch (Exception e2) {
      e2.printStackTrace();
      }
      }
      return result.toString();
      }
    /**
    • 向指定URL发送PUT方法的请求
    • @param url 发送请求的URL
    • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    • @param username 验证所需的用户名
    • @param password 验证所需的密码
    • @param json 请求json字符串
    • @param type 返回xml和json格式数据,默认xml,传入json返回json数据
    • @return URL 所代表远程资源的响应结果
      */
      public static String sendPUT(String url, String param, String username, String password, String json, String type) { StringBuilder result = new StringBuilder();
      BufferedReader in = null;
      try {
      String wwwAuth = sendGet(url, param); //发起一次授权请求
      if (wwwAuth.startsWith(“WWW-Authenticate:”)) {
      wwwAuth = wwwAuth.replaceFirst(“WWW-Authenticate:”, “”);
      } else {
      return wwwAuth;
      }
      nc ++;
      String urlNameString = url + (StringUtils.isNotEmpty(param) ? “?” + param : “”);
      URL realUrl = new URL(urlNameString);
      // 打开和URL之间的连接
      HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection(); // 设置是否向connection输出,因为这个是post请求,参数要放在 // http正文内,因此需要设为true connection.setDoOutput(true); // Read from the connection. Defaultis true. connection.setDoInput(true); // 默认是 GET方式 connection.setRequestMethod(PUT); // Post 请求不能使用缓存 connection.setUseCaches(false); // 设置通用的请求属性 setRequestProperty(connection, wwwAuth,realUrl, username, password, PUT, type); if (!StringUtils.isEmpty(json)) { byte[] writebytes =json.getBytes(); connection.setRequestProperty("Content-Length",String.valueOf(writebytes.length)); OutputStream outwritestream = connection.getOutputStream(); outwritestream.write(json.getBytes()); outwritestream.flush(); outwritestream.close(); } if (connection.getResponseCode() == 200) { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result.append(line); } } else { String errResult = formatResultInfo(connection, type); logger.info(errResult); return errResult; } nc = 0; } catch (Exception e) {
      nc = 0;
      throw new RuntimeException(e);
      } finally {
      try {
      if (in != null) in.close();
      } catch (Exception e2) {
      e2.printStackTrace();
      }
      }
      return result.toString();
      }
    /**
    • 向指定URL发送POST方法的请求
    • @param url 发送请求的URL
    • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    • @param username 验证所需的用户名
    • @param password 验证所需的密码
    • @param json 请求json字符串
    • @param type 返回xml和json格式数据,默认xml,传入json返回json数据
    • @return URL 所代表远程资源的响应结果
      */
      public static String sendPost(String url, String param, String username, String password, String json, String type) { StringBuilder result = new StringBuilder();
      BufferedReader in = null;
      try {
      String wwwAuth = sendGet(url, param); //发起一次授权请求
      if (wwwAuth.startsWith(“WWW-Authenticate:”)) {
      wwwAuth = wwwAuth.replaceFirst(“WWW-Authenticate:”, “”);
      } else {
      return wwwAuth;
      }
      nc ++;
      String urlNameString = url + (StringUtils.isNotEmpty(param) ? “?” + param : “”);
      URL realUrl = new URL(urlNameString);
      // 打开和URL之间的连接
      HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection(); // 设置是否向connection输出,因为这个是post请求,参数要放在 // http正文内,因此需要设为true connection.setDoOutput(true); // Read from the connection. Defaultis true. connection.setDoInput(true); // 默认是 GET方式 connection.setRequestMethod(POST); // Post 请求不能使用缓存 connection.setUseCaches(false); // 设置通用的请求属性 setRequestProperty(connection, wwwAuth,realUrl, username, password, POST, type); if (!StringUtils.isEmpty(json)) { byte[] writebytes =json.getBytes(); connection.setRequestProperty("Content-Length",String.valueOf(writebytes.length)); OutputStream outwritestream = connection.getOutputStream(); outwritestream.write(json.getBytes()); outwritestream.flush(); outwritestream.close(); } if (connection.getResponseCode() == 200 || connection.getResponseCode() == 201) { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result.append(line); } } else { String errResult = formatResultInfo(connection, type); logger.info(errResult); return errResult; } nc = 0; } catch (Exception e) {
      nc = 0;
      throw new RuntimeException(e);
      } finally {
      try {
      if (in != null) in.close();
      } catch (Exception e2) {
      e2.printStackTrace();
      }
      }
      return result.toString();
      }
    /**
    • 向指定URL发送GET方法的请求
    • @param url 发送请求的URL
    • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    • @param username 验证所需的用户名
    • @param password 验证所需的密码
    • @param type 返回xml和json格式数据,默认xml,传入json返回json数据
    • @return URL 所代表远程资源的响应结果
      */
      public static String sendGet(String url, String param, String username, String password, String type) { StringBuilder result = new StringBuilder();
      BufferedReader in = null;
      try {
      String wwwAuth = sendGet(url, param); //发起一次授权请求
      if (wwwAuth.startsWith(“WWW-Authenticate:”)) {
      wwwAuth = wwwAuth.replaceFirst(“WWW-Authenticate:”, “”);
      } else {
      return wwwAuth;
      }
      nc ++;
      String urlNameString = url + (StringUtils.isNotEmpty(param) ? “?” + param : “”);
      URL realUrl = new URL(urlNameString);
      // 打开和URL之间的连接
      HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection();
      // 设置通用的请求属性
      setRequestProperty(connection, wwwAuth,realUrl, username, password, GET, type);
      // 建立实际的连接
      // connection.connect();
      in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      String line;
      while ((line = in.readLine()) != null) {
      result.append(line);
      }
      nc = 0;
      } catch (Exception e) {
      nc = 0;
      throw new RuntimeException(e);
      } finally {
      try {
      if (in != null) in.close();
      } catch (Exception e2) {
      e2.printStackTrace();
      }
      }
      return result.toString();
      }
    /**
    • 生成授权信息
    • @param authorization 上一次调用返回401的WWW-Authenticate数据
    • @param username 用户名
    • @param password 密码
    • @return 授权后的数据, 应放在http头的Authorization里
    • @throws IOException 异常
      */
      private static String getAuthorization(String authorization, String uri, String username, String password, String method) throws IOException { uri = StringUtils.isEmpty(uri) ? “/” : uri;
      // String temp = authorization.replaceFirst(“Digest”, “”).trim();
      String temp = authorization.replaceFirst(“Digest”, “”).trim().replace(“MD5″,”\”MD5\””);
      // String json = “{\”” + temp.replaceAll(“=”, “\”:”).replaceAll(“,”, “,\””) + “}”;
      String json = withdrawJson(authorization);
      // String json = “{ \”realm\”: \”Wowza\”, \” domain\”: \”/\”, \” nonce\”: \”MTU1NzgxMTU1NzQ4MDo2NzI3MWYxZTZkYjBiMjQ2ZGRjYTQ3ZjNiOTM2YjJjZA==\”, \” algorithm\”: \”MD5\”, \” qop\”: \”auth\” }”; JSONObject jsonObject = JSON.parseObject(json);
      // String cnonce = new String(Hex.encodeHex(Digests.generateSalt(8))); //客户端随机数
      String cnonce = Digests.generateSalt2(8);
      String ncstr = (“00000000” + nc).substring(Integer.toString(nc).length()); //认证的次数,第一次是1,第二次是2…
      // String algorithm = jsonObject.getString(“algorithm”);
      String algorithm = jsonObject.getString(“algorithm”);
      String qop = jsonObject.getString(“qop”);
      String nonce = jsonObject.getString(“nonce”);
      String realm = jsonObject.getString(“realm”); String response = Digests.http_da_calc_HA1(username, realm, password,
      nonce, ncstr, cnonce, qop,
      method, uri, algorithm); //组成响应authorization
      authorization = “Digest username=\”” + username + “\”,” + temp;
      authorization += “,uri=\”” + uri
      + “\”,nc=\”” + ncstr
      + “\”,cnonce=\”” + cnonce
      + “\”,response=\”” + response+”\””;
      return authorization;
      }
    /**
    • 将返回的Authrization信息转成json
    • @param authorization authorization info
    • @return 返回authrization json格式数据 如:String json = “{ \”realm\”: \”Wowza\”, \” domain\”: \”/\”, \” nonce\”: \”MTU1NzgxMTU1NzQ4MDo2NzI3MWYxZTZkYjBiMjQ2ZGRjYTQ3ZjNiOTM2YjJjZA==\”, \” algorithm\”: \”MD5\”, \” qop\”: \”auth\” }”;
      */
      private static String withdrawJson(String authorization) {
      String temp = authorization.replaceFirst(“Digest”, “”).trim().replaceAll(“\””,””);
      // String noncetemp = temp.substring(temp.indexOf(“nonce=”), temp.indexOf(“uri=”));
      // String json = “{\”” + temp.replaceAll(“=”, “\”:”).replaceAll(“,”, “,\””) + “}”;
      String[] split = temp.split(“,”);
      Map map = new HashMap<>();
      Arrays.asList(split).forEach(c -> {
      String c1 = c.replaceFirst(“=”,”:”);
      String[] split1 = c1.split(“:”);
      map.put(split1[0].trim(), split1[1].trim());
      });
      return JSONObject.toJSONString(map);
      }
    /**
    • 向指定URL发送GET方法的请求
    • @param url 发送请求的URL
    • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    • @return URL 所代表远程资源的响应结果
      */
      public static String sendGet(String url, String param) {
      StringBuilder result = new StringBuilder();
      BufferedReader in = null;
      try { String urlNameString = url + (StringUtils.isNotEmpty(param) ? "?" + param : ""); URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.connect(); //返回401时需再次用用户名和密码请求 //此情况返回服务器的 WWW-Authenticate 信息 if (((HttpURLConnection) connection).getResponseCode() == 401) { Map<String, List<String>> map = connection.getHeaderFields(); return "WWW-Authenticate:" + map.get("WWW-Authenticate").get(0); } in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result.append(line); } } catch (Exception e) {
      throw new RuntimeException(“get请求发送失败”,e);
      }
      // 使用finally块来关闭输入流
      finally {
      try {
      if (in != null) in.close();
      } catch (Exception e2) {
      e2.printStackTrace();
      }
      }
      return result.toString();
      }
    /**
    • HTTP set request property
      *
    • @param connection HttpConnection
    • @param wwwAuth 授权auth
    • @param realUrl 实际url
    • @param username 验证所需的用户名
    • @param password 验证所需的密码
    • @param method 请求方式
    • @param type 返回xml和json格式数据,默认xml,传入json返回json数据
      */
      private static void setRequestProperty(HttpURLConnection connection, String wwwAuth, URL realUrl, String username, String password, String method, String type)
      throws IOException { if (type != null && type.equals(“json”)) {
      // 返回json
      connection.setRequestProperty(“accept”, “application/json;charset=UTF-8”);
      connection.setRequestProperty(“Content-Type”,”application/json;charset=UTF-8″);
      connection.setRequestProperty(“connection”, “Keep-Alive”);
      connection.setRequestProperty(“user-agent”,
      “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)”);
      } else {
      // 返回xml
      if (!method.equals(GET)) {
      connection.setRequestProperty(“Content-Type”,”application/json;charset=UTF-8″);
      }
      connection.setRequestProperty(“accept”, “/“);
      connection.setRequestProperty(“connection”, “Keep-Alive”);
      // connection.setRequestProperty(“Cache-Control”, “no-cache”);
      connection.setRequestProperty(“user-agent”,
      “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)”); }
      //授权信息
      String authentication = getAuthorization(wwwAuth, realUrl.getPath(), username, password, method);
      connection.setRequestProperty(“Authorization”, authentication);
      }
    /**
    • 格式化请求返回信息,支持json和xml格式
    • @param connection HttpConnection
    • @param type 指定返回数据格式,json、xml,默认xml
    • @return 返回数据
      */
      private static String formatResultInfo(HttpURLConnection connection, String type) throws IOException {
      String result = “”;
      if (type != null && type.equals(“json”)) {
      result = String.format(“{\”errCode\”:%s, \”message\”:%s}”,connection.getResponseCode(),connection.getResponseMessage());
      } else {
      result = String.format(” “
      + ” ” + ” %d” + ” %s” + ” “,connection.getResponseCode(),connection.getResponseMessage());
      }
      return result;
      }

}

作者 east
Java 11月 8,2020

GAT1400人脸相关接口

人脸相关接口

批量人脸新增

1.接口概览

URI /VIID/Faces
方法 查询字符串 消息体 返回结果
POST 无 <FaceList> <ResponseStatusList>
备注  

2.消息体特征参数

消息体结构参考C.9,字段定义参考A.9 。

3.返回消息

         结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/ Faces
请求方法 POST
请求头 参见请求参数
请求体 {     “FaceListObject”: {         “FaceObject”: [             {                 “FaceID”: “650100000011900000010220171219100515999830656599”,                 “InfoKind”: 1,                 “SourceID”: “66000000001190123456022017120110101000007”,                 “DeviceID”: “55000111221190000007”,                 “LeftTopX”: 1,                 “LeftTopY”: 1,                 “RightBtmX”: 1,                 “RightBtmY”: 1,                 “LocationMarkTime”: “19981230010000”,                 “FaceAppearTime”: “19981230010000”,                 “FaceDisAppearTime”: “19981230010000”,                 “IDType”: “111”,                 “IDNumber”: “1”,                 “Name”: “大华”,                 “UsedName”: “dahua”,                 “Alias”: “dahua”,                 “GenderCode”: “1”,                 “AgeUpLimit”: 10,                 “AgeLowerLimit”: 20,                 “EthicCode”: “01”,                 “NationalityCode”: “CHN”,                 “NativeCityCode”: “330108”,                 “ResidenceAdminDivision”: “330100”,                 “ChineseAccentCode”: “1”,                 “JobCategory”: “1”,                 “AccompanyNumber”: 1,                 “SkinColor”: “1”,                 “HairStyle”: “1”,                 “HairColor”: “1”,                 “FaceStyle”: “1”,                 “FacialFeature”: “1”,                 “PhysicalFeature”: “1”,                 “RespiratorColor”: “1”,                 “CapStyle”: “1”,                 “CapColor”: “1”,                 “GlassStyle”: “1”,                 “GlassColor”: “1”,                 “IsDriver”: 1,                 “IsForeigner”: 1,                 “PassportType”: “1”,                 “ImmigrantTypeCode”: “1”,                 “IsSuspectedTerrorist”: 1,                 “SuspectedTerroristNumber”: “1”,                 “IsCriminalInvolved”: 1,                 “CriminalInvolvedSpecilisationCode”: “1”,                 “BodySpeciallMark”: “1”,                 “CrimeMethod”: “1”,                 “CrimeCharacterCode”: “111”,                 “EscapedCriminalNumber”: “11111111111111111111111”,                 “IsDetainees”: 1,                 “DetentionHouseCode”: “111111111”,                 “DetaineesIdentity”: “1”,                 “DetaineesSpecialIdentity”: “1”,                 “MemberTypeCode”: “1”,                 “IsVictim”: 1,                 “VictimType”: “1”,                 “InjuredDegree”: “1”,                 “CorpseConditionCode”: “1”,                 “IsSuspiciousPerson”: 1,                 “Attitude”: 1,                 “Similaritydegree”: 1,                 “EyebrowStyle”: “1”,                 “NoseStyle”: “1”,                 “MustacheStyle”: “1”,                 “LipStyle”: “1”,                 “WrinklePouch”: “1”,                 “AcneStain”: “1”,                 “FreckleBirthmark”: “1”,                 “ScarDimple”: “1”,                 “OtherFeature”: “1”,                 “SubImageList”: {                     “SubImageInfoObject”: [                         {                             “ImageID”: “33020300001190000001022017122111111100001”,                             “EventSort”: 11,                             “DeviceID”: “33070299011190000253”,                             “StoragePath”: “http://10.33.6.108:9080/testx_108_20170908/a2421c4fde6d4a74ac923e8470d6e7fa.jpg”,                             “Type”: “01”,                             “FileFormat”: “Jpeg”,                             “ShotTime”: “20170825032455”,                             “Width”: 437,                             “Height”: 350                         }                     ]                 }             }         ]     } }
响应体 {     “ResponseStatusListObject”: {         “ResponseStatusObject”: [             {                 “RequestURL”: “http://localhost:8080/VIID/Faces”,                 “StatusCode”: 0,                 “StatusString”: “正常”,                 “Id”: “650100000011900000010220171219100515999830656599”,                 “LocalTime”: “20171222162927”             }         ]     } }

批量人脸查询

1.接口概览

URI /VIID/Faces
方法 查询字符串 消息体 返回结果
GET Face属性键-值对 无 < FaceList>
备注  

2.查询字符串

查询指令为Face属性键-值对,特征属性定义参考A.9 。

3.返回结果

结构参考C.9,字段定义参考A.9。

4.示例

URI /VIID/ Faces
请求方法 GET
请求头 参见请求参数
查询参数 ?FaceID =650100000011900000010220171219100515999830656599 &InfoKind=1 &IDType=111 &LocationMarkTime=19981230010000…
响应体 {     “FaceListObject”: {         “FaceObject”: [             {                 “FaceID”: “650100000011900000010220171219100515999830656489”,                 “InfoKind”: 1,                 “SourceID”: “66000000001190123456022017120110101000007”,                 “DeviceID”: “55000111221190000007”,                 “LeftTopX”: 1,                 “LeftTopY”: 1,                 “RightBtmX”: 1,                 “RightBtmY”: 1,                 “LocationMarkTime”: “19981230010000”,                 “FaceAppearTime”: “19981230010000”,                 “FaceDisAppearTime”: “19981230010000”,                 “IDType”: “111”,                 “IDNumber”: “1”,                 “Name”: “大华”,                 “UsedName”: “dahua”,                 “Alias”: “dahua”,                 “GenderCode”: “1”,                 “AgeUpLimit”: 10,                 “AgeLowerLimit”: 20,                 “EthicCode”: “1”,                 “NationalityCode”: “CHN”,                 “NativeCityCode”: “330108”,                 “ResidenceAdminDivision”: “330100”,                 “ChineseAccentCode”: “1”,                 “JobCategory”: “1”,                 “AccompanyNumber”: 1,                 “SkinColor”: “1”,                 “HairStyle”: “1”,                 “HairColor”: “1”,                 “FaceStyle”: “1”,                 “FacialFeature”: “1”,                 “PhysicalFeature”: “1”,                 “RespiratorColor”: “1”,                 “CapStyle”: “1”,                 “CapColor”: “1”,                 “GlassStyle”: “1”,                 “GlassColor”: “1”,                 “IsDriver”: 1,                 “IsForeigner”: 1,                 “PassportType”: “1”,                 “ImmigrantTypeCode”: “1”,                 “IsSuspectedTerrorist”: 1,                 “SuspectedTerroristNumber”: “1”,                 “IsCriminalInvolved”: 1,                 “CriminalInvolvedSpecilisationCode”: “1”,                 “BodySpeciallMark”: “1”,                 “CrimeMethod”: “1”,                 “CrimeCharacterCode”: “111”,                 “EscapedCriminalNumber”: “11111111111111111111111”,                 “IsDetainees”: 1,                 “DetentionHouseCode”: “111111111”,                 “DetaineesIdentity”: “1”,                 “DetaineesSpecialIdentity”: “1”,                 “MemberTypeCode”: “1”,                 “IsVictim”: 1,                 “VictimType”: “1”,                 “InjuredDegree”: “1”,                 “CorpseConditionCode”: “1”,                 “IsSuspiciousPerson”: 1,                 “Attitude”: 1,                 “Similaritydegree”: 1,                 “EyebrowStyle”: “1”,                 “NoseStyle”: “1”,                 “MustacheStyle”: “1”,                 “LipStyle”: “1”,                 “WrinklePouch”: “1”,                 “AcneStain”: “1”,                 “FreckleBirthmark”: “1”,                 “ScarDimple”: “1”,                 “OtherFeature”: “1”,                 “SubImageList”: {                     “SubImageInfoObject”: [                         {                             “ImageID”: “33020300001190000001022017122111111100001”,                             “EventSort”: 1,                             “DeviceID”: “33070299011190000253”,                             “StoragePath”: “http://172.26.8.236:11180/pictures//07314a17009347ab86d1d4a9b52abd1d.jpg”,                             “Type”: “11”,                             “FileFormat”: “Jpeg”,                             “ShotTime”: “20171221104550”,                             “Width”: 358,                             “Height”: 441                         }                     ]                 }             }         ]     } }

批量人脸修改

1.   接口概览

URI /VIID/Faces
方法 查询字符串 消息体 返回结果
PUT 无 <FaceList> <ResponseStatusList>
备注 消息体中FaceID必填,否则操作无效

2.消息体特征参数

消息体结构参考C.9,字段定义参考A.9 。

3.返回结果

         结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/Faces
请求方法 PUT
请求头 参见请求参数
请求体 {     “FaceListObject”: {         “FaceObject”: [             {                 “FaceID”: “650100000011900000010220171219100515999830656489”,                 “InfoKind”: 2,                 “LeftTopX”: 10,                 “LeftTopY”: 10,                 “RightBtmX”: 10,                 “RightBtmY”: 10,                 “NativeCityCode”: “330109”,                 “ResidenceAdminDivision”: “330101”,                 “ChineseAccentCode”: “2”,                 “JobCategory”: “2”,                 “AccompanyNumber”: 2,                 “SkinColor”: “2”,                 “HairStyle”: “2”,                 “HairColor”: “2”,                 “FaceStyle”: “2”,                 “FacialFeature”: “2”,                 “PhysicalFeature”: “2” …             }         ]     } }            
响应体 {     “ResponseStatusListObject”: {         “ResponseStatusObject”: [             {                 “RequestURL”: “http://localhost:8080/VIID/Faces”,                 “StatusCode”: 0,                 “StatusString”: “正常”,                 “Id”: “650100000011900000010220171219100515999830656489”,                 “LocalTime”: “20171223094319”             }         ]     } }

批量人脸删除

1.接口概览

URI /VIID/Faces
方法 请求参数 消息体 返回结果
DELETE 键为IDList,值为用英文半角分号”,”分隔的字符串 无 <ResponseStatusList>
备注  

2.请求参数

IDList=<FaceID >,< FaceID >。

3.返回结果

         结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/ Faces
请求方法 DELETE
请求头 参见请求参数
请求参数 ?IDList=650100000011900000010220171219100515999830656489,650100000011900000010220171219100515999830656490  
响应体 {     “ResponseStatusListObject”: {         “ResponseStatusObject”: [             {                 “RequestURL”: “http://localhost:8080/VIID/Faces”,                 “StatusCode”: 0,                 “StatusString”: “正常”,                 “Id”: “650100000011900000010220171219100515999830656489”,                 “LocalTime”: “20171223094319”             },             {                 “RequestURL”: “http://localhost:8080/VIID/Faces”,                 “StatusCode”: 0,                 “StatusString”: “正常”,                 “Id”: “650100000011900000010220171219100515999830656490”,                 “LocalTime”: “20171223094319”             }         ]     } }

单个人脸查询

1.接口概览

URI /VIID/Faces/<FaceID>
方法 请求参数 消息体 返回结果
GET 无 无 <Face>
备注  

2.   请求参数

无

3.返回结果

         结构参考C.9,字段定义参考A.9。

4.示例

URI /VIID/Faces/650100000011900000010220171219100515999830656489
请求方法 GET
请求头 参见请求参数
请求体 无
响应体 {     “FaceObject”: {         “FaceID”: “650100000011900000010220171219100515999830656489”,         “InfoKind”: 2,         “SourceID”: “66000000001190123456022017120110101000007”,         “DeviceID”: “55000111221190000007”,         “LeftTopX”: 10,         “LeftTopY”: 10,         “RightBtmX”: 10,         “RightBtmY”: 10,         “LocationMarkTime”: “19981230010000”,         “FaceAppearTime”: “19981230010000”,         “FaceDisAppearTime”: “19981230010000”,         “IDType”: “111”,         “IDNumber”: “1”,         “Name”: “大华”,         “UsedName”: “dahua”,         “Alias”: “dahua”,         “GenderCode”: “1”,         “AgeUpLimit”: 10,         “AgeLowerLimit”: 20,         “EthicCode”: “1”,         “NationalityCode”: “CHN”,         “NativeCityCode”: “330109”,         “ResidenceAdminDivision”: “330101”,         “ChineseAccentCode”: “2”,         “JobCategory”: “2”,         “AccompanyNumber”: 2,         “SkinColor”: “2”,         “HairStyle”: “2”,         “HairColor”: “2”,         “FaceStyle”: “2”,         “FacialFeature”: “2”,         “PhysicalFeature”: “2”,         “RespiratorColor”: “1”,         “CapStyle”: “1”,         “CapColor”: “1”,         “GlassStyle”: “1”,         “GlassColor”: “1”,         “IsDriver”: 1,         “IsForeigner”: 1,         “PassportType”: “1”,         “ImmigrantTypeCode”: “1”,         “IsSuspectedTerrorist”: 1,         “SuspectedTerroristNumber”: “1”,         “IsCriminalInvolved”: 1,         “CriminalInvolvedSpecilisationCode”: “1”,         “BodySpeciallMark”: “1”,         “CrimeMethod”: “1”,         “CrimeCharacterCode”: “111”,         “EscapedCriminalNumber”: “11111111111111111111111”,         “IsDetainees”: 1,         “DetentionHouseCode”: “111111111”,         “DetaineesIdentity”: “1”,         “DetaineesSpecialIdentity”: “1”,         “MemberTypeCode”: “1”,         “IsVictim”: 1,         “VictimType”: “1”,         “InjuredDegree”: “1”,         “CorpseConditionCode”: “1”,         “IsSuspiciousPerson”: 1,         “Attitude”: 1,         “Similaritydegree”: 1,         “EyebrowStyle”: “1”,         “NoseStyle”: “1”,         “MustacheStyle”: “1”,         “LipStyle”: “1”,         “WrinklePouch”: “1”,         “AcneStain”: “1”,         “FreckleBirthmark”: “1”,         “ScarDimple”: “1”,         “OtherFeature”: “1”,         “SubImageList”: {             “SubImageInfoObject”: [                 {                     “ImageID”: “33020300001190000001022017122111111100001”,                     “EventSort”: 4,                     “DeviceID”: “55220299011190000253”,                     “StoragePath”: “http://localhost:9080/testx_108_20170908/a2421c4fde6d4a74ac923e8470d6e7fa.jpg”,                     “Type”: “01”,                     “FileFormat”: “Jpeg”,                     “ShotTime”: “20170925032455”,                     “Width”: 437,                     “Height”: 350                 }             ]         }     } }

单个人脸修改

1.接口概览

URI /VIID/Faces/<FaceID>
方法 请求参数 消息体 返回结果
PUT  无 <Face> <ResponseStatus>
备注  

2.消息体特征参数

         结构参考C.9,字段定义参考A.9。

3.返回结果

         结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/Faces/650100000011900000010220171219100515999830656489
请求方法 PUT
请求头 参见请求参数
请求体 {     “FaceObject”: {         “FaceID”: “650100000011900000010220171219100515999830656489”,         “LeftTopX”: 10,         “LeftTopY”: 10,         “RightBtmX”: 10,         “RightBtmY”: 10 …     } }
响应体 {     “ResponseStatusObject”: {         “RequestURL”: “http://localhost:8080 /VIID/Faces/650100000011900000010220171219100515999830656589”,         “StatusCode”: 0,         “StatusString”: “正常”,         “Id”: “650100000011900000010220171219100515999830656589”,         “LocalTime”: “20171223135905”     } }

单个人脸删除

1.接口概览

URI /VIID/Faces/<FaceID>
方法 请求参数 消息体 返回结果
DELETE  无 无 <ResponseStatus>
备注  

2.请求参数

无

3.返回结果

         结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/Faces/650100000011900000010220171219100515999830656489
请求方法 DELETE
请求头 参见请求参数
请求体  
响应体 {     “ResponseStatusObject”: {         “RequestURL”: “http://localhost:8080 /VIID/Faces/650100000011900000010220171219100515999830656489”,         “StatusCode”: 0,         “StatusString”: “正常”,         “Id”: “650100000011900000010220171219100515999830656489”,         “LocalTime”: “20171223135905”     } }
作者 east

上一 1 … 70 71 72 … 93 下一个

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。回复”chatgpt”获取免注册可用chatgpt。回复“大数据”获取多本大数据电子书

标签

AIGC AI创作 bert chatgpt github GPT-3 gpt3 GTP-3 hive mysql O2O tensorflow UI控件 不含后台 交流 共享经济 出行 图像 地图定位 外卖 多媒体 娱乐 小程序 布局 带后台完整项目 开源项目 搜索 支付 效率 教育 日历 机器学习 深度学习 物流 用户系统 电商 画图 画布(canvas) 社交 签到 联网 读书 资讯 阅读 预订

官方QQ群

小程序开发群:74052405

大数据开发群: 952493060

近期文章

  • spark内存溢出怎样区分是软件还是代码原因
  • MQTT完全解析和实践
  • 解决运行Selenium报错:self.driver = webdriver.Chrome(service=service) TypeError: __init__() got an unexpected keyword argument ‘service’
  • python 3.6使用mysql-connector-python报错:SyntaxError: future feature annotations is not defined
  • 详解Python当中的pip常用命令
  • AUTOSAR如何在多个供应商交付的配置中避免ARXML不兼容?
  • C++thread pool(线程池)设计应关注哪些扩展性问题?
  • 各类MCAL(Microcontroller Abstraction Layer)如何与AUTOSAR工具链解耦?
  • 如何设计AUTOSAR中的“域控制器”以支持未来扩展?
  • C++ 中避免悬挂引用的企业策略有哪些?

文章归档

  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年1月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年7月
  • 2018年6月

分类目录

  • Android (73)
  • bug清单 (79)
  • C++ (34)
  • Fuchsia (15)
  • php (4)
  • python (45)
  • sklearn (1)
  • 云计算 (20)
  • 人工智能 (61)
    • chatgpt (21)
      • 提示词 (6)
    • Keras (1)
    • Tensorflow (3)
    • 大模型 (1)
    • 智能体 (4)
    • 深度学习 (14)
  • 储能 (44)
  • 前端 (4)
  • 大数据开发 (491)
    • CDH (6)
    • datax (4)
    • doris (31)
    • Elasticsearch (15)
    • Flink (78)
    • flume (7)
    • Hadoop (19)
    • Hbase (23)
    • Hive (41)
    • Impala (2)
    • Java (71)
    • Kafka (10)
    • neo4j (5)
    • shardingsphere (6)
    • solr (5)
    • Spark (100)
    • spring (11)
    • 数据仓库 (9)
    • 数据挖掘 (7)
    • 海豚调度器 (10)
    • 运维 (34)
      • Docker (3)
  • 小游戏代码 (1)
  • 小程序代码 (139)
    • O2O (16)
    • UI控件 (5)
    • 互联网类 (23)
    • 企业类 (6)
    • 地图定位 (9)
    • 多媒体 (6)
    • 工具类 (25)
    • 电商类 (22)
    • 社交 (7)
    • 行业软件 (7)
    • 资讯读书 (11)
  • 嵌入式 (71)
    • autosar (63)
    • RTOS (1)
    • 总线 (1)
  • 开发博客 (16)
    • Harmony (9)
  • 技术架构 (6)
  • 数据库 (32)
    • mongodb (1)
    • mysql (13)
    • pgsql (2)
    • redis (1)
    • tdengine (4)
  • 未分类 (7)
  • 程序员网赚 (20)
    • 广告联盟 (3)
    • 私域流量 (5)
    • 自媒体 (5)
  • 量化投资 (4)
  • 面试 (14)

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

All Rights Reserved by Gitweixin.本站收集网友上传代码, 如有侵犯版权,请发邮件联系yiyuyos@gmail.com删除.