新增表单接收通用接口

master
queyounan 4 years ago
parent c2e7c11986
commit 1169e5ef20

@ -0,0 +1,70 @@
package com.yuyou.openapi.openapi.api;
import cn.hutool.json.JSONUtil;
import com.yuyou.openapi.openapi.common.CommonResponse;
import com.yuyou.openapi.openapi.common.ResponseCode;
import com.yuyou.openapi.openapi.model.dto.FormMessageDTO;
import com.yuyou.openapi.openapi.model.vo.FormClientMessageVO;
import com.yuyou.openapi.openapi.service.FormMessageService;
import com.yuyou.openapi.openapi.utils.SecurityOperationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;
/**
*
*/
@RestController
@Slf4j
public class FormClient {
@Autowired
private FormMessageService formMessageService;
/**
*
*
* @return
*/
@PostMapping(value = "/api/req/form/{actName}")
@ResponseBody
public CommonResponse getFormData(@PathVariable("actName") String actName, @RequestBody FormClientMessageVO formClientMessageVO){
if (StringUtils.isEmpty(actName) || Objects.isNull(formClientMessageVO)) {
return CommonResponse.createByErrorMessage(ResponseCode.EMPTY_ARGUMENT.getDesc());
}
log.info("====== [ Receive one request, content is {} ] ======", formClientMessageVO.toString());
// 验证参数,并进行解密
String callLog = formClientMessageVO.getCallLog();
if (StringUtils.isEmpty(callLog)){
return CommonResponse.createByErrorMessage("CallLog is empty.");
}
// 解密获取Json字串
String jsonStr = SecurityOperationUtil.decCallLogSecurityInfo(callLog);
if (StringUtils.isEmpty(jsonStr)){
return CommonResponse.createByErrorMessage(ResponseCode.DECRYPT_ERROR.getDesc());
}
FormMessageDTO formMessageDTO = convertFormMessageDTO(jsonStr, formClientMessageVO);
// 解析JSON并入库
return formMessageService.recordFormMessage(actName, formMessageDTO) ?
CommonResponse.createBySuccess() : CommonResponse.createByErrorMessage("调用失败请重试");
}
/**
* FormMessageDTO
* @param jsonStr
* @return
*/
private FormMessageDTO convertFormMessageDTO(String jsonStr, FormClientMessageVO formClientMessageVO) {
FormMessageDTO formMessageDTO = JSONUtil.toBean(jsonStr, FormMessageDTO.class);
BeanUtils.copyProperties(formClientMessageVO, formMessageDTO);
return formMessageDTO;
}
}

@ -0,0 +1,22 @@
package com.yuyou.openapi.openapi.common.spi;
public interface ErrorCode {
// 错误码编号
String getCode();
// 错误码描述
String getDescription();
/** toString
*
* <pre>
* &#064;Override
* public String toString() {
* return String.format(&quot;Code:[%s], Description:[%s]. &quot;, this.code, this.describe);
* }
* </pre>
*
*/
String toString();
}

@ -0,0 +1,9 @@
package com.yuyou.openapi.openapi.dao;
import com.yuyou.openapi.openapi.model.dataobject.FormActInfo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FormActInfoRepository extends JpaRepository<FormActInfo, Long> {
FormActInfo findFirstByActName(String actName);
}

@ -0,0 +1,67 @@
package com.yuyou.openapi.openapi.exception;
import com.yuyou.openapi.openapi.common.spi.ErrorCode;
/**
*
*/
public class BaiyeException extends RuntimeException {
private static final long serialVersionUID = 1L;
private ErrorCode errorCode;
public BaiyeException(ErrorCode errorCode) {
super(errorCode.toString());
this.errorCode = errorCode;
}
public BaiyeException(ErrorCode errorCode, String errorMessage) {
super(errorCode.toString() + " - " + errorMessage);
this.errorCode = errorCode;
}
private BaiyeException(ErrorCode errorCode, String errorMessage,
Throwable cause) {
super(errorCode.toString() + " - " + getMessage(errorMessage)
+ " - " + getMessage(cause), cause);
this.errorCode = errorCode;
}
public static BaiyeException asBaiyeException(ErrorCode errorCode, String message) {
return new BaiyeException(errorCode, message);
}
public static BaiyeException asBaiyeException(ErrorCode errorCode, String message,
Throwable cause) {
if (cause instanceof BaiyeException) {
return (BaiyeException) cause;
}
return new BaiyeException(errorCode, message, cause);
}
public static BaiyeException asBaiyeException(ErrorCode errorCode,
Throwable cause) {
if (cause instanceof BaiyeException) {
return (BaiyeException) cause;
}
return new BaiyeException(errorCode, getMessage(cause), cause);
}
public ErrorCode getErrorCode() {
return this.errorCode;
}
private static String getMessage(Object obj) {
if (obj == null) {
return "";
}
if (obj instanceof Throwable) {
return ((Throwable) obj).getMessage();
} else {
return obj.toString();
}
}
}

