黑马头条_SpringCloud项目阶段二:FreeMarker组件以及MinIO系统集成
知识点一:分表-垂直分表
- 垂直分表:将一个表的字段分散到多个表中,每个表存储器中的一部分。
- 垂直分表的规则
- 示例
知识点二:文章列表SQL查询
- 条件
- 实现SQL
# 按照发布时间,倒序查询10条数据
select * from ap_article
ORDER BY ap_article.publish_time
DESC LIMIT 10;# 频道筛选 例如查询频道为Java的select * from ap_article
WHERE ap_article.channel_id=1
ORDER BY ap_article.publish_time
DESC LIMIT 10# 加载首页数据select * from ap_article
WHERE ap_article.channel_id=1
AND
ap_article.publish_time<'2063-00-00 00:00:00'
ORDER BY ap_article.publish_time
DESC LIMIT 10# 加载更多 示例:找到本页最后一条数据后,判断小于他的发布时间就好了
select * from ap_article
WHERE ap_article.channel_id=1
AND
ap_article.publish_time<'2020-09-07 22:30:09'
ORDER BY ap_article.publish_time
DESC LIMIT 10# 加载最新 示例:找到本页最后一条数据后,判断大于他的发布时间就好了
select * from ap_article
WHERE ap_article.channel_id=1
AND
ap_article.publish_time>'2020-09-07 22:30:09'
ORDER BY ap_article.publish_time
DESC LIMIT 10# 以上情况,连表查询 ap_article_config和 ap_article并添加条件,文章是没有删除,没有下架的
select * from ap_article LEFT JOIN ap_article_config
ON
ap_article.id = ap_article_config.article_id
WHERE
ap_article_config.is_down !=1
andap_article_config.is_delete != 1
and
ap_article.channel_id=1
AND
ap_article.publish_time>'2020-09-07 22:30:09'
ORDER BY
ap_article.publish_time
DESC LIMIT
10
知识点三: @Param注解
- 作用:于给 SQL 映射方法中的参数起别名,便于在 XML 映射文件中引用。
- 好处:开发者在定义参数名时,就不需要一定要按照mapper.xml文件,可以随意命名。
- 示例
package com.heima.article.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.commons.net.nntp.Article;
import org.mapstruct.Mapper;import java.util.List;@Mapper
public interface ApArticleMapper extends BaseMapper<ApArticle> {List<ApArticle> loadArticleList( @Param("dto") ArticleHomeDto dto, @Param("type") short type);
}
知识点四:app端文章详情页使用技术以及开发思路
- 传统方法
- 通过点击文章将文章表(ap_article)的id传入到详情页中,再通过文章内容表(ap_article_content)查询文章id显示内容
- 静态模版方法
- 先从content表中将内容通过freemarker技术生成静态的html文件,再使用minIO存储该文件
- 并在article表中通过static_url存储静态html文章的地址
知识点五:freemarker模版引擎技术
- 实现效果:
- freemarker可以使用的扩展名:
- ftl
- html
- xml
- jsp
- 存放文件默认目录:resources下的templates
知识点六:freemarker模版引擎技术Demo
- 结构
- 倒入依赖
<?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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.heima</groupId><artifactId>heima-leadnews-test</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>freemarker-demo</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- apache 对 java io 的封装工具库 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>1.3.2</version></dependency></dependencies></project>
- yml配置
server:port: 8881 #服务端口
spring:application:name: freemarker-demo #指定服务名freemarker:cache: false #关闭模板缓存,方便测试settings:template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试suffix: .ftl #指定Freemarker模板文件的后缀名
- 创建ftl文件
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hello World!</title></head><body>
<b>普通文本 String 展示:</b><br><br>
Hello ${name} <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${student.name}<br/>
年龄:${student.age}
<hr>
</body></html>
- 编写Controller
package cn.varin.freemarkerDemo.controller;import cn.varin.freemarkerDemo.entity.Student;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class FreemarkerDemoController {@GetMapping("/basic")public String basic(Model model) {model.addAttribute("name", "freemarkerDemo");Student student = new Student();student.setAge(22);student.setName("varin");model.addAttribute("student", student);return "01-basic";}
}
- 访问
http://localhost:8881/basic
知识点七:freemarker模版引擎技术基本语法
- 基本语法
- 列表指令
语法:
<#list></#list>
案例示例:
解释: 标签中的list为集合,student为对象
注意点:想要获取到集合下标格式:对象_index
下标值默认为0,
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hello World!</title></head><body>
<b>普通文本 String 展示:</b><br><br>
Hello ${name} <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
<#list list as student >序号:${student_index}姓名:${student.name}<br/>年龄:${student.age}<hr/>
</#list><hr>
</body></html>
- 集合指令
示例代码:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hello World!</title></head><body>
<b>普通文本 String 展示:</b><br><br>
Hello ${name} <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
<#list students?keys as key >姓名:${students[key].name}<br/>年龄:${students[key].age}<hr/>
</#list><hr><h1>s1对象的名称</h1>
${students["s1"].name}
${students.s1.name}
</body></html>
- if指令
- 注意点:条件判断中的=和==效果是一样的。
- 运输符
- 空值处理
- 内建函数
知识点八:free marker生成html
- 流程
- 示例
package cn.varin.freemarkder.test;import cn.varin.freemarkerDemo.FreemarkerDemoApplication;
import cn.varin.freemarkerDemo.entity.Student;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.assertj.core.util.Maps;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;@SpringBootTest(classes = FreemarkerDemoApplication.class)
@RunWith(SpringRunner.class)
public class FreemarderDemoTest {@Autowiredprivate Configuration freemarkerConfig;@Testpublic void test() throws IOException, TemplateException {// 获取模版Template template = freemarkerConfig.getTemplate("03-basic.ftl");// 加载数据并输出template.process(getMap(),new FileWriter("/usr/local/freemarkderFiles/2-basic.html"));}// 数据集,和之前的Controller类似,就是将model换成一个map就可以了public Map getMap() {Map<String, Object> map = new HashMap<>();Student student = new Student();student.setAge(22);student.setName("varin");Student student2 = new Student();student2.setAge(22);student2.setName("varya");HashMap<String, Object> students = new HashMap<>();students.put("s1", student);students.put("s2", student2);map.put("students", students);return map;}
}
注意点:需要到配置文件中添加freemarker模版的加载位置
server:port: 8881 #服务端口
spring:application:name: freemarker-demo #指定服务名freemarker:cache: false #关闭模板缓存,方便测试settings:template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试suffix: .ftl #指定Freemarker模板文件的后缀名template-loader-path: classpath:/templates # 指定加载模版的目录
知识点九:MinIO分布式文件系统简介
知识点十:MinIO搭建
# 创建主机目录#先创建主机目录(如果不存在)
sudo mkdir -p /opt/minio/data
# dockerdocker run -d \--name minio \-p 9000:9000 \-p 9001:9001 \ # 映射控制台端口-v /opt/minio/data:/data \-e "MINIO_ROOT_USER=minio" \-e "MINIO_ROOT_PASSWORD=minio123" \minio/minio server /data --console-address ":9001"
# 一行汇总
sudo mkdir -p /opt/minio/data && docker run -d --name minio -p 9000:9000 -p 9001:9001 -v /opt/minio/data:/data -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio123" minio/minio server /data --console-address ":9001"
- 解释:
- 先创建主机数据目录(如果不存在)
- 启动 MinIO 容器并在后台运行
- 映射 API 端口 9000 和控制台端口 9001
- 设置用户名 minio 和密码 minio123
- 数据持久化到 /opt/minio/data 目录
- 固定控制台端口为 9001(避免随机端口跳转)
- 访问路径:http://ip:9001
<font style="color:rgb(0, 0, 0);">-d</font>
:表示在后台运行容器<font style="color:rgb(0, 0, 0);">--name minio</font>
:给容器指定一个名称为 “minio”<font style="color:rgb(0, 0, 0);">-p 9000:9000</font>
:将容器的 9000 端口映射到主机的 9000 端口<font style="color:rgb(0, 0, 0);">-e "MINIO_ROOT_USER=minio"</font>
:设置环境变量,指定 MinIO 的用户名<font style="color:rgb(0, 0, 0);">-e "MINIO_ROOT_PASSWORD=minio123"</font>
:设置环境变量,指定 MinIO 的密码<font style="color:rgb(0, 0, 0);">minio/minio server /data</font>
:使用 MinIO 镜像,并启动服务,数据存储在容器内的 /data 目录
知识点十一:MinIO上传html文件示例
- 依赖
<dependencies><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>7.1.0</version></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></dependency></dependencies>
- 代码
package cn.varin.minio.test;import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.MinioException;import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.SetBucketPolicyArgs;
import io.minio.errors.MinioException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;public class minioDemoTest {public static void main(String[] args) {FileInputStream fileInputStream = null;try {// 获取到html文件fileInputStream= new FileInputStream("/usr/local/freemarkderDemo/2-basic.html");//创建minio客户端MinioClient minioClient = MinioClient.builder().credentials("minio", "minio123").endpoint("http://varin.cn:9000").build();//配置文件信息PutObjectArgs putObjectArgs = PutObjectArgs.builder().object("freemarkerDemo.html").contentType("text/html;charset=UTF-8").bucket("leadnews").stream(fileInputStream, fileInputStream.available(), -1).build();//上传minioClient. putObject(putObjectArgs);} catch (Exception e) {throw new RuntimeException(e);}}}
上传的文件访问路径为:http://ip:9000:桶名称/上传的路径名加文件名
例如:http://varin.cn:9000/leadnews/freemarkerDemo.html