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

文章目录

    • 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的启动命令
        • 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
        • 5.在maven的插件配置中指定maven打包的配置
    • 8.新建子模块
        • 1.新建api子模块
        • 2.为子模块的parent部分加上relativePath标签(不要加,只有在需要双继承的时候才需要)
        • 3.在maven的配置部分指定编译版本为java8以及maven的打包插件(每个子模块都要加的)
        • 2.新建application子模块
        • 3.跟上面两个一样的常规配置
        • 4.分别新建common、domain、infra、starter模块并进行常规配置
        • 5.各层次目录结构
          • 1.api层
          • 2.starter层
          • 3.infra层
          • 4.domain层![image-20240523154525211](https://img-blog.csdnimg.cn/img_convert/3f12fa1b06453bc80ee1dd82ada22d9b.png)
          • 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仓库
        • 2.编辑sun-club-starter的pom.xml引入SpringBoot的starter-web
        • 3.sun-club-starter模块编写启动类SubjectApplication.java
        • 4.启动测试
        • 5.sun-club-starter模块创建application.yml对项目进行调整
          • 1.文件内容
          • 2.重启测试
    • 10.集成SpringMVC
        • 1.sun-club-application-controller 引入SpringBoot的starter-web
        • 2.编写SubjectController.java
        • 3.sun-club-starter引入sun-club-application-controller模块,使其启动时可以找到
        • 4.测试访问
    • 11.集成MySQL,Druid,MyBatis
        • 1.sun-club-infra模块添加依赖
        • 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
        • 4.sun-club-starter启动类配置MapperScan,扫描基础设施层的包
        • 5.sun-club-starter配置数据源和监控
        • 6.测试
          • 1.sun-club-application-controller 引入sun-club-infra
          • 2.sun-club-application-controller编写SubjectController.java测试
          • 3.启动测试,成功!
        • 7.使用druid对application.yml中的密码进行加密
          • 1.sun-club-infra编写DruidEncryptUtil.java进行加解密
          • 2.sun-club-starter修改application.yml
        • 8.准备apipost测试工具
          • 1.新建目录
          • 2.刷题模块目录
          • 3.再添加一个题目分类的目录
          • 4.添加一个接口
    • 12.分层架构的业务开发演示
        • 1.引入依赖
          • 1.sun-club-common引入lombok和mapstruct,注意lombok必须放到mapstruct前面
          • 2.sun-club-infra引入sun-club-common
        • 2.sun-club-domain层
          • 1.引入sun-club-infra的依赖
          • 2.创建SubjectCategoryBO.java(只关注业务)
          • 3.service层
            • 1.SubjectCategoryDomainService.java
            • 2.由于需要将BO转换为eneity,所以需要转换器SubjectCategoryConverter.java
            • 3.SubjectCategoryDomainServiceImpl.java
        • 3.sun-club-application-controller层
          • 1.引入sun-club-domain的依赖
          • 2.转换器将DTO转换为BO SubjectCategoryDTOConverter.java
          • 3.sun-club-common包中封装统一响应
            • 1.ResultCodeEnum.java
            • 2.Result.java
          • 4.SubjectCategoryController.java
          • 5.测试
        • 4.打印日志
          • 1.sun-club-common引入log4j2和fastjson
          • 2.SubjectCategoryController.java打印日志
          • 3.SubjectCategoryDomainServiceImpl.java
          • 4.SubjectCategoryServiceImpl.java
          • 5.sun-club-starter 引入log4j2-spring.xml
          • 6.sun-club-starter的application.yml配置日志
          • 7.启动会报错
            • 1.报错信息
            • 2.使用Maven Helper查看依赖
            • 3.排除掉springboot-starter-web的log
            • 4.再次测试
        • 5.参数校验
          • 1.使用guava
            • 1.sun-club-common引入依赖
            • 2.sun-club-application-controller引入公共包
            • 3.Preconditions.checkNotNull没有生效,说明guava依赖有问题,clean一下maven,发现报错
            • 4.把所有relativePath全删除,因为并没有双继承,用不上,再次clean,成功!
            • 5.sun-club-application-controller编写SubjectCategoryController.java
            • 6.端口换成3010
          • 2.测试

1.技术选型

image-20240523103709944

2.原型设计

1.安装AxureRP

image-20240523105343084

2.进行汉化

image-20240523105703905

3.载入元件库

image-20240523105759647

image-20240523105923775

4.基本设计

image-20240523110733594

3.元数建模

1.安装元数建模软件

image-20240523111228529

2.新建项目

image-20240523111627437

3.新增一个刷题模块主题域

image-20240523111754467

4.新增数据表 subject_category

image-20240523111946145

image-20240523112335889

5.新增关系图,将表拖过来

image-20240523112425927

image-20240523112456605

6.新增题目标签表

image-20240523112643132

image-20240523113215837

7.新增题目信息表

image-20240523113428035

image-20240523114411374

8.新增单选表、多选表、判断题、简答题

image-20240523115006075

image-20240523115408987

image-20240523115650835

image-20240523120015541

9.新增分类、标签、题目关联表
10.关系图预览

image-20240523131742982

4.项目架构分析

1.现有的架构

image-20240523132552332

2.ddd架构

image-20240523132620853

5.mysql采用docker版的主从复制(之前配置过)

1.docker的启动命令
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.新建仓库

image-20240523145508623

2.克隆到IDEA

image-20240523145552481

7.新建一个sun-club-subject作为父模块

1.新建父模块

image-20240523150655253

2.删除src目录

image-20240523150851198

3.设置整个项目的编码为utf-8

4.在maven的配置部分指定编译版本为java8
    <!-- 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打包的配置
    <!-- maven打包常规配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

image-20240523152517520

8.新建子模块

1.新建api子模块

image-20240523151042356

2.为子模块的parent部分加上relativePath标签(不要加,只有在需要双继承的时候才需要)

image-20240523151631395

3.在maven的配置部分指定编译版本为java8以及maven的打包插件(每个子模块都要加的)
  <!-- 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>

image-20240523152618538

2.新建application子模块

3.跟上面两个一样的常规配置

image-20240523152926046

4.分别新建common、domain、infra、starter模块并进行常规配置

image-20240523153517433

image-20240523153529088

5.各层次目录结构
1.api层

image-20240523154009996

2.starter层

image-20240523154114961

3.infra层

image-20240523154337689

4.domain层image-20240523154525211
5.common层

image-20240523154631912

6.application层
新建三个子模块并加上常规配置

image-20240523155100663

image-20240523155416269

7.整体结构一览

image-20240523155532124

6.目录结构调整
1.sun-club-subject-api

image-20240523160121211

2.sun-club-starter

image-20240523160137202

3.sun-club-infra

image-20240523160342709

4.sun-club-domain

image-20240523160504939

5.sun-club-common

image-20240523160820466

6.sun-club-application

image-20240523161236957

9.集成SpringBoot

1.编辑sun-club-subject的pom.xml引入SpringBoot2并配置maven仓库
    <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>

image-20240523162246282

2.编辑sun-club-starter的pom.xml引入SpringBoot的starter-web
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

image-20240523163020302

3.sun-club-starter模块编写启动类SubjectApplication.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);
    }
}

