文章目录
1.技术选型
2.原型设计
1.安装AxureRP
2.进行汉化
3.载入元件库
4.基本设计
3.元数建模
1.安装元数建模软件
2.新建项目
3.新增一个刷题模块主题域
4.新增数据表 subject_category
5.新增关系图,将表拖过来
6.新增题目标签表
7.新增题目信息表
8.新增单选表、多选表、判断题、简答题
9.新增分类、标签、题目关联表
10.关系图预览
4.项目架构分析
1.现有的架构
2.ddd架构
5.mysql采用docker版的主从复制(之前配置过)
1.docker的启动命令
sh
复制代码
docker run -p 3307:3306 --name mysql-master \
-v /mysql5.7/mysql-master/log:/var/log/mysql \
-v /mysql5.7/mysql-master/data:/var/lib/mysql \
-v /mysql5.7/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=******** \
-d mysql:5.7
2.IDEA测试连接
3.主MySQL的连接信息
4.创建数据库sun_club,然后创建表
6.集成Gitee
1.新建仓库
2.克隆到IDEA
7.新建一个sun-club-subject作为父模块
1.新建父模块
2.删除src目录
3.设置整个项目的编码为utf-8
4.在maven的配置部分指定编译版本为java8
xml
复制代码
<!-- maven的配置 -->
<!-- 解决java: -source 1.5 中不支持 diamond 运算符 问题 -->
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
5.在maven的插件配置中指定maven打包的配置
xml
复制代码
<!-- maven打包常规配置 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
8.新建子模块
1.新建api子模块
2.为子模块的parent部分加上relativePath标签(不要加,只有在需要双继承的时候才需要)
3.在maven的配置部分指定编译版本为java8以及maven的打包插件(每个子模块都要加的)
xml
复制代码
<!-- maven的配置 -->
<!-- 解决java: -source 1.5 中不支持 diamond 运算符 问题 -->
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- maven打包常规配置 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.新建application子模块
3.跟上面两个一样的常规配置
4.分别新建common、domain、infra、starter模块并进行常规配置
5.各层次目录结构
1.api层
2.starter层
3.infra层
4.domain层
5.common层
6.application层
新建三个子模块并加上常规配置
7.整体结构一览
6.目录结构调整
1.sun-club-subject-api
2.sun-club-starter
3.sun-club-infra
4.sun-club-domain
5.sun-club-common
6.sun-club-application
9.集成SpringBoot
1.编辑sun-club-subject的pom.xml引入SpringBoot2并配置maven仓库
xml
复制代码
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
2.编辑sun-club-starter的pom.xml引入SpringBoot的starter-web
xml
复制代码
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.2</version>
</dependency>
</dependencies>
3.sun-club-starter模块编写启动类SubjectApplication.java
java
复制代码
package com.sunxiansheng.subject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* Description: 刷题微服务启动类
* @Author sun
* @Create 2024/5/23 16:30
* @Version 1.0
*/
@SpringBootApplication
@ComponentScan("com.sunxiansheng") // 扫描当前模块下的所有包
public class SubjectApplication {
public static void main(String[] args) {
SpringApplication.run(SubjectApplication.class, args);
}
}
4.启动测试
5.sun-club-starter模块创建application.yml对项目进行调整
1.文件内容
2.重启测试
10.集成SpringMVC
1.sun-club-application-controller 引入SpringBoot的starter-web
xml
复制代码
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.2</version>
</dependency>
</dependencies>
2.编写SubjectController.java
java
复制代码
package com.sunxiansheng.subject.application.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Description: 刷题微服务控制器
* @Author sun
* @Create 2024/5/23 16:42
* @Version 1.0
*/
@RestController
public class SubjectController {
@GetMapping("/test")
public String test() {
return "Hello, World!";
}
}
3.sun-club-starter引入sun-club-application-controller模块,使其启动时可以找到
xml
复制代码
<!-- 引入sun-club-application-controller的依赖,则启动这个模块,就能找到 -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-application-controller</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
4.测试访问
11.集成MySQL,Druid,MyBatis
1.sun-club-infra模块添加依赖
xml
复制代码
<dependencies>
<!-- jdbcStarter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.4.2</version>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!-- mybatisplus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
2.EasyCode插件,生成CRUD
1.安装插件
2.选择表,右键选择EasyCode
3.选择代码生成的位置,和需要的文件
4.查看生成的代码
5.删除与Pageable有关的代码
1.SubjectCategoryDao.java
2.SubjectCategoryService.java
3.SubjectCategoryServiceImpl.java
3.sun-club-starter引入sun-club-infra
xml
复制代码
<!-- 引入sun-club-infra -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-infra</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
4.sun-club-starter启动类配置MapperScan,扫描基础设施层的包
5.sun-club-starter配置数据源和监控
- 这里没有配置扫描Mapper.xml的原因是:Mapper和Mapper.xml的名字相同并且位于常规位置,MyBatis会自动扫描
yaml
复制代码
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url:
username:
password:
type: com.alibaba.druid.pool.DruidDataSource # druid连接池
druid:
initial-size: 20 # 初始化连接数
min-idle: 20 # 最小连接数
max-active: 100 # 最大连接数
max-wait: 60000 # 最大等待时间,单位毫秒
stat-view-servlet:
enabled: true # 是否开启监控
url-pattern: /druid/* # 监控路径
login-username: # 登录用户名
login-password: # 登录密码
filter:
stat:
enabled: true # 是否开启慢sql监控
slow-sql-millis: 2000 # 慢sql阈值,单位毫秒
log-slow-sql: true # 是否打印慢sql
wall:
enabled: true # 是否开启防火墙
6.测试
1.sun-club-application-controller 引入sun-club-infra
xml
复制代码
<!-- 引入sun-club-infra -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-infra</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.sun-club-application-controller编写SubjectController.java测试
3.启动测试,成功!
7.使用druid对application.yml中的密码进行加密
1.sun-club-infra编写DruidEncryptUtil.java进行加解密
java
复制代码
package com.sunxiansheng.subject.infra.basic.utils;
import com.alibaba.druid.filter.config.ConfigTools;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
/**
* Description: 使用druid对配置文件中的密码进行加密
* @Author sun
* @Create 2024/5/23 20:22
* @Version 1.0
*/
public class DruidEncryptUtil {
private static String publicKey;
private static String privateKey;
static {
try {
String[] keyPair = ConfigTools.genKeyPair(512);
privateKey = keyPair[0];
System.out.println("privateKey:" + privateKey);
publicKey = keyPair[1];
System.out.println("publicKey:" + publicKey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
}
public static String encrypt(String plainText) throws Exception {
String encrypt = ConfigTools.encrypt(privateKey, plainText);
System.out.println("encrypt:" + encrypt);
return encrypt;
}
public static String decrypt(String encryptText) throws Exception {
String decrypt = ConfigTools.decrypt(publicKey, encryptText);
System.out.println("decrypt:" + decrypt);
return decrypt;
}
public static void main(String[] args) throws Exception {
String encrypt = encrypt("");
System.out.println("encrypt:" + encrypt);
}
}
2.sun-club-starter修改application.yml
8.准备apipost测试工具
1.新建目录
2.刷题模块目录
3.再添加一个题目分类的目录
4.添加一个接口
12.分层架构的业务开发演示
1.引入依赖
1.sun-club-common引入lombok和mapstruct,注意lombok必须放到mapstruct前面
xml
复制代码
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
2.sun-club-infra引入sun-club-common
xml
复制代码
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.sun-club-domain层
1.引入sun-club-infra的依赖
xml
复制代码
<!-- 引入sun-club-infra -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-infra</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.创建SubjectCategoryBO.java(只关注业务)
java
复制代码
package com.sunxiansheng.subject.domain.entity;
import lombok.Data;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:09
* @Version 1.0
*/
@Data
public class SubjectCategoryBO {
private static final long serialVersionUID = -66163713173399755L;
/**
* 主键
*/
private Long id;
/**
* 分类名称
*/
private String categoryName;
/**
* 分类类型
*/
private Integer categoryType;
/**
* 图标连接
*/
private String imageUrl;
/**
* 父级id
*/
private Long parentId;
}
3.service层
1.SubjectCategoryDomainService.java
java
复制代码
package com.sunxiansheng.subject.domain.service;
import com.sunxiansheng.subject.domain.entity.SubjectCategoryBO;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:03
* @Version 1.0
*/
public interface SubjectCategoryDomainService {
void add(SubjectCategoryBO subjectCategoryBO);
}
2.由于需要将BO转换为eneity,所以需要转换器SubjectCategoryConverter.java
java
复制代码
package com.sunxiansheng.subject.domain.convert;
import com.sunxiansheng.subject.domain.entity.SubjectCategoryBO;
import com.sunxiansheng.subject.infra.basic.entity.SubjectCategory;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:18
* @Version 1.0
*/
@Mapper // mapstruct的注解
public interface SubjectCategoryConverter {
// INSTANCE是一个SubjectCategoryConverter的静态实例,可以直接通过SubjectCategoryConverter.INSTANCE调用内部的方法
SubjectCategoryConverter INSTANCE= Mappers.getMapper(SubjectCategoryConverter.class);
// 将SubjectCategoryBO转换为SubjectCategory
SubjectCategory convertBoToSubjectCategory(SubjectCategoryBO subjectCategoryBO);
}
3.SubjectCategoryDomainServiceImpl.java
java
复制代码
package com.sunxiansheng.subject.domain.service.impl;
import com.sunxiansheng.subject.domain.convert.SubjectCategoryConverter;
import com.sunxiansheng.subject.domain.entity.SubjectCategoryBO;
import com.sunxiansheng.subject.domain.service.SubjectCategoryDomainService;
import com.sunxiansheng.subject.infra.basic.entity.SubjectCategory;
import com.sunxiansheng.subject.infra.basic.service.SubjectCategoryService;
import javax.annotation.Resource;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:03
* @Version 1.0
*/
@Service
public class SubjectCategoryDomainServiceImpl implements SubjectCategoryDomainService {
@Resource
private SubjectCategoryService subjectCategoryService;
@Override
public void add(SubjectCategoryBO subjectCategoryBO) {
SubjectCategory subjectCategory = SubjectCategoryConverter.INSTANCE.convertBoToSubjectCategory(subjectCategoryBO);
subjectCategoryService.insert(subjectCategory);
}
}
3.sun-club-application-controller层
1.引入sun-club-domain的依赖
xml
复制代码
<!-- 引入sun-club-domain -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-domain</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.转换器将DTO转换为BO SubjectCategoryDTOConverter.java
java
复制代码
package com.sunxiansheng.subject.application.convert;
import com.sunxiansheng.subject.application.dto.SubjectCategoryDTO;
import com.sunxiansheng.subject.domain.entity.SubjectCategoryBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:40
* @Version 1.0
*/
@Mapper
public interface SubjectCategoryDTOConverter {
SubjectCategoryDTOConverter INSTANCE= Mappers.getMapper(SubjectCategoryDTOConverter.class);
SubjectCategoryBO convertDTOToSubjectCategory(SubjectCategoryDTO subjectCategoryDTO);
}
3.sun-club-common包中封装统一响应
1.ResultCodeEnum.java
java
复制代码
package com.sunxiansheng.subject.common.enums;
import lombok.Getter;
/**
* Description: 返回结果枚举
* @Author sun
* @Create 2024/5/24 9:53
* @Version 1.0
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(500, "失败");
public int code;
public String desc;
ResultCodeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 根据code获取枚举
* @param code
* @return
*/
public static ResultCodeEnum getByCode(int code) {
for (ResultCodeEnum value : values()) {
if (value.code == code) {
return value;
}
}
return null;
}
}
2.Result.java
java
复制代码
package com.sunxiansheng.subject.common.eneity;
import com.sunxiansheng.subject.common.enums.ResultCodeEnum;
import lombok.Data;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:48
* @Version 1.0
*/
@Data
public class Result<T> {
private Boolean success;
private Integer code;
private String message;
private T data;
/**
* 成功返回结果
* @return
*/
public static Result ok() {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
return result;
}
/**
* 成功返回结果,携带数据
* @param data
* @return
* @param <T>
*/
public static <T> Result ok(T data) {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
result.setData(data);
return result;
}
/**
* 失败返回结果
* @return
*/
public static Result fail() {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.getDesc());
return result;
}
/**
* 失败,携带数据
* @param data
* @return
* @param <T>
*/
public static <T> Result fail(T data) {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.getDesc());
result.setData(data);
return result;
}
}
4.SubjectCategoryController.java
java
复制代码
package com.sunxiansheng.subject.application.controller;
import com.alibaba.fastjson.JSON;
import com.sunxiansheng.subject.application.convert.SubjectCategoryDTOConverter;
import com.sunxiansheng.subject.application.dto.SubjectCategoryDTO;
import com.sunxiansheng.subject.common.eneity.Result;
import com.sunxiansheng.subject.domain.entity.SubjectCategoryBO;
import com.sunxiansheng.subject.domain.service.SubjectCategoryDomainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* Description: 题目分类控制器
* @Author sun
* @Create 2024/5/24 9:33
* @Version 1.0
*/
@RestController
@RequestMapping("/subject/category")
public class SubjectCategoryController {
@Resource
private SubjectCategoryDomainService subjectCategoryDomainService;
@PostMapping("/add")
public Result<Boolean> add(@RequestBody SubjectCategoryDTO subjectCategoryDTO) {
try {
SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOToSubjectCategory(subjectCategoryDTO);
subjectCategoryDomainService.add(subjectCategoryBO);
return Result.ok(true);
} catch (Exception e) {
return Result.fail();
}
}
}
5.测试
4.打印日志
1.sun-club-common引入log4j2和fastjson
xml
复制代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
2.SubjectCategoryController.java打印日志
- 这里判断是否开启日志的原因是:如果不判断,则即使没开启日志,JSON还是会序列化,影响性能
java
复制代码
if (log.isInfoEnabled()) {
log.info("SubjectCategoryController add SubjectCategoryDTO, subjectCategoryDTO:{}", JSON.toJSONString(subjectCategoryDTO));
}
3.SubjectCategoryDomainServiceImpl.java
4.SubjectCategoryServiceImpl.java
5.sun-club-starter 引入log4j2-spring.xml
xml
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="INFO" monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} %X{PFTID} [%thread] %-5level %logger{36} - %msg%n" />
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="../log" />
<property name="FILE_NAME" value="jcClub.log" />
</Properties>
<!--https://logging.apache.org/log4j/2.x/manual/appenders.html-->
<appenders>
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="fileLog" fileName="${FILE_PATH}/temp.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
<appender-ref ref="fileLog"/>
</root>
</loggers>
</configuration>
6.sun-club-starter的application.yml配置日志
7.启动会报错
1.报错信息
2.使用Maven Helper查看依赖
3.排除掉springboot-starter-web的log
4.再次测试
5.参数校验
1.使用guava
1.sun-club-common引入依赖
xml
复制代码
<!-- guava进行参数校验 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
2.sun-club-application-controller引入公共包
xml
复制代码
<!-- 引入sun-club-common -->
<dependency>
<groupId>com.sun.club</groupId>
<artifactId>sun-club-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.Preconditions.checkNotNull没有生效,说明guava依赖有问题,clean一下maven,发现报错
4.把所有relativePath全删除,因为并没有双继承,用不上,再次clean,成功!
5.sun-club-application-controller编写SubjectCategoryController.java
java
复制代码
// 参数校验
Preconditions.checkNotNull(subjectCategoryDTO.getCategoryType(), "分类类型不能为空");
Preconditions.checkArgument(!StringUtils.isBlank(subjectCategoryDTO.getCategoryName()), "分类名称不能为空");
Preconditions.checkNotNull(subjectCategoryDTO.getParentId(), "分类父级id不能为空");
6.端口换成3010
2.测试