当前位置: 首页 > news >正文

【SpringBoot】使用IDEA创建SpringBoot项目

1、使用SpringBoot脚手架创建

我们使用SpringBoot的脚手架Spring Initializr创建,如图所示:
在这里插入图片描述

2、选择SpringBoot版本

最开始做项目时候,组长说创建一个 springboot 2.5.4 的项目,mysql使用 5.6.X ,maven使用是3.6.X。其实最开始我也没有多想,直接照做了,但是后面回想自己平时看到的SpringBoot开源代码,有的是使用的是2.5.X,有的是使用2.6.X,还有的是使用2.7.X版本的,除了3以上版本在实际开发中没有见过,目前2版本的见到的太多版本号不一样的了。难道只要是2版本,都可以随意使用?当然我们知道不同的版本肯定是有差异的,每个版本都存在一些bug,后面的版本会对前一个版本进行修护和升级,也有一些方法,规则的调整。

所以说,如果要是一个人开发,只要你不用到每个框架版本的新特性,使用一些常规的操作,其实也不用太关注版本,但是实际情况是,往往后端不是你一个人在开发,要是每个人版本都不一样,万一出现了什么bug,排查起来也会比统一版本的情况下排查减少很多不必要的麻烦。所以开发中项目指定版本这里存在两个目的,一个是:统一版本,方便管理(跟每家公司有自己的代码规约一样,遵守就行了),第二个目的,降低风险,不使用版本太高的框架,且往往使用常用的框架版本进行开发,开发环境也比较熟悉。当然最后还有一个,多看看官网,多了解一些框架的不同版本特性,也有助于自己开发。

2.1 推荐选择2.7.x版本开发

spring2.X版本在2023年11月24日停止维护了,因此创建spring项目时不再有2.X版本的选项,只能从3.1.X版本开始选择而Spring3.X版本不支持JDK8,JDK11,最低支持JDK17,因此JDK8也无法选择了,如图所示:
在这里插入图片描述
当然,停止维护只代表我们无法用idea主动创建spring2.X版本的项目了,不代表我们无法使用。目前阿里云还是支持创建Spring2.X版本的项目的,修改Server URL为https://start.aliyun.com,如图所示:
在这里插入图片描述

现在可以创建项目了,如图所示:
在这里插入图片描述

点击Next,建议选择2.7.x版本,并且根据项目需求添加依赖如图所示:
在这里插入图片描述
常用的依赖说明一下:

  • Lombok : 需要我们先安装Lombok插件,可以简化实体类书写;
  • String Web:添加项目的web支持,比如内置的Tomcat等;
  • MySQL Driver:我们用到MySQL数据库,所以添加MySQL相关驱动
  • MyBatis Framework:我们用到MyBatis这一ORM框架操作数据库;
  • JDBC API:Spring对JDBC的封装,如JdbcTemplate。

至此,简单的SpringBoot项目算创建完成了。

3、配置项目并启动项目

3.1 创建项目结构

1、创建配置文件
项目刚创建完成时,默认的配置文件是application.properties文件,当然我们也可以创建application.yml文件。如果在yml文件中没有输入提示,需要到设置File Types中检查是否设置了ymal文件,如图所示:
在这里插入图片描述
2、创建项目结构
在这里插入图片描述
3、配置maven
在这里配置本地Maven本地路径、Maven仓库。在本地Maven的settings.xml中会配置maven的镜像资源等信息。
在这里插入图片描述
4、检查pom.xml文件
特别强调,检查一下pom.xml的中的是否为true,有些情况会默认为true。我们需要将其设置为false,或者去掉该标签,否则在打包的时候会没有程序的入口类mainClass,然后导致无法启动程序:
在这里插入图片描述

4、 下载相关依赖
在这里我们下载之前配置好的依赖,一般项目创建后会默认下载
在这里插入图片描述
5、 配置基础内容
在配置文件中配置一些基本的内容:

