IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 1、搭建完整项目工程结构、使用代码生成器开发租房管理模块、整合Swagger进行接口测试、增删改查分页、自动填充封装、统一返回结果、统一异常处理、统一日志处理 -> 正文阅读

[开发测试]1、搭建完整项目工程结构、使用代码生成器开发租房管理模块、整合Swagger进行接口测试、增删改查分页、自动填充封装、统一返回结果、统一异常处理、统一日志处理

目录

一、数据库设计和表

二、搭建后台环境

三、开发租房管理模块(使用代码生成器)

四、整合Swagger进行接口测试(项目不一样,但是过程都一样,模仿着可以实现)https://blog.csdn.net/YyjYsj/article/details/113788709?spm=1001.2014.3001.5501

五、统一返回结果

六、出租者简单分页功能

七、多条件组合查询带分页

八、自动填充封装(有添加和修改方法)

九、统一异常处理

十、统一日志处理


一、数据库设计和表

创建rent_lessor表:

CREATE TABLE `rent_lessor` (
  `id` char(19) NOT NULL COMMENT 'id',
  `openid` varchar(128) DEFAULT NULL COMMENT '微信openid',
  `mobile` varchar(11) DEFAULT '' COMMENT '手机号',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `sex` tinyint(1) unsigned DEFAULT NULL COMMENT '性别 1 男,0 女',
  `age` tinyint(3) unsigned DEFAULT NULL COMMENT '年龄',
  `avatar` varchar(255) DEFAULT NULL COMMENT '用户头像',
  `sign` varchar(100) DEFAULT NULL COMMENT '用户签名',
  `is_disabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否禁用 1(true)已禁用,  0(false)未禁用',
  `is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出租者表';

INSERT INTO `rent_lessor` VALUES ('1','Y15236380001','15236380001','96e79218965eb72c92a549dd5a330112','张三',1,20,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-03 11:13:37','2021-01-03 11:23:44');
INSERT INTO `rent_lessor` VALUES ('2','Y15236380002','15236380002','96e79218965eb72c92a549dd5a330112','李四',0,20,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-04 11:23:37','2021-01-04 11:23:44');
INSERT INTO `rent_lessor` VALUES ('3','Y15236380003','15236380003','96e79218965eb72c92a549dd5a330112','王五',0,20,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-14 11:23:37','2021-01-14 11:23:44');
INSERT INTO `rent_lessor` VALUES ('4','Y15236380004','15236380004','96e79218965eb72c92a549dd5a330112','王三八',1,22,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-17 11:23:37','2021-01-17 11:23:44');
INSERT INTO `rent_lessor` VALUES ('5','Y15236380005','15236380005','96e79218965eb72c92a549dd5a330112','张三丰',1,21,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-25 11:23:37','2021-01-25 11:23:44');
INSERT INTO `rent_lessor` VALUES ('6','Y15236380006','15236380006','96e79218965eb72c92a549dd5a330112','张六六',0,22,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-01-28 11:23:37','2021-01-28 11:23:44');
INSERT INTO `rent_lessor` VALUES ('7','Y15236380007','15236380007','96e79218965eb72c92a549dd5a330112','赵四',1,24,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-02-03 11:23:37','2021-02-03 11:23:44');
INSERT INTO `rent_lessor` VALUES ('8','Y15236380008','15236380008','96e79218965eb72c92a549dd5a330112','迪丽热巴',0,23,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-02-13 11:23:37','2021-02-13 11:23:44');
INSERT INTO `rent_lessor` VALUES ('9','Y15236380009','15236380009','96e79218965eb72c92a549dd5a330112','古力娜扎',0,23,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-02-23 11:23:37','2021-02-23 11:23:44');
INSERT INTO `rent_lessor` VALUES ('10','Y15236380010','15236380010','96e79218965eb72c92a549dd5a330112','马尔扎哈',0,22,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-03-11 11:23:37','2021-03-11 11:23:44');
INSERT INTO `rent_lessor` VALUES ('11','Y15236380011','15236380011','96e79218965eb72c92a549dd5a330112','小东东',1,21,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-03-22 11:23:37','2021-03-22 11:23:44');
INSERT INTO `rent_lessor` VALUES ('12','Y15236380012','15236380012','96e79218965eb72c92a549dd5a330112','小嘻嘻',0,25,'https://fangyuanzulin.oss-cn-beijing.aliyuncs.com/2021/03/05/31f4e1be45744e51b75675201758f59edefault_avatar.jpg',NULL,0,0,'2021-03-23 11:23:37','2021-03-23 11:23:44');

二、搭建后台环境

1、创建父工程rent_parent

2、删除父工程中的src目录,因为不在父工程中写代码,这个目录没有用

3、把父工程中pom.xml文件中的版本改为2.2.1RELEASE,并把父工程的类型改为pom类型(加上pom)

4、引入相关依赖(把下面的pom.xml文件中的所有内容复制到rent_parent中的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>service</module>
        <module>common</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.henu</groupId>
    <artifactId>rent_parent</artifactId>
    <packaging>pom</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>rent_parent</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
        <rent.version>0.0.1-SNAPSHOT</rent.version>
        <mybatis-plus.version>3.0.5</mybatis-plus.version>
        <velocity.version>2.0</velocity.version>
        <swagger.version>2.7.0</swagger.version>

        <aliyun.oss.version>3.10.2</aliyun.oss.version>
        <!--        下面三个是根据阿里云OSS中文档自己加的-->
        <jaxb-api.version>2.3.1</jaxb-api.version>
        <activation.version>1.1.1</activation.version>
        <jaxb-runtime.version>2.3.3</jaxb-runtime.version>

        <jodatime.version>2.10.1</jodatime.version>
        <poi.version>3.17</poi.version>
        <commons-fileupload.version>1.3.1</commons-fileupload.version>
        <commons-io.version>2.6</commons-io.version>
        <httpclient.version>4.5.1</httpclient.version>
        <jwt.version>0.7.0</jwt.version>
        <aliyun-java-sdk-core.version>4.3.3</aliyun-java-sdk-core.version>
        <aliyun-sdk-oss.version>3.1.0</aliyun-sdk-oss.version>
        <aliyun-java-sdk-vod.version>2.15.2</aliyun-java-sdk-vod.version>
        <aliyun-java-vod-upload.version>1.4.11</aliyun-java-vod-upload.version>
        <aliyun-sdk-vod-upload.version>1.4.11</aliyun-sdk-vod-upload.version>
        <fastjson.version>1.2.28</fastjson.version>
        <gson.version>2.8.2</gson.version>
        <json.version>20170516</json.version>
        <commons-dbutils.version>1.7</commons-dbutils.version>
        <canal.client.version>1.1.0</canal.client.version>
        <docker.image.prefix>zx</docker.image.prefix>
        <cloud-alibaba.version>0.2.2.RELEASE</cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--Spring Cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--mybatis-plus 持久层-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>

            <!-- velocity 模板引擎, Mybatis Plus 代码生成器需要 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>${velocity.version}</version>
            </dependency>

            <!--swagger-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <!--swagger ui-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${swagger.version}</version>
            </dependency>

            <!--aliyunOSS-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun.oss.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>${activation.version}</version>
            </dependency>
            <!-- no more than 2.3.3-->
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-runtime</artifactId>
                <version>${jaxb-runtime.version}</version>
            </dependency>

            <!--日期时间工具-->
            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
                <version>${jodatime.version}</version>
            </dependency>

            <!--xls-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>${poi.version}</version>
            </dependency>
            <!--xlsx-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>

            <!--文件上传-->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>${commons-fileupload.version}</version>
            </dependency>

            <!--commons-io-->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons-io.version}</version>
            </dependency>

            <!--httpclient-->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>${httpclient.version}</version>
            </dependency>

            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>${gson.version}</version>
            </dependency>

            <!-- JWT -->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jwt.version}</version>
            </dependency>

            <!--aliyun-->
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-core</artifactId>
                <version>${aliyun-java-sdk-core.version}</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun-sdk-oss.version}</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-vod</artifactId>
                <version>${aliyun-java-sdk-vod.version}</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-vod-upload</artifactId>
                <version>${aliyun-java-vod-upload.version}</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-sdk-vod-upload</artifactId>
                <version>${aliyun-sdk-vod-upload.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.json</groupId>
                <artifactId>json</artifactId>
                <version>${json.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-dbutils</groupId>
                <artifactId>commons-dbutils</artifactId>
                <version>${commons-dbutils.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba.otter</groupId>
                <artifactId>canal.client</artifactId>
                <version>${canal.client.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5、在父工程中创建子模块service

6、删除service模块中的src目录,因为不需要在service模块中写代码,这个目录没有用?

7、将service模块也改为pom类型,并加入相关依赖(service模块需要的依赖)

<!--        前几个暂时用不到,先注释掉,如果不注释掉会报错-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!--        </dependency>-->

        <!--hystrix依赖,主要是用  @HystrixCommand -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>-->
<!--        </dependency>-->

        <!--服务注册-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
<!--        </dependency>-->
        <!--服务调用-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-openfeign</artifactId>-->
<!--        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- velocity 模板引擎, Mybatis Plus 代码生成器需要 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
        </dependency>

        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>

        <!--lombok用来简化实体类:需要安装lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--xls-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

        <!--httpclient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <!--commons-io-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </dependency>
        <!--gson-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!--下面这个是因为在运行时报错加上的,否则会报下面的错:
        Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

8、在service子模块中再创建子子模块,用于写代码

后台环境已经搭建完成了。?

三、开发租房管理模块(使用代码生成器)

包结构如下:(下面每步都是这个包结构的分解)

1、在service_rent模块中的resource目录下创建application.properties配置文件,进行一些配置

# 服务端口
server.port=8001
# 服务名
spring.application.name=service-rent

# 环境设置:dev、test、prod
spring.profiles.active=dev

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/rent?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#返回json的全局时间格式
spring.jackson.default-property-inclusion=non_null
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

2、引入代码生成器的依赖(在service模块的pom.xml文件中已经引入,这一步可以忽略)

3、使用mp提供的代码生成器生成相关代码

代码生成器代码:

package cn.henu.demo;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;

/**
 * @author
 * @since 2018/12/13
 */
public class CodeGenerator {

    @Test
    public void run() {

        // 1、创建代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 2、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");//得到当前模块的路径
        gc.setOutputDir("G:\\IntelliJIDEAProjects\\MyProjects\\rent_parent\\service\\service_rent" + "/src/main/java");//生成的代码最终输出的位置

        gc.setAuthor("testjava");
        gc.setOpen(false); //生成后是否打开资源管理器
        gc.setFileOverride(false); //重新生成时文件是否覆盖
        gc.setServiceName("%sService");	//去掉Service接口的首字母I
        gc.setIdType(IdType.ID_WORKER_STR); //主键策略
        gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
        gc.setSwagger2(true);//开启Swagger2模式

        mpg.setGlobalConfig(gc);

        // 3、数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/rent?serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 4、包配置
        PackageConfig pc = new PackageConfig();
        //cn.henu.rentservice.
        pc.setParent("cn.henu");
        pc.setModuleName("rentservice"); //模块名

        pc.setController("controller");
        pc.setEntity("domain");
        pc.setService("service");
        pc.setMapper("mapper");
        mpg.setPackageInfo(pc);

        // 5、策略配置
        StrategyConfig strategy = new StrategyConfig();
//        strategy.setInclude("rent_lessor","","");如果有多张表,添加多张表的名称
        strategy.setInclude("rent_houseimg");
        strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
        strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀

        strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
        strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

        strategy.setRestControllerStyle(true); //restful api风格控制器
        strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符

        mpg.setStrategy(strategy);

        // 6、执行
        mpg.execute();
    }
}

4、将生成的Controller中的路径修改一下(不改也可以)

5、在实体类上的逻辑删除、创建时间和修改时间上添加注解

6、编写controller(业务逻辑一般都写在service层,这个只是刚开始,后面的都会写在service层。这里面的R需要用到下面的统一返回结果)

package cn.henu.rentservice.controller;

import cn.henu.commonutils.R;
import cn.henu.rentservice.domain.RentLessor;
import cn.henu.rentservice.domain.vo.LessorQuery;
import cn.henu.rentservice.service.RentLessorService;
import cn.henu.servicebase.exceptionhandler.RentException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@Api(description="出租者管理")//这个注解只为了在Swagger测试文档上显示中文注释,有助于查看
//@RestController注解包含@Controller注解和@ResponseBody注解
@RestController//将这个Controller交给Spring管理,返回的数据都是json数据
@RequestMapping("/rentservice/lessor")
@CrossOrigin//解决跨域问题
public class RentLessorController {
    //注入service
    @Autowired
    private RentLessorService lessorService;

    //1、查询出租者表的所有数据
    //rest风格
    //查询:get    添加:post     修改:put      删除:delete
    @ApiOperation(value = "查询所有出租者列表")
    @GetMapping("findAll")
    public R findAllLessor(){
        //调用service的方法实现查询所有出租者的操作
        List<RentLessor> list = lessorService.list(null);
        return R.ok().data("items",list);
    }

    //2、逻辑删除出租者的方法
    @ApiOperation(value = "逻辑删除出租者")
    @DeleteMapping("{id}")//("{id}")表示需要根据id值进行删除,这个id值需要通过浏览器地址栏传递,在下面的@PathVariable注解进行接收
    public R removeLessor(@ApiParam(name = "id", value = "出租者ID", required = true) @PathVariable String id){//@PathVariable 获取路径中id的值
        boolean flag = lessorService.removeById(id);
        if (flag){
            return R.ok();
        }else {
            return R.error();
        }
    }

    //3、分页查询出租者的方法
    //current:当期页
    //limit:每页显示条数
    @ApiOperation(value = "分页查询出租者")
    @GetMapping("pageLessor/{current}/{limit}")
    public R pageListLessor(@ApiParam(name = "current", value = "当期页", required = true) @PathVariable long current,
                            @ApiParam(name = "limit", value = "每页显示条数", required = true) @PathVariable long limit){
        //创建page对象
        Page<RentLessor> pageLessor = new Page<>(current,limit);
        //调用方法实现分页
        //调用方法的时候,底层会进行封装,把分页的所有数据封装到pageLessor对象里面
        lessorService.page(pageLessor,null);

        long total = pageLessor.getTotal();//总记录数
        List<RentLessor> records = pageLessor.getRecords();//每页的数据的list集合
        //两种返回数据的方法
        //方式一
        /*Map map = new HashMap();
        map.put("total",total);
        map.put("rows",records);
        return R.ok().data(map);*/

        //方式二
        return R.ok().data("total",total).data("rows",records);
    }

    //4、多条件查询带分页的方法(这种方式可以实现,但是不常用)
    @ApiOperation(value = "多条件查询带分页(不常用)")
    @GetMapping("pageLessorCondition/{current}/{limit}")
    public R pageLessorCondition(@ApiParam(name = "current", value = "当期页", required = true) @PathVariable long current,
                                   @ApiParam(name = "limit", value = "每页显示条数", required = true) @PathVariable long limit,
                                   LessorQuery lessorQuery){
        //创建page对象
        Page<RentLessor> pageLessor = new Page<>(current,limit);
        //构建条件
        QueryWrapper<RentLessor> wrapper = new QueryWrapper<>();
        //多条件组合查询
        String name = lessorQuery.getName();
        Integer sex = lessorQuery.getSex();
        String wechatid = lessorQuery.getWechatid();
        String phone = lessorQuery.getPhone();
        String begin = lessorQuery.getBegin();
        String end = lessorQuery.getEnd();
        //判断条件值是否为空,如果不为空则拼接条件
        if (!StringUtils.isEmpty(name)){
            //构建条件
            wrapper.like("nickname",name);
        }
        if (!StringUtils.isEmpty(sex)){
            wrapper.eq("sex",sex);
        }
        if (!StringUtils.isEmpty(wechatid)){
            //构建条件
            wrapper.eq("openid",wechatid);
        }
        if (!StringUtils.isEmpty(phone)){
            wrapper.eq("mobile",phone);
        }
        if (!StringUtils.isEmpty(begin)){
            wrapper.ge("gmt_create",begin);
        }
        if (!StringUtils.isEmpty(end)){
            wrapper.le("gmt_modified",end);
        }

        //调用方法实现条件查询分页
        lessorService.page(pageLessor,wrapper);
        long total = pageLessor.getTotal();//总记录数
        List<RentLessor> records = pageLessor.getRecords();//每页的数据的list集合
        return R.ok().data("total",total).data("rows",records);

    }

    //5、多条件查询带分页的方法
    @ApiOperation(value = "多条件查询带分页(常用)")
    @PostMapping("pageLessorCondition/{current}/{limit}")//因为下面使用了@RequestBody注解来取数据,就需要使用POST的提交方式
    public R pageLessorCondition2(@ApiParam(name = "current", value = "当期页", required = true) @PathVariable long current,
                                   @ApiParam(name = "limit", value = "每页显示条数", required = true) @PathVariable long limit,
            /*
             * @ResponseBody的作用是用来返回数据的,主要是返回json数据
             * @RequestBody:使用json形式传递数据,把json数据封装到对应的对象里面。但是如果是@RequestBody,提交方式需要使用POST提交,用GET的话取不到数据。
             * (required = false):表示TeacherQuery teacherQuery的值可以没有,即前端页面中不输入查询条件,也就是查询所有。
             * */
                                   @RequestBody(required = false) LessorQuery lessorQuery){

        //创建page对象
        Page<RentLessor> pageLessor = new Page<>(current,limit);

//        int i = 10/0;//为了测试全局异常和特殊异常而手写的一个异常

        //测试自定义异常
        /*try {
            int i = 10/0;
        }catch (Exception e){
            //执行自定义异常
            throw new RentException(20002,"执行了自定义异常处理...");
        }*/

        //构建条件
        QueryWrapper<RentLessor> wrapper = new QueryWrapper<>();
        //多条件组合查询
        String name = lessorQuery.getName();
        Integer sex = lessorQuery.getSex();
        String wechatid = lessorQuery.getWechatid();
        String phone = lessorQuery.getPhone();
        String begin = lessorQuery.getBegin();
        String end = lessorQuery.getEnd();
        //判断条件值是否为空,如果不为空则拼接条件
        if (!StringUtils.isEmpty(name)){
            //构建条件
            wrapper.like("nickname",name);
        }
        if (!StringUtils.isEmpty(sex)){
            wrapper.eq("sex",sex);
        }
        if (!StringUtils.isEmpty(wechatid)){
            //构建条件
            wrapper.eq("openid",wechatid);
        }
        if (!StringUtils.isEmpty(phone)){
            wrapper.eq("mobile",phone);
        }
        if (!StringUtils.isEmpty(begin)){
            wrapper.ge("gmt_create",begin);
        }
        if (!StringUtils.isEmpty(end)){
            wrapper.le("gmt_modified",end);
        }

        //排序
        wrapper.orderByDesc("gmt_modified");

        //调用方法实现条件查询分页
        lessorService.page(pageLessor,wrapper);
        long total = pageLessor.getTotal();//总记录数
        List<RentLessor> records = pageLessor.getRecords();//每页的数据的list集合
        System.out.println(records);
        return R.ok().data("total",total).data("rows",records);

    }

    //6、添加出租者的方法
    @ApiOperation(value = "添加出租者")
    @PostMapping("addLessor")//因为下面使用了@RequestBody注解来取数据,就需要使用POST的提交方式
    public R addLessor(/*
     * @ResponseBody的作用是用来返回数据的,主要是返回json数据
     * @RequestBody:使用json形式传递数据,把json数据封装到对应的对象里面。但是如果是@RequestBody,提交方式需要使用POST提交,用GET的话取不到数据。
     * (required = false):表示LessorQuery lessorQuery的值可以没有,即前端页面中不输入查询条件,也就是查询所有。
     * */
            @RequestBody RentLessor rentLessor){
        boolean save = lessorService.save(rentLessor);
        if (save){
            return R.ok();
        }else {
            return R.error();
        }

    }

    //7、根据出租者id进行查询
    @ApiOperation(value = "根据出租者id进行查询")
    @GetMapping("getLessor/{id}")
    public R getLessor(@ApiParam(name = "id", value = "房东ID", required = true) @PathVariable String id){
        RentLessor rentLessor = lessorService.getById(id);
        return R.ok().data("lessor",rentLessor);
    }

    //8、房东修改功能
    @ApiOperation(value = "房东修改功能")
    @PostMapping("updateLessor")
    public R updateLessor(@RequestBody RentLessor rentLessor){
        boolean flag = lessorService.updateById(rentLessor);
        if (flag){
            return R.ok();
        }else {
            return R.error();
        }
    }
}

7、创建启动类RentApplication.java

package cn.henu.rentservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EnableDiscoveryClient  //Nacos服务注册
@ComponentScan(basePackages = {"cn.henu"})//组件扫描,扫描所有以 cn.henu 开头的包中的组件
public class RentApplication {
    public static void main(String[] args) {
        SpringApplication.run(RentApplication.class,args);
    }
}

8、创建配置类(由于mapper下只有接口,没有对应的实现类,因此需要写一个MapperScan注解来扫描这些接口。这个MapperScan和其他的一些配置就写在这个配置类中)

package cn.henu.rentservice.config;

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("cn.henu.rentservice.mapper")
public class RentConfig {
    //逻辑删除插件
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

9、运行测试

在启动类上右键运行,等待运行成功后打开浏览器,输入:localhost:8001/rentservice/lessor/findAll?就能查询到所有数据

四、整合Swagger进行接口测试(项目不一样,但是过程都一样,模仿着可以实现)https://blog.csdn.net/YyjYsj/article/details/113788709?spm=1001.2014.3001.5501

五、统一返回结果

1、在common模块中创建一个模块common_utils,专门用来统一返回结果

2、抽取状态码(在common_utils下创建一个包 cn.henu.commonutils,在创建的包下创建一个interface,定义数据返回状态码:成功:20000,失败:20001)

3、创建一个统一结果返回类 R

package cn.henu.commonutils;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

//统一返回结果的类
@Data//会自动生成下面所有字段的get和set方法
public class R {
    @ApiModelProperty(value = "是否成功")
    private Boolean success;

    @ApiModelProperty(value = "返回码")
    private Integer code;

    @ApiModelProperty(value = "返回消息")
    private String message;

    @ApiModelProperty(value = "返回数据")
    private Map<String, Object> data = new HashMap<String, Object>();

    //把构造方法私有化
    private R(){}

    //成功静态方法
    public static R ok(){
        R r = new R();
        r.setSuccess(true);
        r.setCode(ResultCode.SUCCESS);
        r.setMessage("成功");
        return r;
    }

    //失败静态方法
    public static R error(){
        R r = new R();
        r.setSuccess(false);
        r.setCode(ResultCode.ERROR);
        r.setMessage("失败");
        return r;
    }

    public R success(Boolean success){
        this.setSuccess(success);
        return this;//this就是当前对象(r 对象)
    }

    public R message(String message){
        this.setMessage(message);
        return this;
    }

    public R code(Integer code){
        this.setCode(code);
        return this;
    }

    public R data(String key, Object value){
        this.data.put(key, value);
        return this;
    }

    public R data(Map<String, Object> map){
        this.setData(map);
        return this;
    }
}

4、统一返回结果已经创建好了,但是想要使用需要在service模块的pom.xml文件中引入common_utils依赖(引入之后service模块中才能使用统一结果返回)

<dependency>
    <groupId>cn.henu</groupId>
    <artifactId>common_utils</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

六、出租者简单分页功能

1、在service_rent模块中的RentConfig中配置mp分页插件(这个插件在前面已经配置过了)

//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

2、在RentLessorController中编写出租者分页查询的方法(这一步在前面的代码中写过了)

3、启动项目,使用Swagger进行测试

七、多条件组合查询带分页

1、创建一个VO类,用于封装条件查询的条件值,方便把对象传递到接口中

package cn.henu.rentservice.domain.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class LessorQuery {
    @ApiModelProperty(value = "房东名称,模糊查询")
    private String name;

    @ApiModelProperty(value = "性别 1男 0女")
    private Integer sex;

    @ApiModelProperty(value = "微信号")
    private String wechatid;

    @ApiModelProperty(value = "手机号")
    private String phone;

    @ApiModelProperty(value = "查询开始时间", example = "2019-01-01 10:10:10")
    private String begin;//注意,这里使用的是String类型,前端传过来的数据无需进行类型转换

    @ApiModelProperty(value = "查询结束时间", example = "2019-12-01 10:10:10")
    private String end;
}

2、根据条件值进行判断,拼接条件。有常用和不常用两种方法(这些代码在前面写过了)

3、运行,打开Swagger进行测试,测试两种方法,都可以成功实现

八、自动填充封装(有添加和修改方法)

添加出租者数据:

1、在实体类上的开始时间和结束时间属性上加上自动填充注解(这一步在上面已经加过了)

2、在service_base模块中创建包handler,创建自动填充类MyMetaObjectHandler实现MetaObjectHandler接口

package cn.henu.servicebase.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component//注意在这个类上加@Component注解,或者@Service或者@Repository表示将这个类交给Spring进行管理
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        //实体类中的属性名,不是数据库表中的字段名
        this.setFieldValByName("gmtCreate", new Date(), metaObject);
        this.setFieldValByName("gmtModified", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("gmtModified", new Date(), metaObject);
    }
}

3、在RentLessorController中编写添加出租者的方法(这个代码在上面已经写过了)

//6、添加出租者的方法
@ApiOperation(value = "添加出租者")
@PostMapping("addLessor")//因为下面使用了@RequestBody注解来取数据,就需要使用POST的提交方式
public R addLessor(/*
 * @ResponseBody的作用是用来返回数据的,主要是返回json数据
 * @RequestBody:使用json形式传递数据,把json数据封装到对应的对象里面。但是如果是@RequestBody,提交方式需要使用POST提交,用GET的话取不到数据。
 * (required = false):表示LessorQuery lessorQuery的值可以没有,即前端页面中不输入查询条件,也就是查询所有。
 * */
        @RequestBody RentLessor rentLessor){
    boolean save = lessorService.save(rentLessor);
    if (save){
        return R.ok();
    }else {
        return R.error();
    }
}

4、运行,打开Swagger进行测试,注意不填写时间和id,因为时间使用了自动填充,id是数据库自己生成的

修改出租者数据:

1、在RentLessorController中编写修改出租者的方法(这个代码在上面已经写过了)

//7、根据出租者id进行查询
@ApiOperation(value = "根据出租者id进行查询")
@GetMapping("getLessor/{id}")
public R getLessor(@ApiParam(name = "id", value = "房东ID", required = true) @PathVariable String id){
    RentLessor rentLessor = lessorService.getById(id);
    return R.ok().data("lessor",rentLessor);
}

//8、房东修改功能
@ApiOperation(value = "房东修改功能")
@PostMapping("updateLessor")
public R updateLessor(@RequestBody RentLessor rentLessor){
    boolean flag = lessorService.updateById(rentLessor);
    if (flag){
        return R.ok();
    }else {
        return R.error();
    }
}

2、运行,打开Swagger进行测试,注意不填写时间,因为时间使用了自动填充,而id需要填写数据库已经存在的id值,因为是修改数据

九、统一异常处理

(1)全局异常处理

1、在service_base模块中创建包exceptionhandler,在包下再创建全局异常处理类GlobalExceptionHandler.java

package cn.henu.servicebase.exceptionhandler;

import cn.henu.commonutils.ExceptionUtil;
import cn.henu.commonutils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

//统一异常处理
@ControllerAdvice
@Slf4j  //这个注解表示下面这个类要用到logback日志
public class GlobalExceptionHandler {
    //指定当出现什么异常会执行下面这个方法
    //@ExceptionHandler是一个异常处理器,Exception.class表示所有异常都会被处理
    @ExceptionHandler(Exception.class)
    @ResponseBody//为了能够返回数据
    public cn.henu.commonutils.R error(Exception e){
        e.printStackTrace();
        return R.error().message("执行了全局异常处理...");
    }
}

2、将common_utils引入到service_base中,因为在service_base模块中的这个异常处理类需要用到common_utils中的R?

<dependencies>
    <dependency>
        <groupId>cn.henu</groupId>
        <artifactId>common_utils</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

由于在service模块中已经引入过了common_utils依赖,而在service_base模块中又引入了一次common_utils依赖,会造成引入多次,产生冲突,因此将service模块中的common_utils依赖注释掉

(2)特定异常处理

package cn.henu.servicebase.exceptionhandler;

import cn.henu.commonutils.ExceptionUtil;
import cn.henu.commonutils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

//统一异常处理
@ControllerAdvice
@Slf4j  //这个注解表示下面这个类要用到logback日志
public class GlobalExceptionHandler {
    //指定当出现什么异常会执行下面这个方法
    //@ExceptionHandler是一个异常处理器,Exception.class表示所有异常都会被处理
    @ExceptionHandler(Exception.class)
    @ResponseBody//为了能够返回数据
    public cn.henu.commonutils.R error(Exception e){
        e.printStackTrace();
        return R.error().message("执行了全局异常处理...");
    }

    //特定异常
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody//为了能够返回数据
    public R error(ArithmeticException e){
        e.printStackTrace();
        return R.error().message("执行了ArithmeticException异常处理...");
    }
}

(3)自定义异常处理

1、创建自定义异常类,继承RuntimeException

package cn.henu.servicebase.exceptionhandler;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data  //生成get和set方法
@AllArgsConstructor  //生成有参数的构造方法
@NoArgsConstructor  //生成无参数的构造方法
public class RentException extends RuntimeException{
    private Integer code;//状态码
    private String msg;//异常信息

    @Override
    public String toString() {
        return "RentException{" +
                "code=" + code +
                ", msg='" + this.getMessage() + '\'' +
                '}';
    }
}

2、在GlobalException类中添加规则

//自定义异常
//@ExceptionHandler是一个异常处理器,Exception.class表示所有异常都会被处理
@ExceptionHandler(RentException.class)
@ResponseBody//为了能够返回数据
public R error(RentException e){
//    log.error(e.getMessage());//把错误信息写到 G:/IntelliJIDEAProjects/guli_log/log_error.log 文件中
//    log.error(ExceptionUtil.getMessage(e));//将详细的错误信息写到 G:/IntelliJIDEAProjects/guli_log/log_error.log 文件中(用到了异常工具类 ExceptionUtil.java)
    e.printStackTrace();
    return R.error().code(e.getCode()).message(e.getMsg());
}

3、手动抛出自定义异常

4、运行,在Swagger中进行测试

十、统一日志处理

1、设置当前项目的日志级别

# 设置当前项目的日志级别(这种方式只能在控制台输出日志信息)
# OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
logging.level.root=INFO

2、使用Logback日志工具可以将日志信息不仅输出到控制台,还能输出到指定文件中

2.1、注释掉application.properties配置文件中关于日志的配置

2.2、在resources下创建 logback-spring.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="10 seconds">
    <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
    <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
    <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->

    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="G:/IntelliJIDEAProjects/guli_log" />

    <!-- 彩色日志 -->
    <!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
    <!-- magenta:洋红 -->
    <!-- boldMagenta:粗红-->
    <!-- cyan:青色 -->
    <!-- white:白色 -->
    <!-- magenta:洋红 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>

    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--输出到文件-->
    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_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}/info/log-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>

    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_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}/warn/log-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>

    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_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}/error/log-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>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
        <logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              如果未设置此属性,那么当前logger将会继承上级的级别。
    -->
    <!--
        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
        第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
        第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
     -->
    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <!--可以输出项目中的debug日志,包括mybatis的sql日志-->
        <logger name="com.guli" level="INFO" />
        <!--
            root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
            level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
            可以包含零个或多个appender元素。
        -->
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
        </root>
    </springProfile>

    <!--生产环境:输出到文件-->
    <springProfile name="pro">

        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="WARN_FILE" />
        </root>
    </springProfile>
</configuration>

3、如果程序运行出现异常,把异常信息也输出到文件中

3.1、在全局异常处理类上加一个注解,表示这个类要用到logback日志

3.2、在具体的代码上加上一段代码

4、如果想要将更详细的错误信息输出到文件中,就做下面的配置(不需要)

4.1、在common_utils模块下创建一个异常类

package cn.henu.commonutils;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

//异常工具类,将日志堆栈信息输出到文件
public class ExceptionUtil {

    public static String getMessage(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
        return sw.toString();
    }
}

4.2、调用

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-07-07 00:07:16  更:2021-07-07 00:07:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 18:55:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码