前言
本周,笔者将之前的基于 Servlet 的个人博客项目进行了迭代,基于 SpringBoot + SpringMVC + Mybatis + Redis 进行实现。额外实现密码的明文加密处理(加盐算法)、修改博客、公共主页等功能,并将 session 存储到 Redis 中持久化,同时额外实现分页功能并使用对 AOP 思想对用户登录身份验证模块进行升级。emmmm,具体后面会出文章详细介绍。这里先说说遇到的问题:
可以发现:在博客的摘要信息中,形如 #
这样的 markdown 标签也一并展示在了博客摘要信息中。
怎么解决呢? 很显然,一种是自己解决,一种是依赖 api:
- 使用正则表达式对博客正文中的所有 markdown 标签进行匹配,然后使用空字符进行替换;
- 使用 flexmark-java库来解析和转换 Markdown 文本。
下面,笔者将对两种方式分别进行讲解,并使用正则表达式的方式处理个人博客系统中的该问题。我们接着往下看~
文章目录
- 前言
- 1 正则表达式替换 Markdown 文本
- 1.1 正则表达式简介
- 1.2 具体实现
- 2 flexmark-java库解析和转换 Markdown 文本
- 3 实战:对个人博客系统中的摘要信息处理
1 正则表达式替换 Markdown 文本
1.1 正则表达式简介
正则表达式是一种强大的模式匹配工具,可以用于查找和替换文本中的特定模式。当涉及到在Java中使用正则表达式时,可以使用java.util.regex
包提供的类来进行模式匹配、查找和替换操作。以下是一些常用的类和方法:
-
Pattern
类:Pattern
类用于表示正则表达式模式。可以使用Pattern.compile()
方法将正则表达式编译为一个Pattern
对象。String regex = "\\d+"; // 匹配一个或多个数字 Pattern pattern = Pattern.compile(regex);
-
Matcher
类:Matcher
类用于进行模式匹配操作。可以使用Matcher.matches()
方法检查整个输入字符串是否与模式匹配,或使用Matcher.find()
方法在输入字符串中查找下一个匹配项。String input = "Hello 123 World"; Matcher matcher = pattern.matcher(input); if (matcher.find()) { System.out.println("匹配到数字:" + matcher.group()); }
-
String
类的正则表达式方法:String
类提供了一些便捷的方法来处理正则表达式,如String.matches()
、String.replaceAll()
和String.split()
。String input = "Hello 123 World"; if (input.matches("\\d+")) { System.out.println("输入字符串是一个数字"); } String replaced = input.replaceAll("\\d+", "###"); System.out.println("替换后的字符串:" + replaced); String[] parts = input.split("\\s+"); // 使用空白字符分割字符串 System.out.println("分割后的字符串数组:" + Arrays.toString(parts));
具体可参考Java官方文档中关于正则表达式的部分:Java 正则表达式
1.2 具体实现
import java.util.regex.Pattern;
public class MarkdownUtils {
public static String removeMarkdownTags(String markdown) {
// 匹配Markdown标签的正则表达式
String regex = "\\*\\*|__|\\*|_|~~|`|\\[\\]|\\(|\\)|\\{|\\}|\\[|\\]|#|\\+|-|\\.|!";
// 使用空字符串替换Markdown标签
String result = Pattern.compile(regex).matcher(markdown).replaceAll("");
return result;
}
}
在上面的示例中,removeMarkdownTags
方法接受一个Markdown格式的字符串作为输入,并使用正则表达式将Markdown标签替换为空字符串,从而去除Markdown标签。
2 flexmark-java库解析和转换 Markdown 文本
首先,需要在项目中添加flexmark-java
库的依赖。如果使用 Maven,可以在pom.xml
文件中添加以下依赖项:
<dependencies>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-all</artifactId>
<version>0.62.2</version>
</dependency>
</dependencies>
然后就可以使用flexmark-java
库来解析Markdown文本并获取纯文本内容,如下所示:
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
public class MarkdownUtils {
public static String removeMarkdownTags(String markdown) {
Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
// 将Markdown文本解析为HTML
String html = renderer.render(parser.parse(markdown));
// 使用Jsoup库从HTML中获取纯文本内容
String plainText = org.jsoup.Jsoup.parse(html).text();
return plainText;
}
public static void main(String[] args) {
String markdown = "**Hello** _world_!";
String plainText = removeMarkdownTags(markdown);
System.out.println(plainText); // 输出: Hello world!
}
}
在上面的示例中,使用flexmark-java
库将Markdown文本解析为HTML,然后使用Jsoup
库从HTML中提取纯文本内容。
3 实战:对个人博客系统中的摘要信息处理
在这里,笔者使用正则表达式的方式对博客摘要信息进行处理。
首先,创建一个 MarkdownUtils 工具类,该类就是专门用于处理 Markdown 文本的:
- 对摘要进行去除 markdown 标签处理;
- 摘要只截取文章正文前的 n 个字符;
MarkdownUtils.java
import java.util.regex.Pattern;
/**
* @author 兴趣使然黄小黄
* @date 2023/7/23 23:18
* 用于处理文章列表的文章摘要信息
*/
public class MarkdownUtils {
// 匹配Markdown标签的正则表达式
private static String regex = "\\*\\*|__|\\*|_|~~|`|\\[\\]|\\(|\\)|\\{|\\}|\\[|\\]|#|\\+|-|\\.|!";
/**
* 对摘要进行去 markdown 标签处理
*/
public static String removeMarkdownTags(String markdown, int n) {
// 先对 markdown 字符串进行截取
markdown = preprocessingString(markdown, n);
// 使用空字符串替换Markdown标签并返回
return Pattern.compile(regex).matcher(markdown).replaceAll("");
}
/**
* 截取正文的前 n 个字符作为摘要
*/
private static String preprocessingString(String s, int n) {
if (s == null || s == "" || n <= 0) {
return "";
}
String result = "";
if (n >= s.length()) {
result = s.substring(0, s.length());
} else {
result = s.substring(0, n);
}
return result;
}
}
编写完代码后,我们进行简单的 单元测试:
@SpringBootTest
class MarkdownUtilsTest {
@Test
void removeMarkdownTags() {
String markdown = "**Hello** _world_";
String result = MarkdownUtils.removeMarkdownTags(markdown, 256);
System.out.println(result);
Assertions.assertEquals("Hello world", result);
}
}
单元测试结果如下:
测试没问题后,我们可以着手对项目中的返回文章列表部分进行处理。
在项目中,获取个人博客列表信息的 url 为 /art//mylist
, 因此找到对应的 controller,只需要对获取的文章信息对象的列表的正文进行处理后再返回:
为了程序后期的维护,我们把摘要的最大字符长度放在了一个公共类进行保存:
最后,我们撰写一个很长很长的博文来看看 #
是否会被处理,文章是否会被截取吧~结果如下: