04 springboot-工程搭建案例(多环境部署,数据源, Swagger, 国际化,工具类)

项目搭建模板(多环境切换)


springboot系列,最近持续更新中,如需要请关注

如果你觉得我分享的内容或者我的努力对你有帮助,或者你只是想表达对我的支持和鼓励,请考虑给我点赞、评论、收藏。您的鼓励是我前进的动力,让我感到非常感激。

文章目录

  • 1 项目截图
  • 2 pom.xml
  • 3 多环境配置
  • 4 国际化配置文件及工具类
    • 4.1 配置文件
    • 4.2 全局异常码
    • 4.3 国际化工具类
    • 4.4 使用
  • 5 其他相关代码
    • 5.1 主类、接口返回结果包装类
    • 5.2 全局异常
    • 5.3 测试类,及数据库测试接口
    • 5.4 swagger配置
    • 5.5 其他工具类

1 项目截图

请添加图片描述

2 pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!-- modelVersion*属性表示使用的POM模型的版本。选择和你正在使用的Maven版本一致的版本即可。版本4.0.0适用于Maven 23 -->
    <modelVersion>4.0.0</modelVersion>

    <groupId>wyh.com</groupId>
    <artifactId>Demo_01_1_SpringBootItemDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <springfox.version>2.8.0</springfox.version>
    </properties>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!--  Spring相关依赖【开始】-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--  Spring相关依赖【结束】-->

        <!-- 添加日志依赖【开始】 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- 添加日志依赖【结束】 -->


        <!-- 添加工具类【开始】 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
        <!-- 添加工具类【结束】 -->

        <!-- swagger2【开始】 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${springfox.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox.version}</version>
        </dependency>
        <!-- swagger2【结束】 -->

        <!-- mysql数据 驱动【开始】 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <!-- mysql数据 驱动【结束】 -->

        <!-- 整合mybatis【开始】-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 整合mybatis【结束】-->
    </dependencies>

    <!-- 多环境配置【开始】 -->
    <profiles>
        <!-- 开发环境环境 -->
        <profile>
            <id>dev</id>
            <properties>
                <package.environment>dev</package.environment>
            </properties>
            <!-- 是否默认 true表示默认-->
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <!-- 测试环境 -->
        <profile>
            <id>test</id>
            <properties>
                <package.environment>test</package.environment>
            </properties>
        </profile>

        <profile>
            <!-- 生产环境 -->
            <id>prod</id>
            <properties>
                <package.environment>prod</package.environment>
            </properties>
        </profile>
    </profiles>
    <!-- 多环境配置【结束】 -->

    <build>
        <!-- 解决application.yml配置文件中@project.version@获取不到问题 -->
        <resources>
            <resource>
                <directory>${basedir}/src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>application.yml</include>
                    <include>application-${package.environment}.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>

        <!-- 解决打成的jar运行报“找不见注类”问题 -->
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>wyh.com.Demo011SpringBootItemDemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

3 多环境配置

application.yml

# APP版本
app:
  version: @project.version@

# 指定执行环境
spring:
  profiles:
    active: @package.environment@
  servlet:
    multipart:
      # 上传文件总的最大值
      max-file-size: 10MB
      # 单个文件的最大值
      max-request-size: 10MB


# 用户初试密码【测试代码读取静态配置时用】
user:
  password: 123456

application-dev.yml 、application-prod.yml、application-test.yml

# 服务配置
server:
  tomcat:
    uri-encoding: UTF-8
    max-threads: 1000
    min-spare-threads: 30
    # 重新设置tomcat服务器允许上传的文件的大小【默认2MB】,解决MultipartException无法捕获的问题
    max-swallow-size: -1
  port: 16001
  servlet:
    context-path: /Demo_01_1_SpringBootItemDemo
  compression:
    enabled: true
    mime-types: application/json
    min-response-size: 8192

# 日志配置
logging:
  config: classpath:logConfig/logback-dev.xml

# 数据源配置
spring:
  datasource:
    name: test
    # 代码中测试案例连接的库
    url: jdbc:mysql://localhost:3306/personal_demo?useTimezone=true&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root123
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    filters: stat
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
  # 解决数据库返回时间时区不一致导致时差问题
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