image-20240523163512007

4.启动测试

image-20240523163533835

5.sun-club-starter模块创建application.yml对项目进行调整
1.文件内容

2.重启测试

image-20240523163739595

10.集成SpringMVC

1.sun-club-application-controller 引入SpringBoot的starter-web
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

image-20240523164014670

2.编写SubjectController.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!";
    }
}

image-20240523165332899

3.sun-club-starter引入sun-club-application-controller模块,使其启动时可以找到
        <!-- 引入sun-club-application-controller的依赖,则启动这个模块,就能找到 -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-application-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240523165449763

4.测试访问

image-20240523165506077

11.集成MySQL,Druid,MyBatis

1.sun-club-infra模块添加依赖
    <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>

image-20240523170254690

2.EasyCode插件,生成CRUD
1.安装插件

image-20240523185842998

2.选择表,右键选择EasyCode

image-20240523190445627

3.选择代码生成的位置,和需要的文件

image-20240523190627854

4.查看生成的代码

image-20240523192932850

5.删除与Pageable有关的代码
1.SubjectCategoryDao.java

image-20240523191827530

2.SubjectCategoryService.java

image-20240523191858191

3.SubjectCategoryServiceImpl.java

image-20240523191929408

3.sun-club-starter引入sun-club-infra
        <!-- 引入sun-club-infra -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-infra</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240523192617622