server:port: 8080  # 端口号servlet:context-path: /myspringboot001   #项目根路径(前面必须加/)spring:# 项目名称application:name: my-spring-boot001# Mysql配置datasource:driver-class-name:  com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3307/my-springboot-001?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8username: rootpassword: root1998# Mybatis配置
mybatis:mapper-locations: classpath:mappers/*.xml #指定Mybatis的Mapper文件type-aliases-package: com.example.myspringboot001.*.entity  #指定Mybatis的实体目录

6、 配置Mybatis包扫描路径
我们在启动类上配置Mybatis的包扫描路径,用注解@MapperScan

@SpringBootApplication
@MapperScan(value = {"com.example.myspringboot001.**.mapper"})
public class MySpringboot001Application {public static void main(String[] args) {SpringApplication.run(MySpringboot001Application.class, args);}}

以上配置好之后,我们就可以启动springboot项目。浏览器输入:http://localhost:8080/myspringboot001/ 后出现如下内容,说明项目启动成功,如图所示:
在这里插入图片描述

4、配置多环境

在实际开发中,我们一般都会有好几套运行环境。比如开发环境、测试环境、生产环境等等
我们不可能每次都去修改一个配置文件,这就显得很麻烦。下面我们主要说一说怎么配置多环境。

1、 修改application.yml配置文件

spring:# 项目名称application:name: my-spring-boot001# 当前配置文件profiles:active: dev

2、创建多环境配置文件
在这里插入图片描述
上面的配置,项目在启动的时候就会加载application.yml(主)和application-dev.yml(副)配置文件。

注意:如果主配置文件和副配置文件的配置项冲突的时候,会优先使用副配置文件的配置项。

5、连接数据库查询数据

5.1 新建数据库my-springboot-001并且创建sys_user表
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (`id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键id',`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',`nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户密码',`sex` enum('1','2') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户性别',`birthday` date NULL DEFAULT NULL COMMENT '用户生日',`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户邮箱',`phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户电话',`addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户地址',`stop_flag` enum('1','0') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户启用标志',`create_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '用户创建时间',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '用户更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;INSERT INTO `sys_user` VALUES (1, 'xiezhr', '程序员小凡', '12345678', '1', '1999-09-19', 'xiezhr@qq.com', '13288888888', '云南省昆明市', '0', '2023-09-04 21:08:32', NULL);
INSERT INTO `sys_user` VALUES (2, 'xiaoqi', '程序员晓柒', '123456', '1', '2020-10-04', 'xiaoqi@163.com', '13288888888', '云南文山', '0', '2023-09-04 21:09:42', NULL);
INSERT INTO `sys_user` VALUES (3, 'xiaodeng', '财务小邓', '123456', '2', '2019-09-04', 'xiaodeng@qq.com', '13588888888', '云南文山', '0', '2023-09-04 21:10:43', NULL);

执行结果如图所示:
在这里插入图片描述

5.2 创建实体类
@Data
public class SysUser implements Serializable {private static final long serialVersionUID = 123456789L;/*** 主键id*/private Integer id;/*** 用户名*/private String username;/*** 用户昵称*/private String nickname;/*** 用户密码*/private String password;/*** 用户性别*/private String sex;/*** 用户生日*/private Date birthday;/*** 用户邮箱*/private String email;/*** 用户电话*/private String phone;/*** 用户地址*/private String addr;/*** 用户启用标志*/private String stopFlag;/*** 用户创建时间*/private Date createTime;/*** 用户更新时间*/private Date updateTime;}
5.3 创建Mapper接口

数据访问对象,是MVC架构中负责与数据库进行交互的组件。它封装了数据库的访问操作,提供给Service层调用。Dao层通常包含一系列方法,用于对数据库进行增删改查操作,以及与数据库的连接、事务管理等。@Mapper表示这个接口是一个MyBatis的Mapper接口,用于定义数据库操作的方法。

@Mapper
public interface SysUserMapper {/*** 查询所有用户信息* @return  所有用户信息*/List<SysUser> querySysUserList();
}
5.4 创建Mybatis的xml文件

MyBatis的映射文件(mapper),用于操作数据库中的sys_user表。其中定义了一个resultMap用于映射查询结果到SysUser对象,还定义了一个select语句用于查询sys_user表中的所有用户信息。 id=“querySyserList” 必须与mapper接口中方法名一致。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.myspringboot001.system.mapper.SysUserMapper"><resultMap type="com.example.myspringboot001.system.entity.SysUser" id="SysUserMap"><result property="id" column="id" jdbcType="INTEGER"/><result property="username" column="username" jdbcType="VARCHAR"/><result property="nickname" column="nickname" jdbcType="VARCHAR"/><result property="password" column="password" jdbcType="VARCHAR"/><result property="sex" column="sex" jdbcType="VARCHAR"/><result property="birthday" column="birthday" jdbcType="TIMESTAMP"/><result property="email" column="email" jdbcType="VARCHAR"/><result property="phone" column="phone" jdbcType="VARCHAR"/><result property="addr" column="addr" jdbcType="VARCHAR"/><result property="stopFlag" column="stop_flag" jdbcType="VARCHAR"/><result property="createTime" column="create_time" jdbcType="TIMESTAMP"/><result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/></resultMap><!--查询所有用户信息--><select id="querySysUserList" resultMap="SysUserMap">select * from sys_user</select>
</mapper>

这里需要注意的是,IDEA在创建Mybatis的Mapper XML文件时,是没有头部信息,往往我们需要去复制过来,这就会很麻烦,我们可以自定义Mybatis Mapper XML文件模板,这样我们创建Mapper XML时就会有头部信息了如图所示:
在这里插入图片描述
然后我们在新建文件时选择Mybatis Mapper XML就可以了,如图:
在这里插入图片描述

5.5 创建Service接口及实现类

Service是MVC架构中负责处理业务逻辑的组件。它封装了业务逻辑的实现细节,提供给Controller调用。Service层通常包含一系列方法,用于处理各种业务需求,如数据处理、事务管理、业务规则校验等。

1、创建SysUserService接口

public interface SysUserService {/*** 查询所有用户信息* @return  所有用户信息*/List<SysUser> querySysUserList();
}

2、创建SysUserServiceImpl实现类

@Service
public class SysUserServiceImpl implements SysUserService {@Resourceprivate SysUserMapper userMapper;@Overridepublic List<SysUser> querySysUserList() {return userMapper.querySysUserList();}
}
5.6 创建Controller

Controller是MVC架构中负责接收用户请求并处理的组件。它接收来自用户的请求,并根据请求的内容调用相应的Service方法进行业务处理,然后返回结果给用户。Controller通常负责路由请求、参数验证、调用Service等操作。

1、创建SysUserController

@RestController
@RequestMapping("/sysUser")
public class SysUserController {@Autowiredprivate SysUserService sysUserService;/*** 查询所有用户信息* @return*/@RequestMapping(value = "/querySysUser",method = RequestMethod.GET)public List<SysUser> querySysUser(){return sysUserService.querySysUserList();}
}