logConfig 配置 logback-dev.xml、logback-prod.xml、logback-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 定义日志文件 输入位置 -->
    <property name="log_dir" value="D:/00 test"/>
    <!-- 日志最大的历史 6 个月  -->
    <property name="maxHistory" value="6"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n
            </pattern>
        </encoder>
        <target>System.out</target>
    </appender>

    <appender name="SIZEROLLFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n
            </pattern>
        </encoder>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 上环境时修改此路径 -->
            <fileNamePattern>${log_dir}/springboot.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <!-- 输出到指定目录下-->
        <!--<appender-ref ref="SIZEROLLFILE"/>-->
    </root>

    <!-- 修改dao层的日志输出级别 -->
    <logger name="com.huawei.dao" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>

</configuration>

4 国际化配置文件及工具类

4.1 配置文件

messages_en_US.properties

# \u7CFB\u7EDF\u72B6\u6001\u7801 # 系统状态码 ============================================================================================================
error.20000=The request is successful.
error.40000=Param error!
error.50000=System error!

messages_zh_CN.properties

# 系统状态码 ============================================================================================================
error.20000=请求成功.
error.40000=参数错误!
error.50000=系统异常!

4.2 全局异常码

GlobalError

public enum GlobalError {
    // 系统状态码 ====================================================================================================
    SUCCESS(20000),
    PARAM_ERROR(40000),
    EXCEPTION(50000);

    int code;

    GlobalError(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return I18nUtils.getMsgByErrorCode(code);
    }

    public String getMessageWithParams(String supplementMsg) {
        return I18nUtils.getI18nErrorMsg(code, supplementMsg, CookieUtil.getLanguage());
    }

    public String getMessageEnWithParams(String supplementMsg) {
        return I18nUtils.getI18nErrorMsg(code, supplementMsg, Constants.Other.EN);
    }

    public String getMessageCnWithParams(String supplementMsg) {
        return I18nUtils.getI18nErrorMsg(code, supplementMsg, Constants.Other.ZH);
    }
}

4.3 国际化工具类

CookieUtil

public class CookieUtil {
    private static final String ZH = "zh";
    private static final String EN = "en";
    private static final String CN = "cn";
    private static final String US = "us";
    private static final String ZH_CN = "zh_cn";
    private static final String LANG = "lang_key";

    public CookieUtil() {
    }

    public static String getLanguage() {
        return decideLocaleInfoFromCookie("en", "zh");
    }

    public static String getCountry() {
        return decideLocaleInfoFromCookie("us", "cn");
    }

    private static String decideLocaleInfoFromCookie(String defaultEnValue, String cnValue) {
        HttpServletRequest request = getRequest();
        Cookie[] cookies = null;
        if (request != null) {
            cookies = getCookies(request);
        }

        if (cookies != null) {
            Cookie[] var4 = cookies;
            int var5 = cookies.length;

            for (int var6 = 0; var6 < var5; ++var6) {
                Cookie cookie = var4[var6];
                if ("lang_key".equals(cookie.getName()) && "zh_cn".equals(cookie.getValue())) {
                    return cnValue;
                }
            }
        }

        return defaultEnValue;
    }

    public static Cookie[] getCookies(HttpServletRequest request) {
        Cookie[] cookies = null;
        if (request.getCookies() != null) {
            cookies = request.getCookies();
        } else {
            String cookieStr = request.getHeader("cookie");
            if (StringUtils.isNotBlank(cookieStr)) {
                cookies = (Cookie[]) HttpCookie.parse(cookieStr).stream().map((httpCookie) -> {
                    return new Cookie(httpCookie.getName(), httpCookie.getValue());
                }).toArray((x$0) -> {
                    return new Cookie[x$0];
                });
            }
        }

        return cookies;
    }

    public static String getCountryByLanguage(String language) {
        String country = "us";
        if ("zh".equals(language)) {
            country = "cn";
        }

        return country;
    }

    public static HttpServletRequest getRequest() {
        HttpServletRequest request = null;
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        if (attributes != null && attributes instanceof ServletRequestAttributes) {
            request = ((ServletRequestAttributes) attributes).getRequest();
        }

        return request;
    }
}

I18nUtils

