init xlog project

This commit is contained in:
pepsi 2022-09-17 10:04:14 +08:00
parent a921143f22
commit 4ef214d0ca
30 changed files with 1547 additions and 0 deletions

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
application-local.yml
*.log
rebel.xml
.flattened-pom.xml

81
pom.xml Normal file
View File

@ -0,0 +1,81 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>xlog-api</module>
<module>xlog-server</module>
</modules>
<parent>
<groupId>cn.axzo.infra</groupId>
<artifactId>axzo-parent</artifactId>
<version>2.4.13</version>
</parent>
<groupId>cn.axzo.xlog</groupId>
<artifactId>xlog</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>xlog</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mapstruct.version>1.4.2.Final</mapstruct.version>
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>axzo-bom</artifactId>
<version>${axzo-bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>axzo-dependencies</artifactId>
<version>${axzo-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

55
xlog-api/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>xlog</artifactId>
<groupId>cn.axzo.xlog</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>xlog-api</artifactId>
<packaging>jar</packaging>
<name>xlog-api</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-common</artifactId>
</dependency>
</dependencies>
<build>
</build>
</project>

View File

@ -0,0 +1,21 @@
package cn.axzo.xlog.api;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.azxo.framework.common.model.CommonResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
@FeignClient(name = "xlog", url = "http://xlog:10999")
public interface OperateLogApi {
@PostMapping("/api/operateLog/create")
CommonResponse<Boolean> operateLogCreate(@RequestBody OperateLogReq req);
}

View File

@ -0,0 +1,126 @@
package cn.axzo.xlog.api.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
/***
* @author: pepsi
* @description: 操作日志信息
* @date: 2022/9/15
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class OperateLogReq {
/**
* 调用方服务名
*/
private String serviceName;
/**
* 功能Code
*/
private String featureCode;
/**
* 功能name
*/
private String featureName;
/**
* 日志等级 为空默认P4 请参照 {@link cn.axzo.xlog.api.enums.LogGradeEnum}
*/
private Integer logGrade = 4;
/**
* 操作时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date operateTime;
/**
* 操作人安心筑Id
*/
@NotNull(message = "操作人Id不能为空")
private Long identityId;
/**
* 人员类型 1:工人 2:班组长 3:从业人员..实际情况拓展
* 请参照 {@link cn.axzo.xlog.api.enums.IdentityType}
*/
@NotNull(message = "人员类型身份不能为空")
private Integer identityType;
/**
* 所属工作台Id
*/
private Long workspaceId;
/**
* 所属单位Id
*/
private Long ouId;
/**
* 终端类型:token认证返回的terminal字段即可
*/
private String terminal;
/**
* 操作人Ip
*/
private String operateUserIp;
/**
* 操作前数据
*/
private String operateBefore;
/**
* 操作后数据
*/
private String operateAfter;
/**
* 操作参数
*/
private String operateParam;
/**
* 内容摘要
*/
private String contentSummary;
/**
* 拓展字段 按需使用
*/
private String logExt;
/**
* 资源id 预防更小范围数据权限预留字段
*/
private Long resourceId;
/**
* 资源类型 预防更小范围数据权限预留字段
*/
private Integer resourceType;
/**
* 操作类型 1:add 2:add_batch 3:update 4:update_batch 5:delete 6:delete_batch
*/
@NotNull(message = "操作类型不能为空")
private Integer operateType;
/**
* 操作表名
*/
private String operateTable;
}

156
xlog-server/pom.xml Normal file
View File

@ -0,0 +1,156 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>xlog</artifactId>
<groupId>cn.axzo.xlog</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>xlog-server</artifactId>
<packaging>jar</packaging>
<name>xlog-server</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- springcloud starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- spring framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- axzo -->
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-common</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.xlog</groupId>
<artifactId>xlog-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<scope>runtime</scope>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>provided</scope>
</dependency>
<!-- for test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,43 @@
package cn.axzo.xlog.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
@EnableFeignClients(basePackages = {
})
@EnableDiscoveryClient
@SpringBootApplication(scanBasePackages = "cn.axzo")
public class XlogApplication {
private static final Logger logger = LoggerFactory.getLogger(XlogApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(XlogApplication.class, args);
Environment env = context.getEnvironment();
logger.info("Application 【{}】 is running on 【{}】 environment!\n\t" +
"MySQL: \t{}\t username:{}\t\n\t" +
"Redis: \t{}:{}\t database:{}\t\n\t" +
"RabbitMQ: \t{}\t username:{},\t\n",
env.getProperty("spring.application.name"),
env.getProperty("spring.profiles.active"),
env.getProperty("spring.datasource.url"),
env.getProperty("spring.datasource.username"),
env.getProperty("spring.redis.host"),
env.getProperty("spring.redis.port"),
env.getProperty("spring.redis.database"),
env.getProperty("spring.rabbitmq.addresses"),
env.getProperty("spring.rabbitmq.username"));
}
}

View File

@ -0,0 +1,47 @@
package cn.axzo.xlog.server.config;
import cn.axzo.xlog.server.entity.BaseEntity;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.Date;
/**
* @author
*/
@EnableTransactionManagement
@MapperScan(value = {"cn.axzo.**.mapper"})
@Configuration
public class MybatisPlusConfig {
private static final String SYSTEM_TENANT_ID = "agency_id";
@Bean
public MetaObjectHandler EntityMetaObjectHandler() {
return new MetaObjectHandler() {
@Override
public void insertFill(MetaObject metaObject) {
Object entity = metaObject.getOriginalObject();
if (entity instanceof BaseEntity) {
//默认有值不覆盖
this.fillStrategy(metaObject, "createAt", new Date());
this.fillStrategy(metaObject, "updateAt", new Date());
}
}
@Override
public void updateFill(MetaObject metaObject) {
Object entity = metaObject.getOriginalObject();
if (entity instanceof BaseEntity) {
//强制覆盖
this.setFieldValByName("updateAt", new Date(), metaObject);
}
}
};
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.xlog.server.config;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.axzo.xlog.server.service.OperateLogService;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/***
* @author: pepsi
* @description: 消费rabbit推过来的操作日志数据
* @date: 2022/9/15
*/
@Component
public class OperateLogMqConsumer {
private final Logger logger = LoggerFactory.getLogger(OperateLogMqConsumer.class);
@Resource
private OperateLogService operateLogService;
@RabbitListener(queues = RabbitMqConfig.OPERATE_LOG_QUEUE_NAME)
public void consumerOprlogs(Message message, Channel channel) throws IOException {
String msg = new String(message.getBody(), StandardCharsets.UTF_8);
try {
OperateLogReq operateLogReq = JSONObject.parseObject(msg, OperateLogReq.class);
operateLogService.insertOperaLog(operateLogReq);
} catch (Exception e) {
logger.error("handle operate log failed.", e);
//todo 失败处理
} finally {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
}

View File

@ -0,0 +1,41 @@
package cn.axzo.xlog.server.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
@Configuration
public class RabbitMqConfig {
private final Logger logger = LoggerFactory.getLogger(RabbitMqConfig.class);
// 操作日志队列
public static final String OPERATE_LOG_QUEUE_NAME = "unified.operate.log";
public static final String OPERATE_LOG_EXCHANGE = "unified.operate.log.exchange";
public static final String OPERATE_LOG_ROUTING_KEY = "unified.operate.log.routingKey";
@Bean
public Queue operateLogQueue() {
return new Queue(OPERATE_LOG_QUEUE_NAME, true);
}
@Bean
public DirectExchange operateLogExchange() {
return new DirectExchange(OPERATE_LOG_EXCHANGE, true, false);
}
@Bean
public Binding operateLogBindingDirect(DirectExchange exchange, Queue oprlogeQueue) {
Binding binding = BindingBuilder.bind(oprlogeQueue).to(exchange).with(OPERATE_LOG_ROUTING_KEY);
logger.info("rabbitmq queue:[{}] binding exchange:[{}] success.", oprlogeQueue.getName(), exchange.getName());
return binding;
}
}

View File

@ -0,0 +1,10 @@
package cn.axzo.xlog.server.controller;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
public abstract class BaseController {
}

View File

@ -0,0 +1,20 @@
package cn.axzo.xlog.server.controller.api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
@RestController
@RequestMapping("/api")
public class OperateLogController {
private Logger logger = LoggerFactory.getLogger(OperateLogController.class);
}

View File

@ -0,0 +1,39 @@
package cn.axzo.xlog.server.entity;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
* @Author: liyong.tian
* @Date: 2022/9/5
* @Description:
*/
@Getter
@Setter
public abstract class BaseEntity<T extends Model<?>> extends Model<T> {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 是否删除0否 1是
*/
@TableField(value = "is_delete", fill = FieldFill.INSERT)
private Integer isDelete = 0;
@TableField(value = "create_at", fill = FieldFill.INSERT)
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createAt;
@TableField(value = "update_at", fill = FieldFill.INSERT_UPDATE)
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updateAt;
}

View File

@ -0,0 +1,143 @@
package cn.axzo.xlog.server.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.Date;
/**
* 操作日志
*
* @author tanjie@axzo.cn
* @date 2022/06/30 14:01
*/
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = true)
@TableName("unified_log_record")
public class OperateLogRecordEntity extends BaseEntity<OperateLogRecordEntity> {
/**
* 调用方服务名
*/
private String serviceName;
/**
* 功能名称
*/
private String featureName;
/**
* 功能名称code
*/
private String featureCode;
/**
* 日志等级 0:p0 1:p1 2:p2 3:p3 4:p4
*/
private Integer logGrade;
/**
* 操作时间
*/
private Date operateTime;
/**
* 所属终端
*/
private String terminal;
/**
* 操作人id
*/
private Long identityId;
/**
* 操作人名字
*/
private String identityUserName;
/**
* 操作人手机号
*/
private String identityUserPhone;
/**
* 操作人类型-与档案域一致 1:工人 2:班组长 3:从业人员 4:监管人员 5:运营人员
*/
private Integer identityType;
/**
* 工作台id
*/
private Long workspaceId;
/**
* 单位id
*/
private Long ouId;
/**
* 工作台名字
*/
private String workspaceName;
/**
* 单位名字
*/
private String ouName;
/**
* 资源id 预防更小范围数据权限预留字段
*/
private Long resourceId;
/**
* 资源类型 预防更小范围数据权限预留字段
*/
private Integer resourceType;
/**
* 操作类型 1:add 2:add_batch 3:update 4:update_batch 5:delete 6:delete_batch
*/
private Integer operateType;
/**
* 操作人ip
*/
private String operateUserIp;
/**
* 操作表名
*/
private String operateTable;
/**
* 操作前内容
*/
private String operateBefore;
/**
* 操作后内容
*/
private String operateAfter;
/**
* 操作参数
*/
private String operateParam;
/**
* 内容摘要
*/
private String contentSummary;
/**
* 日志拓展内容
*/
private String logExt;
}

View File

@ -0,0 +1,28 @@
package cn.axzo.xlog.server.enums;
/**
* 项目名称pudge
* AbstractEnum
* TODO
* 创建时间2022/7/14 12:26
* xuyaozuo
*/
public interface IEnum {
Integer getCode();
String getMessage();
static <T extends Enum<T> & IEnum> T enumFromCode(Class<T> enumType, Integer code) {
T defaultEnum = null;
for (T c : enumType.getEnumConstants()) {
if (c.getCode().equals(code)) {
return c;
}
if (c.getCode().equals(0)) {
defaultEnum = c;
}
}
return defaultEnum;
}
}

View File

@ -0,0 +1,52 @@
package cn.axzo.xlog.server.enums;
import cn.axzo.xlog.server.exception.ServiceException;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 人员身份类型枚举
*
* @author xuyaozuo
* @since 2022/5/9 21:59
*/
@Getter
@AllArgsConstructor
public enum IdentityType implements IEnum {
/*人员身份类型*/
NOT_SUPPORT(0, "NOT_SUPPORT", "无效类型"),
WORKER(1, "WORKER", "工人"),
WORKER_LEADER(2, "WORKER_LEADER", "班组长"),
PRACTITIONER(3, "PRACTITIONER", "从业人员"),
REGULATOR(4, "REGULATOR", "监管人员"),
OPERATOR(5, "OPERATOR", "运营人员"),
;
@EnumValue
@JsonValue
private final Integer code;
private final String message;
private final String desc;
public static IdentityType getIdentityType(Integer code) {
IdentityType[] values = values();
for (IdentityType item : values) {
if (item.getCode().equals(code)) {
return item;
}
}
throw new ServiceException("档案身份类型不匹配 code:" + code);
}
public static IdentityType getIdentityType(String message) {
IdentityType[] values = values();
for (IdentityType item : values) {
if (item.getMessage().equals(message)) {
return item;
}
}
throw new ServiceException("档案身份类型不匹配 message:" + message);
}
}

View File

@ -0,0 +1,32 @@
package cn.axzo.xlog.server.enums;
import lombok.Getter;
/**
* @author : liuchuntao
* @date : 2022/6/28 15:53
* @description : 日志等级
*/
@Getter
public enum LogGradeEnum {
P0(0, "P0"),
P1(1, "P1"),
P2(2, "P2"),
P3(3, "P3"),
P4(4, "P4");
public final Integer value;
public final String desc;
LogGradeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}

View File

@ -0,0 +1,18 @@
package cn.axzo.xlog.server.exception;
/**
* @author Smile
* 服务异常
*/
public class ServiceException extends RuntimeException {
public ServiceException(String msg) {
super(msg);
}
public static void error(boolean condition, String msg) {
if (!condition) {
throw new ServiceException(msg);
}
}
}

View File

@ -0,0 +1,15 @@
package cn.axzo.xlog.server.mapper;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/15
*/
@Mapper
public interface OperateLogMapper extends BaseMapper<OperateLogRecordEntity> {
}

View File

@ -0,0 +1,17 @@
package cn.axzo.xlog.server.repository;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/15
*/
public interface OperateLogRepository {
/**
* @param user
* @return
*/
OperateLogRecordEntity save(OperateLogRecordEntity user);
}

View File

@ -0,0 +1,27 @@
package cn.axzo.xlog.server.repository.impl;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
import cn.axzo.xlog.server.mapper.OperateLogMapper;
import cn.axzo.xlog.server.repository.OperateLogRepository;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/15
*/
@Repository
public class OperateLogRepositoryImpl implements OperateLogRepository {
@Resource
private OperateLogMapper mapper;
@Override
public OperateLogRecordEntity save(OperateLogRecordEntity logRecordEntity) {
mapper.insert(logRecordEntity);
return logRecordEntity;
}
}

View File

@ -0,0 +1,26 @@
package cn.axzo.xlog.server.service;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/15
*/
public interface OperateLogService {
/**
* @param operateLogReq
* @return
*/
boolean insertOperaLog(OperateLogReq operateLogReq);
/**
* 字段补全
*
* @param operateLogReq
* @return
*/
OperateLogRecordEntity fieldFill(OperateLogReq operateLogReq);
}

View File

@ -0,0 +1,15 @@
package cn.axzo.xlog.server.service.converter;
import java.util.List;
/**
* @Author: liyong.tian
* @Date: 2022/9/5
* @Description:
*/
public interface EntityConverter<V, E> {
V toVm(E var);
List<V> toVm(List<E> var);
}

View File

@ -0,0 +1,63 @@
package cn.axzo.xlog.server.service.impl;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
import cn.axzo.xlog.server.enums.IdentityType;
import cn.axzo.xlog.server.repository.OperateLogRepository;
import cn.axzo.xlog.server.service.OperateLogService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/15
*/
@Service
public class OperateLogServiceImpl implements OperateLogService {
@Resource
private OperateLogRepository operateLogRepository;
@Override
public boolean insertOperaLog(OperateLogReq operateLogReq) {
//调用接口字段补全
OperateLogRecordEntity record = fieldFill(operateLogReq);
//落库
operateLogRepository.save(record);
return true;
}
@Override
public OperateLogRecordEntity fieldFill(OperateLogReq req) {
//补充 termimnal identityType featureName
IdentityType type = IdentityType.getIdentityType(req.getIdentityType());
OperateLogRecordEntity unifiedLogRecord = new OperateLogRecordEntity();
unifiedLogRecord.setServiceName(req.getServiceName());
unifiedLogRecord.setFeatureCode(req.getFeatureCode());
unifiedLogRecord.setFeatureName(req.getFeatureName());
unifiedLogRecord.setLogGrade(req.getLogGrade());
unifiedLogRecord.setOperateTime(req.getOperateTime());
unifiedLogRecord.setTerminal(req.getTerminal());
unifiedLogRecord.setIdentityId(req.getIdentityId());
//不用 enums
unifiedLogRecord.setIdentityType(type.getCode());
unifiedLogRecord.setWorkspaceId(req.getWorkspaceId());
unifiedLogRecord.setOuId(req.getOuId());
unifiedLogRecord.setOperateUserIp(req.getOperateUserIp());
unifiedLogRecord.setOperateBefore(req.getOperateBefore());
unifiedLogRecord.setOperateAfter(req.getOperateAfter());
unifiedLogRecord.setOperateParam(req.getOperateParam());
unifiedLogRecord.setContentSummary(req.getContentSummary());
unifiedLogRecord.setLogExt(req.getLogExt());
unifiedLogRecord.setResourceId(req.getResourceId());
unifiedLogRecord.setOperateTable(req.getOperateTable());
unifiedLogRecord.setOperateType(req.getOperateType());
unifiedLogRecord.setResourceType(req.getResourceType());
//todo 缓存方式 + 通过接口方式调用 workspaceApiprofileApi获取name单位等信息,
return unifiedLogRecord;
}
}

View File

@ -0,0 +1,41 @@
spring:
application:
name: xlog
cloud:
nacos:
config:
server-addr: ${NACOS_HOST:test1-nacos.axzo.cn}:${NACOS_PORT:80}
file-extension: yaml
namespace: ${NACOS_NAMESPACE_ID:6b278234-1409-4054-beb7-4bbc0def8e54}
prefix: ${spring.application.name}
profiles:
active: ${NACOS_PROFILES_ACTIVE:test1}
main:
allow-bean-definition-overriding: true
datasource:
hikari:
pool-name: xlog_HikariCP
minimum-idle: 2
idle-timeout: 120000
maximum-pool-size: 20
auto-commit: true
max-lifetime: 1200000
connection-timeout: 600000
connection-test-query: SELECT 1
mybatis-plus:
type-aliases-package: cn.axzo.xlog.domain
configuration:
auto-mapping-behavior: full
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #这个配置会将执行的sql打印出来在开发或测试的时候可以用
#配置扫描xml
mapper-locations: classpath*:mapper/**/*.xml
global-config:
db-config:
id-type: auto
logic-delete-value: 1 #逻辑已删除值(默认为 1)
logic-not-delete-value: 0 #逻辑未删除值(默认为 0)
logic-delete-field: is_delete #逻辑删除字段
logging:
level:
root: DEBUG

View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<springProperty scope="context" name="appName" source="spring.application.name"/>
<!--属性-->
<property name="PROJECT_NAME" value="${appName}"/>
<define name="LOG_PREFIX"
class="cn.azxo.framework.common.logger.logback.LogPrefixPropertyDefiner"/>
<!--日志路径-->
<property name="LOG_PATH" value="${LOG_PREFIX}/${appName}/"/>
<!-- 日志最大的历史 7天 -->
<property name="MAX_HISTORY" value="7"/>
<!--默认日志输出模式-->
<property name="LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} %green(${appName}) %highlight(%-5level) [%15thread] [%X{ctxLogId}] %cyan([%class{36}#%M:%L]) %n%msg%n"/>
<!-- 采用这个将 ctxLogId 打印出来方便排查问题-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} %-5level --- [%15thread] [%X{ctxLogId}] %logger: %msg%n"/>
<!--<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} %-5level -&#45;&#45; [%15thread] %logger: %msg%n"/>-->
<!--环境名-->
<contextName>${PROJECT_NAME}</contextName>
<!--错误日志-->
<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}/error/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--每个文件的大小限制-->
<maxFileSize>30MB</maxFileSize>
<!--最多保留7天的文件7天之前的将被清除-->
<maxHistory>${MAX_HISTORY}</maxHistory>
<!--该滚动策略日志的总大小,超过的日志会被清除-->
<totalSizeCap>1GB</totalSizeCap>
<!--启动时清理日志文件 此项置灰清理超过保留天数的 也会清理超过总大小的-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/warn/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--每个文件的大小限制-->
<maxFileSize>30MB</maxFileSize>
<!--最多保留7天的文件7天之前的将被清除-->
<maxHistory>${MAX_HISTORY}</maxHistory>
<!--该滚动策略日志的总大小,超过的日志会被清除-->
<totalSizeCap>1GB</totalSizeCap>
<!--启动时清理日志文件 此项置灰清理超过保留天数的 也会清理超过总大小的-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/info/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--每个文件的大小限制-->
<maxFileSize>30MB</maxFileSize>
<!--最多保留7天的文件7天之前的将被清除-->
<maxHistory>${MAX_HISTORY}</maxHistory>
<!--该滚动策略日志的总大小,超过的日志会被清除-->
<totalSizeCap>1GB</totalSizeCap>
<!--启动时清理日志文件 此项置灰清理超过保留天数的 也会清理超过总大小的-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<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}/debug/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--每个文件的大小限制-->
<maxFileSize>30MB</maxFileSize>
<!--最多保留7天的文件7天之前的将被清除-->
<maxHistory>${MAX_HISTORY}</maxHistory>
<!--该滚动策略日志的总大小,超过的日志会被清除-->
<totalSizeCap>1GB</totalSizeCap>
<!--启动时清理日志文件 此项置灰清理超过保留天数的 也会清理超过总大小的-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- ConsoleAppender 控制台输出日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender" addtivity="false">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
</appender>
<springProfile name="local">
<root level="info">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="dev">
<root level="info">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="test">
<root level="info">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="test1">
<root level="info">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="pre">
<root level="debug">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="uat">
<root level="debug">
<appender-ref ref="ERROR"/>
<appender-ref ref="WARN"/>
<appender-ref ref="INFO"/>
<appender-ref ref="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>

