feat(note): 初始化笔记服务模块

- 添加笔记、频道、话题等核心数据表结构
- 创建对应的数据访问对象(DO)和MyBatis映射文件
- 配置Spring Boot应用启动类及基础依赖
- 设置Nacos服务发现与配置中心相关配置
- 添加全局异常处理机制和响应码枚举定义
- 配置RedisTemplate以支持JSON序列化存储
- 定义日志输出格式及异步写入策略
- 新增笔记状态、类型、可见性等相关枚举类
- 配置MyBatis-Plus、MySQL、Druid等数据访问组件
- 添加Maven模块结构并集成到主项目中
This commit is contained in:
Hanserwei
2025-10-07 18:07:30 +08:00
parent eb74ebae8d
commit 665ea930fd
31 changed files with 919 additions and 8 deletions

1
.gitignore vendored
View File

@@ -48,3 +48,4 @@ build/
/han-note-kv/han-note-kv-biz/src/main/resources/application-dev.yml /han-note-kv/han-note-kv-biz/src/main/resources/application-dev.yml
/han-note-kv/han-note-kv-biz/src/main/resources/application-prod.yml /han-note-kv/han-note-kv-biz/src/main/resources/application-prod.yml
/han-note-kv/han-note-kv-biz/logs/ /han-note-kv/han-note-kv-biz/logs/
/han-note-note/han-note-note-biz/src/main/resources/application-dev.yml

6
.idea/encodings.xml generated
View File

@@ -17,6 +17,12 @@
<file url="file://$PROJECT_DIR$/han-note-kv/han-note-kv-biz/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-kv/han-note-kv-biz/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-kv/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-kv/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-kv/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-kv/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/han-note-note-api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/han-note-note-api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/han-note-note-biz/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/han-note-note-biz/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-note/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-api/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-api/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-biz/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/han-note-oss/han-note-oss-biz/src/main/java" charset="UTF-8" />

View File

@@ -6,10 +6,10 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication @SpringBootApplication
@EnableFeignClients(basePackages = "com.hanserwei.hannote") @EnableFeignClients(basePackages = "com.hanserwei.hannote")
public class HanNoteAuthApplication { public class HannoteAuthApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(HanNoteAuthApplication.class, args); SpringApplication.run(HannoteAuthApplication.class, args);
} }
} }

View File

@@ -3,12 +3,6 @@ spring:
name: han-note-auth name: han-note-auth
profiles: profiles:
active: dev # 默认激活 dev 本地开发环境 active: dev # 默认激活 dev 本地开发环境
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver # 指定数据库驱动类
# 数据库连接信息
url: ${spring.datasource.url}
username: ${spring.datasource.username} # 数据库用户名
password: ${spring.datasource.password} # 数据库密码
data: data:
redis: redis:
database: 5 # Redis 数据库索引(默认为 0 database: 5 # Redis 数据库索引(默认为 0

View File

@@ -0,0 +1,24 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父项目 -->
<parent>
<groupId>com.hanserwei</groupId>
<artifactId>han-note-note</artifactId>
<version>${revision}</version>
</parent>
<!-- 打包方式 -->
<packaging>jar</packaging>
<artifactId>han-note-api</artifactId>
<name>${project.artifactId}</name>
<description>RPC层, 供其他服务调用</description>
<dependencies>
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>hanserwei-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,105 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父项目 -->
<parent>
<groupId>com.hanserwei</groupId>
<artifactId>han-note-note</artifactId>
<version>${revision}</version>
</parent>
<!-- 打包方式 -->
<packaging>jar</packaging>
<artifactId>han-note-note-biz</artifactId>
<name>${project.artifactId}</name>
<description>笔记服务业务层</description>
<dependencies>
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>hanserwei-common</artifactId>
</dependency>
<!-- 业务接口日志组件 -->
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>hanserwei-spring-boot-starter-biz-operationlog</artifactId>
</dependency>
<!-- 上下文组件 -->
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>hanserwei-spring-boot-starter-biz-context</artifactId>
</dependency>
<!-- Jackson 组件 -->
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>hanserwei-spring-boot-starter-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Redis 连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,11 @@
package com.hanserwei.hannote.note.biz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HannoteNoteBizApplication {
public static void main(String[] args) {
SpringApplication.run(HannoteNoteBizApplication.class, args);
}
}

View File

@@ -0,0 +1,31 @@
package com.hanserwei.hannote.note.biz.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置 RedisTemplate 的连接工厂
redisTemplate.setConnectionFactory(connectionFactory);
// 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key 值,确保 key 是可读的字符串
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值, 确保存储的是 JSON 格式
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

View File

@@ -0,0 +1,49 @@
package com.hanserwei.hannote.note.biz.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 频道表
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_channel")
public class ChannelDO {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 频道名称
*/
@TableField(value = "`name`")
private String name;
/**
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 逻辑删除(0未删除 1已删除)
*/
@TableField(value = "is_deleted")
private Boolean isDeleted;
}

