《黑马点评》项目学习
例如:第一章 《黑马点评》项目学习1:项目搭建与登录实现
文章目录
前言
开始学习app前端界面的搭建
一、导入文章数据库
一般是直接导入现有的sql文件,不熟练mysql的话,手敲一遍熟悉一下sql语句会比较好。
表结构分析
主要有三个表,文章信息表ap_article、文章配置表ap_article_config和文章内容表ap_article_content。目前三个表之间是一一对应的关系,但是为什么需要对表进行拆分呢?(垂直分表,实际项目是实现是直接在构建表的时候进行分表)
垂直分表:将一个表的字段分散到多个表中,每个表存储其中一部分字段。
优势:
1、减少IO争抢,减少锁表的几率,查看文章概述与文章详情互不影响
2、充分发挥高频数据的操作效率,对文章概述数据操作的高效率不会被操作文章详情数据的低效率所拖累
拆分规则:
1、把不常用的字段单独放在一张表
2、把text,blob等大字段拆分出来单独放在一张表
3、经常组合查询的字段单独放在一张表中
注:数据库的配置放在nacos中,目前数据库可以进行的操作是查询,但无法实现增删改,具体原因还有待探究
二、文章列表查询实现
1.实现思路
该部分内容在sql中使用sql语句实现:
1.在默认频道展示10条文章信息
2.可以切换频道查看不同种类文章
3.当用户下拉可以加载最新的文章(分页)本页文章列表中发布时间为最大的时间为依据
4.当用户上拉可以加载更多的文章信息(按照发布时间)本页文章列表中发布时间最小的时间为依据
5.如果是当前频道的首页,前端传递默认参数:
maxBehotTime:0(ms)
minBehotTime:20000000000000(ms)
2063年
#按照发布时间倒叙查询10条文章
#频道筛选
#加载首页
#加载更多 2020-09-07 22:30:09
#加载最新
select * from ap_article aa LEFT JOIN ap_article_config aac ON aa.id = aac.article_id
where aac.is_down != 1 and aac.is_delete != 1
and aa.channel_id = 1
and aa.publish_time < '2020-09-07 22:30:09'
ORDER BY aa.publish_time DESC
LIMIT 10
2.接口定义
实现步骤:
1.导入article微服务,需在nacos中添加对应得配置
直接复制文件夹,在总的pom文件里添加模块名称,随后重新编译maven;nacos中需要添加article的配置文件,以及修改gateway配置文件,格式与user类似。
2.定义接口
接口路径、请求方式、入参、出参
主要分为三种情况,初始加载、下拉更新、上滑加载;都是用ResponseResault作为返回参数。
3.编写mapper文件
文章表与文章配置表多表查询,直接复制资料代码
4.编写业务层代码
实现逻辑主要包含分页条数校验、type参数校验、频道参数校验和时间校验:
public ResponseResult<ApArticle> load(ArticleHomeDto dto, Short type) {
//分页条数的校验
Integer size = dto.getSize();
if(size == null || size == 0){
size = 10;
}
//分页的值不超过50
size = Math.min(size, MAX_PAGE_SIZE);
//校验参数type
if(!type.equals(ArticleConstants.LOADTYPE_LORD_MORE) && !type.equals(ArticleConstants.LOADTYPE_LORD_NEW)) {
type = ArticleConstants.LOADTYPE_LORD_MORE;
}
//频道参数校验
if(StringUtils.isBlank(dto.getTag())){
dto.setTag(ArticleConstants.DEFAULT_TAG);
}
//时间校验
if(dto.getMaxBehotTime() == null) dto.setMaxBehotTime(new Date());
if(dto.getMinBehotTime() == null) dto.setMinBehotTime(new Date());
List<ApArticle> articleList = apArticleMapper.loadArticleList(dto, type);
return ResponseResult.okResult(articleList);
}
5.编写控制层代码
6.swagger测试或前后端联调测试
启动时需要在maven里对service模块进行clean操作
三、文章详情
1.实现方案
具体实现方法与前端类似,进行了一定的了解,暂时没有整理
四、MinIO
1、MinIO简介
存储方式的对比
本节介绍的MInIO就属于分布式文件系统的一种,其优点如下:
2、MinIO搭建
在云服务器上部署minio时,会有访问不了的情况发生可以参考https://blog.youkuaiyun.com/qq_45128719/article/details/137015811解决。
docker run -p 9000:9000 -p 9090:9090 --name minio -d --restart=always -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio123" -v /home/data:/data -v /home/config:/root/.minio minio/minio server /data --console-address ":9090" --address ":9000"
这里在服务器上实现一定要配置好两个端口,只配置一个是无法返回请求的。
在安装好docker容器后,还需要在腾讯云上配置端口,实现防火墙放行。
在运行完成并登录之后,得到如下界面
bucket—类比于文件系统的目录
Object—类比于文件系统的文件
Keys—类比文件名
FileInputStream fileInputStream = new FileInputStream
("e:\\BUPT\\java\\project\\heima-leadnews\\plugins\\js\\index.js");
//1.获取minio的链接信息,创建一个minio的客户端
MinioClient minioClient = MinioClient.builder()
.endpoint("http://81.70.34.138:9000")
.credentials("minio", "minio123")
.build();
//上传
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.object("plugins/js/index.js") //文件名称
.contentType("text/js") //文件类型
.bucket("leadnews") //桶名称 与minio管理界面创建的桶一致即可
.stream(fileInputStream, fileInputStream.available(), -1)
.build();
minioClient.putObject(putObjectArgs);
}catch (Exception e) {
e.printStackTrace();
}
3.封装MinIO为starter(参考springboot)
1、直接复制文件夹到项目中
2、修改配置文件(pom.xml、spring.factories)
4.使用MinIO服务
miniostarter中定义了minio配置类
@Data
@ConfigurationProperties(prefix = "minio") // 文件上传 配置前缀file.oss
public class MinIOConfigProperties implements Serializable {
private String accessKey;
private String secretKey;
private String bucket;
private String endpoint;
private String readPath;
}
minio类对象
@Data
@Configuration
@EnableConfigurationProperties({MinIOConfigProperties.class})
//当引入FileStorageService接口时
@ConditionalOnClass(FileStorageService.class)
public class MinIOConfig {
@Autowired
private MinIOConfigProperties minIOConfigProperties;
@Bean
public MinioClient buildMinioClient() {
return MinioClient
.builder()
.credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey())
.endpoint(minIOConfigProperties.getEndpoint())
.build();
}
以及上传文件的方法接口FileStorageService与实现类MinIOFileStorageService
在使用minio-starter时,直接在微服务的pom.xml中依赖该模块,并在微服务的注册中心配置文件中加入minio登录配置即可实现功能,其具体测试代码如下:
//1、获取文章内容(已知文章id)
ApArticleContent apArticleContent = apArticleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery()
.eq(ApArticleContent::getArticleId, "1302865474094120961L"));
if(apArticleContent != null && StringUtils.isNotBlank(apArticleContent.getContent())){
//2、文章内容通过freemarker生成html文件
Template template = configuration.getTemplate("article.ftl");
//数据模型
Map<String, Object> content = new HashMap<>();
content.put("content", JSONArray.parseArray(apArticleContent.getContent()));
StringWriter out = new StringWriter();
//合成
template.process(content, out);
//3、把html文件上传到minio中
InputStream in = new ByteArrayInputStream(out.toString().getBytes());
String path = fileStorageService.uploadHtmlFile("",
apArticleContent.getArticleId() + ".html", in);
System.out.println(path);
//4、修改ap_article表,保存static_url字段
apArticleService.update(Wrappers.<ApArticle>lambdaUpdate().eq(ApArticle::getId,
apArticleContent.getArticleId()).set(ApArticle::getStaticUrl, path));
总结
整理的有点乱,由于黑马的minio等服务都是在虚拟机或本地实现,而我尝试在云服务器上实现,导致被某些bug卡了很久,继续加油。