View File

@ -0,0 +1,7 @@
<?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="cn.axzo.xlog.mapper.OperateLogMapper">
</mapper>

View File

@ -0,0 +1,16 @@
package cn.axzo.xlog.server;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class XlogApplicationTestBase {
}

View File

@ -0,0 +1,51 @@
package cn.axzo.xlog.server.config;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.axzo.xlog.server.XlogApplicationTestBase;
import com.alibaba.fastjson.JSONObject;
import org.junit.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import javax.annotation.Resource;
import java.util.Date;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
public class RabbitMqConsumerTest extends XlogApplicationTestBase {
@Resource
private RabbitTemplate rabbitTemplate;
@Test
public void sendMsg() throws InterruptedException {
for (int i = 0; i < 10; i++) {
OperateLogReq reqData = new OperateLogReq();
reqData.setLogGrade(1);
reqData.setLogExt("test");
reqData.setIdentityId(1L);
reqData.setOperateAfter("test");
reqData.setOperateParam("test");
reqData.setFeatureCode("test");
reqData.setOperateTable("test");
reqData.setOperateType(1);
reqData.setContentSummary("test");
reqData.setOperateTime(new Date());
reqData.setServiceName("test");
reqData.setOuId(1L);
reqData.setOperateUserIp("test");
reqData.setWorkspaceId(1L);
reqData.setResourceType(1);
reqData.setIdentityType(1);
reqData.setTerminal("test");
reqData.setOperateBefore("test");
reqData.setFeatureName("test");
reqData.setResourceId(1L);
rabbitTemplate.convertAndSend(RabbitMqConfig.OPERATE_LOG_QUEUE_NAME, JSONObject.toJSONString(reqData));
System.out.println("send msg success");
}
Thread.sleep(1000 * 10);
}
}