到此我们三大组件的代码都写完了,接下来我们来看看我们写好的接口,PostMan地址栏输入:http://localhost:8080/myspringboot001/sysUser/querySysUser,如图所示:
在这里插入图片描述
我们可以看到返回的时间格式是"2020-10-03T16:00:00.000+00:00"这样的,可读性很差。其实呢,日期格式化非常简单,我们只需要在之前定义好的实体类SysUser的日期属性上加上一个注解**@JsonFormat**即可:

import com.fasterxml.jackson.annotation.JsonFormat;@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;

我们来测试一下,通过格式化的日期就是我们习惯的日期格式了,如图所示:
在这里插入图片描述

6、封装统一结果返回

为了保证所有接口返回的数据格式一致,减少重复代码编写。我们将对返回结果进行统一处理。
具体返回结果格式如下:

{"code": 200, // 状态码,表示请求的处理结果"message": "请求成功", // 状态消息,对请求结果的简要描述"data": { // 数据对象,用于存储具体的返回数据"key1": "value1","key2": "value2"}
}
  • code :表示请求的处理结果,一般采用HTTP状态码或自定义的业务状态码
  • message :对请求结果的简要描述,通常是一个字符串
  • data :用于存储具体的返回数据,可以是一个对象、数组或其他类型的数据
6.1 定义 IResultCode 的接口

它位于com.example.myspringboot001.common包中,可以由不同的类来实现,实现一致且统一的结果码和消息的处理和返回:

public interface IResultCode {/*** 获取状态码* @return  状态码*/String getCode();/*** 获取状态信息* @return  状态信息*/String getMsg();
}
6.2 定义了一个枚举类 ResultCode

定义了一个枚举类 ResultCode ,它实现了 IResultCode 接口,并包含了一些常见的响应码和对应的消息:

public enum ResultCode implements IResultCode, Serializable {SUCCESS("200","成功"),NOT_FOUND("404","未找到"),INTERNAL_SERVER_ERROR("500","服务器内部错误");private String code;private String msg;ResultCode(String code, String msg){this.code = code;this.msg = msg;}@Overridepublic String getCode() {return code;}@Overridepublic String getMsg() {return msg;}
}

定义系统中常见的响应码和对应的消息,用于表示不同的业务场景或操作的执行结果每个枚举常量都包含一个 code 和一个 msg ,分别表示响应码和消息内容枚举常量包括了一些常见的响应码,如 SUCCESS 表示成功, INTERNAL_SERVER_ERROR 服务器内部错误, NOT_FOUND 表示未找到。

6.3 定义统一响应结构体

定义了一个名为 Result 的类,用于表示统一的响应结构体:

@Data
public class Result<T> implements Serializable {private static final long serialVersionUID = 1L;private String code;private String msg;private T data;public static<T>  Result<T> success() {return success(null);}public static<T>  Result<T> success(T data) {Result result = new Result<>();result.setCode(ResultCode.SUCCESS.getCode());result.setMsg(ResultCode.SUCCESS.getMsg());result.setData(data);return result;}public static <T> Result<T> error(String msg) {Result<T> result = new Result<>();result.setCode(ResultCode.ERROR.getCode());result.setMsg(ResultCode.ERROR.getMsg());return result;}
}

到此,统一响应返回我们已经封装好了,我们来改造一下Controller中的代码看看效果。

1、SysUserController未改之前:

@RequestMapping(value = "/querySysUser",method = RequestMethod.GET)
public List<SysUser> querySysUser(){return sysUserService.querySysUserList();
}

2、SysUserController未改之后:

@RequestMapping(value = "/querySysUser",method = RequestMethod.GET)
public Result querySysUser(){return Result.success(sysUserService.querySysUserList());
}

再次测试返回的数据:
在这里插入图片描述

7、定义视图对象VO

从上面的返回结果,我们会发现将密码等敏感信息返回到了前端,这是非常不可取的这时,我们就需要根据前端的需求,灵活地选择需要展示的数据字段。

7.1 定义VO

定义一个需要返回前端的VO

@Data
public class SysUserVo {/*** 用户名*/private String username;/*** 用户昵称*/private String nickname;/*** 用户性别*/private String sex;/*** 用户生日*/@JsonFormat(pattern = "yyyy-MM-dd")private Date birthday;/*** 用户邮箱*/private String email;/*** 用户电话*/private String phone;/*** 用户地址*/private String addr;
}
7.2 service改造

SysUserService改造前

/*** 查询所有用户信息* @return  所有用户信息*/List<SysUser> querySysUserList();

SysUserServiceImpl改造前

@Overridepublic List<SysUser> querySysUserList() {System.out.println(sysUserMapper);return sysUserMapper.querySysUserList();}

SysUserService改造后

/*** 查询所有用户信息* @return  所有用户信息*/List<SysUserVo> querySysUserList();