@Slf4j
public class I18nUtils {

    public static String getI18nErrorMsg(int code, String supplementMsg, String language) {
        String key = "error." + code;
        String message = getMsgByLanguage(key, language);
        if (StringUtils.isNotEmpty(message)) {
            message = message + " " + supplementMsg;
        }
        return message;
    }

    private static String getMsgByLanguage(String key, String language) {
        String country = getCountryByLanguage(language);

        ResourceBundle bundle = null;
        String value = null;

        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        return getMsg(key, language, country, value, contextClassLoader);
    }

    private static String getMsg(String key, String language, String country, String value, ClassLoader contextClassLoader) {
        ResourceBundle bundle;
        try {
            if (contextClassLoader != null) {
                bundle = ResourceBundle.getBundle("i18/messages", new Locale(language, country), contextClassLoader);
            } else {
                bundle = ResourceBundle.getBundle("i18/message", new Locale(language, country));
            }

            if (bundle != null) {
                value = bundle.getString(key);
            }
        } catch (MissingResourceException var8) {
            log.error("missing resource error !");
        }

        return value;
    }


    private static String getCountryByLanguage(String language) {
        String country = "us";
        if ("zh".equals(language)) {
            country = "cn";
        }

        return country;
    }

    public static String getMsgByErrorCode(int code) {
        ClassLoader classLoader = null;
        if (code > 10000) {
            classLoader = Thread.currentThread().getContextClassLoader();
        }

        String key = "error." + code;

        String language = CookieUtil.getLanguage();

        String country = CookieUtil.getCountry();
        String value = null;

        return getMsg(key, language, country, value, classLoader);
    }
}

Constants

public interface Constants {

    /**
     * The interface Other.
     */
    interface Other {

        /**
         * The constant ZH.
         */
        String ZH = "zh";

        /**
         * The constant EN.
         */
        String EN = "en";
    }
}

4.4 使用

使用测试接口测试即可

  @ApiOperation(value = "Hello测试", notes = "无参数测试")
    @GetMapping("/testMysql")
    public RespResult testMysql(String name, Map reqParam) {
        String testStr = testService.getTestStr();
        return RespResult.resultOK(testStr);
    }

在这里插入图片描述

5 其他相关代码

5.1 主类、接口返回结果包装类

Demo011SpringBootItemDemoApplication

@SpringBootApplication
public class Demo011SpringBootItemDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(Demo011SpringBootItemDemoApplication.class, args);
    }
}

RespResult

@Data
public class RespResult {
    /**
     * The Code.
     */
    int code = RespCodeEnum.SUCCESS.getCode();

    /**
     * The Data.
     */
    Object data;

    /**
     * The Msg.
     */
    String msg;

    /**
     * 处理请求响应正常时方法
     *
     * @param data 返回的数据
     * @return RespResult 数据
     */
    public static RespResult resultOK(Object data) {
        RespResult respResult = new RespResult();
        respResult.data = data == null ? new HashMap<>() : data;
        respResult.msg = GlobalError.SUCCESS.getMessage();
        return respResult;
    }

    /**
     * 处理请求异常时方法
     *
     * @param code 状态码
     * @param msg  异常信息
     * @param data 数据
     * @return RespResult data
     */
    public static RespResult resultFail(int code, String msg, Object data) {
        RespResult respResult = new RespResult();
        respResult.code = code;
        respResult.msg = msg;
        respResult.data = data;
        return respResult;
    }

    /**
     * 处理请求异常时方法
     *
     * @param code 状态码
     * @param msg  异常信息
     * @return RespResult data
     */
    public static RespResult resultFail(int code, String msg) {
        RespResult respResult = new RespResult();
        respResult.data = new HashMap<>();
        respResult.code = code;
        respResult.msg = msg;
        return respResult;
    }
}

RespCodeEnum

/**
 * < 存放请求响应码常量>
 * <p>
 */
public enum RespCodeEnum {
    SUCCESS(200, "The request is successful.", "请求成功."),
    EXP(500, "System error! ", "系统异常!");

    private Integer code;

    private String descEn;

    private String descCn;

    RespCodeEnum(final int code, final String descEn, final String descCn) {
        this.code = code;
        this.descEn = descEn;
        this.descCn = descCn;
    }