4.sun-club-starter启动类配置MapperScan,扫描基础设施层的包

image-20240523193811911

5.sun-club-starter配置数据源和监控
  • 这里没有配置扫描Mapper.xml的原因是:Mapper和Mapper.xml的名字相同并且位于常规位置,MyBatis会自动扫描
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
        <!-- 引入sun-club-infra -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-infra</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240523195248619

2.sun-club-application-controller编写SubjectController.java测试

image-20240523195659126

3.启动测试,成功!

image-20240523200243396

7.使用druid对application.yml中的密码进行加密
1.sun-club-infra编写DruidEncryptUtil.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.新建目录

image-20240523210503359

2.刷题模块目录

image-20240523210528522

3.再添加一个题目分类的目录

image-20240523210638230

4.添加一个接口

image-20240523212045274

12.分层架构的业务开发演示

1.引入依赖
1.sun-club-common引入lombok和mapstruct,注意lombok必须放到mapstruct前面
        <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>

image-20240524085305340

2.sun-club-infra引入sun-club-common
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240524085626235

2.sun-club-domain层
1.引入sun-club-infra的依赖
        <!-- 引入sun-club-infra -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-infra</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240524090625626

2.创建SubjectCategoryBO.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;

}

image-20240524091100109

3.service层
1.SubjectCategoryDomainService.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
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);
}

image-20240524092625918

3.SubjectCategoryDomainServiceImpl.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的依赖
        <!-- 引入sun-club-domain -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-domain</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240524093157459

2.转换器将DTO转换为BO SubjectCategoryDTOConverter.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);
}

image-20240524094752234

3.sun-club-common包中封装统一响应
1.ResultCodeEnum.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
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
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();
        }
    }
}

image-20240524105641724

5.测试

image-20240524101631593

4.打印日志
1.sun-club-common引入log4j2和fastjson
        <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>

image-20240524102109158

2.SubjectCategoryController.java打印日志
  • 这里判断是否开启日志的原因是:如果不判断,则即使没开启日志,JSON还是会序列化,影响性能
            if (log.isInfoEnabled()) {
                log.info("SubjectCategoryController add SubjectCategoryDTO, subjectCategoryDTO:{}", JSON.toJSONString(subjectCategoryDTO));
            }

image-20240524102957593

3.SubjectCategoryDomainServiceImpl.java

image-20240524103208321

4.SubjectCategoryServiceImpl.java

image-20240524103344499

5.sun-club-starter 引入log4j2-spring.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配置日志

image-20240524103748300

7.启动会报错
1.报错信息

image-20240524103854701

2.使用Maven Helper查看依赖

image-20240524104809749

3.排除掉springboot-starter-web的log

image-20240524104842840

4.再次测试

image-20240524105731421

5.参数校验
1.使用guava
1.sun-club-common引入依赖
        <!-- guava进行参数校验 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>

image-20240524110320126

2.sun-club-application-controller引入公共包
        <!-- 引入sun-club-common -->
        <dependency>
            <groupId>com.sun.club</groupId>
            <artifactId>sun-club-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

image-20240524110819200

3.Preconditions.checkNotNull没有生效,说明guava依赖有问题,clean一下maven,发现报错

image-20240524112009829

4.把所有relativePath全删除,因为并没有双继承,用不上,再次clean,成功!

image-20240524112139199

