refactor: 基于 novel 项目 & Spring Cloud 2022 & Spring Cloud Alibaba 2022 重构

This commit is contained in:
xiongxiaoyang
2023-03-30 16:15:56 +08:00
parent d68ce51c82
commit 3d098eea5e
505 changed files with 14127 additions and 24067 deletions

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>novel-news</artifactId>
<groupId>io.github.xxyopen</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>novel-news-service</artifactId>
<dependencies>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-news-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-config</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,19 @@
package io.github.xxyopen.novel.news;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication(scanBasePackages = {"io.github.xxyopen.novel"})
@MapperScan("io.github.xxyopen.novel.news.dao.mapper")
@EnableCaching
@EnableDiscoveryClient
public class NovelNewsApplication {
public static void main(String[] args) {
SpringApplication.run(NovelNewsApplication.class, args);
}
}

View File

@ -0,0 +1,50 @@
package io.github.xxyopen.novel.news.controller;
import io.github.xxyopen.novel.common.constant.ApiRouterConsts;
import io.github.xxyopen.novel.common.resp.RestResp;
import io.github.xxyopen.novel.news.dto.resp.NewsInfoRespDto;
import io.github.xxyopen.novel.news.service.NewsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 前台门户-新闻模块 API 控制器
*
* @author xiongxiaoyang
* @date 2022/5/12
*/
@Tag(name = "NewsController", description = "前台门户-新闻模块")
@RestController
@RequestMapping(ApiRouterConsts.API_FRONT_NEWS_URL_PREFIX)
@RequiredArgsConstructor
public class NewsController {
private final NewsService newsService;
/**
* 最新新闻列表查询接口
*/
@Operation(summary = "最新新闻列表查询接口")
@GetMapping("latest_list")
public RestResp<List<NewsInfoRespDto>> listLatestNews() {
return newsService.listLatestNews();
}
/**
* 新闻信息查询接口
*/
@Operation(summary = "新闻信息查询接口")
@GetMapping("{id}")
public RestResp<NewsInfoRespDto> getNews(
@Parameter(description = "新闻ID") @PathVariable Long id) {
return newsService.getNews(id);
}
}

View File