    /**
     * <设置code值>
     *
     * @return Integer 数据
     */
    public Integer getCode() {
        return code;
    }

    /**
     * <获取导入校验枚举描述>
     *
     * @return Integer 数据
     */
    public String getDescEn() {
        return descEn;
    }

    /**
     * <获取导入校验枚举描述>
     *
     * @return Integer 数据
     */
    public String getDescCn() {
        return descCn;
    }
}

5.2 全局异常

CommonServiceException

/**
 * 自定义公共异常类
 */
@Data
public class CommonServiceException extends RuntimeException {
    private static final long serialVersionUID = -3387516993124223448L;

    private int errorCode;

    private String errorMsg;

    private String errorMsgEn;

    private String errorMsgCn;

    /**
     * Gets error code.
     *
     * @return the error code
     */
    public int getErrorCode() {
        return GlobalError.EXCEPTION.getCode() == errorCode ? RespCodeEnum.EXP.getCode() : errorCode;
    }

    /**
     * Instantiates a new Common service exception.
     */
    public CommonServiceException() {
        super();
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param msg the msg
     */
    public CommonServiceException(String msg) {
        super(msg);
        this.errorCode = RespCodeEnum.EXP.getCode();
        this.errorMsg = msg;
        this.errorMsgEn = msg;
        this.errorMsgCn = msg;
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param cause the cause
     */
    public CommonServiceException(Throwable cause) {
        super(cause);
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param globalError the ai model error
     * @param cause the cause
     */
    public CommonServiceException(GlobalError globalError, Throwable cause) {
        super(globalError.getMessageEnWithParams(null), cause);
        this.errorCode = globalError.getCode();
        this.errorMsg = globalError.getMessage();
        this.errorMsgEn = globalError.getMessageEnWithParams(null);
        this.errorMsgCn = globalError.getMessageCnWithParams(null);
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param globalError the ai model error
     */
    public CommonServiceException(GlobalError globalError) {
        super(globalError.getMessageEnWithParams(null));
        this.errorCode = globalError.getCode();
        this.errorMsg = globalError.getMessage();
        this.errorMsgEn = globalError.getMessageEnWithParams(null);
        this.errorMsgCn = globalError.getMessageCnWithParams(null);
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param globalError the ai model error
     * @param supplementMsg the supplement msg
     * @param cause the cause
     */
    public CommonServiceException(GlobalError globalError, String supplementMsg, Throwable cause) {
        super(globalError.getMessageEnWithParams(null), cause);
        this.errorCode = globalError.getCode();
        this.errorMsg = globalError.getMessageWithParams(supplementMsg);
        this.errorMsgEn = globalError.getMessageEnWithParams(supplementMsg);
        this.errorMsgCn = globalError.getMessageCnWithParams(supplementMsg);
    }

    /**
     * Instantiates a new Common service exception.
     *
     * @param globalError the ai model error
     * @param supplementMsg the supplement msg
     */
    public CommonServiceException(GlobalError globalError, String supplementMsg) {
        super(globalError.getMessageEnWithParams(null));
        this.errorCode = globalError.getCode();
        this.errorMsg = globalError.getMessageWithParams(supplementMsg);
        this.errorMsgEn = globalError.getMessageEnWithParams(supplementMsg);
        this.errorMsgCn = globalError.getMessageCnWithParams(supplementMsg);
    }
}

GlobalExceptionHandler

/**
 * 全局异常处理器
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 全局所有异常处理器
     *
     * @param exception 异常对象
     * @param request 请求对象
     * @param response 响应对象
     * @return RespResult 返回结果
     */
    @ExceptionHandler( {Exception.class, Error.class})
    @ResponseBody
    public RespResult exceptionHandler(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("contentType", "text/html; charset=utf-8");
        boolean isSensitiveException = isSensitiveException1(exception);
        if (isSensitiveException) {
            LOGGER.error("{} Exception: System Exception", OtherUtils.replaceCRLF(request.getRequestURI()));
            printLocalExceptionInfo(exception);
        } else {
            LOGGER.error("{} Exception: ", OtherUtils.replaceCRLF(request.getRequestURI()), exception);
        }
        if (exception instanceof ServletException) {
            ServletException exp = (ServletException) exception;
            return RespResult.resultFail(RespCodeEnum.EXP.getCode(),
                GlobalError.EXCEPTION.getMessageWithParams(exp.getLocalizedMessage()));
        }
        return RespResult.resultFail(RespCodeEnum.EXP.getCode(), GlobalError.EXCEPTION.getMessage());
    }

    /**
     * 自定义的异常处理器
     *
     * @param exception 异常对象
     * @param request 请求对象
     * @param response 响应对象
     * @return RespResult 返回结果
     */
    @ExceptionHandler( {CommonServiceException.class})
    @ResponseBody
    public RespResult exceptionHandler1(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("contentType", "text/html; charset=utf-8");
        if (exception instanceof CommonServiceException) {
            CommonServiceException commonException = (CommonServiceException) exception;
            Throwable cause = exception.getCause();
            boolean isSensitiveException = isSensitiveException1(cause);
            if (isSensitiveException) {
                LOGGER.error("{} Exception: System Exception", OtherUtils.replaceCRLF(request.getRequestURI()));
                printLocalExceptionInfo(cause);
            } else {
                LOGGER.error("{} Exception: ", OtherUtils.replaceCRLF(request.getRequestURI()), exception);
            }
            return RespResult.resultFail(commonException.getErrorCode(), commonException.getErrorMsg());
        } else {
            return RespResult.resultFail(RespCodeEnum.EXP.getCode(), GlobalError.EXCEPTION.getMessage());
        }
    }

    private boolean isSensitiveException1(Throwable cause) {
        /*if (cause instanceof DataAccessException || cause instanceof SQLException
                || cause instanceof ConcurrentModificationException) {
            return true;
        }*/
        if (cause instanceof FileNotFoundException || cause instanceof JarException || isSensitiveException2(cause)) {
            return true;
        }
        return false;
    }

    private boolean isSensitiveException2(Throwable cause) {
        if (cause instanceof MissingResourceException || cause instanceof NotOwnerException
            || cause instanceof BindException) {
            return true;
        }
        if (cause instanceof OutOfMemoryError || cause instanceof StackOverflowError
            || cause instanceof JSONException) {
            return true;
        }
        if (cause instanceof IllegalArgumentException) {
            return true;
        }
        return false;
    }

    private void printLocalExceptionInfo(Throwable exception) {
        StackTraceElement[] stackTrace = exception.getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if (stackTraceElement.getClassName().startsWith("wyh.com")) {
                LOGGER.error(stackTraceElement.toString());
            }
        }
    }
}

ExceptionUtils

public class ExceptionUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionUtils.class);

    /**
     * 脱敏打印异常
     *
     * @param exp 异常对象
     */
    public static void printExceptionInfo(Throwable exp) {
        if (exp instanceof CommonServiceException) {
            if (exp.getCause() == null) {
                printException(exp);
            } else {
                CommonServiceException commonException = (CommonServiceException) exp;
                Throwable cause = exp.getCause();
                boolean isSensitiveException = isSensitiveException1(cause);
                if (isSensitiveException) {
                    LOGGER.error("Exception: {}", commonException.getErrorMsgEn());
                    printLocalExceptionInfo(commonException);
                } else {
                    printException(commonException);
                }
            }
        } else {
            boolean isSensitiveException = isSensitiveException1(exp);
            if (isSensitiveException) {
                LOGGER.error("Exception: System Exception");
                printLocalExceptionInfo(exp);
            } else {
                printException(exp);
            }
        }
    }

    private static boolean isSensitiveException1(Throwable cause) {
        if (cause instanceof FileNotFoundException || cause instanceof JarException || isSensitiveException2(cause)) {
            return true;
        }
        return cause instanceof DataAccessException || cause instanceof SQLException
            || cause instanceof ConcurrentModificationException;
    }

    private static boolean isSensitiveException2(Throwable cause) {
        if (cause instanceof OutOfMemoryError || cause instanceof StackOverflowError
            || cause instanceof JSONException) {
            return true;
        }
        if (cause instanceof IllegalArgumentException) {
            return true;
        }
        return cause instanceof MissingResourceException || cause instanceof NotOwnerException
            || cause instanceof BindException;
    }

    private static void printLocalExceptionInfo(Throwable exception) {
        StackTraceElement[] stackTrace = exception.getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if (stackTraceElement.getClassName().startsWith("wyh.com")) {
                LOGGER.error(stackTraceElement.toString());
            }
        }
    }

