mirror of
https://gitee.com/freshday/radar.git
synced 2026-03-22 12:47:16 +08:00
20
README.md
20
README.md
@@ -5,6 +5,7 @@
|
||||
A real-time risk analysis engine,which can update risk rule in real-time and make it effective immediately.
|
||||
It applies to the anti-fraud application perfectly.
|
||||
The project code called Radar, like the code, monitor the transaction at the back.
|
||||
|
||||
## 项目特点
|
||||
|
||||
* 实时风控,特殊场景可以做到100ms内响应
|
||||
@@ -15,6 +16,13 @@ The project code called Radar, like the code, monitor the transaction at the bac
|
||||
* NoSQL,易扩展,高性能
|
||||
* 配置简单,开箱即用!
|
||||
|
||||
## 相关站点
|
||||
Github: https://github.com/wfh45678/radar
|
||||
Gitee: https://gitee.com/freshday/radar // 码云为镜像网站,贡献代码请提交到 github
|
||||
官网: http://radar.pgmmer.top
|
||||
Wiki: https://gitee.com/freshday/radar/wikis/home
|
||||
|
||||
|
||||
## 背景
|
||||
伴随着移动互联网的高速发展,羊毛党快速崛起,从一平台到另一个平台,所过之处一地鸡毛,这还不是最可怕的,
|
||||
随之而来的黑产令大部分互联网应用为之胆寒,通常新上线的APP的福利比较大,风控系统不完善,BUG 被发现的频率也比较高,
|
||||
@@ -96,19 +104,15 @@ https://gitee.com/freshday/radar/wikis/manual?sort_id=1637446
|
||||
建议大家自行注册用户,避免使用同样的测试账号受干扰.
|
||||
|
||||
## 未完待续
|
||||
### 小迭代
|
||||
* React 版本升级(v15.0.0)
|
||||
* 集成嵌入式redis版本,本地调试的时候就不用再单独部署redis
|
||||
* 集成 JWT(JSON WEB TOKEN),前后端分离标准化
|
||||
* 插件配置管理,可以集成其他中间件的数据能力
|
||||
* 支持Flink,增加特征(abstraction)的提取基于Flink 的实现,以应对时间窗口相对较短,实时性要求更高的情况。
|
||||
|
||||
### 重大特性
|
||||
* 支持机器学习
|
||||
* 数据分析平台
|
||||
|
||||
## 致谢
|
||||
感恩 XWF 团队,感谢参入的每一位小伙伴,后续征得同意后会一一列出名字。
|
||||
|
||||
感恩 XWF 团队,感谢参入的每一位小伙伴,后续征得同意后会一一列出名字。
|
||||
千面怪, 烈日下的从容, DerekDingLu, king, sanying2012, 紫泉夜, 玄梦
|
||||
成书平, 徐帅...
|
||||
## Contact to
|
||||
|
||||
如果喜欢本项目,Star支持一下, 让更多人了解本项目,谢谢!
|
||||
|
||||
3
pom.xml
3
pom.xml
@@ -19,13 +19,14 @@
|
||||
</parent>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<artifactId>radar</artifactId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
<name>radar</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<tomcat.version>8.5.37</tomcat.version>
|
||||
</properties>
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>radar-admin</artifactId>
|
||||
@@ -13,7 +13,6 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -44,6 +43,11 @@
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
|
||||
<dependency>
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.pgmmers.radar.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.pgmmers.radar.dal.bean.AbstractionQuery;
|
||||
import com.pgmmers.radar.enums.PluginType;
|
||||
import com.pgmmers.radar.service.common.CommonResult;
|
||||
@@ -19,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@RestController
|
||||
@RequestMapping("/services/v1/abstraction")
|
||||
@@ -70,21 +72,20 @@ public class AbstractionApiController {
|
||||
// 2、PREPARE
|
||||
ds = new DataColumnInfo(DataType.PREITEMS.getDesc(), DataType.PREITEMS.getName());
|
||||
List<PreItemVO> listPreItem = preItemService.listPreItem(modelId);
|
||||
if(listPreItem!=null&&listPreItem.size()!=0){
|
||||
if(listPreItem != null && listPreItem.size()!= 0){
|
||||
for (PreItemVO preItem : listPreItem) {
|
||||
PluginType pt = PluginType.get(preItem.getPlugin());
|
||||
if (StringUtils.isNoneBlank(pt.getType())) {
|
||||
if (StringUtils.isNotEmpty(pt.getType()) && pt.getType().equals("JSON")) {
|
||||
//load http request data
|
||||
JsonNode json = preItem.getConfigJson();
|
||||
List<DataColumnInfo> children = new ArrayList<>();
|
||||
extractMetaColumn(ds, preItem, json.toString(), children);
|
||||
} else if (StringUtils.isNotEmpty(pt.getType())) {
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), pt.getType());
|
||||
} else {
|
||||
List<DataColumnInfo> children = new ArrayList<>();
|
||||
JSONArray array = JSONArray.parseArray(pt.getMeta());
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject obj = array.getJSONObject(i);
|
||||
children.add(new DataColumnInfo(obj.getString("title"), obj.getString("column"), obj
|
||||
.getString("type")));
|
||||
}
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), children);
|
||||
}
|
||||
extractMetaColumn(ds, preItem, pt.getMeta(), children);
|
||||
}
|
||||
}
|
||||
list.add(ds);
|
||||
}
|
||||
@@ -95,7 +96,17 @@ public class AbstractionApiController {
|
||||
return result;
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
private void extractMetaColumn(DataColumnInfo ds, PreItemVO preItem, String jsonStr, List<DataColumnInfo> children) {
|
||||
JSONArray array = JSONArray.parseArray(jsonStr);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject obj = array.getJSONObject(i);
|
||||
children.add(new DataColumnInfo(obj.getString("title"), obj.getString("column"), obj
|
||||
.getString("type")));
|
||||
}
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), children);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public CommonResult save(@RequestBody AbstractionVO abstraction) {
|
||||
return abstractionService.save(abstraction);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.pgmmers.radar.controller;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.pgmmers.radar.dal.bean.ActivationQuery;
|
||||
import com.pgmmers.radar.enums.FieldType;
|
||||
import com.pgmmers.radar.enums.PluginType;
|
||||
@@ -67,17 +68,16 @@ public class ActivationApiController {
|
||||
List<PreItemVO> listPreItem = preItemService.listPreItem(modelId);
|
||||
for (PreItemVO preItem : listPreItem) {
|
||||
PluginType pt = PluginType.get(preItem.getPlugin());
|
||||
if (StringUtils.isNoneBlank(pt.getType())) {
|
||||
if (StringUtils.isNotEmpty(pt.getType()) && pt.getType().equals("JSON")) {
|
||||
//load http request data
|
||||
JsonNode json = preItem.getConfigJson();
|
||||
List<DataColumnInfo> children = new ArrayList<>();
|
||||
extractMetaColumn(ds, preItem, json.toString(), children);
|
||||
} else if (StringUtils.isNotEmpty(pt.getType())) {
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), pt.getType());
|
||||
} else {
|
||||
List<DataColumnInfo> children = new ArrayList<>();
|
||||
JSONArray array = JSONArray.parseArray(pt.getMeta());
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject obj = array.getJSONObject(i);
|
||||
children.add(new DataColumnInfo(obj.getString("title"), obj.getString("column"), obj
|
||||
.getString("type")));
|
||||
}
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), children);
|
||||
extractMetaColumn(ds, preItem, pt.getMeta(), children);
|
||||
}
|
||||
}
|
||||
list.add(ds);
|
||||
@@ -133,5 +133,15 @@ public class ActivationApiController {
|
||||
@PostMapping("/updateOrder")
|
||||
public CommonResult updateOrder(@RequestParam Long activationId, @RequestParam String ruleOrder) {
|
||||
return activationService.updateOrder(activationId,ruleOrder);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractMetaColumn(DataColumnInfo ds, PreItemVO preItem, String jsonStr, List<DataColumnInfo> children) {
|
||||
JSONArray array = JSONArray.parseArray(jsonStr);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject obj = array.getJSONObject(i);
|
||||
children.add(new DataColumnInfo(obj.getString("title"), obj.getString("column"), obj
|
||||
.getString("type")));
|
||||
}
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), children);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
package com.pgmmers.radar.controller;
|
||||
|
||||
|
||||
import com.pgmmers.radar.dal.bean.DataListQuery;
|
||||
import com.pgmmers.radar.service.common.CommonResult;
|
||||
import com.pgmmers.radar.service.model.DataListsService;
|
||||
import com.pgmmers.radar.util.ExcelImportUtil;
|
||||
import com.pgmmers.radar.util.ExportExcelInfo;
|
||||
import com.pgmmers.radar.vo.model.DataListsVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/services/v1/datalist")
|
||||
@Api(value = "DataListsApi", description = "黑白名单列表接口相关操作", tags = {"数据列表API"})
|
||||
public class DataListApiController {
|
||||
|
||||
public static Logger logger = LoggerFactory.getLogger(DataListApiController.class);
|
||||
|
||||
@Autowired
|
||||
private DataListsService dataListsService;
|
||||
|
||||
@@ -49,4 +60,47 @@ public class DataListApiController {
|
||||
return dataListsService.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 批量导入黑/白名单管理
|
||||
* @param file 文件
|
||||
* @param modelId 模型ID
|
||||
* @return
|
||||
* @author xushuai
|
||||
*/
|
||||
@PostMapping(value = "/batchImportData")
|
||||
public CommonResult batchImportData(@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, @RequestParam(value = "modelId", required = true)Long modelId) {
|
||||
CommonResult result = new CommonResult();
|
||||
result.setSuccess(false);
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (fileName != null && !(fileName.contains(".xls") || fileName.contains(".xlsx"))) {
|
||||
result.setMsg("传入的件格式有误!");
|
||||
return result;
|
||||
}
|
||||
ExportExcelInfo<DataListsVO> info = getImportMeta();
|
||||
List<Map<String, Object>> listError = new ArrayList<>();
|
||||
List<DataListsVO> list = null;
|
||||
try {
|
||||
list = ExcelImportUtil.excelToList(file.getInputStream(), info, listError, DataListsVO.class);
|
||||
} catch (Exception e) {
|
||||
logger.error("导入Excel失败:" + e.getMessage());
|
||||
}
|
||||
if (list == null || list.size() == 0) {
|
||||
result.setMsg("无导入数据!");
|
||||
return result;
|
||||
}
|
||||
if (list.size() > 1000) {
|
||||
result.setMsg("最大导入不能超过" + 1000 + "条");
|
||||
return result;
|
||||
}
|
||||
return dataListsService.batchImportData(list, modelId);
|
||||
}
|
||||
|
||||
private ExportExcelInfo<DataListsVO> getImportMeta() {
|
||||
ExportExcelInfo<DataListsVO> info = new ExportExcelInfo<DataListsVO>(null);
|
||||
info.addExcelColumn("备注", "comment");
|
||||
info.addExcelColumn("列表名", "label");
|
||||
info.addExcelColumn("名单类型", "listType");
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,28 @@ package com.pgmmers.radar.controller;
|
||||
import com.pgmmers.radar.dal.bean.DataListRecordQuery;
|
||||
import com.pgmmers.radar.service.common.CommonResult;
|
||||
import com.pgmmers.radar.service.model.DataListsService;
|
||||
import com.pgmmers.radar.util.ExcelImportUtil;
|
||||
import com.pgmmers.radar.util.ExportExcelInfo;
|
||||
import com.pgmmers.radar.vo.model.DataListRecordVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/services/v1/datalistrecord")
|
||||
@Api(value = "DataListRecordApi", description = "列表内容维护接口相关操作", tags = {"列表内容API"})
|
||||
public class DataListRecordApiController {
|
||||
|
||||
public static Logger logger = LoggerFactory.getLogger(DataListRecordApiController.class);
|
||||
|
||||
@Autowired
|
||||
private DataListsService dataListsService;
|
||||
|
||||
@@ -45,4 +57,46 @@ public class DataListRecordApiController {
|
||||
return dataListsService.deleteRecord(id);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 批量导入黑/白名单管理
|
||||
* @param file 文件
|
||||
* @param dataListId 数据列表ID
|
||||
* @return
|
||||
* @author xushuai
|
||||
*/
|
||||
@PostMapping(value = "/batchImportDataRecord")
|
||||
public CommonResult batchImportDataRecord(@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, @RequestParam(value = "dataListId", required = true)Long dataListId) {
|
||||
CommonResult result = new CommonResult();
|
||||
result.setSuccess(false);
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (fileName != null && !(fileName.contains(".xls") || fileName.contains(".xlsx"))) {
|
||||
result.setMsg("传入的件格式有误!");
|
||||
return result;
|
||||
}
|
||||
ExportExcelInfo<DataListRecordVO> info = getImportMeta();
|
||||
List<Map<String, Object>> listError = new ArrayList<>();
|
||||
List<DataListRecordVO> list = null;
|
||||
try {
|
||||
list = ExcelImportUtil.excelToList(file.getInputStream(), info, listError, DataListRecordVO.class);
|
||||
} catch (Exception e) {
|
||||
logger.error("导入Excel失败:" + e.getMessage());
|
||||
}
|
||||
if (list == null || list.size() == 0) {
|
||||
result.setMsg("无导入数据!");
|
||||
return result;
|
||||
}
|
||||
if (list.size() > 1000) {
|
||||
result.setMsg("最大导入不能超过" + 1000 + "条");
|
||||
return result;
|
||||
}
|
||||
return dataListsService.batchImportDataRecord(list, dataListId);
|
||||
}
|
||||
|
||||
private ExportExcelInfo<DataListRecordVO> getImportMeta() {
|
||||
ExportExcelInfo<DataListRecordVO> info = new ExportExcelInfo<DataListRecordVO>(null);
|
||||
info.addExcelColumn("dataRecord", "dataRecord");
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -260,7 +260,6 @@ public class EventApiController {
|
||||
os.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 优化参数名称
|
||||
* @author xushuai
|
||||
*/
|
||||
public class CamelUtil {
|
||||
public static final char UNDERLINE = '_';
|
||||
|
||||
public static String camelToUnderline(String param) {
|
||||
if (param == null || "".equals(param.trim())) {
|
||||
return "";
|
||||
}
|
||||
int len = param.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = param.charAt(i);
|
||||
if (Character.isUpperCase(c)) {
|
||||
sb.append(UNDERLINE);
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String underlineToCamel(String param) {
|
||||
if (param == null || "".equals(param.trim())) {
|
||||
return "";
|
||||
}
|
||||
int len = param.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = param.charAt(i);
|
||||
if (c == UNDERLINE) {
|
||||
if (++i < len) {
|
||||
sb.append(Character.toUpperCase(param.charAt(i)));
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String underlineToCamel2(String param) {
|
||||
if (param == null || "".equals(param.trim())) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(param);
|
||||
Matcher mc = Pattern.compile("_").matcher(param);
|
||||
int i = 0;
|
||||
while (mc.find()) {
|
||||
int position = mc.end() - (i++);
|
||||
//String.valueOf(Character.toUpperCase(sb.charAt(position)));
|
||||
sb.replace(position - 1, position + 1, sb.substring(position, position + 1).toUpperCase());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
/**
|
||||
* Excel字段类型
|
||||
* @author xushuai
|
||||
*/
|
||||
public enum EnumExcelColumnType {
|
||||
ColumnType_Double(0),
|
||||
ColumnType_Date(1),
|
||||
ColumnType_Calendar(2),
|
||||
ColumnType_String(3),
|
||||
ColumnType__BOOLEAN(4),
|
||||
ColumnType_ERROR(5);
|
||||
private int RowId;
|
||||
private EnumExcelColumnType(int id) {
|
||||
RowId = id;
|
||||
}
|
||||
public int GetValue() {
|
||||
return RowId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 列信息整理
|
||||
* @author xushuai
|
||||
*/
|
||||
public class ExcelColumn<T> {
|
||||
String text;
|
||||
String tableName;
|
||||
String columnName;
|
||||
String camelColumnName;
|
||||
EnumExcelColumnType columnType;
|
||||
boolean isNull=true;
|
||||
int orderIndex;
|
||||
FunctionFormatter<Object, T, Integer, Object> formatter;
|
||||
double columnWidth;
|
||||
public ExcelColumn()
|
||||
{
|
||||
|
||||
}
|
||||
public ExcelColumn(String columnName, String tableName, String text)
|
||||
{
|
||||
this.columnName=columnName;
|
||||
this.camelColumnName= CamelUtil.underlineToCamel(this.columnName);
|
||||
this.tableName=tableName;
|
||||
this.text=text;
|
||||
}
|
||||
public ExcelColumn(String columnName, String tableName, String text, boolean isNull) {
|
||||
this(columnName, tableName, text);
|
||||
this.isNull = isNull;
|
||||
}
|
||||
public ExcelColumn(String columnName, int orderIndex, String tableName, String text)
|
||||
{
|
||||
this.columnName=columnName;
|
||||
this.camelColumnName= CamelUtil.underlineToCamel(this.columnName);
|
||||
this.orderIndex=orderIndex;
|
||||
this.tableName=tableName;
|
||||
this.text=text;
|
||||
}
|
||||
public ExcelColumn(String columnName, int orderIndex, String tableName, String text, boolean isNull)
|
||||
{
|
||||
this(columnName,orderIndex,tableName,text);
|
||||
this.isNull=isNull;
|
||||
}
|
||||
public ExcelColumn(String columnName, int orderIndex, String tableName, String text, EnumExcelColumnType columnType, boolean isNull)
|
||||
{
|
||||
this(columnName,orderIndex,tableName,text);
|
||||
this.columnType=columnType;
|
||||
this.isNull=isNull;
|
||||
}
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
private String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
public void setColumnName(String columnName) {
|
||||
this.columnName = columnName;
|
||||
}
|
||||
|
||||
public String getCamelColumnName() {
|
||||
if(StringUtils.isEmpty(camelColumnName))
|
||||
{
|
||||
return this.getColumnName();
|
||||
}
|
||||
return camelColumnName;
|
||||
}
|
||||
|
||||
public void setCamelColumnName(String camelColumnName) {
|
||||
this.camelColumnName = camelColumnName;
|
||||
}
|
||||
|
||||
public EnumExcelColumnType getColumnType() {
|
||||
return columnType;
|
||||
}
|
||||
|
||||
public void setColumnType(EnumExcelColumnType columnType) {
|
||||
this.columnType = columnType;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return isNull;
|
||||
}
|
||||
|
||||
public void setNull(boolean aNull) {
|
||||
isNull = aNull;
|
||||
}
|
||||
|
||||
public int getOrderIndex() {
|
||||
return orderIndex;
|
||||
}
|
||||
|
||||
public void setOrderIndex(int orderIndex) {
|
||||
this.orderIndex = orderIndex;
|
||||
}
|
||||
|
||||
public FunctionFormatter<Object, T, Integer, Object> getFormatter() {
|
||||
return formatter;
|
||||
}
|
||||
|
||||
public void setFormatter(FunctionFormatter<Object, T, Integer, Object> formatter) {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
public double getColumnWidth() {
|
||||
return columnWidth;
|
||||
}
|
||||
|
||||
public void setColumnWidth(double columnWidth) {
|
||||
this.columnWidth = columnWidth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 将导入的文件列信息转换为model
|
||||
* @author xushuai
|
||||
*/
|
||||
public class ExcelImportUtil {
|
||||
|
||||
public static <TModel> List<TModel> excelToList(
|
||||
HttpServletRequest request,
|
||||
ExportExcelInfo<TModel> info,List<Map<String, Object>> listErrorMap,Class<TModel> entityClass
|
||||
) throws Exception {
|
||||
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
|
||||
String fileName= multiRequest.getFileNames().next();
|
||||
|
||||
MultipartFile multipartFile=multiRequest.getFile(fileName);
|
||||
// MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
|
||||
// MultipartFile File= multiRequest.getMultiFileMap().;
|
||||
// request.get
|
||||
//
|
||||
// multiRequest.getMultiFileMap().f
|
||||
//取得上传文件流
|
||||
InputStream in =multipartFile.getInputStream() ;
|
||||
return excelToList(in, info, listErrorMap, entityClass);
|
||||
}
|
||||
|
||||
public static <TModel> List<TModel> excelToList(
|
||||
InputStream in,
|
||||
ExportExcelInfo<TModel> info,List<Map<String, Object>> listErrorMap,Class<TModel> entityClass
|
||||
) throws Exception {
|
||||
//定义要返回的list
|
||||
List<TModel> resultList = new ArrayList<TModel>();
|
||||
String sheetName = info.getSheet();
|
||||
//根据Excel数据源创建WorkBook
|
||||
Workbook wb = WorkbookFactory.create(in);
|
||||
// HSSFWorkbook wb = new HSSFWorkbook(in);
|
||||
//获取工作表
|
||||
Sheet sheet;
|
||||
if (wb.getNumberOfSheets() > 1 && !sheetName.equals("")) {
|
||||
sheet = wb.getSheet(sheetName);
|
||||
} else {
|
||||
sheet = wb.getSheetAt(0);
|
||||
}
|
||||
importSheet(sheet, info, resultList, listErrorMap, entityClass);
|
||||
return resultList;
|
||||
}
|
||||
public static <TModel> void importSheet(Sheet productSheet, ExportExcelInfo<TModel> info, List<TModel> listTModel, List<Map<String, Object>> listErrorMap, Class<TModel> entityClass) throws Exception {
|
||||
importSheet(productSheet, info, listTModel, listErrorMap, entityClass,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param productSheet listTModel
|
||||
* @param listTModel 导入集合
|
||||
* @param listErrorMap 导入错误集合
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <TModel> void importSheet(Sheet productSheet, ExportExcelInfo<TModel> info, List<TModel> listTModel, List<Map<String, Object>> listErrorMap, Class<TModel> entityClass, int columnRowIndex) throws Exception {
|
||||
int LastCellNum = productSheet.getRow(0).getLastCellNum();//列数量
|
||||
Row rowColumn = productSheet.getRow(columnRowIndex);//excel列所在行
|
||||
Map<String, Integer> mapExcelColumn = new HashMap<>();//excel 列名字和列索引对应 key:excel列名字 value:excel列索引
|
||||
for (int i = 0; i < LastCellNum; i++) {
|
||||
mapExcelColumn.put(ExcelUtils.getString(rowColumn, i), i);
|
||||
}
|
||||
Map<String, Field> mapFiled = getMapFiled(entityClass);
|
||||
//TModel 所有属性字段Field key: 字段名
|
||||
int LastRowNum = productSheet.getLastRowNum();//excel最后一行
|
||||
TModel model;
|
||||
String errorMsg=null;
|
||||
for (int i = columnRowIndex + 1; i <= LastRowNum; i++) {
|
||||
Row row = productSheet.getRow(i);//获取行
|
||||
|
||||
model = entityClass.newInstance();
|
||||
if(row!=null) {
|
||||
errorMsg = rowToModel(mapExcelColumn, info, row, model, mapFiled);//行转model
|
||||
} else {errorMsg=null;}
|
||||
if (!StringUtils.isEmpty(errorMsg)) {//转换失败 保存错误行
|
||||
Map<String, Object> errorMap = getErrorMap(row, mapExcelColumn);//row转map
|
||||
errorMap.put("errorMsg", errorMsg);
|
||||
listErrorMap.add(errorMap);//加入转换错误行集合
|
||||
} else {//转换成功
|
||||
listTModel.add(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static <TModel> Map<String, Field> getMapFiled(Class<TModel> entityClass) {
|
||||
Map<String, Field> mapFiled = new HashMap<>();
|
||||
List<Field> listField = ReflectUtil.getListField(entityClass);
|
||||
for (Field field : listField) {
|
||||
mapFiled.put(field.getName(), field);
|
||||
}
|
||||
return mapFiled;
|
||||
}
|
||||
/**
|
||||
* 行转model
|
||||
*/
|
||||
static <TModel> String rowToModel(Map<String, Integer> mapExcelColumn, ExportExcelInfo<TModel> info, Row row, TModel model, Map<String, Field> mapFiled) throws Exception {
|
||||
String errorMsg = "";
|
||||
boolean hasValue = false;
|
||||
for (ExcelColumn column : info.getListColumn()) {
|
||||
if (mapExcelColumn.containsKey(column.getText())) {
|
||||
if (!mapFiled.containsKey(column.getCamelColumnName())) {
|
||||
throw new Exception(model.getClass().getName() + "不存在字段" + column.getCamelColumnName());
|
||||
}
|
||||
Field field = mapFiled.get(column.getCamelColumnName());
|
||||
String content = getString(row.getCell(mapExcelColumn.get(column.getText())));
|
||||
if (!column.isNull()) {
|
||||
if (StringUtils.isEmpty(content)) {
|
||||
errorMsg += column.getCamelColumnName() + "不能为空";
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (!StringUtils.isEmpty(content)) {
|
||||
hasValue = true;
|
||||
ReflectUtil.setFieldValueByName(field, content.trim(), model);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMsg += column.getCamelColumnName() + ":" + e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!hasValue){
|
||||
errorMsg +="该表格中有空行";
|
||||
}
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
static Map<String, Object> getErrorMap(Row row, Map<String, Integer> mapExcelColumn) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
for (String key : mapExcelColumn.keySet()) {
|
||||
Cell cell = row.getCell(mapExcelColumn.get(key));
|
||||
map.put(key, getString(cell));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static String getString(Cell cell) {
|
||||
String result = "";
|
||||
if (cell == null) return result;
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:// 数字类型
|
||||
//1、判断是否是数值格式
|
||||
if (HSSFDateUtil.isCellDateFormatted(cell)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
double value = cell.getNumericCellValue();
|
||||
Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
|
||||
result = sdf.format(date);
|
||||
} else {
|
||||
Double value = cell.getNumericCellValue();
|
||||
DecimalFormat format = new DecimalFormat();
|
||||
format.applyPattern("###################.###################");
|
||||
result = format.format(value);
|
||||
}
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:// String类型
|
||||
result = cell.getRichStringCellValue().toString();
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_FORMULA://公式型
|
||||
//读公式计算值
|
||||
try {
|
||||
|
||||
double value = cell.getNumericCellValue();
|
||||
if (Double.isNaN(value)) {//如果获取的数据值为非法值,则转换为获取字符串 //result.equals("NaN")
|
||||
result = cell.getRichStringCellValue().toString();
|
||||
} else {
|
||||
DecimalFormat format = new DecimalFormat();
|
||||
format.applyPattern("###################.###################");
|
||||
result = format.format(value);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
result = cell.getRichStringCellValue().toString();
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
result = "";
|
||||
break;
|
||||
default:
|
||||
result = "";
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 导入Excel列信息
|
||||
* @author xushuai
|
||||
*/
|
||||
public class ExportExcelInfo<TRow> {
|
||||
|
||||
public ExportExcelInfo(List<TRow> dataSource) {
|
||||
this.setDataSource(dataSource);
|
||||
}
|
||||
|
||||
List<ExcelColumn<TRow>> listColumn = new ArrayList<ExcelColumn<TRow>>();
|
||||
String fileName;
|
||||
List<TRow> dataSource;
|
||||
String Sheet = "sheet1";
|
||||
|
||||
int columnType;//列的类型 0:text(文本) 1:columnName
|
||||
|
||||
public int getColumnType() {
|
||||
return columnType;
|
||||
}
|
||||
|
||||
public void setColumnType(int columnType) {
|
||||
this.columnType = columnType;
|
||||
}
|
||||
|
||||
boolean IsDisplayColumnName = false;
|
||||
|
||||
|
||||
public boolean isDisplayColumnName() {
|
||||
return IsDisplayColumnName;
|
||||
}
|
||||
|
||||
public void setDisplayColumnName(boolean displayColumnName) {
|
||||
IsDisplayColumnName = displayColumnName;
|
||||
}
|
||||
|
||||
public String getSheet() {
|
||||
return Sheet;
|
||||
}
|
||||
|
||||
public void setSheet(String sheet) {
|
||||
Sheet = sheet;
|
||||
}
|
||||
|
||||
public List<TRow> getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public void setDataSource(List<TRow> dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public List<ExcelColumn<TRow>> getListColumn() {
|
||||
return listColumn;
|
||||
}
|
||||
|
||||
public void setListColumn(List<ExcelColumn<TRow>> listColumn) {
|
||||
this.listColumn = listColumn;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void addExcelColumn(ExcelColumn column) {
|
||||
listColumn.add(column);
|
||||
}
|
||||
|
||||
public ExcelColumn<TRow> addExcelColumn(String text, String columnName) {
|
||||
ExcelColumn<TRow> column = new ExcelColumn<TRow>();
|
||||
column.setText(text);
|
||||
column.setColumnName(columnName);
|
||||
column.setColumnType(EnumExcelColumnType.ColumnType_String);
|
||||
this.getListColumn().add(column);
|
||||
return column;
|
||||
}
|
||||
|
||||
public ExcelColumn addExcelColumn(String text, String columnName, EnumExcelColumnType columnType) {
|
||||
ExcelColumn<TRow> column = addExcelColumn(text, columnName);
|
||||
column.setColumnType(columnType);
|
||||
return column;
|
||||
}
|
||||
|
||||
public ExcelColumn<TRow> addExcelColumn(String text, String columnName, FunctionFormatter<Object, TRow, Integer, Object> formatter) {
|
||||
ExcelColumn<TRow> column = addExcelColumn(text, columnName);
|
||||
column.setFormatter(formatter);
|
||||
return column;
|
||||
}
|
||||
|
||||
public ExcelColumn<TRow> addExcelColumn(String text, String columnName, FunctionFormatter<Object, TRow, Integer, Object> formatter, EnumExcelColumnType columnType) {
|
||||
ExcelColumn column = addExcelColumn(text, columnName, formatter);
|
||||
column.setColumnType(columnType);
|
||||
return column;
|
||||
}
|
||||
|
||||
public ExcelColumn<TRow> getErrorColumn() {
|
||||
ExcelColumn<TRow> column = new ExcelColumn<TRow>();
|
||||
column.setText("异常信息");
|
||||
column.setColumnName("errorMsg");//errorMsg
|
||||
column.setColumnType(EnumExcelColumnType.ColumnType_String);
|
||||
column.setCamelColumnName("errorMsg");
|
||||
return column;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
/**
|
||||
* @author xushuai
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface FunctionFormatter<TValue,TRow,TIndex,R> {
|
||||
R apply(TValue value, TRow row, TIndex index);
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.pgmmers.radar.util;
|
||||
|
||||
import com.pgmmers.radar.dal.util.JsonUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 根据字段名获取字段
|
||||
* @author xushuai
|
||||
*/
|
||||
public class ReflectUtil {
|
||||
|
||||
public static void setFieldValueByName(Field field, Object fieldValue, Object o) throws Exception {
|
||||
field.setAccessible(true);
|
||||
//获取字段类型
|
||||
Class<?> fieldType = field.getType();
|
||||
//根据字段类型给字段赋值
|
||||
if (String.class == fieldType) {
|
||||
field.set(o, String.valueOf(fieldValue));
|
||||
} else if ((Integer.TYPE == fieldType)
|
||||
|| (Integer.class == fieldType)) {
|
||||
field.set(o, Integer.parseInt(fieldValue.toString()));
|
||||
} else if ((Long.TYPE == fieldType)
|
||||
|| (Long.class == fieldType)) {
|
||||
field.set(o, Long.valueOf(fieldValue.toString()));
|
||||
} else if ((Float.TYPE == fieldType)
|
||||
|| (Float.class == fieldType)) {
|
||||
field.set(o, Float.valueOf(fieldValue.toString()));
|
||||
} else if ((Short.TYPE == fieldType)
|
||||
|| (Short.class == fieldType)) {
|
||||
field.set(o, Short.valueOf(fieldValue.toString()));
|
||||
} else if ((Byte.TYPE == fieldType)
|
||||
|| (Byte.class == fieldType)) {
|
||||
field.set(o, Byte.valueOf(fieldValue.toString()));
|
||||
}
|
||||
else if ((Double.TYPE == fieldType)
|
||||
|| (Double.class == fieldType)) {
|
||||
field.set(o, Double.valueOf(fieldValue.toString()));
|
||||
} else if (Character.TYPE == fieldType) {
|
||||
if ((fieldValue != null) && (fieldValue.toString().length() > 0)) {
|
||||
field.set(o, fieldValue.toString().charAt(0));
|
||||
}
|
||||
} else if (BigDecimal.class == fieldType) {
|
||||
Long v1 = Long.valueOf(fieldValue.toString());
|
||||
field.set(o, BigDecimal.valueOf(v1));
|
||||
} else if (Date.class == fieldType) {
|
||||
field.set(o, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fieldValue.toString()));
|
||||
} else if (boolean.class == fieldType) {
|
||||
if ("1".equals(fieldValue)) {
|
||||
field.set(o, true);
|
||||
}
|
||||
if ("0".equals(fieldValue)) {
|
||||
field.set(o, false);
|
||||
}
|
||||
field.set(o, Boolean.valueOf(fieldValue.toString()));
|
||||
} else if (String[].class == fieldType) {
|
||||
String[] arr = JsonUtils.fromJson(fieldValue.toString(), String[].class);
|
||||
field.set(o, arr);
|
||||
} else {
|
||||
field.set(o, fieldValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Field> getListField(Class<?> clazz) {
|
||||
Field[] selfFields = clazz.getDeclaredFields();
|
||||
List<Field> list = new ArrayList<>(Arrays.asList(selfFields));
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
if (superClazz != null && superClazz != Object.class) {
|
||||
List<Field> listSuperField = getListField(superClazz);
|
||||
for (Field field : listSuperField) {
|
||||
list.add(field);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段名获取字段
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @param clazz 包含该字段的类
|
||||
* @return 字段
|
||||
*/
|
||||
public static Field getFieldByName(String fieldName, Class<?> clazz) {
|
||||
//拿到本类的所有字段
|
||||
Field[] selfFields = clazz.getDeclaredFields();
|
||||
//如果本类中存在该字段,则返回
|
||||
for (Field field : selfFields) {
|
||||
if (field.getName().equals(fieldName)) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
//否则,查看父类中是否存在此字段,如果有则返回
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
if (superClazz != null && superClazz != Object.class) {
|
||||
return getFieldByName(fieldName, superClazz);
|
||||
}
|
||||
//如果本类和父类都没有,则返回空
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* getFieldValueByNameSequence
|
||||
*
|
||||
* @param fieldNameSequence 带路径的属性名或简单属性名
|
||||
* @param o 对象
|
||||
* @return 属性值
|
||||
* @throws Exception 根据带路径或不带路径的属性名获取属性值
|
||||
* 即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
|
||||
*/
|
||||
public static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception {
|
||||
Object value;
|
||||
//将fieldNameSequence进行拆分
|
||||
String[] attributes = fieldNameSequence.split("\\.");
|
||||
if (attributes.length == 1) {
|
||||
value = getFieldValueByName(fieldNameSequence, o);
|
||||
} else {
|
||||
//根据属性名获取属性对象
|
||||
Object fieldObj = getFieldValueByName(attributes[0], o);
|
||||
String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
|
||||
value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
/*<-------------------------辅助的私有方法----------------------------------------------->*/
|
||||
|
||||
/**
|
||||
* 根据字段名获取字段值
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @param o 对象
|
||||
* @return 字段值
|
||||
*/
|
||||
public static Object getFieldValueByName(String fieldName, Object o) throws Exception {
|
||||
Object value;
|
||||
Field field = getFieldByName(fieldName, o.getClass());
|
||||
if (field == null) {
|
||||
throw new Exception(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);
|
||||
}
|
||||
value = getValueByField(fieldName, o, field);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static Object getValueByField(String fieldName, Object o, Field field) throws IllegalAccessException {
|
||||
field.setAccessible(true);
|
||||
return field.get(o);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>风控引擎管理平台</title> <link rel="shortcut icon" href="/images/anquan.png"> <!--[if lt IE 10]>
|
||||
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.5.7/es5-shim.min.js,es5-shim/4.5.7/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]--> <link href="./index.b4475d72-1.css" rel="stylesheet"><link href="./index.b4475d72-2.css" rel="stylesheet"><link href="./index.b4475d72-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.b4475d72.js"></script></body> </html>
|
||||
<![endif]--> <link href="./index.3b7ff13c-1.css" rel="stylesheet"><link href="./index.3b7ff13c-2.css" rel="stylesheet"><link href="./index.3b7ff13c-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.3b7ff13c.js"></script></body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -112,4 +114,45 @@ public class ExcelUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 row 的第 index 列,获取字符串值
|
||||
*
|
||||
* @param row 目标行
|
||||
* @param index 目标列
|
||||
* @return 字符串值
|
||||
* @author xushuai
|
||||
*/
|
||||
public static String getString(Row row, int index) {
|
||||
return getString(row, index, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 row 的第 index 列,获取字符串值
|
||||
*
|
||||
* @param row 目标行
|
||||
* @param index 目标列
|
||||
* @param numberFormat 对原值为数字时的,数字格式化格式
|
||||
* @return 字符串值
|
||||
* @author xushuai
|
||||
*/
|
||||
public static String getString(Row row, int index, String numberFormat) {
|
||||
Cell cell = row.getCell(index);
|
||||
|
||||
if (cell == null) return null;
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case Cell.CELL_TYPE_NUMERIC:
|
||||
double val = cell.getNumericCellValue();
|
||||
if (numberFormat == null)
|
||||
return String.valueOf(val);
|
||||
NumberFormat formatter = new DecimalFormat(numberFormat);
|
||||
return formatter.format(val);
|
||||
case Cell.CELL_TYPE_STRING:
|
||||
return cell.getStringCellValue();
|
||||
case Cell.CELL_TYPE_FORMULA:
|
||||
return cell.getStringCellValue();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ public class ModelDalImpl implements ModelDal {
|
||||
PreItemVO vo = null;
|
||||
for (PreItemPO po : itemPOList) {
|
||||
vo = new PreItemVO();
|
||||
BeanUtils.copyProperties(po, vo);
|
||||
vo = POVOUtils.copyFromPreItemPO(po);
|
||||
itemList.add(vo);
|
||||
}
|
||||
return itemList;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
|
||||
import com.pgmmers.radar.dal.bean.PageResult;
|
||||
import com.pgmmers.radar.dal.bean.PreItemQuery;
|
||||
import com.pgmmers.radar.dal.model.PreItemDal;
|
||||
import com.pgmmers.radar.dal.util.POVOUtils;
|
||||
import com.pgmmers.radar.mapper.PreItemMapper;
|
||||
import com.pgmmers.radar.model.PreItemPO;
|
||||
import com.pgmmers.radar.vo.model.PreItemVO;
|
||||
@@ -34,7 +35,8 @@ public class PreItemDalImpl implements PreItemDal {
|
||||
PreItemPO preItem = preItemMapper.selectByPrimaryKey(id);
|
||||
if (preItem != null) {
|
||||
PreItemVO preItemVO = new PreItemVO();
|
||||
BeanUtils.copyProperties(preItem, preItemVO);
|
||||
//BeanUtils.copyProperties(preItem, preItemVO);
|
||||
preItemVO = POVOUtils.copyFromPreItemPO(preItem);
|
||||
return preItemVO;
|
||||
}
|
||||
return null;
|
||||
@@ -63,8 +65,8 @@ public class PreItemDalImpl implements PreItemDal {
|
||||
|
||||
List<PreItemVO> listVO = new ArrayList<PreItemVO>();
|
||||
for (PreItemPO preItemPO : page.getResult()) {
|
||||
PreItemVO preItemVO = new PreItemVO();
|
||||
BeanUtils.copyProperties(preItemPO, preItemVO);
|
||||
PreItemVO preItemVO ;
|
||||
preItemVO = POVOUtils.copyFromPreItemPO(preItemPO);
|
||||
listVO.add(preItemVO);
|
||||
}
|
||||
|
||||
@@ -75,15 +77,15 @@ public class PreItemDalImpl implements PreItemDal {
|
||||
|
||||
@Override
|
||||
public int save(PreItemVO preItem) {
|
||||
PreItemPO preItemPO = new PreItemPO();
|
||||
BeanUtils.copyProperties(preItem, preItemPO);
|
||||
PreItemPO preItemPO ;
|
||||
preItemPO = POVOUtils.copyFromPreItemVO(preItem);
|
||||
Date sysDate = new Date();
|
||||
int count = 0;
|
||||
if (preItemPO.getId() == null) {
|
||||
preItemPO.setCreateTime(sysDate);
|
||||
preItemPO.setUpdateTime(sysDate);
|
||||
count = preItemMapper.insertSelective(preItemPO);
|
||||
preItem.setId(preItemPO.getId());// 返回id
|
||||
preItem.setId(preItemPO.getId());
|
||||
} else {
|
||||
preItemPO.setUpdateTime(sysDate);
|
||||
count = preItemMapper.updateByPrimaryKeySelective(preItemPO);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.pgmmers.radar.dal.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonParser.Feature;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* json对象转换
|
||||
* @author xushuai
|
||||
*/
|
||||
public class JsonUtils {
|
||||
public JsonUtils() {
|
||||
}
|
||||
|
||||
public static String toJson(Object object) {
|
||||
try {
|
||||
return (new ObjectMapper()).setSerializationInclusion(Include.NON_NULL).writeValueAsString(object);
|
||||
} catch (JsonProcessingException var2) {
|
||||
throw new RuntimeException(var2);
|
||||
}
|
||||
}
|
||||
|
||||
public static <E> E fromJson(String json, Class<E> type) {
|
||||
try {
|
||||
return (new ObjectMapper()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readValue(json, type);
|
||||
} catch (IOException var3) {
|
||||
throw new RuntimeException(var3);
|
||||
}
|
||||
}
|
||||
|
||||
public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
|
||||
return (new ObjectMapper()).getTypeFactory().constructParametricType(collectionClass, elementClasses);
|
||||
}
|
||||
|
||||
public static String toJsonString(Object object) {
|
||||
try {
|
||||
return (new ObjectMapper()).writeValueAsString(object);
|
||||
} catch (JsonProcessingException var2) {
|
||||
var2.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map writeJsonToMap(String json) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
Map map = null;
|
||||
|
||||
try {
|
||||
map = (Map)mapper.readValue(json, Map.class);
|
||||
return map;
|
||||
} catch (IOException var4) {
|
||||
throw new RuntimeException(var4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,14 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.util.JSONPObject;
|
||||
import com.pgmmers.radar.model.AbstractionPO;
|
||||
import com.pgmmers.radar.model.MobileInfoPO;
|
||||
import com.pgmmers.radar.model.ModelPO;
|
||||
import com.pgmmers.radar.model.RulePO;
|
||||
import com.pgmmers.radar.model.*;
|
||||
import com.pgmmers.radar.vo.data.MobileInfoVO;
|
||||
import com.pgmmers.radar.vo.model.AbstractionVO;
|
||||
import com.pgmmers.radar.vo.model.ModelVO;
|
||||
import com.pgmmers.radar.vo.model.PreItemVO;
|
||||
import com.pgmmers.radar.vo.model.RuleVO;
|
||||
import jdk.nashorn.internal.parser.JSONParser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -89,4 +88,34 @@ public class POVOUtils {
|
||||
}
|
||||
return po;
|
||||
}
|
||||
|
||||
public static PreItemPO copyFromPreItemVO(PreItemVO vo) {
|
||||
PreItemPO po = new PreItemPO();
|
||||
BeanUtils.copyProperties(vo, po);
|
||||
try {
|
||||
if (vo.getConfigJson() != null) {
|
||||
String str = objectMapper.writeValueAsString(vo.getConfigJson());
|
||||
po.setConfigJson(str);
|
||||
}
|
||||
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return po;
|
||||
}
|
||||
|
||||
public static PreItemVO copyFromPreItemPO(PreItemPO po) {
|
||||
PreItemVO vo = new PreItemVO();
|
||||
BeanUtils.copyProperties(po, vo);
|
||||
JsonNode json = null;
|
||||
try {
|
||||
if (!StringUtils.isEmpty(po.getConfigJson())) {
|
||||
json = objectMapper.readTree(po.getConfigJson());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
vo.setConfigJson(json);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ public enum PluginType {
|
||||
"ip2location",
|
||||
"IP转换成地址",
|
||||
null,
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"provice\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"province\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
GPS2LOCATION(
|
||||
2,
|
||||
"gps2location",
|
||||
"GPS转换成地址",
|
||||
null,
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"provice\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"province\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
ALLINONE(3, "allInOne", "字段合并", "STRING", null), //
|
||||
SUBSTRING(4, "subString", "字符串截短", "STRING", null), //
|
||||
MOBILE2LOCATION(
|
||||
@@ -30,9 +30,10 @@ public enum PluginType {
|
||||
"mobile2location",
|
||||
"手机号码归属地",
|
||||
null,
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"provice\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
"[{\"column\":\"country\", \"title\":\"国家\", \"type\":\"STRING\"},{\"column\":\"province\", \"title\":\"省份\", \"type\":\"STRING\"},{\"column\":\"city\", \"title\":\"城市\", \"type\":\"STRING\"}]"), //
|
||||
SENSITIVE_TIME(6, "getSensitiveTime", "敏感时间段(小时)", "STRING", null),
|
||||
DATEFORMAT(7, "formatDate", "日期时间格式化", "STRING", null),
|
||||
HTTP_UTIL(8, "httpRequest", "HttpUtil", "JSON", null),
|
||||
;
|
||||
|
||||
private Integer key;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
package com.pgmmers.radar.vo.model;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@@ -22,6 +25,10 @@ public class PreItemVO implements Serializable{
|
||||
|
||||
private String plugin;
|
||||
|
||||
private String reqType = "GET";
|
||||
|
||||
@JsonProperty
|
||||
private JsonNode configJson;
|
||||
|
||||
private Integer status;
|
||||
|
||||
@@ -141,6 +148,22 @@ public class PreItemVO implements Serializable{
|
||||
public void setSourceLabel(String sourceLabel) {
|
||||
this.sourceLabel = sourceLabel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public JsonNode getConfigJson() {
|
||||
return configJson;
|
||||
}
|
||||
|
||||
public void setConfigJson(JsonNode configJson) {
|
||||
this.configJson = configJson;
|
||||
}
|
||||
|
||||
|
||||
public String getReqType() {
|
||||
return reqType;
|
||||
}
|
||||
|
||||
public void setReqType(String reqType) {
|
||||
this.reqType = reqType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>radar-dao</artifactId>
|
||||
@@ -79,7 +79,7 @@
|
||||
<dependency>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<artifactId>radar-commons</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
@@ -49,6 +49,15 @@ public class PreItemPO {
|
||||
@Column(name = "PLUGIN")
|
||||
private String plugin;
|
||||
|
||||
@Column(name = "CONFIG_JSON")
|
||||
private String configJson;
|
||||
|
||||
/**
|
||||
* 请求方式
|
||||
*/
|
||||
@Column(name = "REQ_TYPE")
|
||||
private String reqType;
|
||||
|
||||
@Column(name = "STATUS")
|
||||
private Integer status;
|
||||
|
||||
@@ -194,6 +203,38 @@ public class PreItemPO {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CONFIG_JSON
|
||||
*/
|
||||
public String getConfigJson() {
|
||||
return configJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configJson
|
||||
*/
|
||||
public void setConfigJson(String configJson) {
|
||||
this.configJson = configJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求方式
|
||||
*
|
||||
* @return REQ_TYPE - 请求方式
|
||||
*/
|
||||
public String getReqType() {
|
||||
return reqType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求方式
|
||||
*
|
||||
* @param reqType 请求方式
|
||||
*/
|
||||
public void setReqType(String reqType) {
|
||||
this.reqType = reqType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return STATUS
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
<result column="LABEL" jdbcType="VARCHAR" property="label" />
|
||||
<result column="ARGS" jdbcType="VARCHAR" property="args" />
|
||||
<result column="PLUGIN" jdbcType="VARCHAR" property="plugin" />
|
||||
<result column="CONFIG_JSON" jdbcType="VARCHAR" property="configJson" />
|
||||
<result column="REQ_TYPE" jdbcType="VARCHAR" property="reqType" />
|
||||
<result column="STATUS" jdbcType="INTEGER" property="status" />
|
||||
<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime" />
|
||||
<result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.pgmmers.radar.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
//ms
|
||||
factory.setReadTimeout(5000);
|
||||
factory.setConnectTimeout(5000);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -61,5 +61,10 @@
|
||||
<groupId>org.elasticsearch</groupId>
|
||||
<artifactId>elasticsearch</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -120,7 +120,7 @@ public class AntiFraudServiceImpl implements AntiFraudService {
|
||||
jsonInfo.get(sourceField[1]).toString());
|
||||
break;
|
||||
case ALLINONE:
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
List<Object> values = new ArrayList<>();
|
||||
for (String field : sourceField) {
|
||||
values.add(jsonInfo.get(field));
|
||||
}
|
||||
@@ -142,11 +142,16 @@ public class AntiFraudServiceImpl implements AntiFraudService {
|
||||
millis = Long.parseLong(jsonInfo.get(sourceField[0]).toString());
|
||||
transfer = pluginService.formatDate(millis, formatStr);
|
||||
break;
|
||||
case HTTP_UTIL:
|
||||
String url = item.getArgs();
|
||||
String reqType = item.getReqType();
|
||||
String arg = jsonInfo.get(sourceField[0]).toString();
|
||||
transfer = pluginService.httpRequest(url, reqType, arg);
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
result.put(item.getDestField(), transfer);
|
||||
//result.put(plugin.getFieldName(), transfer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.pgmmers.radar.service.impl.engine;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.pgmmers.radar.enums.CombineType;
|
||||
import com.pgmmers.radar.service.data.MobileInfoService;
|
||||
import com.pgmmers.radar.service.engine.PluginService;
|
||||
@@ -17,7 +18,9 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Calendar;
|
||||
@@ -37,6 +40,9 @@ public class PluginServiceImpl implements PluginService {
|
||||
@Autowired
|
||||
private MobileInfoService mobileInfoService;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
@@ -53,14 +59,13 @@ public class PluginServiceImpl implements PluginService {
|
||||
if (!Util.isIpAddress(ip)) {
|
||||
return null;
|
||||
}
|
||||
;
|
||||
try {
|
||||
DataBlock block = ipSearcher.memorySearch(ip);
|
||||
String[] detail = block.getRegion().split("\\|");
|
||||
location = new Location();
|
||||
location.setCountry(detail[0]);
|
||||
location.setRegion(detail[1]);
|
||||
location.setProvice(detail[2]);
|
||||
location.setProvince(detail[2]);
|
||||
location.setCity(detail[3]);
|
||||
location.setAddress(detail[4]);
|
||||
} catch (Exception e) {
|
||||
@@ -72,7 +77,7 @@ public class PluginServiceImpl implements PluginService {
|
||||
|
||||
@Override
|
||||
public Location gps2location(String lng, String lat) {
|
||||
// TODO Auto-generated method stub
|
||||
// TODO 可以参考 http://jwd.funnyapi.com/#/index , 最好是本地库。
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -111,7 +116,7 @@ public class PluginServiceImpl implements PluginService {
|
||||
MobileInfoVO vo = mobileInfoService.getMobileInfoByMobile(mobile);
|
||||
Location location = new Location();
|
||||
if (vo != null) {
|
||||
location.setProvice(vo.getProvince());
|
||||
location.setProvince(vo.getProvince());
|
||||
location.setCity(vo.getCity());
|
||||
location.setCountry("中国");
|
||||
}
|
||||
@@ -131,4 +136,16 @@ public class PluginServiceImpl implements PluginService {
|
||||
return dateStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject httpRequest(String url, String reqType, String... args) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||
ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, HttpMethod.valueOf(reqType), entity, JSONObject.class, args);
|
||||
logger.info("http plugin:{}\n{}\n {}", url, args, responseEntity.toString());
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK) {
|
||||
return responseEntity.getBody();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.pgmmers.radar.service.impl.model;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import com.pgmmers.radar.dal.bean.DataListQuery;
|
||||
import com.pgmmers.radar.dal.bean.DataListRecordQuery;
|
||||
import com.pgmmers.radar.dal.model.DataListDal;
|
||||
@@ -279,4 +278,45 @@ public class DataListsServiceImpl implements DataListsService, SubscribeHandle {
|
||||
Map<String, Object> listMap = dataListRecordCacheMap.get(modelId);
|
||||
return listMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult batchImportData(List<DataListsVO> list, Long modelId) {
|
||||
CommonResult result = new CommonResult();
|
||||
for (DataListsVO data : list) {
|
||||
data.setStatus(1);
|
||||
data.setName("");
|
||||
data.setModelId(modelId);
|
||||
int count = dataListDal.save(data);
|
||||
if (count > 0) {
|
||||
if(StringUtils.isEmpty(data.getName())){
|
||||
data.setName("dataList_"+data.getId());
|
||||
dataListDal.save(data);
|
||||
}
|
||||
// 通知更新
|
||||
data.setOpt("new");
|
||||
cacheService.publishDataList(data);
|
||||
}
|
||||
}
|
||||
result.setSuccess(true);
|
||||
result.setMsg("导入成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult batchImportDataRecord(List<DataListRecordVO> list, Long dataListId) {
|
||||
CommonResult result = new CommonResult();
|
||||
for (DataListRecordVO dataListRecord : list) {
|
||||
int count = dataListDal.saveRecord(dataListRecord);
|
||||
if (count > 0) {
|
||||
// 通知更新
|
||||
DataListsVO dataListVO = dataListDal.get(dataListRecord.getDataListId());
|
||||
dataListRecord.setModelId(dataListVO.getModelId());
|
||||
dataListRecord.setOpt("update");
|
||||
cacheService.publishDataListRecord(dataListRecord);
|
||||
}
|
||||
}
|
||||
result.setSuccess(true);
|
||||
result.setMsg("导入成功");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,20 +85,11 @@ public class PreItemServiceImpl implements PreItemService, SubscribeHandle {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// if (preItem.getId() == null) {
|
||||
// FieldQuery query = new FieldQuery();
|
||||
// query.setModelId(preItem.getModelId());
|
||||
// query.setFieldName(fieldName);
|
||||
// PageResult<FieldVO> page = fieldDal.query(query);
|
||||
// if (page != null && page.getRowCount() > 0) {
|
||||
// result.setMsg("字段名已定义");
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
|
||||
int count = preItemDal.save(preItem);
|
||||
if (count > 0) {
|
||||
if(StringUtils.isEmpty(preItem.getDestField())){
|
||||
preItem.setDestField("preItem_"+preItem.getId());
|
||||
preItem.setDestField("preItem_" + preItem.getId());
|
||||
preItemDal.save(preItem);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.pgmmers.radar.service.engine;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.pgmmers.radar.service.engine.vo.Location;
|
||||
|
||||
import java.util.List;
|
||||
@@ -51,5 +52,22 @@ public interface PluginService {
|
||||
|
||||
String getSensitiveTime(Long timeMills);
|
||||
|
||||
/**
|
||||
* date format by format str, like yyyyMMdd.
|
||||
* @param timeMills
|
||||
* @param format
|
||||
* @return
|
||||
* @author feihu.wang
|
||||
*/
|
||||
String formatDate(Long timeMills, String format);
|
||||
|
||||
/**
|
||||
* http util.
|
||||
* @param url
|
||||
* @param reqType
|
||||
* @param args
|
||||
* @return
|
||||
* @author feihu.wang
|
||||
*/
|
||||
JSONObject httpRequest(String url, String reqType, String ...args);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ public class Location {
|
||||
|
||||
private String region = "";
|
||||
|
||||
private String provice = "";
|
||||
private String province = "";
|
||||
|
||||
private String city = "";
|
||||
|
||||
@@ -28,12 +28,12 @@ public class Location {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getProvice() {
|
||||
return provice;
|
||||
public String getProvince() {
|
||||
return province;
|
||||
}
|
||||
|
||||
public void setProvice(String provice) {
|
||||
this.provice = provice;
|
||||
public void setProvince(String province) {
|
||||
this.province = province;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
|
||||
@@ -48,4 +48,7 @@ public interface DataListsService {
|
||||
|
||||
Map<String, Object> getDataListMap(Long modelId);
|
||||
|
||||
CommonResult batchImportData(List<DataListsVO> list, Long modelId);
|
||||
|
||||
CommonResult batchImportDataRecord(List<DataListRecordVO> list, Long dataListId);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
-- developers of radar
|
||||
CREATE TABLE `contribute_info` (
|
||||
`ID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`NAME` varchar(30) NOT NULL COMMENT '功能名称',
|
||||
`CONTENT` varchar(200) NOT NULL COMMENT '功能描叙',
|
||||
`DEVELOPER` varchar(60) NOT NULL COMMENT '开发者',
|
||||
`RELEASE_VERSION` varchar(30) DEFAULT NULL COMMENT '发布版本',
|
||||
`CREATE_TIME` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`ID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
7
sql/radar-1.0.2.sql
Normal file
7
sql/radar-1.0.2.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE `engine_pre_item`
|
||||
MODIFY COLUMN `ARGS` varchar(250) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '参数' AFTER `LABEL`;
|
||||
ALTER TABLE `engine_pre_item`
|
||||
ADD COLUMN `CONFIG_JSON` varchar(250) NULL COMMENT '响应字段配置信息' AFTER `PLUGIN`;
|
||||
ALTER TABLE `engine_pre_item`
|
||||
ADD COLUMN `REQ_TYPE` varchar(16) NULL COMMENT '请求方式' AFTER `CONFIG_JSON`;
|
||||
|
||||
@@ -1 +1 @@
|
||||
//TODO: 项目前后端分离,此目录用于存放前端代码
|
||||
//项目前后端分离,此目录用于存放前端代码
|
||||
@@ -22,24 +22,31 @@ export default class AddPreItem extends React.Component{
|
||||
sourceLabel:'',
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:''
|
||||
args:'',
|
||||
reqType:'GET',
|
||||
configJson:''
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
console.log(e,'==')
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
state[name] = typeof value==='number'?value: trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
if(name=='plugin'){
|
||||
state['sourceField']='';
|
||||
state['sourceLabel']='';
|
||||
state['args']='';
|
||||
state['args']='';
|
||||
state['status']=1;
|
||||
state['configJson']='';
|
||||
}
|
||||
state[name] = trim(value);
|
||||
|
||||
@@ -74,11 +81,16 @@ export default class AddPreItem extends React.Component{
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:'',
|
||||
visible:true
|
||||
reqType:'GET',
|
||||
visible:true,
|
||||
configJson:''
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(typeof JSON.parse(this.state.configJson)!='object'){
|
||||
return message.error('多文本框json格式不对');
|
||||
}
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
@@ -93,10 +105,11 @@ export default class AddPreItem extends React.Component{
|
||||
param.sourceField=this.state.sourceField;
|
||||
param.sourceLabel=this.state.sourceLabel;
|
||||
param.plugin=this.state.plugin;
|
||||
param.status=this.state.status;
|
||||
param.args=this.state.args;
|
||||
|
||||
FetchUtil('/preitem/','PUT',JSON.stringify(param),
|
||||
param.status=this.state.status;
|
||||
param.reqType=this.state.reqType;
|
||||
param.args=this.state.args;
|
||||
param.configJson=JSON.parse(this.state.configJson);
|
||||
FetchUtil('/preitem/','PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
@@ -175,11 +188,15 @@ export default class AddPreItem extends React.Component{
|
||||
} else if (this.state.plugin=='DATEFORMAT') {
|
||||
validate.args.help='请输入日期格式化字符串';
|
||||
isValidated=false;
|
||||
} else if (this.state.plugin=='RESTUTIL') {
|
||||
validate.args.help='请输入正确的 url';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
const plugin=this.state.plugin;
|
||||
let fieldArr=this.state.sourceField==''?[]:this.state.sourceField.split(',');
|
||||
let fieldArr=this.state.sourceField==''?[]:this.state.sourceField.split(',');
|
||||
console.log( this.props.plugins)
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
@@ -270,7 +287,43 @@ export default class AddPreItem extends React.Component{
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="请求信息" style={plugin=='HTTP_UTIL'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Radio.Group name="reqType" onChange={this.handleChange} value={this.state.reqType}>
|
||||
<Radio value={'GET'}>GET</Radio>
|
||||
<Radio disabled={true} value={'POST'}>POST</Radio>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'请求方式: POST, GET'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'Rest url, like http://xxx/getSth?id={1}'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="configJson" value={this.state.configJson} onChange={(e)=>this.handleChange(e)} rows={4} placeholder="请输入响应结果字段描叙信息:json数组" />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'响应字段元信息, like:[{"column":"country","title":"国家","type":"STRING"},{"column":"province","title":"省份","type":"STRING"}]'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
|
||||
@@ -23,7 +23,8 @@ export default class EditPreItem extends React.Component{
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:'',
|
||||
|
||||
reqType:'GET',
|
||||
configJson:'',
|
||||
preItem:null
|
||||
}
|
||||
|
||||
@@ -40,8 +41,11 @@ export default class EditPreItem extends React.Component{
|
||||
sourceField:preItem.sourceField,
|
||||
sourceLabel:preItem.sourceLabel,
|
||||
plugin:preItem.plugin,
|
||||
status:preItem.status,
|
||||
args:preItem.args
|
||||
status:preItem.status,
|
||||
reqType:preItem.reqType,
|
||||
args:preItem.args,
|
||||
configJson:JSON.stringify(preItem.configJson)
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -50,7 +54,7 @@ export default class EditPreItem extends React.Component{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
state[name] = typeof value==='number'?value: trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
@@ -59,7 +63,8 @@ export default class EditPreItem extends React.Component{
|
||||
if(name=='plugin'){
|
||||
state['sourceField']='';
|
||||
state['sourceLabel']='';
|
||||
state['args']='';
|
||||
state['args']='';
|
||||
state['configJson']='';
|
||||
}
|
||||
state[name] = trim(value);
|
||||
|
||||
@@ -93,6 +98,9 @@ export default class EditPreItem extends React.Component{
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(typeof JSON.parse(this.state.configJson)!='object'){
|
||||
return message.error('多文本框json格式不对');
|
||||
}
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
@@ -109,7 +117,9 @@ export default class EditPreItem extends React.Component{
|
||||
param.sourceLabel=this.state.sourceLabel;
|
||||
param.plugin=this.state.plugin;
|
||||
param.status=this.state.status;
|
||||
param.args=this.state.args;
|
||||
param.args=this.state.args;
|
||||
param.reqType=this.state.reqType;
|
||||
param.configJson=JSON.parse(this.state.configJson);
|
||||
|
||||
FetchUtil('/preitem/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
@@ -270,7 +280,45 @@ export default class EditPreItem extends React.Component{
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="请求信息" style={plugin=='HTTP_UTIL'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Radio.Group name="reqType" onChange={this.handleChange} value={this.state.reqType}>
|
||||
<Radio value={'GET'}>GET</Radio>
|
||||
<Radio disabled={true} value={'POST'}>POST</Radio>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'请求方式: POST, GET'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'Rest url, like http://xxx/getSth?id={1}'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="configJson" value={this.state.configJson} onChange={(e)=>this.handleChange(e)} rows={4} placeholder="请输入响应结果字段描叙信息:json数组" />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'响应字段元信息,like:[{"column":"country","title":"国家","type":"STRING"},{"column":"province","title":"省份","type":"STRING"}]'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
|
||||
@@ -26,7 +26,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
disableHostCheck: true, // 新增该配置项
|
||||
proxy: [{
|
||||
context: ["/services/v1/"],
|
||||
target: "http://104.128.89.231:8080",
|
||||
target: "http://10.50.3.218:8080",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
onProxyRes: function (proxyRes, req, res) { //
|
||||
|
||||
Reference in New Issue
Block a user