@ -0,0 +1,97 @@
package io.github.xxyopen.novel.news.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 新闻类别
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/12
*/
@TableName("news_category")
public class NewsCategory implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 类别名
*/
private String name;
/**
* 排序
*/
private Integer sort;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "NewsCategory{" +
"id=" + id +
", name=" + name +
", sort=" + sort +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,100 @@
package io.github.xxyopen.novel.news.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 新闻内容
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
@TableName("news_content")
public class NewsContent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 新闻ID
*/
private Long newsId;
/**
* 新闻内容
*/
private String content;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getNewsId() {
return newsId;
}
public void setNewsId(Long newsId) {
this.newsId = newsId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "NewsContent{" +
"id=" + id +
", newsId=" + newsId +
", content=" + content +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,128 @@
package io.github.xxyopen.novel.news.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 新闻信息
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/12
*/
@TableName("news_info")
public class NewsInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 类别ID
*/
private Long categoryId;
/**
* 类别名
*/
private String categoryName;
/**
* 新闻来源
*/
private String sourceName;
/**
* 新闻标题
*/
private String title;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCategoryId() {
return categoryId;
}
public void setCategoryId(Long categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getSourceName() {
return sourceName;
}
public void setSourceName(String sourceName) {
this.sourceName = sourceName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "NewsInfo{" +
"id=" + id +
", categoryId=" + categoryId +
", categoryName=" + categoryName +
", sourceName=" + sourceName +
", title=" + title +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,17 @@
package io.github.xxyopen.novel.news.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.news.dao.entity.NewsCategory;
/**
* <p>
* 新闻类别 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/12
*/
public interface NewsCategoryMapper extends BaseMapper<NewsCategory> {
}

View File

@ -0,0 +1,17 @@
package io.github.xxyopen.novel.news.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.news.dao.entity.NewsContent;
/**
* <p>
* 新闻内容 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
public interface NewsContentMapper extends BaseMapper<NewsContent> {
}

View File

@ -0,0 +1,16 @@
package io.github.xxyopen.novel.news.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.news.dao.entity.NewsInfo;
/**
* <p>
* 新闻信息 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/12
*/
public interface NewsInfoMapper extends BaseMapper<NewsInfo> {
}

View File

@ -0,0 +1,47 @@
package io.github.xxyopen.novel.news.manager.cache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.github.xxyopen.novel.common.constant.CacheConsts;
import io.github.xxyopen.novel.common.constant.DatabaseConsts;
import io.github.xxyopen.novel.news.dao.entity.NewsInfo;
import io.github.xxyopen.novel.news.dao.mapper.NewsInfoMapper;
import io.github.xxyopen.novel.news.dto.resp.NewsInfoRespDto;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 新闻 缓存管理类
*
* @author xiongxiaoyang
* @date 2022/5/12
*/
@Component
@RequiredArgsConstructor
public class NewsCacheManager {
private final NewsInfoMapper newsInfoMapper;
/**
* 最新新闻列表查询,并放入缓存中
*/
@Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER,
value = CacheConsts.LATEST_NEWS_CACHE_NAME)
public List<NewsInfoRespDto> listLatestNews() {
// 从新闻信息表中查询出最新发布的两条新闻
QueryWrapper<NewsInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName())
.last(DatabaseConsts.SqlEnum.LIMIT_2.getSql());
return newsInfoMapper.selectList(queryWrapper).stream().map(v -> NewsInfoRespDto.builder()
.id(v.getId())
.categoryId(v.getCategoryId())
.categoryName(v.getCategoryName())
.title(v.getTitle())
.sourceName(v.getSourceName())
.updateTime(v.getUpdateTime())
.build()).toList();
}
}

View File

@ -0,0 +1,30 @@
package io.github.xxyopen.novel.news.service;
import io.github.xxyopen.novel.common.resp.RestResp;
import io.github.xxyopen.novel.news.dto.resp.NewsInfoRespDto;
import java.util.List;
/**
* 新闻模块 服务类
*
* @author xiongxiaoyang
* @date 2022/5/14
*/
public interface NewsService {
/**
* 最新新闻列表查询
*
* @return 新闻列表
*/
RestResp<List<NewsInfoRespDto>> listLatestNews();
/**
* 新闻信息查询
*
* @param id 新闻ID
* @return 新闻信息
*/
RestResp<NewsInfoRespDto> getNews(Long id);
}

View File

@ -0,0 +1,53 @@
package io.github.xxyopen.novel.news.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.github.xxyopen.novel.common.constant.DatabaseConsts;
import io.github.xxyopen.novel.common.resp.RestResp;
import io.github.xxyopen.novel.news.dao.entity.NewsContent;
import io.github.xxyopen.novel.news.dao.entity.NewsInfo;
import io.github.xxyopen.novel.news.dao.mapper.NewsContentMapper;
import io.github.xxyopen.novel.news.dao.mapper.NewsInfoMapper;
import io.github.xxyopen.novel.news.dto.resp.NewsInfoRespDto;
import io.github.xxyopen.novel.news.manager.cache.NewsCacheManager;
import io.github.xxyopen.novel.news.service.NewsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 新闻模块 服务实现类
*
* @author xiongxiaoyang
* @date 2022/5/14
*/
@Service
@RequiredArgsConstructor
public class NewsServiceImpl implements NewsService {
private final NewsCacheManager newsCacheManager;
private final NewsInfoMapper newsInfoMapper;
private final NewsContentMapper newsContentMapper;
@Override
public RestResp<List<NewsInfoRespDto>> listLatestNews() {
return RestResp.ok(newsCacheManager.listLatestNews());
}
@Override
public RestResp<NewsInfoRespDto> getNews(Long id) {
NewsInfo newsInfo = newsInfoMapper.selectById(id);
QueryWrapper<NewsContent> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(DatabaseConsts.NewsContentTable.COLUMN_NEWS_ID, id)
.last(DatabaseConsts.SqlEnum.LIMIT_1.getSql());
NewsContent newsContent = newsContentMapper.selectOne(queryWrapper);
return RestResp.ok(NewsInfoRespDto.builder()
.title(newsInfo.getTitle())
.sourceName(newsInfo.getSourceName())
.updateTime(newsInfo.getUpdateTime())
.content(newsContent.getContent())
.build());
}
}

View File

@ -0,0 +1,15 @@
server:
port: 9030
spring:
profiles:
include: common
active: dev
management:
# 端点启用配置
endpoint:
logfile:
# 启用返回日志文件内容的端点
enabled: true
# 外部日志文件路径
external-file: logs/novel-news-service.log

View File

@ -0,0 +1,6 @@
spring:
application:
name: novel-news-service
profiles:
include: common

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
<!-- appender是configuration的子节点是负责写日志的组件。 -->
<!-- ConsoleAppender把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是demo.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过1KB时对当前日志进行分割 重命名 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/novel-news-service.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名logs/demo.2017-12-05.0.log -->
<fileNamePattern>logs/debug.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天 -->
<maxHistory>30</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小默认值是10MB测试时可改成1KB看效果 -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- pattern节点用来设置日志的输入格式 -->
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<springProfile name="dev">
<!-- ROOT 日志级别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.maijinjie.springboot 为根包也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="io.github.xxyopen" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
</springProfile>
<springProfile name="prod">
<!-- ROOT 日志级别 -->
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.maijinjie.springboot 为根包也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="io.github.xxyopen" level="ERROR" additivity="false">
<appender-ref ref="FILE"/>
</logger>
</springProfile>
</configuration>