目录
一、数据库设计和表
二、搭建后台环境
三、开发租房管理模块(使用代码生成器)
四、整合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?就能查询到所有数据
五、统一返回结果
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、调用
|