社区项目-项目介绍&环境搭建

文章目录

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.测试
相关推荐
Peter_chq27 分钟前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml41 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~1 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616881 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
一坨阿亮1 小时前
Linux 使用中的问题
linux·运维
aloha_7891 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
dsywws2 小时前
Linux学习笔记之vim入门
linux·笔记·学习
程序媛小果2 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot