master
wujingtao 3 years ago
parent c5ca515e7d
commit 477ca4a773

@ -18,6 +18,17 @@
</properties>
<dependencies>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>2.1.5</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>

@ -0,0 +1,16 @@
package com.baiye.exception;
import com.dangdang.ddframe.job.executor.handler.JobExceptionHandler;
import lombok.extern.slf4j.Slf4j;
/**
* @author wjt
* @date 2021/12/15
*/
@Slf4j
public class ElasticException implements JobExceptionHandler {
@Override
public void handleException(String s, Throwable throwable) {
log.info("elastic-job 捕获全局异常,任务名:{},异常原因:{}", s, throwable.getMessage());
}
}

@ -24,7 +24,12 @@ spring:
- Path=/api-source/**
filters:
- StripPrefix=1
- id: platform-task
uri: lb://ad-platform-task
predicates:
- Path=/api-task/**
filters:
- StripPrefix=1
hystrix:
command:
default:

@ -18,6 +18,11 @@
</properties>
<dependencies>
<dependency>
<groupId>com.baiye</groupId>
<artifactId>ad-platform-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>

@ -3,12 +3,11 @@ package com.baiye.model.dto;
import com.baiye.annotation.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.domain.Pageable;
import javax.persistence.Column;
/**
* clue
* @author wjt
*/
@Data
public class ClueQueryCriteria {

@ -0,0 +1,26 @@
package com.baiye.model.entity;
import lombok.Data;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
/**
* @author wjt
* @date 2021/12/14
*/
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Data
public class BaseCallClueInfo {
@Column(name = "team_id")
private Long teamId;
@Column(name = "member_id")
private Long memberId;
@Column(name = "status")
private Integer status;
@Column(name = "task_id")
private Long taskId;
}

@ -0,0 +1,40 @@
package com.baiye.model.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author wjt
* @date 2021/12/10
*/
@Getter
@AllArgsConstructor
public enum CallStatusEnum {
/**
*
*/
CALL(0, "call"),
/**
*
*/
ALERT(1, "alert"),
/**
*
*/
ANSWER(2, "answer"),
/**
*
*/
HANGUP(3, "hangup");
private final int value;
private final String description;
public static CallStatusEnum find(String val) {
for (CallStatusEnum dataScopeEnum : CallStatusEnum.values()) {
if (val.equals(dataScopeEnum.getDescription())) {
return dataScopeEnum;
}
}
return null;
}
}

@ -30,7 +30,6 @@
<artifactId>ad-platform-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.baiye</groupId>
<artifactId>ad-platform-pojo</artifactId>
@ -109,6 +108,10 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
</dependency>
</dependencies>

@ -203,7 +203,7 @@
@Override
public List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts) {
if (deptDto.getPid() == null) {
if (deptDto.getPid() == null || deptDto.getPid() == DefaultNumberConstants.ZERO_NUMBER) {
depts.addAll(deptRepository.findByPidIsNull());
return deptMapper.toDto(depts);
}

@ -16,9 +16,7 @@
package com.baiye.modules.system.service.mapstruct;
import com.baiye.model.base.BaseMapper;
import com.baiye.modules.system.domain.Dept;
import com.baiye.modules.system.domain.Task;
import com.baiye.modules.system.service.dto.DeptDto;
import com.baiye.modules.system.service.dto.TaskDto;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;

@ -0,0 +1,84 @@
package com.baiye.modules.telemarkting.api;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baiye.http.CommonResponse;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackStatusDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallReqDTO;
import com.baiye.modules.telemarkting.service.DoubleCallService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* @author wjt
* @date 2021/12/14
*/
@Slf4j
@RestController
@RequestMapping("/api")
@Api(tags = "对接双呼")
public class DoubleCallController {
@Resource
private DoubleCallService doubleCallService;
@PostMapping("/double/req")
@ApiOperation("请求接入双呼")
public CommonResponse<Object> doubleCallReq(@RequestBody DoubleCallReqDTO doubleCallReq) {
if (ObjectUtil.isEmpty(doubleCallReq)) {
return CommonResponse.createByError();
}
return doubleCallService.doubleCallReq(doubleCallReq);
}
@PostMapping("/back/cdrUrl")
@ApiOperation("双呼系统回调话单")
public CommonResponse<String> doubleCallBack(@RequestBody String json) {
try {
DoubleCallBackDTO doubleCallReq = JSONUtil.toBean(json, DoubleCallBackDTO.class);
if (ObjectUtil.isEmpty(doubleCallReq) || StrUtil.isEmpty(doubleCallReq.getSessionId())) {
return CommonResponse.createByErrorMessage("参数为空");
}
log.info("=======双呼回调: {}", doubleCallReq);
doubleCallService.doubleCallBack(doubleCallReq);
} catch (Exception e) {
log.error("双呼回调话单错误 参数 {}", json);
log.error("双呼回调话单错误,数据解析错误 {}", e.getMessage());
return CommonResponse.createByError();
}
return CommonResponse.createBySuccess();
}
@PostMapping("/back/status")
@ApiOperation("双呼系统回调状态")
public CommonResponse<String> doubleCallBackStatus(@RequestBody String json) {
try {
DoubleCallBackStatusDTO doubleCallBack = JSONUtil.toBean(json, DoubleCallBackStatusDTO.class);
if (ObjectUtil.isEmpty(doubleCallBack) || StrUtil.isEmpty(doubleCallBack.getSessionId())) {
return CommonResponse.createByErrorMessage("参数为空");
}
log.info("解析状态后的对象 {}", doubleCallBack);
doubleCallService.doubleCallBackStatus(doubleCallBack);
} catch (Exception e) {
log.error("双呼回调状态错误 参数 {}", json);
log.error("双呼回调状态错误,数据解析错误 {}", e.getMessage());
return CommonResponse.createByError();
}
return CommonResponse.createBySuccess();
}
@GetMapping("/double/stop")
@ApiOperation("挂断呼叫")
public CommonResponse<Object> doubleCallStop(String sessionId) {
if (StrUtil.isEmpty(sessionId)) {
return CommonResponse.createByErrorMessage("SESSION_ID不存在");
}
return doubleCallService.doubleCallStop(sessionId);
}
}

@ -0,0 +1,33 @@
package com.baiye.modules.telemarkting.dao;
import com.baiye.modules.telemarkting.entity.CallClueInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author wjt
* @date 2021/12/13
*/
@Repository
public interface CallClueRepository extends JpaRepository<CallClueInfo, Long>, JpaSpecificationExecutor<CallClueInfo> {
/**
*
*
* @param id
* @return
*/
CallClueInfo findByClueId(Long id);
/**
*
*
* @param memberId
* @return
*/
@Query("select d from CallClueInfo d where d.memberId=?1 ")
List<CallClueInfo> selectByMember(Long memberId);
}

@ -0,0 +1,33 @@
package com.baiye.modules.telemarkting.dao;
import com.baiye.modules.telemarkting.entity.DoubleCallInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author wjt
* @date 2021/12/06
*/
@Repository
public interface DoubleCallRepository extends JpaRepository<DoubleCallInfo, Long>, JpaSpecificationExecutor<DoubleCallInfo> {
/**
* id
*
* @param id
* @return
*/
DoubleCallInfo findById(String id);
/**
*
*
* @param memberId
* @return
*/
@Query("select d from DoubleCallInfo d where d.memberId=?1 ")
List<DoubleCallInfo> selectByMemberAndStatus(Long memberId);
}

@ -0,0 +1,33 @@
package com.baiye.modules.telemarkting.entity;
import cn.hutool.core.date.DatePattern;
import com.baiye.model.entity.BaseCallClueInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* @author wjt
* @date 2021/12/13
* 线
*/
@Data
@Entity
@Table(name = "tb_call_clue")
@EntityListeners(AuditingEntityListener.class)
public class CallClueInfo extends BaseCallClueInfo implements Serializable {
private static final long serialVersionUID = -2063303635710762496L;
@Id
@Column(name = "clue_id")
private Long clueId;
@LastModifiedDate
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
@Column(name = "create_time")
private Date createTime;
}

@ -0,0 +1,107 @@
package com.baiye.modules.telemarkting.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* @author wjt
* @date 2021/12/06
*/
@Data
@Entity
@Table(name = "tb_double_call")
@EntityListeners(AuditingEntityListener.class)
public class DoubleCallInfo implements Serializable {
private static final long serialVersionUID = -1452118686043669994L;
@Id
@Column(name = "id")
@ApiModelProperty(value = "id双呼请求/回调的sessionId")
private String id;
@Column(name = "request_id")
@ApiModelProperty(value = "请求的唯一id")
private String requestId;
@Column(name = "clue_id")
@ApiModelProperty(value = "线索id")
private String clueId;
@Column(name = "member_id")
@ApiModelProperty(value = "所属人id")
private Long memberId;
@LastModifiedDate
@Column(name = "create_time")
@ApiModelProperty(value = "创建时间")
private Date createTime;
@Column(name = "direction")
@ApiModelProperty(value = "通话的呼叫方向")
private Integer direction;
@Column(name = "sp_id")
@ApiModelProperty(value = "客户的云服务账号")
private String spId;
@Column(name = "app_key")
@ApiModelProperty(value = "隐私保护通话应用的 app_key")
private String appKey;
@Column(name = "icid")
@ApiModelProperty(value = "呼叫记录的唯一标识")
private String icid;
@Column(name = "bind_num")
@ApiModelProperty(value = "隐私保护号码")
private String bindNum;
@Column(name = "caller_num")
@ApiModelProperty(value = "主叫号码")
private String callerNum;
@Column(name = "callee_num")
@ApiModelProperty(value = "被叫号码")
private String calleeNum;
@Column(name = "fwd_display_num")
@ApiModelProperty(value = "转接呼叫时的显示号")
private String fwdDisplayNum;
@Column(name = "fwd_dst_num")
@ApiModelProperty(value = "转接呼叫时的转接号码")
private String fwdDstNum;
@Column(name = "fwd_start_time")
@ApiModelProperty(value = "被叫呼叫操作的开始时间")
private String fwdStartTime;
@Column(name = "call_end_time")
@ApiModelProperty(value = "呼叫结束时间")
private String callEndTime;
@Column(name = "call_out_start_time")
@ApiModelProperty(value = "主叫呼叫开始时间")
private String callOutStartTime;
@Column(name = "call_out_answer_time")
@ApiModelProperty(value = "主叫呼叫应答时间")
private String callOutAnswerTime;
@Column(name = "duration")
@ApiModelProperty(value = "通话时长")
private Integer duration;
@Column(name = "record_flag")
@ApiModelProperty(value = "该字段用于录音标识 0未有 1有")
private Integer recordFlag;
@Column(name = "record_file_download_url")
@ApiModelProperty(value = "录音下载地址")
private String recordFileDownloadUrl;
@Column(name = "binding_id")
@ApiModelProperty(value = "绑定 id同绑定请求中的 bindingId")
private String bindingId;
}

@ -0,0 +1,47 @@
package com.baiye.modules.telemarkting.entity.dto;
import lombok.Data;
/**
* @author wjt
* @date 2021/12/02
*
*/
@Data
public class DoubleCallBackDTO {
private Integer direction;
private String spId;
private String appKey;
private String icid;
private String bindNum;
private String sessionId;
private String callerNum;
private String calleeNum;
private String fwdDisplayNum;
private String fwdDstNum;
private String fwdStartTime;
private String fwdAlertingTime;
private String fwdAnswerTime;
private String callEndTime;
private Integer fwdUnaswRsn;
private Integer ulFailReason;
private Integer sipStatusCode;
private String callOutStartTime;
private String callOutAlertingTime;
private String callOutAnswerTime;
private Integer callOutUnaswRsn;
private Integer duration;
private Integer fee_duration;
private String price;
private String fee;
private Integer recordFlag;
private Integer recordStartTime;
private Integer ttsPlayTimes;
private String ttsTransDuration;
private String serviceType;
private String hostName;
private String userData;
private String recordFileDownloadUrl;
private String bindingId;
}

@ -0,0 +1,16 @@
package com.baiye.modules.telemarkting.entity.dto;
import lombok.Data;
/**
* @author wjt
* @date 2021/12/06
*
*/
@Data
public class DoubleCallBackStatusDTO {
private String status;
private String callId;
private String sessionId;
private String userData;
}

@ -0,0 +1,33 @@
package com.baiye.modules.telemarkting.entity.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author wjt
* @date 2021/12/02
*
*/
@Data
public class DoubleCallReqDTO implements Serializable {
private static final long serialVersionUID = 8037829549747968861L;
/**
*
*/
private String telA;
/**
*
*/
private String telB;
private String requestId;
/**
* 线id
*/
private String userData;
private Long teamId;
private Long memberId;
private Long taskId;
}

@ -0,0 +1,19 @@
package com.baiye.modules.telemarkting.entity.dto;
import lombok.Data;
/**
* @author wjt
* @date 2021/12/14
*/
@Data
public class DoubleCallSystemDTO {
private String appid;
private String requestId;
private String telA;
private String telB;
private String companyName;
private String userData;
private String cdrUrl;
private String statusUrl;
}

@ -0,0 +1,98 @@
package com.baiye.modules.telemarkting.httpRequest;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallReqDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallSystemDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author wjt
* @date 2021/12/03
*/
@Slf4j
@Component
public class CallReq {
@Value("${double.call.reqUrl}")
private String reqUrl;
@Value("${double.call.stopUrl}")
private String stopUrl;
@Value("${double.call.appid}")
private String appid;
@Value("${double.call.companyName}")
private String companyName;
@Value("${double.call.cdrUrl}")
private String cdrUrl;
@Value("${double.call.statusUrl}")
private String statusUrl;
public String startReq(DoubleCallReqDTO doubleCallReq) {
log.info("=======================doubleCallReq start in {}", DateUtil.date());
return reqTask(doubleCallReq);
}
private String reqTask(DoubleCallReqDTO doubleCallReq) {
DoubleCallSystemDTO doubleCallSystemDTO = new DoubleCallSystemDTO();
BeanUtil.copyProperties(doubleCallReq, doubleCallSystemDTO);
doubleCallSystemDTO.setAppid(appid);
doubleCallSystemDTO.setCompanyName(companyName);
doubleCallSystemDTO.setCdrUrl(cdrUrl);
doubleCallSystemDTO.setStatusUrl(statusUrl);
int count = 0;
int flag = 3;
log.info("请求对象:{}", JSONUtil.toJsonPrettyStr(doubleCallSystemDTO));
while (count <= flag) {
HttpResponse httpResponse = sendCallReq(JSONUtil.toJsonPrettyStr(doubleCallSystemDTO), reqUrl);
// if (httpResponse.isOk() && httpResponse.body().contains("success")) {
// log.info("请求成功");
// log.info("返回值:{}", httpResponse.body());
// JSONObject result = JSONUtil.parseObj(httpResponse.body());
// return result.get("sessionId").toString();
// } else {
// count++;
// log.error("请求失败,response==={}", httpResponse.body());
// }
return RandomUtil.randomString(6);
}
log.info("=======================doubleCallReq end in {}", DateUtil.date());
return null;
}
public Boolean stopReq(String sessionId) {
log.info("=======================stopReq start in {}", DateUtil.date());
return stopTask(sessionId);
}
private Boolean stopTask(String sessionId) {
JSONObject jsonObject = new JSONObject();
jsonObject.putOpt("sessionId", sessionId);
jsonObject.putOpt("callId", "");
int count = 0;
int flag = 3;
while (count <= flag) {
log.info("请求对象:{}", jsonObject);
HttpResponse httpResponse = sendCallReq(jsonObject.toString(), stopUrl);
if (httpResponse.isOk()) {
log.info("请求成功");log.info("返回值:{}", httpResponse.body());
return Boolean.TRUE;
} else {
count++;
log.error("请求失败,response==={}", httpResponse.body());
}
}
log.info("=======================stopReq end in {}", DateUtil.date());
return Boolean.FALSE;
}
private HttpResponse sendCallReq(String json, String url) {
return HttpRequest.post(url).body(json).execute();
}
}

@ -0,0 +1,42 @@
package com.baiye.modules.telemarkting.service;
import com.baiye.http.CommonResponse;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackStatusDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallReqDTO;
/**
* @author wjt
* @date 2021/12/14
*/
public interface DoubleCallService {
/**
*
*
* @param doubleCallReq
* @return
*/
CommonResponse<Object> doubleCallReq(DoubleCallReqDTO doubleCallReq);
/**
*
*
* @param doubleCallBack
*/
void doubleCallBack(DoubleCallBackDTO doubleCallBack);
/**
*
*
* @param doubleCallBackStatus
*/
void doubleCallBackStatus(DoubleCallBackStatusDTO doubleCallBackStatus);
/**
*
*
* @param sessionId
* @return
*/
CommonResponse<Object> doubleCallStop(String sessionId);
}

@ -0,0 +1,96 @@
package com.baiye.modules.telemarkting.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baiye.http.CommonResponse;
import com.baiye.model.enums.CallStatusEnum;
import com.baiye.modules.telemarkting.dao.CallClueRepository;
import com.baiye.modules.telemarkting.dao.DoubleCallRepository;
import com.baiye.modules.telemarkting.entity.CallClueInfo;
import com.baiye.modules.telemarkting.entity.DoubleCallInfo;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallBackStatusDTO;
import com.baiye.modules.telemarkting.entity.dto.DoubleCallReqDTO;
import com.baiye.modules.telemarkting.httpRequest.CallReq;
import com.baiye.modules.telemarkting.service.DoubleCallService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Objects;
/**
* @author wjt
* @date 2021/12/14
*/
@Service
@Slf4j
public class DoubleCallServiceImpl implements DoubleCallService {
@Resource
private CallReq callReq;
@Resource
private DoubleCallRepository doubleCallRepository;
@Resource
private CallClueRepository callClueRepository;
@Override
public CommonResponse<Object> doubleCallReq(DoubleCallReqDTO doubleCallReq) {
String requestId = RandomUtil.randomString(10);
doubleCallReq.setRequestId(requestId);
String sessionId = callReq.startReq(doubleCallReq);
if (StrUtil.isNotBlank(sessionId)) {
DoubleCallInfo doubleCallInfo = new DoubleCallInfo();
doubleCallInfo.setId(sessionId);
doubleCallInfo.setRequestId(requestId);
doubleCallInfo.setClueId(doubleCallReq.getUserData());
doubleCallInfo.setMemberId(doubleCallReq.getMemberId());
CallClueInfo clueInfo = new CallClueInfo();
clueInfo.setClueId(Long.parseLong(doubleCallReq.getUserData()));
clueInfo.setTeamId(doubleCallReq.getTeamId());
clueInfo.setMemberId(doubleCallReq.getMemberId());
clueInfo.setStatus(CallStatusEnum.CALL.getValue());
clueInfo.setTaskId(doubleCallReq.getTaskId());
doubleCallRepository.save(doubleCallInfo);
callClueRepository.save(clueInfo);
} else {
return CommonResponse.createByError();
}
return CommonResponse.createBySuccess(sessionId);
}
@Override
public void doubleCallBack(DoubleCallBackDTO doubleCallBack) {
String sessionId = doubleCallBack.getSessionId();
DoubleCallInfo doubleCallInfo = doubleCallRepository.findById(sessionId);
if (ObjectUtil.isNotEmpty(doubleCallInfo)) {
BeanUtil.copyProperties(doubleCallBack, doubleCallInfo);
log.info("===================话单回调信息: {}", doubleCallInfo);
doubleCallRepository.save(doubleCallInfo);
}
log.info("===========回调话单 未查询到会话信息 id:{}", sessionId);
}
@Override
public void doubleCallBackStatus(DoubleCallBackStatusDTO doubleCallBackStatus) {
String sessionId = doubleCallBackStatus.getSessionId();
long userDate = Long.parseLong(doubleCallBackStatus.getUserData());
CallClueInfo clueInfo = callClueRepository.findByClueId(userDate);
if (ObjectUtil.isNotEmpty(clueInfo)) {
clueInfo.setStatus(Objects.requireNonNull(CallStatusEnum.find(doubleCallBackStatus.getStatus())).getValue());
}
log.info("===========回调状态 未查询到会话信息 id:{}", sessionId);
}
@Override
public CommonResponse<Object> doubleCallStop(String sessionId) {
if (callReq.stopReq(sessionId)) {
return CommonResponse.createBySuccess();
}
return CommonResponse.createByError();
}
}

@ -1,5 +1,5 @@
server:
port: 8000
port: 8866
spring:
application:
@ -15,7 +15,9 @@ spring:
repositories:
enabled: false
ribbon:
ReadTimeout: 3000
ConnectTimeout: 3000
#配置 Jpa
jpa:
@ -53,3 +55,12 @@ code:
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKLhn7fPqFSK9z3Ao4yFFisDO8YV1dOn1I3wpwj1IIu3Z7vkaHyynBf7eF8fo86EQRvnJIo3jVO2jUw5Lor2OYcZVK72oxD5LIULVYI/eXJogzd1C+tJ5IHC7dmTJ37qfjP9VV3mDWlsRusdCoVPE2xUI13H4bPOCE4DyyeldXlFAgMBAAECgYBakWx3D5+AyvipPKl0JDhsWFLvVQrdss+M0Uh/wZWEOsoSfvHejI4hA7It6nDyDzYI5uC5fiQ2bSZqQM1xdXIMmq4F0WM2+ni4Q/bYbaLt9UDGs6GXwHcg3gOTBJoSJq0SZxBpflxbfVOj63ITehTl51q0FvaedxWl63hf6bikQQJBANT3s1usMZmubYxQPLrBeK1mcXG1JxwKDK6n7bJnlBeZy1GCUZ7bwBgr32gRvUXtgqrzT3IyZlld5cUScX601TUCQQDDyxVAPExwbpxD0Ao7CZE9LRYC8YaMQ46NENqaIhnmhMa4vqoTky8t2nLZITmk0EqecTBt/Io+37+X/KCHD+XRAkAraGmIb+qUNndhuCEIt9KPFWheEtxr3KiFGPlb+by3qsNEU9mrFYNr6dVZcvQvQp/1lC5HSnqOEJN6va2gc99ZAkEAnYtF+EAMydNXDgHSmZqjMXSb55Zsy2R4ye2r2KZj7Ocd9/4DYGjoZ58FFs3zUjkAMemmLHouy1TDGAsBKGyUYQJBAJ1io1DxuejCE+sN/bu4Y2S7oQ2Mpfjh7jRYGruDzhdqVnnLxf0spaqJZ5HekQz3uMpkQQGkcN1MZZcRpoWJ7XU=
double:
call:
reqUrl: http://ax.hzdaba.cn/callback/Accounts/dbby_hangzhoubaiyehl/Hw/CallBack
appid: app1
companyName: 杭州百业互联科技有限公司
cdrUrl: http://118.178.137.129:8866/call/back/cdrUrl
statusUrl: http://118.178.137.129:8866/call/back/status
stopUrl: http://ax.hzdaba.cn/callback/Accounts/dbby_hangzhoubaiyehl/Hw/CallBackStop

@ -30,5 +30,79 @@
<artifactId>ad-platform-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.dangdang</groupId>-->
<!-- <artifactId>elastic-job-lite-core</artifactId>-->
<!-- <version>2.1.5</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>guava</artifactId>-->
<!-- <groupId>com.google.guava</groupId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.3.2.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.12.0</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
</dependency>
<!--注册中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--feign 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring boot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
</project>

@ -1,7 +1,11 @@
package com.baiye;
import com.spring4all.swagger.EnableSwagger2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
/**
* 广
@ -9,6 +13,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author q
* @date 2021/11/11
*/
@EnableSwagger2Doc
@EnableJpaAuditing
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class AdPlatformTaskApplication {

@ -0,0 +1,111 @@
package com.baiye.api;
import com.baiye.entity.Job;
import com.baiye.entity.JobBriefInfo;
import com.baiye.service.ElasticJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author wjt
* @date 2021/11/26
*/
@Slf4j
@RestController
@RequestMapping("/api/job")
public class ElasticJobController {
@Resource
private ElasticJobService jobService;
/**
*
*
* @param job
*/
@PostMapping("/add")
public void addJob(@RequestBody Job job) {
log.info("++++++++++++++++++++++++++++++++++++++++++++++++注册定时任务:{}", job.toString());
jobService.addJob(job);
}
/**
*
*
* @param jobName
*/
@GetMapping("/remove")
public void remove(String jobName) {
log.info("=+++++++++++++++++++++++++++++++++++++++++++++++删除定时任务:{}", jobName);
jobService.removeJob(jobName);
}
/**
*
*
* @param jobName
* @return
*/
@GetMapping("/info")
public Job getJobDetails(String jobName) {
return jobService.getJobDetail(jobName);
}
/**
*
*
* @return
*/
@GetMapping("/all")
public List<JobBriefInfo> getAllJobsDetails() {
return jobService.getAllJobsDetails();
}
@PostMapping("/update")
public void updateJob(@RequestBody Job job) {
log.info("++++++++++++++++++++++++++++++++++++++++++++++++修改任务:{}", job.toString());
jobService.updateJob(job);
}
/**
*
*
* @param jobName
*/
@GetMapping("/trigger")
public void trigger(String jobName) {
jobService.trigger(jobName);
}
/**
*
*
* @param jobName
*/
@GetMapping("/disable")
public void disable(String jobName) {
jobService.disable(jobName);
}
/**
*
*
* @param jobName
*/
@GetMapping("/enable")
public void enable(String jobName) {
jobService.enable(jobName);
}
/**
*
*
* @param jobName
*/
@GetMapping("/shutdown")
public void shutdown(String jobName) {
jobService.shutdown(jobName);
}
}

@ -0,0 +1,35 @@
package com.baiye.api;
import com.baiye.entity.vo.MemberInfoVO;
import com.baiye.http.CommonResponse;
import com.baiye.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author wjt
* @date 2021/12/14
*/
@RestController
@RequestMapping("/api")
@Slf4j
public class ReportController {
@Resource
private ReportService reportService;
@GetMapping("/report/member")
public CommonResponse<Object> getMemberReport(Long memberId) {
MemberInfoVO memberReport = reportService.getMemberReport(memberId);
return CommonResponse.createBySuccess(memberReport);
}
@GetMapping("/report/manager")
public CommonResponse<Object> getReportHour() {
reportService.reportHour();
return CommonResponse.createBySuccess();
}
}

@ -0,0 +1,40 @@
package com.baiye.config;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* @author wjt
*/
@Configuration
@EnableConfigurationProperties(ZookeeperProperties.class)
public class JobParserAutoConfiguration {
@Resource
private ZookeeperProperties zookeeperProperties;
/**
* Zookeeper
*
* @return
*/
@Bean(initMethod = "init")
public ZookeeperRegistryCenter zookeeperRegistryCenter() {
ZookeeperConfiguration zkConfig = new ZookeeperConfiguration(zookeeperProperties.getServerLists(),
zookeeperProperties.getNamespace());
zkConfig.setBaseSleepTimeMilliseconds(zookeeperProperties.getBaseSleepTimeMilliseconds());
zkConfig.setConnectionTimeoutMilliseconds(zookeeperProperties.getConnectionTimeoutMilliseconds());
zkConfig.setDigest(zookeeperProperties.getDigest());
zkConfig.setMaxRetries(zookeeperProperties.getMaxRetries());
zkConfig.setMaxSleepTimeMilliseconds(zookeeperProperties.getMaxSleepTimeMilliseconds());
zkConfig.setSessionTimeoutMilliseconds(zookeeperProperties.getSessionTimeoutMilliseconds());
return new ZookeeperRegistryCenter(zkConfig);
}
}

@ -0,0 +1,131 @@
package com.baiye.config;
import com.baiye.entity.jobInstance.ElasticSimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobTypeConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.executor.handler.JobProperties;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Map;
/**
* @author wjt
* @date 2021/12/15
*/
@Configuration
@ConditionalOnBean(CoordinatorRegistryCenter.class)
@AutoConfigureAfter(JobParserAutoConfiguration.class)
public class SimpleJobAutoConfig implements ApplicationContextAware {
private Environment environment;
private final String prefix = "elastic.job.";
@Resource
private CoordinatorRegistryCenter center;
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
environment = ctx.getEnvironment();
Map<String, Object> beanMap = ctx.getBeansWithAnnotation(ElasticSimpleJob.class);
for (Object bean : beanMap.values()) {
Class<?> cls = bean.getClass();
String jobTypeName = cls.getInterfaces()[0].getSimpleName();
if ("SimpleJob".equals(jobTypeName)) {
ElasticSimpleJob annotation = AnnotationUtils.findAnnotation(cls, ElasticSimpleJob.class);
String jobClass = cls.getName();
String jobName = annotation.jobName();
String cron = getEnvironmentStringValue(jobName, "cron", annotation.cron());
int shardingTotalCount = getEnvironmentIntValue(jobName, "shardingTotalCount", annotation.shardingTotalCount());
String shardingItemParameters = getEnvironmentStringValue(jobName, "shardingItemParameters", annotation.shardingItemParameters());
String jobParameter = getEnvironmentStringValue(jobName, "jobParameter", annotation.jobParameter());
boolean monitorExecution = getEnvironmentBooleanValue(jobName, "monitorExecution", annotation.monitorExecution());
int maxTimeDiffSeconds = getEnvironmentIntValue(jobName, "maxTimeDiffSeconds", annotation.maxTimeDiffSeconds());
int monitorPort = getEnvironmentIntValue(jobName, "monitorPort", annotation.monitorPort());
boolean failover = getEnvironmentBooleanValue(jobName, "failover", annotation.failover());
boolean misfire = getEnvironmentBooleanValue(jobName, "misfire", annotation.misfire());
String jobShardingStrategyClass = getEnvironmentStringValue(jobName, "jobShardingStrategyClass", annotation.jobShardingStrategyClass());
String description = getEnvironmentStringValue(jobName, "description", annotation.description());
int reconcileIntervalMinutes = getEnvironmentIntValue(jobName, "reconcileIntervalMinutes", annotation.reconcileIntervalMinutes());
String jobExceptionHandler = getEnvironmentStringValue(jobName, "jobExceptionHandler", annotation.jobExceptionHandler());
String executorServiceHandler = getEnvironmentStringValue(jobName, "executorServiceHandler", annotation.executorServiceHandler());
boolean overwrite = getEnvironmentBooleanValue(jobName, "overwrite", annotation.overwrite());
// 核心配置
JobCoreConfiguration coreConfig =
JobCoreConfiguration.newBuilder(jobName, cron, shardingTotalCount)
.shardingItemParameters(shardingItemParameters)
.description(description)
.failover(failover)
.jobParameter(jobParameter)
.misfire(misfire)
.jobProperties(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), jobExceptionHandler)
.jobProperties(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER.getKey(), executorServiceHandler)
.build();
JobTypeConfiguration typeConfig = new SimpleJobConfiguration(coreConfig, jobClass);
LiteJobConfiguration jobConfig = LiteJobConfiguration.newBuilder(typeConfig)
.overwrite(overwrite)
.monitorPort(monitorPort)
.monitorExecution(monitorExecution)
.maxTimeDiffSeconds(maxTimeDiffSeconds)
.jobShardingStrategyClass(jobShardingStrategyClass)
.reconcileIntervalMinutes(reconcileIntervalMinutes)
.build();
new JobScheduler(center, jobConfig).init();
}
}
}
/**
* environment
*
* @param jobName
* @param fieldName
* @param defaultValue
* @return
*/
private String getEnvironmentStringValue(String jobName, String fieldName, String defaultValue) {
String key = prefix + jobName + "." + fieldName;
String value = environment.getProperty(key);
if (StringUtils.hasText(value)) {
return value;
}
return defaultValue;
}
private int getEnvironmentIntValue(String jobName, String fieldName, int defaultValue) {
String key = prefix + jobName + "." + fieldName;
String value = environment.getProperty(key);
if (StringUtils.hasText(value)) {
return Integer.parseInt(value);
}
return defaultValue;
}
private long getEnvironmentLongValue(String jobName, String fieldName, long defaultValue) {
String key = prefix + jobName + "." + fieldName;
String value = environment.getProperty(key);
if (StringUtils.hasText(value)) {
return Long.parseLong(value);
}
return defaultValue;
}
private boolean getEnvironmentBooleanValue(String jobName, String fieldName, boolean defaultValue) {
String key = prefix + jobName + "." + fieldName;
String value = environment.getProperty(key);
if (StringUtils.hasText(value)) {
return Boolean.parseBoolean(value);
}
return defaultValue;
}
}

@ -0,0 +1,18 @@
package com.baiye.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author wjt
* @date 2021/12/17
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

@ -0,0 +1,51 @@
package com.baiye.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author wjt
*/
@ConfigurationProperties(prefix = "elastic.job.zk")
@Data
public class ZookeeperProperties {
/**
* Zookeeper. IP. . : host1:2181,host2:2181
*/
private String serverLists;
/**
* .
*/
private String namespace;
/**
* . .
*/
private int baseSleepTimeMilliseconds = 1000;
/**
* . .
*/
private int maxSleepTimeMilliseconds = 3000;
/**
* .
*/
private int maxRetries = 3;
/**
* . .
*/
private int sessionTimeoutMilliseconds;
/**
* . .
*/
private int connectionTimeoutMilliseconds;
/**
* Zookeeper. .
*/
private String digest;
}

@ -0,0 +1,43 @@
package com.baiye.dao;
import com.baiye.entity.CallClueInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author wjt
* @date 2021/12/13
*/
@Repository
public interface CallClueRepository extends JpaRepository<CallClueInfo, Long>, JpaSpecificationExecutor<CallClueInfo> {
/**
*
*
* @param id
* @return
*/
CallClueInfo findByClueId(Long id);
/**
*
*
* @param memberId
* @return
*/
@Query("select d from CallClueInfo d where d.memberId=?1 ")
List<CallClueInfo> selectByMember(Long memberId);
/**
*
*
* @param taskId
* @param day
* @return
*/
@Query("select d from CallClueInfo d where d.taskId=?1 and concat(d.createTime,'') =?2 ")
List<CallClueInfo> selectByCondition(Long taskId, String day);
}

@ -0,0 +1,23 @@
package com.baiye.dao;
import com.baiye.entity.ReportDay;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author wjt
* @date 2021/12/13
*/
@Repository
public interface ReportDayRepository extends JpaRepository<ReportDay, Long>, JpaSpecificationExecutor<ReportDay> {
/**
* id
*
* @param taskId
* @return
*/
List<ReportDay> findAllByTaskId(Long taskId);
}

@ -0,0 +1,33 @@
package com.baiye.entity;
import cn.hutool.core.date.DatePattern;
import com.baiye.model.entity.BaseCallClueInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* @author wjt
* @date 2021/12/13
* 线
*/
@Data
@Entity
@Table(name = "tb_call_clue")
@EntityListeners(AuditingEntityListener.class)
public class CallClueInfo extends BaseCallClueInfo implements Serializable {
private static final long serialVersionUID = -2063303635710762496L;
@Id
@Column(name = "clue_id")
private Long clueId;
@LastModifiedDate
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
@Column(name = "create_time")
private Date createTime;
}

@ -0,0 +1,106 @@
package com.baiye.entity;
import com.dangdang.ddframe.job.executor.handler.JobProperties;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author wjt
* @date 2021/11/26
*/
@Data
public class Job implements Serializable {
private static final long serialVersionUID = -7135891833447229851L;
public Job() {
}
/**
*
*/
@NotNull
private String jobName;
/**
*
*/
private String jobType;
/**
*
*/
@NotNull
private String jobClass;
/**
*
*/
@NotNull
private String cron;
/**
*
*/
private int shardingTotalCount = 1;
/**
* /
* 0
* 0=a,1=b,2=c
*/
private String shardingItemParameters = "";
/**
* ,
*/
private String jobParameter = "";
/**
*
*
*/
private boolean monitorExecution = true;
/**
*
* ,
*/
private boolean streamingProcess = false;
/**
*
* >-1
*/
private int maxTimeDiffSeconds = -1;
/**
*
*/
private int monitorPort = -1;
/**
*
*/
private boolean failover = false;
/**
*
*/
private boolean misfire = false;
/**
* ,使
*/
private String jobShardingStrategyClass = "";
/**
*
*/
private String description = "";
/**
*
*/
private String scriptCommandLine = "";
/**
* 1,
*/
private int reconcileIntervalMinutes = 10;
/**
*
*/
private Map<String, String> jobProperties = new LinkedHashMap(JobProperties.JobPropertiesEnum.values().length, 1.0F);
private Boolean overwrite = true;
}

@ -0,0 +1,48 @@
package com.baiye.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author wjt
* @date 2021/11/30
*/
@Data
public class JobBriefInfo implements Serializable,Comparable<JobBriefInfo> {
private static final long serialVersionUID = -2150981397641113926L;
private String jobName;
private JobStatus status;
private String description;
private String cron;
private int instanceCount;
private int shardingTotalCount;
@Override
public int compareTo(JobBriefInfo o) {
return this.getJobName().compareTo(o.getJobName());
}
public static enum JobStatus {
/**
*
*/
OK,
/**
* 线
*/
CRASHED,
/**
*
*/
DISABLED,
/**
*
*/
SHARDING_FLAG;
private JobStatus() {
}
}
}

@ -0,0 +1,37 @@
package com.baiye.entity;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* @author wjt
* @date 2021/12/09
*/
@Data
@Entity
@Table(name = "tb_report_day")
@EntityListeners(AuditingEntityListener.class)
public class ReportDay implements Serializable {
private static final long serialVersionUID = 4019826389911404260L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String taskName;
private Long memberId;
private Long taskId;
private Integer turnOnNum;
private Double turnOnRate;
private Double usrRate;
private Integer totalNum;
@CreatedDate
@Column(name = "create_time")
private Date createTime;
}

@ -0,0 +1,101 @@
package com.baiye.entity.jobInstance;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wjt
* @date 2021/12/15
*/
@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ElasticSimpleJob {
/**
*
*/
String jobName();
/**
*
*/
String cron() default "";
/**
*
*/
int shardingTotalCount() default 1;
/**
* /
* 0
* 0=a,1=b,2=c
*/
String shardingItemParameters() default "";
/**
* ,
*/
String jobParameter() default "";
/**
*
*
*/
boolean monitorExecution() default true;
/**
*
* >-1
*/
int maxTimeDiffSeconds() default -1;
/**
*
*/
int monitorPort() default -1;
/**
*
*/
boolean failover() default false;
/**
*
*/
boolean misfire() default false;
/**
* ,使
*/
String jobShardingStrategyClass() default "";
/**
*
*/
String description() default "";
/**
* 1,
*/
int reconcileIntervalMinutes() default 10;
/**
*
*/
String jobExceptionHandler() default "com.baiye.exception.ElasticException";
/**
* 线
*
* @return
*/
String executorServiceHandler() default "com.dangdang.ddframe.job.executor.handler.impl.DefaultExecutorServiceHandler";
boolean overwrite() default true;
}

@ -0,0 +1,37 @@
package com.baiye.entity.vo;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author wjt
* @date 2021/12/09
*/
@Data
public class MemberInfoVO {
/**
* id
*/
private Long memberId;
/**
*
*/
private Integer turnOnNum;
/**
*
*/
private Double turnOnRate;
/**
* 使
*/
private Double usrRate;
/**
*
*/
private Integer totalNum;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date date;
}

@ -0,0 +1,17 @@
package com.baiye.entity.vo;
import com.baiye.entity.ReportDay;
import lombok.Data;
import java.util.List;
/**
* @author wjt
* @date 2021/12/13
*/
@Data
public class ReportMessageInfoVO {
private Long sessionId;
private List<ReportDay> list;
}

@ -0,0 +1,24 @@
package com.baiye.feign;
import com.baiye.model.dto.TaskQueryCriteria;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* @author wujingtao
* @date 2021/12/27
*/
@FeignClient(name = "ad-platform-management")
public interface ConnectManageFeign {
String API_PREFIX = "/api";
@ApiOperation("查询任务")
@PostMapping(API_PREFIX + "/task/query")
ResponseEntity<Object> query(@RequestBody TaskQueryCriteria taskQueryCriteria);
}

@ -0,0 +1,17 @@
package com.baiye.feign;
import com.baiye.model.dto.TaskQueryCriteria;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
/**
* @author wujingtao
* @date 2021/12/27
*/
@Component
public class ConnectManageFeignFallBack implements ConnectManageFeign {
@Override
public ResponseEntity<Object> query(TaskQueryCriteria taskQueryCriteria) {
return null;
}
}

@ -0,0 +1,21 @@
package com.baiye.feign;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author wujingtao
* @date 2021/12/23
*/
@FeignClient(name = "ad-platform-source")
public interface ConnectSourceFeign {
@ApiOperation("查询组员资源总数")
@GetMapping("/source/clue/queryMemberNum")
ResponseEntity<Object> queryMemberNum(@RequestParam("memberId") Long memberId);
}

@ -0,0 +1,18 @@
package com.baiye.feign;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
/**
* @author wujingtao
* @date 2021/12/23
*/
@Component
public class ConnectSourceFeignFallBack implements ConnectSourceFeign {
@Override
public ResponseEntity<Object> queryMemberNum(Long memberId) {
return null;
}
}

@ -0,0 +1,38 @@
package com.baiye.job;
import cn.hutool.core.date.DateUtil;
import com.baiye.entity.jobInstance.ElasticSimpleJob;
import com.baiye.service.ReportService;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.naming.Name;
/**
* @author wjt
* @date 2021/12/10
*
*/
@Slf4j
@Component
@ElasticSimpleJob(jobName = "StatisticsHourJob", cron = "0 0 0/1 * * ?", jobExceptionHandler = "com.baiye.exception.ElasticException", overwrite = true)
public class StatisticsHourJob implements SimpleJob {
@Resource
private ReportService reportService;
private static StatisticsHourJob statisticsHourJob;
@PostConstruct
public void init() {
statisticsHourJob = this;
}
@Override
public void execute(ShardingContext shardingContext) {
log.info("每小时调用一次 {} 点", DateUtil.hour(DateUtil.date(), true));
statisticsHourJob.reportService.reportHour();
}
}

@ -0,0 +1,27 @@
package com.baiye.listener;
import com.dangdang.ddframe.job.executor.ShardingContexts;
import com.dangdang.ddframe.job.lite.api.listener.ElasticJobListener;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
/**
* @author wjt
* @date 2021/12/02
*/
@Slf4j
public class JobListener implements ElasticJobListener {
/**
*
*/
@Override
public void beforeJobExecuted(ShardingContexts shardingContexts) {
log.info("我是 : {} 作业, {}开始执行!", shardingContexts.getJobName(), LocalDateTime.now());
}
@Override
public void afterJobExecuted(ShardingContexts shardingContexts) {
log.info("我是 : {} 作业, {}结束执行!", shardingContexts.getJobName(), LocalDateTime.now());
}
}

@ -0,0 +1,77 @@
package com.baiye.service;
import com.baiye.entity.Job;
import com.baiye.entity.JobBriefInfo;
import java.util.List;
/**
* @author wjt
* @date 2021/11/26
*/
public interface ElasticJobService {
/**
* job
*
* @param job
*/
void addJob(Job job);
/**
*
*
* @param jobName
*/
void removeJob(String jobName);
/**
* job
*
* @param jobName
* @return
*/
Job getJobDetail(String jobName);
/**
*
*
* @return
*/
List<JobBriefInfo> getAllJobsDetails();
/**
*
*
* @param job
*/
void updateJob(Job job);
/**
*
*
* @param jobName
*/
void trigger(String jobName);
/**
*
*
* @param jobName
*/
void disable(String jobName);
/**
*
*
* @param jobName
*/
void enable(String jobName);
/**
*
*
* @param jobName
*/
void shutdown(String jobName);
}

@ -0,0 +1,22 @@
package com.baiye.service;
import com.baiye.entity.vo.MemberInfoVO;
/**
* @author wjt
* @date 2021/12/10
*/
public interface ReportService {
/**
*
*/
void reportHour();
/**
*
*
* @param memberId
* @return
*/
MemberInfoVO getMemberReport(Long memberId);
}

@ -0,0 +1,236 @@
package com.baiye.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baiye.entity.Job;
import com.baiye.entity.JobBriefInfo;
import com.baiye.service.ElasticJobService;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.executor.handler.JobProperties;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.internal.config.LiteJobConfigurationGsonFactory;
import com.dangdang.ddframe.job.lite.internal.storage.JobNodePath;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* @author wjt
* @date 2021/11/26
*/
@Slf4j
@Service
public class ElasticJobServiceImpl implements ElasticJobService {
@Resource
private CoordinatorRegistryCenter center;
@Resource
private ZookeeperRegistryCenter zookeeperRegistryCenter;
// @Resource
// private DataSource dataSource;
@Override
public void addJob(Job job) {
boolean overwrite = job.getOverwrite();
String exceptionClass = job.getJobProperties().get("JOB_EXCEPTION_HANDLER");
if (StrUtil.isEmpty(exceptionClass)) {
exceptionClass = "com.baiye.exception.ElasticException";
}
JobCoreConfiguration jcc = JobCoreConfiguration
.newBuilder(job.getJobName(), job.getCron(), job.getShardingTotalCount())
.shardingItemParameters(job.getShardingItemParameters())
.description(job.getDescription())
.failover(job.isFailover())
.jobParameter(job.getJobParameter())
.misfire(job.isMisfire())
.jobProperties(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), exceptionClass)
.jobProperties(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER.getKey(), job.getJobProperties().get("EXECUTOR_SERVICE_HANDLER"))
.build();
SimpleJobConfiguration sjc = new SimpleJobConfiguration(
jcc, job.getJobClass()
);
LiteJobConfiguration ljc = LiteJobConfiguration
.newBuilder(sjc)
.overwrite(overwrite)
.monitorPort(job.getMonitorPort())
.monitorExecution(job.isMonitorExecution())
.maxTimeDiffSeconds(job.getMaxTimeDiffSeconds())
.jobShardingStrategyClass(job.getJobShardingStrategyClass())
.reconcileIntervalMinutes(job.getReconcileIntervalMinutes())
.build();
// 配置数据源
// JobEventConfiguration jec = new JobEventRdbConfiguration(dataSource);
//配置监听
// MyNormalListener myNormalListener = new MyNormalListener();
new JobScheduler(center, ljc).init();
}
@Override
public void removeJob(String jobName) {
try {
CuratorFramework client = zookeeperRegistryCenter.getClient();
client.delete().deletingChildrenIfNeeded().forPath("/" + jobName);
} catch (Exception e) {
log.error("删除任务:{} 错误 {}", jobName, e.getMessage());
}
}
/**
*
*/
@Override
public Job getJobDetail(String jobName) {
Job job = new Job();
try {
JobNodePath jobNodePath = new JobNodePath(jobName);
LiteJobConfiguration liteJobConfig = LiteJobConfigurationGsonFactory.fromJson(center.get(jobNodePath.getConfigNodePath()));
job.setJobType(liteJobConfig.getTypeConfig().getJobType().name());
this.buildSimpleJobSettings(jobName, job, liteJobConfig);
} catch (Exception e) {
log.error("查询job任务{} 错误 {}", jobName, e.getMessage());
return null;
}
return job;
}
/**
*
*/
@Override
public List<JobBriefInfo> getAllJobsDetails() {
List<String> jobNames = zookeeperRegistryCenter.getChildrenKeys("/");
List<JobBriefInfo> result = new ArrayList<>(jobNames.size());
for (String each : jobNames) {
JobBriefInfo jobBriefInfo = this.getJobBriefInfo(each);
if (null != jobBriefInfo) {
result.add(jobBriefInfo);
}
}
Collections.sort(result);
return result;
}
@Override
public void updateJob(Job job) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(job.getJobName()), "jobName can not be empty.");
Preconditions.checkArgument(!Strings.isNullOrEmpty(job.getCron()), "cron can not be empty.");
Preconditions.checkArgument(job.getShardingTotalCount() > 0, "shardingTotalCount should larger than zero.");
JobNodePath jobNodePath = new JobNodePath(job.getJobName());
center.update(jobNodePath.getConfigNodePath(), LiteJobConfigurationGsonFactory.toJsonForObject(job));
}
@Override
public void trigger(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
for (String each : center.getChildrenKeys(jobNodePath.getInstancesNodePath())) {
center.persist(jobNodePath.getInstanceNodePath(each), "TRIGGER");
}
}
@Override
public void disable(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
for (String each : center.getChildrenKeys(jobNodePath.getServerNodePath())) {
center.persist(jobNodePath.getServerNodePath(each), "DISABLED");
}
}
@Override
public void enable(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
for (String each : center.getChildrenKeys(jobNodePath.getServerNodePath())) {
center.persist(jobNodePath.getServerNodePath(each), "");
}
}
@Override
public void shutdown(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
for (String job : center.getChildrenKeys(jobNodePath.getInstancesNodePath())) {
center.remove(jobNodePath.getInstanceNodePath(job));
}
}
private void buildSimpleJobSettings(String jobName, Job job, LiteJobConfiguration liteJobConfig) {
job.setJobName(jobName);
job.setJobType(liteJobConfig.getTypeConfig().getJobType().name());
job.setJobClass(liteJobConfig.getTypeConfig().getJobClass());
job.setShardingTotalCount(liteJobConfig.getTypeConfig().getCoreConfig().getShardingTotalCount());
job.setCron(liteJobConfig.getTypeConfig().getCoreConfig().getCron());
job.setShardingItemParameters(liteJobConfig.getTypeConfig().getCoreConfig().getShardingItemParameters());
job.setJobParameter(liteJobConfig.getTypeConfig().getCoreConfig().getJobParameter());
job.setMonitorExecution(liteJobConfig.isMonitorExecution());
job.setMaxTimeDiffSeconds(liteJobConfig.getMaxTimeDiffSeconds());
job.setMonitorPort(liteJobConfig.getMonitorPort());
job.setFailover(liteJobConfig.getTypeConfig().getCoreConfig().isFailover());
job.setMisfire(liteJobConfig.getTypeConfig().getCoreConfig().isMisfire());
job.setJobShardingStrategyClass(liteJobConfig.getJobShardingStrategyClass());
job.setDescription(liteJobConfig.getTypeConfig().getCoreConfig().getDescription());
job.setReconcileIntervalMinutes(liteJobConfig.getReconcileIntervalMinutes());
job.setOverwrite(liteJobConfig.isOverwrite());
}
private JobBriefInfo getJobBriefInfo(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
JobBriefInfo result = new JobBriefInfo();
result.setJobName(jobName);
String liteJobConfigJson = center.get(jobNodePath.getConfigNodePath());
if (null == liteJobConfigJson) {
return null;
} else {
LiteJobConfiguration liteJobConfig = LiteJobConfigurationGsonFactory.fromJson(liteJobConfigJson);
result.setDescription(liteJobConfig.getTypeConfig().getCoreConfig().getDescription());
result.setCron(liteJobConfig.getTypeConfig().getCoreConfig().getCron());
result.setInstanceCount(center.getChildrenKeys((new JobNodePath(jobName)).getInstancesNodePath()).size());
result.setShardingTotalCount(liteJobConfig.getTypeConfig().getCoreConfig().getShardingTotalCount());
result.setStatus(this.getJobStatus(jobName));
return result;
}
}
private JobBriefInfo.JobStatus getJobStatus(String jobName) {
JobNodePath jobNodePath = new JobNodePath(jobName);
List<String> instances = center.getChildrenKeys(jobNodePath.getInstancesNodePath());
if (instances.isEmpty()) {
return JobBriefInfo.JobStatus.CRASHED;
} else if (this.isAllDisabled(jobNodePath)) {
return JobBriefInfo.JobStatus.DISABLED;
} else {
return this.isHasShardingFlag(jobNodePath, instances) ? JobBriefInfo.JobStatus.SHARDING_FLAG : JobBriefInfo.JobStatus.OK;
}
}
private boolean isAllDisabled(JobNodePath jobNodePath) {
List<String> serversPath = zookeeperRegistryCenter.getChildrenKeys(jobNodePath.getServerNodePath());
int disabledServerCount = 0;
for (String each : serversPath) {
if (JobBriefInfo.JobStatus.DISABLED.name().equals(center.get(jobNodePath.getServerNodePath(each)))) {
++disabledServerCount;
}
}
return disabledServerCount == serversPath.size();
}
private boolean isHasShardingFlag(JobNodePath jobNodePath, List<String> instances) {
Set<String> shardingInstances = new HashSet<>();
for (String each : center.getChildrenKeys(jobNodePath.getShardingNodePath())) {
String instanceId = center.get(jobNodePath.getShardingNodePath(each, "instance"));
if (null != instanceId && !instanceId.isEmpty()) {
shardingInstances.add(instanceId);
}
}
return !instances.containsAll(shardingInstances) || shardingInstances.isEmpty();
}
}