    private static void printException(Throwable exp) {
        LOGGER.error("Exception: {}", exp);
    }
}

5.3 测试类,及数据库测试接口

TestController

@Api(tags = { "Swagger2测试Controller" })
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    /* maven中配置的环境常量 */
    @Value("${app.version}")
    String version;
    @Value("${spring.profiles.active}")
    String packagEnvironment;

    /* 配置文件中自定义的常量 */
    @Value("${user.password}")
    String userPassword;

    @Autowired
    private TestService testService;


    @ApiOperation(value = "Hello测试", notes = "无参数测试")
    @GetMapping("/hello")
    public String hello(String name, Map reqParam) {
        return version + " --- " + packagEnvironment + " --- " + userPassword;
    }


    @ApiOperation(value = "Hello测试", notes = "无参数测试")
    @GetMapping("/testMysql")
    public RespResult testMysql(String name, Map reqParam) {
        String testStr = testService.getTestStr();
        return RespResult.resultOK(testStr);
    }
}

service层

public interface TestService {
    String getTestStr();
}


@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private TestDao testDao;

    @Override
    public String getTestStr() {
        return testDao.getTestStr();
    }
}

TestDao

@Mapper
public interface TestDao {

    String getTestStr();
}

TestDao.xml

<?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="wyh.com.dev.dao.TestDao">

    <select id="getTestStr" resultType="java.lang.String">
        select name from test_user  limit 0,1;
    </select>