View File

@ -0,0 +1,64 @@
package cn.axzo.xlog.server.service;
import cn.axzo.xlog.api.dto.OperateLogReq;
import cn.axzo.xlog.server.XlogApplicationTestBase;
import cn.axzo.xlog.server.entity.OperateLogRecordEntity;
import com.alibaba.fastjson.JSONObject;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
/***
* @author: pepsi
* @description: TODO
* @date: 2022/9/16
*/
public class OperateLogServiceTest extends XlogApplicationTestBase {
private OperateLogReq reqData;
@Autowired
private OperateLogService operateLogService;
@Before
public void initreqDataData() {
reqData = new OperateLogReq();
reqData.setLogGrade(1);
reqData.setLogExt("test");
reqData.setIdentityId(1L);
reqData.setOperateAfter("test");
reqData.setOperateParam("test");
reqData.setFeatureCode("test");
reqData.setOperateTable("test");
reqData.setOperateType(1);
reqData.setContentSummary("test");
reqData.setOperateTime(new Date());
reqData.setServiceName("test");
reqData.setOuId(1L);
reqData.setOperateUserIp("test");
reqData.setWorkspaceId(1L);
reqData.setResourceType(1);
reqData.setIdentityType(1);
reqData.setTerminal("test");
reqData.setOperateBefore("test");
reqData.setFeatureName("test");
reqData.setResourceId(1L);
System.out.println(JSONObject.toJSONString(reqData));
}
@Test
public void testFieldFill() {
OperateLogRecordEntity entity = operateLogService.fieldFill(reqData);
Assert.assertEquals(reqData.getLogGrade(), entity.getLogGrade());
}
@Test
public void testInsert() {
boolean res = operateLogService.insertOperaLog(reqData);
Assert.assertTrue(res);
}
}