@ -0,0 +1,34 @@
package com.yuyou.openapi.openapi.exception;
import com.yuyou.openapi.openapi.common.spi.ErrorCode;
public enum CommonErrorCode implements ErrorCode {
CONFIG_ERROR(501, "您提供的配置文件存在错误信息,请检查您的作业配置"),
RUNTIME_ERROR(500, "运行时内部调用错误"),
DATA_NOT_EXIT(502, "数据不存在"),;
private final int code;
private final String describe;
private CommonErrorCode(int code, String describe) {
this.code = code;
this.describe = describe;
}
@Override
public String getCode() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public String toString() {
return String.format("Code:[%s], Describe:[%s]", this.code,
this.describe);
}
}

@ -0,0 +1,50 @@
package com.yuyou.openapi.openapi.model.dataobject;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@Table(name = "form_act_info")
public class FormActInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long actId;
/**
*
*/
@Column(name = "gmt_create")
@CreatedDate
private Date gmtCreate;
/**
*
*/
@Column(name = "gmt_modified")
@LastModifiedDate
private Date gmtModified;
/**
*
*/
@Column(name = "act_name")
private String actName;
/**
*
*/
@Column(name = "act_table_name")
private String actTableName;
/**
*
*/
@Column(name = "columns_rule")
private String columnsRule;
}

@ -0,0 +1,29 @@
package com.yuyou.openapi.openapi.model.dto;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
@Data
public class FormMessageDTO {
/**
* ID
*/
private String appId;
/**
*
*/
private Long timestamp;
/**
*
*/
private JSONObject tag;
/**
*
*/
private JSONObject data;
}

@ -0,0 +1,51 @@
package com.yuyou.openapi.openapi.model.param;
import lombok.Data;
import java.util.List;
/**
*
*/
@Data
public class FormQueryParam {
/**
*
*/
private String tableName;
/**
* uid
*/
private String uid;
/**
* ID
*/
private Long recId;
/**
* ID
*/
private String appId;
/**
*
*/
private List<Integer> stuSubjects;
/**
*
*/
private List<Integer> stuGrades;
private Integer gradeStart;
private Integer gradeEnd;
/**
*
*/
private String pushTimeStart;
private String pushTimeEnd;
}

@ -0,0 +1,21 @@
package com.yuyou.openapi.openapi.model.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
*
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class FormClientMessageVO extends ABClientBaseVO implements Serializable {
/**
*
*/
@JsonProperty(value = "calllog")
private String callLog;
}

@ -0,0 +1,18 @@
package com.yuyou.openapi.openapi.service;
import com.yuyou.openapi.openapi.model.dto.FormMessageDTO;
import org.springframework.validation.annotation.Validated;
/**
*
*/
@Validated
public interface FormMessageService {
/**
*
* @param actName
* @param formMessageDTO
*/
boolean recordFormMessage(String actName, FormMessageDTO formMessageDTO);
}