SysUserServiceImpl改造后

    @Overridepublic List<SysUserVo> querySysUserList() {List<SysUserVo> sysUserVos = new ArrayList<>();List<SysUser> sysUsers = sysUserMapper.querySysUserList();// 将po的值复制到vo中sysUsers.forEach(sysUser -> {SysUserVo vo = new SysUserVo();BeanUtils.copyProperties(sysUser, vo);sysUserVos.add(vo);});return sysUserVos;}

我们再次用postman测试,输入http://localhost:8080/myspringboot001/sysUser/querySysUser,结果如图所示:
在这里插入图片描述

8、统一异常处理

日常开发中,我们处理异常一般都会用到try-catch 、throw和throws 的方式抛出异常。这种方式不仅仅程序员处理麻烦,对用户来说也不太友好我们都希望不用写过多的重复代码处理异常,又能提升用户体验。这时候全局异常处理就显得很便捷很重要了。
Springboot对于异常的处理也做了不错的支持,它提供两个注解供我们使用。

  • @ControllerAdvice注解 :用来开启全局的异常捕获,
  • @ExceptionHandler注解:说明捕获哪些异常,对那些异常进行处理
8.1 添加自定义异常与其他异常返回结果

我们在Result 类中添加如下两个方法来处理自定义异常和其他异常返回结果:

//自定义异常返回的结果
public static <T> Result<T> bussinessErr(BusinessException e) {Result<T> result = new Result<>();result.setCode(e.getErrorCode());result.setMsg(e.getErrorMsg());result.setData(null);return result;
}
//其他异常处理方法返回的结果
public static <T> Result<T> otherErr(ResultCode resultCode) {Result<T> result = new Result<>();result.setCode(resultCode.getCode());result.setMsg(resultCode.getMsg());result.setData(null);return result;
}
8.2 自定义异常类

在com.example.myspringboot001.common.exception包中新建BusinessException异常类:

public class BusinessException  extends RuntimeException{private String errorCode;private String errorMsg;public BusinessException() { }public BusinessException(String errorCode, String errorMsg) {this.errorCode = errorCode;this.errorMsg = errorMsg;}public String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}public String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}}
8.3 全局异常处理

我们自定义一个全局异常处理类,来处理各种异常,包括自己定义的异常和内部异常 。这样可以简化不少代码,不用自己对每个异常都使用try,catch的方式来实现。
在com.example.myspringboot001.common.handler包中新建GlobalExceptionHandler全局异常处理类:

@RestControllerAdvice
public class GlobalExceptionHandler {/*** 处理自定义异常**/@ExceptionHandler(value = BusinessException.class)@ResponseBodypublic<T> Result<T> bizExceptionHandler(BusinessException e) {return Result.bussinessErr(e);}/*** 处理其他异常**/@ExceptionHandler(value = Exception.class)@ResponseBodypublic Result exceptionHandler(Exception e) {return Result.otherErr(ResultCode.ERROR);}}
8.4 测试异常处理

我们在SysUserController 中添加如下代码来测试下异常,看看能不能捕获到:

	@RequestMapping("/getBusinessException")public Result DeException(){throw new BusinessException("400","我出错了");}@RequestMapping("/getException")public Result Exception(){Result result = new Result();int a = 1 / 0;return result;}

在这里插入图片描述
在这里插入图片描述

9、 添加系统日志

日志记录应用程序的运行状态,通过日志开发者可以更好的了解应用程序的运行情况当系统出现bug时,也能通过日志快速定位问题和解决问题。

9.1 常用日志框架

在这里插入图片描述
我们需要需要选择一个日志门面 和日志实现,Spring Boot默认集成了SLF4j 和Logback作为日志实现框架。如果您使用Maven构建项目,通常无需手动添加Logback依赖,因为Spring Boot的起步依赖(starter dependencies)中已经包含了它。

9.2 日志常用配置

1、日志输出分析,如图所示:
在这里插入图片描述

  • 日期时间:精确到毫秒
  • 日志级别:TRACE | DEBUG | INFO | WARN | ERR
  • 进程ID:60236
  • 分隔符:默认以—进行分割
  • 线程名:由中括号括起来,如[ main]
  • Logger名: 一般使用类全限定名
  • 日志内容

2、日志级别
日志级别由低到高如下

TRACE < DEBUG< INFO< WARN < ERROR

如果设置为 WARN ,则低于 WARN 的信息都不会输出 Spring Boot中默认配置是INFO级别。

3、调整日志级别
可以在配置文件application.yml中设置:

logging.level.root=DEBUG

或者在运行Spring Boot应用程序时,通过命令行参数来设置日志级别

java -jar your-application.jar --logging.level.root=DEBUG

4、日志写到文件中
需在application.properties或application.yml配置文件中设置logging.file.pathlogging.file.name属性。

logging:file:path: /myspringboot/log   # 只能指定路径,文件名默认为 spring.log,这里相当于window的 E:myspringbootlogspring.log#name: /myspringboot/log/my.log # 可以指定文件路径和文件名,这里相当于window的 E:myspringbootlogmy.log#name: my.log  使用相对路径,这里相当于window的 E:WorkPlaceIDEAmy-springboot-001my.log

注意:logging.file.path和logging.file.name只能生效一个,在配置了两者的情况下,以logging.file.name的配置为准。

9.3 日志的基本使用

1、使用官方例子

 Logger logger = LoggerFactory.getLogger(SysUserController.class);@Autowiredprivate SysUserService sysUserService;/*** 查询所有用户信息* @return*/@RequestMapping(value = "/querySysUser",method = RequestMethod.GET)public Result querySysUser(){String name = "tanya";logger.info("this name is {}", name);return Result.success(sysUserService.querySysUserList());}

2、使用lombok插件
第一种方法中,每次使用都要创建了一个名为 logger 的Logger对象,使用起来有点繁琐。这里我们引入注解方式实现。使用注解**@Slf4j** 需要安装lombok插件。