5.sun-club-application-controller编写SubjectCategoryController.java
// 参数校验
Preconditions.checkNotNull(subjectCategoryDTO.getCategoryType(), "分类类型不能为空");
           Preconditions.checkArgument(!StringUtils.isBlank(subjectCategoryDTO.getCategoryName()), "分类名称不能为空");
Preconditions.checkNotNull(subjectCategoryDTO.getParentId(), "分类父级id不能为空");

image-20240524113226527

6.端口换成3010

image-20240524113342129

2.测试

image-20240524113432866

image-20240524113501078

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/730791.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows Server查看W3SVC IIS服务器中对应的网站日志

W3SVC日志文件夹中序号的含义&#xff0c;格式就是W3SVC网站ID 如果没有自定义站点的日志路径&#xff0c;日志默认的路径是C:\inetpub\logs\LogFiles\ 基本上每个网站存放日志的文件夹名称都是以W3SVC开头&#xff0c;区别在于后面的ID/编号/序号&#xff0c;对应的是网站各…

工具与技术:如何使用工具创建和实现导航栏图标动效

这篇教程的目的主要是带领大家做UI交互的入门引导,让大家理解做交互动效的一些基本逻辑思维,利用原型交互动画做导航栏icon动画效果。 导航栏icon动效的详细教程&#xff1a; 即时设计 - 可实时协作的专业 UI 设计工具即时设计是一款支持在线协作的专业级 UI 设计工具&#x…

使用Apache Flink实现实时数据同步与清洗:MySQL和Oracle到目标MySQL的ETL流程

使用Apache Flink实现实时数据同步与清洗&#xff1a;MySQL和Oracle到目标MySQL的ETL流程 实现数据同步的ETL&#xff08;抽取、转换、加载&#xff09;过程通常涉及从源系统&#xff08;如数据库、消息队列或文件&#xff09;中抽取数据&#xff0c;进行必要的转换&#xff0c…

开发中遇到的错误 - @SpringBootTest 注解爆红

我在使用 SpringBootTest 注解的时候爆红了&#xff0c;ait 回车也导不了包&#xff0c;后面发现是因为没有加依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>…

噪声-降噪引脚如何提高系统性能

由于LDO是电子器件&#xff0c;因此它们会自行产生一定量的噪声。选择低噪声LDO并采取措施来降低内部噪声对于生成不会影响系统性能的清洁电源轨而言不可或缺。 识别噪声 理想的 LDO 会生成没有交流元件的电压轨。遗憾的是&#xff0c;LDO 会像其他电子器件一样自行产生噪声。…

详细解读“找不到mfc140u.dll无法继续执行代码”问题

当你打开某个软件或者运行游戏&#xff0c;系统提示mfc140u.dll丢失&#xff0c;此时这个软件或者游戏根本无法运行。其实&#xff0c;mfc140u.dll是动态库文件&#xff0c;它是VS2010编译的软件所产生的&#xff0c;如果电脑运行程序时提示缺少mfc140u.dll文件&#xff0c;程序…

网络虚拟化考题

vrrp讲过吗&#xff1f;&#xff1f;&#xff1f; d 每一层都是什么设备啊 abcd 为啥流量不可控不可视 c是啥意思 讲过吗 abc aNET网络虚拟化是啥啊 为啥&#xff1f;&#xff1f; 啥是CDN&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;

汇聚荣做拼多多运营口碑怎么样?

拼多多作为国内领先的电商平台&#xff0c;其运营口碑一直是业界和消费者关注的焦点。汇聚荣作为拼多多的运营服务商&#xff0c;其服务质量直接影响到拼多多平台的用户体验和品牌形象。那么&#xff0c;汇聚荣做拼多多运营口碑怎么样呢? 一、服务响应速度 汇聚荣在服务响应速…

聊聊JSON

引言 JSON的概念 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它基于JavaScript的一个子集&#xff0c;但独立于语言&#xff0c;这意味着它可以被许多编程语言轻松解析。JSON的简洁性和易读性使其成为Web开发中数据交换的…