</mapper>

5.4 swagger配置

Swagger2Config

@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket allDocket() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("所有模块接口")
            .apiInfo(apiInfo())
            .consumes(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .produces(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .genericModelSubstitutes(ResponseEntity.class)
            .select()
            // 只有标记@ApiOperation才会暴露出给swagger
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            .paths(PathSelectors.regex(".*")) // and by paths
            .build();
    }

    @Bean
    public Docket commonDocket() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("测试组1")
            .apiInfo(apiInfo())
            .consumes(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .produces(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .genericModelSubstitutes(ResponseEntity.class)
            .select()
            // 只有标记@ApiOperation才会暴露出给swagger
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            .paths(PathSelectors.regex("/test1.*")) // and by paths
            .build();
    }

    @Bean
    public Docket officeDocket() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("测试组2")
            .apiInfo(apiInfo())
            .consumes(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .produces(Collections.singleton(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .genericModelSubstitutes(ResponseEntity.class)
            //.genericModelSubstitutes(RespResult2.class)
            .select()
            // 只有标记@ApiOperation才会暴露出给swagger
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            .paths(PathSelectors.regex("/test2.*")) // and by paths
            .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("SpringBoot整合第三方测试API文档")
            .description("RESTful风格接口")
            .termsOfServiceUrl("http://api.wyh.huawei.com")
            .version("1.0.0")
            .build();
    }
}

访问地址:项目访问路径+/swagger-ui.html
例如:http://localhost:16000/Demo_00_1_CreatAndSwagger/swagger-ui.html

5.5 其他工具类

OtherUtils

@Slf4j
public class OtherUtils {

    private static final String COMMAND_WHITE_LIST
            = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890:\\-_./ ";

    public static String replaceCRLF(String message) {
        if (message == null) {
            return "";
        }
        return message.replace('\n', '_').replace('\r', '_');
    }

    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String checkCommand(final String command) {
        if (StringUtils.isBlank(command)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < command.length(); i++) {
            for (int j = 0; j < COMMAND_WHITE_LIST.length(); j++) {
                if (command.charAt(i) == COMMAND_WHITE_LIST.charAt(j)) {
                    sb.append(COMMAND_WHITE_LIST.charAt(j));
                    break;
                }
            }
        }
        return sb.toString();
    }

    public static boolean checkJson(String jsonStr) {
        try {
            if (StringUtils.isNotEmpty(jsonStr)) {
                JSON.parse(jsonStr);
                return true;
            }
        } catch (Exception exp) {
            log.error("The JSON format is abnormal. jsonStr:{}", jsonStr);
        }
        return false;

    }

    public static void deleteFolderAllFile(String path) {
        File folder = new File(path);
        if (!folder.isDirectory()) {
            return;
        }
        File[] files = folder.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                deleteFolder(file);
            } else {
                if (file.delete()) {
                    log.info("delete file success");
                } else {
                    log.error("delete file failure");
                }
            }
        }
    }

    private static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                deleteFolder(file);
            } else {
                if (file.delete()) {
                    log.info("delete file success");
                } else {
                    log.error("delete file failure");
                }
            }
        }
        if (folder.delete()) {
            log.info("delete file success");
        } else {
            log.error("delete file failure");
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/898634.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于CRNN模型的多位数字序列识别的应用【代码+数据集+python环境+GUI系统】

基于CRNN模型的多位数字序列识别的应用【代码数据集python环境GUI系统】 基于CRNN模型的多位数字序列识别的应用【代码数据集python环境GUI系统】 背景意义 多位手写数字识别&#xff0c;即计算机从纸张文档、照片、触摸屏等来源接收并解释可理解的手写数字输入的能力。 随着…

2024软件测试面试秘籍(含答案+文档)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师…

低代码可视化-uniapp海报可视化设计-代码生成

在uni-app中&#xff0c;海报生成器通常是通过集成特定的插件或组件来实现的&#xff0c;这些插件或组件提供了生成海报所需的功能和灵活性。我们采用了lime-painter海报组件。lime-painter是一款canvas海报组件&#xff0c;可以更轻松地生成海报。它支持通过JSON及Template的方…

【Linux】如何升级宝塔面板

执行命令&#xff0c;即可升级 curl https://io.bt.sy/install/update_panel.sh|bash

【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView,快速上手使用

前言 【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView&#xff0c;快速上手使用一、UGUI ScrollRect拓展插件&#xff1a;SuperScrollView1.1 介绍1.2 效果展示1.3 使用说明及下载 二、SuperScrollView 快速上手使用2.1 LoopListView22.2 LoopGridView2.3 LoopStaggered…

【Python爬虫】获取汽车之家车型配置附代码(2024.10)

参考大哥&#xff0c;感谢大哥&#xff1a;https://blog.csdn.net/weixin_43498642/article/details/136896338 【任务目标】 工作需要想更方便地下载汽车之家某车系配置清单&#xff1b;&#xff08;垃圾汽车之家不给下载导出表格&#xff0c;配置页叉掉了车系要出来还要重新…

提问: 监督学习, 无监督学习, 机器学习, 深度学习的关系? (通义千问2.5的回答)

前言: 以下内容由AI大模型通义千问大模型2.5生成 监督学习, 无监督学习, 机器学习, 深度学习的关系? 监督学习、无监督学习、机器学习和深度学习是人工智能领域的几个重要概念&#xff0c;它们之间存在一定的关系和区别。下面我将详细解释这些概念及其相互之间的关系&#xf…

Unity中使用UnityEvent遇到Bug

UnityEvent绑定过程中&#xff0c;放在Start&#xff08;&#xff09;中绑定会报错&#xff08;通过脚本添加UnityEvent事件脚本&#xff0c;绑定&#xff09; 绑定事件放在OnEnable&#xff08;&#xff09;中不会报错&#xff0c;但是依然不可以立刻添加UnityEvent事件脚本紧…

GeoWebCache1.26调用ArcGIS切片

GeoServer GeoWebCache (osgeo.org) 一、版本需要适配&#xff1a;Geoserver与GeoWebCache、jdk等的版本适配对照 ​ 查看来源 二、准备工作 1、数据&#xff1a;Arcgis标准的切片&#xff0c;通过ArcGIS Server发布的切片文件&#xff0c;注意切片的存储格式为exploded&…

rust入门基础总结

文章目录 前言1、输出格式规范一、占位符相关&#xff08;一&#xff09;{}与{:?} 二、参数替换方式&#xff08;一&#xff09;位置参数&#xff08;二&#xff09;具名参数 三、格式化参数&#xff08;一&#xff09;宽度&#xff08;二&#xff09;对齐&#xff08;三&…

电脑异常情况总结

文章目录 笔记本无症状息屏黑屏 笔记本无症状息屏黑屏 &#x1f34e; 问题描述&#xff1a; 息屏导致黑屏&#xff1b;依次操作计算机--》右键--》管理--》事件查看器--》Windows日志--》系统&#xff1b;从息屏到异常黑屏之间出现了很多错误&#xff0c;如下&#xff1a;事件…

如何区别医疗器械唯一标识(UDI)、医用耗材统一标识码(HCBS)和医保医用耗材编码

医疗器械唯一标识&#xff08;UDI&#xff09;、医用耗材统一标识码&#xff08;HCBS&#xff09;和医保医用耗材编码三种重要标识&#xff0c;在医疗领域发挥着举足轻重的作用。 医疗器械唯一标识UDI码是被比喻成医疗器械产品的“身份证”&#xff08;每个人都有&#xff09;…

「AIGC」n8n AI Agent开源的工作流自动化工具

n8n AI Agent 是一个利用大型语言模型(LLMs)来设计和构建智能体(agents)的工具,这些智能体能够执行一系列复杂的任务,如理解指令、模仿类人推理,以及从用户命令中理解隐含意图。n8n AI Agent 的核心在于构建一系列提示(prompts),使 LLM 能够模拟自主行为。 传送门→ …

鸿蒙软件开发中常见的如何快速自动生成二维码?QRCode组件

QRCode 用于显示单个二维码的组件。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 二维码组件的像素点数量与内容有关&#xff0c;当组件尺寸过小时&#xff0c;可能出现无法展示内容的情况&…

电脑输入账号密码后,屏幕黑屏只有鼠标解决办法

最近办公电脑出现了两次输入密码后,屏幕黑屏之后鼠标能动的问题,只能有手机查一些资料尝试自己解决,具体什么原因导致的暂时还不清楚。解决这个问题大概有两个方案吧&#xff0c;第一次黑屏用的第一个方案&#xff0c;第二次发现第一个方案不好用了就用的第二个方案。 方案一 …

【Python-AI篇】人工智能机器学习

1. 机器学习简介 1.1 机器学习流程 获取数据 SKLEARN数据集查看数据分布数据集分类 数据基本处理 缺省值处理缩小数据范围异常数据处理数据分割类别不平衡数据处理方式 特征工程机器学习(算法) K-近邻算法线性回归线性回归的改进-岭回归逻辑回归(分类)决策树朴素贝叶斯SVMEM算…

创建型模式-----(单例模式)

目录 基本概念 饿汉式&#xff1a; 懒汉式&#xff1a; 上锁双判空版本 std::call_once版本&#xff1a; C11标准后局部静态变量版本&#xff1a; 项目中单例模板的应用 基本概念 单例模式&#xff1a;在程序运行期间只有一份&#xff0c;与程序生存周期一样&#xff0c;…

记一行代码顺序引起的事故

01 前情回顾 在这里跟同学们分享一个前几天在线上遇见的 bug… bug描述&#xff1a;客户端轮询服务端接口获取数据做打字机效果展示&#xff0c;会偶现输出到一半就停止不动了&#xff0c;但是数据还没输出完&#xff08;如下图&#xff0c;到红色部分就卡住了&#xff09;。…

【Axure高保真原型】移动案例

今天和大家分享多个常用的移动案例的原型模板&#xff0c;包括轮盘滑动控制元件移动、页面按钮控制元件移动、鼠标单击控制元件移动、元件跟随鼠标移动、鼠标拖动控制元件移动、键盘方向键控制元件移动&#xff0c;具体效果可以点击下方视频观看或打开下方预览地址查看哦 【原…

虚拟装配解决方案:在虚拟现实中实现移动零件与三维模型碰撞检测

装配过程占产品开发时间和成本的很大一部分。在投入生产前对产品装配进行碰撞检测能够有效的降低因设计疏忽所导致的重复试错所导致的成本增加&#xff0c;并进一步降低设计审核整体流程所需时间。 选择、移动和操作3D模型的各个部分 TechViz多通道软件具有通用零件识别引擎&am…