@ -0,0 +1,144 @@
package com.baiye.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baiye.dao.CallClueRepository;
import com.baiye.dao.ReportDayRepository;
import com.baiye.entity.CallClueInfo;
import com.baiye.entity.ReportDay;
import com.baiye.entity.vo.MemberInfoVO;
import com.baiye.entity.vo.ReportMessageInfoVO;
import com.baiye.feign.ConnectManageFeign;
import com.baiye.feign.ConnectSourceFeign;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.model.enums.CallStatusEnum;
import com.baiye.service.ReportService;
import com.baiye.socket.WebSocketServer;
import com.baiye.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author wjt
* @date 2021/12/10
*/
@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
@Resource
private WebSocketServer webSocketServer;
@Resource
private CallClueRepository callClueRepository;
@Resource
private ReportDayRepository reportDayRepository;
@Resource
private ConnectSourceFeign connectSourceFeign;
@Resource
private ConnectManageFeign connectManageFeign;
@Override
public void reportHour() {
TaskQueryCriteria taskQueryCriteria = new TaskQueryCriteria();
taskQueryCriteria.setIsDistribution(1);
ResponseEntity<Object> query = connectManageFeign.query(taskQueryCriteria);
JSONArray array = JSONUtil.parseArray(query.getBody());
//获取当天的信息
String today = DateUtil.today();
for (Object o : array) {
JSONObject jsonObject = (JSONObject) o;
Long id = jsonObject.getLong("id");
int clueTotal = jsonObject.getInt("totalNumber");
String taskName = jsonObject.getStr("taskName");
List<CallClueInfo> list = callClueRepository.selectByCondition(id, today);
if (CollUtil.isEmpty(list)) {
continue;
}
JSONObject json = getMessageInfo(list, clueTotal);
ReportDay reportDay = new ReportDay();
reportDay.setTaskId(id);
reportDay.setTaskName(taskName);
reportDay.setTotalNum(clueTotal);
reportDay.setTurnOnNum(json.getInt("turnOnNum"));
reportDay.setTurnOnRate(json.getDouble("turnOnRate"));
reportDay.setUsrRate(json.getDouble("usrRate"));
reportDay.setCreateTime(DateUtil.date());
List<ReportDay> allByTaskId = reportDayRepository.findAllByTaskId(id);
allByTaskId.add(reportDay);
ReportMessageInfoVO reportMessageInfoVO = new ReportMessageInfoVO();
reportMessageInfoVO.setList(allByTaskId);
log.info("当前用户 {}", SecurityUtils.getCurrentUserId());
reportMessageInfoVO.setSessionId(SecurityUtils.getCurrentUserId());
try {
if (DateUtil.hour(DateUtil.date(), true) == 13) {
//每天23点的统计 保存在数据库
reportDayRepository.save(reportDay);
}
webSocketServer.sendMessage(reportMessageInfoVO);
} catch (Exception e) {
log.error("发生websocket异常 {}", e.getMessage());
}
}
}
@Override
public MemberInfoVO getMemberReport(Long memberId) {
//查询此员工的所有线索
ResponseEntity<Object> objectResponseEntity = connectSourceFeign.queryMemberNum(memberId);
int total = objectResponseEntity.getStatusCodeValue();
MemberInfoVO memberInfoVO = new MemberInfoVO();
memberInfoVO.setMemberId(memberId);
memberInfoVO.setTotalNum(total);
memberInfoVO.setDate(DateUtil.date());
memberInfoVO.setTurnOnNum(0);
memberInfoVO.setTurnOnRate(0.00);
memberInfoVO.setUsrRate(0.00);
if (total == 0) {
return memberInfoVO;
}
List<CallClueInfo> callClueInfos = callClueRepository.selectByMember(memberId);
if (CollUtil.isEmpty(callClueInfos)) {
return memberInfoVO;
}
JSONObject json = getMessageInfo(callClueInfos, total);
memberInfoVO.setTurnOnNum(json.getInt("turnOnNum"));
memberInfoVO.setTurnOnRate(json.getDouble("turnOnRate"));
memberInfoVO.setUsrRate(json.getDouble("usrRate"));
return memberInfoVO;
}
private JSONObject getMessageInfo(List<CallClueInfo> callClueInfos, int total) {
int usrNum = 0;
int turnOnNum = 0;
double turnOnRate = 0.00;
double usrRate = 0.00;
for (CallClueInfo info : callClueInfos) {
if (info.getStatus() != 0) {
usrNum++;
if (info.getStatus() == CallStatusEnum.ANSWER.getValue()) {
turnOnNum++;
}
}
}
//使用率 =使用数/总数
usrRate = NumberUtil.div(usrNum, total, 2);
if (usrNum != 0) {
//接通率=接通数/使用数
turnOnRate = NumberUtil.div(turnOnNum, usrNum, 2);
}
JSONObject json = new JSONObject();
json.putOpt("turnOnNum", turnOnNum);
json.putOpt("turnOnRate", turnOnRate);
json.putOpt("usrRate", usrRate);
return json;
}
}

