提交 e73c5435 authored 作者: 李秋林's avatar 李秋林

初始化代码分支,提交已有代码:java框架、mysql连接、勤策api拉取数据

上级
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
mvnw
mvnw.cmd
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.mvn
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
/logs/**
### VS Code ###
.vscode/
# promotion项目,提供销售服务
## 提供服务
* 销售人员登录
* 销售人员记录售卖信息
* 销售人员处理用户数据
## 目前跑mvp,之后再拆小模块
目前只跑mvp与小迭代,所以代码都放在这个包里,程序跑通之后再进行拆分,所以在写代码时需要注意以下事项
* 业务分离的代码,进行逻辑隔离,便于以后拆分
* 当前项目之后会拆分为promotion子模块,当前pom文件会提升为parent依赖
## 代码提交事项
* 无需提交:本地log文件
* 无需提交:本地application-dev.yml文件
* 无需提交:本地打包target目录
* 需提交:单元测试
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 当前pom依赖在项目进行拆分时,拆到parent项目中,此项目做为promotion业务子模块-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/>
</parent>
<groupId>com.wangxiaolu</groupId>
<artifactId>wangxiaolu-promotion-service</artifactId>
<version>0.0.1</version>
<name>wangxiaolu-promotion-service</name>
<description>promotion-service</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Web 场景启动器) 来为 Web 开发予以支持。spring-boot-starter-web 为我们提供了嵌入的 Servlet 容器以及 SpringMVC 的依赖,并为 Spring MVC 提供了大量自动配置,可以适用于大多数 Web 开发场景。-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.4.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.44</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.wangxiaolu.promotion;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableConfigurationProperties
@EnableAspectJAutoProxy
@SpringBootApplication
public class WangxiaoluPromotionServiceApplication {
public static void main(String[] args) {
SpringApplication.run(WangxiaoluPromotionServiceApplication.class, args);
}
}
package com.wangxiaolu.promotion.config.aspet;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@Component
@Aspect
public class ControllerLogAspect {
/**
* 对controller包中的所有类中的所有public类进行增强
*/
@Pointcut("execution(public * com.wangxiaolu.promotion.controller..*.*(..))")
private void pointcut(){}
@Before("pointcut()")
public void before(JoinPoint joinPoint){
/**
* 此次请求
*/
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = sra.getRequest();
// Signature signature = joinPoint.getSignature();
// String name = signature.getName();
log.info("------------- 开始 -------------");
log.info("请求地址:{}:{}", request.getMethod(), request.getRequestURL().toString());
// log.info("类路径:{};方法名:{}", signature.getDeclaringTypeName(), name);
Object[] args = joinPoint.getArgs();
Object[] arguments = new Object[args.length];
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof ServletRequest
|| args[i] instanceof ServletResponse
|| args[i] instanceof MultipartFile) {
continue;
}
arguments[i] = args[i];
}
String[] excludeProperties = {"password", "file"};
PropertyPreFilters filters = new PropertyPreFilters();
PropertyPreFilters.MySimplePropertyPreFilter excludeFilter = filters.addFilter();
excludeFilter.addExcludes(excludeProperties);
log.info("请求参数: {}", JSONObject.toJSONString(arguments, excludeFilter));
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long millis = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
String[] excludeProperties = {"password", "file"};
PropertyPreFilters filters = new PropertyPreFilters();
PropertyPreFilters.MySimplePropertyPreFilter excludeFilter = filters.addFilter();
excludeFilter.addExcludes(excludeProperties);
log.info("返回结果: {}", JSONObject.toJSONString(result, excludeFilter));
log.info("------------- 结束 耗时:{} ms -------------", System.currentTimeMillis() - millis);
return result;
}
}
package com.wangxiaolu.promotion.config.thread;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* @author : liqiulin
* @date : 2024-03-29 10
* @describe : 线程配置
*/
@EnableAsync
@Configuration
public class AsyncThreadConfig implements AsyncConfigurer {
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心数量,根据cpu确认
//核心线程池数量
executor.setCorePoolSize(corePoolSize);
//最大线程数量
executor.setMaxPoolSize(corePoolSize*5);
//线程池的队列容量
executor.setQueueCapacity(corePoolSize*2);
//线程名称的前缀
executor.setThreadNamePrefix(namePrefix);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
package com.wangxiaolu.promotion.controller.user;
import com.wangxiaolu.promotion.pojo.user.vo.UserLoginParam;
import com.wangxiaolu.promotion.service.user.PromotionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe :用户(销售)登录
*/
@RestController
@RequestMapping("/user/promotion")
public class PromotionLoginController {
@Autowired
PromotionService promotionService;
@PostMapping("/login")
public void login(@Validated @RequestBody UserLoginParam userLoginParam){
promotionService.login(userLoginParam);
}
}
package com.wangxiaolu.promotion.controller.user;
import com.wangxiaolu.promotion.service.user.QinCeDataTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : liqiulin
* @date : 2024-03-29 16
* @describe : 勤策同步数据接口
*/
@RestController
@RequestMapping("/user/qince/task")
public class QinCeDataTaskController {
@Autowired
QinCeDataTaskService qinCeDataTaskService;
/**
* 同步组织架构/部门数据
*/
@GetMapping("/department")
public void departmentTask(){
qinCeDataTaskService.departmentSyncTask();
}
/**
* 同步员工数据
*/
@GetMapping("/employee")
public void employeeTask(){
qinCeDataTaskService.employeeSyncTask();
}
}
package com.wangxiaolu.promotion.domain.user.dao;
import com.alibaba.fastjson.JSONArray;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe :勤策部门数据
*/
public interface QinCeDepartmentDao {
/**
* 勤策部门数据同步
*/
void departmentSyncTask(JSONArray responseDatas);
}
package com.wangxiaolu.promotion.domain.user.dao;
import com.alibaba.fastjson.JSONArray;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe : 勤策人员数据
*/
public interface QinCeEmployeeDao {
/**
* 勤微人员数据同步
*/
void employeeSyncTask(JSONArray responseDatas);
}
package com.wangxiaolu.promotion.domain.user.dao;
/**
* @author : liqiulin
* @date : 2024-03-28 19
* @describe :
*/
public interface UserInfoDao {
Integer findUserByUserName(String name);
}
package com.wangxiaolu.promotion.domain.user.dao.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wangxiaolu.promotion.domain.user.dao.QinCeDepartmentDao;
import com.wangxiaolu.promotion.domain.user.mapper.QinceDepartmentMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeDepartmentDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe :勤策部门
*/
@Slf4j
@Service
public class QinCeDepartmentDaoImpl implements QinCeDepartmentDao {
@Autowired
QinceDepartmentMapper qinceDepartmentMapper;
@Override
public void departmentSyncTask(JSONArray responseDatas) {
log.info("勤策-同步组织架构/部门数据,共「{}」条数据", responseDatas.size());
LambdaQueryWrapper<QinCeDepartmentDO> qw = new LambdaQueryWrapper<>();
for (Object responseData : responseDatas) {
qw.clear();
// 查询当前部门是否存在
QinCeDepartmentDO qcDo = JSONObject.parseObject(JSONObject.toJSONString(responseData), QinCeDepartmentDO.class);
qw.eq(QinCeDepartmentDO::getQcId, qcDo.getQcId());
QinCeDepartmentDO doExist = qinceDepartmentMapper.selectOne(qw);
// 存在则修改,不存在则添加
if (Objects.isNull(doExist)) {
qinceDepartmentMapper.insert(qcDo);
log.info("勤策-{}部门数据未存在,已添加,路径为:{}", qcDo.getOrgName(), qcDo.getFullNames());
} else {
qcDo.setId(doExist.getId());
qinceDepartmentMapper.updateById(qcDo);
log.info("勤策-{}部门数据已存在,现已修改,路径为:{}", qcDo.getOrgName(), qcDo.getFullNames());
}
}
}
}
package com.wangxiaolu.promotion.domain.user.dao.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wangxiaolu.promotion.domain.user.dao.QinCeEmployeeDao;
import com.wangxiaolu.promotion.domain.user.mapper.QinceEmployeeMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeEmployeeDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe :勤策人员数据处理
*/
@Slf4j
@Service
public class QinCeEmployeeDaoImpl implements QinCeEmployeeDao {
@Autowired
QinceEmployeeMapper qinceEmployeeMapper;
@Override
public void employeeSyncTask(JSONArray responseDatas) {
log.info("勤策-同步人员数据,共「{}」条数据", responseDatas.size());
LambdaQueryWrapper<QinCeEmployeeDO> qw = new LambdaQueryWrapper<>();
for (Object responseData : responseDatas) {
qw.clear();
// 查询人员是否存在
QinCeEmployeeDO qcDo = JSONObject.parseObject(JSONObject.toJSONString(responseData), QinCeEmployeeDO.class);
qw.eq(QinCeEmployeeDO::getQcId, qcDo.getQcId());
QinCeEmployeeDO doExist = qinceEmployeeMapper.selectOne(qw);
// 存在则修改,不存在则添加
if (Objects.isNull(doExist)) {
qinceEmployeeMapper.insert(qcDo);
log.info("勤策-[{}]人员数据未存在,已添加,手机号:{}", qcDo.getEmpName(), qcDo.getEmpMobile());
} else {
qcDo.setId(doExist.getId());
qinceEmployeeMapper.updateById(qcDo);
log.info("勤策--[{}]人员数据已存在,现已修改,手机号:{}", qcDo.getEmpName(), qcDo.getEmpMobile());
}
}
}
}
package com.wangxiaolu.promotion.domain.user.dao.impl;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wangxiaolu.promotion.domain.user.dao.UserInfoDao;
import com.wangxiaolu.promotion.domain.user.mapper.UserInfoMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.UserInfoDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author : liqiulin
* @date : 2024-03-28 19
* @describe :
*/
@Service
public class UserInfoDaoImpl implements UserInfoDao {
@Autowired
UserInfoMapper userInfoMapper;
@Override
public Integer findUserByUserName(String name) {
LambdaQueryWrapper queryWrapper = buildQueryList(name);
Integer cout = userInfoMapper.selectCount(queryWrapper);
return cout;
}
private LambdaQueryWrapper buildQueryList(String name){
LambdaQueryWrapper<UserInfoDO> queryWrapper = new LambdaQueryWrapper<>();
if (!StringUtils.isEmpty(name)){
queryWrapper.eq(UserInfoDO::getName,name);
}
return queryWrapper;
}
}
package com.wangxiaolu.promotion.domain.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeDepartmentDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* @author a02200059
* @description 针对表【qince_department(勤策-组织架构)】的数据库操作Mapper
* @createDate 2024-04-01 13:55:24
*/
@Mapper
@Repository
public interface QinceDepartmentMapper extends BaseMapper<QinCeDepartmentDO> {
}
package com.wangxiaolu.promotion.domain.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeEmployeeDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* @author a02200059
* @description 针对表【qince_employee(勤策-人员数据)】的数据库操作Mapper
* @createDate 2024-04-01 15:19:53
* @Entity generator.domain.QinceEmployee
*/
@Mapper
@Repository
public interface QinceEmployeeMapper extends BaseMapper<QinCeEmployeeDO> {
}
package com.wangxiaolu.promotion.domain.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.UserInfoDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* @author a02200059
* @description 针对表【user_info】的数据库操作Mapper
* @createDate 2024-03-28 19:00:09
*/
@Repository
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfoDO> {
}
package com.wangxiaolu.promotion.domain.user.mapper.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author : liqiulin
* @date : 2024-03-29 15
* @describe : 勤策-组织架构-dto
*/
@TableName(value ="qince_department")
@Data
public class QinCeDepartmentDO {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 勤策的部门唯一ID。如果id和org_id同时存在则优先顺序为id、org_id
*/
@JsonProperty("id")
private String qcId;
/**
* 来源于第三方系统的部门唯一ID,对应新增部门 (org_id)字段,只有当数据来源于新增接口时才有值,如果数据从勤策系统中直接创建则该字段值为空。
* 如果id和org_id同时存在则优先顺序为id、org_id
*/
@JsonProperty("org_id")
private String orgId;
/**
* 部门编码,必须唯一
*/
@JsonProperty("org_code")
private String orgCode;
/**
* 部门名称。同一部门下的子部门的名称不能重复
*/
@JsonProperty("org_name")
private String orgName;
/**
* 勤策上级部门唯一ID
*/
@JsonProperty("waiqin365_parent_id")
private String waiqin365ParentId;
/**
* 第三方系统上级部门唯一ID
*/
@JsonProperty("org_parent_id")
private String orgParentId;
/**
* 上级部门编码
*/
@JsonProperty("parent_code")
private String parentCode;
/**
* 上级部门名称
*/
@JsonProperty("parent_name")
private String parentName;
/**
* 勤策部门ID全路径
*/
@JsonProperty("full_ids")
private String fullIds;
/**
* 部门编码全路径
*/
@JsonProperty("full_codes")
private String fullCodes;
/**
* 部门名称全路径
*/
@JsonProperty("full_names")
private String fullNames;
/**
* 排序号,顺序排列
*/
@JsonProperty("org_sequence")
private BigDecimal orgSequence;
/**
* 部门状态。0:删除,1:正常
*/
@JsonProperty("org_status")
private Integer orgStatus;
/**
* 创建时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("create_time")
private Date createTime;
/**
* 修改时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("modify_time")
private Date modifyTime;
}
package com.wangxiaolu.promotion.domain.user.mapper.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @author : liqiulin
* @date : 2024-03-29 16
* @describe :
*/
@TableName(value ="qince_employee")
@Data
public class QinCeEmployeeDO {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 勤策的员工唯一标识
* 对应[QinCeEmployeeDTO.id]
*/
@JsonProperty("id")
private String qcId;
/**
* 来源第三方系统的员工唯一标识
*/
@JsonProperty("emp_id")
private String empId;
/**
* 员工登录帐号
*/
@JsonProperty("emp_code")
private String empCode;
/**
* 姓名
*/
@JsonProperty("emp_name")
private String empName;
/**
* 员工别名
*/
@JsonProperty("alias_name")
private String aliasName;
/**
* 人员编码
*/
@JsonProperty("employee_code")
private String employeeCode;
/**
* 最近登录时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("last_use_time")
private String lastUseTime;
/**
* 员工性别。F:女性,M:男性
*/
@JsonProperty("emp_sex")
private String empSex;
/**
* 员工手机号码
*/
@JsonProperty("emp_mobile")
private String empMobile;
/**
* 员工手机地区码
*/
@JsonProperty("mobile_district_code")
private String mobileDistrictCode;
/**
* 固定电话
*/
@JsonProperty("emp_tel")
private String empTel;
/**
* 生日
*/
@JsonProperty("emp_birthday")
private String empBirthday;
/**
* QQ
*/
@JsonProperty("emp_qq")
private String empQq;
/**
* 微信
*/
@JsonProperty("emp_weixin")
private String empWeixin;
/**
* 身份证号码
*/
@JsonProperty("emp_idcard")
private String empIdcard;
/**
* 邮箱
*/
@JsonProperty("emp_email")
private String empEmail;
/**
* 地址
*/
@JsonProperty("emp_addr")
private String empAddr;
/**
* 来源第三方系统隶属部门
*/
@JsonProperty("emp_org_id")
private String empOrgId;
/**
* 隶属部门编码
*/
@JsonProperty("emp_org_code")
private String empOrgCode;
/**
* 勤策部门唯一标识
* 对应QinCeDepartmentDO.qcId
*/
@JsonProperty("waiqin365_org_id")
private String waiqin365OrgId;
/**
* 来源第三方系统,员工上级唯一标识
*/
@JsonProperty("emp_parent_id")
private String empParentId;
/**
* 员工上级编码
*/
@JsonProperty("parent_code")
private String parentCode;
/**
* 勤策员工上级唯一标识
*/
@JsonProperty("waiqin365_parent_id")
private String waiqin365ParentId;
/**
* 是否机构领导。0:否,1:是,默认值0
*/
@JsonProperty("emp_is_org_learder")
private String empIsOrgLearder;
/**
* 员工账号状态。0:销户,1:正常,2:停用
*/
@JsonProperty("emp_status")
private String empStatus;
/**
* 手机卡绑定。0:不绑定,1:绑定
*/
@JsonProperty("emp_imsi_binding")
private String empImsiBinding;
/**
* 创建时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("create_time")
private String createTime;
/**
* 修改时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("modify_time")
private String modifyTime;
/**
* 勤策经销商唯一标识
*/
@JsonProperty("dealer_id")
private String dealerId;
/**
* 经销商中文名称
*/
@JsonProperty("dealer_name")
private String dealerName;
/**
* 常驻地省信息
*/
@JsonProperty("emp_baseprovince")
private String empBaseprovince;
/**
* 常驻地市信息
*/
@JsonProperty("emp_basecity")
private String empBasecity;
/**
* 勤策职务唯一标识
*/
@JsonProperty("waiqin365_position_id")
private String waiqin365PositionId;
/**
* 职务编码
*/
@JsonProperty("emp_position_code")
private String empPositionCode;
/**
* 职务名称
*/
@JsonProperty("emp_position")
private String empPosition;
/**
* 勤策岗位唯一标识
*/
@JsonProperty("waiqin365_job_id")
private String waiqin365JobId;
/**
* 岗位编码
*/
@JsonProperty("emp_job_code")
private String empJobCode;
/**
* 岗位名称
*/
@JsonProperty("emp_job")
private String empJob;
/**
* 来源企微员工唯一标识。只有企微同步过来的人员该字段才有值
*/
@JsonProperty("emp_wechat_code")
private String empWechatCode;
/**
* 入职时间。格式:yyyy-MM-dd
*/
@JsonProperty("emp_enrollment_time")
private String empEnrollmentTime;
/**
* 离职时间。格式:yyyy-MM-dd
*/
@JsonProperty("emp_resignation_time")
private String empResignationTime;
/**
* 手机认证,0为是,1为否
*/
@JsonProperty("mobile_auth")
private String mobileAuth;
/**
* 头像上传时间。格式:yyyy-MM-dd HH:mm:ss
*/
@JsonProperty("face_time")
private String faceTime;
/**
* 客户端类型。0:标准客户端(APP)、1:定制客户端(APP)、2:微信小程序、3:企业微信
*/
@JsonProperty("terminal_type")
private String terminalType;
/**
* 扩展字段列表
*/
// @JsonProperty("exts")
// private List<ExtsDTO> exts;
// @NoArgsConstructor
// @Data
// public class ExtsDTO {
// /**
// * 扩展字段的字段名称
// */
// @JsonProperty("ext_column")
// private String extColumn;
//
// /**
// * 扩展字段名称
// */
// @JsonProperty("ext_key")
// private String extKey;
//
// /**
// * 扩展字段值
// */
// @JsonProperty("ext_value")
// private String extValue;
// }
}
package com.wangxiaolu.promotion.domain.user.mapper.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
* @TableName user_info
*/
@TableName(value ="user_info")
@Data
public class UserInfoDO implements Serializable {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 手机号
*/
private String phone;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改时间
*/
private Date modifyTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
\ No newline at end of file
package com.wangxiaolu.promotion.exception;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.result.basedata.StatusCode;
import lombok.Getter;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe : response包装R失败
*/
@Getter
public class APIException extends RuntimeException {
private int code;
private String msg;
public APIException(StatusCode statusCode, String message) {
super(message);
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
}
/**
* 默认异常编码
*/
public APIException(String message) {
super(message);
this.code = RCode.API_ERROR.getCode();
this.msg = RCode.API_ERROR.getMsg();
}
}
package com.wangxiaolu.promotion.exception;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.result.basedata.StatusCode;
import lombok.Getter;
/**
* @author : liqiulin
* @date : 2024-03-28 19
* @describe : 参数异常
*/
@Getter
public class ParamException extends RuntimeException{
private int code;
private String msg;
public ParamException(StatusCode statusCode, String message) {
super(message);
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
}
/**
* 默认异常编码
*/
public ParamException(String message) {
super(message);
this.code = RCode.LOGIN_PARAM_ERROR.getCode();
this.msg = RCode.LOGIN_PARAM_ERROR.getMsg();
}
}
package com.wangxiaolu.promotion.pojo.user.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
/**
* @author : liqiulin
* @date : 2024-03-28 18
* @describe : 接收用
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class UserLoginParam {
@NotBlank(message = "登录名不可为空")
String loginName;
String password;
}
package com.wangxiaolu.promotion.result.advice;
import com.wangxiaolu.promotion.exception.APIException;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.result.basedata.R;
import com.wangxiaolu.promotion.result.basedata.RCode;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author : liqiulin
* @date : 2024-03-28 19
* @describe : 统一异常处理
*/
@RestControllerAdvice
public class ControllerExceptionAdvice {
@ExceptionHandler({ParamException.class})
public R ParamExceptionHandler(ParamException e) {
return new R(e.getCode(), e.getMsg(), e.getMessage());
}
@ExceptionHandler({APIException.class})
public R APIExceptionHandler(APIException e) {
return new R(e.getCode(), e.getMsg(), e.getMessage());
}
@ExceptionHandler({MethodArgumentNotValidException.class})
public R MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return new R(RCode.PARAM_ERROR.getCode(), msg);
}
}
package com.wangxiaolu.promotion.result.advice;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wangxiaolu.promotion.exception.APIException;
import com.wangxiaolu.promotion.result.basedata.R;
import com.wangxiaolu.promotion.result.basedata.RCode;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe : 自动封装 R
*/
@RestControllerAdvice(basePackages = {"com.wangxiaolu.promotion.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
// response是R类型或者注释了NotControllerResponseAdvice都不进行包装
return !methodParameter.getParameterType().isAssignableFrom(R.class);
}
@Override
public Object beforeBodyWrite(Object data, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// String类型不能直接包装
if (methodParameter.getGenericParameterType().equals(String.class)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
// 将数据包装在ResultVo里后转换为json串进行返回
return objectMapper.writeValueAsString(new R(data));
} catch (JsonProcessingException e) {
throw new APIException(RCode.RESPONSE_PACK_ERROR, e.getMessage());
}
}
// 包装成R返回
return new R(data);
}
}
package com.wangxiaolu.promotion.result.basedata;
import lombok.Data;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe : 统一响应VO
*/
@Data
public class R {
/**
* 响应码
* 非0失败
*/
private int code;
/**
* 提示信息
*/
private String msg;
/**
* 返回对象
*/
private Object data;
/**
* 默认成功
*/
public R(Object data) {
this.code = RCode.SUCCESS.getCode();
this.msg = RCode.SUCCESS.getMsg();
this.data = data;
}
/**
* 无数据返回
*/
public R(StatusCode statusCode) {
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
this.data = null;
}
/**
* 手动配置code、msg
*/
public R(Integer code, String msg) {
this.code = code;
this.msg = msg;
this.data = null;
}
/**
* 指定状态
*/
public R(StatusCode statusCode, Object data) {
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
this.data = data;
}
/**
* 手动设置
*/
public R(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
package com.wangxiaolu.promotion.result.basedata;
import lombok.Getter;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe : 返回状态编码
*/
@Getter
public enum RCode implements StatusCode {
/**
* 程序统一编码(不分模块)
* 1000+
*/
SUCCESS(0, "请求成功"),
FAILED(1001, "请求失败"),
PARAM_ERROR(1002, "参数错误"),
RESPONSE_PACK_ERROR(1003, "包装R失败"),
/**
* 业务统一编码(不分模块)
* 2000+
*/
API_ERROR(2000, "业务异常"),
/**
* user模块
* 3000+
*/
LOGIN_PARAM_ERROR(3000, "登录信息错误");
;
private int code;
private String msg;
RCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.wangxiaolu.promotion.result.basedata;
/**
* @author : liqiulin
* @date : 2024-03-28 17
* @describe :返回状态编码
*/
public interface StatusCode {
int getCode();
String getMsg();
}
package com.wangxiaolu.promotion.service.user;
import com.wangxiaolu.promotion.pojo.user.vo.UserLoginParam;
/**
* @author : liqiulin
* @date : 2024-03-28 18
* @describe : user模块-promotion逻辑
*/
public interface PromotionService {
/**
* Promotion登录验证
*/
void login(UserLoginParam userLoginParam);
}
package com.wangxiaolu.promotion.service.user;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe : 勤策同步数据服务
*/
public interface QinCeDataTaskService {
void departmentSyncTask();
void employeeSyncTask();
}
package com.wangxiaolu.promotion.service.user.impl;
import com.wangxiaolu.promotion.domain.user.dao.UserInfoDao;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.pojo.user.vo.UserLoginParam;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.user.PromotionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author : liqiulin
* @date : 2024-03-28 18
* @describe : user模块-promotion逻辑
*/
@Slf4j
@Service
public class PromotionServiceImpl implements PromotionService {
@Autowired
UserInfoDao userInfoDao;
/**
* Promotion登录验证
*/
@Override
public void login(UserLoginParam userLoginParam) {
Integer userCount = userInfoDao.findUserByUserName(userLoginParam.getLoginName());
if (1 == userCount){
// 生成登录信息
log.info("生成登录信息:{}",userLoginParam.getLoginName());
return;
}
throw new ParamException(RCode.LOGIN_PARAM_ERROR,null);
}
}
package com.wangxiaolu.promotion.service.user.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wangxiaolu.promotion.domain.user.dao.QinCeDepartmentDao;
import com.wangxiaolu.promotion.domain.user.dao.QinCeEmployeeDao;
import com.wangxiaolu.promotion.service.user.QinCeDataTaskService;
import com.wangxiaolu.promotion.utils.OkHttp;
import com.wangxiaolu.promotion.utils.QinCeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe :
*/
@Slf4j
@Service
public class QinCeDataTaskServiceImpl implements QinCeDataTaskService {
@Autowired
QinCeDepartmentDao qinCeDepartmentDao;
@Autowired
QinCeEmployeeDao qinCeEmployeeDao;
@Autowired
QinCeUtils qinCeUtils;
@Override
public void departmentSyncTask() {
// 查询组织架构参数、创建url
Map<String, Object> params = qinCeUtils.queryOrgParam();
String url = qinCeUtils.builderUrl(QinCeUtils.QUERY_ORGANIZATION,params);
// 发起请求、接收结果
JSONObject resultJson = OkHttp.post(url, params);
JSONArray responseDatas = resultJson.getJSONArray("response_data");
if (responseDatas.size() <= 0) {
log.error("勤策-同步组织架构/部门数据,未查询到数据");
return;
}
qinCeDepartmentDao.departmentSyncTask(responseDatas);
}
@Override
public void employeeSyncTask() {
// 查询组织架构参数、创建url
Map<String, Object> params = qinCeUtils.queryEmployeeParam(false);
String url = qinCeUtils.builderUrl(QinCeUtils.QUERY_EMPLOYEE,params);
// 发起请求、接收结果
JSONObject resultJson = OkHttp.post(url, params);
JSONArray responseDatas = resultJson.getJSONArray("response_data");
if (responseDatas.size() <= 0) {
log.error("勤策-同步人员数据,未查询到数据");
return;
}
qinCeEmployeeDao.employeeSyncTask(responseDatas);
}
}
package com.wangxiaolu.promotion.utils;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.Map;
/**
* @author : liqiulin
* @date : 2024-03-29 13
* @describe : 关于https请求的工具
*/
public class OkHttp {
public static JSONObject post(String url, Map<String, Object> params) {
String requestBody= HttpUtil.createPost(url).contentType("application/json;charset=utf-8").body(JSONObject.toJSONString(params)).execute().body();
JSONObject resultJson = JSONObject.parseObject(requestBody);
String returnCode = resultJson.getString("return_code");
if (!"0".equals(returnCode)){
throw new RuntimeException("OkHttp.post请求error,详情:" + requestBody);
}
return resultJson;
}
}
package com.wangxiaolu.promotion.utils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author : liqiulin
* @date : 2024-03-29 18
* @describe : 勤策 api请求配置
*/
@Component
@Slf4j
public class QinCeUtils {
/**
* =================== 勤策API - config ===================
*/
private static final String OPEN_API = "https://openapi.region2.qince.com";
private static final String OPEN_ID = "8030282350124307682";
private static final String APP_KEY = "Gx0yQw4UhDtNjESmDl";
/**
* =================== 勤策API - path ===================
*/
// 部门、组织架构
public static final String QUERY_ORGANIZATION = "/api/organization/v1/queryOrganization/";
// 员工列表
public static final String QUERY_EMPLOYEE = "/api/employee/v3/queryEmployee/";
public String builderUrl(String sidepath, Map<String, Object> params) {
String msgId = UUID.randomUUID().toString();
Long currentTimeMillis = System.currentTimeMillis();
String digest = getDigest(params, currentTimeMillis);
StringBuilder builder = new StringBuilder().append(OPEN_API).append(sidepath).append(OPEN_ID).append("/").append(currentTimeMillis).append("/").append(digest).append("/").append(msgId);
return builder.toString();
}
/**
* 查询部门参数
*/
public Map<String, Object> queryOrgParam() {
Map<String, Object> params = new HashMap<>();
params.put("id", "");
params.put("org_id", "");
params.put("org_code", "");
params.put("org_name", "");
params.put("org_status", "");
params.put("create_date", "");
params.put("modify_date", "");
return params;
}
/**
* 查询人员参数
*/
public Map<String, Object> queryEmployeeParam(boolean queryId) {
Map<String, Object> params = new HashMap<>();
// 根据来源勤策的员工唯一标识精确查询
if (queryId){
params.put("id", "");
}
// 根据来源第三方系统的员工唯一标识精确查询,id、emp_id如果同时存在优先取id
params.put("emp_id", "");
// 根据员工登录帐号精确查询
params.put("emp_code", "");
// 根据姓名模糊查询
params.put("emp_name", "");
// 根据人员编码精确查询
params.put("employee_code", "");
// 根据员工状态查询
params.put("emp_status", "");
// 根据创建日期查询用户。格式:yyyy-MM-dd
params.put("create_date", "");
// 根据修改日期查询用户。格式:yyyy-MM-dd
params.put("modify_date", "");
// 根据手机号查询
params.put("emp_mobile", "");
return params;
}
private String getDigest(Map<String, Object> params, Long currentTimeMillis) {
String json = "";
if (!CollectionUtils.isEmpty(params)) {
json = JSONObject.toJSONString(params);
}
System.out.println(json + "|" + APP_KEY + "|" + currentTimeMillis);
String digest = DigestUtils.md5Hex(json + "|" + APP_KEY + "|" + currentTimeMillis);
return digest;
}
}
server:
port: 8011
spring:
application:
name: wangxiaolu-promotion-service
profiles:
active: dev
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/wangxiaolu?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: 1qaz2wsx
logging:
config: classpath:logback-spring.xml
async:
executor:
thread:
core_pool_size: 4
name:
prefix: promotion-
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<property name="APP_NAME" value="promotion-service"/>
<contextName>${APP_NAME}</contextName>
<!-- <include resource="org/springframework/boot/logging/logback/defaults.xml" />-->
<property name="HOSTNAME" value="${HOSTNAME}"/>
<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" />
<!-- 对应yml文件中spring.profiles.active配置-->
<springProfile name="dev">
<property name="LOG_PATH" value="./logs/${APP_NAME}" />
</springProfile>
<springProfile name="qa,live">
<property name="LOG_PATH" value="./data/logs/${APP_NAME}/${HOSTNAME}" />
</springProfile>
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${HOSTNAME} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${HOSTNAME} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 日志发送至logstash -->
<!-- <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">-->
<!-- &lt;!&ndash; logstash的服务器地址和通信端口 (logstash.yml中配置的就是5043端口进行输入)&ndash;&gt;-->
<!-- <destination>localhost:5043</destination>-->
<!-- &lt;!&ndash; encoder is required &ndash;&gt;-->
<!-- <encoder class="net.logstash.logback.encoder.LogstashEncoder">-->
<!-- &lt;!&ndash; 在elasticsearch的index中追加applicationName字段 &ndash;&gt;-->
<!-- <customFields>{"applicationName":"${applicationName}"}</customFields>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- 按照每天生成日志文件 -->
<appender name="rollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/promotion-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<cleanHistoryOnStart>false</cleanHistoryOnStart>
<fileNamePattern>${LOG_PATH}/promotion-%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>200MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>0</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="errorFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/promotion-error-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<cleanHistoryOnStart>false</cleanHistoryOnStart>
<fileNamePattern>${LOG_PATH}/promotion-error-%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>200MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>0</totalSizeCap>
</rollingPolicy>
<!--
此日志文件只记录debug级别的
onMatch和onMismatch都有三个属性值,分别为Accept、DENY和NEUTRAL
onMatch="ACCEPT" 表示匹配该级别及以上
onMatch="DENY" 表示不匹配该级别及以上
onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上
onMismatch="ACCEPT" 表示匹配该级别以下
onMismatch="NEUTRAL" 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
onMismatch="DENY" 表示不匹配该级别以下的
-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="rollingFile" />
<appender-ref ref="errorFile" />
<!-- <appender-ref ref="logstash"/>-->
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<property name="APP_NAME" value="promotion-service"/>
<contextName>${APP_NAME}</contextName>
<!-- <include resource="org/springframework/boot/logging/logback/defaults.xml" />-->
<property name="HOSTNAME" value="${HOSTNAME}"/>
<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" />
<!-- 对应yml文件中spring.profiles.active配置-->
<springProfile name="dev">
<property name="LOG_PATH" value="./logs/${APP_NAME}" />
</springProfile>
<springProfile name="qa,live">
<property name="LOG_PATH" value="./data/logs/${APP_NAME}/${HOSTNAME}" />
</springProfile>
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${HOSTNAME} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${HOSTNAME} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 日志发送至logstash -->
<!-- <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">-->
<!-- &lt;!&ndash; logstash的服务器地址和通信端口 (logstash.yml中配置的就是5043端口进行输入)&ndash;&gt;-->
<!-- <destination>localhost:5043</destination>-->
<!-- &lt;!&ndash; encoder is required &ndash;&gt;-->
<!-- <encoder class="net.logstash.logback.encoder.LogstashEncoder">-->
<!-- &lt;!&ndash; 在elasticsearch的index中追加applicationName字段 &ndash;&gt;-->
<!-- <customFields>{"applicationName":"${applicationName}"}</customFields>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- 按照每天生成日志文件 -->
<appender name="rollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/promotion-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<cleanHistoryOnStart>false</cleanHistoryOnStart>
<fileNamePattern>${LOG_PATH}/promotion-%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>200MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>0</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="errorFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/promotion-error-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<cleanHistoryOnStart>false</cleanHistoryOnStart>
<fileNamePattern>${LOG_PATH}/promotion-error-%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>200MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>0</totalSizeCap>
</rollingPolicy>
<!--
此日志文件只记录debug级别的
onMatch和onMismatch都有三个属性值,分别为Accept、DENY和NEUTRAL
onMatch="ACCEPT" 表示匹配该级别及以上
onMatch="DENY" 表示不匹配该级别及以上
onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上
onMismatch="ACCEPT" 表示匹配该级别以下
onMismatch="NEUTRAL" 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
onMismatch="DENY" 表示不匹配该级别以下的
-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="rollingFile" />
<appender-ref ref="errorFile" />
<!-- <appender-ref ref="logstash"/>-->
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangxiaolu.promotion.domain.user.mapper.QinceDepartmentMapper">
<resultMap id="BaseResultMap" type="com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeDepartmentDO">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="qcId" column="qc_id" jdbcType="VARCHAR"/>
<result property="orgId" column="org_id" jdbcType="VARCHAR"/>
<result property="orgCode" column="org_code" jdbcType="VARCHAR"/>
<result property="orgName" column="org_name" jdbcType="VARCHAR"/>
<result property="waiqin365ParentId" column="waiqin365_parent_id" jdbcType="VARCHAR"/>
<result property="orgParentId" column="org_parent_id" jdbcType="VARCHAR"/>
<result property="parentCode" column="parent_code" jdbcType="VARCHAR"/>
<result property="parentName" column="parent_name" jdbcType="VARCHAR"/>
<result property="fullIds" column="full_ids" jdbcType="VARCHAR"/>
<result property="fullCodes" column="full_codes" jdbcType="VARCHAR"/>
<result property="fullNames" column="full_names" jdbcType="VARCHAR"/>
<result property="orgSequence" column="org_sequence" jdbcType="VARCHAR"/>
<result property="orgStatus" column="org_status" jdbcType="INTEGER"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="modifyTime" column="modify_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,qc_id,org_id,
org_code,org_name,waiqin365_parent_id,
org_parent_id,parent_code,parent_name,
full_ids,full_codes,full_names,
org_sequence,org_status,create_time,
modify_time
</sql>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangxiaolu.promotion.domain.user.mapper.QinceEmployeeMapper">
<resultMap id="BaseResultMap" type="com.wangxiaolu.promotion.domain.user.mapper.entity.QinCeEmployeeDO">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="qcId" column="qc_id" jdbcType="VARCHAR"/>
<result property="empId" column="emp_id" jdbcType="VARCHAR"/>
<result property="empCode" column="emp_code" jdbcType="VARCHAR"/>
<result property="empName" column="emp_name" jdbcType="VARCHAR"/>
<result property="aliasName" column="alias_name" jdbcType="VARCHAR"/>
<result property="employeeCode" column="employee_code" jdbcType="VARCHAR"/>
<result property="empSex" column="emp_sex" jdbcType="CHAR"/>
<result property="empMobile" column="emp_mobile" jdbcType="VARCHAR"/>
<result property="mobileDistrictCode" column="mobile_district_code" jdbcType="VARCHAR"/>
<result property="empTel" column="emp_tel" jdbcType="VARCHAR"/>
<result property="empBirthday" column="emp_birthday" jdbcType="CHAR"/>
<result property="empQq" column="emp_qq" jdbcType="VARCHAR"/>
<result property="empWeixin" column="emp_weixin" jdbcType="VARCHAR"/>
<result property="empWechatCode" column="emp_wechat_code" jdbcType="VARCHAR"/>
<result property="empIdcard" column="emp_idcard" jdbcType="VARCHAR"/>
<result property="empEmail" column="emp_email" jdbcType="VARCHAR"/>
<result property="empAddr" column="emp_addr" jdbcType="VARCHAR"/>
<result property="empOrgId" column="emp_org_id" jdbcType="VARCHAR"/>
<result property="empOrgCode" column="emp_org_code" jdbcType="VARCHAR"/>
<result property="waiqin365OrgId" column="waiqin365_org_id" jdbcType="VARCHAR"/>
<result property="empParentId" column="emp_parent_id" jdbcType="VARCHAR"/>
<result property="parentCode" column="parent_code" jdbcType="VARCHAR"/>
<result property="waiqin365ParentId" column="waiqin365_parent_id" jdbcType="VARCHAR"/>
<result property="empIsOrgLearder" column="emp_is_org_learder" jdbcType="CHAR"/>
<result property="empStatus" column="emp_status" jdbcType="CHAR"/>
<result property="empImsiBinding" column="emp_imsi_binding" jdbcType="CHAR"/>
<result property="dealerId" column="dealer_id" jdbcType="VARCHAR"/>
<result property="dealerName" column="dealer_name" jdbcType="VARCHAR"/>
<result property="empBaseprovince" column="emp_baseprovince" jdbcType="VARCHAR"/>
<result property="empBasecity" column="emp_basecity" jdbcType="VARCHAR"/>
<result property="waiqin365PositionId" column="waiqin365_position_id" jdbcType="VARCHAR"/>
<result property="empPositionCode" column="emp_position_code" jdbcType="VARCHAR"/>
<result property="empPosition" column="emp_position" jdbcType="VARCHAR"/>
<result property="waiqin365JobId" column="waiqin365_job_id" jdbcType="VARCHAR"/>
<result property="empJobCode" column="emp_job_code" jdbcType="VARCHAR"/>
<result property="empJob" column="emp_job" jdbcType="VARCHAR"/>
<result property="mobileAuth" column="mobile_auth" jdbcType="CHAR"/>
<result property="terminalType" column="terminal_type" jdbcType="VARCHAR"/>
<result property="faceTime" column="face_time" jdbcType="TIMESTAMP"/>
<result property="empEnrollmentTime" column="emp_enrollment_time" jdbcType="TIMESTAMP"/>
<result property="empResignationTime" column="emp_resignation_time" jdbcType="TIMESTAMP"/>
<result property="lastUseTime" column="last_use_time" jdbcType="TIMESTAMP"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="modifyTime" column="modify_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,qc_id,emp_id,
emp_code,emp_name,alias_name,
employee_code,emp_sex,emp_mobile,
mobile_district_code,emp_tel,emp_birthday,
emp_qq,emp_weixin,emp_wechat_code,
emp_idcard,emp_email,emp_addr,
emp_org_id,emp_org_code,waiqin365_org_id,
emp_parent_id,parent_code,waiqin365_parent_id,
emp_is_org_learder,emp_status,emp_imsi_binding,
dealer_id,dealer_name,emp_baseprovince,
emp_basecity,waiqin365_position_id,emp_position_code,
emp_position,waiqin365_job_id,emp_job_code,
emp_job,mobile_auth,terminal_type,
face_time,emp_enrollment_time,emp_resignation_time,
last_use_time,create_time,modify_time
</sql>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangxiaolu.promotion.domain.user.mapper.UserInfoMapper">
<resultMap id="BaseResultMap" type="com.wangxiaolu.promotion.domain.user.mapper.entity.UserInfoDO">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="phone" column="phone" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="modifyTime" column="modify_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,name,phone,
create_time,modify_time
</sql>
</mapper>
package com.wangxiaolu.promotion;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class WangxiaoluPromotionServiceApplicationTests {
@Test
void contextLoads() {
}
}
package com.wangxiaolu.promotion.controller.user;
import com.wangxiaolu.promotion.pojo.user.vo.UserLoginParam;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author : liqiulin
* @date : 2024-03-29 14
* @describe :
*/
@SpringBootTest
@RunWith(SpringRunner.class)
class PromotionLoginControllerTest {
@Autowired
PromotionLoginController promotionLoginController;
@Test
void login() {
UserLoginParam param = new UserLoginParam().setLoginName("李秋林1");
promotionLoginController.login(param);
}
}
\ No newline at end of file
package com.wangxiaolu.promotion.controller.user;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author : liqiulin
* @date : 2024-03-29 17
* @describe :
*/
@SpringBootTest
@RunWith(SpringRunner.class)
class QinCeDataTaskControllerTest {
@Autowired
QinCeDataTaskController qinCeDataTaskController;
@Test
void departmentTask() {
qinCeDataTaskController.departmentTask();
}
@Test
void employeeTask() {
qinCeDataTaskController.employeeTask();
}
}
\ No newline at end of file
package com.wangxiaolu.promotion.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author : liqiulin
* @date : 2024-03-29 15
* @describe :
*/
@SpringBootTest
@RunWith(SpringRunner.class)
class OkHttpTest {
@Autowired
QinCeUtils qinCeUtils;
@Test
void postDepartment() {
// 查询组织架构参数
Map<String, Object> params = qinCeUtils.queryOrgParam();
// 创建url
String url = qinCeUtils.builderUrl(QinCeUtils.QUERY_ORGANIZATION,params);
System.out.println(url);
// 发起请求
JSONObject resultJson = OkHttp.post(url, params);
JSONArray responseDatas = resultJson.getJSONArray("response_data");
for (Object responseData : responseDatas) {
System.out.println(responseData);
}
System.out.println(resultJson);
}
@Test
void postEmployee() {
// 查询组织架构参数
Map<String, Object> params = qinCeUtils.queryEmployeeParam(false);
// 创建url
String url = qinCeUtils.builderUrl(QinCeUtils.QUERY_EMPLOYEE,params);
System.out.println(url);
// 发起请求
JSONObject resultJson = OkHttp.post(url, params);
JSONArray responseDatas = resultJson.getJSONArray("response_data");
for (Object responseData : responseDatas) {
System.out.println(responseData);
}
System.out.println(resultJson);
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论