@Slf4j
public class SysUserController {@Autowiredprivate SysUserService sysUserService;/*** 查询所有用户信息* @return*/@RequestMapping(value = "/querySysUser",method = RequestMethod.GET)public Result querySysUser(){log.info("this name is {}", name);return Result.success(sysUserService.querySysUserList());}
}

可以用{} 占位符来拼接字符串,而不需要使用+来连接字符串。

9.4 日志高级配置

前面几节说的都是springboot基本日志配置,如果这些都不能满足我们的需求,我们就需要添加logback-spring.xml 官方推荐的配置文件进行配置。

注意:如果同时存在logback.xmllogback-spring.xml,Spring Boot 将会优先选择 logback-spring.xml 作为日志配置。logback.xml多用于非springboot项目;logback-spring.xml只能用于springboot项目,即带有@SpringBootApplication启动程序中才生效,在main或者Junit中依然不生效。并且这两个文件的配置项优先于application.yml的日志配置。

logback-spring.xml 中 配置了两个 分别是

  • 输出到控制台

  • 将日志写到文件中

  • 使用 指定开发/生产环境配置
    参考如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- SpringBoot默认logback的配置 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/><springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
    <property name="LOG_HOME" value="/logs/${APP_NAME}"/><!--1. 输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!-- <withJansi>true</withJansi>--><!--此日志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. 输出到文件  -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 当前记录的日志文档完整路径 --><file>${LOG_HOME}/log.log</file><!--日志文档输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>   <!--这里是超出大小后新建的文件名,并且保存的是分割前面的旧日志,新日志还是在log.log中--><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>5KB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文档保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 临界值过滤器,输出大于INFO级别日志 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter>
    </appender><!-- 开发环境输出至控制台和文件 -->
    <springProfile name="dev"><root level="INFO"><appender-ref ref="CONSOLE"/><appender-ref ref="FILE"/></root>
    </springProfile><!-- 生产环境输出至控制台和文件 -->
    <springProfile name="prod"><root level="INFO"><appender-ref ref="CONSOLE"/><appender-ref ref="FILE"/></root>
    </springProfile>
    

最终完整的项目结构如下:
在这里插入图片描述

相关文章:

【SpringBoot】使用IDEA创建SpringBoot项目

1、使用SpringBoot脚手架创建 我们使用SpringBoot的脚手架Spring Initializr创建&#xff0c;如图所示&#xff1a; 2、选择SpringBoot版本 最开始做项目时候&#xff0c;组长说创建一个 springboot 2.5.4 的项目&#xff0c;mysql使用 5.6.X &#xff0c;maven使用是3.6.X…...

Mysql锁

锁的分类 基于锁的属性分类&#xff1a;共享锁、排它锁。基于锁的粒度分类&#xff1a;表锁、行锁、记录锁、间隙锁、临键锁。基于锁的状态分类&#xff1a;意向共享锁、意向排它锁。 排他锁与任何的锁都不兼容&#xff0c;共享锁仅和共享锁兼容。由于MVCC的存在&#xff0c;…...

深入浅出:PHP中的数据类型全解析

文章目录 引言理解数据类型标量类型整数 (integer)浮点数 (float)布尔值 (boolean)字符串 (string) 复合类型数组 (array)对象 (object)资源 (resource)NULL 特殊类型Callable强制类型转换 实战案例总结与展望参考资料 引言 在编程的世界里&#xff0c;数据类型是构建任何应用…...

030.随机指纹chromium编译-修改windows操作系统版本

一、目标&#xff1a; 1.了解js是如何获取windows版本的。2.如何从c层面修改chromium源码&#xff0c;修改win系统版本 二、js是如何获取windows系统版本&#xff1a; 将下面的js复制到F12控制台 async function detectWindowsVersion() {let userAgent navigator.userAge…...

IP 协议

IP协议 一、介绍1、IP协议2、IPv43、IPv6 二、主要功能三、协议格式1、示意图2、说明 四、网段划分1、介绍2、目的3、方法4、步骤 五、基于类别的IP地址分配方式1、示意图2、范围 六、CIDR1、介绍2、组成3、优点4、示意图 七、子网掩码1、介绍2、功能3、表示方法4、CIDR表示法5…...

【Docker】创建Docker并部署Web站点

要在服务器上创建Docker容器&#xff0c;并在其中部署站点&#xff0c;你可以按照以下步骤操作。我们将以Flask应用为例来说明如何完成这一过程。 1. 准备工作 确保你的服务器已经安装了Docker。如果没有&#xff0c;请根据官方文档安装&#xff1a; Docker 安装指南 2. 创…...

【C语言的奥秘9】数据类型总结

一、数据类型的介绍 数据类型是按被定义变量的性质&#xff0c;表示形式&#xff0c;占据存储空间的多少&#xff0c;构造特点来划分的。在C语言中&#xff0c;数据类型可分为:基本数据类型&#xff0c;构造数据类型&#xff0c;指针类型&#xff0c;空类型四大类。 基本数据类…...

EasyExcel注解使用

上接《Springboot下导入导出excel》&#xff0c;本篇详细介绍 EasyExcel 注解使用。 1. ExcelProperty value&#xff1a;指定写入的列头&#xff0c;如果不指定则使用成员变量的名字作为列头&#xff1b;如果要设置复杂的头&#xff0c;可以为value指定多个值order&#xff…...

什么是多模态和模态

文章目录 前言一、定义1. 模态 (Modal)2. 非模态 (Non-modal) 二、GUI中1. 模态&#xff08;Modal&#xff09;对话框2. 非模态&#xff08;Modeless&#xff09;对话框 三、模态 vs 非模态 的对比四、何时使用模态和非模态对话框&#xff1f;五、Qt 中 exec() 与 show() 的区别…...