@ -0,0 +1,211 @@
package com.yuyou.openapi.openapi.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yuyou.openapi.openapi.dao.FormActInfoRepository;
import com.yuyou.openapi.openapi.exception.BaiyeException;
import com.yuyou.openapi.openapi.exception.CommonErrorCode;
import com.yuyou.openapi.openapi.model.dataobject.FormActInfo;
import com.yuyou.openapi.openapi.model.dto.FormMessageDTO;
import com.yuyou.openapi.openapi.service.FormMessageService;
import com.yuyou.openapi.openapi.utils.ConvertHelp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.math.BigInteger;
import java.util.*;
@Service
@Slf4j
public class FormMessageServiceImpl implements FormMessageService {
/**
*
*/
private static final String GMT_CREATE_COLUMN = "gmt_create";
private static final String GMT_MODIFIED_COLUMN = "gmt_modified";
private static final String RECID_COLUMN = "rec_id";
private static final String APPID_COLUMN = "app_id";
private static final String PUSHTIME_COLUMN = "push_time";
@PersistenceContext
private EntityManager entityManager;
@Autowired
private FormActInfoRepository formActInfoRepository;
@Override
@Modifying
@Transactional
public boolean recordFormMessage(String actName, FormMessageDTO formMessageDTO) {
if (StringUtils.isEmpty(actName) || Objects.isNull(formMessageDTO)) {
log.error("actName or formMessageDTO can not be null.");
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
if (Objects.isNull(formMessageDTO.getAppId()) || Objects.isNull(formMessageDTO.getTag()) || Objects.isNull(formMessageDTO.getTimestamp())) {
throw new BaiyeException(CommonErrorCode.DATA_NOT_EXIT, "appId/tag/timestamp can not be null");
}
// 获取业务对应的表单结构
FormActInfo formActInfo = formActInfoRepository.findFirstByActName(actName);
if (Objects.isNull(formActInfo)) {
log.error("no act info match with actName: " + actName);
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
// 表单参数校验
if (StringUtils.isEmpty(formActInfo.getActTableName())) {
log.error("act tableName is Empty, actName" + actName);
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
JSONObject columnsRule = JSON.parseObject(formActInfo.getColumnsRule());
if (Objects.isNull(columnsRule)) {
log.error("columnsRule is illegal, actName: " + actName);
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
Long recId = Long.valueOf(formMessageDTO.getTag().get("tag_key_id").toString());
// 解析入库
Map<String, Object> columnMap = new HashMap<>();
try {
columnMap = ConvertHelp.convertFields(columnsRule, formMessageDTO.getData());
}catch (Exception e) {
log.error("Parse value raise error, err:", e);
}
if (CollectionUtils.isEmpty(columnMap)) {
log.error("Get empty value map, must have some error.");
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
// 添加固定的字段
columnMap.put(RECID_COLUMN, recId);
columnMap.put(APPID_COLUMN, formMessageDTO.getAppId());
columnMap.put(PUSHTIME_COLUMN, new Date(formMessageDTO.getTimestamp()));
// 是否为已成单客户
String pid = String.valueOf(columnMap.get("pnum"));
if (countSubmitRecByPid(formActInfo.getActTableName(), pid) > 0) {
log.info("uid is exist, recId={}", recId);
return true;
}
try {
// 根据推送地址和记录id共同判断是否为重复记录若重复则覆盖更新
if (countExistRec(formActInfo.getActTableName(), recId, formMessageDTO.getAppId()) > 0) {
// 重复则更新
updateMoreFiled(formActInfo.getActTableName(), columnMap, recId, formMessageDTO.getAppId());
} else {
// 新记录直接插入
insert(formActInfo.getActTableName(), columnMap);
}
}catch (Exception e) {
log.error("Insert/Update rec raise error, error is :", e);
throw new BaiyeException(CommonErrorCode.RUNTIME_ERROR);
}
return true;
}
// TODO: 可将以下sql封装为一个EntityManager构建的通用DAO
/**
* mobile
* @param tableName
* @param pid
* @return
*/
private int countSubmitRecByPid(String tableName, String pid) {
String sql = String.format("SELECT COUNT(*) FROM %s WHERE pnum = :pid AND submit_status = 1", tableName);
Query query = entityManager.createNativeQuery(sql);
query.setParameter("pid", pid);
return ((BigInteger) query.getSingleResult()).intValue();
}
/**
*
* @param tableName
* @param recId
* @param appId
* @return
*/
private int countExistRec(String tableName, Long recId, String appId) {
String sql = String.format("SELECT COUNT(*) FROM %s WHERE rec_id = :recId AND app_id = :appId", tableName);
Query query = entityManager.createNativeQuery(sql);
query.setParameter("recId", recId);
query.setParameter("appId", appId);
return ((BigInteger) query.getSingleResult()).intValue();
}
// insert
public int insert(String tableName, Map<String, Object> map) {
int result;
Set<String> set = map.keySet();
List<String> columns = new ArrayList<>(set);
List<Object> values = new ArrayList<>(columns.size());
columns.forEach(each -> values.add(map.get(each)));
// 记录入库创建时间
columns.add(GMT_CREATE_COLUMN);
columns.add(GMT_MODIFIED_COLUMN);
values.add(new Date());
values.add(new Date());
String columnStr = StrUtil.join(", ", columns);
String valueStr = StrUtil.repeat("?, ", values.size());
String insertSql = String.format("INSERT INTO %s(%s) VALUES (%s)",
tableName, columnStr, valueStr.substring(0, valueStr.length() - 2));
log.info("SQL: " + insertSql);
Query query = entityManager.createNativeQuery(insertSql);
for (int i = 0; i < values.size(); i++) {
query.setParameter(i + 1, values.get(i));
}
result = query.executeUpdate();
return result;
}
// update
public Integer updateMoreFiled(String tableName, Map<String, Object> map, Long recId, String appId) {
int result;
StringBuilder sqlSb = new StringBuilder("UPDATE " + tableName + " SET ");
map.put(GMT_MODIFIED_COLUMN, new Date());
Set<String> set = map.keySet();
List<String> updateColumnList = new ArrayList<>(set);
for (int i = 0; i <= updateColumnList.size() - 1 ; i++){
sqlSb.append(updateColumnList.get(i) + "=:" + updateColumnList.get(i) + ", ");
}
String sql = sqlSb.toString().substring(0, sqlSb.toString().length() - 2);
sql += " WHERE rec_id = :recId AND app_id = :appId";
log.info("SQL: " + sql);
Query query = entityManager.createNativeQuery(sql);
for (int i = 0; i <= updateColumnList.size() - 1; i++) {
query.setParameter(updateColumnList.get(i), map.get(updateColumnList.get(i)));
}
query.setParameter("recId", recId);
query.setParameter("appId", appId);
result = query.executeUpdate();
return result;
}
}

@ -0,0 +1,54 @@
package com.yuyou.openapi.openapi.utils;
import com.alibaba.fastjson.JSONObject;
import com.yuyou.openapi.openapi.common.security.SecurityConstants;
import com.yuyou.openapi.openapi.common.security.SecurityService;
import com.yuyou.openapi.openapi.exception.SecretException;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
public final class ConvertHelp implements SecurityConstants {
/**
*
* @param columnRules
* @param filedValues
* @return
* @throws SecretException
*/
public static Map<String, Object> convertFields(JSONObject columnRules, JSONObject filedValues) throws SecretException {
Map<String, Object> resultMap = new HashMap<>(columnRules.size());
for (String column : columnRules.keySet()) {
Object rule = columnRules.get(column);
// 特殊列名在匹配时进行转换
column = StringUtils.isNotEmpty(column) && "pnum" == column ? "mobile" : column;
String value = filedValues.getString(column);
if (rule instanceof Integer) {
Integer tag = (Integer) rule;
switch (tag) {
case PHONE_ENCRYPT_TAG:
String pnum = SecurityService.encrypt(value, SecurityConstants.PHONE);
resultMap.put("pnum", pnum);
break;
case SIMPLE_ENCRYPT_TAG:
String encryptedValue = SecurityService.encrypt(value, SecurityConstants.SIMPLE);
resultMap.put(column, encryptedValue);
break;
default:
resultMap.put(column, value);
break;
}
} else if (rule instanceof JSONObject) {
// 基于规则进行映射, 规则统一有一个"未知"映射
JSONObject map = (JSONObject) rule;
Object mapValue = map.keySet().contains(value) ? map.get(value) : map.get("未知");
resultMap.put(column, mapValue);
} else {
continue;
}
}
return resultMap;
}
}
Loading…
Cancel
Save