Browse Source

增加代码

master
liuchen 8 months ago
commit
2a159f80cd
  1. 34
      .gitignore
  2. 66
      pom.xml
  3. 18
      src/main/java/com/win/qad/Application.java
  4. 112
      src/main/java/com/win/qad/common/CommonResult.java
  5. 31
      src/main/java/com/win/qad/config/RestTemplateConfig.java
  6. 18
      src/main/java/com/win/qad/config/ShellConfig.java
  7. 34
      src/main/java/com/win/qad/config/SmfsConfigure.java
  8. 96
      src/main/java/com/win/qad/controller/ShellController.java
  9. 26
      src/main/java/com/win/qad/exception/ErrorCode.java
  10. 44
      src/main/java/com/win/qad/exception/GlobalErrorCodeConstants.java
  11. 58
      src/main/java/com/win/qad/exception/ServerException.java
  12. 58
      src/main/java/com/win/qad/exception/ServiceException.java
  13. 26
      src/main/java/com/win/qad/utils/ProfileUtil.java
  14. 69
      src/main/java/com/win/qad/utils/shell/ShellUtil.java
  15. 32
      src/main/java/com/win/qad/utils/shell/ShellVo.java
  16. 56
      src/main/resources/application-dev.yml
  17. 12
      src/main/resources/application.yml
  18. 108
      src/main/resources/logback-spring.xml

34
.gitignore

@ -0,0 +1,34 @@
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/
/logs

66
pom.xml

@ -0,0 +1,66 @@
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.15</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.win.mq</groupId>
<artifactId>qad</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mq</name>
<description>win mq</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

18
src/main/java/com/win/qad/Application.java

@ -0,0 +1,18 @@
package com.win.qad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
* 启动程序
*
* @author win
*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("闻音启动成功");
}
}

112
src/main/java/com/win/qad/common/CommonResult.java

@ -0,0 +1,112 @@
package com.win.qad.common;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.win.qad.exception.ErrorCode;
import com.win.qad.exception.GlobalErrorCodeConstants;
import com.win.qad.exception.ServiceException;
import lombok.Data;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.util.Objects;
/**
* 通用返回
*
* @param <T> 数据泛型
*/
@Data
public class CommonResult<T> implements Serializable {
/**
* 错误码
*
* @see ErrorCode#getCode()
*/
private Integer code;
/**
* 返回数据
*/
private T data;
/**
* 错误提示用户可阅读
*
* @see ErrorCode#getMsg() ()
*/
private String msg;
/**
* 将传入的 result 对象转换成另外一个泛型结果的对象
*
* 因为 A 方法返回的 CommonResult 对象不满足调用其的 B 方法的返回所以需要进行转换
*
* @param result 传入的 result 对象
* @param <T> 返回的泛型
* @return 新的 CommonResult 对象
*/
public static <T> CommonResult<T> error(CommonResult<?> result) {
return error(result.getCode(), result.getMsg());
}
public static <T> CommonResult<T> error(Integer code, String message) {
Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code), "code 必须是错误的!");
CommonResult<T> result = new CommonResult<>();
result.code = code;
result.msg = message;
return result;
}
public static <T> CommonResult<T> error(ErrorCode errorCode) {
return error(errorCode.getCode(), errorCode.getMsg());
}
public static <T> CommonResult<T> success(T data) {
CommonResult<T> result = new CommonResult<>();
result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
result.data = data;
result.msg = "";
return result;
}
public static boolean isSuccess(Integer code) {
return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
}
@JsonIgnore // 避免 jackson 序列化
public boolean isSuccess() {
return isSuccess(code);
}
@JsonIgnore // 避免 jackson 序列化
public boolean isError() {
return !isSuccess();
}
// ========= 和 Exception 异常体系集成 =========
/**
* 判断是否有异常如果有则抛出 {@link ServiceException} 异常
*/
public void checkError() throws ServiceException {
if (isSuccess()) {
return;
}
// 业务异常
throw new ServiceException(code, msg);
}
/**
* 判断是否有异常如果有则抛出 {@link ServiceException} 异常
* 如果没有则返回 {@link #data} 数据
*/
@JsonIgnore // 避免 jackson 序列化
public T getCheckedData() {
checkError();
return data;
}
public static <T> CommonResult<T> error(ServiceException serviceException) {
return error(serviceException.getCode(), serviceException.getMessage());
}
}