【系统架构设计师】真题论文: 论NoSQL数据库技术及其应用(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2018年 试题4)解题思路论文素材参考真题题目(2018年 试题4) 随着互联网 web2.0 网站的兴起,传统关系数据库在应对 web2.0 网站,特别是超大规模和高并发的 web2.0 纯动态 SNS 网站上已经显得力不从心…...

TCP/IP 协议图--计算机网络体系结构分层

计算机网络体系结构分层 计算机网络体系结构分层 不难看出&#xff0c;TCP/IP 与 OSI 在分层模块上稍有区别。OSI 参考模型注重“通信协议必要的功能是什么”&#xff0c;而 TCP/IP 则更强调“在计算机上实现协议应该开发哪种程序”...

【Android】Intent类详解

目录 引言 一、Intent的定义 二、Intent的用途 三、Intent的七大属性 四、Intent的种类 4.1 显式Intent 4.2 隐式Intent 五、代码示例 5.1 activity_intent.xml 5.2 IntentActivity.java 5.3 AndroidManifest.xml 5.4 实现效果 结语 引言 Intent在Android开发…...

【LeetCode刷题之路】64.最小路径和 (动态规划入门)

LeetCode刷题记录 &#x1f310; 我的博客主页&#xff1a;iiiiiankor&#x1f3af; 如果你觉得我的内容对你有帮助&#xff0c;不妨点个赞&#x1f44d;、留个评论✍&#xff0c;或者收藏⭐&#xff0c;让我们一起进步&#xff01;&#x1f4dd; 专栏系列&#xff1a;LeetCode…...

Facebook:筑牢隐私安全堡垒,守护社交净土

在全球社交媒体平台中&#xff0c;Facebook一直是风靡全球的佼佼者。然而&#xff0c;随着数字化信息的迅速膨胀&#xff0c;用户隐私保护的重要性日益凸显。面对用户对数据安全性的高度重视&#xff0c;Facebook致力于通过一系列措施来确保隐私保护&#xff0c;守护每位用户的…...

MongoDB 索引类型详解

MongoDB 索引类型详解 在 MongoDB 中&#xff0c;索引是提高查询效率、优化数据库性能的重要手段。MongoDB 支持多种类型的索引&#xff0c;每种索引类型适用于不同的查询需求和场景。本文将详细介绍 MongoDB 中几种常见的索引类型、示例及其限制。 1. 单字段索引&#xff08…...

国家信息中心单志广:智慧城市转型中的数据要素价值释放

今日&#xff0c;由中国电信集团主办的2024数字科技生态大会数据要素合作论坛在广州市举办。国家发改委国家信息中心信息化和产业发展部主任单志广在论坛发展主旨演讲&#xff1a;智慧城市转型中的数据要素价值释放&#xff0c;主要包括发展新形势、数据新要素、数据新产权、数…...

底层逻辑之:欧拉-拉格朗日方程(Euler-Lagrange equations)变分法(Calculus of Variations)的核心思想

0前言&#xff1a; 0.1 17世纪的泛函&#xff08;Functional&#xff09;分析与变分法&#xff08;Calculus of Variations&#xff09; 在17世纪&#xff0c;数学家们开始遇到一些需要处理函数集合的问题&#xff0c;这些问题涉及到函数的极值、曲线的长度、曲面的面积等。这…...

2024-12-03OpenCV图片处理基础

OpenCV图片处理基础 OpenCV的视频教学&#xff1a;https://www.bilibili.com/video/BV14P411D7MH 1-OpenCV摄像头读取 OpenCV使用摄像头读取图片帧&#xff0c;点击S保存当前帧到指定文件夹&#xff0c;点击Q关闭窗口&#xff0c;点击其他按钮打印按钮的值 要实现这个功能&…...

【汇编语言】标志寄存器(二) —— 标志位驱动的计算:ADC、SBB 和 CMP 的巧妙应用

前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但仅仅从课程的角度出发就太片面了&#xff0c;其实学习汇编语言可以深入理解计算机底层工作原理&#xff0c;提升代码效率&#xff0c;尤其在嵌入式系统和性能优…...

Java刷题训练第一期

个人主页&#xff1a;手握风云 专栏&#xff1a;Java刷题训练营 1. 字符转ASCII码 问题描述&#xff1a;BoBo教KiKi字符常量或字符变量表示的字符在内存中以ASCII码形式存储。BoBo出了一个问题给KiKi&#xff0c;输入一个字符&#xff0c;输出该字符相应的ASCII码。 输入描述…...

【leetcode100】矩阵置零

1、题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用原地算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 2、初始思路 2…...

【MySQL 进阶之路】SQL 优化

6.SQL 性能分析笔记 在现代数据库的高并发环境下&#xff0c;SQL 查询优化成为提升系统性能和响应速度的关键。本文将总结常见的 SQL 优化策略&#xff0c;包括插入优化、主键设计、排序优化、GROUP BY 优化等&#xff0c;帮助你在面对大规模数据时&#xff0c;做到高效查询和…...

本地部署开源趣味艺术画板Paint Board结合内网穿透跨网络多设备在线绘画

文章目录 前言1.关于Paint Board2.本地部署paint-board3.使用Paint Board4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Paint Board公网地址 前言 大家好&#xff0c;是不是每次想要在电脑上画画时&#xff0c;都被那些笨重的专业绘图软件搞得头大如斗呢&#xff1f;…...