Focal Network for Image Restoration

Focal Network for Image Restoration 用于图像恢复的焦点网络 Yuning Cui1 Wenqi Ren2* Xiaochun Cao2 Alois Knoll1 1Technical University of Munich 2Shenzhen Campus of Sun Yat-sen University {yuning.cui,knoll}in.tum.de {renwq3,caoxiaochun}mail.sysu.edu.cn 论文…

【python】OpenCV——Color Correction

文章目录 cv2.aruco 介绍imutils.perspective.four_point_transform 介绍skimage.exposure.match_histograms 介绍牛刀小试遇到的问题 参考学习来自 OpenCV基础&#xff08;18&#xff09;使用 OpenCV 和 Python 进行自动色彩校正 cv2.aruco 介绍 一、cv2.aruco模块概述 cv2.…

【2024德国工作】外国人在德国找工作是什么体验?

挺难的&#xff0c;德语应该是所有中国人的难点。大部分中国人进德国公司要么是做中国业务相关&#xff0c;要么是做技术领域的工程师。先讲讲人在中国怎么找德国的工作&#xff0c;顺便延申下&#xff0c;德国工作的真实体验&#xff0c;最后聊聊在今年的德国工作签证申请条件…

网络与协议安全复习 - 电子邮件安全

文章目录 PGP(Pretty Good Privacy)功能 S/MIME(Secure/Multipurpose Internet Mail Extensions)DKIM(Domain Keys Identified Mail) PGP(Pretty Good Privacy) 使用符号&#xff1a; Ks&#xff1a;会话密钥、KRa&#xff1a;A 的私钥、KUa&#xff1a;A 的公钥、EP&#xff…

Android开发系列(六)Jetpack Compose之Box

Box是一个用来组合和控制子元素布局的组件。它可以在一个矩形区域内排列一个或多个子元素&#xff0c;并根据所提供的参数来控制它们的位置、大小和样式。 Box的功能类似传统的FrameLayout。 下面通过示例了解Box的使用方法&#xff0c;首先看一个最简单的示例&#xff0c;如下…

永磁同步电机驱动死区补偿

1 死区效应及补偿 1. 1 死区效应 在本文的电机控制嵌入式系统中,逆变器为三 相电压型桥式逆变电路,如图 1 所示。 在理想状态 下,上桥臂和下桥臂的控制信号满足互补通断原则, 即上桥臂开通时,下桥臂关断,反之亦然。 而在实际 应用中,开关管的通断需要一定的开通时…

大语言模型-Transformer

目录 1.概述 2.作用 3.诞生背景 4.历史版本 5.优缺点 5.1.优点 5.2.缺点 6.如何使用 7.应用场景 7.1.十大应用场景 7.2.聊天机器人 8.Python示例 9.总结 1.概述 大语言模型-Transformer是一种基于自注意力机制&#xff08;self-attention&#xff09;的深度学习…

如何使用Windows备份轻松将数据转移到新电脑?这里有详细步骤

序言 我们都知道那种买了一台新电脑,就想直接上手的感觉。我记得在过去的日子里,要花几个小时传输我的文件,并试图复制我的设置。在当今传输数据的众多方法中,Windows备份提供了一个简单可靠的解决方案。 登录到你的Microsoft帐户 Microsoft在传输过程中使用其云存储来保…

NGINX_六 nginx 日志文件详解

六 nginx 日志文件详解 nginx 日志文件分为 **log_format** 和 **access_log** 两部分log_format 定义记录的格式&#xff0c;其语法格式为log_format 样式名称 样式详情配置文件中默认有log_format main $remote_addr - $remote_user [time_local] "req…

二,SpringFramework

二、SpringFramework实战指南 目录 一、技术体系结构 1.1 总体技术体系1.2 框架概念和理解 二、SpringFramework介绍 2.1 Spring 和 SpringFramework概念2.2 SpringFramework主要功能模块2.3 SpringFramework 主要优势 三、Spring IoC容器和核心概念 3.1 组件和组件管理概念3…