@ -0,0 +1,155 @@
package com.baiye.socket;
import cn.hutool.json.JSONUtil;
import com.baiye.entity.vo.ReportMessageInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author wjt
* @date 2021/12/13
*/
@Slf4j
@Component
@ServerEndpoint(value = "/task/prosperous/{userId}")
public class WebSocketServer {
private static String user;
@PostConstruct
public void init() {
log.info("websocket 加载");
}
private static final AtomicInteger ONLINE_COUNT = new AtomicInteger(0);
/**
* concurrent线SetSession
*/
// private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();
private static ConcurrentHashMap<String, Session> SESSIONS = new ConcurrentHashMap<String, Session>();
/**
*
*/
@OnOpen
public void onOpen(@PathParam(value = "userId") String userId, Session session) {
SESSIONS.put(userId, session);
user = userId;
// 在线数加1
int cnt = ONLINE_COUNT.incrementAndGet();
log.info("有连接加入,当前连接用户为 {},当前连接数为:{}", userId, cnt);
sendMessage(session, "连接成功");
}
/**
*
*/
@OnClose
public void onClose(Session session) {
if (user != null) {
SESSIONS.remove(user);
int cnt = ONLINE_COUNT.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
}
/**
*
*
* @param message
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("来自客户端的消息:{}", message);
sendMessage(session, "收到消息,消息内容:" + message);
}
/**
*
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{}Session ID {}", error.getMessage(), session.getId());
error.printStackTrace();
}
/**
* session
*
* @param session
* @param message
*/
public static void sendMessage(Session session, String message) {
try {
session.getBasicRemote().sendText(String.format("%s (From ServerSession ID=%s ,userId =%s)", message, session, user));
} catch (IOException e) {
log.error("发送消息出错:{}", e.getMessage());
e.printStackTrace();
}
}
/**
*
*
* @param message
* @throws IOException
*/
public static void broadCastInfo(String message) {
for (String key : SESSIONS.keySet()) {
if (!user.equals(key)) {
sendMessage(SESSIONS.get(key), message);
}
}
}
/**
* Session
*
* @param message
* @param sessionId
* @throws IOException
*/
public static void sendMessage(String message, String sessionId) throws IOException {
Session session = null;
if (SESSIONS.get(sessionId) != null) {
session = SESSIONS.get(sessionId);
}
if (session != null) {
sendMessage(session, message);
} else {
log.warn("没有找到你指定ID的会话{}", sessionId);
}
}
public void sendMessage(ReportMessageInfoVO reportMessageInfoVO) throws IOException {
log.info("发给webSocket信息 {}", reportMessageInfoVO);
Session session = null;
for (String key : SESSIONS.keySet()) {
if (key.equals(String.valueOf(reportMessageInfoVO.getSessionId()))) {
session = SESSIONS.get(key);
break;
}
}
if (session != null) {
session.getBasicRemote().sendText(JSONUtil.toJsonStr(reportMessageInfoVO));
} else {
log.warn("没有找到你指定ID的会话{}", reportMessageInfoVO.getSessionId());
}
}
}

@ -0,0 +1,60 @@
{
"properties": [
{
"name": "elastic.job.zk.serverLists",
"type": "java.lang.String",
"description": "Zoo keeper server list, delimited by ,",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": "localhost:2181"
},
{
"name": "elastic.job.zk.namespace",
"type": "java.lang.String",
"description": "Namespace for the jobs",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": "elastic-job"
},
{
"name": "elastic.job.zk.baseSleepTimeMilliseconds",
"type": "java.lang.Integer",
"description": "等待重试的间隔时间的初始值. 单位毫秒",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": 1000
},
{
"name": "elastic.job.zk.maxSleepTimeMilliseconds",
"type": "java.lang.Integer",
"description": "等待重试的间隔时间的最大值. 单位毫秒",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": 3000
},
{
"name": "elastic.job.zk.maxRetries",
"type": "java.lang.Integer",
"description": "最大重试次数",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": 3000
},
{
"name": "elastic.job.zk.sessionTimeoutMilliseconds",
"type": "java.lang.Integer",
"description": "会话超时时间. 单位毫秒",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": 0
},
{
"name": "elastic.job.zk.connectionTimeoutMilliseconds",
"type": "java.lang.Integer",
"description": "连接超时时间. 单位毫秒",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": 0
},
{
"name": "elastic.job.zk.digest",
"type": "java.lang.String",
"description": "连接Zookeeper的权限令牌. 缺省为不需要权限验证",
"sourceType": "com.baiye.config.ZookeeperProperties",
"defaultValue": null
}
]
}

@ -0,0 +1,133 @@
#配置数据源
spring:
jpa:
show-sql: true
cloud:
nacos:
discovery:
server-addr: ${NACOS_HOST:118.178.137.129}:${NACOS_PORT:8848}
redis:
database: 2
host: 118.178.137.129
timeout: 5000
datasource:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://118.178.137.129:3306/ad-platform?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
username: root
password: root
# url: jdbc:mysql://localhost:3306/ad-platform?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
# username: root
# password: 12345678
# 初始连接数
initial-size: 5
# 最小连接数
min-idle: 15
# 最大连接数
max-active: 30
# 超时时间(以秒数为单位)
remove-abandoned-timeout: 180
# 获取连接超时时间
max-wait: 3000
# 连接有效性检测时间
time-between-eviction-runs-millis: 60000
# 连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
# 连接在池中最大生存的时间
max-evictable-idle-time-millis: 900000
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
test-while-idle: true
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
test-on-borrow: true
# 是否在归还到池中前进行检验
test-on-return: false
# 检测连接是否有效
validation-query: select 1
# 配置监控统计
webStatFilter:
enabled: true
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: false
filter:
stat:
enabled: true
# 记录慢SQL
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# 登录相关配置
login:
# 登录缓存
cache-enable: true
# 是否限制单用户登录
single-login: false
# 验证码
login-code:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
height: 36
# 内容长度
length: 2
# 字体名称,为空则使用默认字体
font-name:
# 字体大小
font-size: 25
#jwt
jwt:
header: Authorization
# 令牌前缀
token-start-with: Bearer
# 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 默认4小时可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000
# 在线用户key
online-key: online-token-
# 验证码
code-key: code-key-
# token 续期检查时间范围默认30分钟单位毫秒在token即将过期的一段时间内用户操作了则给用户的token续期
detect: 1800000
# 续期时间范围默认1小时单位毫秒
renew: 3600000
#是否允许生成代码生产环境设置为false
generator:
enabled: true
#是否开启 swagger-ui
swagger:
enabled: true
# IP 本地解析
ip:
local-parsing: true
# 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/eladmin/file/
avatar: /home/eladmin/avatar/
windows:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5

@ -0,0 +1,24 @@
spring:
profiles:
active: dev
application:
name: @artifactId@
server:
port: 8869
elastic:
job:
zk:
namespace: elastic-job
serverLists: localhost:2181
logging:
config: classpath:logback-spring.xml
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
ribbon:
ReadTimeout: 3000
ConnectTimeout: 3000

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- Log file debug output -->
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!--nacos 心跳 INFO 屏蔽-->
<logger name="com.alibaba.nacos" level="OFF">
<appender-ref ref="error"/>
</logger>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="debug"/>
<appender-ref ref="error"/>
</root>
</configuration>
Loading…
Cancel
Save