puzhibing
2026-04-10 4f8b07e136c39cc22fbadfd2c869578bb9827a18
还原数据
18个文件已修改
913 ■■■■■ 已修改文件
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/MyLocaleResolver.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/enums/SignatureType.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/dto/FleetAddDTO.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/dto/FleetEditDTO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/FleetPageQuery.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/FleetUserPageQuery.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/IndexDataQuery.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/VehicleTaskRoutineQuery.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetDetailVO.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetPageVO.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetUserVO.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/IndexDataVO.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/QueryPolicyInfoVO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IndexDataService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/HMACSHA1.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/HexUtil.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/ResourceUtil.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/resources/logback.xml.bak 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/MyLocaleResolver.java
@@ -0,0 +1,83 @@
package com.xiaopeng.vehicleConvoy.config;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //1=中文,2=英文,3=印尼文
        //1=Chinese, 2=English, 3=Indonesian.
        String language = getQueryParams(request, "language");
        Locale locale = null;
        if (StringUtils.isEmpty(language)) {
            locale = Locale.getDefault();
            language = "1";
        }
        //如果请求不为空
        //If the request is not empty.
        if(!StringUtils.isEmpty(language)){
            if (language.equals("1")) {
                locale = new Locale("zh", "CN");
            } else if (language.equals("2")) {
                locale = new Locale("en", "US");
            }
        }
        return locale;
    }
    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
    }
    public String getQueryParams(HttpServletRequest request, String key) {
        try {
            String method = request.getMethod();
            if("POST".equals(method)){
                String parameter = request.getParameter(key);
                if(!StringUtils.isEmpty(parameter)){
                    return parameter;
                }
                Object attribute = request.getAttribute(key);
                if(null != attribute){
                    return attribute.toString();
                }
                StringBuffer sb = new StringBuffer();
                ServletInputStream inputStream = request.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                String s;
                while ((s = bufferedReader.readLine()) != null){
                    sb.append(s);
                }
                bufferedReader.close();
                inputStream.close();
                JSONObject jsonObject = JSON.parseObject(sb.toString());
                return jsonObject.getString(key);
            }else{
                String parameter = request.getParameter(key);
                if(!StringUtils.isEmpty(parameter)){
                    return parameter;
                }
                Object attribute = request.getAttribute(key);
                if(null != attribute){
                    return attribute.toString();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/enums/SignatureType.java
@@ -0,0 +1,15 @@
package com.xiaopeng.vehicleConvoy.enums;
/** 签名类型枚举 */
public enum SignatureType {
    MD5("MD5"), SHA1("SHA1"), SHA256("SHA256");
    private String value;
    private SignatureType(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/dto/FleetAddDTO.java
@@ -0,0 +1,40 @@
package com.xiaopeng.vehicleConvoy.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 添加车队DTO
 *
 * @author mitao
 */
@Data
@ApiModel("添加车队数据传输对象")
public class FleetAddDTO {
    @ApiModelProperty(value = "车队名称", required = true)
    @NotBlank(message = "车队名称不能为空")
    private String fleetName;
    @ApiModelProperty(value = "负责人id", required = true)
    @NotNull(message = "负责人id不能为空")
    private Long operationsUserId;
    @ApiModelProperty(value = "打卡地id", required = true)
    @NotNull(message = "打卡地id不能为空")
    private Long locationId;
    @ApiModelProperty(value = "关联车辆ids", required = true)
    @NotEmpty(message = "关联车辆不能为空")
    private List<Long> vehicleIds;
    @ApiModelProperty(value = "关联人员ids", required = true)
    @NotEmpty(message = "关联人员不能为空")
    private List<Long> operationsUserIds;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/dto/FleetEditDTO.java
@@ -0,0 +1,33 @@
package com.xiaopeng.vehicleConvoy.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
 * 编辑车队DTO
 *
 * @author mitao
 */
@Data
@ApiModel("编辑车队数据传输对象")
public class FleetEditDTO {
    @ApiModelProperty(value = "车队id", required = true)
    @NotNull(message = "车队id不能为空")
    private Long id;
    @ApiModelProperty(value = "车队名称", required = true)
    @NotBlank(message = "车队名称不能为空")
    private String fleetName;
    @ApiModelProperty(value = "负责人id", required = true)
    @NotNull(message = "负责人id不能为空")
    private Long operationsUserId;
    @ApiModelProperty(value = "打卡地ID")
    private Long locationId;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/FleetPageQuery.java
@@ -0,0 +1,24 @@
package com.xiaopeng.vehicleConvoy.model.query;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 车队分页查询参数
 *
 * @author mitao
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "车队分页查询参数")
public class FleetPageQuery extends BasePage {
    @ApiModelProperty(value = "车队名称")
    private String fleetName;
    @ApiModelProperty(value = "负责人电话")
    private String phoneNumber;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/FleetUserPageQuery.java
@@ -0,0 +1,30 @@
package com.xiaopeng.vehicleConvoy.model.query;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 车队人员分页查询参数
 *
 * @author mitao
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "车队人员分页查询参数")
public class FleetUserPageQuery extends BasePage {
    @ApiModelProperty(value = "车队id")
    private Long fleetId;
    @ApiModelProperty(value = "人员姓名")
    private String nickName;
    @ApiModelProperty(value = "电话")
    private String phone;
    @ApiModelProperty(value = "角色ID")
    private Long roleId;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/IndexDataQuery.java
@@ -0,0 +1,30 @@
package com.xiaopeng.vehicleConvoy.model.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/**
 * 首页数据查询参数
 *
 * @author mitao
 */
@Data
@ApiModel(value = "首页数据查询参数")
public class IndexDataQuery {
    @ApiModelProperty(value = "今日运行情况-查询日期(默认当天)")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate runningDate;
    @ApiModelProperty(value = "运营增长数据-开始日期(默认当天)")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate growthStartDate;
    @ApiModelProperty(value = "运营增长数据-结束日期(默认当天)")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate growthEndDate;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/query/VehicleTaskRoutineQuery.java
@@ -0,0 +1,33 @@
package com.xiaopeng.vehicleConvoy.model.query;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
/**
 * 车辆年检记录分页查询参数
 *
 * @author mitao
 */
@Data
@ApiModel(value = "车辆年检记录分页查询参数")
public class VehicleTaskRoutineQuery extends BasePage {
    @ApiModelProperty(value = "车辆id", required = true)
    private Long vehicleId;
    @ApiModelProperty(value = "操作人")
    private String operationsUserName;
    @ApiModelProperty(value = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate startTime;
    @ApiModelProperty(value = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate endTime;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetDetailVO.java
@@ -0,0 +1,56 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * 车队详情视图对象
 *
 * @author mitao
 */
@Data
@ApiModel("车队详情视图对象")
public class FleetDetailVO {
    @ApiModelProperty(value = "车队id")
    private Long id;
    @ApiModelProperty(value = "车队名称")
    private String fleetName;
    @ApiModelProperty(value = "负责人id")
    private Long operationsUserId;
    @ApiModelProperty(value = "负责人姓名")
    private String operationsUserName;
    @ApiModelProperty(value = "负责人-手机号")
    private String phoneNumber;
    @ApiModelProperty(value = "打卡地id")
    private Long locationId;
    @ApiModelProperty(value = "打卡地名称")
    private String locationName;
    @ApiModelProperty(value = "电子围栏id")
    private Long electronicId;
    @ApiModelProperty(value = "人员数量")
    private Integer userCount;
    @ApiModelProperty(value = "车辆数量")
    private Integer vehicleCount;
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime updateTime;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetPageVO.java
@@ -0,0 +1,57 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * 车队分页列表视图对象
 *
 * @author mitao
 */
@Data
@ApiModel("车队分页列表视图对象")
public class FleetPageVO {
    @ApiModelProperty(value = "车队id")
    private Long id;
    @ApiModelProperty(value = "车队名称")
    private String fleetName;
    @ApiModelProperty(value = "负责人id")
    private Long operationsUserId;
    @ApiModelProperty(value = "负责人姓名")
    private String operationsUserName;
    @ApiModelProperty(value = "关联运营区域")
    private String electronicName;
    @ApiModelProperty(value = "打卡地名称")
    private String locationName;
    @ApiModelProperty(value = "负责人电话")
    private String phoneNumber;
    @ApiModelProperty(value = "人员数量")
    private Integer userCount;
    @ApiModelProperty(value = "车辆数量")
    private Integer vehicleCount;
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "电子围栏id")
    private Long electronicId;
    @ApiModelProperty(value = "打卡地id")
    private Long locationId;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/FleetUserVO.java
@@ -0,0 +1,30 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 车队人员视图对象
 *
 * @author mitao
 */
@Data
@ApiModel("车队人员视图对象")
public class FleetUserVO {
    @ApiModelProperty(value = "人员id")
    private Long userId;
    @ApiModelProperty(value = "人员姓名")
    private String nickName;
    @ApiModelProperty(value = "电话")
    private String phoneNumber;
    @ApiModelProperty(value = "工号")
    private String jobNumber;
    @ApiModelProperty(value = "角色名称")
    private String roleName;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/IndexDataVO.java
@@ -0,0 +1,67 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * 首页数据统计VO
 *
 * @author mitao
 */
@Data
@ApiModel(value = "首页数据统计VO")
public class IndexDataVO {
    // ==================== 今日运行情况 ====================
    @ApiModelProperty(value = "今日运行情况-新增用户数")
    private Long newUserCount;
    @ApiModelProperty(value = "今日运行情况-新增车辆数量")
    private Long vehicleCount;
    @ApiModelProperty(value = "今日运行情况-新增订单数量")
    private Long orderCount;
    // ==================== 运营总数据 ====================
    @ApiModelProperty(value = "运营总数据-用户总数")
    private Long totalUserCount;
    @ApiModelProperty(value = "运营总数据-车队数量")
    private Long fleetCount;
    @ApiModelProperty(value = "运营总数据-车辆数量")
    private Long totalVehicleCount;
    @ApiModelProperty(value = "运营总数据-订单数量")
    private Long totalOrderCount;
    @ApiModelProperty(value = "运营总数据-总交易金额")
    private Long totalMoney;
    @ApiModelProperty(value = "运营总数据-总收入")
    private Long totalIncome;
    // ==================== 运营数据增长 ====================
    @ApiModelProperty(value = "运营数据增长-用户增长数")
    private Long userGrowthCount;
    @ApiModelProperty(value = "运营数据增长-车辆增长数")
    private Long vehicleGrowthCount;
    @ApiModelProperty(value = "运营数据增长-订单增长数")
    private Long orderGrowthCount;
    // ==================== 运营总趋势(近30天) ====================
    @ApiModelProperty(value = "运营总趋势-订单趋势图(近30天每日订单数)")
    private List<Long> orderCountList;
    @ApiModelProperty(value = "运营总趋势-用户注册趋势图(近30天每日用户注册数)")
    private List<Long> userCountList;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/QueryPolicyInfoVO.java
@@ -0,0 +1,19 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "保单审核信息VO")
public class QueryPolicyInfoVO implements Serializable {
    @ApiModelProperty(value = "保单申请状态 0=待申请 1=待审核 2=已通过 3=已驳回")
    private Integer status;
    @ApiModelProperty(value = "保单申请对象")
    private XpPolicyApplicationVO xpPolicyApplicationVO;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IndexDataService.java
@@ -0,0 +1,21 @@
package com.xiaopeng.vehicleConvoy.service;
import com.xiaopeng.vehicleConvoy.model.query.IndexDataQuery;
import com.xiaopeng.vehicleConvoy.model.vo.IndexDataVO;
/**
 * 首页数据统计服务
 *
 * @author mitao
 */
public interface IndexDataService {
    /**
     * 获取首页统计数据
     *
     * @param query 查询参数
     * @return 首页统计数据
     */
    IndexDataVO getIndexData(IndexDataQuery query);
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/HMACSHA1.java
@@ -0,0 +1,35 @@
package com.xiaopeng.vehicleConvoy.util;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HMACSHA1 {
    private static final String MAC_NAME = "HmacSHA1";
    private static final String ENCODING = "UTF-8";
    /**
     * 使用 HMAC-SHA1 签名方法对对encryptText进行签名
     *
     * @param encryptText 被签名的字符串
     * @param encryptKey  密钥
     * @return
     * @throws Exception
     */
    public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception {
        byte[] data = encryptKey.getBytes(ENCODING);
        // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        Mac mac = Mac.getInstance(MAC_NAME);
        SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
        // 生成一个指定 Mac 算法 的 Mac 对象
        // 用给定密钥初始化 Mac 对象
        mac.init(secretKey);
        byte[] text = encryptText.getBytes(ENCODING);
        // 完成 Mac 操作
        return mac.doFinal(text);
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/HexUtil.java
@@ -0,0 +1,36 @@
package com.xiaopeng.vehicleConvoy.util;
import com.xiaopeng.vehicleConvoy.DecodingException;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
/**
 * 与字节16进制相关的工具类<br/>
 */
public class HexUtil {
    /** 将十六进制字符串转成字节数组 */
    public static byte[] toHexBytes(String hexText) {
        try {
            return Hex.decodeHex(hexText.toCharArray());
        } catch (DecoderException e) {
            throw new DecodingException(e);
        }
    }
    /** 将字节数组转成十六进制字符串(字母小写) */
    public static String toLowerCase(byte[] hex) {
        return new String(Hex.encodeHex(hex, true));
    }
    /** 将字节数组转成十六进制字符串(字母大写) */
    public static String toUpperCase(byte[] hex) {
        return new String(Hex.encodeHex(hex, false));
    }
    /** 将字节数组转成整数 */
    public static int hashToInt(byte[] hash) {
        return (int) (hash[3] << 24 | hash[2] << 16 | hash[1] << 8 | hash[0]);
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/ResourceUtil.java
@@ -0,0 +1,82 @@
package com.xiaopeng.vehicleConvoy.util;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
/**
 * 资源工具类
 * @author binghuoliu
 *
 */
public class ResourceUtil {
    /**
     * 读取classpath下的文件<br>
     * 读取classpath下的文件 一般用于读取classpath下的配置文件,注意读取的配置文件路径是相对传入参数clazz的load入路径. 例:<br>
     * ClassTest c1;//假设c1是从/usr/local/classpath/ 载入<br>
     * ClassTest c2;//假设c2是从/home/classpath/ 载入<br>
     * ............<br>
     * loadConfigFile("a.xml",c1.class);//从/usr/local/classpath1/下寻找a.xml<br>
     * loadConfigFile("a.xml",c2.class);//从/home/classpath/下寻找a.xml<br>
     * @param resource 资源路径
     * @param clazz
     * @return InputStream 文件的inputstram,如果找不到则返回null
     */
    @SuppressWarnings("unchecked")
    public static InputStream loadConfigFile(String resource, Class clazz) {
        ClassLoader classLoader = null;
        try {
            Method method = Thread.class.getMethod("getContextClassLoader");
            classLoader = (ClassLoader) method.invoke(Thread.currentThread());
        } catch (Exception e) {
            throw new RuntimeException("loadConfigFile error: ", e);
        }
        if (classLoader == null) {
            classLoader = clazz.getClassLoader();
        }
        try {
            if (classLoader != null) {
                URL url = classLoader.getResource(resource);
                if (url == null) {
                    System.out.println("Can not find resource:" + resource);
                    return null;
                }
                if (url.toString().startsWith("jar:file:")) {
                    System.out.println("Get resource \"" + resource + "\" from jar:\t" + url.toString());
                    return clazz.getResourceAsStream(resource.startsWith("/") ? resource : "/" + resource);
                } else {
                    System.out.println("Get resource \"" + resource + "\" from:\t" + url.toString());
                    return new FileInputStream(new File(url.toURI()));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("loadConfigFile error: ", e);
        }
        return null;
    }
    /**
     * 释放资源(有异常抛出)
     * @param closeable
     * @throws IOException
     */
    public static void close(Closeable closeable) throws IOException {
        if (closeable != null) {
            closeable.close();
        }
    }
    /**
     * 以优雅的形式释放资源(内部吃掉了异常)
     * @param closeable
     */
    public static void closeGracefully(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
            }
        }
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/resources/logback.xml.bak
@@ -0,0 +1,222 @@
<?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">
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使"${}"来使用变量。 -->
    <property name="log.path" value="/data/log/app/ruoyi-account"/>
    <!--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}}"/>
    <!--1. 输出到控制台-->
    <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>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/all.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
        <logger name="org.springframework.web" level="info"/>
        <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
    -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!-- 4  最终的策略:
                 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
    <springProfile name="dev">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
    </springProfile>
    <springProfile name="test">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
    <springProfile name="prod">
        <root level="info">
            <!-- 生产环境最好不配置console写文件 -->
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
</configuration>