位图(bitmap)和布隆过滤器(bloom_filter)

1.位图-Bitmap 1.1问题引入 :给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f; 40亿个无符号整数大约16G的大小&#xff0c;用map或者set显然是无法支持海量数据的存储。那么我们能否不存储数…...

如何使用JDBC向数据库中插入日期数据???

在学习JDBC 的过程中很多小明有疑问在IDEA编辑器是如何插入一个日期类型的数据的&#xff0c;此篇一些方法希望可以帮助到你。 示例&#xff1a; import java.text.ParseException; import java.text.SimpleDateFormat; import java.sql.Date; import java.util.Scanner;publi…...

电子系统设计实验4 信号发生电路设计实验

一、实验目的 1. 掌握正弦信号发生器的设计方法。 2. 掌握方波发生器的设计方法。 二、实验内容及结果 1. 实验内容 设计一用于RFID读卡器测试的幅移键控发生器&#xff08;ASK&#xff09;&#xff0c;其结构如图4-1所示。正弦振荡器输出频率为150kHz&#xff0c;幅度为3V…...

【Docker】Linux与Windows系统安装Docker+Docker上简单安装MySQL

一、Windows安装Docker 由于我在许多平台搜索Windows下安装Docker的方法&#xff0c;都提到了Win10家庭版无法直接安装Docker。个人电脑就是Win10家庭版&#xff0c;本着实践出真知的想法&#xff0c;个人在本机Win10家庭版实验结果为需要采用下述传统手动安装的办法&#xff…...

linux更新镜像源

镜像源地址 1 阿里云 http://mirrors.aliyun.com/ubuntu/ 2 网易源 http://mirrors.163.com/ubuntu/ 3 浙大源 http://mirrors.zju.edu.cn/ubuntu 4 中科大源 http://mirrors.ustc.edu.cn/ubuntu/ 5 清华源 http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ 更新镜像源 此处…...

HarmonyOS 5.0应用开发——UIAbility生命周期

【高心星出品】 文章目录 UIAbility组件创建AbilityUIAbility的生命周期Create状态WindowStageCreate状态Foreground和Background状态WindowStageWillDestroy状态Destroy状态 UIAbility组件 UIAbility组件是一种包含UI的应用组件&#xff0c;主要用于和用户交互。 UIAbility组…...

【Linux】C语言实现简易的Linux shell命令行解释器

我们要实现自己的简易的shel&#xff0c;先了解一下shell运行原理。 1. shell运行原理 shell从用户读入字符串"ls"。shell建立一个子进程&#xff0c;在子进程中运行ls程序并等待进程结束。 然后shell读取新的一行输入&#xff0c;建立一个新的子进程&#xff0c;在…...

构建个人大模型问答助手(基于Streamlit +gpt-4o/o1-mini):全面解析与实现

在当今人工智能迅猛发展的时代&#xff0c;构建一个个人化的大模型问答助手不仅能够提高工作效率&#xff0c;还能为日常生活带来便利。本篇博客将详细解析如何使用Python和Streamlit框架&#xff0c;结合OpenAI的API&#xff0c;搭建一个类似于ChatGPT的问答系统。我们将分步骤…...

10.请求拦截和响应拦截

文章目录 前言前景回顾拦截器应用请求拦截器响应拦截器测试响应拦截器原理 总结 前言 优秀的设计总是少不了丰富的扩展点, 比如spring可以自动装配, aop扩展, web模块也有拦截器, 甚至对servlet的过滤器都有封装; 再比如netty、doubbo等等都支持在数据流入流出都允许用户自定义…...

github使用SSH进行克隆仓库

SSH 密钥拉取git 查询密钥是否存在 s -al ~/.ssh这个文件夹下 known_hosts 就是存在的密钥文件 创建密钥文件 ssh-keygen -t rsa -b 4096 -C "testtt.com"-t rsa 是 rsa 算法加密 -b 是指定密钥的长度&#xff08;以位为单位&#xff09;。 -C 是用于给密钥添加注…...

如何成长为一名工程技术经理

https://medium.com/srivatsan-sridharan/how-to-grow-as-an-engineering-manager-687cad0bcac7 作为一名工程技术经理&#xff0c;你可能已经积累了丰富的团队管理经验&#xff0c;并展示了出色的项目管理、优先级管理和员工指导能力。然而&#xff0c;尽管如此&#xff0c;你…...

前端热门面试题目(四五六七)

1. 使用 import 时&#xff0c;Webpack 如何处理 node_modules 中的依赖&#xff1f; 依赖解析&#xff1a; Webpack 遇到 import 时&#xff0c;利用 resolve 配置查找依赖。如果是第三方依赖&#xff08;node_modules&#xff09;&#xff0c;Webpack 会优先查找其主入口&…...

三、使用 Maven:命令行环境

文章目录 1. 第一节 实验一&#xff1a;根据坐标创建 Maven 工程1.1 Maven 核心概念&#xff1a;坐标1.2 实验操作1.3 Maven核心概念&#xff1a;POM1.4 Maven核心概念&#xff1a;约定的目录结构 2. 实验二&#xff1a;在 Maven 工程中编写代码2.1 主体程序2.2 测试程序 3. 执…...

深度学习在网络管理中的应用:智能化的新时代