View File

@@ -0,0 +1,49 @@
package com.hanserwei.hannote.note.biz.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 频道-话题关联表
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_channel_topic_rel")
public class ChannelTopicRelDO {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 频道ID
*/
@TableField(value = "channel_id")
private Long channelId;
/**
* 话题ID
*/
@TableField(value = "topic_id")
private Long topicId;
/**
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
}

View File

@@ -0,0 +1,103 @@
package com.hanserwei.hannote.note.biz.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 笔记表
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_note")
public class NoteDO {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 标题
*/
@TableField(value = "title")
private String title;
/**
* 内容是否为空(0不为空 1空)
*/
@TableField(value = "is_content_empty")
private Boolean isContentEmpty;
/**
* 发布者ID
*/
@TableField(value = "creator_id")
private Long creatorId;
/**
* 话题ID
*/
@TableField(value = "topic_id")
private Long topicId;
/**
* 话题名称
*/
@TableField(value = "topic_name")
private String topicName;
/**
* 是否置顶(0未置顶 1置顶)
*/
@TableField(value = "is_top")
private Boolean isTop;
/**
* 类型(0图文 1视频)
*/
@TableField(value = "`type`")
private Byte type;
/**
* 笔记图片链接(逗号隔开)
*/
@TableField(value = "img_uris")
private String imgUris;
/**
* 视频链接
*/
@TableField(value = "video_uri")
private String videoUri;
/**
* 可见范围(0公开,所有人可见 1仅对自己可见)
*/
@TableField(value = "visible")
private Byte visible;
/**
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 状态(0待审核 1正常展示 2被删除(逻辑删除) 3被下架)
*/
@TableField(value = "`status`")
private Byte status;
}

View File

@@ -0,0 +1,49 @@
package com.hanserwei.hannote.note.biz.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 话题表
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_topic")
public class TopicDO {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 话题名称
*/
@TableField(value = "`name`")
private String name;
/**
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 逻辑删除(0未删除 1已删除)
*/
@TableField(value = "is_deleted")
private Boolean isDeleted;
}

View File

@@ -0,0 +1,7 @@
package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelDO;
public interface ChannelDOMapper extends BaseMapper<ChannelDO> {
}

View File

@@ -0,0 +1,7 @@
package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelTopicRelDO;
public interface ChannelTopicRelDOMapper extends BaseMapper<ChannelTopicRelDO> {
}

View File

@@ -0,0 +1,7 @@
package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
public interface NoteDOMapper extends BaseMapper<NoteDO> {
}

View File

@@ -0,0 +1,7 @@
package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO;
public interface TopicDOMapper extends BaseMapper<TopicDO> {
}

View File

@@ -0,0 +1,18 @@
package com.hanserwei.hannote.note.biz.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum NoteStatusEnum {
BE_EXAMINE(0), // 待审核
NORMAL(1), // 正常展示
DELETED(2), // 被删除
DOWNED(3), // 被下架
;
private final Integer code;
}

View File