31
src/main/java/com/win/qad/config/RestTemplateConfig.java

@ -0,0 +1,31 @@
package com.win.qad.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// 支持中文编码
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//单位为ms
factory.setConnectTimeout(5000);//单位为ms
return factory;
}
}

18
src/main/java/com/win/qad/config/ShellConfig.java

@ -0,0 +1,18 @@
package com.win.qad.config;
import com.win.qad.utils.shell.ShellVo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "shell")
public class ShellConfig {
private ShellVo jlht;
private ShellVo jlht2;
//linux配置信息
// private Map<String, ShellVo> linux;
}

34
src/main/java/com/win/qad/config/SmfsConfigure.java

@ -0,0 +1,34 @@
package com.win.qad.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "sfms")
public class SmfsConfigure {
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 采购订单请求地址
*/
private String purchaseOrder;
/**
* 访问token
*/
private String accessToken;
/**
* 刷新token
*/
private String refreshToken;
}

96
src/main/java/com/win/qad/controller/ShellController.java

@ -0,0 +1,96 @@
package com.win.qad.controller;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.win.qad.common.CommonResult;
import com.win.qad.config.ShellConfig;
import com.win.qad.exception.GlobalErrorCodeConstants;
import com.win.qad.utils.ProfileUtil;
import com.win.qad.utils.shell.ShellUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
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;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/shell")
public class ShellController {
@Autowired
private ShellUtil shellUtil;
@Autowired
private ShellConfig shellConfig;
/**
* 对外提供一个接口通过header中的interfaceName反射机制调用方法方法必须写到这个controller中并且不用加PostMapping注解
*
* @param request request
* @param body 请求主体
* @return 结果
*/
@PostMapping("/api")
@SuppressWarnings("unchecked")
public CommonResult<String> api(HttpServletRequest request, @RequestBody String body) {
String interfaceName = request.getHeader("interface");
String sign = request.getHeader("sign");
String timeStr = request.getHeader("timestamp");
if(timeStr == null || timeStr.isEmpty()) {
return CommonResult.error(GlobalErrorCodeConstants.TIMESTAMP_ERROR);
}
long timestamp = 0;
try {
timestamp = Long.parseLong(timeStr);
} catch (NumberFormatException e) {
return CommonResult.error(GlobalErrorCodeConstants.TIMESTAMP_ERROR);
}
String tmp = interfaceName + body + timestamp;
String computeSign = DigestUtils.md5DigestAsHex(tmp.getBytes());
log.info("{}, interfaceName: {}", "interfaceName", interfaceName);
log.info("{}, sign: {}", "sign", sign);
log.info("{}, timestamp: {}", "timestamp", timestamp);
log.info("{}, tmp: {}", "tmp", tmp);
log.info("{}, computeSign: {}", "computeSign", computeSign);
long tenTimestamp = timestamp + (10 * 60 * 1000); // 计算10分钟后的时间戳
long currentTimestamp = System.currentTimeMillis(); // 获取当前时间戳
//过期
if(timestamp > currentTimestamp || tenTimestamp < currentTimestamp) {
return CommonResult.error(GlobalErrorCodeConstants.EXPIRE_ERROR);
}
List<String> activeProfile = ProfileUtil.getActiveProfile();
//dev环境不校验签名
if(!activeProfile.contains("dev") && !StringUtils.equals(sign, computeSign.toUpperCase())) {
return CommonResult.error(GlobalErrorCodeConstants.SIGN_ERROR);
}
try {
Method method = this.getClass().getMethod(interfaceName, String.class);
return (CommonResult<String>) method.invoke(this, body);
} catch (NoSuchMethodException e) {
return CommonResult.error(GlobalErrorCodeConstants.INTERFACE_ERROR);
} catch (Exception e) {
return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
}
}
public CommonResult<String> jlht(String body) throws JSchException, IOException {
Session session = shellUtil.getShellSession(shellConfig.getJlht());
String result = shellUtil.execute(session, "cd /opt && ls -l");
return CommonResult.success(result);
}
public CommonResult<String> jlht2(String body) throws JSchException, IOException {
Session session = shellUtil.getShellSession(shellConfig.getJlht2());
String result = shellUtil.execute(session, "cd /opt && ls -l");
return CommonResult.success(result);
}
}