网络管理在现代信息技术中占据着举足轻重的地位。随着网络规模的扩大和复杂性的增加&#xff0c;传统的网络管理手段已经无法满足日益增长的需求。深度学习作为人工智能的一个重要分支&#xff0c;通过其强大的数据处理和模式识别能力&#xff0c;为网络管理带来了新的契机。本…...

微信小程序日期格式化报错: iOS 下无法正常使用,iOS 只支持 “yyyy/MM/dd“、“yyyy/MM/dd HH:mm:ss“、“yyyy-

微信小程序日期格式化报错 报错内容解决办法 报错内容 at formatDate (http://127.0.0.1:10118/appservice-hotreload/pages/index/index.js?1;:103:18) new Date(“2024-11-27 15:05:23”) 在部分 iOS 下无法正常使用&#xff0c;iOS 只支持 “yyyy/MM/dd”、“yyyy/MM/dd H…...

第K大数求解方案

思想&#xff1a;利用快速排序的思想&#xff0c;从数组S中随机找出一个元素X&#xff0c;把数组分为两部分Sa和Sb。Sa中的元素大于等于X&#xff0c;Sb中元素小于X。这时有两种情况&#xff1a; 1. Sa中元素的个数小于k&#xff0c;则Sb中的第k-|Sa|个元素即为第k大数&#xf…...

【AI系统】MobileFormer

MobileFormer 在本文中&#xff0c;将介绍一种新的网络-MobileFormer&#xff0c;它实现了 Transformer 全局特征与 CNN 局部特征的融合&#xff0c;在较低的成本内&#xff0c;创造一个高效的网络。通过本节&#xff0c;让大家去了解如何将 CNN 与 Transformer 更好的结合起来…...

《重生之我学VTK》-- 基本介绍与相关概念

目录 简介 可视化模型 示例&#xff08;圆锥体&#xff09; VTK官方用户手册&#xff08;中文C版&#xff09;附末尾&#xff0c;有需要的直接划到末尾 简介 VTK&#xff08;Visualization Toolkit&#xff09;是一个开源的、跨平台的软件系统&#xff0c;主要用于三维计算机图…...

HTML笔记()蜘蛛纸牌之卡牌拖拽

效果 代码 <!DOCTYPE html> <html><head><style>body{display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #2b2b2b;position: relative;}.card{/*设置卡牌的外观*/width: 150px;height: 200px;background-…...

记一次跑前端老项目的问题

记一次跑前端老项目的问题 一、前言二、过程1、下载依赖2、启动项目3、打包 一、前言 在一次跑前端老项目的时候&#xff0c;遇到了一些坑&#xff0c;这里记录一下。 二、过程 1、下载依赖 使用 npm install下载很久&#xff0c;然后给我报了个错 core-js2.6.12: core-js…...

041_Compare_Matrix_Squre_Sum_in_MATLAB中矩阵平方和的比较

矩阵平方和的计算 矩阵平方和的定义 矩阵平方和的定义是对矩阵中的每一个元素进行平方&#xff0c;然后求和。 对于一个矩阵 A A A&#xff0c;其平方和定义为&#xff1a; sum ∑ i 1 m ∑ j 1 n A ( i , j ) 2 \text{sum} \sum_{i1}^{m}\sum_{j1}^{n} A(i,j)^2 sumi1∑…...

vue3中 axios 发送请求 刷新token 封装axios

service.js 页面 import axios from axios // 创建axios实例 const instance axios.create({baseURL: http://gcm-test.jhzhkj.cn:8600/h5card/,timeout: 5000, // 请求超时时间headers: {get: {Content-Type: application/x-www-form-urlencoded},post: {Content-Type: appl…...

vue+mars3d叠加展示arcgis动态服务

数据格式&#xff1a;使用arcgis发布的动态服务 叠加和移除arcgis服务图层的方法 //加载arcgis地图服务function arcgisServer(i,d,m,p){i[d.data] new mars3d.layer.ArcGisLayer({name:d.label,url:p,flyTo: true})m.addLayer(i[d.data])}//移除arcgis服务范围线function rem…...

PostgreSQL 中进行数据导入和导出

在数据库管理中&#xff0c;数据的导入和导出是非常常见的操作。特别是在 PostgreSQL 中&#xff0c;提供了多种工具和方法来实现数据的有效管理。无论是备份数据&#xff0c;还是将数据迁移到其他数据库&#xff0c;或是进行数据分析&#xff0c;掌握数据导入和导出的技巧都是…...

Stable Audio Open模型部署教程:用AI打造独家节拍,让声音焕发新活力!

Stable Audio Open 是一个开源的文本到音频模型&#xff0c;允许用户从简单的文本提示中生成长达 47 秒的高质量音频数据。该模型非常适合创建鼓点、乐器即兴演奏、环境声音、拟音录音和其他用于音乐制作和声音设计的音频样本。用户还可以根据他们的自定义音频数据微调模型&…...

python更新程序并部署服务器服务

本地客户端程序 import json import hashlib import os import shutil import requests from pathlib import Pathclass AutoUpdater:def __init__(self, config_path"http://【XXXIP地址】/update_config"):self.config_path config_pathself.config Nonewith op…...

Nmap 扫描技巧:自定义端口、扫描速度与并行化设置

Nmap 扫描技巧&#xff1a;自定义端口、扫描速度与并行化设置 在进行网络安全扫描时&#xff0c;Nmap 是一个非常强大的工具。除了默认扫描 1000 个端口外&#xff0c;你还可以根据需要自定义扫描的端口、调整扫描速度以及优化扫描并行化。今天&#xff0c;我们就来介绍如何通…...