@@ -0,0 +1,48 @@
package com.hanserwei.hannote.note.biz.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
@Getter
@AllArgsConstructor
public enum NoteTypeEnum {
IMAGE_TEXT(0, "图文"),
VIDEO(1, "视频");
private final Integer code;
private final String description;
/**
* 类型是否有效
*
* @param code 类型 code
* @return 是否有效
*/
public static boolean isValid(Integer code) {
for (NoteTypeEnum noteTypeEnum : NoteTypeEnum.values()) {
if (Objects.equals(code, noteTypeEnum.getCode())) {
return true;
}
}
return false;
}
/**
* 根据类型 code 获取对应的枚举
*
* @param code 类型 code
* @return 对应的枚举
*/
public static NoteTypeEnum valueOf(Integer code) {
for (NoteTypeEnum noteTypeEnum : NoteTypeEnum.values()) {
if (Objects.equals(code, noteTypeEnum.getCode())) {
return noteTypeEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,15 @@
package com.hanserwei.hannote.note.biz.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum NoteVisibleEnum {
PUBLIC(0), // 公开,所有人可见
PRIVATE(1); // 仅自己可见
private final Integer code;
}

View File

@@ -0,0 +1,23 @@
package com.hanserwei.hannote.note.biz.enums;
import com.hanserwei.framework.common.exception.BaseExceptionInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ResponseCodeEnum implements BaseExceptionInterface {
// ----------- 通用异常状态码 -----------
SYSTEM_ERROR("NOTE-10000", "出错啦,后台小哥正在努力修复中..."),
PARAM_NOT_VALID("NOTE-10001", "参数错误"),
// ----------- 业务异常状态码 -----------
;
// 异常码
private final String errorCode;
// 错误信息
private final String errorMsg;
}

View File

@@ -0,0 +1,103 @@
package com.hanserwei.hannote.note.biz.exception;
import com.hanserwei.framework.common.exception.ApiException;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.note.biz.enums.ResponseCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Optional;
@SuppressWarnings("LoggingSimilarMessage")
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获自定义业务异常
*
* @return Response.fail(e)
*/
@ExceptionHandler({ApiException.class})
@ResponseBody
public Response<Object> handleApiException(HttpServletRequest request, ApiException e) {
log.warn("{} request fail, errorCode: {}, errorMessage: {}", request.getRequestURI(), e.getErrorCode(), e.getErrorMsg());
return Response.fail(e);
}
/**
* 捕获参数校验异常
*
* @return Response.fail(errorCode, errorMessage)
*/
@ExceptionHandler({MethodArgumentNotValidException.class})
@ResponseBody
public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
// 参数错误异常码
String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();
// 获取 BindingResult
BindingResult bindingResult = e.getBindingResult();
StringBuilder sb = new StringBuilder();
// 获取校验不通过的字段,并组合错误信息,格式为: email 邮箱格式不正确, 当前值: '123124qq.com';
Optional.of(bindingResult.getFieldErrors()).ifPresent(errors -> {
errors.forEach(error ->
sb.append(error.getField())
.append(" ")
.append(error.getDefaultMessage())
.append(", 当前值: '")
.append(error.getRejectedValue())
.append("'; ")
);
});
// 错误信息
String errorMessage = sb.toString();
log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage);
return Response.fail(errorCode, errorMessage);
}
/**
* 捕获 guava 参数校验异常
*
* @return Response.fail(ResponseCodeEnum.PARAM_NOT_VALID)
*/
@ExceptionHandler({IllegalArgumentException.class})
@ResponseBody
public Response<Object> handleIllegalArgumentException(HttpServletRequest request, IllegalArgumentException e) {
// 参数错误异常码
String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();
// 错误信息
String errorMessage = e.getMessage();
log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage);
return Response.fail(errorCode, errorMessage);
}
/**
* 其他类型异常
*
* @param request 请求
* @param e 异常
* @return Response.fail(ResponseCodeEnum.SYSTEM_ERROR)
*/
@ExceptionHandler({Exception.class})
@ResponseBody
public Response<Object> handleOtherException(HttpServletRequest request, Exception e) {
log.error("{} request error, ", request.getRequestURI(), e);
return Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
}
}

View File