26
src/main/java/com/win/qad/exception/ErrorCode.java

@ -0,0 +1,26 @@
package com.win.qad.exception;
import lombok.Data;
/**
* 错误码对象
* TODO 错误码设计成对象的原因为未来的 i18 国际化做准备
*/
@Data
public class ErrorCode {
/**
* 错误码
*/
private final Integer code;
/**
* 错误提示
*/
private final String msg;
public ErrorCode(Integer code, String message) {
this.code = code;
this.msg = message;
}
}

44
src/main/java/com/win/qad/exception/GlobalErrorCodeConstants.java

@ -0,0 +1,44 @@
package com.win.qad.exception;
/**
* 全局错误码枚举
* 0-999 系统异常编码保留
*
* 一般情况下使用 HTTP 响应状态码 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
* 虽然说HTTP 响应状态码作为业务使用表达能力偏弱但是使用在系统层面还是非常不错的
* 比较特殊的是因为之前一直使用 0 作为成功就不使用 200
*
* @author 闻荫源码
*/
public interface GlobalErrorCodeConstants {
ErrorCode SUCCESS = new ErrorCode(0, "成功");
ErrorCode SIGN_ERROR = new ErrorCode(300, "签名不正确");
ErrorCode TIMESTAMP_ERROR = new ErrorCode(301, "时间戳不正确");
ErrorCode EXPIRE_ERROR = new ErrorCode(302, "请求已过期");
ErrorCode INTERFACE_ERROR = new ErrorCode(303, "接口不正确");
ErrorCode CONFIG_ERROR = new ErrorCode(304, "请先维护推送设置");
ErrorCode SEND_ERROR = new ErrorCode(305, "发送消息失败");
// ========== 客户端错误段 ==========
ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录");
ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限");
ErrorCode NOT_FOUND = new ErrorCode(404, "请求未找到");
ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确");
ErrorCode LOCKED = new ErrorCode(423, "请求失败,请稍后重试"); // 并发请求,不允许
ErrorCode TOO_MANY_REQUESTS = new ErrorCode(429, "请求过于频繁,请稍后重试");
// ========== 服务端错误段 ==========
ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启");
// ========== 自定义错误段 ==========
ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求
ErrorCode DEMO_DENY = new ErrorCode(901, "演示模式,禁止写操作");
ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
}

58
src/main/java/com/win/qad/exception/ServerException.java

@ -0,0 +1,58 @@
package com.win.qad.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 服务器异常 Exception
*/
@Data
@EqualsAndHashCode(callSuper = true)
public final class ServerException extends RuntimeException {
/**
* 全局错误码
*
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 空构造方法避免反序列化问题
*/
public ServerException() {
}
public ServerException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMsg();
}
public ServerException(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public ServerException setCode(Integer code) {
this.code = code;
return this;
}
@Override
public String getMessage() {
return message;
}
public ServerException setMessage(String message) {
this.message = message;
return this;
}
}

58
src/main/java/com/win/qad/exception/ServiceException.java

@ -0,0 +1,58 @@
package com.win.qad.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 业务逻辑异常 Exception
*/
@Data
@EqualsAndHashCode(callSuper = true)
public final class ServiceException extends RuntimeException {
/**
* 业务错误码
*
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 空构造方法避免反序列化问题
*/
public ServiceException() {
}
public ServiceException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMsg();
}
public ServiceException(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public ServiceException setCode(Integer code) {
this.code = code;
return this;
}
@Override
public String getMessage() {
return message;
}
public ServiceException setMessage(String message) {
this.message = message;
return this;
}
}

26
src/main/java/com/win/qad/utils/ProfileUtil.java

