JasonsGong.github.io/posts/64695.html
2024-06-14 22:00:25 +08:00

1080 lines
620 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>项目实战-黑马头条 | The Blog</title><meta name="author" content="Jason"><meta name="copyright" content="Jason"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="一.项目介绍1.项目概述​ 随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻。 2.业务说明功能架构图 3.技术栈 Sprin">
<meta property="og:type" content="article">
<meta property="og:title" content="项目实战-黑马头条">
<meta property="og:url" content="https://qingling.icu/posts/64695.html">
<meta property="og:site_name" content="The Blog">
<meta property="og:description" content="一.项目介绍1.项目概述​ 随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻。 2.业务说明功能架构图 3.技术栈 Sprin">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://qingling.icu/img/4.png">
<meta property="article:published_time" content="2023-08-07T09:12:08.000Z">
<meta property="article:modified_time" content="2024-05-10T05:31:11.583Z">
<meta property="article:author" content="Jason">
<meta property="article:tag" content="项目实战">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://qingling.icu/img/4.png"><link rel="shortcut icon" href="/img/%E5%9B%BE%E6%A0%87.png"><link rel="canonical" href="https://qingling.icu/posts/64695.html"><link rel="preconnect" href="//fastly.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="/cdn/icon/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="/cdn/css/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="/cdn/css/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: {"path":"/search.xml","preload":true,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"找不到您查询的内容:${query}","hits_stats":"共找到 ${hits} 篇文章"}},
translate: undefined,
noticeOutdate: undefined,
highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":400},
copy: {
success: '复制成功',
error: '复制错误',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: true,
post: true
},
runtime: '天',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'mediumZoom',
Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#006650","bgDark":"#006650","position":"top-center"},
source: {
justifiedGallery: {
js: 'https://fastly.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
css: 'https://fastly.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
}
},
isPhotoFigcaption: false,
islazyload: false,
isAnchor: true,
percent: {
toc: true,
rightside: false,
},
autoDarkmode: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '项目实战-黑马头条',
isPost: true,
isHome: false,
isHighlightShrink: false,
isToc: true,
postUpdate: '2024-05-10 13:31:11'
}</script><noscript><style type="text/css">
#nav {
opacity: 1
}
.justified-gallery img {
opacity: 1
}
#recent-posts time,
#post-meta time {
display: inline !important
}
</style></noscript><script>(win=>{
win.saveToLocal = {
set: function setWithExpiry(key, value, ttl) {
if (ttl === 0) return
const now = new Date()
const expiryDay = ttl * 86400000
const item = {
value: value,
expiry: now.getTime() + expiryDay,
}
localStorage.setItem(key, JSON.stringify(item))
},
get: function getWithExpiry(key) {
const itemStr = localStorage.getItem(key)
if (!itemStr) {
return undefined
}
const item = JSON.parse(itemStr)
const now = new Date()
if (now.getTime() > item.expiry) {
localStorage.removeItem(key)
return undefined
}
return item.value
}
}
win.getScript = url => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
document.head.appendChild(script)
})
win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onerror = reject
link.onload = link.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
link.onload = link.onreadystatechange = null
resolve()
}
document.head.appendChild(link)
})
win.activateDarkMode = function () {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
win.activateLightMode = function () {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
const t = saveToLocal.get('theme')
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
if (t === undefined) {
if (isLightMode) activateLightMode()
else if (isDarkMode) activateDarkMode()
else if (isNotSpecified || hasNoSupport) {
const now = new Date()
const hour = now.getHours()
const isNight = hour <= 8 || hour >= 22
isNight ? activateDarkMode() : activateLightMode()
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
if (saveToLocal.get('theme') === undefined) {
e.matches ? activateDarkMode() : activateLightMode()
}
})
} else if (t === 'light') activateLightMode()
else activateDarkMode()
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
if (asideStatus === 'hide') {
document.documentElement.classList.add('hide-aside')
} else {
document.documentElement.classList.remove('hide-aside')
}
}
const detectApple = () => {
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
document.documentElement.classList.add('apple')
}
}
detectApple()
})(window)</script><script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript" src ="/js/welcome.js" ></script><script src="/js/sweetalert.js"></script><link rel="stylesheet" href="/css/sweetalert.css"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/avatar.jpg" onerror="onerror=null;src='/img/loading.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">60</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">39</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">10</div></a></div><br/><div class="menus_items"><div class="menus_item"><a class="site-page" target="_blank" rel="noopener" href="https://www.tutorialspoint.com/compile_java8_online.php"><i class="fa-fw fas fa-code"></i><span> 代码</span></a></div><div class="menus_item"><a class="site-page" href="/notice/"><i class="fa-fw fas fa-stream"></i><span> 公告</span></a></div><div class="menus_item"><a class="site-page" href="/website/"><i class="fa-fw fas fa-list"></i><span> 网址</span></a></div><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="not-top-img" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="The Blog"><img class="site-icon" src="/img/logo.png"/><span class="site-name">The Blog</span></a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search" href="javascript:void(0);"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" target="_blank" rel="noopener" href="https://www.tutorialspoint.com/compile_java8_online.php"><i class="fa-fw fas fa-code"></i><span> 代码</span></a></div><div class="menus_item"><a class="site-page" href="/notice/"><i class="fa-fw fas fa-stream"></i><span> 公告</span></a></div><div class="menus_item"><a class="site-page" href="/website/"><i class="fa-fw fas fa-list"></i><span> 网址</span></a></div><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav></header><main class="layout" id="content-inner"><div id="post"><div id="post-info"><h1 class="post-title">项目实战-黑马头条</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2023-08-07T09:12:08.000Z" title="发表于 2023-08-07 17:12:08">2023-08-07</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-05-10T05:31:11.583Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E5%90%8E%E7%AB%AF/">后端</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">23.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>114分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="项目实战-黑马头条"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><article class="post-content" id="article-container"><h1 id="一-项目介绍"><a href="#一-项目介绍" class="headerlink" title="一.项目介绍"></a>一.项目介绍</h1><h2 id="1-项目概述"><a href="#1-项目概述" class="headerlink" title="1.项目概述"></a>1.项目概述</h2><p> 随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻。</p>
<p><img src="/pictures/image-20230810153039562.png" alt="image-20230810153039562"></p>
<h2 id="2-业务说明"><a href="#2-业务说明" class="headerlink" title="2.业务说明"></a>2.业务说明</h2><p><strong>功能架构图</strong></p>
<p><img src="/pictures/image-20230810153700690.png" alt="image-20230810153700690"></p>
<h2 id="3-技术栈"><a href="#3-技术栈" class="headerlink" title="3.技术栈"></a>3.技术栈</h2><ul>
<li>Spring-Cloud-Gateway : 微服务之前架设的网关服务实现服务注册中的API请求路由以及控制流速控制和熔断处理都是常用的架构手段而这些功能Gateway天然支持</li>
<li>运用Spring Boot快速开发框架构建项目工程并结合Spring Cloud全家桶技术实现后端个人中心、自媒体、管理中心等微服务。</li>
<li>运用Spring Cloud Alibaba Nacos作为项目中的注册中心和配置中心</li>
<li>运用mybatis-plus作为持久层提升开发效率</li>
<li>运用Kafka完成内部系统消息通知与客户端系统消息通知以及实时数据计算</li>
<li>运用Redis缓存技术实现热数据的计算提升系统性能指标</li>
<li>使用Mysql存储用户数据以保证上层数据查询的高性能</li>
<li>使用Mongo存储用户热数据以保证用户热数据高扩展和高性能指标</li>
<li>使用FastDFS作为静态资源存储器在其上实现热静态资源缓存、淘汰等功能</li>
<li>运用Hbase技术存储系统中的冷数据保证系统数据的可靠性</li>
<li>运用ES搜索技术对冷数据、文章数据建立索引以保证冷数据、文章查询性能</li>
<li>运用AI技术来完成系统自动化功能以提升效率及节省成本。比如实名认证自动化</li>
<li>PMD&amp;P3C : 静态代码扫描工具,在项目中扫描项目代码,检查异常点、优化点、代码规范等,为开发团队提供规范统一,提升项目代码质量</li>
</ul>
<p><strong>技术栈</strong></p>
<p><img src="/pictures/image-20230809170653756.png" alt="image-20230809170653756"></p>
<p><strong>解决方案</strong></p>
<p><img src="/pictures/image-20230809170929986.png" alt="image-20230809170929986"></p>
<h1 id="二-环境搭建"><a href="#二-环境搭建" class="headerlink" title="二.环境搭建"></a>二.环境搭建</h1><h2 id="1-Linxu环境的搭建"><a href="#1-Linxu环境的搭建" class="headerlink" title="1.Linxu环境的搭建"></a>1.Linxu环境的搭建</h2><h3 id="1-1-虚拟机的安装"><a href="#1-1-虚拟机的安装" class="headerlink" title="1.1 虚拟机的安装"></a>1.1 虚拟机的安装</h3><p><strong>1.解压分享的虚拟机镜像文件</strong></p>
<p><img src="/pictures/image-20230811103629846.png" alt="image-20230811103629846"></p>
<p><strong>2.使用VmWare打开.vmx文件</strong><br><img src="/pictures/image-20230811103800217.png" alt="image-20230811103800217"></p>
<p><strong>3.配置虚拟机的网络环境</strong></p>
<p><img src="/pictures/image-20230811104150226.png" alt="image-20230811104150226"></p>
<p><img src="/pictures/image-20230811104320075.png" alt="image-20230811104320075"></p>
<p><strong>4.开启虚拟机</strong></p>
<p><img src="/pictures/image-20230811104523506.png" alt="image-20230811104523506"></p>
<p><strong>5.使用FinalShell连接此虚拟机</strong></p>
<p>用户名: root 密码:root IP地址: 192.168.200.130</p>
<p><img src="/pictures/image-20230811104741394.png" alt="image-20230811104741394"></p>
<h3 id="1-2-Linux软件安装"><a href="#1-2-Linux软件安装" class="headerlink" title="1.2 Linux软件安装"></a>1.2 Linux软件安装</h3><p><strong><a href="https://qingling.icu/posts/20683.html">Linux中开发环境的搭建 | The Blog (qingling.icu)</a></strong></p>
<h2 id="2-开发环境的配置"><a href="#2-开发环境的配置" class="headerlink" title="2.开发环境的配置"></a>2.开发环境的配置</h2><h3 id="2-1-项目依赖的环境"><a href="#2-1-项目依赖的环境" class="headerlink" title="2.1 项目依赖的环境"></a>2.1 项目依赖的环境</h3><ul>
<li><p><strong>JDK1.8</strong></p>
</li>
<li><p><strong>Intellij Idea</strong></p>
</li>
<li><p><strong>maven-3.6.1</strong></p>
</li>
<li><p><strong>Git</strong></p>
</li>
</ul>
<h3 id="2-2-后端工程的搭建"><a href="#2-2-后端工程的搭建" class="headerlink" title="2.2 后端工程的搭建"></a>2.2 后端工程的搭建</h3><p><img src="/pictures/image-20230811160530674.png" alt="image-20230811160530674"></p>
<p>解压heima-leadnews.zip文件并用IDEA工具打开</p>
<p><img src="/pictures/image-20230811152915886.png" alt="image-20230811152915886"></p>
<p>编码格式的设置</p>
<p><img src="/pictures/image-20230811154426723.png" alt="image-20230811154426723"></p>
<h1 id="三-app端功能开发"><a href="#三-app端功能开发" class="headerlink" title="三.app端功能开发"></a>三.app端功能开发</h1><h2 id="1-app登录"><a href="#1-app登录" class="headerlink" title="1.app登录"></a>1.app登录</h2><p>登录相关的表结构</p>
<table>
<thead>
<tr>
<th><strong>表名称</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>ap_user</td>
<td>APP用户信息表</td>
</tr>
<tr>
<td>ap_user_fan</td>
<td>APP用户粉丝信息表</td>
</tr>
<tr>
<td>ap_user_follow</td>
<td>APP用户关注信息表</td>
</tr>
<tr>
<td>ap_user_realname</td>
<td>APP实名认证信息表</td>
</tr>
</tbody></table>
<p>ap_user表对应的实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.user.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * APP用户信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;ap_user&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ApUser</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 主键</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 密码、通信等加密盐</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;salt&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String salt;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 用户名</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;name&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 密码,md5加密</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;password&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String password;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 手机号</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;phone&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String phone;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 头像</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;image&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String image;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 0 男</span></span><br><span class="line"><span class="comment"> 1 女</span></span><br><span class="line"><span class="comment"> 2 未知</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;sex&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean sex;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 0 未</span></span><br><span class="line"><span class="comment"> 1 是</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_certification&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean certification;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否身份认证</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_identity_authentication&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean identityAuthentication;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 0正常</span></span><br><span class="line"><span class="comment"> 1锁定</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;status&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean status;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 0 普通用户</span></span><br><span class="line"><span class="comment"> 1 自媒体人</span></span><br><span class="line"><span class="comment"> 2 大V</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;flag&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short flag;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 注册时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;created_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date createdTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="1-1-用户登录逻辑"><a href="#1-1-用户登录逻辑" class="headerlink" title="1.1 用户登录逻辑"></a>1.1 用户登录逻辑</h3><p><strong>注册加盐的过程</strong></p>
<p> 用户在登录的时候会生成一个随机的字符串(salt),这个随机的字符串会加到密码后面然后连同密码加密存储到数据库。</p>
<p><img src="/pictures/image-20230811165505210.png" alt="image-20230811165505210"></p>
<p><strong>登录加盐的过程</strong></p>
<p> 先根据账号查询是否存在该用户如果存在的话根据用户输入的密码和数据库中的salt进行md5加密并和数据库中的密码比对一致的话比对通过不一样的话不通过。</p>
<p><img src="/pictures/image-20230811165808912.png" alt="image-20230811165808912"></p>
<h3 id="1-2-用户模块搭建"><a href="#1-2-用户模块搭建" class="headerlink" title="1.2 用户模块搭建"></a>1.2 用户模块搭建</h3><p>heima-leadnews-service父工程依赖文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-leadnews<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">packaging</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">modules</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">module</span>&gt;</span>heima-leadnews-user<span class="tag">&lt;/<span class="name">module</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">modules</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-leadnews-service<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">maven.compiler.source</span>&gt;</span>8<span class="tag">&lt;/<span class="name">maven.compiler.source</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">maven.compiler.target</span>&gt;</span>8<span class="tag">&lt;/<span class="name">maven.compiler.target</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 数据模型子模块 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-leadnews-model<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 公共子模块 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-leadnews-common<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 远程调用子模块 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-leadnews-feign-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Spring Boot Web starter --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Spring Boot Test测试 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Nacos注册中心 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Nacos配置中心 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-config<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Feign远程调用客户端 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-openfeign<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ol>
<li><p>创建子模块并创建出对应的目录结构</p>
<p>在heima-leadnews-service父工程下创建工程heima-leadnews-user</p>
<p><img src="/pictures/image-20230812172036450.png" alt="image-20230812172036450"></p>
</li>
<li><p>编写用户模块的配置文件</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">51801</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">application:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">leadnews-user</span></span><br><span class="line"> <span class="attr">cloud:</span></span><br><span class="line"> <span class="attr">nacos:</span></span><br><span class="line"> <span class="attr">discovery:</span></span><br><span class="line"> <span class="attr">server-addr:</span> <span class="number">192.168</span><span class="number">.200</span><span class="number">.130</span><span class="string">:8848</span></span><br><span class="line"> <span class="attr">config:</span></span><br><span class="line"> <span class="attr">server-addr:</span> <span class="number">192.168</span><span class="number">.200</span><span class="number">.130</span><span class="string">:8848</span></span><br><span class="line"> <span class="attr">file-extension:</span> <span class="string">yml</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>在配置中心中添加数据库等相关的配置</p>
<p><img src="/pictures/image-20230812173024036.png" alt="image-20230812173024036"></p>
</li>
<li><p>在resources目录下添加日志的配置文件</p>
<p>logback.xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!--定义日志文件的存储地址,使用绝对路径--&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;LOG_HOME&quot;</span> <span class="attr">value</span>=<span class="string">&quot;e:/logs&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- Console 输出设置 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender</span> <span class="attr">name</span>=<span class="string">&quot;CONSOLE&quot;</span> <span class="attr">class</span>=<span class="string">&quot;ch.qos.logback.core.ConsoleAppender&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">encoder</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符--&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">pattern</span>&gt;</span>%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;36&#125; - %msg%n<span class="tag">&lt;/<span class="name">pattern</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">charset</span>&gt;</span>utf8<span class="tag">&lt;/<span class="name">charset</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">encoder</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">appender</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 按照每天生成日志文件 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender</span> <span class="attr">name</span>=<span class="string">&quot;FILE&quot;</span> <span class="attr">class</span>=<span class="string">&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">rollingPolicy</span> <span class="attr">class</span>=<span class="string">&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!--日志文件输出的文件名--&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">fileNamePattern</span>&gt;</span>$&#123;LOG_HOME&#125;/leadnews.%d&#123;yyyy-MM-dd&#125;.log<span class="tag">&lt;/<span class="name">fileNamePattern</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">rollingPolicy</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">encoder</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">pattern</span>&gt;</span>%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;36&#125; - %msg%n<span class="tag">&lt;/<span class="name">pattern</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">encoder</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">appender</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 异步输出 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender</span> <span class="attr">name</span>=<span class="string">&quot;ASYNC&quot;</span> <span class="attr">class</span>=<span class="string">&quot;ch.qos.logback.classic.AsyncAppender&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">discardingThreshold</span>&gt;</span>0<span class="tag">&lt;/<span class="name">discardingThreshold</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">queueSize</span>&gt;</span>512<span class="tag">&lt;/<span class="name">queueSize</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 添加附加的appender,最多只能添加一个 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;FILE&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">appender</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">logger</span> <span class="attr">name</span>=<span class="string">&quot;org.apache.ibatis.cache.decorators.LoggingCache&quot;</span> <span class="attr">level</span>=<span class="string">&quot;DEBUG&quot;</span> <span class="attr">additivity</span>=<span class="string">&quot;false&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;CONSOLE&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">logger</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">logger</span> <span class="attr">name</span>=<span class="string">&quot;org.springframework.boot&quot;</span> <span class="attr">level</span>=<span class="string">&quot;debug&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">root</span> <span class="attr">level</span>=<span class="string">&quot;info&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!--&lt;appender-ref ref=&quot;ASYNC&quot;/&gt;--&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;FILE&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;CONSOLE&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">root</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ol>
<p><strong>遇到的问题:</strong></p>
<ol>
<li><p>问题一:引入@EnableDiscoveryClient注解的时候爆红</p>
<p>解决方案:在heima-leadnews-service父工程下加入如下的注解</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- Feign远程调用客户端 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-openfeign<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="1-3-登录功能实现"><a href="#1-3-登录功能实现" class="headerlink" title="1.3 登录功能实现"></a>1.3 登录功能实现</h3><h4 id="1-3-1-接口定义"><a href="#1-3-1-接口定义" class="headerlink" title="1.3.1 接口定义"></a>1.3.1 接口定义</h4><table>
<thead>
<tr>
<th><strong>接口路径</strong></th>
<th>&#x2F;api&#x2F;v1&#x2F;login&#x2F;login_auth</th>
</tr>
</thead>
<tbody><tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>LoginDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p>LoginDto </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoginDto</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 手机号</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@ApiModelProperty(value = &quot;手机号&quot;,required = true)</span></span><br><span class="line"> <span class="keyword">private</span> String phone;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 密码</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@ApiModelProperty(value = &quot;密码&quot;,required = true)</span></span><br><span class="line"> <span class="keyword">private</span> String password;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>统一返回结果类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.common.dtos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.enums.AppHttpCodeEnum;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 通用的结果返回类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &lt;T&gt;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ResponseResult</span>&lt;T&gt; <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String host;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Integer code;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String errorMessage;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> T data;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ResponseResult</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = <span class="number">200</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ResponseResult</span><span class="params">(Integer code, T data)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ResponseResult</span><span class="params">(Integer code, String msg, T data)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.errorMessage = msg;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ResponseResult</span><span class="params">(Integer code, String msg)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.errorMessage = msg;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">errorResult</span><span class="params">(<span class="type">int</span> code, String msg)</span> &#123;</span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ResponseResult</span>();</span><br><span class="line"> <span class="keyword">return</span> result.error(code, msg);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">okResult</span><span class="params">(<span class="type">int</span> code, String msg)</span> &#123;</span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ResponseResult</span>();</span><br><span class="line"> <span class="keyword">return</span> result.ok(code, <span class="literal">null</span>, msg);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">okResult</span><span class="params">(Object data)</span> &#123;</span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage());</span><br><span class="line"> <span class="keyword">if</span>(data!=<span class="literal">null</span>) &#123;</span><br><span class="line"> result.setData(data);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">errorResult</span><span class="params">(AppHttpCodeEnum enums)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> setAppHttpCodeEnum(enums,enums.getErrorMessage());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">errorResult</span><span class="params">(AppHttpCodeEnum enums, String errorMessage)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> setAppHttpCodeEnum(enums,errorMessage);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> ResponseResult <span class="title function_">setAppHttpCodeEnum</span><span class="params">(AppHttpCodeEnum enums)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> okResult(enums.getCode(),enums.getErrorMessage());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> ResponseResult <span class="title function_">setAppHttpCodeEnum</span><span class="params">(AppHttpCodeEnum enums, String errorMessage)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> okResult(enums.getCode(),errorMessage);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;?&gt; error(Integer code, String msg) &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.errorMessage = msg;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;?&gt; ok(Integer code, T data) &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;?&gt; ok(Integer code, T data, String msg) &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> <span class="built_in">this</span>.errorMessage = msg;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;?&gt; ok(T data) &#123;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Integer <span class="title function_">getCode</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> code;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setCode</span><span class="params">(Integer code)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getErrorMessage</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> errorMessage;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setErrorMessage</span><span class="params">(String errorMessage)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.errorMessage = errorMessage;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> T <span class="title function_">getData</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> data;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setData</span><span class="params">(T data)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getHost</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> host;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setHost</span><span class="params">(String host)</span> &#123;</span><br><span class="line"> <span class="built_in">this</span>.host = host;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"> <span class="comment">//前置</span></span><br><span class="line"> <span class="comment">/*AppHttpCodeEnum success = AppHttpCodeEnum.SUCCESS;</span></span><br><span class="line"><span class="comment"> System.out.println(success.getCode());</span></span><br><span class="line"><span class="comment"> System.out.println(success.getErrorMessage());*/</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//查询一个对象</span></span><br><span class="line"> <span class="comment">/*Map map = new HashMap();</span></span><br><span class="line"><span class="comment"> map.put(&quot;name&quot;,&quot;zhangsan&quot;);</span></span><br><span class="line"><span class="comment"> map.put(&quot;age&quot;,18);</span></span><br><span class="line"><span class="comment"> ResponseResult result = ResponseResult.okResult(map);</span></span><br><span class="line"><span class="comment"> System.out.println(JSON.toJSONString(result));*/</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//新增,修改,删除 在项目中统一返回成功即可</span></span><br><span class="line"> <span class="comment">/* ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.SUCCESS);</span></span><br><span class="line"><span class="comment"> System.out.println(JSON.toJSONString(result));*/</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//根据不用的业务返回不同的提示信息 比如:当前操作需要登录、参数错误</span></span><br><span class="line"> <span class="comment">/*ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span></span><br><span class="line"><span class="comment"> System.out.println(JSON.toJSONString(result));*/</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//查询分页信息</span></span><br><span class="line"> <span class="type">PageResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageResponseResult</span>(<span class="number">1</span>,<span class="number">5</span>,<span class="number">50</span>);</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> list.add(<span class="string">&quot;itcast&quot;</span>);</span><br><span class="line"> list.add(<span class="string">&quot;itheima&quot;</span>);</span><br><span class="line"> responseResult.setData(list);</span><br><span class="line"> System.out.println(JSON.toJSONString(responseResult));</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="1-3-2-登录思路分析"><a href="#1-3-2-登录思路分析" class="headerlink" title="1.3.2 登录思路分析"></a>1.3.2 登录思路分析</h4><p><img src="/pictures/image-20230812180918302.png" alt="image-20230812180918302"></p>
<h4 id="1-3-3-登录关键代码实现"><a href="#1-3-3-登录关键代码实现" class="headerlink" title="1.3.3 登录关键代码实现"></a>1.3.3 登录关键代码实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.user.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.toolkit.Wrappers;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.enums.AppHttpCodeEnum;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.user.dtos.LoginDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.user.pojos.ApUser;</span><br><span class="line"><span class="keyword">import</span> com.heima.user.mapper.ApUserMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.user.service.ApUserService;</span><br><span class="line"><span class="keyword">import</span> com.heima.utils.common.AppJwtUtil;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"><span class="keyword">import</span> org.springframework.util.DigestUtils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/8/12</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ApUserServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span>&lt;ApUserMapper, ApUser&gt; <span class="keyword">implements</span> <span class="title class_">ApUserService</span> &#123;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">login</span><span class="params">(LoginDto loginDto)</span> &#123;</span><br><span class="line"> <span class="comment">//1 正常的登录 用户名和密码</span></span><br><span class="line"> <span class="keyword">if</span>(StringUtils.isNotBlank(loginDto.getPhone()) &amp;&amp; StringUtils.isNotBlank(loginDto.getPassword())) &#123;</span><br><span class="line"> <span class="comment">//1.1 根据手机号查询用户的信息</span></span><br><span class="line"> <span class="type">ApUser</span> <span class="variable">dbUser</span> <span class="operator">=</span> getOne(<span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;ApUser&gt;().eq(ApUser::getPhone, loginDto.getPhone()));</span><br><span class="line"> <span class="keyword">if</span>(dbUser == <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,<span class="string">&quot;用户信息不存在&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="type">String</span> <span class="variable">salt</span> <span class="operator">=</span> dbUser.getSalt();</span><br><span class="line"> <span class="type">String</span> <span class="variable">password</span> <span class="operator">=</span> loginDto.getPassword();</span><br><span class="line"> <span class="type">String</span> <span class="variable">pwd</span> <span class="operator">=</span> DigestUtils.md5DigestAsHex((password + salt).getBytes());</span><br><span class="line"> <span class="comment">//1.2 比对密码</span></span><br><span class="line"> <span class="keyword">if</span>(!pwd.equals(dbUser.getPassword()))&#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//1.3 生成token</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> AppJwtUtil.getToken(dbUser.getId().longValue());</span><br><span class="line"> Map&lt;String,Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;token&quot;</span>,token);</span><br><span class="line"> dbUser.setSalt(<span class="string">&quot;&quot;</span>);</span><br><span class="line"> dbUser.setPassword(<span class="string">&quot;&quot;</span>);</span><br><span class="line"> map.put(<span class="string">&quot;user&quot;</span>,dbUser);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(map);</span><br><span class="line"> &#125;<span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//2.游客登录</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> AppJwtUtil.getToken(<span class="number">0L</span>);</span><br><span class="line"> Map&lt;String,Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;token&quot;</span>,token);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(map);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="1-3-4-使用接口工具测试"><a href="#1-3-4-使用接口工具测试" class="headerlink" title="1.3.4 使用接口工具测试"></a>1.3.4 使用接口工具测试</h4><p>接口测试工具使用教程:<a href="https://qingling.icu/posts/35630.html">https://qingling.icu/posts/35630.html</a></p>
<p><img src="/pictures/image-20230813165436808.png" alt="image-20230813165436808"></p>
<h2 id="2-app端网关搭建"><a href="#2-app端网关搭建" class="headerlink" title="2. app端网关搭建"></a>2. app端网关搭建</h2><p>网关的概述</p>
<p><img src="/pictures/image-20230814142355139.png" alt="image-20230814142355139"></p>
<p>项目中搭建的网关</p>
<p><img src="/pictures/image-20230814142700349.png" alt="image-20230814142700349"></p>
<h3 id="2-1-搭建过程"><a href="#2-1-搭建过程" class="headerlink" title="2.1 搭建过程"></a>2.1 搭建过程</h3><p><strong>1.在heima-leadnews-gateway导入以下依赖</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-gateway<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-config<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.jsonwebtoken<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jjwt<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>2.创建网关的模块</strong></p>
<p><img src="/pictures/image-20230814143113564.png" alt="image-20230814143113564"></p>
<p><strong>3.创建启动类和bootstrap.yml配置文件</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableDiscoveryClient</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AppGatewayApplication</span> &#123;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"> SpringApplication.run(AppGatewayApplication.class,args);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">51601</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">application:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">leadnews-app-gateway</span></span><br><span class="line"> <span class="attr">cloud:</span></span><br><span class="line"> <span class="attr">nacos:</span></span><br><span class="line"> <span class="attr">discovery:</span></span><br><span class="line"> <span class="attr">server-addr:</span> <span class="number">192.168</span><span class="number">.200</span><span class="number">.130</span><span class="string">:8848</span></span><br><span class="line"> <span class="attr">config:</span></span><br><span class="line"> <span class="attr">server-addr:</span> <span class="number">192.168</span><span class="number">.200</span><span class="number">.130</span><span class="string">:8848</span></span><br><span class="line"> <span class="attr">file-extension:</span> <span class="string">yml</span></span><br></pre></td></tr></table></figure>
<p><strong>4.在nacos中创建app端网关的配置</strong></p>
<p><img src="/pictures/image-20230814143939252.png" alt="image-20230814143939252"></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">cloud:</span></span><br><span class="line"> <span class="attr">gateway:</span></span><br><span class="line"> <span class="attr">globalcors:</span></span><br><span class="line"> <span class="attr">add-to-simple-url-handler-mapping:</span> <span class="literal">true</span></span><br><span class="line"> <span class="attr">corsConfigurations:</span></span><br><span class="line"> <span class="string">&#x27;[/**]&#x27;</span><span class="string">:</span></span><br><span class="line"> <span class="attr">allowedHeaders:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line"> <span class="attr">allowedOrigins:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line"> <span class="attr">allowedMethods:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">GET</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">POST</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">DELETE</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">PUT</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">OPTION</span></span><br><span class="line"> <span class="attr">routes:</span></span><br><span class="line"> <span class="comment"># 平台管理</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">user</span></span><br><span class="line"> <span class="attr">uri:</span> <span class="string">lb://leadnews-user</span></span><br><span class="line"> <span class="attr">predicates:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">Path=/user/**</span></span><br><span class="line"> <span class="attr">filters:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">StripPrefix=</span> <span class="number">1</span></span><br></pre></td></tr></table></figure>
<p><strong>5.使用Postman测试网关</strong></p>
<p><a target="_blank" rel="noopener" href="http://localhost:51601/user/api/v1/login/login_auth">http://localhost:51601/user/api/v1/login/login_auth</a></p>
<p><img src="/pictures/image-20230814144314358.png" alt="image-20230814144314358"></p>
<h3 id="2-2-全局过滤器实现jwt校验"><a href="#2-2-全局过滤器实现jwt校验" class="headerlink" title="2.2 全局过滤器实现jwt校验"></a>2.2 全局过滤器实现jwt校验</h3><p>网关的过滤流程</p>
<p><img src="/pictures/image-20230814144806282.png" alt="image-20230814144806282"></p>
<p>思路分析:</p>
<ol>
<li>用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录</li>
<li>用户登录成功后台管理微服务签发JWT TOKEN信息返回给用户</li>
<li>用户再次进入网关开始访问网关过滤器接收用户携带的TOKEN </li>
<li>网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误</li>
</ol>
<p><strong>JWT认证的过滤器</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/8/14</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 权限认证的过滤器</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthorizeFilter</span> <span class="keyword">implements</span> <span class="title class_">Ordered</span>, GlobalFilter &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 过滤的设置</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> Mono&lt;Void&gt; <span class="title function_">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span> &#123;</span><br><span class="line"> <span class="comment">//1.获取request和response对象</span></span><br><span class="line"> <span class="type">ServerHttpRequest</span> <span class="variable">request</span> <span class="operator">=</span> exchange.getRequest();</span><br><span class="line"> <span class="type">ServerHttpResponse</span> <span class="variable">response</span> <span class="operator">=</span> exchange.getResponse();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.判断是否登录</span></span><br><span class="line"> <span class="comment">//通过请求的路径的url判断</span></span><br><span class="line"> <span class="keyword">if</span> (request.getURI().getPath().contains(<span class="string">&quot;/login&quot;</span>)) &#123;</span><br><span class="line"> <span class="comment">//放行</span></span><br><span class="line"> <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//3.获取token</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> request.getHeaders().getFirst(<span class="string">&quot;token&quot;</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//4.判断token是否存在</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isBlank(token)) &#123;</span><br><span class="line"> <span class="comment">//设置401的状态码</span></span><br><span class="line"> response.setStatusCode(HttpStatus.UNAUTHORIZED);</span><br><span class="line"> <span class="keyword">return</span> response.setComplete();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//5.判断token是否有效</span></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//获取token中的数据</span></span><br><span class="line"> <span class="type">Claims</span> <span class="variable">claims</span> <span class="operator">=</span> AppJwtUtil.getClaimsBody(token);</span><br><span class="line"> <span class="comment">//判断token是否过期 -1有效0有效1过期2过期</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">res</span> <span class="operator">=</span> AppJwtUtil.verifyToken(claims);</span><br><span class="line"> <span class="keyword">if</span> (res == <span class="number">1</span> || res == <span class="number">2</span>) &#123;</span><br><span class="line"> <span class="comment">//设置401的状态码</span></span><br><span class="line"> response.setStatusCode(HttpStatus.UNAUTHORIZED);</span><br><span class="line"> <span class="keyword">return</span> response.setComplete();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="comment">//设置401的状态码</span></span><br><span class="line"> response.setStatusCode(HttpStatus.UNAUTHORIZED);</span><br><span class="line"> <span class="keyword">return</span> response.setComplete();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//6.放行</span></span><br><span class="line"> <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 优先级设置 值越小 优先值越高</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getOrder</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="3-app前端项目集成"><a href="#3-app前端项目集成" class="headerlink" title="3.app前端项目集成"></a>3.app前端项目集成</h2><p><img src="/pictures/image-20230814151319382.png" alt="image-20230814151319382"></p>
<p>通过nginx来进行配置功能如下</p>
<ul>
<li>通过nginx的反向代理功能访问后台的网关资源</li>
<li>通过nginx的静态服务器功能访问前端静态页面</li>
</ul>
<h3 id="3-1-Nginx集成前端项目步骤"><a href="#3-1-Nginx集成前端项目步骤" class="headerlink" title="3.1 Nginx集成前端项目步骤"></a>3.1 Nginx集成前端项目步骤</h3><p><strong>解压资料文件夹中的压缩包nginx-1.18.0.zip</strong></p>
<p>cmd切换到nginx所有的目录输入nginx启动nginx</p>
<p><img src="/pictures/image-20230814152058708.png" alt="image-20230814152058708"></p>
<p><img src="/pictures/image-20230814152144765.png" alt="image-20230814152144765"></p>
<p><strong>解压资料文件夹中的前端项目app-web.zip</strong></p>
<p>解压到一个没有中文的文件夹中后面nginx配置中会指向这个目录</p>
<p><strong>配置nginx.conf文件</strong></p>
<p>在nginx安装的conf目录下新建一个文件夹<code>leadnews.conf</code>,在当前文件夹中新建<code>heima-leadnews-app.conf</code>文件</p>
<p>heima-leadnews-app.conf配置如下</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">upstream heima-app-gateway&#123;</span><br><span class="line"> #APP端网关所在的端口</span><br><span class="line"> server localhost:51601;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line"> listen 8801;</span><br><span class="line"> location / &#123;</span><br><span class="line"> root C:/Gong/data/app-web/;</span><br><span class="line"> index index.html;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> location ~/app/(.*) &#123;</span><br><span class="line"> proxy_pass http://heima-app-gateway/$1;</span><br><span class="line"> proxy_set_header HOST $host; # 不改变源请求头的值</span><br><span class="line"> proxy_pass_request_body on; #开启获取请求体</span><br><span class="line"> proxy_pass_request_headers on; #开启获取请求头</span><br><span class="line"> proxy_set_header X-Real-IP $remote_addr; # 记录真实发出请求的客户端IP</span><br><span class="line"> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>nginx.conf 把里面注释的内容和静态资源配置相关删除引入heima-leadnews-app.conf文件加载</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">#user nobody;</span><br><span class="line">worker_processes <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">events &#123;</span><br><span class="line"> worker_connections <span class="number">1024</span>;</span><br><span class="line">&#125;</span><br><span class="line">http &#123;</span><br><span class="line"> include mime.<span class="property">types</span>;</span><br><span class="line"> default_type application/octet-stream;</span><br><span class="line"> sendfile on;</span><br><span class="line"> keepalive_timeout <span class="number">65</span>;</span><br><span class="line"> # 引入自定义配置文件</span><br><span class="line"> include leadnews.<span class="property">conf</span><span class="comment">/*.conf;</span></span><br><span class="line"><span class="comment">&#125;</span></span><br></pre></td></tr></table></figure>
<p><strong>启动nginx</strong></p>
<p> 在nginx安装包中使用命令提示符打开输入命令nginx启动项目</p>
<p> 可查看进程检查nginx是否启动</p>
<p> 重新加载配置文件:<code>nginx -s reload</code></p>
<p><strong>⑤:打开前端项目进行测试 &gt; <a target="_blank" rel="noopener" href="http://localhost:8801/">http://localhost:8801</a></strong></p>
<p> 用谷歌浏览器打开,调试移动端模式进行访问</p>
<p><img src="/pictures/image-20230814153335349.png" alt="image-20230814153335349"></p>
<h2 id="4-app端文章列表功能"><a href="#4-app端文章列表功能" class="headerlink" title="4.app端文章列表功能"></a>4.app端文章列表功能</h2><p><strong>开发前app的首页面</strong></p>
<p><img src="/pictures/image-20230814154205134.png" alt="image-20230814154205134"></p>
<p><strong>文章的布局展示</strong></p>
<p><img src="/pictures/image-20230814154405531.png" alt="image-20230814154405531"></p>
<h3 id="4-1-数据库表的创建"><a href="#4-1-数据库表的创建" class="headerlink" title="4.1 数据库表的创建"></a>4.1 数据库表的创建</h3><p><strong>文章的相关的数据库</strong></p>
<table>
<thead>
<tr>
<th><strong>表名称</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>ap_article</td>
<td>文章信息表,存储已发布的文章</td>
</tr>
<tr>
<td>ap_article_config</td>
<td>APP已发布文章配置表</td>
</tr>
<tr>
<td>ap_article_content</td>
<td>APP已发布文章内容表</td>
</tr>
<tr>
<td>ap_author</td>
<td>APP文章作者信息表</td>
</tr>
<tr>
<td>ap_collection</td>
<td>APP收藏信息表</td>
</tr>
</tbody></table>
<p><strong>导入资料中的sql文件创建相关的数据库表</strong></p>
<p><img src="/pictures/image-20230814160312382.png" alt="image-20230814160312382"></p>
<p><strong>关键的数据库表</strong></p>
<p>文章基本信息表</p>
<p><img src="/pictures/image-20230814160547893.png" alt="image-20230814160547893"></p>
<p> APP已发布文章配置表 </p>
<p><img src="/pictures/image-20230814160652330.png" alt="image-20230814160652330"></p>
<p>APP已发布文章内容表 </p>
<p><img src="/pictures/image-20230814160728715.png" alt="image-20230814160728715"></p>
<p>APP文章作者信息表 </p>
<p><img src="/pictures/image-20230814160805398.png" alt="image-20230814160805398"></p>
<p>APP收藏信息表 </p>
<p><img src="/pictures/image-20230814160823771.png" alt="image-20230814160823771"></p>
<p><strong>垂直分表</strong></p>
<p>将文章相关的表分成文章配置表和文章内容表和文章信息表</p>
<p><img src="/pictures/image-20230814161909312.png" alt="image-20230814161909312"></p>
<p>垂直分表:将一个表的字段分散到多个表中,每个表存储其中一部分字段</p>
<p><strong>优势:</strong></p>
<ol>
<li><p>减少IO争抢减少锁表的几率查看文章概述与文章详情互不影响</p>
</li>
<li><p>充分发挥高频数据的操作效率,对文章概述数据操作的高效率不会被操作文章详情数据的低效率所拖累</p>
</li>
</ol>
<p><strong>拆分规则:</strong></p>
<p>1.把不常用的字段单独放在一张表</p>
<p>2.把textblob等大字段拆分出来单独放在一张表</p>
<p>3.经常组合查询的字段单独放在一张表中</p>
<h3 id="4-2-文章模块搭建"><a href="#4-2-文章模块搭建" class="headerlink" title="4.2 文章模块搭建"></a>4.2 文章模块搭建</h3><p><strong>导入资料中的模块</strong></p>
<p><img src="/pictures/image-20230815184540157.png" alt="image-20230815184540157"></p>
<p><strong>在nacos中添加配置</strong></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">datasource:</span></span><br><span class="line"> <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line"> <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/leadnews_article?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC</span></span><br><span class="line"> <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line"> <span class="attr">password:</span> <span class="number">123456</span></span><br><span class="line"><span class="comment"># 设置Mapper接口所对应的XML文件位置如果你在Mapper接口中有自定义方法需要进行该配置</span></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line"> <span class="attr">mapper-locations:</span> <span class="string">classpath*:mapper/*.xml</span></span><br><span class="line"> <span class="comment"># 设置别名包扫描路径,通过该属性可以给包中的类注册别名</span></span><br><span class="line"> <span class="attr">type-aliases-package:</span> <span class="string">com.heima.model.article.pojos</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20230815162119814.png" alt="image-20230815162119814"></p>
<p><strong>踩坑</strong>: 在导入项目的时候提示Caused by: java.io.FileNotFoundException: class path resource [com&#x2F;heima&#x2F;apis&#x2F;article&#x2F;IArticleClient.class] cannot be opened because it does not exist ,先删除这个项目,手动创建这个项目,然后复制资料里面文件到这个项目即可,直接复制整个项目可能会报这个错!</p>
<h3 id="4-3-首页文章的列表显示"><a href="#4-3-首页文章的列表显示" class="headerlink" title="4.3 首页文章的列表显示"></a>4.3 首页文章的列表显示</h3><p><strong>首页上拉和下拉的实现思路</strong></p>
<p><img src="/pictures/image-20230814163019582.png" alt="image-20230814163019582"></p>
<p><strong>Sql语句实现</strong></p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">#按照发布时间倒序查询十条文章</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> ap_article aa <span class="keyword">order</span> <span class="keyword">by</span> aa.publish_time <span class="keyword">desc</span> limit <span class="number">10</span></span><br><span class="line">#频道筛选</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> ap_article aa <span class="keyword">where</span> aa.channel_id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">order</span> <span class="keyword">by</span> aa.publish_time <span class="keyword">desc</span> limit <span class="number">10</span></span><br><span class="line">#加载首页</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> ap_article aa <span class="keyword">where</span> aa.channel_id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> aa.publish_time <span class="operator">&lt;</span> <span class="string">&#x27;2063-09-08 10:20:12&#x27;</span> <span class="keyword">order</span> <span class="keyword">by</span> aa.publish_time <span class="keyword">desc</span> limit <span class="number">10</span></span><br><span class="line">#加载更多</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> ap_article aa <span class="keyword">where</span> aa.channel_id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> aa.publish_time <span class="operator">&lt;</span> <span class="string">&#x27;2020-09-07 22:30:09&#x27;</span> <span class="keyword">order</span> <span class="keyword">by</span> aa.publish_time <span class="keyword">desc</span> limit <span class="number">10</span></span><br><span class="line">#加载最新</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> ap_article aa <span class="keyword">where</span> aa.channel_id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> aa.publish_time <span class="operator">&gt;</span> <span class="string">&#x27;2020-09-07 22:30:09&#x27;</span> <span class="keyword">order</span> <span class="keyword">by</span> aa.publish_time <span class="keyword">desc</span> limit <span class="number">10</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20230815160034436.png" alt="image-20230815160034436"></p>
<h4 id="4-2-1-接口定义"><a href="#4-2-1-接口定义" class="headerlink" title="4.2.1 接口定义"></a>4.2.1 接口定义</h4><table>
<thead>
<tr>
<th></th>
<th><strong>加载首页</strong></th>
<th><strong>加载更多</strong></th>
<th><strong>加载最新</strong></th>
</tr>
</thead>
<tbody><tr>
<td>接口路径</td>
<td>&#x2F;api&#x2F;v1&#x2F;article&#x2F;load</td>
<td>&#x2F;api&#x2F;v1&#x2F;article&#x2F;loadmore</td>
<td>&#x2F;api&#x2F;v1&#x2F;article&#x2F;loadnew</td>
</tr>
<tr>
<td>请求方式</td>
<td>POST</td>
<td>POST</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>ArticleHomeDto</td>
<td>ArticleHomeDto</td>
<td>ArticleHomeDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
<td>ResponseResult</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p>ArticleHomeDto</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.article.dtos;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleHomeDto</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 最大时间</span></span><br><span class="line"> Date maxBehotTime;</span><br><span class="line"> <span class="comment">// 最小时间</span></span><br><span class="line"> Date minBehotTime;</span><br><span class="line"> <span class="comment">// 分页size</span></span><br><span class="line"> Integer size;</span><br><span class="line"> <span class="comment">// 频道ID</span></span><br><span class="line"> String tag;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="4-2-2-实现思路"><a href="#4-2-2-实现思路" class="headerlink" title="4.2.2 实现思路"></a>4.2.2 实现思路</h4><p><strong>导入heima-leadnews-article微服务资料在当天的文件夹中</strong></p>
<p> <strong>需要在nacos中添加对应的配置</strong></p>
<p><strong>②:定义接口</strong></p>
<p> <strong>接口路径、请求方式、入参、出参</strong></p>
<p><strong>编写mapper文件</strong></p>
<p> <strong>文章表与文章配置表多表查询</strong></p>
<p><strong>④:编写业务层代码</strong></p>
<p><strong>⑤:编写控制器代码</strong></p>
<p><strong>swagger测试或前后端联调测试</strong></p>
<h4 id="4-2-3-功能的关键代码实现"><a href="#4-2-3-功能的关键代码实现" class="headerlink" title="4.2.3 功能的关键代码实现"></a>4.2.3 功能的关键代码实现</h4><p>mapper层的代码</p>
<p><img src="/pictures/image-20230816142705510.png" alt="image-20230816142705510"></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span> <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.heima.article.mapper.ApArticleMapper&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;resultMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;com.heima.model.article.pojos.ApArticle&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;title&quot;</span> <span class="attr">property</span>=<span class="string">&quot;title&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;author_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;authorId&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;author_name&quot;</span> <span class="attr">property</span>=<span class="string">&quot;authorName&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;channel_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;channelId&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;channel_name&quot;</span> <span class="attr">property</span>=<span class="string">&quot;channelName&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;layout&quot;</span> <span class="attr">property</span>=<span class="string">&quot;layout&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;flag&quot;</span> <span class="attr">property</span>=<span class="string">&quot;flag&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;images&quot;</span> <span class="attr">property</span>=<span class="string">&quot;images&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;labels&quot;</span> <span class="attr">property</span>=<span class="string">&quot;labels&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;likes&quot;</span> <span class="attr">property</span>=<span class="string">&quot;likes&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;collection&quot;</span> <span class="attr">property</span>=<span class="string">&quot;collection&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;comment&quot;</span> <span class="attr">property</span>=<span class="string">&quot;comment&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;views&quot;</span> <span class="attr">property</span>=<span class="string">&quot;views&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;province_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;provinceId&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;city_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;cityId&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;county_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;countyId&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;created_time&quot;</span> <span class="attr">property</span>=<span class="string">&quot;createdTime&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;publish_time&quot;</span> <span class="attr">property</span>=<span class="string">&quot;publishTime&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;sync_status&quot;</span> <span class="attr">property</span>=<span class="string">&quot;syncStatus&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;static_url&quot;</span> <span class="attr">property</span>=<span class="string">&quot;staticUrl&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;loadArticleList&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;resultMap&quot;</span>&gt;</span></span><br><span class="line"> SELECT</span><br><span class="line"> aa.*</span><br><span class="line"> FROM</span><br><span class="line"> `ap_article` aa</span><br><span class="line"> LEFT JOIN ap_article_config aac ON aa.id = aac.article_id</span><br><span class="line"> <span class="tag">&lt;<span class="name">where</span>&gt;</span></span><br><span class="line"> and aac.is_delete != 1</span><br><span class="line"> and aac.is_down != 1</span><br><span class="line"> <span class="comment">&lt;!-- loadmore --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;type != null and type == 1&quot;</span>&gt;</span></span><br><span class="line"> and aa.publish_time &lt;![CDATA[&lt;]]&gt; #&#123;dto.minBehotTime&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;type != null and type == 2&quot;</span>&gt;</span></span><br><span class="line"> and aa.publish_time &lt;![CDATA[&gt;]]&gt; #&#123;dto.maxBehotTime&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;dto.tag != &#x27;__all__&#x27;&quot;</span>&gt;</span></span><br><span class="line"> and aa.channel_id = #&#123;dto.tag&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">where</span>&gt;</span></span><br><span class="line"> order by aa.publish_time desc</span><br><span class="line"> limit #&#123;dto.size&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>service层的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.service.Impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.mapper.ApArticleMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ApArticleService;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.constants.ArticleConstants;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleHomeDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticle;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/8/15</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ApArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span>&lt;ApArticleMapper, ApArticle&gt; <span class="keyword">implements</span> <span class="title class_">ApArticleService</span> &#123;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleMapper apArticleMapper;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Integer</span> <span class="variable">MAX_PAGE_SIZE</span> <span class="operator">=</span> <span class="number">50</span>;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">load</span><span class="params">(ArticleHomeDto dto, Short type)</span> &#123;</span><br><span class="line"> <span class="comment">//1.参数校验</span></span><br><span class="line"> <span class="comment">//分页条数的校验</span></span><br><span class="line"> <span class="type">Integer</span> <span class="variable">size</span> <span class="operator">=</span> dto.getSize();</span><br><span class="line"> <span class="keyword">if</span> (size == <span class="literal">null</span> || size == <span class="number">0</span>) &#123;</span><br><span class="line"> size = <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//最大分页条数的限制</span></span><br><span class="line"> size = Math.min(size, <span class="number">50</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//type参数的校验</span></span><br><span class="line"> <span class="keyword">if</span> (!type.equals(ArticleConstants.LOADTYPE_LOAD_MORE) &amp;&amp; !type.equals(ArticleConstants.LOADTYPE_LOAD_NEW)) &#123;</span><br><span class="line"> type = <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//频道参数校验</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isBlank(dto.getTag())) &#123;</span><br><span class="line"> dto.setTag(ArticleConstants.DEFAULT_TAG);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//时间检验</span></span><br><span class="line"> <span class="keyword">if</span> (dto.getMinBehotTime() == <span class="literal">null</span>) dto.setMinBehotTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> <span class="keyword">if</span> (dto.getMaxBehotTime() == <span class="literal">null</span>) dto.setMaxBehotTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.查询</span></span><br><span class="line"> List&lt;ApArticle&gt; apArticles = apArticleMapper.loadArticleList(dto, type);</span><br><span class="line"> <span class="comment">//3.数据返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(apArticles);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>controller层的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.controller.v1;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ApArticleService;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.constants.ArticleConstants;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleHomeDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.*;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/8/15</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/api/v1/article&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleHomeController</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleService apArticleService;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 加载首页</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@PostMapping(&quot;/load&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;Object&gt; <span class="title function_">load</span><span class="params">(<span class="meta">@RequestBody</span> ArticleHomeDto articleHomeDto)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> apArticleService.load(articleHomeDto, ArticleConstants.LOADTYPE_LOAD_MORE);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 加载更多</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@PostMapping(&quot;/loadmore&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;Object&gt; <span class="title function_">loadmore</span><span class="params">(<span class="meta">@RequestBody</span> ArticleHomeDto articleHomeDto)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> apArticleService.load(articleHomeDto, ArticleConstants.LOADTYPE_LOAD_MORE);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 加载更新</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@PostMapping(&quot;/loadnew&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult&lt;Object&gt; <span class="title function_">loadnew</span><span class="params">(<span class="meta">@RequestBody</span> ArticleHomeDto articleHomeDto)</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> apArticleService.load(articleHomeDto, ArticleConstants.LOADTYPE_LOAD_NEW);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>网关中增加文章模块的路由</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">cloud:</span></span><br><span class="line"> <span class="attr">gateway:</span></span><br><span class="line"> <span class="attr">globalcors:</span></span><br><span class="line"> <span class="attr">add-to-simple-url-handler-mapping:</span> <span class="literal">true</span></span><br><span class="line"> <span class="attr">corsConfigurations:</span></span><br><span class="line"> <span class="string">&#x27;[/**]&#x27;</span><span class="string">:</span></span><br><span class="line"> <span class="attr">allowedHeaders:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line"> <span class="attr">allowedOrigins:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line"> <span class="attr">allowedMethods:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">GET</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">POST</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">DELETE</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">PUT</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">OPTION</span></span><br><span class="line"> <span class="attr">routes:</span></span><br><span class="line"> <span class="comment"># 平台管理</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">user</span></span><br><span class="line"> <span class="attr">uri:</span> <span class="string">lb://leadnews-user</span></span><br><span class="line"> <span class="attr">predicates:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">Path=/user/**</span></span><br><span class="line"> <span class="attr">filters:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">StripPrefix=</span> <span class="number">1</span></span><br><span class="line"> <span class="comment"># 文章管理</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">article</span></span><br><span class="line"> <span class="attr">uri:</span> <span class="string">lb://leadnews-article</span></span><br><span class="line"> <span class="attr">predicates:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">Path=/article/**</span></span><br><span class="line"> <span class="attr">filters:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">StripPrefix=</span> <span class="number">1</span></span><br></pre></td></tr></table></figure>
<h2 id="5-app端文章详情功能"><a href="#5-app端文章详情功能" class="headerlink" title="5. app端文章详情功能"></a>5. app端文章详情功能</h2><h3 id="5-1-需求分析"><a href="#5-1-需求分析" class="headerlink" title="5.1 需求分析"></a>5.1 需求分析</h3><p><img src="/pictures/image-20230816143201242.png" alt="image-20230816143201242"></p>
<h3 id="5-2-实现方案-静态模板展示"><a href="#5-2-实现方案-静态模板展示" class="headerlink" title="5.2 实现方案-静态模板展示"></a>5.2 实现方案-静态模板展示</h3><p><img src="/pictures/image-20230816143544351.png" alt="image-20230816143544351"></p>
<p><strong>静态模板展示关键技术-Freemarker</strong></p>
<p>Freemarker教程: <a href="https://qingling.icu/posts/29367.html">https://qingling.icu/posts/29367.html</a></p>
<h3 id="5-3-对象存储服务MinIO"><a href="#5-3-对象存储服务MinIO" class="headerlink" title="5.3 对象存储服务MinIO"></a>5.3 对象存储服务MinIO</h3><p>MinIO 教程: <a href="https://qingling.icu/posts/36397.html">https://qingling.icu/posts/36397.html</a></p>
<h3 id="5-4-实现思路以及代码实现"><a href="#5-4-实现思路以及代码实现" class="headerlink" title="5.4 实现思路以及代码实现"></a>5.4 实现思路以及代码实现</h3><p><img src="/pictures/image-20230818210507999.png" alt="image-20230818210507999"></p>
<p><img src="/pictures/image-20230818210638036.png" alt="image-20230818210638036"></p>
<p><strong>代码实现</strong></p>
<p>1.在文章模块的pom.xml文件中加入以下的依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-freemarker<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-file-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>2.在nacos中有关文章模块的配置中添加以下的内容</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">minio:</span></span><br><span class="line"> <span class="attr">accessKey:</span> <span class="string">minio</span></span><br><span class="line"> <span class="attr">secretKey:</span> <span class="string">minio123</span></span><br><span class="line"> <span class="attr">bucket:</span> <span class="string">leadnews</span></span><br><span class="line"> <span class="attr">endpoint:</span> <span class="string">http://192.168.200.130:9000</span></span><br><span class="line"> <span class="attr">readPath:</span> <span class="string">http://192.168.200.130:9000</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20230818211310728.png" alt="image-20230818211310728"></p>
<p>3.将资料中的article.ftl文件拷贝到文章模块的templates目录下article.ftl文件内容如下</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;IE=edge&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">title</span>&gt;</span>黑马头条<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 引入样式文件 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://fastly.jsdelivr.net/npm/vant@2.12.20/lib/index.css&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 页面样式 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;../../../plugins/css/index.css&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;article&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;24&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-title&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-header&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-image</span> <span class="attr">round</span> <span class="attr">class</span>=<span class="string">&quot;article-avatar&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://p3.pstatp.com/thumb/1480/7186611868&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-image</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;16&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">v-html</span>=<span class="string">&quot;authorName&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123; publishTime | timestampToDateTime &#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;5&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">:icon</span>=<span class="string">&quot;relation.isfollow ? &#x27;&#x27; : &#x27;plus&#x27;&quot;</span> <span class="attr">type</span>=<span class="string">&quot;info&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-focus&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">:text</span>=<span class="string">&quot;relation.isfollow ? &#x27;取消关注&#x27; : &#x27;关注&#x27;&quot;</span> <span class="attr">:loading</span>=<span class="string">&quot;followLoading&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleClickArticleFollow&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">class</span>=<span class="string">&quot;article-content&quot;</span>&gt;</span></span><br><span class="line"> &lt;#if content??&gt;</span><br><span class="line"> &lt;#list content as item&gt;</span><br><span class="line"> &lt;#if item.type=&#x27;text&#x27;&gt;</span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;24&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-text&quot;</span>&gt;</span>$&#123;item.value&#125;<span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> &lt;#else&gt;</span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;24&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-image&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-image</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;$&#123;item.value&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-image</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> &lt;/#if&gt;</span><br><span class="line"> &lt;/#list&gt;</span><br><span class="line"> &lt;/#if&gt;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">justify</span>=<span class="string">&quot;center&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-action&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">:icon</span>=<span class="string">&quot;relation.islike ? &#x27;good-job&#x27; : &#x27;good-job-o&#x27;&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-like&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">:loading</span>=<span class="string">&quot;likeLoading&quot;</span> <span class="attr">:text</span>=<span class="string">&quot;relation.islike ? &#x27;取消赞&#x27; : &#x27;点赞&#x27;&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleClickArticleLike&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">:icon</span>=<span class="string">&quot;relation.isunlike ? &#x27;delete&#x27; : &#x27;delete-o&#x27;&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-unlike&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">:loading</span>=<span class="string">&quot;unlikeLoading&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleClickArticleUnlike&quot;</span>&gt;</span>不喜欢<span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 文章评论列表 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-list</span> <span class="attr">v-model</span>=<span class="string">&quot;commentsLoading&quot;</span> <span class="attr">:finished</span>=<span class="string">&quot;commentsFinished&quot;</span> <span class="attr">finished-text</span>=<span class="string">&quot;没有更多了&quot;</span></span></span><br><span class="line"><span class="tag"> @<span class="attr">load</span>=<span class="string">&quot;onLoadArticleComments&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">id</span>=<span class="string">&quot;#comment-view&quot;</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-comment&quot;</span> <span class="attr">v-for</span>=<span class="string">&quot;(item, index) in comments&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;index&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-image</span> <span class="attr">round</span> <span class="attr">src</span>=<span class="string">&quot;https://p3.pstatp.com/thumb/1480/7186611868&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-avatar&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-image</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;21&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span> <span class="attr">justify</span>=<span class="string">&quot;space-between&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">class</span>=<span class="string">&quot;comment-author&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;item.authorName&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">:icon</span>=<span class="string">&quot;item.operation === 0 ? &#x27;good-job&#x27; : &#x27;good-job-o&#x27;&quot;</span> <span class="attr">size</span>=<span class="string">&quot;normal&quot;</span></span></span><br><span class="line"><span class="tag"> @<span class="attr">click</span>=<span class="string">&quot;handleClickCommentLike(item)&quot;</span>&gt;</span>&#123;&#123; item.likes || &#x27;&#x27; &#125;&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">class</span>=<span class="string">&quot;comment-content&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;item.content&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;10&quot;</span> <span class="attr">class</span>=<span class="string">&quot;comment-time&quot;</span>&gt;</span></span><br><span class="line"> &#123;&#123; item.createdTime | timestampToDateTime &#125;&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">size</span>=<span class="string">&quot;normal&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;item.reply&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;showCommentRepliesPopup(item.id)&quot;</span>&gt;</span>回复 &#123;&#123;</span><br><span class="line"> item.reply || &#x27;&#x27; &#125;&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-list</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 文章底部栏 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">justify</span>=<span class="string">&quot;space-around&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-bottom-bar&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;13&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-field</span> <span class="attr">v-model</span>=<span class="string">&quot;commentValue&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;写评论&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">template</span> #<span class="attr">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;back-top&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleSaveComment&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-field</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;comment-o&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleScrollIntoCommentView&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">:icon</span>=<span class="string">&quot;relation.iscollection ? &#x27;star&#x27; : &#x27;star-o&#x27;&quot;</span> <span class="attr">:loading</span>=<span class="string">&quot;collectionLoading&quot;</span></span></span><br><span class="line"><span class="tag"> @<span class="attr">click</span>=<span class="string">&quot;handleClickArticleCollection&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;share-o&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 评论Popup 弹出层 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-popup</span> <span class="attr">v-model</span>=<span class="string">&quot;showPopup&quot;</span> <span class="attr">closeable</span> <span class="attr">position</span>=<span class="string">&quot;bottom&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">:style</span>=<span class="string">&quot;&#123; width: &#x27;750px&#x27;, height: &#x27;60%&#x27;, left: &#x27;50%&#x27;, &#x27;margin-left&#x27;: &#x27;-375px&#x27; &#125;&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 评论回复列表 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-list</span> <span class="attr">v-model</span>=<span class="string">&quot;commentRepliesLoading&quot;</span> <span class="attr">:finished</span>=<span class="string">&quot;commentRepliesFinished&quot;</span> <span class="attr">finished-text</span>=<span class="string">&quot;没有更多了&quot;</span></span></span><br><span class="line"><span class="tag"> @<span class="attr">load</span>=<span class="string">&quot;onLoadCommentReplies&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">id</span>=<span class="string">&quot;#comment-reply-view&quot;</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-comment-reply&quot;</span></span></span><br><span class="line"><span class="tag"> <span class="attr">v-for</span>=<span class="string">&quot;(item, index) in commentReplies&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;index&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-image</span> <span class="attr">round</span> <span class="attr">src</span>=<span class="string">&quot;https://p3.pstatp.com/thumb/1480/7186611868&quot;</span> <span class="attr">class</span>=<span class="string">&quot;article-avatar&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-image</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;21&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span> <span class="attr">justify</span>=<span class="string">&quot;space-between&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">class</span>=<span class="string">&quot;comment-author&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;item.authorName&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">round</span> <span class="attr">:icon</span>=<span class="string">&quot;item.operation === 0 ? &#x27;good-job&#x27; : &#x27;good-job-o&#x27;&quot;</span> <span class="attr">size</span>=<span class="string">&quot;normal&quot;</span></span></span><br><span class="line"><span class="tag"> @<span class="attr">click</span>=<span class="string">&quot;handleClickCommentReplyLike(item)&quot;</span>&gt;</span>&#123;&#123; item.likes || &#x27;&#x27; &#125;&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">class</span>=<span class="string">&quot;comment-content&quot;</span> <span class="attr">v-html</span>=<span class="string">&quot;item.content&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- <span class="doctag">TODO:</span> js计算时间差 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;10&quot;</span> <span class="attr">class</span>=<span class="string">&quot;comment-time&quot;</span>&gt;</span></span><br><span class="line"> &#123;&#123; item.createdTime | timestampToDateTime &#125;&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-list</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 评论回复底部栏 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-row</span> <span class="attr">type</span>=<span class="string">&quot;flex&quot;</span> <span class="attr">justify</span>=<span class="string">&quot;space-around&quot;</span> <span class="attr">align</span>=<span class="string">&quot;center&quot;</span> <span class="attr">class</span>=<span class="string">&quot;comment-reply-bottom-bar&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;13&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-field</span> <span class="attr">v-model</span>=<span class="string">&quot;commentReplyValue&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;写评论&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">template</span> #<span class="attr">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;back-top&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleSaveCommentReply&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-field</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;comment-o&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;star-o&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-col</span> <span class="attr">span</span>=<span class="string">&quot;3&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">van-button</span> <span class="attr">icon</span>=<span class="string">&quot;share-o&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">van-button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-col</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-row</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">van-popup</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 引入 Vue 和 Vant 的 JS 文件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot; https://fastly.jsdelivr.net/npm/vue/dist/vue.min.js&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://fastly.jsdelivr.net/npm/vant@2.12.20/lib/vant.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 引入 Axios 的 JS 文件 --&gt;</span></span><br><span class="line">&lt;#--<span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span>--&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;../../../plugins/js/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 页面逻辑 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;../../../plugins/js/index.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>4.手动上传资料中index.js和index.css两个文件到MinIO中</p>
<p>上传index.js</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testMinIO</span><span class="params">()</span>&#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//读取一个文件</span></span><br><span class="line"> <span class="type">FileInputStream</span> <span class="variable">inputStream</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(<span class="string">&quot;C:\\Gong\\java\\黑马头条\\day02-app端文章查看静态化freemarker,分布式文件系统minIO\\资料\\模板文件\\plugins\\js\\index.js&quot;</span>);</span><br><span class="line"> <span class="comment">//1.获取MinIO的连接信息创建一个minio的客户端</span></span><br><span class="line"> <span class="type">MinioClient</span> <span class="variable">minioClient</span> <span class="operator">=</span> MinioClient.builder()</span><br><span class="line"> .credentials(<span class="string">&quot;minio&quot;</span>, <span class="string">&quot;minio123&quot;</span>)<span class="comment">//minio的账号密码</span></span><br><span class="line"> .endpoint(<span class="string">&quot;http://192.168.200.130:9000&quot;</span>)<span class="comment">//minio的地址</span></span><br><span class="line"> .build();</span><br><span class="line"> <span class="comment">//2.上传</span></span><br><span class="line"> <span class="type">PutObjectArgs</span> <span class="variable">putObjectArgs</span> <span class="operator">=</span> PutObjectArgs.builder()</span><br><span class="line"> .object(<span class="string">&quot;plugins/js/index.js&quot;</span>)<span class="comment">//文件的名称</span></span><br><span class="line"> .contentType(<span class="string">&quot;text/js&quot;</span>)<span class="comment">//文件的类型</span></span><br><span class="line"> .bucket(<span class="string">&quot;leadnews&quot;</span>)<span class="comment">//桶的名称与之前的minio管理界面创建的bucket名称一致即可</span></span><br><span class="line"> .stream(inputStream,inputStream.available(),-<span class="number">1</span>)</span><br><span class="line"> .build();</span><br><span class="line"> minioClient.putObject(putObjectArgs);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上传index.css</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testMinIO</span><span class="params">()</span>&#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//读取一个文件</span></span><br><span class="line"> <span class="type">FileInputStream</span> <span class="variable">inputStream</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(<span class="string">&quot;C:\\Gong\\java\\黑马头条\\day02-app端文章查看静态化freemarker,分布式文件系统minIO\\资料\\模板文件\\plugins\\css\\index.css&quot;</span>);</span><br><span class="line"> <span class="comment">//1.获取MinIO的连接信息创建一个minio的客户端</span></span><br><span class="line"> <span class="type">MinioClient</span> <span class="variable">minioClient</span> <span class="operator">=</span> MinioClient.builder()</span><br><span class="line"> .credentials(<span class="string">&quot;minio&quot;</span>, <span class="string">&quot;minio123&quot;</span>)<span class="comment">//minio的账号密码</span></span><br><span class="line"> .endpoint(<span class="string">&quot;http://192.168.200.130:9000&quot;</span>)<span class="comment">//minio的地址</span></span><br><span class="line"> .build();</span><br><span class="line"> <span class="comment">//2.上传</span></span><br><span class="line"> <span class="type">PutObjectArgs</span> <span class="variable">putObjectArgs</span> <span class="operator">=</span> PutObjectArgs.builder()</span><br><span class="line"> .object(<span class="string">&quot;plugins/css/index.css&quot;</span>)<span class="comment">//文件的名称</span></span><br><span class="line"> .contentType(<span class="string">&quot;text/css&quot;</span>)<span class="comment">//文件的类型</span></span><br><span class="line"> .bucket(<span class="string">&quot;leadnews&quot;</span>)<span class="comment">//桶的名称与之前的minio管理界面创建的bucket名称一致即可</span></span><br><span class="line"> .stream(inputStream,inputStream.available(),-<span class="number">1</span>)</span><br><span class="line"> .build();</span><br><span class="line"> minioClient.putObject(putObjectArgs);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>5.测试根据文章的内容生成html文件上传到minio中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.test;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONArray;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.ArticleApplication;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.mapper.ApArticleContentMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ApArticleService;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticle;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticleContent;</span><br><span class="line"><span class="keyword">import</span> freemarker.template.Configuration;</span><br><span class="line"><span class="keyword">import</span> freemarker.template.Template;</span><br><span class="line"><span class="keyword">import</span> freemarker.template.TemplateException;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.junit.Test;</span><br><span class="line"><span class="keyword">import</span> org.junit.runner.RunWith;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.test.context.junit4.SpringRunner;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.ByteArrayInputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.StringWriter;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/8/19</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootTest(classes = ArticleApplication.class)</span></span><br><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleFreeMarkerTest</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleContentMapper apArticleContentMapper;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> Configuration configuration;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleService apArticleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">createStaticUrlTest</span><span class="params">()</span> <span class="keyword">throws</span> IOException, TemplateException &#123;</span><br><span class="line"> <span class="comment">//已知文章的id</span></span><br><span class="line"> <span class="comment">//1.获取文章的内容</span></span><br><span class="line"> <span class="type">ApArticleContent</span> <span class="variable">apArticleContent</span> <span class="operator">=</span> apArticleContentMapper.selectOne(<span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;ApArticleContent&gt;().eq(ApArticleContent::getArticleId, <span class="string">&quot;1383827995813531650L&quot;</span>));</span><br><span class="line"> <span class="keyword">if</span> (apArticleContent != <span class="literal">null</span> &amp;&amp; StringUtils.isNotBlank(apArticleContent.getContent())) &#123;</span><br><span class="line"> <span class="comment">//2.文章内容通过freemarker生成html文件 详细教程见:https://qingling.icu/posts/29367.html</span></span><br><span class="line"> <span class="type">Template</span> <span class="variable">template</span> <span class="operator">=</span> configuration.getTemplate(<span class="string">&quot;article.ftl&quot;</span>);</span><br><span class="line"> <span class="comment">//构建数据模型</span></span><br><span class="line"> HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;content&quot;</span>, JSONArray.parseArray(apArticleContent.getContent()));</span><br><span class="line"> <span class="comment">//输出流</span></span><br><span class="line"> <span class="type">StringWriter</span> <span class="variable">out</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringWriter</span>();</span><br><span class="line"> <span class="comment">//合成html文件</span></span><br><span class="line"> template.process(map, out);</span><br><span class="line"> <span class="comment">//3.把html文件上传到minio中</span></span><br><span class="line"> <span class="comment">//构建一个输入流</span></span><br><span class="line"> <span class="type">InputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(out.toString().getBytes());</span><br><span class="line"> <span class="comment">//上传到minio并返回访问的路径</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> fileStorageService.uploadHtmlFile(<span class="string">&quot;&quot;</span>, apArticleContent.getArticleId() + <span class="string">&quot;.html&quot;</span>, in);</span><br><span class="line"> System.out.println(<span class="string">&quot;文件在minio中的路径:&quot;</span>+path);</span><br><span class="line"> <span class="comment">//4.修改ap_article表保存static_url字段</span></span><br><span class="line"> <span class="type">ApArticle</span> <span class="variable">apArticle</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticle</span>();</span><br><span class="line"> apArticle.setId(apArticleContent.getArticleId());</span><br><span class="line"> apArticle.setStaticUrl(path);</span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isSuccess</span> <span class="operator">=</span> apArticleService.updateById(apArticle);</span><br><span class="line"> System.out.println(isSuccess ? <span class="string">&quot;文件上传成功&quot;</span> : <span class="string">&quot;文件上传失败&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>6.实现效果</p>
<p><img src="/pictures/image-20230819153507360.png" alt="image-20230819153507360"></p>
<h1 id="四-自媒体端功能开发"><a href="#四-自媒体端功能开发" class="headerlink" title="四.自媒体端功能开发"></a>四.自媒体端功能开发</h1><h2 id="1-后端环境搭建"><a href="#1-后端环境搭建" class="headerlink" title="1.后端环境搭建"></a>1.后端环境搭建</h2><p><strong>需要搭建的模块</strong></p>
<p><img src="/pictures/image-20230819155333131.png" alt="image-20230819155333131"></p>
<p><strong>搭建步骤</strong></p>
<p><img src="/pictures/image-20230819155229550.png" alt="image-20230819155229550"></p>
<p>1.创建自媒体模块的数据库</p>
<p><img src="/pictures/image-20230819155853252.png" alt="image-20230819155853252"></p>
<p>2.导入相应的工程文件</p>
<p><img src="/pictures/image-20230819161650118.png" alt="image-20230819161650118"></p>
<p>3.配置自媒体模块和网关模块在nacos中的配置</p>
<p>自媒体模块的配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">datasource:</span></span><br><span class="line"> <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line"> <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/leadnews_wemedia?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC</span></span><br><span class="line"> <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line"> <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"><span class="comment"># 设置Mapper接口所对应的XML文件位置如果你在Mapper接口中有自定义方法需要进行该配置</span></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line"> <span class="attr">mapper-locations:</span> <span class="string">classpath*:mapper/*.xml</span></span><br><span class="line"> <span class="comment"># 设置别名包扫描路径,通过该属性可以给包中的类注册别名</span></span><br><span class="line"> <span class="attr">type-aliases-package:</span> <span class="string">com.heima.model.media.pojos</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20230819161148830.png" alt="image-20230819161148830"></p>
<p>网关模块的配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">cloud:</span></span><br><span class="line"> <span class="attr">gateway:</span></span><br><span class="line"> <span class="attr">globalcors:</span></span><br><span class="line"> <span class="attr">cors-configurations:</span></span><br><span class="line"> <span class="string">&#x27;[/**]&#x27;</span><span class="string">:</span> <span class="comment"># 匹配所有请求</span></span><br><span class="line"> <span class="attr">allowedOrigins:</span> <span class="string">&quot;*&quot;</span> <span class="comment">#跨域处理 允许所有的域</span></span><br><span class="line"> <span class="attr">allowedMethods:</span> <span class="comment"># 支持的方法</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">GET</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">POST</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">PUT</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">DELETE</span></span><br><span class="line"> <span class="attr">routes:</span></span><br><span class="line"> <span class="comment"># 平台管理</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">wemedia</span></span><br><span class="line"> <span class="attr">uri:</span> <span class="string">lb://leadnews-wemedia</span></span><br><span class="line"> <span class="attr">predicates:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">Path=/wemedia/**</span></span><br><span class="line"> <span class="attr">filters:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">StripPrefix=</span> <span class="number">1</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20230819161529210.png" alt="image-20230819161529210"></p>
<h2 id="2-前端环境搭建"><a href="#2-前端环境搭建" class="headerlink" title="2.前端环境搭建"></a>2.前端环境搭建</h2><p><strong>搭建思路</strong></p>
<p><img src="/pictures/image-20230819162116240.png" alt="image-20230819162116240"></p>
<p><strong>搭建步骤</strong></p>
<p><img src="/pictures/image-20230819162230133.png" alt="image-20230819162230133"></p>
<p><strong>heima-leadnews-wemedia配置文件</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">upstream heima-wemedia-gateway&#123;</span><br><span class="line"> #APP端网关所在的端口</span><br><span class="line"> server localhost:51602;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line"> listen 8802;</span><br><span class="line"> location / &#123;</span><br><span class="line"> root C:/Gong/data/wemedia-web/;</span><br><span class="line"> index index.html;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> location ~/wemedia/MEDIA/(.*) &#123;</span><br><span class="line"> proxy_pass http://heima-wemedia-gateway/$1;</span><br><span class="line"> proxy_set_header HOST $host; # 不改变源请求头的值</span><br><span class="line"> proxy_pass_request_body on; #开启获取请求体</span><br><span class="line"> proxy_pass_request_headers on; #开启获取请求头</span><br><span class="line"> proxy_set_header X-Real-IP $remote_addr; # 记录真实发出请求的客户端IP</span><br><span class="line"> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>重启nginx访问</strong></p>
<p><img src="/pictures/image-20230902145814017.png" alt="image-20230902145814017"></p>
<h2 id="3-自媒体素材管理功能"><a href="#3-自媒体素材管理功能" class="headerlink" title="3.自媒体素材管理功能"></a>3.自媒体素材管理功能</h2><h3 id="3-1-素材管理-图片上传"><a href="#3-1-素材管理-图片上传" class="headerlink" title="3.1 素材管理-图片上传"></a>3.1 素材管理-图片上传</h3><p><strong>图片素材相关的实体类</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 自媒体图文素材信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;wm_material&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmMaterial</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 主键</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自媒体用户ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;user_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer userId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 图片地址</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;url&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String url;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 素材类型</span></span><br><span class="line"><span class="comment"> 0 图片</span></span><br><span class="line"><span class="comment"> 1 视频</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;type&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short type;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否收藏</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_collection&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short isCollection;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;created_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date createdTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-1-1-解决图片素材实体类中获取图片userId的问题"><a href="#3-1-1-解决图片素材实体类中获取图片userId的问题" class="headerlink" title="3.1.1 解决图片素材实体类中获取图片userId的问题"></a>3.1.1 解决图片素材实体类中获取图片userId的问题</h4><p><strong>实现思路</strong></p>
<p><img src="/pictures/image-20230902154806019.png" alt="image-20230902154806019"></p>
<p>1.token解析为用户存入header</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.gateway.filter;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.gateway.util.AppJwtUtil;</span><br><span class="line"><span class="keyword">import</span> io.jsonwebtoken.Claims;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilterChain;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GlobalFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.Ordered;</span><br><span class="line"><span class="keyword">import</span> org.springframework.http.HttpStatus;</span><br><span class="line"><span class="keyword">import</span> org.springframework.http.server.reactive.ServerHttpRequest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.http.server.reactive.ServerHttpResponse;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.server.ServerWebExchange;</span><br><span class="line"><span class="keyword">import</span> reactor.core.publisher.Mono;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthorizeFilter</span> <span class="keyword">implements</span> <span class="title class_">Ordered</span>, GlobalFilter &#123;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> Mono&lt;Void&gt; <span class="title function_">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span> &#123;</span><br><span class="line"> <span class="comment">//1.获取request和response对象</span></span><br><span class="line"> <span class="type">ServerHttpRequest</span> <span class="variable">request</span> <span class="operator">=</span> exchange.getRequest();</span><br><span class="line"> <span class="type">ServerHttpResponse</span> <span class="variable">response</span> <span class="operator">=</span> exchange.getResponse();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.判断是否是登录</span></span><br><span class="line"> <span class="keyword">if</span>(request.getURI().getPath().contains(<span class="string">&quot;/login&quot;</span>))&#123;</span><br><span class="line"> <span class="comment">//放行</span></span><br><span class="line"> <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//3.获取token</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> request.getHeaders().getFirst(<span class="string">&quot;token&quot;</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//4.判断token是否存在</span></span><br><span class="line"> <span class="keyword">if</span>(StringUtils.isBlank(token))&#123;</span><br><span class="line"> response.setStatusCode(HttpStatus.UNAUTHORIZED);</span><br><span class="line"> <span class="keyword">return</span> response.setComplete();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//5.判断token是否有效</span></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="type">Claims</span> <span class="variable">claimsBody</span> <span class="operator">=</span> AppJwtUtil.getClaimsBody(token);</span><br><span class="line"> <span class="comment">//是否是过期</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> AppJwtUtil.verifyToken(claimsBody);</span><br><span class="line"> <span class="keyword">if</span>(result == <span class="number">1</span> || result == <span class="number">2</span>)&#123;</span><br><span class="line"> response.setStatusCode(HttpStatus.UNAUTHORIZED);</span><br><span class="line"> <span class="keyword">return</span> response.setComplete();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//获取用户信息</span></span><br><span class="line"> <span class="type">Object</span> <span class="variable">userId</span> <span class="operator">=</span> claimsBody.get(<span class="string">&quot;id&quot;</span>);</span><br><span class="line"> <span class="comment">//存入header中</span></span><br><span class="line"> <span class="type">ServerHttpRequest</span> <span class="variable">serverHttpRequest</span> <span class="operator">=</span> request.mutate().headers(httpHeaders -&gt; &#123;</span><br><span class="line"> httpHeaders.add(<span class="string">&quot;userId&quot;</span>, userId + <span class="string">&quot;&quot;</span>);</span><br><span class="line"> &#125;).build();</span><br><span class="line"> <span class="comment">//重置请求</span></span><br><span class="line"> exchange.mutate().request(serverHttpRequest);</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//6.放行</span></span><br><span class="line"> <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 优先级设置 值越小 优先级越高</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getOrder</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.创建拦截器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.interceptor;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmUser;</span><br><span class="line"><span class="keyword">import</span> com.heima.utils.thread.WmThreadLocalUtil;</span><br><span class="line"><span class="keyword">import</span> io.swagger.models.auth.In;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.HandlerInterceptor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.util.Enumeration;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/9/2</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmTokenInterceptor</span> <span class="keyword">implements</span> <span class="title class_">HandlerInterceptor</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取header中的信息 存入当前的线程中</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> <span class="comment">//获取header中的userId信息</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">userId</span> <span class="operator">=</span> request.getHeader(<span class="string">&quot;userId&quot;</span>);</span><br><span class="line"> <span class="comment">//判断userId是否为空</span></span><br><span class="line"> <span class="keyword">if</span>(userId != <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="comment">//将userId存入当前的线程中我们可以在任何位置获取</span></span><br><span class="line"> <span class="type">WmUser</span> <span class="variable">wmUser</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WmUser</span>();</span><br><span class="line"> wmUser.setId(Integer.valueOf(userId));</span><br><span class="line"> WmThreadLocalUtil.setUser(wmUser);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 清理线程中的数据</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">postHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> WmThreadLocalUtil.clear();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>ThreadLocal工具类实现在线程中存储、获取、清理用户信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.utils.thread;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmUser;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmThreadLocalUtil</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> ThreadLocal&lt;WmUser&gt; WM_USER_THREAD_LOCAL = <span class="keyword">new</span> <span class="title class_">ThreadLocal</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 添加用户</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmUser</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">setUser</span><span class="params">(WmUser wmUser)</span>&#123;</span><br><span class="line"> WM_USER_THREAD_LOCAL.set(wmUser);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取用户</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> WmUser <span class="title function_">getUser</span><span class="params">()</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> WM_USER_THREAD_LOCAL.get();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 清理用户</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">clear</span><span class="params">()</span>&#123;</span><br><span class="line"> WM_USER_THREAD_LOCAL.remove();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3.让拦截器生效</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.interceptor.WmTokenInterceptor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.InterceptorRegistry;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/9/2</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WebMvcConfig</span> <span class="keyword">implements</span> <span class="title class_">WebMvcConfigurer</span> &#123;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addInterceptors</span><span class="params">(InterceptorRegistry registry)</span> &#123;</span><br><span class="line"> registry.addInterceptor(<span class="keyword">new</span> <span class="title class_">WmTokenInterceptor</span>()).addPathPatterns(<span class="string">&quot;/**&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-1-2-图片上传接口的定义"><a href="#3-1-2-图片上传接口的定义" class="headerlink" title="3.1.2 图片上传接口的定义"></a>3.1.2 图片上传接口的定义</h4><table>
<thead>
<tr>
<th></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>接口路径</td>
<td>&#x2F;api&#x2F;v1&#x2F;material&#x2F;upload_picture</td>
</tr>
<tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>MultipartFile</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<h4 id="3-1-3-代码实现"><a href="#3-1-3-代码实现" class="headerlink" title="3.1.3 代码实现"></a>3.1.3 代码实现</h4><p>1.在pom.xml中引入自定义minio的starter依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.heima<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>heima-file-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>2.在项目中添加minio的配置(在nacos中配置)</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">minio:</span></span><br><span class="line"> <span class="attr">accessKey:</span> <span class="string">minio</span></span><br><span class="line"> <span class="attr">secretKey:</span> <span class="string">minio123</span></span><br><span class="line"> <span class="attr">bucket:</span> <span class="string">leadnews</span></span><br><span class="line"> <span class="attr">endpoint:</span> <span class="string">http://192.168.200.130:9000</span></span><br><span class="line"> <span class="attr">readPath:</span> <span class="string">http://192.168.200.130:9000</span></span><br></pre></td></tr></table></figure>
<p>3.上传图片的关键代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.enums.AppHttpCodeEnum;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmMaterial;</span><br><span class="line"><span class="keyword">import</span> com.heima.utils.thread.WmThreadLocalUtil;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmMaterialMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.service.WmMaterialService;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.multipart.MultipartFile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> java.util.UUID;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmMaterialServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span>&lt;WmMaterialMapper, WmMaterial&gt; <span class="keyword">implements</span> <span class="title class_">WmMaterialService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService; <span class="comment">//使用minio</span></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">uploadPicture</span><span class="params">(MultipartFile multipartFile)</span> &#123;</span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> <span class="keyword">if</span>(multipartFile == <span class="literal">null</span> || multipartFile.getSize() == <span class="number">0</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//2.上传图片到minio中</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">fileName</span> <span class="operator">=</span> UUID.randomUUID().toString().replace(<span class="string">&quot;-&quot;</span>, <span class="string">&quot;&quot;</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">originalFilename</span> <span class="operator">=</span> multipartFile.getOriginalFilename();</span><br><span class="line"> <span class="type">String</span> <span class="variable">postfix</span> <span class="operator">=</span> originalFilename.substring(originalFilename.lastIndexOf(<span class="string">&quot;.&quot;</span>));</span><br><span class="line"> <span class="type">String</span> <span class="variable">fileId</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> fileId = fileStorageService.uploadImgFile(<span class="string">&quot;&quot;</span>, fileName + postfix, multipartFile.getInputStream());</span><br><span class="line"> log.info(<span class="string">&quot;上传图片到Minio中,fileId:&#123;&#125;&quot;</span>,fileId);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line"> log.info(<span class="string">&quot;WmMaterialServiceImpl-上传图片失败&quot;</span>);</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//3.将图片的信息保存在数据库中</span></span><br><span class="line"> <span class="type">WmMaterial</span> <span class="variable">wmMaterial</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WmMaterial</span>();</span><br><span class="line"> wmMaterial.setUserId(WmThreadLocalUtil.getUser().getId());</span><br><span class="line"> wmMaterial.setUrl(fileId);</span><br><span class="line"> wmMaterial.setType((<span class="type">short</span>)<span class="number">0</span>);</span><br><span class="line"> wmMaterial.setIsCollection((<span class="type">short</span>)<span class="number">0</span>);</span><br><span class="line"> wmMaterial.setCreatedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> save(wmMaterial);</span><br><span class="line"> <span class="comment">//4.返回参数</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(wmMaterial);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>4.测试上传功能</p>
<p><img src="/pictures/image-20230902220022201.png" alt="image-20230902220022201"></p>
<h3 id="3-2-素材管理-图片列表"><a href="#3-2-素材管理-图片列表" class="headerlink" title="3.2 素材管理-图片列表"></a>3.2 素材管理-图片列表</h3><p><strong>接口定义</strong></p>
<table>
<thead>
<tr>
<th><strong>接口路径</strong></th>
<th><strong>&#x2F;api</strong>&#x2F;<strong>&#x2F;v1&#x2F;material&#x2F;list</strong></th>
</tr>
</thead>
<tbody><tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>WmMaterialDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p><strong>请求参数的DTO</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmMaterialDto</span> <span class="keyword">extends</span> <span class="title class_">PageRequestDto</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1 收藏</span></span><br><span class="line"><span class="comment"> * 0 未收藏</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Short isCollection;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>关键代码</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 素材图片的列表显示</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">findList</span><span class="params">(WmMaterialDto wmMaterialDto)</span> &#123;</span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> wmMaterialDto.checkParam();</span><br><span class="line"> <span class="comment">//2.分页查询</span></span><br><span class="line"> <span class="type">IPage</span> <span class="variable">page</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Page</span>(wmMaterialDto.getPage(),wmMaterialDto.getSize());</span><br><span class="line"> LambdaQueryWrapper&lt;WmMaterial&gt; queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;&gt;();</span><br><span class="line"> <span class="comment">//是否收藏</span></span><br><span class="line"> <span class="keyword">if</span>(wmMaterialDto.getIsCollection() != <span class="literal">null</span> &amp;&amp; wmMaterialDto.getIsCollection() == <span class="number">1</span>)&#123;</span><br><span class="line"> queryWrapper.eq(WmMaterial::getIsCollection,wmMaterialDto.getIsCollection());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//按照用户查询</span></span><br><span class="line"> queryWrapper.eq(WmMaterial::getUserId,WmThreadLocalUtil.getUser().getId());</span><br><span class="line"> <span class="comment">//按照时间查询</span></span><br><span class="line"> queryWrapper.orderByDesc(WmMaterial::getCreatedTime);</span><br><span class="line"> page = page(page,queryWrapper);</span><br><span class="line"> <span class="comment">//3.结果返回</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageResponseResult</span>(wmMaterialDto.getPage(), wmMaterialDto.getSize(), (<span class="type">int</span>) page.getTotal());</span><br><span class="line"> responseResult.setData(page.getRecords());</span><br><span class="line"> <span class="keyword">return</span> responseResult;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>MP的配置</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> MybatisPlusInterceptor <span class="title function_">mybatisPlusInterceptor</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="type">MybatisPlusInterceptor</span> <span class="variable">interceptor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MybatisPlusInterceptor</span>();</span><br><span class="line"> interceptor.addInnerInterceptor(<span class="keyword">new</span> <span class="title class_">PaginationInnerInterceptor</span>(DbType.MYSQL));</span><br><span class="line"> <span class="keyword">return</span> interceptor;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现效果</strong></p>
<p><img src="/pictures/image-20230903125528872.png" alt="image-20230903125528872"></p>
<h2 id="4-自媒体文章管理功能"><a href="#4-自媒体文章管理功能" class="headerlink" title="4.自媒体文章管理功能"></a>4.自媒体文章管理功能</h2><h3 id="4-1-频道列表查询"><a href="#4-1-频道列表查询" class="headerlink" title="4.1 频道列表查询"></a>4.1 频道列表查询</h3><p><strong>频道对应的实体类</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 频道信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;wm_channel&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmChannel</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 频道名称</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;name&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 频道描述</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;description&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String description;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否默认频道</span></span><br><span class="line"><span class="comment"> * 1默认 true</span></span><br><span class="line"><span class="comment"> * 0非默认 false</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_default&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean isDefault;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否启用</span></span><br><span class="line"><span class="comment"> * 1启用 true</span></span><br><span class="line"><span class="comment"> * 0禁用 false</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;status&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean status;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 默认排序</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;ord&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer ord;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;created_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date createdTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>接口定义</strong></p>
<table>
<thead>
<tr>
<th></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>接口路径</td>
<td>&#x2F;api&#x2F;v1&#x2F;channel&#x2F;channels</td>
</tr>
<tr>
<td>请求方式</td>
<td>GET</td>
</tr>
<tr>
<td>参数</td>
<td></td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p><strong>关键代码</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 查询所有的频道信息</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/channels&quot;)</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">findAllChannels</span><span class="params">()</span>&#123;</span><br><span class="line"> List&lt;WmChannel&gt; channels = wmChannelService.list();</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(channels);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现效果</strong></p>
<p><img src="/pictures/image-20230903151216766.png" alt="image-20230903151216766"></p>
<h3 id="4-2-文章列表加载"><a href="#4-2-文章列表加载" class="headerlink" title="4.2 文章列表加载"></a>4.2 文章列表加载</h3><p><strong>文章表对应的实体类</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.type.Alias;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 自媒体图文内容信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;wm_news&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNews</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 主键</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自媒体用户ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;user_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer userId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 标题</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;title&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String title;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 图文内容</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;content&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String content;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 文章布局</span></span><br><span class="line"><span class="comment"> 0 无图文章</span></span><br><span class="line"><span class="comment"> 1 单图文章</span></span><br><span class="line"><span class="comment"> 3 多图文章</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;type&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short type;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 图文频道ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;channel_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer channelId;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@TableField(&quot;labels&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String labels;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;created_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date createdTime;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提交时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;submited_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date submitedTime;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 当前状态</span></span><br><span class="line"><span class="comment"> 0 草稿</span></span><br><span class="line"><span class="comment"> 1 提交(待审核)</span></span><br><span class="line"><span class="comment"> 2 审核失败</span></span><br><span class="line"><span class="comment"> 3 人工审核</span></span><br><span class="line"><span class="comment"> 4 人工审核通过</span></span><br><span class="line"><span class="comment"> 8 审核通过(待发布)</span></span><br><span class="line"><span class="comment"> 9 已发布</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;status&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short status;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 定时发布时间,不定时则为空</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;publish_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date publishTime;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 拒绝理由</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;reason&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String reason;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 发布库文章ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;article_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Long articleId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * //图片用逗号分隔</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;images&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String images;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@TableField(&quot;enable&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short enable;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//状态枚举类</span></span><br><span class="line"> <span class="meta">@Alias(&quot;WmNewsStatus&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">Status</span>&#123;</span><br><span class="line"> NORMAL((<span class="type">short</span>)<span class="number">0</span>),SUBMIT((<span class="type">short</span>)<span class="number">1</span>),FAIL((<span class="type">short</span>)<span class="number">2</span>),ADMIN_AUTH((<span class="type">short</span>)<span class="number">3</span>),ADMIN_SUCCESS((<span class="type">short</span>)<span class="number">4</span>),SUCCESS((<span class="type">short</span>)<span class="number">8</span>),PUBLISHED((<span class="type">short</span>)<span class="number">9</span>);</span><br><span class="line"> <span class="type">short</span> code;</span><br><span class="line"> Status(<span class="type">short</span> code)&#123;</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">public</span> <span class="type">short</span> <span class="title function_">getCode</span><span class="params">()</span>&#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.code;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>接口定义</strong></p>
<table>
<thead>
<tr>
<th><strong>接口路径</strong></th>
<th><strong>&#x2F;api</strong>&#x2F;<strong>&#x2F;v1&#x2F;news&#x2F;list</strong></th>
</tr>
</thead>
<tbody><tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>WmNewsPageReqDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p><strong>关键代码</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">findNewsList</span><span class="params">(WmNewsPageReqDto wmNewsPageReqDto)</span> &#123;</span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> wmNewsPageReqDto.checkParam();</span><br><span class="line"> <span class="comment">//2.根据条件查询</span></span><br><span class="line"> <span class="type">IPage</span> <span class="variable">page</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Page</span>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize());</span><br><span class="line"> LambdaQueryWrapper&lt;WmNews&gt; queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;&gt;();</span><br><span class="line"> <span class="comment">//状态</span></span><br><span class="line"> <span class="keyword">if</span>(wmNewsPageReqDto.getStatus() != <span class="literal">null</span>)&#123;</span><br><span class="line"> queryWrapper.eq(WmNews::getStatus,wmNewsPageReqDto.getStatus());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//开始时间 结束时间</span></span><br><span class="line"> <span class="keyword">if</span>(wmNewsPageReqDto.getBeginPubDate() != <span class="literal">null</span> &amp;&amp; wmNewsPageReqDto.getEndPubDate()!=<span class="literal">null</span>)&#123;</span><br><span class="line"> queryWrapper.between(WmNews::getPublishTime,wmNewsPageReqDto.getBeginPubDate(),wmNewsPageReqDto.getEndPubDate());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//所属频道id</span></span><br><span class="line"> <span class="keyword">if</span>(wmNewsPageReqDto.getChannelId() != <span class="literal">null</span>)&#123;</span><br><span class="line"> queryWrapper.eq(WmNews::getChannelId,wmNewsPageReqDto.getChannelId());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//关键字</span></span><br><span class="line"> <span class="keyword">if</span>(wmNewsPageReqDto.getKeyword() != <span class="literal">null</span>)&#123;</span><br><span class="line"> queryWrapper.like(WmNews::getTitle,wmNewsPageReqDto.getKeyword());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//查询当前登录人的文章</span></span><br><span class="line"> queryWrapper.eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId());</span><br><span class="line"> <span class="comment">//按照发布时间倒序查询</span></span><br><span class="line"> queryWrapper.orderByDesc(WmNews::getPublishTime);</span><br><span class="line"> page = page(page,queryWrapper);</span><br><span class="line"> <span class="comment">//3.结果返回</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageResponseResult</span>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize(), (<span class="type">int</span>) page.getTotal());</span><br><span class="line"> responseResult.setData(page.getRecords());</span><br><span class="line"> <span class="keyword">return</span> responseResult;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现效果</strong></p>
<p><img src="/pictures/image-20230903185956428.png" alt="image-20230903185956428"></p>
<h3 id="4-3-发布文章功能-核心功能"><a href="#4-3-发布文章功能-核心功能" class="headerlink" title="4.3 发布文章功能(核心功能)"></a>4.3 发布文章功能(核心功能)</h3><p><strong>文章和素材对应关系表</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 自媒体图文引用素材信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;wm_news_material&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsMaterial</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 主键</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 素材ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;material_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer materialId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 图文ID</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;news_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Integer newsId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 引用类型</span></span><br><span class="line"><span class="comment"> 0 内容引用</span></span><br><span class="line"><span class="comment"> 1 主图引用</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;type&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short type;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 引用排序</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;ord&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Short ord;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现流程</strong></p>
<p><img src="/pictures/image-20230904151910210.png" alt="image-20230904151910210"></p>
<p><strong>接口定义</strong></p>
<table>
<thead>
<tr>
<th></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>接口路径</td>
<td>&#x2F;api&#x2F;v1&#x2F;news&#x2F;submit</td>
</tr>
<tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>WmNewsDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p><strong>WmNewsDto</strong> </p>
<p>接收前端参数的dto</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.dtos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsDto</span> &#123;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 标题</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String title;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 频道id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Integer channelId;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 标签</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String labels;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 发布时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Date publishTime;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 文章内容</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String content;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 文章封面类型 0 无图 1 单图 3 多图 -1 自动</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Short type;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提交时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Date submitedTime; </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 状态 提交为1 草稿为0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Short status;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 封面图片列表 多张图以逗号隔开</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> List&lt;String&gt; images;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>前端传递的json格式数据举例</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span><span class="string">&quot;黑马头条项目背景&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;1&quot;</span><span class="punctuation">,</span><span class="comment">//这个 0 是无图 1 是单图 3 是多图 -1 是自动</span></span><br><span class="line"> <span class="attr">&quot;labels&quot;</span><span class="punctuation">:</span><span class="string">&quot;黑马头条&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;publishTime&quot;</span><span class="punctuation">:</span><span class="string">&quot;2020-03-14T11:35:49.000Z&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;channelId&quot;</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;images&quot;</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"> <span class="string">&quot;http://192.168.200.130/group1/M00/00/00/wKjIgl5swbGATaSAAAEPfZfx6Iw790.png&quot;</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;content&quot;</span><span class="punctuation">:</span><span class="string">&quot;[</span></span><br><span class="line"><span class="string"> &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>type<span class="string">&quot;:&quot;</span>text<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>value<span class="string">&quot;:&quot;</span>随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻<span class="string">&quot;</span></span><br><span class="line"><span class="string"> &#125;,</span></span><br><span class="line"><span class="string"> &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>type<span class="string">&quot;:&quot;</span>image<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>value<span class="string">&quot;:&quot;</span>http<span class="punctuation">:</span><span class="comment">//192.168.200.130/group1/M00/00/00/wKjIgl5swbGATaSAAAEPfZfx6Iw790.png&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">]</span><span class="string">&quot;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>
<p><strong>保存文章和素材对应关系mapper接口</strong></p>
<p>mapper接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mapper</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">WmNewsMaterialMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span>&lt;WmNewsMaterial&gt; &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 批量保存文章和素材之间的关系</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> materialIds 素材的id</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> newsId 文章的id</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> type 类型</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">void</span> <span class="title function_">saveRelations</span><span class="params">(<span class="meta">@Param(&quot;materialIds&quot;)</span> List&lt;Integer&gt; materialIds,<span class="meta">@Param(&quot;newsId&quot;)</span> Integer newsId, <span class="meta">@Param(&quot;type&quot;)</span>Short type)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>mapper.xml文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span> <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.heima.wemedia.mapper.WmNewsMaterialMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;saveRelations&quot;</span>&gt;</span></span><br><span class="line"> insert into wm_news_material (material_id,news_id,type,ord)</span><br><span class="line"> values</span><br><span class="line"> <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">collection</span>=<span class="string">&quot;materialIds&quot;</span> <span class="attr">index</span>=<span class="string">&quot;ord&quot;</span> <span class="attr">item</span>=<span class="string">&quot;mid&quot;</span> <span class="attr">separator</span>=<span class="string">&quot;,&quot;</span>&gt;</span></span><br><span class="line"> (#&#123;mid&#125;,#&#123;newsId&#125;,#&#123;type&#125;,#&#123;ord&#125;)</span><br><span class="line"> <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>使用到的常量类</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.common.constants;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WemediaConstants</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">COLLECT_MATERIAL</span> <span class="operator">=</span> <span class="number">1</span>;<span class="comment">//收藏</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">CANCEL_COLLECT_MATERIAL</span> <span class="operator">=</span> <span class="number">0</span>;<span class="comment">//取消收藏</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">WM_NEWS_TYPE_IMAGE</span> <span class="operator">=</span> <span class="string">&quot;image&quot;</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_NEWS_NONE_IMAGE</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_NEWS_SINGLE_IMAGE</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_NEWS_MANY_IMAGE</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_NEWS_TYPE_AUTO</span> <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_CONTENT_REFERENCE</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Short</span> <span class="variable">WM_COVER_REFERENCE</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>发布文章功能的关键代码</strong></p>
<p>存在许多的bug</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.service.impl;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.metadata.IPage;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.plugins.pagination.Page;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.constants.WemediaConstants;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.exception.CustomException;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.PageResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.enums.AppHttpCodeEnum;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.dtos.WmNewsDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.dtos.WmNewsPageReqDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmMaterial;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmNews;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmNewsMaterial;</span><br><span class="line"><span class="keyword">import</span> com.heima.utils.thread.WmThreadLocalUtil;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmMaterialMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmNewsMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmNewsMaterialMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.service.WmNewsService;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.jute.compiler.JString;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.BeanUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="keyword">import</span> java.util.stream.Collectors;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span>&lt;WmNewsMapper, WmNews&gt; <span class="keyword">implements</span> <span class="title class_">WmNewsService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmNewsMaterialMapper wmNewsMaterialMapper;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmMaterialMapper wmMaterialMapper;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">findNewsList</span><span class="params">(WmNewsPageReqDto wmNewsPageReqDto)</span> &#123;</span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> wmNewsPageReqDto.checkParam();</span><br><span class="line"> <span class="comment">//2.根据条件查询</span></span><br><span class="line"> <span class="type">IPage</span> <span class="variable">page</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Page</span>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize());</span><br><span class="line"> LambdaQueryWrapper&lt;WmNews&gt; queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;&gt;();</span><br><span class="line"> <span class="comment">//状态</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsPageReqDto.getStatus() != <span class="literal">null</span>) &#123;</span><br><span class="line"> queryWrapper.eq(WmNews::getStatus, wmNewsPageReqDto.getStatus());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//开始时间 结束时间</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsPageReqDto.getBeginPubDate() != <span class="literal">null</span> &amp;&amp; wmNewsPageReqDto.getEndPubDate() != <span class="literal">null</span>) &#123;</span><br><span class="line"> queryWrapper.between(WmNews::getPublishTime, wmNewsPageReqDto.getBeginPubDate(), wmNewsPageReqDto.getEndPubDate());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//所属频道id</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsPageReqDto.getChannelId() != <span class="literal">null</span>) &#123;</span><br><span class="line"> queryWrapper.eq(WmNews::getChannelId, wmNewsPageReqDto.getChannelId());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//关键字</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsPageReqDto.getKeyword() != <span class="literal">null</span>) &#123;</span><br><span class="line"> queryWrapper.like(WmNews::getTitle, wmNewsPageReqDto.getKeyword());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//查询当前登录人的文章</span></span><br><span class="line"> queryWrapper.eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId());</span><br><span class="line"> <span class="comment">//按照发布时间倒序查询</span></span><br><span class="line"> queryWrapper.orderByDesc(WmNews::getPublishTime);</span><br><span class="line"> page = page(page, queryWrapper);</span><br><span class="line"> <span class="comment">//3.结果返回</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageResponseResult</span>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize(), (<span class="type">int</span>) page.getTotal());</span><br><span class="line"> responseResult.setData(page.getRecords());</span><br><span class="line"> <span class="keyword">return</span> responseResult;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">submitNews</span><span class="params">(WmNewsDto wmNewsDto)</span> &#123;</span><br><span class="line"> <span class="comment">//参数校验</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsDto == <span class="literal">null</span> || wmNewsDto.getContent() == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//保存或者修改文章</span></span><br><span class="line"> <span class="type">WmNews</span> <span class="variable">wmNews</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WmNews</span>();</span><br><span class="line"> BeanUtils.copyProperties(wmNewsDto, wmNews);</span><br><span class="line"> <span class="comment">//封面图片从list集合转化成字符串(以,作为分割符号)</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsDto.getImages() != <span class="literal">null</span> &amp;&amp; wmNewsDto.getImages().size() &gt; <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">imageStr</span> <span class="operator">=</span> StringUtils.join(wmNewsDto.getImages(), <span class="string">&quot;,&quot;</span>);</span><br><span class="line"> wmNews.setImages(imageStr);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//设置封面的类型(数据库中封面的类型是无符号的,无法使用-1表示,所以我们先置空)</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) &#123;</span><br><span class="line"> wmNews.setType(<span class="literal">null</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//保存或者修改文章的方法</span></span><br><span class="line"> saveOrUpdateWmNews(wmNews);</span><br><span class="line"> <span class="comment">//判断是否为草稿,如果是草稿就退出该方法,草稿是不保存文章与素材的关系的</span></span><br><span class="line"> <span class="keyword">if</span> (wmNewsDto.getStatus().equals(WmNews.Status.NORMAL.getCode())) &#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//不是草稿,保存文章内容与素材的关系</span></span><br><span class="line"> <span class="comment">//获取文章内容中的图片信息</span></span><br><span class="line"> List&lt;String&gt; materials = getUrlInfo(wmNewsDto.getContent());</span><br><span class="line"> <span class="comment">//保存文章和素材的关系</span></span><br><span class="line"> saveRelativeInfoContent(materials,wmNews.getId());</span><br><span class="line"> <span class="comment">//文章封面图片与素材的关系,布局是自动的,需要自动匹配图片</span></span><br><span class="line"> saveRelativeInfoForCover(wmNewsDto,wmNews,materials);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存文章封面图片与素材的关系,布局是自动的,需要自动匹配图片</span></span><br><span class="line"><span class="comment"> * 1.如果内容图片大于等于1 小于3 单图 type 1</span></span><br><span class="line"><span class="comment"> * 2.如果内容图片大于3 多图 type 3</span></span><br><span class="line"><span class="comment"> * 3.如果内容没有图片 无图 type 0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">saveRelativeInfoForCover</span><span class="params">(WmNewsDto wmNewsDto, WmNews wmNews, List&lt;String&gt; materials)</span> &#123;</span><br><span class="line"> List&lt;String&gt; images = wmNewsDto.getImages();</span><br><span class="line"> <span class="comment">//处理匹配规则</span></span><br><span class="line"> <span class="keyword">if</span>(wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO))&#123;</span><br><span class="line"> <span class="keyword">if</span>(materials.size() &gt;= <span class="number">3</span>)&#123;<span class="comment">//多图</span></span><br><span class="line"> wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);</span><br><span class="line"> <span class="comment">//截取这篇文章中的三种图片给文章的封面</span></span><br><span class="line"> images = materials.stream().limit(<span class="number">3</span>).collect(Collectors.toList());</span><br><span class="line"> &#125;<span class="keyword">else</span> <span class="keyword">if</span> (materials.size() &gt; <span class="number">1</span> &amp;&amp; materials.size() &lt; <span class="number">3</span>)&#123;<span class="comment">//单图</span></span><br><span class="line"> wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);</span><br><span class="line"> images = materials.stream().limit(<span class="number">1</span>).collect(Collectors.toList());</span><br><span class="line"> &#125;<span class="keyword">else</span> &#123;<span class="comment">//无图</span></span><br><span class="line"> wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//修改文章</span></span><br><span class="line"> <span class="keyword">if</span> (images != <span class="literal">null</span> &amp;&amp; images.size() &gt; <span class="number">0</span>)&#123;</span><br><span class="line"> wmNews.setImages(StringUtils.join(images,<span class="string">&quot;,&quot;</span>));</span><br><span class="line"> &#125;</span><br><span class="line"> updateById(wmNews);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//保存封面与素材的关系</span></span><br><span class="line"> <span class="keyword">if</span> (images != <span class="literal">null</span> &amp;&amp; images.size() &gt; <span class="number">0</span>)&#123;</span><br><span class="line"> saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存文章和素材的对应关系</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> materials 同一篇文章的所有素材图片url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> newsId 文章的id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">saveRelativeInfoContent</span><span class="params">(List&lt;String&gt; materials, Integer newsId)</span> &#123;</span><br><span class="line"> saveRelativeInfo(materials,newsId,WemediaConstants.WM_CONTENT_REFERENCE);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存文章图片与素材的关系到数据库中</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> materials 同一篇文章中所有的素材图片</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> newsId 文章的id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">saveRelativeInfo</span><span class="params">(List&lt;String&gt; materials, Integer newsId, Short type)</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (materials != <span class="literal">null</span> &amp;&amp; !materials.isEmpty())&#123;</span><br><span class="line"> <span class="comment">//根据图片的url查询素材的id</span></span><br><span class="line"> LambdaQueryWrapper&lt;WmMaterial&gt; queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;&gt;();</span><br><span class="line"> queryWrapper.in(WmMaterial::getUrl,materials);</span><br><span class="line"> List&lt;WmMaterial&gt; wmMaterials = wmMaterialMapper.selectList(queryWrapper);</span><br><span class="line"> <span class="comment">//判断素材是否被删除</span></span><br><span class="line"> <span class="keyword">if</span> (wmMaterials == <span class="literal">null</span> || wmMaterials.size() == <span class="number">0</span>)&#123;</span><br><span class="line"> <span class="comment">//手动的抛出异常,上面的操作可以回滚</span></span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">CustomException</span>(AppHttpCodeEnum.MATERIASL_REFERENCE);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (materials.size() != wmMaterials.size())&#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">CustomException</span>(AppHttpCodeEnum.MATERIASL_REFERENCE);</span><br><span class="line"> &#125;</span><br><span class="line"> List&lt;Integer&gt; idList = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());</span><br><span class="line"> wmNewsMaterialMapper.saveRelations(idList,newsId,type);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提取文章内容中的图片信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content 文章的内容信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 图片url组成的集合</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> List&lt;String&gt; <span class="title function_">getUrlInfo</span><span class="params">(String content)</span> &#123;</span><br><span class="line"> ArrayList&lt;String&gt; materials = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"> List&lt;Map&gt; maps = JSON.parseArray(content, Map.class);</span><br><span class="line"> <span class="keyword">for</span> (Map map : maps) &#123;</span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;type&quot;</span>).equals(<span class="string">&quot;image&quot;</span>))&#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">imgUrl</span> <span class="operator">=</span> (String) map.get(<span class="string">&quot;value&quot;</span>);</span><br><span class="line"> materials.add(imgUrl);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> materials;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存或者修改文章的方法</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章实体类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">saveOrUpdateWmNews</span><span class="params">(WmNews wmNews)</span> &#123;</span><br><span class="line"> <span class="comment">//补全属性</span></span><br><span class="line"> wmNews.setUserId(WmThreadLocalUtil.getUser().getId());</span><br><span class="line"> wmNews.setCreatedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> wmNews.setSubmitedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> wmNews.setEnable((<span class="type">short</span>) <span class="number">1</span>); <span class="comment">//设置默认上架</span></span><br><span class="line"> <span class="comment">//判断是保存还是修改操作,执行不同的处理逻辑</span></span><br><span class="line"> <span class="keyword">if</span> (wmNews.getId() == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//保存操作</span></span><br><span class="line"> save(wmNews);</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//修改操作</span></span><br><span class="line"> <span class="comment">//删除文章与素材的关联关系</span></span><br><span class="line"> LambdaQueryWrapper&lt;WmNewsMaterial&gt; queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span>&lt;&gt;();</span><br><span class="line"> queryWrapper.eq(WmNewsMaterial::getNewsId, wmNews.getId());</span><br><span class="line"> wmNewsMaterialMapper.delete(queryWrapper);</span><br><span class="line"> updateById(wmNews);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20231029220319010.png" alt="image-20231029220319010"></p>
<h3 id="4-4-文章的审核功能-未实现"><a href="#4-4-文章的审核功能-未实现" class="headerlink" title="4.4 文章的审核功能(未实现)"></a>4.4 文章的审核功能(未实现)</h3><h4 id="4-4-1-文章审核功能介绍"><a href="#4-4-1-文章审核功能介绍" class="headerlink" title="4.4.1 文章审核功能介绍"></a>4.4.1 文章审核功能介绍</h4><p>调用第三方的接口(阿里云内容安全审核接口)实现审核功能</p>
<p><strong>功能介绍</strong></p>
<p><img src="/pictures/image-20231029220622019.png" alt="image-20231029220622019"></p>
<p><img src="/pictures/image-20231029220707636.png" alt="image-20231029220707636"></p>
<p><strong>审核流程</strong></p>
<p><img src="/pictures/image-20231029221745020.png" alt="image-20231029221745020"></p>
<p>1 自媒体端发布文章后,开始审核文章</p>
<p>2 审核的主要是审核文章的内容(文本内容和图片)</p>
<p>3 借助第三方提供的接口审核文本</p>
<p>4 借助第三方提供的接口审核图片由于图片存储到minIO中需要先下载才能审核</p>
<p>5 如果审核失败则需要修改自媒体文章的状态status:2 审核失败 status:3 转到人工审核</p>
<p>6 如果审核成功则需要在文章微服务中创建app端需要的文章</p>
<h4 id="4-4-2-调用第三方的审核接口"><a href="#4-4-2-调用第三方的审核接口" class="headerlink" title="4.4.2 调用第三方的审核接口"></a>4.4.2 调用第三方的审核接口</h4><p><strong>第三方审核接口</strong></p>
<p>1.内容安全接口介绍:</p>
<p>内容安全是识别服务支持对图片、视频、文本、语音等对象进行多样化场景检测有效降低内容违规风险。目前很多平台都支持内容检测如阿里云、腾讯云、百度AI、网易云等国内大型互联网公司都对外提供了API。</p>
<p>2.文件检测和图片检测api文档</p>
<p>文本垃圾内容Java SDK: <a target="_blank" rel="noopener" href="https://help.aliyun.com/document_detail/53427.html?spm=a2c4g.11186623.6.717.466d7544QbU8Lr">https://help.aliyun.com/document_detail/53427.html?spm=a2c4g.11186623.6.717.466d7544QbU8Lr</a></p>
<p>图片垃圾内容Java SDK: <a target="_blank" rel="noopener" href="https://help.aliyun.com/document_detail/53424.html?spm=a2c4g.11186623.6.715.c8f69b12ey35j4">https://help.aliyun.com/document_detail/53424.html?spm=a2c4g.11186623.6.715.c8f69b12ey35j4</a></p>
<p><strong>项目中集成阿里云内容安全接口</strong></p>
<p>1.依赖导入</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.aliyun<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>aliyun-java-sdk-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.aliyun<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>aliyun-java-sdk-green<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>2.相关的工具类</p>
<p>GreenImageScan(图片审核的工具类)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.common.aliyun;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONArray;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONObject;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.DefaultAcsClient;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.IAcsClient;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.green.model.v20180509.ImageSyncScanRequest;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.FormatType;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.HttpResponse;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.MethodType;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.ProtocolType;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.profile.DefaultProfile;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.profile.IClientProfile;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.util.ClientUploader;</span><br><span class="line"><span class="keyword">import</span> lombok.Getter;</span><br><span class="line"><span class="keyword">import</span> lombok.Setter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.PropertySource;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@Setter</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;aliyun&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GreenImageScan</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String accessKeyId;</span><br><span class="line"> <span class="keyword">private</span> String secret;</span><br><span class="line"> <span class="keyword">private</span> String scenes;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Map <span class="title function_">imageScan</span><span class="params">(List&lt;<span class="type">byte</span>[]&gt; imageList)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> <span class="type">IClientProfile</span> <span class="variable">profile</span> <span class="operator">=</span> DefaultProfile</span><br><span class="line"> .getProfile(<span class="string">&quot;cn-shanghai&quot;</span>, accessKeyId, secret);</span><br><span class="line"> DefaultProfile</span><br><span class="line"> .addEndpoint(<span class="string">&quot;cn-shanghai&quot;</span>, <span class="string">&quot;cn-shanghai&quot;</span>, <span class="string">&quot;Green&quot;</span>, <span class="string">&quot;green.cn-shanghai.aliyuncs.com&quot;</span>);</span><br><span class="line"> <span class="type">IAcsClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultAcsClient</span>(profile);</span><br><span class="line"> <span class="type">ImageSyncScanRequest</span> <span class="variable">imageSyncScanRequest</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ImageSyncScanRequest</span>();</span><br><span class="line"> <span class="comment">// 指定api返回格式</span></span><br><span class="line"> imageSyncScanRequest.setAcceptFormat(FormatType.JSON);</span><br><span class="line"> <span class="comment">// 指定请求方法</span></span><br><span class="line"> imageSyncScanRequest.setMethod(MethodType.POST);</span><br><span class="line"> imageSyncScanRequest.setEncoding(<span class="string">&quot;utf-8&quot;</span>);</span><br><span class="line"> <span class="comment">//支持http和https</span></span><br><span class="line"> imageSyncScanRequest.setProtocol(ProtocolType.HTTP);</span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">httpBody</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JSONObject</span>();</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置要检测的场景, 计费是按照该处传递的场景进行</span></span><br><span class="line"><span class="comment"> * 一次请求中可以同时检测多张图片,每张图片可以同时检测多个风险场景,计费按照场景计算</span></span><br><span class="line"><span class="comment"> * 例如检测2张图片场景传递porn、terrorism计费会按照2张图片鉴黄2张图片暴恐检测计算</span></span><br><span class="line"><span class="comment"> * porn: porn表示色情场景检测</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> httpBody.put(<span class="string">&quot;scenes&quot;</span>, Arrays.asList(scenes.split(<span class="string">&quot;,&quot;</span>)));</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 如果您要检测的文件存于本地服务器上可以通过下述代码片生成url</span></span><br><span class="line"><span class="comment"> * 再将返回的url作为图片地址传递到服务端进行检测</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置待检测图片, 一张图片一个task</span></span><br><span class="line"><span class="comment"> * 多张图片同时检测时,处理的时间由最后一个处理完的图片决定</span></span><br><span class="line"><span class="comment"> * 通常情况下批量检测的平均rt比单张检测的要长, 一次批量提交的图片数越多rt被拉长的概率越高</span></span><br><span class="line"><span class="comment"> * 这里以单张图片检测作为示例, 如果是批量图片检测请自行构建多个task</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="type">ClientUploader</span> <span class="variable">clientUploader</span> <span class="operator">=</span> ClientUploader.getImageClientUploader(profile, <span class="literal">false</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> List&lt;JSONObject&gt; urlList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;JSONObject&gt;();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">byte</span>[] bytes : imageList) &#123;</span><br><span class="line"> url = clientUploader.uploadBytes(bytes);</span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">task</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JSONObject</span>();</span><br><span class="line"> task.put(<span class="string">&quot;dataId&quot;</span>, UUID.randomUUID().toString());</span><br><span class="line"> <span class="comment">//设置图片链接为上传后的url</span></span><br><span class="line"> task.put(<span class="string">&quot;url&quot;</span>, url);</span><br><span class="line"> task.put(<span class="string">&quot;time&quot;</span>, <span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> urlList.add(task);</span><br><span class="line"> &#125;</span><br><span class="line"> httpBody.put(<span class="string">&quot;tasks&quot;</span>, urlList);</span><br><span class="line"> imageSyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),</span><br><span class="line"> <span class="string">&quot;UTF-8&quot;</span>, FormatType.JSON);</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 请设置超时时间, 服务端全链路处理超时时间为10秒请做相应设置</span></span><br><span class="line"><span class="comment"> * 如果您设置的ReadTimeout小于服务端处理的时间程序中会获得一个read timeout异常</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> imageSyncScanRequest.setConnectTimeout(<span class="number">3000</span>);</span><br><span class="line"> imageSyncScanRequest.setReadTimeout(<span class="number">10000</span>);</span><br><span class="line"> <span class="type">HttpResponse</span> <span class="variable">httpResponse</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> httpResponse = client.doAction(imageSyncScanRequest);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> Map&lt;String, String&gt; resultMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//服务端接收到请求,并完成处理返回的结果</span></span><br><span class="line"> <span class="keyword">if</span> (httpResponse != <span class="literal">null</span> &amp;&amp; httpResponse.isSuccess()) &#123;</span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">scrResponse</span> <span class="operator">=</span> JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));</span><br><span class="line"> System.out.println(JSON.toJSONString(scrResponse, <span class="literal">true</span>));</span><br><span class="line"> <span class="type">int</span> <span class="variable">requestCode</span> <span class="operator">=</span> scrResponse.getIntValue(<span class="string">&quot;code&quot;</span>);</span><br><span class="line"> <span class="comment">//每一张图片的检测结果</span></span><br><span class="line"> <span class="type">JSONArray</span> <span class="variable">taskResults</span> <span class="operator">=</span> scrResponse.getJSONArray(<span class="string">&quot;data&quot;</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="number">200</span> == requestCode) &#123;</span><br><span class="line"> <span class="keyword">for</span> (Object taskResult : taskResults) &#123;</span><br><span class="line"> <span class="comment">//单张图片的处理结果</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">taskCode</span> <span class="operator">=</span> ((JSONObject) taskResult).getIntValue(<span class="string">&quot;code&quot;</span>);</span><br><span class="line"> <span class="comment">//图片要检测的场景的处理结果, 如果是多个场景,则会有每个场景的结果</span></span><br><span class="line"> <span class="type">JSONArray</span> <span class="variable">sceneResults</span> <span class="operator">=</span> ((JSONObject) taskResult).getJSONArray(<span class="string">&quot;results&quot;</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="number">200</span> == taskCode) &#123;</span><br><span class="line"> <span class="keyword">for</span> (Object sceneResult : sceneResults) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">scene</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;scene&quot;</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">label</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;label&quot;</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">suggestion</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;suggestion&quot;</span>);</span><br><span class="line"> <span class="comment">//根据scene和suggetion做相关处理</span></span><br><span class="line"> <span class="comment">//do something</span></span><br><span class="line"> System.out.println(<span class="string">&quot;scene = [&quot;</span> + scene + <span class="string">&quot;]&quot;</span>);</span><br><span class="line"> System.out.println(<span class="string">&quot;suggestion = [&quot;</span> + suggestion + <span class="string">&quot;]&quot;</span>);</span><br><span class="line"> System.out.println(<span class="string">&quot;suggestion = [&quot;</span> + label + <span class="string">&quot;]&quot;</span>);</span><br><span class="line"> <span class="keyword">if</span> (!suggestion.equals(<span class="string">&quot;pass&quot;</span>)) &#123;</span><br><span class="line"> resultMap.put(<span class="string">&quot;suggestion&quot;</span>, suggestion);</span><br><span class="line"> resultMap.put(<span class="string">&quot;label&quot;</span>, label);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//单张图片处理失败, 原因视具体的情况详细分析</span></span><br><span class="line"> System.out.println(<span class="string">&quot;task process fail. task response:&quot;</span> + JSON.toJSONString(taskResult));</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> resultMap.put(<span class="string">&quot;suggestion&quot;</span>,<span class="string">&quot;pass&quot;</span>);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 表明请求整体处理失败,原因视具体的情况详细分析</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> System.out.println(<span class="string">&quot;the whole image scan request failed. response:&quot;</span> + JSON.toJSONString(scrResponse));</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>GreenTextScan文字审核的工具类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.common.aliyun;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONArray;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONObject;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.DefaultAcsClient;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.IAcsClient;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.exceptions.ClientException;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.exceptions.ServerException;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.green.model.v20180509.TextScanRequest;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.FormatType;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.http.HttpResponse;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.profile.DefaultProfile;</span><br><span class="line"><span class="keyword">import</span> com.aliyuncs.profile.IClientProfile;</span><br><span class="line"><span class="keyword">import</span> lombok.Getter;</span><br><span class="line"><span class="keyword">import</span> lombok.Setter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.PropertySource;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@Setter</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;aliyun&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GreenTextScan</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String accessKeyId;</span><br><span class="line"> <span class="keyword">private</span> String secret;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Map <span class="title function_">greeTextScan</span><span class="params">(String content)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> System.out.println(accessKeyId);</span><br><span class="line"> <span class="type">IClientProfile</span> <span class="variable">profile</span> <span class="operator">=</span> DefaultProfile</span><br><span class="line"> .getProfile(<span class="string">&quot;cn-shanghai&quot;</span>, accessKeyId, secret);</span><br><span class="line"> DefaultProfile.addEndpoint(<span class="string">&quot;cn-shanghai&quot;</span>, <span class="string">&quot;cn-shanghai&quot;</span>, <span class="string">&quot;Green&quot;</span>, <span class="string">&quot;green.cn-shanghai.aliyuncs.com&quot;</span>);</span><br><span class="line"> <span class="type">IAcsClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultAcsClient</span>(profile);</span><br><span class="line"> <span class="type">TextScanRequest</span> <span class="variable">textScanRequest</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TextScanRequest</span>();</span><br><span class="line"> textScanRequest.setAcceptFormat(FormatType.JSON); <span class="comment">// 指定api返回格式</span></span><br><span class="line"> textScanRequest.setHttpContentType(FormatType.JSON);</span><br><span class="line"> textScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); <span class="comment">// 指定请求方法</span></span><br><span class="line"> textScanRequest.setEncoding(<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line"> textScanRequest.setRegionId(<span class="string">&quot;cn-shanghai&quot;</span>);</span><br><span class="line"> List&lt;Map&lt;String, Object&gt;&gt; tasks = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;Map&lt;String, Object&gt;&gt;();</span><br><span class="line"> Map&lt;String, Object&gt; task1 = <span class="keyword">new</span> <span class="title class_">LinkedHashMap</span>&lt;String, Object&gt;();</span><br><span class="line"> task1.put(<span class="string">&quot;dataId&quot;</span>, UUID.randomUUID().toString());</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 待检测的文本长度不超过10000个字符</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> task1.put(<span class="string">&quot;content&quot;</span>, content);</span><br><span class="line"> tasks.add(task1);</span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">data</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JSONObject</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 检测场景文本垃圾检测传递antispam</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"> data.put(<span class="string">&quot;scenes&quot;</span>, Arrays.asList(<span class="string">&quot;antispam&quot;</span>));</span><br><span class="line"> data.put(<span class="string">&quot;tasks&quot;</span>, tasks);</span><br><span class="line"> System.out.println(JSON.toJSONString(data, <span class="literal">true</span>));</span><br><span class="line"> textScanRequest.setHttpContent(data.toJSONString().getBytes(<span class="string">&quot;UTF-8&quot;</span>), <span class="string">&quot;UTF-8&quot;</span>, FormatType.JSON);</span><br><span class="line"> <span class="comment">// 请务必设置超时时间</span></span><br><span class="line"> textScanRequest.setConnectTimeout(<span class="number">3000</span>);</span><br><span class="line"> textScanRequest.setReadTimeout(<span class="number">6000</span>);</span><br><span class="line"></span><br><span class="line"> Map&lt;String, String&gt; resultMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="type">HttpResponse</span> <span class="variable">httpResponse</span> <span class="operator">=</span> client.doAction(textScanRequest);</span><br><span class="line"> <span class="keyword">if</span> (httpResponse.isSuccess()) &#123;</span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">scrResponse</span> <span class="operator">=</span> JSON.parseObject(<span class="keyword">new</span> <span class="title class_">String</span>(httpResponse.getHttpContent(), <span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line"> System.out.println(JSON.toJSONString(scrResponse, <span class="literal">true</span>));</span><br><span class="line"> <span class="keyword">if</span> (<span class="number">200</span> == scrResponse.getInteger(<span class="string">&quot;code&quot;</span>)) &#123;</span><br><span class="line"> <span class="type">JSONArray</span> <span class="variable">taskResults</span> <span class="operator">=</span> scrResponse.getJSONArray(<span class="string">&quot;data&quot;</span>);</span><br><span class="line"> <span class="keyword">for</span> (Object taskResult : taskResults) &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="number">200</span> == ((JSONObject) taskResult).getInteger(<span class="string">&quot;code&quot;</span>)) &#123;</span><br><span class="line"> <span class="type">JSONArray</span> <span class="variable">sceneResults</span> <span class="operator">=</span> ((JSONObject) taskResult).getJSONArray(<span class="string">&quot;results&quot;</span>);</span><br><span class="line"> <span class="keyword">for</span> (Object sceneResult : sceneResults) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">scene</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;scene&quot;</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">label</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;label&quot;</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">suggestion</span> <span class="operator">=</span> ((JSONObject) sceneResult).getString(<span class="string">&quot;suggestion&quot;</span>);</span><br><span class="line"> System.out.println(<span class="string">&quot;suggestion = [&quot;</span> + label + <span class="string">&quot;]&quot;</span>);</span><br><span class="line"> <span class="keyword">if</span> (!suggestion.equals(<span class="string">&quot;pass&quot;</span>)) &#123;</span><br><span class="line"> resultMap.put(<span class="string">&quot;suggestion&quot;</span>, suggestion);</span><br><span class="line"> resultMap.put(<span class="string">&quot;label&quot;</span>, label);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> resultMap.put(<span class="string">&quot;suggestion&quot;</span>, <span class="string">&quot;pass&quot;</span>);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (ServerException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125; <span class="keyword">catch</span> (ClientException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3.在heima-leadnews-wemedia中的nacos配置中心添加以下配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">aliyun:</span></span><br><span class="line"> <span class="attr">accessKeyId:</span> <span class="string">xxxxxxxxxxxxxxxxxxx</span></span><br><span class="line"> <span class="attr">secret:</span> <span class="string">xxxxxxxxxxxxxxxxxxxxxxxx</span></span><br><span class="line"><span class="comment">#aliyun.scenes=porn,terrorism,ad,qrcode,live,logo</span></span><br><span class="line"> <span class="attr">scenes:</span> <span class="string">terrorism</span> <span class="comment">#检测的场景</span></span><br></pre></td></tr></table></figure>
<p>4.编写测试类测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenImageScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenTextScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> org.junit.Test;</span><br><span class="line"><span class="keyword">import</span> org.junit.runner.RunWith;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.test.context.junit4.SpringRunner;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest(classes = WemediaApplication.class)</span></span><br><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AliyunTest</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenTextScan greenTextScan;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenImageScan greenImageScan;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testScanText</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenTextScan.greeTextScan(<span class="string">&quot;我是一个好人,冰毒&quot;</span>);</span><br><span class="line"> System.out.println(map);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testScanImage</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"> <span class="type">byte</span>[] bytes = fileStorageService.downLoadFile(<span class="string">&quot;http://192.168.200.130:9000/leadnews/2021/04/26/ef3cbe458db249f7bd6fb4339e593e55.jpg&quot;</span>);</span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenImageScan.imageScan(Arrays.asList(bytes));</span><br><span class="line"> System.out.println(map);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="4-4-3-分布式ID的实现"><a href="#4-4-3-分布式ID的实现" class="headerlink" title="4.4.3 分布式ID的实现"></a>4.4.3 分布式ID的实现</h4><p>为什么使用分布式ID</p>
<p><img src="/pictures/image-20231116230439706.png" alt="image-20231116230439706"></p>
<p>分布式ID的技术选型</p>
<p><img src="/pictures/image-20231116230714014.png" alt="image-20231116230714014"></p>
<p>雪花算法的介绍</p>
<p><img src="/pictures/image-20231116230953909.png" alt="image-20231116230953909"></p>
<p>mybatis-plus已经集成了雪花算法完成以下两步即可在项目中集成雪花算法</p>
<p>第一在实体类中的id上加入如下配置指定类型为id_worker</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@TableId(value = &quot;id&quot;,type = IdType.ID_WORKER)</span></span><br><span class="line"><span class="keyword">private</span> Long id;</span><br></pre></td></tr></table></figure>
<p>第二在application.yml文件中配置数据中心id和机器id</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line"> <span class="attr">mapper-locations:</span> <span class="string">classpath*:mapper/*.xml</span></span><br><span class="line"> <span class="comment"># 设置别名包扫描路径,通过该属性可以给包中的类注册别名</span></span><br><span class="line"> <span class="attr">type-aliases-package:</span> <span class="string">com.heima.model.article.pojos</span></span><br><span class="line"> <span class="attr">global-config:</span></span><br><span class="line"> <span class="attr">datacenter-id:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">workerId:</span> <span class="number">1</span></span><br></pre></td></tr></table></figure>
<p>datacenter-id:数据中心id(取值范围0-31) workerId:机器id(取值范围0-31)</p>
<h4 id="4-4-4-审核功能的具体实现"><a href="#4-4-4-审核功能的具体实现" class="headerlink" title="4.4.4 审核功能的具体实现"></a>4.4.4 审核功能的具体实现</h4><p>由于没有阿里云相关的ak和sk所以本部分默认每篇文章的文字和图片都审核通过中间会注释掉调用第三方审核接口的代码</p>
<p><img src="/pictures/image-20231202174634986.png" alt="image-20231202174634986"></p>
<p>service层代码实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.heima.apis.article.IArticleClient;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenImageScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenTextScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmChannel;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmNews;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmUser;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmChannelMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmNewsMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmUserMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.service.WmNewsAutoScanService;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.BeanUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Value;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"><span class="keyword">import</span> java.util.stream.Collectors;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@website</span> https://qingling.icu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/11/19</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsAutoScanServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">WmNewsAutoScanService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//涉及文本内容的审核,需要调用第三方的服务,这里我们直接设置成测试环境,跳过调用第三方服务校验的过程</span></span><br><span class="line"> <span class="meta">@Value(&quot;$&#123;check.env&#125;&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String environment;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmNewsMapper wmNewsMapper;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenTextScan greenTextScan;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenImageScan greenImageScan;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> IArticleClient iArticleClient;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmChannelMapper wmChannelMapper;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmUserMapper wmUserMapper;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">autoScanWmNews</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line"> <span class="comment">//1.查询自媒体文章的信息</span></span><br><span class="line"> <span class="type">WmNews</span> <span class="variable">wmNews</span> <span class="operator">=</span> wmNewsMapper.selectById(id);</span><br><span class="line"> <span class="comment">//文章不存在的话,直接抛出异常</span></span><br><span class="line"> <span class="keyword">if</span> (wmNews == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;文章不存在,无法审核!&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//判断文章是不是待审核的状态</span></span><br><span class="line"> <span class="keyword">if</span> (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) &#123;</span><br><span class="line"> <span class="comment">//2.抽取文章内容中的文字和图片信息</span></span><br><span class="line"> Map&lt;String, Object&gt; textAndImages = getTextAndImages(wmNews);</span><br><span class="line"> <span class="comment">//3.调用阿里云的接口实现文章的审核功能</span></span><br><span class="line"> <span class="comment">//审核文本内容</span></span><br><span class="line"> <span class="type">Boolean</span> <span class="variable">isPassText</span> <span class="operator">=</span> checkText((String) textAndImages.get(<span class="string">&quot;content&quot;</span>), wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!isPassText) <span class="keyword">return</span>;</span><br><span class="line"> <span class="comment">//审核图片内容</span></span><br><span class="line"> <span class="type">Boolean</span> <span class="variable">isPassImage</span> <span class="operator">=</span> checkImages((List&lt;String&gt;) textAndImages.get(<span class="string">&quot;images&quot;</span>), wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!isPassImage) <span class="keyword">return</span>;</span><br><span class="line"> <span class="comment">//4.审核成功,保存app端的相关文章数据</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> saveAppArticle(wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!responseResult.getCode().equals(<span class="number">200</span>)) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;文章审核-保存app端文章失败&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//回填article_id</span></span><br><span class="line"> wmNews.setArticleId((Long) responseResult.getData());</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">9</span>, <span class="string">&quot;审核成功&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存app端的相关文章数据</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章相关的信息</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> ResponseResult <span class="title function_">saveAppArticle</span><span class="params">(WmNews wmNews)</span> &#123;</span><br><span class="line"> <span class="type">ArticleDto</span> <span class="variable">dto</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArticleDto</span>();</span><br><span class="line"> BeanUtils.copyProperties(wmNews, dto);</span><br><span class="line"> <span class="comment">//文章布局</span></span><br><span class="line"> dto.setLayout(wmNews.getType());</span><br><span class="line"> <span class="comment">//频道</span></span><br><span class="line"> <span class="type">WmChannel</span> <span class="variable">wmChannel</span> <span class="operator">=</span> wmChannelMapper.selectById(wmNews.getChannelId());</span><br><span class="line"> <span class="keyword">if</span> (wmChannel != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setChannelName(wmChannel.getName());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//作者</span></span><br><span class="line"> dto.setAuthorId(wmNews.getUserId().longValue());</span><br><span class="line"> <span class="type">WmUser</span> <span class="variable">wmUser</span> <span class="operator">=</span> wmUserMapper.selectById(wmNews.getUserId());</span><br><span class="line"> <span class="keyword">if</span> (wmUser != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setAuthorName(wmUser.getName());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//设置文章的id</span></span><br><span class="line"> <span class="keyword">if</span> (wmNews.getArticleId() != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setId(wmNews.getArticleId());</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//设置创建时间</span></span><br><span class="line"> dto.setCreatedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> <span class="keyword">return</span> iArticleClient.saveArticle(dto);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 审核文章的图片内容</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> images 文章的图片信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章实体</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 是否通过校验</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Boolean <span class="title function_">checkImages</span><span class="params">(List&lt;String&gt; images, WmNews wmNews)</span> &#123;</span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (images == <span class="literal">null</span> || images.size() == <span class="number">0</span> || <span class="string">&quot;test&quot;</span>.equals(environment)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//下载图片</span></span><br><span class="line"> <span class="comment">//去重</span></span><br><span class="line"> images = images.stream().distinct().collect(Collectors.toList());</span><br><span class="line"> <span class="comment">//创建集合,用于存储下载的图片</span></span><br><span class="line"> ArrayList&lt;<span class="type">byte</span>[]&gt; byteList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"> <span class="keyword">for</span> (String image : images) &#123;</span><br><span class="line"> <span class="type">byte</span>[] bytes = fileStorageService.downLoadFile(image);</span><br><span class="line"> byteList.add(bytes);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//审核图片</span></span><br><span class="line"> <span class="comment">//调用方法正式审核</span></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//调用阿里云的接口对文字进行审核</span></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenImageScan.imageScan(byteList);</span><br><span class="line"> <span class="comment">//根据审核反馈的结果做出不同的处理</span></span><br><span class="line"> <span class="keyword">if</span> (map != <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//审核失败</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;block&quot;</span>)) &#123;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">2</span>, <span class="string">&quot;图片存在违规内容!&quot;</span>);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//不确定,需要人工审核</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;review&quot;</span>)) &#123;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">3</span>, <span class="string">&quot;图片存在违规内容!&quot;</span>);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;图片审核时出现异常!&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 审核文章的文字内容</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content 文章的文字信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章实体</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 是否通过审核</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Boolean <span class="title function_">checkText</span><span class="params">(String content, WmNews wmNews)</span> &#123;</span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> ((content + wmNews.getTitle()).length() == <span class="number">0</span> || <span class="string">&quot;test&quot;</span>.equals(environment)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//调用方法正式审核</span></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//调用阿里云的接口对文字进行审核</span></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenTextScan.greeTextScan(content);</span><br><span class="line"> <span class="comment">//根据审核反馈的结果做出不同的处理</span></span><br><span class="line"> <span class="keyword">if</span> (map != <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//审核失败</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;block&quot;</span>)) &#123;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">2</span>, <span class="string">&quot;文章中的文字信息出现违规内容!&quot;</span>);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//不确定,需要人工审核</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;review&quot;</span>)) &#123;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">3</span>, <span class="string">&quot;文章中的文字信息在审核时有不确定的内容!&quot;</span>);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;文字审核时出现异常!&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 修改文章审核相关信息的方法</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章实体</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> status 文章的审核状态</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> reason 审核不通过的原因</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">updateWmNews</span><span class="params">(WmNews wmNews, <span class="type">short</span> status, String reason)</span> &#123;</span><br><span class="line"> wmNews.setStatus(status);</span><br><span class="line"> wmNews.setReason(reason);</span><br><span class="line"> wmNewsMapper.updateById(wmNews);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提取文章中的文字和图片信息</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews 文章</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 图片和文字组成的集合</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Map&lt;String, Object&gt; <span class="title function_">getTextAndImages</span><span class="params">(WmNews wmNews)</span> &#123;</span><br><span class="line"> <span class="comment">//存储文字信息</span></span><br><span class="line"> <span class="type">StringBuilder</span> <span class="variable">stringBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line"> <span class="comment">//文章中图片信息组成的集合</span></span><br><span class="line"> ArrayList&lt;String&gt; images = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"> <span class="comment">//从文章中提取文字和图片信息</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(wmNews.getContent())) &#123;</span><br><span class="line"> List&lt;Map&gt; maps = JSON.parseArray(wmNews.getContent(), Map.class);</span><br><span class="line"> <span class="keyword">for</span> (Map map : maps) &#123;</span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;type&quot;</span>).equals(<span class="string">&quot;text&quot;</span>)) &#123;</span><br><span class="line"> stringBuilder.append(map.get(<span class="string">&quot;value&quot;</span>));</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;type&quot;</span>).equals(<span class="string">&quot;image&quot;</span>)) &#123;</span><br><span class="line"> images.add((String) map.get(<span class="string">&quot;values&quot;</span>));</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//保存文章的封面信息到图片的集合中</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(wmNews.getImages())) &#123;</span><br><span class="line"> String[] split = wmNews.getImages().split(<span class="string">&quot;,&quot;</span>);</span><br><span class="line"> images.addAll(Arrays.asList(split));</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//创建返回的结果</span></span><br><span class="line"> HashMap&lt;String, Object&gt; resultMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> resultMap.put(<span class="string">&quot;content&quot;</span>, stringBuilder.toString());</span><br><span class="line"> resultMap.put(<span class="string">&quot;images&quot;</span>, images);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>单元测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.WemediaApplication;</span><br><span class="line"><span class="keyword">import</span> org.junit.Test;</span><br><span class="line"><span class="keyword">import</span> org.junit.runner.RunWith;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.test.context.junit4.SpringRunner;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/12/2</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootTest(classes = WemediaApplication.class)</span></span><br><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsAutoScanServiceTest</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmNewsAutoScanService wmNewsAutoScanService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">autoScanWmNews</span><span class="params">()</span> &#123;</span><br><span class="line"> wmNewsAutoScanService.autoScanWmNews(<span class="number">3</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20231202232643073.png" alt="image-20231202232643073"></p>
<p>实现步骤:</p>
<p>在heima-leadnews-feign-api编写降级逻辑</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.apis.article.fallback;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.apis.article.IArticleClient;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.enums.AppHttpCodeEnum;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * feign失败配置</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">IArticleClientFallback</span> <span class="keyword">implements</span> <span class="title class_">IArticleClient</span> &#123;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">saveArticle</span><span class="params">(ArticleDto dto)</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,<span class="string">&quot;获取数据失败&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在自媒体微服务中添加类,扫描降级代码类的包</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.ComponentScan;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ComponentScan(&quot;com.heima.apis.article.fallback&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InitConfig</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>②:远程接口中指向降级代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.apis.article;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.apis.article.fallback.IArticleClientFallback;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.openfeign.FeignClient;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestBody;</span><br><span class="line"></span><br><span class="line"><span class="meta">@FeignClient(value = &quot;leadnews-article&quot;,fallback = IArticleClientFallback.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IArticleClient</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping(&quot;/api/v1/article/save&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">saveArticle</span><span class="params">(<span class="meta">@RequestBody</span> ArticleDto dto)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>客户端开启降级heima-leadnews-wemedia</p>
<p>在wemedia的nacos配置中心里添加如下内容开启服务降级也可以指定服务响应的超时的时间</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">feign:</span></span><br><span class="line"> <span class="comment"># 开启feign对hystrix熔断降级的支持</span></span><br><span class="line"> <span class="attr">hystrix:</span></span><br><span class="line"> <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line"> <span class="comment"># 修改调用超时时间</span></span><br><span class="line"> <span class="attr">client:</span></span><br><span class="line"> <span class="attr">config:</span></span><br><span class="line"> <span class="attr">default:</span></span><br><span class="line"> <span class="attr">connectTimeout:</span> <span class="number">2000</span></span><br><span class="line"> <span class="attr">readTimeout:</span> <span class="number">2000</span></span><br></pre></td></tr></table></figure>
<p>④:测试</p>
<p>在ApArticleServiceImpl类中saveArticle方法添加代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line"> Thread.sleep(<span class="number">3000</span>);</span><br><span class="line">&#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在自媒体端进行审核测试,会出现服务降级的现象</p>
<h3 id="4-5-app端文章保存功能"><a href="#4-5-app端文章保存功能" class="headerlink" title="4.5 app端文章保存功能"></a>4.5 app端文章保存功能</h3><p><strong>实现思路</strong></p>
<p>在文章审核成功以后需要在app的article库中新增文章数据</p>
<p>1.保存文章信息 ap_article</p>
<p>2.保存文章配置信息 ap_article_config</p>
<p>3.保存文章内容 ap_article_content</p>
<p><img src="/pictures/image-20231117221219911.png" alt="image-20231117221219911"></p>
<p><strong>保存文章的接口</strong></p>
<table>
<thead>
<tr>
<th></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>接口路径</td>
<td>&#x2F;api&#x2F;v1&#x2F;article&#x2F;save</td>
</tr>
<tr>
<td>请求方式</td>
<td>POST</td>
</tr>
<tr>
<td>参数</td>
<td>ArticleDto</td>
</tr>
<tr>
<td>响应结果</td>
<td>ResponseResult</td>
</tr>
</tbody></table>
<p>ArticleDto</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.article.dtos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticle;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleDto</span> <span class="keyword">extends</span> <span class="title class_">ApArticle</span> &#123;</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 文章内容</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String content;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>成功:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;code&quot;</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;errorMessage&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;操作成功&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;data&quot;</span><span class="punctuation">:</span><span class="string">&quot;1302864436297442242&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p>失败:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;code&quot;</span><span class="punctuation">:</span><span class="number">501</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;errorMessage&quot;</span><span class="punctuation">:</span><span class="string">&quot;参数失效&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;code&quot;</span><span class="punctuation">:</span><span class="number">501</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;errorMessage&quot;</span><span class="punctuation">:</span><span class="string">&quot;文章没有找到&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p><strong>实现步骤</strong></p>
<p><img src="/pictures/image-20231117221333422.png" alt="image-20231117221333422"></p>
<p>功能实现:</p>
<p>在heima-leadnews- feign-api中新增接口</p>
<p>第一线导入feign的依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-openfeign<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>第二:定义文章端的接口</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">package com.heima.apis.article;</span><br><span class="line"></span><br><span class="line">import com.heima.model.article.dtos.ArticleDto;</span><br><span class="line">import com.heima.model.common.dtos.ResponseResult;</span><br><span class="line">import org.springframework.cloud.openfeign.FeignClient;</span><br><span class="line">import org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line">import org.springframework.web.bind.annotation.RequestBody;</span><br><span class="line"></span><br><span class="line">import java.io.IOException;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@FeignClient(value = <span class="string">&quot;leadnews-article&quot;</span>)</span><br><span class="line">public interface IArticleClient <span class="punctuation">&#123;</span></span><br><span class="line"></span><br><span class="line"> @PostMapping(<span class="string">&quot;/api/v1/article/save&quot;</span>)</span><br><span class="line"> public ResponseResult saveArticle(@RequestBody ArticleDto dto) ;</span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p>在heima-leadnews-article中实现该方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.feign;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.apis.article.IArticleClient;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ApArticleService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleClient</span> <span class="keyword">implements</span> <span class="title class_">IArticleClient</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleService apArticleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@PostMapping(&quot;/api/v1/article/save&quot;)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">saveArticle</span><span class="params">(<span class="meta">@RequestBody</span> ArticleDto dto)</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> apArticleService.saveArticle(dto);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>拷贝mapper</p>
<p>在资料文件夹中拷贝ApArticleConfigMapper类到mapper文件夹中</p>
<p>同时修改ApArticleConfig类添加如下构造函数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.article.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"><span class="keyword">import</span> lombok.NoArgsConstructor;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * APP已发布文章配置表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@TableName(&quot;ap_article_config&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ApArticleConfig</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ApArticleConfig</span><span class="params">(Long articleId)</span>&#123;</span><br><span class="line"> <span class="built_in">this</span>.articleId = articleId;</span><br><span class="line"> <span class="built_in">this</span>.isComment = <span class="literal">true</span>;</span><br><span class="line"> <span class="built_in">this</span>.isForward = <span class="literal">true</span>;</span><br><span class="line"> <span class="built_in">this</span>.isDelete = <span class="literal">false</span>;</span><br><span class="line"> <span class="built_in">this</span>.isDown = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;,type = IdType.ID_WORKER)</span></span><br><span class="line"> <span class="keyword">private</span> Long id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 文章id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;article_id&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Long articleId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否可评论</span></span><br><span class="line"><span class="comment"> * true: 可以评论 1</span></span><br><span class="line"><span class="comment"> * false: 不可评论 0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_comment&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean isComment;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否转发</span></span><br><span class="line"><span class="comment"> * true: 可以转发 1</span></span><br><span class="line"><span class="comment"> * false: 不可转发 0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_forward&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean isForward;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否下架</span></span><br><span class="line"><span class="comment"> * true: 下架 1</span></span><br><span class="line"><span class="comment"> * false: 没有下架 0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_down&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean isDown;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 是否已删除</span></span><br><span class="line"><span class="comment"> * true: 删除 1</span></span><br><span class="line"><span class="comment"> * false: 没有删除 0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;is_delete&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Boolean isDelete;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在ApArticleService中新增方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存app端相关文章</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> dto</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">ResponseResult <span class="title function_">saveArticle</span><span class="params">(ArticleDto dto)</span> ;</span><br></pre></td></tr></table></figure>
<p>实现类:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> ApArticleConfigMapper apArticleConfigMapper;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> ApArticleContentMapper apArticleContentMapper;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存app端相关文章</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> dto</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">saveArticle</span><span class="params">(ArticleDto dto)</span> &#123;</span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> <span class="keyword">if</span>(dto == <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="type">ApArticle</span> <span class="variable">apArticle</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticle</span>();</span><br><span class="line"> BeanUtils.copyProperties(dto,apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.判断是否存在id</span></span><br><span class="line"> <span class="keyword">if</span>(dto.getId() == <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="comment">//2.1 不存在id 保存 文章 文章配置 文章内容</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存文章</span></span><br><span class="line"> save(apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存配置</span></span><br><span class="line"> <span class="type">ApArticleConfig</span> <span class="variable">apArticleConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticleConfig</span>(apArticle.getId());</span><br><span class="line"> apArticleConfigMapper.insert(apArticleConfig);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存 文章内容</span></span><br><span class="line"> <span class="type">ApArticleContent</span> <span class="variable">apArticleContent</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticleContent</span>();</span><br><span class="line"> apArticleContent.setArticleId(apArticle.getId());</span><br><span class="line"> apArticleContent.setContent(dto.getContent());</span><br><span class="line"> apArticleContentMapper.insert(apArticleContent);</span><br><span class="line"></span><br><span class="line"> &#125;<span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//2.2 存在id 修改 文章 文章内容</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//修改 文章</span></span><br><span class="line"> updateById(apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//修改文章内容</span></span><br><span class="line"> <span class="type">ApArticleContent</span> <span class="variable">apArticleContent</span> <span class="operator">=</span> apArticleContentMapper.selectOne(Wrappers.&lt;ApArticleContent&gt;lambdaQuery().eq(ApArticleContent::getArticleId, dto.getId()));</span><br><span class="line"> apArticleContent.setContent(dto.getContent());</span><br><span class="line"> apArticleContentMapper.updateById(apArticleContent);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//3.结果返回 文章的id</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(apArticle.getId());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>⑤:测试</p>
<p>编写junit单元测试或使用postman进行测试</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span><span class="string">&quot;黑马头条项目背景&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;authoId&quot;</span><span class="punctuation">:</span><span class="number">1102</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;layout&quot;</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;labels&quot;</span><span class="punctuation">:</span><span class="string">&quot;黑马头条&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;publishTime&quot;</span><span class="punctuation">:</span><span class="string">&quot;2028-03-14T11:35:49.000Z&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;images&quot;</span><span class="punctuation">:</span> <span class="string">&quot;http://192.168.200.130:9000/leadnews/2021/04/26/5ddbdb5c68094ce393b08a47860da275.jpg&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;content&quot;</span><span class="punctuation">:</span><span class="string">&quot;黑马头条项目背景,黑马头条项目背景,黑马头条项目背景,黑马头条项目背景,黑马头条项目背景&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20231119212628556.png" alt="image-20231119212628556"></p>
<h3 id="4-6-发布文章提交审核集成"><a href="#4-6-发布文章提交审核集成" class="headerlink" title="4.6 发布文章提交审核集成"></a>4.6 发布文章提交审核集成</h3><h4 id="4-6-1-同步调用与异步调用"><a href="#4-6-1-同步调用与异步调用" class="headerlink" title="4.6.1 同步调用与异步调用"></a>4.6.1 同步调用与异步调用</h4><p><img src="/pictures/image-20231202234439362.png" alt="image-20231202234439362"></p>
<h4 id="4-6-2-Springboot集成异步线程调用"><a href="#4-6-2-Springboot集成异步线程调用" class="headerlink" title="4.6.2 Springboot集成异步线程调用"></a>4.6.2 Springboot集成异步线程调用</h4><p>①:在自动审核的方法上加上@Async注解标明要异步调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="meta">@Async</span> <span class="comment">//标明当前方法是一个异步方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">autoScanWmNews</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line"> <span class="comment">//代码略</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>②:在文章发布成功后调用审核的方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> WmNewsAutoScanService wmNewsAutoScanService;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 发布修改文章或保存为草稿</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> dto</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">submitNews</span><span class="params">(WmNewsDto dto)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//代码略</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//审核文章</span></span><br><span class="line"> wmNewsAutoScanService.autoScanWmNews(wmNews.getId());</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>③:在自媒体引导类中使用@EnableAsync注解开启异步调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@EnableDiscoveryClient</span></span><br><span class="line"><span class="meta">@MapperScan(&quot;com.heima.wemedia.mapper&quot;)</span></span><br><span class="line"><span class="meta">@EnableFeignClients(basePackages = &quot;com.heima.apis&quot;)</span></span><br><span class="line"><span class="meta">@EnableAsync</span> <span class="comment">//开启异步调用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WemediaApplication</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"> SpringApplication.run(WemediaApplication.class,args);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> MybatisPlusInterceptor <span class="title function_">mybatisPlusInterceptor</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="type">MybatisPlusInterceptor</span> <span class="variable">interceptor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MybatisPlusInterceptor</span>();</span><br><span class="line"> interceptor.addInnerInterceptor(<span class="keyword">new</span> <span class="title class_">PaginationInnerInterceptor</span>(DbType.MYSQL));</span><br><span class="line"> <span class="keyword">return</span> interceptor;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="4-7-文章审核功能-综合测试"><a href="#4-7-文章审核功能-综合测试" class="headerlink" title="4.7 文章审核功能-综合测试"></a>4.7 文章审核功能-综合测试</h3><h4 id="4-7-1-服务启动列表"><a href="#4-7-1-服务启动列表" class="headerlink" title="4.7.1 服务启动列表"></a>4.7.1 服务启动列表</h4><p>1nacos服务端</p>
<p>2article微服务</p>
<p>3wemedia微服务</p>
<p>4启动wemedia网关微服务</p>
<p>5启动前端系统wemedia</p>
<h4 id="4-7-2-测试情况列表"><a href="#4-7-2-测试情况列表" class="headerlink" title="4.7.2 测试情况列表"></a>4.7.2 测试情况列表</h4><p>1自媒体前端发布一篇正常的文章</p>
<p> 审核成功后app端的article相关数据是否可以正常保存自媒体文章状态和app端文章id是否回显</p>
<p>2自媒体前端发布一篇包含敏感词的文章</p>
<p> 正常是审核失败, wm_news表中的状态是否改变成功和失败原因正常保存</p>
<p>3自媒体前端发布一篇包含敏感图片的文章</p>
<p> 正常是审核失败, wm_news表中的状态是否改变成功和失败原因正常保存</p>
<p><img src="/pictures/image-20231202235800149.png" alt="image-20231202235800149"></p>
<h3 id="4-8-自管理敏感词过滤"><a href="#4-8-自管理敏感词过滤" class="headerlink" title="4.8 自管理敏感词过滤"></a>4.8 自管理敏感词过滤</h3><h4 id="4-8-1-需求"><a href="#4-8-1-需求" class="headerlink" title="4.8.1 需求"></a>4.8.1 需求</h4><p><img src="/pictures/image-20231203000259877.png" alt="image-20231203000259877"></p>
<h4 id="4-8-2-可选方案"><a href="#4-8-2-可选方案" class="headerlink" title="4.8.2 可选方案"></a>4.8.2 可选方案</h4><table>
<thead>
<tr>
<th><strong>方案</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>数据库模糊查询</td>
<td>效率太低</td>
</tr>
<tr>
<td>String.indexOf(“”)查找</td>
<td>数据库量大的话也是比较慢</td>
</tr>
<tr>
<td>全文检索</td>
<td>分词再匹配</td>
</tr>
<tr>
<td>DFA算法</td>
<td>确定有穷自动机(一种数据结构)</td>
</tr>
</tbody></table>
<h4 id="4-8-3-DFA算法"><a href="#4-8-3-DFA算法" class="headerlink" title="4.8.3 DFA算法"></a>4.8.3 DFA算法</h4><p><img src="/pictures/image-20231203130434677.png" alt="image-20231203130434677"></p>
<p><img src="/pictures/image-20231203130929391.png" alt="image-20231203130929391"></p>
<h4 id="4-8-4-工具类"><a href="#4-8-4-工具类" class="headerlink" title="4.8.4 工具类"></a>4.8.4 工具类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.utils.common;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SensitiveWordUtil</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Map&lt;String, Object&gt; dictionaryMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 生成关键词字典库</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> words</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">initMap</span><span class="params">(Collection&lt;String&gt; words)</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (words == <span class="literal">null</span>) &#123;</span><br><span class="line"> System.out.println(<span class="string">&quot;敏感词列表不能为空&quot;</span>);</span><br><span class="line"> <span class="keyword">return</span> ;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// map初始长度words.size(),整个字典库的入口字数(小于words.size(),因为不同的词可能会有相同的首字)</span></span><br><span class="line"> Map&lt;String, Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;(words.size());</span><br><span class="line"> <span class="comment">// 遍历过程中当前层次的数据</span></span><br><span class="line"> Map&lt;String, Object&gt; curMap = <span class="literal">null</span>;</span><br><span class="line"> Iterator&lt;String&gt; iterator = words.iterator();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (iterator.hasNext()) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">word</span> <span class="operator">=</span> iterator.next();</span><br><span class="line"> curMap = map;</span><br><span class="line"> <span class="type">int</span> <span class="variable">len</span> <span class="operator">=</span> word.length();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span><span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line"> <span class="comment">// 遍历每个词的字</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> String.valueOf(word.charAt(i));</span><br><span class="line"> <span class="comment">// 当前字在当前层是否存在, 不存在则新建, 当前层数据指向下一个节点, 继续判断是否存在数据</span></span><br><span class="line"> Map&lt;String, Object&gt; wordMap = (Map&lt;String, Object&gt;) curMap.get(key);</span><br><span class="line"> <span class="keyword">if</span> (wordMap == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">// 每个节点存在两个数据: 下一个节点和isEnd(是否结束标志)</span></span><br><span class="line"> wordMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;(<span class="number">2</span>);</span><br><span class="line"> wordMap.put(<span class="string">&quot;isEnd&quot;</span>, <span class="string">&quot;0&quot;</span>);</span><br><span class="line"> curMap.put(key, wordMap);</span><br><span class="line"> &#125;</span><br><span class="line"> curMap = wordMap;</span><br><span class="line"> <span class="comment">// 如果当前字是词的最后一个字则将isEnd标志置1</span></span><br><span class="line"> <span class="keyword">if</span> (i == len -<span class="number">1</span>) &#123;</span><br><span class="line"> curMap.put(<span class="string">&quot;isEnd&quot;</span>, <span class="string">&quot;1&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> dictionaryMap = map;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 搜索文本中某个文字是否匹配关键词</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> text</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> beginIndex</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">checkWord</span><span class="params">(String text, <span class="type">int</span> beginIndex)</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (dictionaryMap == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;字典不能为空&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isEnd</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="type">int</span> <span class="variable">wordLength</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> Map&lt;String, Object&gt; curMap = dictionaryMap;</span><br><span class="line"> <span class="type">int</span> <span class="variable">len</span> <span class="operator">=</span> text.length();</span><br><span class="line"> <span class="comment">// 从文本的第beginIndex开始匹配</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> beginIndex; i &lt; len; i++) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> String.valueOf(text.charAt(i));</span><br><span class="line"> <span class="comment">// 获取当前key的下一个节点</span></span><br><span class="line"> curMap = (Map&lt;String, Object&gt;) curMap.get(key);</span><br><span class="line"> <span class="keyword">if</span> (curMap == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> wordLength ++;</span><br><span class="line"> <span class="keyword">if</span> (<span class="string">&quot;1&quot;</span>.equals(curMap.get(<span class="string">&quot;isEnd&quot;</span>))) &#123;</span><br><span class="line"> isEnd = <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!isEnd) &#123;</span><br><span class="line"> wordLength = <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> wordLength;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取匹配的关键词和命中次数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> text</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Map&lt;String, Integer&gt; <span class="title function_">matchWords</span><span class="params">(String text)</span> &#123;</span><br><span class="line"> Map&lt;String, Integer&gt; wordMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> <span class="type">int</span> <span class="variable">len</span> <span class="operator">=</span> text.length();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line"> <span class="type">int</span> <span class="variable">wordLength</span> <span class="operator">=</span> checkWord(text, i);</span><br><span class="line"> <span class="keyword">if</span> (wordLength &gt; <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="type">String</span> <span class="variable">word</span> <span class="operator">=</span> text.substring(i, i + wordLength);</span><br><span class="line"> <span class="comment">// 添加关键词匹配次数</span></span><br><span class="line"> <span class="keyword">if</span> (wordMap.containsKey(word)) &#123;</span><br><span class="line"> wordMap.put(word, wordMap.get(word) + <span class="number">1</span>);</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> wordMap.put(word, <span class="number">1</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> i += wordLength - <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> wordMap;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//测试工具类</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"> List&lt;String&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"> list.add(<span class="string">&quot;法轮&quot;</span>);</span><br><span class="line"> list.add(<span class="string">&quot;法轮功&quot;</span>);</span><br><span class="line"> list.add(<span class="string">&quot;冰毒&quot;</span>);</span><br><span class="line"> <span class="comment">//初始hua敏感词库</span></span><br><span class="line"> initMap(list);</span><br><span class="line"> String content=<span class="string">&quot;我是一个好人,并不会卖冰毒,也不操练法轮功,我真的不卖冰毒&quot;</span>;</span><br><span class="line"> Map&lt;String, Integer&gt; map = matchWords(content);</span><br><span class="line"> System.out.println(map);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="4-8-5-项目中集成自管理敏感词过滤"><a href="#4-8-5-项目中集成自管理敏感词过滤" class="headerlink" title="4.8.5 项目中集成自管理敏感词过滤"></a>4.8.5 项目中集成自管理敏感词过滤</h4><p>创建敏感词表导入资料中wm_sensitive到leadnews_wemedia库中并创建对应的实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.model.wemedia.pojos;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 敏感词信息表</span></span><br><span class="line"><span class="comment"> * &lt;/p&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itheima</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@TableName(&quot;wm_sensitive&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmSensitive</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 主键</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableId(value = &quot;id&quot;, type = IdType.AUTO)</span></span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 敏感词</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;sensitives&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String sensitives;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建时间</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@TableField(&quot;created_time&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> Date createdTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>拷贝对应的wm_sensitive的mapper到项目中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.mapper;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.mapper.BaseMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmSensitive;</span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.annotations.Mapper;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@Mapper</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">WmSensitiveMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span>&lt;WmSensitive&gt; &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>③:在文章审核的代码中添加自管理敏感词审核</p>
<p>第一在WmNewsAutoScanServiceImpl中的autoScanWmNews方法上添加如下代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//从内容中提取纯文本内容和图片</span></span><br><span class="line"><span class="comment">//.....省略</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//自管理的敏感词过滤</span></span><br><span class="line"><span class="type">boolean</span> <span class="variable">isSensitive</span> <span class="operator">=</span> handleSensitiveScan((String) textAndImages.get(<span class="string">&quot;content&quot;</span>), wmNews);</span><br><span class="line"><span class="keyword">if</span>(!isSensitive) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//2.审核文本内容 阿里云接口</span></span><br><span class="line"><span class="comment">//.....省略</span></span><br></pre></td></tr></table></figure>
<p>新增自管理敏感词审核代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> WmSensitiveMapper wmSensitiveMapper;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自管理的敏感词审核</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">handleSensitiveScan</span><span class="params">(String content, WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取所有的敏感词</span></span><br><span class="line"> List&lt;WmSensitive&gt; wmSensitives = wmSensitiveMapper.selectList(Wrappers.&lt;WmSensitive&gt;lambdaQuery().select(WmSensitive::getSensitives));</span><br><span class="line"> List&lt;String&gt; sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//初始化敏感词库</span></span><br><span class="line"> SensitiveWordUtil.initMap(sensitiveList);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查看文章中是否包含敏感词</span></span><br><span class="line"> Map&lt;String, Integer&gt; map = SensitiveWordUtil.matchWords(content);</span><br><span class="line"> <span class="keyword">if</span>(map.size() &gt;<span class="number">0</span>)&#123;</span><br><span class="line"> updateWmNews(wmNews,(<span class="type">short</span>) <span class="number">2</span>,<span class="string">&quot;当前文章中存在违规内容&quot;</span>+map);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img src="/pictures/image-20231203161902523.png" alt="image-20231203161902523"></p>
<h3 id="4-9-图片识别文字审核敏感词"><a href="#4-9-图片识别文字审核敏感词" class="headerlink" title="4.9 图片识别文字审核敏感词"></a>4.9 图片识别文字审核敏感词</h3><p>详细教程: <a href="https://qingling.icu/posts/58456.html">https://qingling.icu/posts/58456.html</a></p>
<p>在heima-leadnews-common中创建工具类简单封装一下tess4j</p>
<p>需要先导入pom</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.sourceforge.tess4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>tess4j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>工具类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.common.tess4j;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.Getter;</span><br><span class="line"><span class="keyword">import</span> lombok.Setter;</span><br><span class="line"><span class="keyword">import</span> net.sourceforge.tess4j.ITesseract;</span><br><span class="line"><span class="keyword">import</span> net.sourceforge.tess4j.Tesseract;</span><br><span class="line"><span class="keyword">import</span> net.sourceforge.tess4j.TesseractException;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.awt.image.BufferedImage;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@Setter</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;tess4j&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Tess4jClient</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String dataPath;</span><br><span class="line"> <span class="keyword">private</span> String language;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">doOCR</span><span class="params">(BufferedImage image)</span> <span class="keyword">throws</span> TesseractException &#123;</span><br><span class="line"> <span class="comment">//创建Tesseract对象</span></span><br><span class="line"> <span class="type">ITesseract</span> <span class="variable">tesseract</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Tesseract</span>();</span><br><span class="line"> <span class="comment">//设置字体库路径</span></span><br><span class="line"> tesseract.setDatapath(dataPath);</span><br><span class="line"> <span class="comment">//中文识别</span></span><br><span class="line"> tesseract.setLanguage(language);</span><br><span class="line"> <span class="comment">//执行ocr识别</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> tesseract.doOCR(image);</span><br><span class="line"> <span class="comment">//替换回车和tal键 使结果为一行</span></span><br><span class="line"> result = result.replaceAll(<span class="string">&quot;\\r|\\n&quot;</span>, <span class="string">&quot;-&quot;</span>).replaceAll(<span class="string">&quot; &quot;</span>, <span class="string">&quot;&quot;</span>);</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在spring.factories配置中添加该类,完整如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">org.springframework.boot.autoconfigure.EnableAutoConfiguration=\</span><br><span class="line"> com.heima.common.exception.ExceptionCatch,\</span><br><span class="line"> com.heima.common.swagger.SwaggerConfiguration,\</span><br><span class="line"> com.heima.common.swagger.Swagger2Configuration,\</span><br><span class="line"> com.heima.common.aliyun.GreenTextScan,\</span><br><span class="line"> com.heima.common.aliyun.GreenImageScan,\</span><br><span class="line"> com.heima.common.tess4j.Tess4jClient</span><br></pre></td></tr></table></figure>
<p>在heima-leadnews-wemedia中的配置中添加两个属性</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">tess4j:</span></span><br><span class="line"> <span class="attr">data-path:</span> <span class="string">D:\workspace\tessdata</span></span><br><span class="line"> <span class="attr">language:</span> <span class="string">chi_sim</span></span><br></pre></td></tr></table></figure>
<p>在WmNewsAutoScanServiceImpl中的handleImageScan方法上添加如下代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">for</span> (String image : images) &#123;</span><br><span class="line"> <span class="type">byte</span>[] bytes = fileStorageService.downLoadFile(image);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//图片识别文字审核---begin-----</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//从byte[]转换为butteredImage</span></span><br><span class="line"> <span class="type">ByteArrayInputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(bytes);</span><br><span class="line"> <span class="type">BufferedImage</span> <span class="variable">imageFile</span> <span class="operator">=</span> ImageIO.read(in);</span><br><span class="line"> <span class="comment">//识别图片的文字</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> tess4jClient.doOCR(imageFile);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//审核是否包含自管理的敏感词</span></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isSensitive</span> <span class="operator">=</span> handleSensitiveScan(result, wmNews);</span><br><span class="line"> <span class="keyword">if</span>(!isSensitive)&#123;</span><br><span class="line"> <span class="keyword">return</span> isSensitive;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//图片识别文字审核---end-----</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> imageList.add(bytes);</span><br><span class="line"></span><br><span class="line"> &#125; </span><br><span class="line">&#125;<span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>最后附上文章审核的完整代码如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.wemedia.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONArray;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.toolkit.Wrappers;</span><br><span class="line"><span class="keyword">import</span> com.heima.apis.article.IArticleClient;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenImageScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.aliyun.GreenTextScan;</span><br><span class="line"><span class="keyword">import</span> com.heima.common.tess4j.Tess4jClient;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.dtos.ArticleDto;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.common.dtos.ResponseResult;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmChannel;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmNews;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmSensitive;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.wemedia.pojos.WmUser;</span><br><span class="line"><span class="keyword">import</span> com.heima.utils.common.SensitiveWordUtil;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmChannelMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmNewsMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmSensitiveMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.mapper.WmUserMapper;</span><br><span class="line"><span class="keyword">import</span> com.heima.wemedia.service.WmNewsAutoScanService;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.BeanUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.scheduling.annotation.Async;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.imageio.ImageIO;</span><br><span class="line"><span class="keyword">import</span> java.awt.image.BufferedImage;</span><br><span class="line"><span class="keyword">import</span> java.io.ByteArrayInputStream;</span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"><span class="keyword">import</span> java.util.stream.Collectors;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WmNewsAutoScanServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">WmNewsAutoScanService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmNewsMapper wmNewsMapper;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自媒体文章审核</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> id 自媒体文章id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@Async</span> <span class="comment">//标明当前方法是一个异步方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">autoScanWmNews</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">// int a = 1/0;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//1.查询自媒体文章</span></span><br><span class="line"> <span class="type">WmNews</span> <span class="variable">wmNews</span> <span class="operator">=</span> wmNewsMapper.selectById(id);</span><br><span class="line"> <span class="keyword">if</span> (wmNews == <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;WmNewsAutoScanServiceImpl-文章不存在&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) &#123;</span><br><span class="line"> <span class="comment">//从内容中提取纯文本内容和图片</span></span><br><span class="line"> Map&lt;String, Object&gt; textAndImages = handleTextAndImages(wmNews);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//自管理的敏感词过滤</span></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isSensitive</span> <span class="operator">=</span> handleSensitiveScan((String) textAndImages.get(<span class="string">&quot;content&quot;</span>), wmNews);</span><br><span class="line"> <span class="keyword">if</span>(!isSensitive) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.审核文本内容 阿里云接口</span></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isTextScan</span> <span class="operator">=</span> handleTextScan((String) textAndImages.get(<span class="string">&quot;content&quot;</span>), wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!isTextScan) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//3.审核图片 阿里云接口</span></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isImageScan</span> <span class="operator">=</span> handleImageScan((List&lt;String&gt;) textAndImages.get(<span class="string">&quot;images&quot;</span>), wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!isImageScan) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//4.审核成功保存app端的相关的文章数据</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> saveAppArticle(wmNews);</span><br><span class="line"> <span class="keyword">if</span> (!responseResult.getCode().equals(<span class="number">200</span>)) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;WmNewsAutoScanServiceImpl-文章审核保存app端相关文章数据失败&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//回填article_id</span></span><br><span class="line"> wmNews.setArticleId((Long) responseResult.getData());</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">9</span>, <span class="string">&quot;审核成功&quot;</span>);</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmSensitiveMapper wmSensitiveMapper;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自管理的敏感词审核</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">handleSensitiveScan</span><span class="params">(String content, WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取所有的敏感词</span></span><br><span class="line"> List&lt;WmSensitive&gt; wmSensitives = wmSensitiveMapper.selectList(Wrappers.&lt;WmSensitive&gt;lambdaQuery().select(WmSensitive::getSensitives));</span><br><span class="line"> List&lt;String&gt; sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//初始化敏感词库</span></span><br><span class="line"> SensitiveWordUtil.initMap(sensitiveList);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查看文章中是否包含敏感词</span></span><br><span class="line"> Map&lt;String, Integer&gt; map = SensitiveWordUtil.matchWords(content);</span><br><span class="line"> <span class="keyword">if</span>(map.size() &gt;<span class="number">0</span>)&#123;</span><br><span class="line"> updateWmNews(wmNews,(<span class="type">short</span>) <span class="number">2</span>,<span class="string">&quot;当前文章中存在违规内容&quot;</span>+map);</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> IArticleClient articleClient;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmChannelMapper wmChannelMapper;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> WmUserMapper wmUserMapper;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存app端相关的文章数据</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> ResponseResult <span class="title function_">saveAppArticle</span><span class="params">(WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="type">ArticleDto</span> <span class="variable">dto</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArticleDto</span>();</span><br><span class="line"> <span class="comment">//属性的拷贝</span></span><br><span class="line"> BeanUtils.copyProperties(wmNews, dto);</span><br><span class="line"> <span class="comment">//文章的布局</span></span><br><span class="line"> dto.setLayout(wmNews.getType());</span><br><span class="line"> <span class="comment">//频道</span></span><br><span class="line"> <span class="type">WmChannel</span> <span class="variable">wmChannel</span> <span class="operator">=</span> wmChannelMapper.selectById(wmNews.getChannelId());</span><br><span class="line"> <span class="keyword">if</span> (wmChannel != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setChannelName(wmChannel.getName());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//作者</span></span><br><span class="line"> dto.setAuthorId(wmNews.getUserId().longValue());</span><br><span class="line"> <span class="type">WmUser</span> <span class="variable">wmUser</span> <span class="operator">=</span> wmUserMapper.selectById(wmNews.getUserId());</span><br><span class="line"> <span class="keyword">if</span> (wmUser != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setAuthorName(wmUser.getName());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//设置文章id</span></span><br><span class="line"> <span class="keyword">if</span> (wmNews.getArticleId() != <span class="literal">null</span>) &#123;</span><br><span class="line"> dto.setId(wmNews.getArticleId());</span><br><span class="line"> &#125;</span><br><span class="line"> dto.setCreatedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">responseResult</span> <span class="operator">=</span> articleClient.saveArticle(dto);</span><br><span class="line"> <span class="keyword">return</span> responseResult;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenImageScan greenImageScan;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> Tess4jClient tess4jClient;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 审核图片</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> images</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">handleImageScan</span><span class="params">(List&lt;String&gt; images, WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (images == <span class="literal">null</span> || images.size() == <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//下载图片 minIO</span></span><br><span class="line"> <span class="comment">//图片去重</span></span><br><span class="line"> images = images.stream().distinct().collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line"> List&lt;<span class="type">byte</span>[]&gt; imageList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">for</span> (String image : images) &#123;</span><br><span class="line"> <span class="type">byte</span>[] bytes = fileStorageService.downLoadFile(image);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//图片识别文字审核---begin-----</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//从byte[]转换为butteredImage</span></span><br><span class="line"> <span class="type">ByteArrayInputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(bytes);</span><br><span class="line"> <span class="type">BufferedImage</span> <span class="variable">imageFile</span> <span class="operator">=</span> ImageIO.read(in);</span><br><span class="line"> <span class="comment">//识别图片的文字</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> tess4jClient.doOCR(imageFile);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//审核是否包含自管理的敏感词</span></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isSensitive</span> <span class="operator">=</span> handleSensitiveScan(result, wmNews);</span><br><span class="line"> <span class="keyword">if</span>(!isSensitive)&#123;</span><br><span class="line"> <span class="keyword">return</span> isSensitive;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//图片识别文字审核---end-----</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> imageList.add(bytes);</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;<span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//审核图片</span></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenImageScan.imageScan(imageList);</span><br><span class="line"> <span class="keyword">if</span> (map != <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//审核失败</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;block&quot;</span>)) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">2</span>, <span class="string">&quot;当前文章中存在违规内容&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//不确定信息 需要人工审核</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;review&quot;</span>)) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">3</span>, <span class="string">&quot;当前文章中存在不确定内容&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> GreenTextScan greenTextScan;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 审核纯文本内容</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">handleTextScan</span><span class="params">(String content, WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ((wmNews.getTitle() + <span class="string">&quot;-&quot;</span> + content).length() == <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> greenTextScan.greeTextScan((wmNews.getTitle() + <span class="string">&quot;-&quot;</span> + content));</span><br><span class="line"> <span class="keyword">if</span> (map != <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//审核失败</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;block&quot;</span>)) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">2</span>, <span class="string">&quot;当前文章中存在违规内容&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//不确定信息 需要人工审核</span></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;suggestion&quot;</span>).equals(<span class="string">&quot;review&quot;</span>)) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> updateWmNews(wmNews, (<span class="type">short</span>) <span class="number">3</span>, <span class="string">&quot;当前文章中存在不确定内容&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> flag = <span class="literal">false</span>;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> flag;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 修改文章内容</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> status</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> reason</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">updateWmNews</span><span class="params">(WmNews wmNews, <span class="type">short</span> status, String reason)</span> &#123;</span><br><span class="line"> wmNews.setStatus(status);</span><br><span class="line"> wmNews.setReason(reason);</span><br><span class="line"> wmNewsMapper.updateById(wmNews);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1。从自媒体文章的内容中提取文本和图片</span></span><br><span class="line"><span class="comment"> * 2.提取文章的封面图片</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> wmNews</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Map&lt;String, Object&gt; <span class="title function_">handleTextAndImages</span><span class="params">(WmNews wmNews)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//存储纯文本内容</span></span><br><span class="line"> <span class="type">StringBuilder</span> <span class="variable">stringBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line"></span><br><span class="line"> List&lt;String&gt; images = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//1。从自媒体文章的内容中提取文本和图片</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(wmNews.getContent())) &#123;</span><br><span class="line"> List&lt;Map&gt; maps = JSONArray.parseArray(wmNews.getContent(), Map.class);</span><br><span class="line"> <span class="keyword">for</span> (Map map : maps) &#123;</span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;type&quot;</span>).equals(<span class="string">&quot;text&quot;</span>)) &#123;</span><br><span class="line"> stringBuilder.append(map.get(<span class="string">&quot;value&quot;</span>));</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (map.get(<span class="string">&quot;type&quot;</span>).equals(<span class="string">&quot;image&quot;</span>)) &#123;</span><br><span class="line"> images.add((String) map.get(<span class="string">&quot;value&quot;</span>));</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//2.提取文章的封面图片</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(wmNews.getImages())) &#123;</span><br><span class="line"> String[] split = wmNews.getImages().split(<span class="string">&quot;,&quot;</span>);</span><br><span class="line"> images.addAll(Arrays.asList(split));</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> Map&lt;String, Object&gt; resultMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> resultMap.put(<span class="string">&quot;content&quot;</span>, stringBuilder.toString());</span><br><span class="line"> resultMap.put(<span class="string">&quot;images&quot;</span>, images);</span><br><span class="line"> <span class="keyword">return</span> resultMap;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="4-10-文章详情-静态文件生成"><a href="#4-10-文章详情-静态文件生成" class="headerlink" title="4.10 文章详情-静态文件生成"></a>4.10 文章详情-静态文件生成</h3><p><img src="/pictures/image-20231209210352188.png" alt="image-20231209210352188"></p>
<p><strong>实现步骤</strong></p>
<p>1.新建ArticleFreemarkerService 定义创建静态文件并上传到minIO中方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticle;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ArticleFreemarkerService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 生成静态文件上传到minIO中</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> apArticle</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> content</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildArticleToMinIO</span><span class="params">(ApArticle apArticle,String content)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article.service.Impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONArray;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ApArticleService;</span><br><span class="line"><span class="keyword">import</span> com.heima.article.service.ArticleFreemarkerService;</span><br><span class="line"><span class="keyword">import</span> com.heima.file.service.FileStorageService;</span><br><span class="line"><span class="keyword">import</span> com.heima.model.article.pojos.ApArticle;</span><br><span class="line"><span class="keyword">import</span> freemarker.template.Configuration;</span><br><span class="line"><span class="keyword">import</span> freemarker.template.Template;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.scheduling.annotation.Async;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.ByteArrayInputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.StringWriter;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Jason Gong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/12/9</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleFreemarkerServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">ArticleFreemarkerService</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> Configuration configuration;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> FileStorageService fileStorageService;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> ApArticleService apArticleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Async</span> <span class="comment">//标记为一个异步调用的方法</span></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildArticleToMinio</span><span class="params">(ApArticle apArticle, String content)</span> &#123;</span><br><span class="line"> <span class="comment">//已知文章的id</span></span><br><span class="line"> <span class="comment">//1.获取文章的内容</span></span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(content)) &#123;</span><br><span class="line"> <span class="type">StringWriter</span> <span class="variable">out</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringWriter</span>();</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="comment">//2.文章内容通过freemarker生成html文件 详细教程见:https://qingling.icu/posts/29367.html</span></span><br><span class="line"> <span class="type">Template</span> <span class="variable">template</span> <span class="operator">=</span> configuration.getTemplate(<span class="string">&quot;article.ftl&quot;</span>);</span><br><span class="line"> <span class="comment">//构建数据模型</span></span><br><span class="line"> HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;content&quot;</span>, JSONArray.parseArray(content));</span><br><span class="line"> <span class="comment">//输出流</span></span><br><span class="line"> out = <span class="keyword">new</span> <span class="title class_">StringWriter</span>();</span><br><span class="line"> <span class="comment">//合成html文件</span></span><br><span class="line"> template.process(map, out);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//3.把html文件上传到minio中</span></span><br><span class="line"> <span class="comment">//构建一个输入流</span></span><br><span class="line"> <span class="type">InputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(out.toString().getBytes());</span><br><span class="line"> <span class="comment">//上传到minio并返回访问的路径</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> fileStorageService.uploadHtmlFile(<span class="string">&quot;&quot;</span>, apArticle.getId() + <span class="string">&quot;.html&quot;</span>, in);</span><br><span class="line"> log.info(<span class="string">&quot;文件在minio中的路径:&quot;</span> + path);</span><br><span class="line"> <span class="comment">//4.修改ap_article表保存static_url字段</span></span><br><span class="line"> apArticle.setStaticUrl(path);</span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isSuccess</span> <span class="operator">=</span> apArticleService.updateById(apArticle);</span><br><span class="line"> log.info(isSuccess ? <span class="string">&quot;文件上传成功&quot;</span> : <span class="string">&quot;文件上传失败&quot;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.在ApArticleService的saveArticle实现方法中添加调用生成文件的方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存app端相关文章</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> dto</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">saveArticle</span><span class="params">(ArticleDto dto)</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// try &#123;</span></span><br><span class="line"> <span class="comment">// Thread.sleep(3000);</span></span><br><span class="line"> <span class="comment">// &#125; catch (InterruptedException e) &#123;</span></span><br><span class="line"> <span class="comment">// e.printStackTrace();</span></span><br><span class="line"> <span class="comment">// &#125;</span></span><br><span class="line"> <span class="comment">//1.检查参数</span></span><br><span class="line"> <span class="keyword">if</span>(dto == <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="type">ApArticle</span> <span class="variable">apArticle</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticle</span>();</span><br><span class="line"> BeanUtils.copyProperties(dto,apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//2.判断是否存在id</span></span><br><span class="line"> <span class="keyword">if</span>(dto.getId() == <span class="literal">null</span>)&#123;</span><br><span class="line"> <span class="comment">//2.1 不存在id 保存 文章 文章配置 文章内容</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存文章</span></span><br><span class="line"> save(apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存配置</span></span><br><span class="line"> <span class="type">ApArticleConfig</span> <span class="variable">apArticleConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticleConfig</span>(apArticle.getId());</span><br><span class="line"> apArticleConfigMapper.insert(apArticleConfig);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//保存 文章内容</span></span><br><span class="line"> <span class="type">ApArticleContent</span> <span class="variable">apArticleContent</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ApArticleContent</span>();</span><br><span class="line"> apArticleContent.setArticleId(apArticle.getId());</span><br><span class="line"> apArticleContent.setContent(dto.getContent());</span><br><span class="line"> apArticleContentMapper.insert(apArticleContent);</span><br><span class="line"></span><br><span class="line"> &#125;<span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//2.2 存在id 修改 文章 文章内容</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//修改 文章</span></span><br><span class="line"> updateById(apArticle);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//修改文章内容</span></span><br><span class="line"> <span class="type">ApArticleContent</span> <span class="variable">apArticleContent</span> <span class="operator">=</span> apArticleContentMapper.selectOne(Wrappers.&lt;ApArticleContent&gt;lambdaQuery().eq(ApArticleContent::getArticleId, dto.getId()));</span><br><span class="line"> apArticleContent.setContent(dto.getContent());</span><br><span class="line"> apArticleContentMapper.updateById(apArticleContent);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//异步调用 生成静态文件上传到minio中</span></span><br><span class="line"> articleFreemarkerService.buildArticleToMinIO(apArticle,dto.getContent());</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//3.结果返回 文章的id</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(apArticle.getId());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3.文章微服务开启异步调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.heima.article;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.DbType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;</span><br><span class="line"><span class="keyword">import</span> org.mybatis.spring.annotation.MapperScan;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.client.discovery.EnableDiscoveryClient;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.scheduling.annotation.EnableAsync;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@EnableDiscoveryClient</span></span><br><span class="line"><span class="meta">@EnableAsync</span> <span class="comment">//开启异步调用</span></span><br><span class="line"><span class="meta">@MapperScan(&quot;com.heima.article.mapper&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleApplication</span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"> SpringApplication.run(ArticleApplication.class,args);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> MybatisPlusInterceptor <span class="title function_">mybatisPlusInterceptor</span><span class="params">()</span> &#123;</span><br><span class="line"> <span class="type">MybatisPlusInterceptor</span> <span class="variable">interceptor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MybatisPlusInterceptor</span>();</span><br><span class="line"> interceptor.addInnerInterceptor(<span class="keyword">new</span> <span class="title class_">PaginationInnerInterceptor</span>(DbType.MYSQL));</span><br><span class="line"> <span class="keyword">return</span> interceptor;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>测试</strong></p>
<p><img src="/pictures/image-20231209214205338.png" alt="image-20231209214205338"></p>
<p><img src="/pictures/image-20231209214309957.png" alt="image-20231209214309957"></p>
<h3 id="4-11-文章定时发布"><a href="#4-11-文章定时发布" class="headerlink" title="4.11 文章定时发布"></a>4.11 文章定时发布</h3></article><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/">项目实战</a></div><div class="post_share"><div class="social-share" data-image="/img/4.png" data-sites="wechat,weibo,qq"></div><link rel="stylesheet" href="/cdn/css/share.min.css" media="print" onload="this.media='all'"><script src="/cdn/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.jpg" target="_blank"><img class="post-qr-code-img" src="/img/wechat.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" src="/img/alipay.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><br/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="far fa-comment-alt fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="gitalk-container"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/loading.gif'" alt="avatar"/></div><div class="author-info__name">Jason</div><div class="author-info__description">Debug the World</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">60</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">39</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">10</div></a></div><a id="card-info-btn"><i class="fab fa-microsoft"></i><span>Ctrl + D 收藏</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/JasonsGong" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="tencent://AddContact/?fromId=45&amp;fromSubId=1&amp;subcmd=all&amp;uin=2602183349&amp;website=www.oicqzone.com" target="_blank" title="QQ"><i class="fab fa-qq"></i></a><a class="social-icon" href="mailto:2602183349@qq.com" target="_blank" title="Email"><i class="fas fa-envelope-open-text"></i></a><a class="social-icon" href="https://github.com/JasonsGong?tab=repositories" target="_blank" title="代码仓库"><i class="fas fa-database"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">本网站是静态网站,更新页面资源请使用Ctrl+F5;若网站内文章对你有帮助,请使用Ctrl+D收藏该网站</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80-%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D"><span class="toc-text">一.项目介绍</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%BF%B0"><span class="toc-text">1.项目概述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E4%B8%9A%E5%8A%A1%E8%AF%B4%E6%98%8E"><span class="toc-text">2.业务说明</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E6%8A%80%E6%9C%AF%E6%A0%88"><span class="toc-text">3.技术栈</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%8C-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="toc-text">二.环境搭建</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-Linxu%E7%8E%AF%E5%A2%83%E7%9A%84%E6%90%AD%E5%BB%BA"><span class="toc-text">1.Linxu环境的搭建</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1-%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%9A%84%E5%AE%89%E8%A3%85"><span class="toc-text">1.1 虚拟机的安装</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2-Linux%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85"><span class="toc-text">1.2 Linux软件安装</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E7%9A%84%E9%85%8D%E7%BD%AE"><span class="toc-text">2.开发环境的配置</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E9%A1%B9%E7%9B%AE%E4%BE%9D%E8%B5%96%E7%9A%84%E7%8E%AF%E5%A2%83"><span class="toc-text">2.1 项目依赖的环境</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E7%9A%84%E6%90%AD%E5%BB%BA"><span class="toc-text">2.2 后端工程的搭建</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%89-app%E7%AB%AF%E5%8A%9F%E8%83%BD%E5%BC%80%E5%8F%91"><span class="toc-text">三.app端功能开发</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-app%E7%99%BB%E5%BD%95"><span class="toc-text">1.app登录</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1-%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E9%80%BB%E8%BE%91"><span class="toc-text">1.1 用户登录逻辑</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2-%E7%94%A8%E6%88%B7%E6%A8%A1%E5%9D%97%E6%90%AD%E5%BB%BA"><span class="toc-text">1.2 用户模块搭建</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-3-%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0"><span class="toc-text">1.3 登录功能实现</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-1-%E6%8E%A5%E5%8F%A3%E5%AE%9A%E4%B9%89"><span class="toc-text">1.3.1 接口定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-2-%E7%99%BB%E5%BD%95%E6%80%9D%E8%B7%AF%E5%88%86%E6%9E%90"><span class="toc-text">1.3.2 登录思路分析</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-3-%E7%99%BB%E5%BD%95%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="toc-text">1.3.3 登录关键代码实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-4-%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3%E5%B7%A5%E5%85%B7%E6%B5%8B%E8%AF%95"><span class="toc-text">1.3.4 使用接口工具测试</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-app%E7%AB%AF%E7%BD%91%E5%85%B3%E6%90%AD%E5%BB%BA"><span class="toc-text">2. app端网关搭建</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E6%90%AD%E5%BB%BA%E8%BF%87%E7%A8%8B"><span class="toc-text">2.1 搭建过程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-%E5%85%A8%E5%B1%80%E8%BF%87%E6%BB%A4%E5%99%A8%E5%AE%9E%E7%8E%B0jwt%E6%A0%A1%E9%AA%8C"><span class="toc-text">2.2 全局过滤器实现jwt校验</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-app%E5%89%8D%E7%AB%AF%E9%A1%B9%E7%9B%AE%E9%9B%86%E6%88%90"><span class="toc-text">3.app前端项目集成</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-Nginx%E9%9B%86%E6%88%90%E5%89%8D%E7%AB%AF%E9%A1%B9%E7%9B%AE%E6%AD%A5%E9%AA%A4"><span class="toc-text">3.1 Nginx集成前端项目步骤</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-app%E7%AB%AF%E6%96%87%E7%AB%A0%E5%88%97%E8%A1%A8%E5%8A%9F%E8%83%BD"><span class="toc-text">4.app端文章列表功能</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A1%A8%E7%9A%84%E5%88%9B%E5%BB%BA"><span class="toc-text">4.1 数据库表的创建</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-%E6%96%87%E7%AB%A0%E6%A8%A1%E5%9D%97%E6%90%AD%E5%BB%BA"><span class="toc-text">4.2 文章模块搭建</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-3-%E9%A6%96%E9%A1%B5%E6%96%87%E7%AB%A0%E7%9A%84%E5%88%97%E8%A1%A8%E6%98%BE%E7%A4%BA"><span class="toc-text">4.3 首页文章的列表显示</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-1-%E6%8E%A5%E5%8F%A3%E5%AE%9A%E4%B9%89"><span class="toc-text">4.2.1 接口定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-2-%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF"><span class="toc-text">4.2.2 实现思路</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-3-%E5%8A%9F%E8%83%BD%E7%9A%84%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="toc-text">4.2.3 功能的关键代码实现</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-app%E7%AB%AF%E6%96%87%E7%AB%A0%E8%AF%A6%E6%83%85%E5%8A%9F%E8%83%BD"><span class="toc-text">5. app端文章详情功能</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-1-%E9%9C%80%E6%B1%82%E5%88%86%E6%9E%90"><span class="toc-text">5.1 需求分析</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-2-%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%A1%88-%E9%9D%99%E6%80%81%E6%A8%A1%E6%9D%BF%E5%B1%95%E7%A4%BA"><span class="toc-text">5.2 实现方案-静态模板展示</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-3-%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1MinIO"><span class="toc-text">5.3 对象存储服务MinIO</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-4-%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF%E4%BB%A5%E5%8F%8A%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="toc-text">5.4 实现思路以及代码实现</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%9B%9B-%E8%87%AA%E5%AA%92%E4%BD%93%E7%AB%AF%E5%8A%9F%E8%83%BD%E5%BC%80%E5%8F%91"><span class="toc-text">四.自媒体端功能开发</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E5%90%8E%E7%AB%AF%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="toc-text">1.后端环境搭建</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%89%8D%E7%AB%AF%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="toc-text">2.前端环境搭建</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E8%87%AA%E5%AA%92%E4%BD%93%E7%B4%A0%E6%9D%90%E7%AE%A1%E7%90%86%E5%8A%9F%E8%83%BD"><span class="toc-text">3.自媒体素材管理功能</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-%E7%B4%A0%E6%9D%90%E7%AE%A1%E7%90%86-%E5%9B%BE%E7%89%87%E4%B8%8A%E4%BC%A0"><span class="toc-text">3.1 素材管理-图片上传</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-1-%E8%A7%A3%E5%86%B3%E5%9B%BE%E7%89%87%E7%B4%A0%E6%9D%90%E5%AE%9E%E4%BD%93%E7%B1%BB%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%9B%BE%E7%89%87userId%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">3.1.1 解决图片素材实体类中获取图片userId的问题</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-2-%E5%9B%BE%E7%89%87%E4%B8%8A%E4%BC%A0%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%9A%E4%B9%89"><span class="toc-text">3.1.2 图片上传接口的定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-3-%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="toc-text">3.1.3 代码实现</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2-%E7%B4%A0%E6%9D%90%E7%AE%A1%E7%90%86-%E5%9B%BE%E7%89%87%E5%88%97%E8%A1%A8"><span class="toc-text">3.2 素材管理-图片列表</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-%E8%87%AA%E5%AA%92%E4%BD%93%E6%96%87%E7%AB%A0%E7%AE%A1%E7%90%86%E5%8A%9F%E8%83%BD"><span class="toc-text">4.自媒体文章管理功能</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8%E6%9F%A5%E8%AF%A2"><span class="toc-text">4.1 频道列表查询</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-%E6%96%87%E7%AB%A0%E5%88%97%E8%A1%A8%E5%8A%A0%E8%BD%BD"><span class="toc-text">4.2 文章列表加载</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-3-%E5%8F%91%E5%B8%83%E6%96%87%E7%AB%A0%E5%8A%9F%E8%83%BD-%E6%A0%B8%E5%BF%83%E5%8A%9F%E8%83%BD"><span class="toc-text">4.3 发布文章功能(核心功能)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-4-%E6%96%87%E7%AB%A0%E7%9A%84%E5%AE%A1%E6%A0%B8%E5%8A%9F%E8%83%BD-%E6%9C%AA%E5%AE%9E%E7%8E%B0"><span class="toc-text">4.4 文章的审核功能(未实现)</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-4-1-%E6%96%87%E7%AB%A0%E5%AE%A1%E6%A0%B8%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D"><span class="toc-text">4.4.1 文章审核功能介绍</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-4-2-%E8%B0%83%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9%E7%9A%84%E5%AE%A1%E6%A0%B8%E6%8E%A5%E5%8F%A3"><span class="toc-text">4.4.2 调用第三方的审核接口</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-4-3-%E5%88%86%E5%B8%83%E5%BC%8FID%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="toc-text">4.4.3 分布式ID的实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-4-4-%E5%AE%A1%E6%A0%B8%E5%8A%9F%E8%83%BD%E7%9A%84%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0"><span class="toc-text">4.4.4 审核功能的具体实现</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-5-app%E7%AB%AF%E6%96%87%E7%AB%A0%E4%BF%9D%E5%AD%98%E5%8A%9F%E8%83%BD"><span class="toc-text">4.5 app端文章保存功能</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-6-%E5%8F%91%E5%B8%83%E6%96%87%E7%AB%A0%E6%8F%90%E4%BA%A4%E5%AE%A1%E6%A0%B8%E9%9B%86%E6%88%90"><span class="toc-text">4.6 发布文章提交审核集成</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-6-1-%E5%90%8C%E6%AD%A5%E8%B0%83%E7%94%A8%E4%B8%8E%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8"><span class="toc-text">4.6.1 同步调用与异步调用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-6-2-Springboot%E9%9B%86%E6%88%90%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%B0%83%E7%94%A8"><span class="toc-text">4.6.2 Springboot集成异步线程调用</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-7-%E6%96%87%E7%AB%A0%E5%AE%A1%E6%A0%B8%E5%8A%9F%E8%83%BD-%E7%BB%BC%E5%90%88%E6%B5%8B%E8%AF%95"><span class="toc-text">4.7 文章审核功能-综合测试</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-7-1-%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E5%88%97%E8%A1%A8"><span class="toc-text">4.7.1 服务启动列表</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-7-2-%E6%B5%8B%E8%AF%95%E6%83%85%E5%86%B5%E5%88%97%E8%A1%A8"><span class="toc-text">4.7.2 测试情况列表</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-8-%E8%87%AA%E7%AE%A1%E7%90%86%E6%95%8F%E6%84%9F%E8%AF%8D%E8%BF%87%E6%BB%A4"><span class="toc-text">4.8 自管理敏感词过滤</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-8-1-%E9%9C%80%E6%B1%82"><span class="toc-text">4.8.1 需求</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-8-2-%E5%8F%AF%E9%80%89%E6%96%B9%E6%A1%88"><span class="toc-text">4.8.2 可选方案</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-8-3-DFA%E7%AE%97%E6%B3%95"><span class="toc-text">4.8.3 DFA算法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-8-4-%E5%B7%A5%E5%85%B7%E7%B1%BB"><span class="toc-text">4.8.4 工具类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-8-5-%E9%A1%B9%E7%9B%AE%E4%B8%AD%E9%9B%86%E6%88%90%E8%87%AA%E7%AE%A1%E7%90%86%E6%95%8F%E6%84%9F%E8%AF%8D%E8%BF%87%E6%BB%A4"><span class="toc-text">4.8.5 项目中集成自管理敏感词过滤</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-9-%E5%9B%BE%E7%89%87%E8%AF%86%E5%88%AB%E6%96%87%E5%AD%97%E5%AE%A1%E6%A0%B8%E6%95%8F%E6%84%9F%E8%AF%8D"><span class="toc-text">4.9 图片识别文字审核敏感词</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-10-%E6%96%87%E7%AB%A0%E8%AF%A6%E6%83%85-%E9%9D%99%E6%80%81%E6%96%87%E4%BB%B6%E7%94%9F%E6%88%90"><span class="toc-text">4.10 文章详情-静态文件生成</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-11-%E6%96%87%E7%AB%A0%E5%AE%9A%E6%97%B6%E5%8F%91%E5%B8%83"><span class="toc-text">4.11 文章定时发布</span></a></li></ol></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最近更新</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/8957.html" title="Linux从入门到进阶"><img src="/img/8.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Linux从入门到进阶"/></a><div class="content"><a class="title" href="/posts/8957.html" title="Linux从入门到进阶">Linux从入门到进阶</a><time datetime="2024-05-10T05:31:11.691Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/35630.html" title="接口测试工具"><img src="/img/2.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="接口测试工具"/></a><div class="content"><a class="title" href="/posts/35630.html" title="接口测试工具">接口测试工具</a><time datetime="2024-05-10T05:31:11.686Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/32246.html" title="SpringBoot中整合Swagger2"><img src="/img/3.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="SpringBoot中整合Swagger2"/></a><div class="content"><a class="title" href="/posts/32246.html" title="SpringBoot中整合Swagger2">SpringBoot中整合Swagger2</a><time datetime="2024-05-10T05:31:11.681Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/19306.html" title="Docker容器化技术"><img src="/img/1.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Docker容器化技术"/></a><div class="content"><a class="title" href="/posts/19306.html" title="Docker容器化技术">Docker容器化技术</a><time datetime="2024-05-10T05:31:11.675Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/20683.html" title="Linux中开发环境的搭建"><img src="/img/8.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Linux中开发环境的搭建"/></a><div class="content"><a class="title" href="/posts/20683.html" title="Linux中开发环境的搭建">Linux中开发环境的搭建</a><time datetime="2024-05-10T05:31:11.669Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comment-alt"></i></a><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/cdn/js/medium-zoom.min.js"></script><script src="/cdn/js/instantpage.min.js" type="module"></script><script src="/cdn/js/snackbar.min.js"></script><div class="js-pjax"><script>function loadGitalk () {
function initGitalk () {
var gitalk = new Gitalk(Object.assign({
clientID: '00fb27b1e484536359c2',
clientSecret: 'be41a12281c68b6e228d1a27e8d08aeb91541145',
repo: 'BlogComment',
owner: 'JasonsGong',
admin: ['JasonsGong'],
id: '8fd65f0c3b4dd09c2aa8d83eacb6aa53',
updateCountCallback: commentCount
},null))
gitalk.render('gitalk-container')
}
if (typeof Gitalk === 'function') initGitalk()
else {
getCSS('/cdn/css/gitalk.min.css')
getScript('/cdn/js/gitalk.min.js').then(initGitalk)
}
}
function commentCount(n){
let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count')
if (isCommentCount) {
isCommentCount.textContent= n
}
}
if ('Gitalk' === 'Gitalk' || !true) {
if (true) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk)
else loadGitalk()
} else {
function loadOtherComment () {
loadGitalk()
}
}</script></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span> 数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><br/><div class="no-result" id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div><!-- hexo injector body_end start --><script data-pjax>
function butterfly_swiper_injector_config(){
var parent_div_git = document.getElementById('recent-posts');
var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/19306.html" alt=""><img width="48" height="48" src="/img/1.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-04-21</span><a class="blog-slider__title" href="posts/19306.html" alt="">Docker容器化技术</a><div class="blog-slider__text">Docker</div><a class="blog-slider__button" href="posts/19306.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/47003.html" alt=""><img width="48" height="48" src="/img/5.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-03-10</span><a class="blog-slider__title" href="posts/47003.html" alt="">常用正则表达式大全</a><div class="blog-slider__text">正则表达式</div><a class="blog-slider__button" href="posts/47003.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/20683.html" alt=""><img width="48" height="48" src="/img/8.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-06-05</span><a class="blog-slider__title" href="posts/20683.html" alt="">Linux中开发环境的搭建</a><div class="blog-slider__text">环境搭建</div><a class="blog-slider__button" href="posts/20683.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/63333.html" alt=""><img width="48" height="48" src="/img/10.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-06-03</span><a class="blog-slider__title" href="posts/63333.html" alt="">开发环境的搭建</a><div class="blog-slider__text">环境搭建</div><a class="blog-slider__button" href="posts/63333.html" alt="">详情 </a></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div></div></div>';
if (parent_div_git !== null && typeof parent_div_git !== 'undefined') {
parent_div_git.insertAdjacentHTML("afterbegin",item_html)
}
}
var elist = 'undefined'.split(',');
var cpage = location.pathname;
var epage = 'all';
var flag = 0;
for (var i=0;i<elist.length;i++){
if (cpage.includes(elist[i])){
flag++;
}
}
if ((epage ==='all')&&(flag == 0)){
butterfly_swiper_injector_config();
}
else if (epage === cpage){
butterfly_swiper_injector_config();
}
</script><script defer src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js"></script><script defer data-pjax src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js"></script><!-- hexo injector body_end end --></body></html>