@@ -0,0 +1,17 @@
server:
port: 8086 # 项目启动的端口
spring:
profiles:
active: dev # 默认激活 dev 本地开发环境
servlet:
multipart:
max-file-size: 20MB # 单个文件最大大小
max-request-size: 100MB # 单次请求最大大小(包含多个文件)
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
global-config:
banner: false
mapper-locations: classpath*:/mapperxml/*.xml

View File

@@ -0,0 +1,12 @@
spring:
application:
name: han-note-note # 应用名称
profiles:
active: dev # 默认激活 dev 本地开发环境
cloud:
nacos:
discovery:
enabled: true # 启用服务发现
group: DEFAULT_GROUP # 所属组
namespace: han-note # 命名空间
server-addr: 127.0.0.1:8848 # 指定 Nacos 配置中心的服务器地址

View File

@@ -0,0 +1,58 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 应用名称 -->
<property scope="context" name="appName" value="note"/>
<!-- 自定义日志输出路径,以及日志名称前缀 -->
<property name="LOG_FILE" value="./logs/${appName}.%d{yyyy-MM-dd}"/>
<!-- 每行日志输出的格式 -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- 文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的命名格式 -->
<fileNamePattern>${LOG_FILE}-%i.log</fileNamePattern>
<!-- 保留 30 天的日志文件 -->
<maxHistory>30</maxHistory>
<!-- 单个日志文件最大大小 -->
<maxFileSize>10MB</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>0</totalSizeCap>
<!-- 重启服务时,是否清除历史日志,不推荐清理 -->
<cleanHistoryOnStart>false</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 异步写入日志,提升性能 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 是否丢弃日志, 0 表示不丢弃。默认情况下,如果队列满 80%, 会丢弃 TRACE、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 队列大小。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/>
</appender>
<!-- 本地 dev 开发环境 -->
<springProfile name="dev">
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/> <!-- 输出控制台日志 -->
<appender-ref ref="ASYNC_FILE"/> <!-- 打印日志到文件中。PS: 本地环境下,如果不想打印日志到文件,可注释掉此行 -->
</root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="prod">
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/> <!-- 生产环境下,仅打印日志到文件中 -->
</root>
</springProfile>
</configuration>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanserwei.hannote.note.biz.domain.mapper.ChannelDOMapper">
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.note.biz.domain.dataobject.ChannelDO">
<!--@mbg.generated-->
<!--@Table t_channel-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="is_deleted" jdbcType="BIT" property="isDeleted" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, `name`, create_time, update_time, is_deleted
</sql>
</mapper>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanserwei.hannote.note.biz.domain.mapper.ChannelTopicRelDOMapper">
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.note.biz.domain.dataobject.ChannelTopicRelDO">
<!--@mbg.generated-->
<!--@Table t_channel_topic_rel-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="channel_id" jdbcType="BIGINT" property="channelId" />
<result column="topic_id" jdbcType="BIGINT" property="topicId" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, channel_id, topic_id, create_time, update_time
</sql>
</mapper>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanserwei.hannote.note.biz.domain.mapper.NoteDOMapper">
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO">
<!--@mbg.generated-->
<!--@Table t_note-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="is_content_empty" jdbcType="BIT" property="isContentEmpty" />
<result column="creator_id" jdbcType="BIGINT" property="creatorId" />
<result column="topic_id" jdbcType="BIGINT" property="topicId" />
<result column="topic_name" jdbcType="VARCHAR" property="topicName" />
<result column="is_top" jdbcType="BIT" property="isTop" />
<result column="type" jdbcType="TINYINT" property="type" />
<result column="img_uris" jdbcType="VARCHAR" property="imgUris" />
<result column="video_uri" jdbcType="VARCHAR" property="videoUri" />
<result column="visible" jdbcType="TINYINT" property="visible" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="status" jdbcType="TINYINT" property="status" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, title, is_content_empty, creator_id, topic_id, topic_name, is_top, `type`, img_uris,
video_uri, visible, create_time, update_time, `status`
</sql>
</mapper>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanserwei.hannote.note.biz.domain.mapper.TopicDOMapper">
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO">
<!--@mbg.generated-->
<!--@Table t_topic-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="is_deleted" jdbcType="BIT" property="isDeleted" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, `name`, create_time, update_time, is_deleted
</sql>
</mapper>

24
han-note-note/pom.xml Normal file
View File

@@ -0,0 +1,24 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父项目 -->
<parent>
<groupId>com.hanserwei</groupId>
<artifactId>han-note</artifactId>
<version>${revision}</version>
</parent>
<!-- 多模块项目需要配置打包方式为 pom -->
<packaging>pom</packaging>
<!-- 子模块管理 -->
<modules>
<module>han-note-note-api</module>
</modules>
<artifactId>han-note-note</artifactId>
<!-- 项目名称 -->
<name>${project.artifactId}</name>
<!-- 项目描述 -->
<description>笔记服务</description>
</project>

View File

@@ -18,6 +18,8 @@
<module>han-note-user</module> <module>han-note-user</module>
<module>han-note-kv</module> <module>han-note-kv</module>
<module>han-note-distributed-id-generator</module> <module>han-note-distributed-id-generator</module>
<module>han-note-note</module>
<module>han-note-note/han-note-note-biz</module>
</modules> </modules>
<properties> <properties>

View File

@@ -84,3 +84,66 @@ CREATE TABLE `t_role_permission_rel`
COLLATE = utf8mb4_unicode_ci COMMENT ='用户权限表'; COLLATE = utf8mb4_unicode_ci COMMENT ='用户权限表';
-- 表t_channel
CREATE TABLE `t_channel`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '频道名称',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除(0未删除 1已删除)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='频道表';
-- 表t_topic
CREATE TABLE `t_topic`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '话题名称',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除(0未删除 1已删除)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='话题表';
-- 表t_channel_topic_rel
CREATE TABLE `t_channel_topic_rel`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`channel_id` bigint unsigned NOT NULL COMMENT '频道ID',
`topic_id` bigint unsigned NOT NULL COMMENT '话题ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='频道-话题关联表';
-- 表t_note
CREATE TABLE `t_note`
(
`id` bigint unsigned NOT NULL COMMENT '主键ID',
`title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '标题',
`is_content_empty` bit(1) NOT NULL DEFAULT b'0' COMMENT '内容是否为空(0不为空 1空)',
`creator_id` bigint unsigned NOT NULL COMMENT '发布者ID',
`topic_id` bigint unsigned DEFAULT NULL COMMENT '话题ID',
`topic_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '话题名称',
`is_top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶(0未置顶 1置顶)',
`type` tinyint DEFAULT '0' COMMENT '类型(0图文 1视频)',
`img_uris` varchar(660) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '笔记图片链接(逗号隔开)',
`video_uri` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '视频链接',
`visible` tinyint DEFAULT '0' COMMENT '可见范围(0公开,所有人可见 1仅对自己可见)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态(0待审核 1正常展示 2被删除(逻辑删除) 3被下架)',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_creator_id` (`creator_id`),
KEY `idx_topic_id` (`topic_id`),
KEY `idx_status` (`status`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='笔记表';