@ -0,0 +1,26 @@
package com.win.qad.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class ProfileUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
// 获取当前环境参数 exp: dev,prod,test
public static List<String> getActiveProfile() {
return Arrays.asList(context.getEnvironment().getActiveProfiles());
}
}

69
src/main/java/com/win/qad/utils/shell/ShellUtil.java

@ -0,0 +1,69 @@
package com.win.qad.utils.shell;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
public class ShellUtil {
protected ConcurrentHashMap<String, Session> sessionConcurrentHashMap = new ConcurrentHashMap<>();
public Session getShellSession(ShellVo shellVo) throws JSchException {
Session session = this.sessionConcurrentHashMap.get(shellVo.getQadDomain());
if(session == null || !session.isConnected()) {
session = this.createSession(shellVo);
this.sessionConcurrentHashMap.put(shellVo.getQadDomain(), session);
return session;
} else {
return session;
}
}
public String execute(Session session, String command) throws JSchException, IOException {
// 创建SSH Channel
Channel channel = session.openChannel("exec");
// 执行命令
((ChannelExec)channel).setCommand(command);
channel.connect();
//读取通道的输出
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//存放命令的执行结果,如果结果有很多行,则每次line的值不同
String line;
//result用来拼接line结果
String result = "";
while ((line = reader.readLine()) != null) {
//去除头尾的空格
line.trim();
result = result + line + "\r\n";
}
result = result.substring(0, result.length() - 2);
// 关闭SSH Channel
channel.disconnect();
return result;
}
protected Session createSession(ShellVo shellVo) throws JSchException {
// 创建JSch实例
JSch jsch = new JSch();
// 创建SSH Session
Session session = jsch.getSession(shellVo.getLinuxId(), shellVo.getIp(), shellVo.getPort());
session.setPassword(shellVo.getLinuxPassword());
// 禁用用户信息验证
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// 启动SSH Session
session.connect();
return session;
}
}

32
src/main/java/com/win/qad/utils/shell/ShellVo.java

@ -0,0 +1,32 @@
package com.win.qad.utils.shell;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ShellVo {
private String qadDomain;
private String companyCode;
private String serverId;
private String ip;
private Integer port;
private String linuxId;
private String linuxPassword;
private String qadUser;
private String qadPassword;
}

56
src/main/resources/application-dev.yml

@ -0,0 +1,56 @@
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 18080
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数,默认为100
accept-count: 100
threads:
# tomcat最大线程数,默认为200
max: 100
# Tomcat启动初始化的线程数,默认值10
min-spare: 10
sfms:
username: admin #用户名
password: 123456 #密码
purchase-order: http://localhost:12080/admin-api/wms/purchase-main/create #采购订单
access-token: http://localhost:12080/admin-api/system/oauth2/token #登陆token
refresh-token: http://localhost:12080/admin-api/system/auth/refresh-token #刷新token
logging:
file:
path: logs
level:
com.win: debug
org.springframework: warn
shell:
jlht:
qad-domain: JLHT
company-code: CCWININ
server-id: master
#ip: dev.ccwin-in.com
#port: 23022
#linux-id: root
#linux-password: Microsoft@2022
ip: 222.169.228.163
port: 6122
linux-id: mfg
linux-password: mfgpro
qad-user: mfg
qad-password: Qadwin1
jlht2:
qad-domain: JLHT2
company-code: CCWININ
server-id: master
ip: 222.169.228.163
port: 6122
linux-id: mfg
linux-password: mfgpro
qad-user: mfg
qad-password: Qadwin1

12
src/main/resources/application.yml

@ -0,0 +1,12 @@
spring:
application:
name: win
profiles:
active: dev
main:
allow-bean-definition-overriding: true
servlet:
multipart:
enabled: true
max-file-size: 200MB
max-request-size: 1000MB

108
src/main/resources/logback-spring.xml

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty scope="context" name="logPath" source="logging.file.path" defaultValue="logs"/>
<!-- 日志存放路径 -->
<property name="log.path" value="${logPath}" />
<!--0. 日志格式和颜色渲染 -->
<!-- 彩色日志依赖的渲染类 -->
<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" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.hc" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="error">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
Loading…
Cancel
Save