-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
46 lines (21 loc) · 555 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>测试图片显示</title>
<link href="/post/d87f7e0c.html"/>
<url>/post/d87f7e0c.html</url>
<content type="html"><![CDATA[<p><strong>测试本地图片显示</strong></p><p><img src="/post/d87f7e0c/1.jpg" alt="测试图片"></p><p><strong>测试网络图片显示</strong></p><img src="https://pic.cnblogs.com/avatar/2248891/20220924221134.png">]]></content>
</entry>
<entry>
<title>项目实战-前后端分离博客系统</title>
<link href="/post/0.html"/>
<url>/post/0.html</url>
<content type="html"><![CDATA[<h1 id="项目实战-前后端分离博客系统"><a href="#项目实战-前后端分离博客系统" class="headerlink" title="项目实战-前后端分离博客系统"></a>项目实战-前后端分离博客系统</h1><h2 id="1-课程介绍"><a href="#1-课程介绍" class="headerlink" title="1.课程介绍"></a>1.课程介绍</h2><ul><li>纯后端讲解</li><li>完整的前台后台代码编写</li><li>主流技术栈(SpringBoot,MybatisPlus,SpringSecurity,EasyExcel,Swagger2,Redis,Echarts,Vue,ElementUI….)</li><li>完善细致的需求分析</li><li>由易到难循序渐进</li></ul><h2 id="2-创建工程"><a href="#2-创建工程" class="headerlink" title="2.创建工程"></a>2.创建工程</h2><p>我们有前台和后台两套系统。两套系统的前端工程都已经提供好了。所以我们只需要写两套系统的后端。</p><p>但是大家思考下,实际上两套后端系统的很多内容是可能重复的。这里如果我们只是单纯的创建两个后端工程。那么就会有大量的重复代码,并且需要修改的时候也需要修改两次。这就是代码复用性不高。</p><p>所以我们需要创建多模块项目,两套系统可能都会用到的代码可以写到一个公共模块中,让前台系统和后台系统分别取依赖公共模块。</p><p>① 创建父模块</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><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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>SGBlog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>pom<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modules</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">module</span>></span>sangeng-framework<span class="tag"></<span class="name">module</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">module</span>></span>sangeng-admin<span class="tag"></<span class="name">module</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">module</span>></span>sangeng-blog<span class="tag"></<span class="name">module</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">modules</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">properties</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">project.build.sourceEncoding</span>></span>UTF-8<span class="tag"></<span class="name">project.build.sourceEncoding</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">java.version</span>></span>1.8<span class="tag"></<span class="name">java.version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">properties</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencyManagement</span>></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- SpringBoot的依赖配置--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-dependencies<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.5.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">type</span>></span>pom<span class="tag"></<span class="name">type</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>import<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--fastjson依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>fastjson<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.2.33<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--jwt依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.jsonwebtoken<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jjwt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>0.9.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--mybatisPlus依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.baomidou<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mybatis-plus-boot-starter<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.4.3<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!--阿里云OSS--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.aliyun.oss<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>aliyun-sdk-oss<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.10.2<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>easyexcel<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.0.5<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger2<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.9.2<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger-ui<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.9.2<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="tag"></<span class="name">dependencyManagement</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">build</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.maven.plugins<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-compiler-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.1<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">source</span>></span>${java.version}<span class="tag"></<span class="name">source</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">target</span>></span>${java.version}<span class="tag"></<span class="name">target</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">encoding</span>></span>${project.build.sourceEncoding}<span class="tag"></<span class="name">encoding</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">build</span>></span></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>②创建公共子模块 sangeng-framework</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><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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>SGBlog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sangeng-framework<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-web<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--lombk--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">optional</span>></span>true<span class="tag"></<span class="name">optional</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--junit--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-test<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--SpringSecurity启动器--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-security<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--redis依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-data-redis<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--fastjson依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>fastjson<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--jwt依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.jsonwebtoken<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jjwt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--mybatisPlus依赖--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.baomidou<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mybatis-plus-boot-starter<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!--mysql数据库驱动--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>mysql<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mysql-connector-java<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!--阿里云OSS--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.aliyun.oss<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>aliyun-sdk-oss<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!--AOP--></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-aop<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>easyexcel<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger2<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger-ui<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>③创建博客后台模块sangeng-admin</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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>SGBlog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sangeng-admin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sangeng-framework<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>④创建博客前台模块sangeng-blog</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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>SGBlog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sangeng-blog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sangeng<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sangeng-framework<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="3-博客前台"><a href="#3-博客前台" class="headerlink" title="3.博客前台"></a>3.博客前台</h2><h3 id="3-0-准备工作"><a href="#3-0-准备工作" class="headerlink" title="3.0 准备工作"></a>3.0 准备工作</h3><h4 id="3-1-SpringBoot和MybatisPuls整合配置测试"><a href="#3-1-SpringBoot和MybatisPuls整合配置测试" class="headerlink" title="3.1 SpringBoot和MybatisPuls整合配置测试"></a>3.1 SpringBoot和MybatisPuls整合配置测试</h4><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></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> 三更 B站: https://space.bilibili.com/663528522</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan("com.sangeng.mapper")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SanGengBlogApplication</span> {</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> {</span><br><span class="line"> SpringApplication.run(SanGengBlogApplication.class,args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>②创建application.yml配置文件</p><figure class="highlight yml"><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">server:</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">7777</span></span><br><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">url:</span> <span class="string">jdbc:mysql://localhost:3306/sg_blog?characterEncoding=utf-8&serverTimezone=Asia/Shanghai</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="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"> <span class="attr">servlet:</span></span><br><span class="line"> <span class="attr">multipart:</span></span><br><span class="line"> <span class="attr">max-file-size:</span> <span class="string">2MB</span></span><br><span class="line"> <span class="attr">max-request-size:</span> <span class="string">5MB</span></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line"> <span class="attr">configuration:</span></span><br><span class="line"> <span class="comment"># 日志</span></span><br><span class="line"> <span class="attr">log-impl:</span> <span class="string">org.apache.ibatis.logging.stdout.StdOutImpl</span></span><br><span class="line"> <span class="attr">global-config:</span></span><br><span class="line"> <span class="attr">db-config:</span></span><br><span class="line"> <span class="attr">logic-delete-field:</span> <span class="string">delFlag</span></span><br><span class="line"> <span class="attr">logic-delete-value:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">logic-not-delete-value:</span> <span class="number">0</span></span><br><span class="line"> <span class="attr">id-type:</span> <span class="string">auto</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>③ SQL语句</p><p>SQL脚本:SGBlog\资源\SQL\sg_article.sql</p><p>④ 创建实体类,Mapper,Service </p><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@SuppressWarnings("serial")</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@TableName("sg_article")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Article</span> {</span><br><span class="line"> <span class="meta">@TableId</span></span><br><span class="line"> <span class="keyword">private</span> Long id;</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="keyword">private</span> String content;</span><br><span class="line"> <span class="comment">//文章类型:1 文章 2草稿</span></span><br><span class="line"> <span class="keyword">private</span> String type;</span><br><span class="line"> <span class="comment">//文章摘要</span></span><br><span class="line"> <span class="keyword">private</span> String summary;</span><br><span class="line"> <span class="comment">//所属分类id</span></span><br><span class="line"> <span class="keyword">private</span> Long categoryId;</span><br><span class="line"> <span class="comment">//缩略图</span></span><br><span class="line"> <span class="keyword">private</span> String thumbnail;</span><br><span class="line"> <span class="comment">//是否置顶(0否,1是)</span></span><br><span class="line"> <span class="keyword">private</span> String isTop;</span><br><span class="line"> <span class="comment">//状态(0已发布,1草稿)</span></span><br><span class="line"> <span class="keyword">private</span> String status;</span><br><span class="line"> <span class="comment">//评论数</span></span><br><span class="line"> <span class="keyword">private</span> Integer commentCount;</span><br><span class="line"> <span class="comment">//访问量</span></span><br><span class="line"> <span class="keyword">private</span> Long viewCount;</span><br><span class="line"> <span class="comment">//是否允许评论 1是,0否</span></span><br><span class="line"> <span class="keyword">private</span> String isComment;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Long createBy;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Date createTime;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Long updateBy;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Date updateTime;</span><br><span class="line"> <span class="comment">//删除标志(0代表未删除,1代表已删除)</span></span><br><span class="line"> <span class="keyword">private</span> Integer delFlag;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ArticleMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span><Article> {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ArticleService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Article> {</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><ArticleMapper, Article> <span class="keyword">implements</span> <span class="title class_">ArticleService</span> {</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>⑤ 创建Controller测试接口</p><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/article")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleController</span> {</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> ArticleService articleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/list")</span></span><br><span class="line"> <span class="keyword">public</span> List<Article> <span class="title function_">test</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> articleService.list();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>我们可以暂时先注释掉sangeng-framework中的SpringSecurity依赖方便测试</p><h3 id="3-1-热门文章列表"><a href="#3-1-热门文章列表" class="headerlink" title="3.1 热门文章列表"></a>3.1 热门文章列表</h3><h4 id="3-1-0-文章表分析"><a href="#3-1-0-文章表分析" class="headerlink" title="3.1.0 文章表分析"></a>3.1.0 文章表分析</h4><p>通过需求去分析需要有哪些字段。</p><h4 id="3-1-1-需求"><a href="#3-1-1-需求" class="headerlink" title="3.1.1 需求"></a>3.1.1 需求</h4><p>需要查询浏览量最高的前10篇文章的信息。要求展示文章标题和浏览量。把能让用户自己点击跳转到具体的文章详情进行浏览。</p><p>注意:不能把草稿展示出来,不能把删除了的文章查询出来。要按照浏览量进行降序排序。</p><h4 id="3-1-2-接口设计"><a href="#3-1-2-接口设计" class="headerlink" title="3.1.2 接口设计"></a>3.1.2 接口设计</h4><p>见接口文档</p><h4 id="3-1-3-基础版本代码实现"><a href="#3-1-3-基础版本代码实现" class="headerlink" title="3.1.3 基础版本代码实现"></a>3.1.3 基础版本代码实现</h4><p>①准备工作</p><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sangeng.domain;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.annotation.JsonInclude;</span><br><span class="line"><span class="keyword">import</span> com.sangeng.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><br><span class="line"><span class="meta">@JsonInclude(JsonInclude.Include.NON_NULL)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ResponseResult</span><T> <span class="keyword">implements</span> <span class="title class_">Serializable</span> {</span><br><span class="line"> <span class="keyword">private</span> Integer code;</span><br><span class="line"> <span class="keyword">private</span> String msg;</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> {</span><br><span class="line"> <span class="built_in">this</span>.code = AppHttpCodeEnum.SUCCESS.getCode();</span><br><span class="line"> <span class="built_in">this</span>.msg = AppHttpCodeEnum.SUCCESS.getMsg();</span><br><span class="line"> }</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> {</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><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> {</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.msg = msg;</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> }</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> {</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.msg = msg;</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> ResponseResult <span class="title function_">errorResult</span><span class="params">(<span class="type">int</span> code, String msg)</span> {</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"> }</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> {</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;</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> {</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"> }</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> {</span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg());</span><br><span class="line"> <span class="keyword">if</span>(data!=<span class="literal">null</span>) {</span><br><span class="line"> result.setData(data);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</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> ResponseResult <span class="title function_">errorResult</span><span class="params">(AppHttpCodeEnum enums)</span>{</span><br><span class="line"> <span class="keyword">return</span> setAppHttpCodeEnum(enums,enums.getMsg());</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> ResponseResult <span class="title function_">errorResult</span><span class="params">(AppHttpCodeEnum enums, String msg)</span>{</span><br><span class="line"> <span class="keyword">return</span> setAppHttpCodeEnum(enums,msg);</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> ResponseResult <span class="title function_">setAppHttpCodeEnum</span><span class="params">(AppHttpCodeEnum enums)</span>{</span><br><span class="line"> <span class="keyword">return</span> okResult(enums.getCode(),enums.getMsg());</span><br><span class="line"> }</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 msg)</span>{</span><br><span class="line"> <span class="keyword">return</span> okResult(enums.getCode(),msg);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<?> error(Integer code, String msg) {</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.msg = msg;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<?> ok(Integer code, T data) {</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"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<?> ok(Integer code, T data, String msg) {</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>.msg = msg;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<?> ok(T data) {</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"> }</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> {</span><br><span class="line"> <span class="keyword">return</span> code;</span><br><span class="line"> }</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> {</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getMsg</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> msg;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setMsg</span><span class="params">(String msg)</span> {</span><br><span class="line"> <span class="built_in">this</span>.msg = msg;</span><br><span class="line"> }</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> {</span><br><span class="line"> <span class="keyword">return</span> data;</span><br><span class="line"> }</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> {</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sangeng.enums;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">AppHttpCodeEnum</span> {</span><br><span class="line"> <span class="comment">// 成功</span></span><br><span class="line"> SUCCESS(<span class="number">200</span>,<span class="string">"操作成功"</span>),</span><br><span class="line"> <span class="comment">// 登录</span></span><br><span class="line"> NEED_LOGIN(<span class="number">401</span>,<span class="string">"需要登录后操作"</span>),</span><br><span class="line"> NO_OPERATOR_AUTH(<span class="number">403</span>,<span class="string">"无权限操作"</span>),</span><br><span class="line"> SYSTEM_ERROR(<span class="number">500</span>,<span class="string">"出现错误"</span>),</span><br><span class="line"> USERNAME_EXIST(<span class="number">501</span>,<span class="string">"用户名已存在"</span>),</span><br><span class="line"> PHONENUMBER_EXIST(<span class="number">502</span>,<span class="string">"手机号已存在"</span>), EMAIL_EXIST(<span class="number">503</span>, <span class="string">"邮箱已存在"</span>),</span><br><span class="line"> REQUIRE_USERNAME(<span class="number">504</span>, <span class="string">"必需填写用户名"</span>),</span><br><span class="line"> LOGIN_ERROR(<span class="number">505</span>,<span class="string">"用户名或密码错误"</span>);</span><br><span class="line"> <span class="type">int</span> code;</span><br><span class="line"> String msg;</span><br><span class="line"></span><br><span class="line"> AppHttpCodeEnum(<span class="type">int</span> code, String errorMessage){</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.msg = errorMessage;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getCode</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> code;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getMsg</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> msg;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/article")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleController</span> {</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> ArticleService articleService;</span><br><span class="line"> </span><br><span class="line"> <span class="meta">@GetMapping("/hotArticleList")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">hotArticleList</span><span class="params">()</span>{</span><br><span class="line"></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> articleService.hotArticleList();</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ArticleService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Article> {</span><br><span class="line"> ResponseResult <span class="title function_">hotArticleList</span><span class="params">()</span>;</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><ArticleMapper, Article> <span class="keyword">implements</span> <span class="title class_">ArticleService</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_">hotArticleList</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询热门文章 封装成ResponseResult返回</span></span><br><span class="line"> LambdaQueryWrapper<Article> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//必须是正式文章</span></span><br><span class="line"> queryWrapper.eq(Article::getStatus,<span class="number">0</span>);</span><br><span class="line"> <span class="comment">//按照浏览量进行排序</span></span><br><span class="line"> queryWrapper.orderByDesc(Article::getViewCount);</span><br><span class="line"> <span class="comment">//最多只查询10条</span></span><br><span class="line"> Page<Article> page = <span class="keyword">new</span> <span class="title class_">Page</span>(<span class="number">1</span>,<span class="number">10</span>);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = page.getRecords();</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(articles);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><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_">WebConfig</span> <span class="keyword">implements</span> <span class="title class_">WebMvcConfigurer</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> <span class="keyword">void</span> <span class="title function_">addCorsMappings</span><span class="params">(CorsRegistry registry)</span> {</span><br><span class="line"> <span class="comment">// 设置允许跨域的路径</span></span><br><span class="line"> registry.addMapping(<span class="string">"/**"</span>)</span><br><span class="line"> <span class="comment">// 设置允许跨域请求的域名</span></span><br><span class="line"> .allowedOriginPatterns(<span class="string">"*"</span>)</span><br><span class="line"> <span class="comment">// 是否允许cookie</span></span><br><span class="line"> .allowCredentials(<span class="literal">true</span>)</span><br><span class="line"> <span class="comment">// 设置允许的请求方式</span></span><br><span class="line"> .allowedMethods(<span class="string">"GET"</span>, <span class="string">"POST"</span>, <span class="string">"DELETE"</span>, <span class="string">"PUT"</span>)</span><br><span class="line"> <span class="comment">// 设置允许的header属性</span></span><br><span class="line"> .allowedHeaders(<span class="string">"*"</span>)</span><br><span class="line"> <span class="comment">// 跨域允许时间</span></span><br><span class="line"> .maxAge(<span class="number">3600</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3-1-4-使用VO优化"><a href="#3-1-4-使用VO优化" class="headerlink" title="3.1.4 使用VO优化"></a>3.1.4 使用VO优化</h4><p>目前我们的响应格式其实是不符合接口文档的标准的,多返回了很多字段。这是因为我们查询出来的结果是Article来封装的,Article中字段比较多。</p><p>我们在项目中一般最后还要把VO来接受查询出来的结果。一个接口对应一个VO,这样即使接口响应字段要修改也只要改VO即可。</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">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HotArticleVo</span> {</span><br><span class="line"> <span class="keyword">private</span> Long id;</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><br><span class="line"> <span class="comment">//访问量</span></span><br><span class="line"> <span class="keyword">private</span> Long viewCount;</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><ArticleMapper, Article> <span class="keyword">implements</span> <span class="title class_">ArticleService</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_">hotArticleList</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询热门文章 封装成ResponseResult返回</span></span><br><span class="line"> LambdaQueryWrapper<Article> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//必须是正式文章</span></span><br><span class="line"> queryWrapper.eq(Article::getStatus,<span class="number">0</span>);</span><br><span class="line"> <span class="comment">//按照浏览量进行排序</span></span><br><span class="line"> queryWrapper.orderByDesc(Article::getViewCount);</span><br><span class="line"> <span class="comment">//最多只查询10条</span></span><br><span class="line"> Page<Article> page = <span class="keyword">new</span> <span class="title class_">Page</span>(<span class="number">1</span>,<span class="number">10</span>);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = page.getRecords();</span><br><span class="line"> <span class="comment">//bean拷贝</span></span><br><span class="line"> List<HotArticleVo> articleVos = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> <span class="keyword">for</span> (Article article : articles) {</span><br><span class="line"> <span class="type">HotArticleVo</span> <span class="variable">vo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HotArticleVo</span>();</span><br><span class="line"> BeanUtils.copyProperties(article,vo);</span><br><span class="line"> articleVos.add(vo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(articleVos);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3-1-5-字面值处理"><a href="#3-1-5-字面值处理" class="headerlink" title="3.1.5 字面值处理"></a>3.1.5 字面值处理</h4><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SystemConstants</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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">ARTICLE_STATUS_DRAFT</span> <span class="operator">=</span> <span class="number">1</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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">ARTICLE_STATUS_NORMAL</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> </span><br><span class="line">}</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><ArticleMapper, Article> <span class="keyword">implements</span> <span class="title class_">ArticleService</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_">hotArticleList</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询热门文章 封装成ResponseResult返回</span></span><br><span class="line"> LambdaQueryWrapper<Article> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//必须是正式文章</span></span><br><span class="line"> queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);</span><br><span class="line"> <span class="comment">//按照浏览量进行排序</span></span><br><span class="line"> queryWrapper.orderByDesc(Article::getViewCount);</span><br><span class="line"> <span class="comment">//最多只查询10条</span></span><br><span class="line"> Page<Article> page = <span class="keyword">new</span> <span class="title class_">Page</span>(<span class="number">1</span>,<span class="number">10</span>);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = page.getRecords();</span><br><span class="line"> <span class="comment">//bean拷贝</span></span><br><span class="line"> List<HotArticleVo> articleVos = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> <span class="keyword">for</span> (Article article : articles) {</span><br><span class="line"> <span class="type">HotArticleVo</span> <span class="variable">vo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HotArticleVo</span>();</span><br><span class="line"> BeanUtils.copyProperties(article,vo);</span><br><span class="line"> articleVos.add(vo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(articleVos);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-2-Bean拷贝工具类封装"><a href="#3-2-Bean拷贝工具类封装" class="headerlink" title="3.2 Bean拷贝工具类封装"></a>3.2 Bean拷贝工具类封装</h3><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BeanCopyUtils</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">BeanCopyUtils</span><span class="params">()</span> {</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> <V> V <span class="title function_">copyBean</span><span class="params">(Object source,Class<V> clazz)</span> {</span><br><span class="line"> <span class="comment">//创建目标对象</span></span><br><span class="line"> <span class="type">V</span> <span class="variable">result</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> result = clazz.newInstance();</span><br><span class="line"> <span class="comment">//实现属性copy</span></span><br><span class="line"> BeanUtils.copyProperties(source, result);</span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//返回结果</span></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <O,V> List<V> <span class="title function_">copyBeanList</span><span class="params">(List<O> list,Class<V> clazz)</span>{</span><br><span class="line"> <span class="keyword">return</span> list.stream()</span><br><span class="line"> .map(o -> copyBean(o, clazz))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-2-查询分类列表"><a href="#3-2-查询分类列表" class="headerlink" title="3.2 查询分类列表"></a>3.2 查询分类列表</h3><h4 id="3-2-0-分类表分析"><a href="#3-2-0-分类表分析" class="headerlink" title="3.2.0 分类表分析"></a>3.2.0 分类表分析</h4><p>通过需求去分析需要有哪些字段。</p><p>建表SQL及初始化数据见:SGBlog\资源\SQL\sg_category.sql</p><h4 id="3-2-1-需求"><a href="#3-2-1-需求" class="headerlink" title="3.2.1 需求"></a>3.2.1 需求</h4><p><img src="/post/0/image-20220202111056036-16437714601701.png" alt="image-20220202111056036"></p><p>页面上需要展示分类列表,用户可以点击具体的分类查看该分类下的文章列表。</p><p>注意: ①要求只展示有发布正式文章的分类 ②必须是正常状态的分类</p><h4 id="3-2-2-接口设计"><a href="#3-2-2-接口设计" class="headerlink" title="3.2.2 接口设计"></a>3.2.2 接口设计</h4><p>见接口文档</p><h4 id="3-2-3-EasyCode代码模板"><a href="#3-2-3-EasyCode代码模板" class="headerlink" title="3.2.3 EasyCode代码模板"></a>3.2.3 EasyCode代码模板</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></pre></td><td class="code"><pre><span class="line">##导入宏定义</span><br><span class="line">$!{define.vm}</span><br><span class="line"></span><br><span class="line">##保存文件(宏定义)</span><br><span class="line">#save(<span class="string">"/entity"</span>, <span class="string">".java"</span>)</span><br><span class="line"></span><br><span class="line">##包路径(宏定义)</span><br><span class="line">#setPackageSuffix(<span class="string">"entity"</span>)</span><br><span class="line"></span><br><span class="line">##自动导入包(全局变量)</span><br><span class="line">$!{autoImport.vm}</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> lombok.AllArgsConstructor;</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 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><br><span class="line">#tableComment(<span class="string">"表实体类"</span>)</span><br><span class="line"><span class="meta">@SuppressWarnings("serial")</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@TableName("$!{tableInfo.obj.name}")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">$</span>!{tableInfo.name} {</span><br><span class="line">#foreach($column in $tableInfo.pkColumn)</span><br><span class="line"> #<span class="keyword">if</span>(${column.comment})<span class="comment">//${column.comment}#end</span></span><br><span class="line"><span class="meta">@TableId</span></span><br><span class="line"> <span class="keyword">private</span> $!{tool.getClsNameByFullName($column.type)} $!{column.name};</span><br><span class="line">#end</span><br><span class="line"></span><br><span class="line">#foreach($column in $tableInfo.otherColumn)</span><br><span class="line"> #<span class="keyword">if</span>(${column.comment})<span class="comment">//${column.comment}#end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> $!{tool.getClsNameByFullName($column.type)} $!{column.name};</span><br><span class="line">#end</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line">##导入宏定义</span><br><span class="line">$!{define.vm}</span><br><span class="line"></span><br><span class="line">##设置表后缀(宏定义)</span><br><span class="line">#setTableSuffix(<span class="string">"Mapper"</span>)</span><br><span class="line"></span><br><span class="line">##保存文件(宏定义)</span><br><span class="line">#save(<span class="string">"/mapper"</span>, <span class="string">"Mapper.java"</span>)</span><br><span class="line"></span><br><span class="line">##包路径(宏定义)</span><br><span class="line">#setPackageSuffix(<span class="string">"mapper"</span>)</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><br><span class="line"></span><br><span class="line">##表注释(宏定义)</span><br><span class="line">#tableComment(<span class="string">"表数据库访问层"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">$</span>!{tableName} <span class="keyword">extends</span> <span class="title class_">BaseMapper</span><$!tableInfo.name> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line">##导入宏定义</span><br><span class="line">$!{define.vm}</span><br><span class="line"></span><br><span class="line">##设置表后缀(宏定义)</span><br><span class="line">#setTableSuffix(<span class="string">"Service"</span>)</span><br><span class="line"></span><br><span class="line">##保存文件(宏定义)</span><br><span class="line">#save(<span class="string">"/service"</span>, <span class="string">"Service.java"</span>)</span><br><span class="line"></span><br><span class="line">##包路径(宏定义)</span><br><span class="line">#setPackageSuffix(<span class="string">"service"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.extension.service.IService;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">##表注释(宏定义)</span><br><span class="line">#tableComment(<span class="string">"表服务接口"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">$</span>!{tableName} <span class="keyword">extends</span> <span class="title class_">IService</span><$!tableInfo.name> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line">##导入宏定义</span><br><span class="line">$!{define.vm}</span><br><span class="line"></span><br><span class="line">##设置表后缀(宏定义)</span><br><span class="line">#setTableSuffix(<span class="string">"ServiceImpl"</span>)</span><br><span class="line"></span><br><span class="line">##保存文件(宏定义)</span><br><span class="line">#save(<span class="string">"/service/impl"</span>, <span class="string">"ServiceImpl.java"</span>)</span><br><span class="line"></span><br><span class="line">##包路径(宏定义)</span><br><span class="line">#setPackageSuffix(<span class="string">"service.impl"</span>)</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> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line">##表注释(宏定义)</span><br><span class="line">#tableComment(<span class="string">"表服务实现类"</span>)</span><br><span class="line"><span class="meta">@Service("$!tool.firstLowerCase($tableInfo.name)Service")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">$</span>!{tableName} <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><$!{tableInfo.name}Mapper, $!{tableInfo.name}> <span class="keyword">implements</span> <span class="title class_">$</span>!{tableInfo.name}Service {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="3-2-4-代码实现"><a href="#3-2-4-代码实现" class="headerlink" title="3.2.4 代码实现"></a>3.2.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></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/category")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CategoryController</span> {</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> CategoryService categoryService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/getCategoryList")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">getCategoryList</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> categoryService.getCategoryList();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> </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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">CategoryService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Category> {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> ResponseResult <span class="title function_">getCategoryList</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">}</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service("categoryService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CategoryServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><CategoryMapper, Category> <span class="keyword">implements</span> <span class="title class_">CategoryService</span> {</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> ArticleService articleService;</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_">getCategoryList</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询文章表 状态为已发布的文章</span></span><br><span class="line"> LambdaQueryWrapper<Article> articleWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> articleWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL);</span><br><span class="line"> List<Article> articleList = articleService.list(articleWrapper);</span><br><span class="line"> <span class="comment">//获取文章的分类id,并且去重</span></span><br><span class="line"> Set<Long> categoryIds = articleList.stream()</span><br><span class="line"> .map(article -> article.getCategoryId())</span><br><span class="line"> .collect(Collectors.toSet());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查询分类表</span></span><br><span class="line"> List<Category> categories = listByIds(categoryIds);</span><br><span class="line"> categories = categories.stream().</span><br><span class="line"> filter(category -> SystemConstants.STATUS_NORMAL.equals(category.getStatus()))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="comment">//封装vo</span></span><br><span class="line"> List<CategoryVo> categoryVos = BeanCopyUtils.copyBeanList(categories, CategoryVo.class);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(categoryVos);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-3-分页查询文章列表"><a href="#3-3-分页查询文章列表" class="headerlink" title="3.3 分页查询文章列表"></a>3.3 分页查询文章列表</h3><h4 id="3-3-1-需求"><a href="#3-3-1-需求" class="headerlink" title="3.3.1 需求"></a>3.3.1 需求</h4><p>在首页和分类页面都需要查询文章列表。</p><p>首页:查询所有的文章</p><p>分类页面:查询对应分类下的文章</p><p>要求:①只能查询正式发布的文章 ②置顶的文章要显示在最前面 </p><h4 id="3-3-2-接口设计"><a href="#3-3-2-接口设计" class="headerlink" title="3.3.2 接口设计"></a>3.3.2 接口设计</h4><p>见文档</p><h4 id="3-3-3-代码实现"><a href="#3-3-3-代码实现" class="headerlink" title="3.3.3 代码实现"></a>3.3.3 代码实现</h4><p>MP支持分页配置</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></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> 三更 B站: https://space.bilibili.com/663528522</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_">MbatisPlusConfig</span> {</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 3.4.0之后版本</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">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> MybatisPlusInterceptor <span class="title function_">mybatisPlusInterceptor</span><span class="params">()</span>{</span><br><span class="line"> <span class="type">MybatisPlusInterceptor</span> <span class="variable">mybatisPlusInterceptor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MybatisPlusInterceptor</span>();</span><br><span class="line"> mybatisPlusInterceptor.addInnerInterceptor(<span class="keyword">new</span> <span class="title class_">PaginationInnerInterceptor</span>());</span><br><span class="line"> <span class="keyword">return</span> mybatisPlusInterceptor;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在ArticleController中</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping("/articleList")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">articleList</span><span class="params">(Integer pageNum,Integer pageSize,Long categoryId)</span>{</span><br><span class="line"> <span class="keyword">return</span> articleService.articleList(pageNum,pageSize,categoryId);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在ArticleService中</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">articleList</span><span class="params">(Integer pageNum, Integer pageSize, Long categoryId)</span>;</span><br></pre></td></tr></table></figure><p>在ArticleServiceImpl中</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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><ArticleMapper, Article> <span class="keyword">implements</span> <span class="title class_">ArticleService</span> {</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> CategoryService categoryService;</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_">hotArticleList</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询热门文章 封装成ResponseResult返回</span></span><br><span class="line"> LambdaQueryWrapper<Article> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//必须是正式文章</span></span><br><span class="line"> queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);</span><br><span class="line"> <span class="comment">//按照浏览量进行排序</span></span><br><span class="line"> queryWrapper.orderByDesc(Article::getViewCount);</span><br><span class="line"> <span class="comment">//最多只查询10条</span></span><br><span class="line"> Page<Article> page = <span class="keyword">new</span> <span class="title class_">Page</span>(<span class="number">1</span>,<span class="number">10</span>);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = page.getRecords();</span><br><span class="line"> <span class="comment">//bean拷贝</span></span><br><span class="line"><span class="comment">// List<HotArticleVo> articleVos = new ArrayList<>();</span></span><br><span class="line"><span class="comment">// for (Article article : articles) {</span></span><br><span class="line"><span class="comment">// HotArticleVo vo = new HotArticleVo();</span></span><br><span class="line"><span class="comment">// BeanUtils.copyProperties(article,vo);</span></span><br><span class="line"><span class="comment">// articleVos.add(vo);</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"> List<HotArticleVo> vs = BeanCopyUtils.copyBeanList(articles, HotArticleVo.class);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(vs);</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_">articleList</span><span class="params">(Integer pageNum, Integer pageSize, Long categoryId)</span> {</span><br><span class="line"> <span class="comment">//查询条件</span></span><br><span class="line"> LambdaQueryWrapper<Article> lambdaQueryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">// 如果 有categoryId 就要 查询时要和传入的相同</span></span><br><span class="line"> lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId><span class="number">0</span> ,Article::getCategoryId,categoryId);</span><br><span class="line"> <span class="comment">// 状态是正式发布的</span></span><br><span class="line"> lambdaQueryWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL);</span><br><span class="line"> <span class="comment">// 对isTop进行降序</span></span><br><span class="line"> lambdaQueryWrapper.orderByDesc(Article::getIsTop);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//分页查询</span></span><br><span class="line"> Page<Article> page = <span class="keyword">new</span> <span class="title class_">Page</span><>(pageNum,pageSize);</span><br><span class="line"> page(page,lambdaQueryWrapper);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = page.getRecords();</span><br><span class="line"> <span class="comment">//查询categoryName</span></span><br><span class="line"> articles.stream()</span><br><span class="line"> .map(article -> article.setCategoryName(categoryService.getById(article.getCategoryId()).getName()))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="comment">//articleId去查询articleName进行设置</span></span><br><span class="line"><span class="comment">// for (Article article : articles) {</span></span><br><span class="line"><span class="comment">// Category category = categoryService.getById(article.getCategoryId());</span></span><br><span class="line"><span class="comment">// article.setCategoryName(category.getName());</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"> List<ArticleListVo> articleListVos = BeanCopyUtils.copyBeanList(page.getRecords(), ArticleListVo.class);</span><br><span class="line"></span><br><span class="line"> <span class="type">PageVo</span> <span class="variable">pageVo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageVo</span>(articleListVos,page.getTotal());</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(pageVo);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>PageVo</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="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PageVo</span> {</span><br><span class="line"> <span class="keyword">private</span> List rows;</span><br><span class="line"> <span class="keyword">private</span> Long total;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>ArticleListVo</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></pre></td><td class="code"><pre><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">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleListVo</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Long id;</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="keyword">private</span> String summary;</span><br><span class="line"> <span class="comment">//所属分类名</span></span><br><span class="line"> <span class="keyword">private</span> String categoryName;</span><br><span class="line"> <span class="comment">//缩略图</span></span><br><span class="line"> <span class="keyword">private</span> String thumbnail;</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">private</span> Long viewCount;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在Article中增加一个字段</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">@TableField(exist = false)</span></span><br><span class="line"><span class="keyword">private</span> String categoryName;</span><br></pre></td></tr></table></figure><h4 id="3-3-4-FastJson配置"><a href="#3-3-4-FastJson配置" class="headerlink" title="3.3.4 FastJson配置"></a>3.3.4 FastJson配置</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span><span class="comment">//使用@Bean注入fastJsonHttpMessageConvert</span></span><br><span class="line"><span class="keyword">public</span> HttpMessageConverter <span class="title function_">fastJsonHttpMessageConverters</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//1.需要定义一个Convert转换消息的对象</span></span><br><span class="line"> <span class="type">FastJsonHttpMessageConverter</span> <span class="variable">fastConverter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FastJsonHttpMessageConverter</span>();</span><br><span class="line"> <span class="type">FastJsonConfig</span> <span class="variable">fastJsonConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FastJsonConfig</span>();</span><br><span class="line"> fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);</span><br><span class="line"> fastJsonConfig.setDateFormat(<span class="string">"yyyy-MM-dd HH:mm:ss"</span>);</span><br><span class="line"></span><br><span class="line"> SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance);</span><br><span class="line"></span><br><span class="line"> fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance);</span><br><span class="line"> fastConverter.setFastJsonConfig(fastJsonConfig);</span><br><span class="line"> HttpMessageConverter<?> converter = fastConverter;</span><br><span class="line"> <span class="keyword">return</span> converter;</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> <span class="keyword">void</span> <span class="title function_">configureMessageConverters</span><span class="params">(List<HttpMessageConverter<?>> converters)</span> {</span><br><span class="line"> converters.add(fastJsonHttpMessageConverters());</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-4-文章详情接口"><a href="#3-4-文章详情接口" class="headerlink" title="3.4 文章详情接口"></a>3.4 文章详情接口</h3><h4 id="3-4-1-需求"><a href="#3-4-1-需求" class="headerlink" title="3.4.1 需求"></a>3.4.1 需求</h4><p>要求在文章列表点击阅读全文时能够跳转到文章详情页面,可以让用户阅读文章正文。</p><p>要求:①要在文章详情中展示其分类名</p><h4 id="3-4-2-接口设计"><a href="#3-4-2-接口设计" class="headerlink" title="3.4.2 接口设计"></a>3.4.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求路径</th></tr></thead><tbody><tr><td>Get</td><td>/article/{id}</td></tr></tbody></table><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"categoryId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"categoryName"</span><span class="punctuation">:</span> <span class="string">"java"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span> <span class="string">"内容"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createTime"</span><span class="punctuation">:</span> <span class="string">"2022-01-23 23:20:11"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"isComment"</span><span class="punctuation">:</span> <span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"title"</span><span class="punctuation">:</span> <span class="string">"SpringSecurity从入门到精通"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"viewCount"</span><span class="punctuation">:</span> <span class="string">"114"</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-4-3-代码实现"><a href="#3-4-3-代码实现" class="headerlink" title="3.4.3 代码实现"></a>3.4.3 代码实现</h4><p>ArticleController中新增</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping("/{id}")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">getArticleDetail</span><span class="params">(<span class="meta">@PathVariable("id")</span> Long id)</span>{</span><br><span class="line"> <span class="keyword">return</span> articleService.getArticleDetail(id);</span><br><span class="line">}</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></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">getArticleDetail</span><span class="params">(Long id)</span>;</span><br></pre></td></tr></table></figure><p>ServiceImpl</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">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">getArticleDetail</span><span class="params">(Long id)</span> {</span><br><span class="line"> <span class="comment">//根据id查询文章</span></span><br><span class="line"> <span class="type">Article</span> <span class="variable">article</span> <span class="operator">=</span> getById(id);</span><br><span class="line"> <span class="comment">//转换成VO</span></span><br><span class="line"> <span class="type">ArticleDetailVo</span> <span class="variable">articleDetailVo</span> <span class="operator">=</span> BeanCopyUtils.copyBean(article, ArticleDetailVo.class);</span><br><span class="line"> <span class="comment">//根据分类id查询分类名</span></span><br><span class="line"> <span class="type">Long</span> <span class="variable">categoryId</span> <span class="operator">=</span> articleDetailVo.getCategoryId();</span><br><span class="line"> <span class="type">Category</span> <span class="variable">category</span> <span class="operator">=</span> categoryService.getById(categoryId);</span><br><span class="line"> <span class="keyword">if</span>(category!=<span class="literal">null</span>){</span><br><span class="line"> articleDetailVo.setCategoryName(category.getName());</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//封装响应返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(articleDetailVo);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-5-友联查询"><a href="#3-5-友联查询" class="headerlink" title="3.5 友联查询"></a>3.5 友联查询</h3><h4 id="3-5-0-友链表分析"><a href="#3-5-0-友链表分析" class="headerlink" title="3.5.0 友链表分析"></a>3.5.0 友链表分析</h4><p>通过需求去分析需要有哪些字段。</p><p>建表SQL及初始化数据见:SGBlog\资源\SQL\sg_link.sql</p><h4 id="3-5-1-需求"><a href="#3-5-1-需求" class="headerlink" title="3.5.1 需求"></a>3.5.1 需求</h4><p>在友链页面要查询出所有的审核通过的友链。</p><h4 id="3-5-2-接口设计"><a href="#3-5-2-接口设计" class="headerlink" title="3.5.2 接口设计"></a>3.5.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求路径</th></tr></thead><tbody><tr><td>Get</td><td>/link/getAllLink</td></tr></tbody></table><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><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="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"address"</span><span class="punctuation">:</span> <span class="string">"https://www.baidu.com"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"description"</span><span class="punctuation">:</span> <span class="string">"sda"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"logo"</span><span class="punctuation">:</span> <span class="string">"图片url1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"name"</span><span class="punctuation">:</span> <span class="string">"sda"</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"address"</span><span class="punctuation">:</span> <span class="string">"https://www.qq.com"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"description"</span><span class="punctuation">:</span> <span class="string">"dada"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"2"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"logo"</span><span class="punctuation">:</span> <span class="string">"图片url2"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"name"</span><span class="punctuation">:</span> <span class="string">"sda"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-5-3-代码实现"><a href="#3-5-3-代码实现" class="headerlink" title="3.5.3 代码实现"></a>3.5.3 代码实现</h4><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/link")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LinkController</span> {</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> LinkService linkService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/getAllLink")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">getAllLink</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> linkService.getAllLink();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">LinkService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Link> {</span><br><span class="line"></span><br><span class="line"> ResponseResult <span class="title function_">getAllLink</span><span class="params">()</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>ServiceImpl</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service("linkService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LinkServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><LinkMapper, Link> <span class="keyword">implements</span> <span class="title class_">LinkService</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_">getAllLink</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//查询所有审核通过的</span></span><br><span class="line"> LambdaQueryWrapper<Link> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> queryWrapper.eq(Link::getStatus, SystemConstants.LINK_STATUS_NORMAL);</span><br><span class="line"> List<Link> links = list(queryWrapper);</span><br><span class="line"> <span class="comment">//转换成vo</span></span><br><span class="line"> List<LinkVo> linkVos = BeanCopyUtils.copyBeanList(links, LinkVo.class);</span><br><span class="line"> <span class="comment">//封装返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(linkVos);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>SystemConstants</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></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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">LINK_STATUS_NORMAL</span> <span class="operator">=</span> <span class="string">"0"</span>;</span><br></pre></td></tr></table></figure><h3 id="3-6-登录功能实现"><a href="#3-6-登录功能实现" class="headerlink" title="3.6 登录功能实现"></a>3.6 登录功能实现</h3><p>使用我们前台和后台的认证授权统一都使用SpringSecurity安全框架来实现。</p><h4 id="3-6-0-需求"><a href="#3-6-0-需求" class="headerlink" title="3.6.0 需求"></a>3.6.0 需求</h4><p>需要实现登录功能</p><p>有些功能必须登录后才能使用,未登录状态是不能使用的。</p><h4 id="3-6-1-接口设计"><a href="#3-6-1-接口设计" class="headerlink" title="3.6.1 接口设计"></a>3.6.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求路径</th></tr></thead><tbody><tr><td>POST</td><td>/login</td></tr></tbody></table><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">{</span></span><br><span class="line"> <span class="attr">"userName"</span><span class="punctuation">:</span><span class="string">"sg"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"password"</span><span class="punctuation">:</span><span class="string">"1234"</span></span><br><span class="line"><span class="punctuation">}</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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span><span class="punctuation">:</span> <span class="string">"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI0ODBmOThmYmJkNmI0NjM0OWUyZjY2NTM0NGNjZWY2NSIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY0Mzg3NDMxNiwiZXhwIjoxNjQzOTYwNzE2fQ.ldLBUvNIxQCGemkCoMgT_0YsjsWndTg5tqfJb77pabk"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"userInfo"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"avatar"</span><span class="punctuation">:</span> <span class="string">"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2F3bf9c263bc0f2ac5c3a7feb9e218d07475573ec8.gi"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"email"</span><span class="punctuation">:</span> <span class="string">"23412332@qq.com"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"nickName"</span><span class="punctuation">:</span> <span class="string">"sg333"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"sex"</span><span class="punctuation">:</span> <span class="string">"1"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-6-2-表分析"><a href="#3-6-2-表分析" class="headerlink" title="3.6.2 表分析"></a>3.6.2 表分析</h4><p>建表SQL及初始化数据见:SGBlog\资源\SQL\sys_user.sql</p><p>顺便生成下User和UserMapper后面会用到</p><h4 id="3-6-3-思路分析"><a href="#3-6-3-思路分析" class="headerlink" title="3.6.3 思路分析"></a>3.6.3 思路分析</h4><p>登录</p><p>①自定义登录接口 </p><p>调用ProviderManager的方法进行认证 如果认证通过生成jwt</p><p>把用户信息存入redis中</p><p>②自定义UserDetailsService </p><p>在这个实现类中去查询数据库</p><p>注意配置passwordEncoder为BCryptPasswordEncoder</p><p>校验:</p><p>①定义Jwt认证过滤器</p><p>获取token</p><p>解析token获取其中的userid</p><p>从redis中获取用户信息</p><p>存入SecurityContextHolder</p><h4 id="3-6-4-准备工作"><a href="#3-6-4-准备工作" class="headerlink" title="3.6.4 准备工作"></a>3.6.4 准备工作</h4><p>①添加依赖</p><p>注意放开Security依赖的注释</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></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--redis依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-data-redis<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="comment"><!--fastjson依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>fastjson<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.2.33<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="comment"><!--jwt依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.jsonwebtoken<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jjwt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>0.9.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><p>②工具类和相关配置类</p><p>见 :SGBlog\资源\登录功能所需资源</p><h4 id="3-6-5-登录接口代码实现"><a href="#3-6-5-登录接口代码实现" class="headerlink" title="3.6.5 登录接口代码实现"></a>3.6.5 登录接口代码实现</h4><h5 id="BlogLoginController"><a href="#BlogLoginController" class="headerlink" title="BlogLoginController"></a>BlogLoginController</h5><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></pre></td><td class="code"><pre><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_">BlogLoginController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> BlogLoginService blogLoginService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping("/login")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">login</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">return</span> blogLoginService.login(user);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="BlogLoginService"><a href="#BlogLoginService" class="headerlink" title="BlogLoginService"></a>BlogLoginService</h5><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">BlogLoginService</span> {</span><br><span class="line"> ResponseResult <span class="title function_">login</span><span class="params">(User user)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="SecurityConfig"><a href="#SecurityConfig" class="headerlink" title="SecurityConfig"></a>SecurityConfig</h5><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></pre></td><td class="code"><pre><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_">SecurityConfig</span> <span class="keyword">extends</span> <span class="title class_">WebSecurityConfigurerAdapter</span> {</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> PasswordEncoder <span class="title function_">passwordEncoder</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BCryptPasswordEncoder</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/login"</span>).anonymous()</span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> AuthenticationManager <span class="title function_">authenticationManagerBean</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">super</span>.authenticationManagerBean();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="BlogLoginServiceImpl"><a href="#BlogLoginServiceImpl" class="headerlink" title="BlogLoginServiceImpl"></a>BlogLoginServiceImpl</h5><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BlogLoginServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">BlogLoginService</span> {</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> AuthenticationManager authenticationManager;</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> RedisCache redisCache;</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_">login</span><span class="params">(User user)</span> {</span><br><span class="line"> <span class="type">UsernamePasswordAuthenticationToken</span> <span class="variable">authenticationToken</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UsernamePasswordAuthenticationToken</span>(user.getUserName(),user.getPassword());</span><br><span class="line"> <span class="type">Authentication</span> <span class="variable">authenticate</span> <span class="operator">=</span> authenticationManager.authenticate(authenticationToken);</span><br><span class="line"> <span class="comment">//判断是否认证通过</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(authenticate)){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"用户名或密码错误"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//获取userid 生成token</span></span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> (LoginUser) authenticate.getPrincipal();</span><br><span class="line"> <span class="type">String</span> <span class="variable">userId</span> <span class="operator">=</span> loginUser.getUser().getId().toString();</span><br><span class="line"> <span class="type">String</span> <span class="variable">jwt</span> <span class="operator">=</span> JwtUtil.createJWT(userId);</span><br><span class="line"> <span class="comment">//把用户信息存入redis</span></span><br><span class="line"> redisCache.setCacheObject(<span class="string">"bloglogin:"</span>+userId,loginUser);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//把token和userinfo封装 返回</span></span><br><span class="line"> <span class="comment">//把User转换成UserInfoVo</span></span><br><span class="line"> <span class="type">UserInfoVo</span> <span class="variable">userInfoVo</span> <span class="operator">=</span> BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);</span><br><span class="line"> <span class="type">BlogUserLoginVo</span> <span class="variable">vo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BlogUserLoginVo</span>(jwt,userInfoVo);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(vo);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="UserDetailServiceImpl"><a href="#UserDetailServiceImpl" class="headerlink" title="UserDetailServiceImpl"></a>UserDetailServiceImpl</h5><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="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDetailsServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UserDetailsService</span> {</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> UserMapper userMapper;</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> UserDetails <span class="title function_">loadUserByUsername</span><span class="params">(String username)</span> <span class="keyword">throws</span> UsernameNotFoundException {</span><br><span class="line"> <span class="comment">//根据用户名查询用户信息</span></span><br><span class="line"> LambdaQueryWrapper<User> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> queryWrapper.eq(User::getUserName,username);</span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> userMapper.selectOne(queryWrapper);</span><br><span class="line"> <span class="comment">//判断是否查到用户 如果没查到抛出异常</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(user)){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"用户不存在"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//返回用户信息</span></span><br><span class="line"> <span class="comment">// TODO 查询权限信息封装</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">LoginUser</span>(user);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="LoginUser"><a href="#LoginUser" class="headerlink" title="LoginUser"></a>LoginUser</h5><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoginUser</span> <span class="keyword">implements</span> <span class="title class_">UserDetails</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> User user;</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> Collection<? <span class="keyword">extends</span> <span class="title class_">GrantedAuthority</span>> getAuthorities() {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</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> String <span class="title function_">getPassword</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> user.getPassword();</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> String <span class="title function_">getUsername</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> user.getUserName();</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> <span class="type">boolean</span> <span class="title function_">isAccountNonExpired</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</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> <span class="type">boolean</span> <span class="title function_">isAccountNonLocked</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</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> <span class="type">boolean</span> <span class="title function_">isCredentialsNonExpired</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</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> <span class="type">boolean</span> <span class="title function_">isEnabled</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="BlogUserLoginVo"><a href="#BlogUserLoginVo" class="headerlink" title="BlogUserLoginVo"></a>BlogUserLoginVo</h5><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="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BlogUserLoginVo</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String token;</span><br><span class="line"> <span class="keyword">private</span> UserInfoVo userInfo;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="UserInfoVo"><a href="#UserInfoVo" class="headerlink" title="UserInfoVo"></a>UserInfoVo</h5><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Accessors(chain = true)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserInfoVo</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="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"> * 昵称</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String nickName;</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> String avatar;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String sex;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String email;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="3-6-6-登录校验过滤器代码实现"><a href="#3-6-6-登录校验过滤器代码实现" class="headerlink" title="3.6.6 登录校验过滤器代码实现"></a>3.6.6 登录校验过滤器代码实现</h4><h5 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h5><p>①定义Jwt认证过滤器</p><p>获取token</p><p>解析token获取其中的userid</p><p>从redis中获取用户信息</p><p>存入SecurityContextHolder</p><h5 id="JwtAuthenticationTokenFilter"><a href="#JwtAuthenticationTokenFilter" class="headerlink" title="JwtAuthenticationTokenFilter"></a>JwtAuthenticationTokenFilter</h5><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></pre></td><td class="code"><pre><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_">JwtAuthenticationTokenFilter</span> <span class="keyword">extends</span> <span class="title class_">OncePerRequestFilter</span> {</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> RedisCache redisCache;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doFilterInternal</span><span class="params">(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span> <span class="keyword">throws</span> ServletException, IOException {</span><br><span class="line"> <span class="comment">//获取请求头中的token</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> request.getHeader(<span class="string">"token"</span>);</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(token)){</span><br><span class="line"> <span class="comment">//说明该接口不需要登录 直接放行</span></span><br><span class="line"> filterChain.doFilter(request, response);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//解析获取userid</span></span><br><span class="line"> <span class="type">Claims</span> <span class="variable">claims</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> claims = JwtUtil.parseJWT(token);</span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="comment">//token超时 token非法</span></span><br><span class="line"> <span class="comment">//响应告诉前端需要重新登录</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">String</span> <span class="variable">userId</span> <span class="operator">=</span> claims.getSubject();</span><br><span class="line"> <span class="comment">//从redis中获取用户信息</span></span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> redisCache.getCacheObject(<span class="string">"bloglogin:"</span> + userId);</span><br><span class="line"> <span class="comment">//如果获取不到</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(loginUser)){</span><br><span class="line"> <span class="comment">//说明登录过期 提示重新登录</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//存入SecurityContextHolder</span></span><br><span class="line"> <span class="type">UsernamePasswordAuthenticationToken</span> <span class="variable">authenticationToken</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UsernamePasswordAuthenticationToken</span>(loginUser,<span class="literal">null</span>,<span class="literal">null</span>);</span><br><span class="line"> SecurityContextHolder.getContext().setAuthentication(authenticationToken);</span><br><span class="line"></span><br><span class="line"> filterChain.doFilter(request, response);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="SecurityConfig-1"><a href="#SecurityConfig-1" class="headerlink" title="SecurityConfig"></a>SecurityConfig</h5><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></pre></td><td class="code"><pre><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_">SecurityConfig</span> <span class="keyword">extends</span> <span class="title class_">WebSecurityConfigurerAdapter</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> AuthenticationManager <span class="title function_">authenticationManagerBean</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">super</span>.authenticationManagerBean();</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> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/login"</span>).anonymous()</span><br><span class="line"> <span class="comment">//jwt过滤器测试用,如果测试没有问题吧这里删除了</span></span><br><span class="line"> .antMatchers(<span class="string">"/link/getAllLink"</span>).authenticated()</span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</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> PasswordEncoder <span class="title function_">passwordEncoder</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BCryptPasswordEncoder</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-7-认证授权失败处理"><a href="#3-7-认证授权失败处理" class="headerlink" title="3.7 认证授权失败处理"></a>3.7 认证授权失败处理</h3><p>目前我们的项目在认证出错或者权限不足的时候响应回来的Json是Security的异常处理结果。但是这个响应的格式肯定是不符合我们项目的接口规范的。所以需要自定义异常处理。</p><p>AuthenticationEntryPoint 认证失败处理器</p><p>AccessDeniedHandler 授权失败处理器</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="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthenticationEntryPointImpl</span> <span class="keyword">implements</span> <span class="title class_">AuthenticationEntryPoint</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> <span class="keyword">void</span> <span class="title function_">commence</span><span class="params">(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)</span> <span class="keyword">throws</span> IOException, ServletException {</span><br><span class="line"> authException.printStackTrace();</span><br><span class="line"> <span class="comment">//InsufficientAuthenticationException</span></span><br><span class="line"> <span class="comment">//BadCredentialsException</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">if</span>(authException <span class="keyword">instanceof</span> BadCredentialsException){</span><br><span class="line"> result = ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(),authException.getMessage());</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(authException <span class="keyword">instanceof</span> InsufficientAuthenticationException){</span><br><span class="line"> result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),<span class="string">"认证或授权失败"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//响应给前端</span></span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><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_">AccessDeniedHandlerImpl</span> <span class="keyword">implements</span> <span class="title class_">AccessDeniedHandler</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_">handle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)</span> <span class="keyword">throws</span> IOException, ServletException {</span><br><span class="line"> accessDeniedException.printStackTrace();</span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);</span><br><span class="line"> <span class="comment">//响应给前端</span></span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>配置Security异常处理器</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></pre></td><td class="code"><pre><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_">SecurityConfig</span> <span class="keyword">extends</span> <span class="title class_">WebSecurityConfigurerAdapter</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> AuthenticationManager <span class="title function_">authenticationManagerBean</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">super</span>.authenticationManagerBean();</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> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> AuthenticationEntryPoint authenticationEntryPoint;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> AccessDeniedHandler accessDeniedHandler;</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">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/login"</span>).anonymous()</span><br><span class="line"> <span class="comment">//jwt过滤器测试用,如果测试没有问题吧这里删除了</span></span><br><span class="line"> .antMatchers(<span class="string">"/link/getAllLink"</span>).authenticated()</span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//配置异常处理器</span></span><br><span class="line"> http.exceptionHandling()</span><br><span class="line"> .authenticationEntryPoint(authenticationEntryPoint)</span><br><span class="line"> .accessDeniedHandler(accessDeniedHandler);</span><br><span class="line"></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</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> PasswordEncoder <span class="title function_">passwordEncoder</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BCryptPasswordEncoder</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-8-统一异常处理"><a href="#3-8-统一异常处理" class="headerlink" title="3.8 统一异常处理"></a>3.8 统一异常处理</h3><p>实际我们在开发过程中可能需要做很多的判断校验,如果出现了非法情况我们是期望响应对应的提示的。但是如果我们每次都自己手动去处理就会非常麻烦。我们可以选择直接抛出异常的方式,然后对异常进行统一处理。把异常中的信息封装成ResponseResult响应给前端。</p><p></p><p>SystemException</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></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> 三更 B站: https://space.bilibili.com/663528522</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_">SystemException</span> <span class="keyword">extends</span> <span class="title class_">RuntimeException</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> code;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String msg;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getCode</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> code;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getMsg</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> msg;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">SystemException</span><span class="params">(AppHttpCodeEnum httpCodeEnum)</span> {</span><br><span class="line"> <span class="built_in">super</span>(httpCodeEnum.getMsg());</span><br><span class="line"> <span class="built_in">this</span>.code = httpCodeEnum.getCode();</span><br><span class="line"> <span class="built_in">this</span>.msg = httpCodeEnum.getMsg();</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>GlobalExceptionHandler</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">@RestControllerAdvice</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_">GlobalExceptionHandler</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ExceptionHandler(SystemException.class)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">systemExceptionHandler</span><span class="params">(SystemException e)</span>{</span><br><span class="line"> <span class="comment">//打印异常信息</span></span><br><span class="line"> log.error(<span class="string">"出现了异常! {}"</span>,e);</span><br><span class="line"> <span class="comment">//从异常对象中获取提示信息封装返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(e.getCode(),e.getMsg());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@ExceptionHandler(Exception.class)</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">exceptionHandler</span><span class="params">(Exception e)</span>{</span><br><span class="line"> <span class="comment">//打印异常信息</span></span><br><span class="line"> log.error(<span class="string">"出现了异常! {}"</span>,e);</span><br><span class="line"> <span class="comment">//从异常对象中获取提示信息封装返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage());</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-9-退出登录接口"><a href="#3-9-退出登录接口" class="headerlink" title="3.9 退出登录接口"></a>3.9 退出登录接口</h3><h4 id="3-9-1-接口设计"><a href="#3-9-1-接口设计" class="headerlink" title="3.9.1 接口设计"></a>3.9.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/logout</td><td>需要token请求头</td></tr></tbody></table><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">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-9-2-代码实现"><a href="#3-9-2-代码实现" class="headerlink" title="3.9.2 代码实现"></a>3.9.2 代码实现</h4><p>要实现的操作:</p><p>删除redis中的用户信息</p><p>BlogLoginController</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping("/logout")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">logout</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> blogLoginService.logout();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>BlogLoginService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">logout</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><p>BlogLoginServiceImpl</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></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_">logout</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//获取token 解析获取userid</span></span><br><span class="line"> <span class="type">Authentication</span> <span class="variable">authentication</span> <span class="operator">=</span> SecurityContextHolder.getContext().getAuthentication();</span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> (LoginUser) authentication.getPrincipal();</span><br><span class="line"> <span class="comment">//获取userid</span></span><br><span class="line"> <span class="type">Long</span> <span class="variable">userId</span> <span class="operator">=</span> loginUser.getUser().getId();</span><br><span class="line"> <span class="comment">//删除redis中的用户信息</span></span><br><span class="line"> redisCache.deleteObject(<span class="string">"bloglogin:"</span>+userId);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SecurityConfig</p><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">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/login"</span>).anonymous()</span><br><span class="line"> <span class="comment">//注销接口需要认证才能访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/logout"</span>).authenticated()</span><br><span class="line"> <span class="comment">//jwt过滤器测试用,如果测试没有问题吧这里删除了</span></span><br><span class="line"> .antMatchers(<span class="string">"/link/getAllLink"</span>).authenticated()</span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//配置异常处理器</span></span><br><span class="line"> http.exceptionHandling()</span><br><span class="line"> .authenticationEntryPoint(authenticationEntryPoint)</span><br><span class="line"> .accessDeniedHandler(accessDeniedHandler);</span><br><span class="line"><span class="comment">//关闭默认的注销功能</span></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="3-10-查询评论列表接口"><a href="#3-10-查询评论列表接口" class="headerlink" title="3.10 查询评论列表接口"></a>3.10 查询评论列表接口</h3><h4 id="3-10-1-需求"><a href="#3-10-1-需求" class="headerlink" title="3.10.1 需求"></a>3.10.1 需求</h4><p>文章详情页面要展示这篇文章下的评论列表。</p><p>效果如下:</p><p><img src="/post/0/image-20220208214106296.png" alt="image-20220208214106296"></p><h4 id="3-10-2-评论表分析"><a href="#3-10-2-评论表分析" class="headerlink" title="3.10.2 评论表分析"></a>3.10.2 评论表分析</h4><p>通过需求去分析需要有哪些字段。</p><p>建表SQL及初始化数据见:SGBlog\资源\SQL\sg_comment.sql</p><p><strong>顺便生成下对应的代码</strong></p><h4 id="3-10-3-接口设计"><a href="#3-10-3-接口设计" class="headerlink" title="3.10.3 接口设计"></a>3.10.3 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/comment/commentList</td><td>不需要token请求头</td></tr></tbody></table><p>Query格式请求参数:</p><p>articleId:文章id</p><p>pageNum: 页码</p><p>pageSize: 每页条数</p><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><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"rows"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"articleId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"children"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"articleId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span> <span class="string">"你说啥?"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createBy"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createTime"</span><span class="punctuation">:</span> <span class="string">"2022-01-30 10:06:21"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"20"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"rootId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserName"</span><span class="punctuation">:</span> <span class="string">"sg333"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"username"</span><span class="punctuation">:</span> <span class="string">"sg333"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span> <span class="string">"asS"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createBy"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createTime"</span><span class="punctuation">:</span> <span class="string">"2022-01-29 07:59:22"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"rootId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"username"</span><span class="punctuation">:</span> <span class="string">"sg333"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"total"</span><span class="punctuation">:</span> <span class="string">"15"</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-10-4-代码实现"><a href="#3-10-4-代码实现" class="headerlink" title="3.10.4 代码实现"></a>3.10.4 代码实现</h4><h5 id="3-10-4-1-不考虑子评论"><a href="#3-10-4-1-不考虑子评论" class="headerlink" title="3.10.4.1 不考虑子评论"></a>3.10.4.1 不考虑子评论</h5><p>CommentController</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="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/comment")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentController</span> {</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> CommentService commentService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/commentList")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">commentList</span><span class="params">(Long articleId,Integer pageNum,Integer pageSize)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.commentList(articleId,pageNum,pageSize);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>CommentService</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">public</span> <span class="keyword">interface</span> <span class="title class_">CommentService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Comment> {</span><br><span class="line"></span><br><span class="line"> ResponseResult <span class="title function_">commentList</span><span class="params">(Long articleId, Integer pageNum, Integer pageSize)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>CommentServiceImpl</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="meta">@Service("commentService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><CommentMapper, Comment> <span class="keyword">implements</span> <span class="title class_">CommentService</span> {</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> UserService userService;</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_">commentList</span><span class="params">(Long articleId, Integer pageNum, Integer pageSize)</span> {</span><br><span class="line"> <span class="comment">//查询对应文章的根评论</span></span><br><span class="line"> LambdaQueryWrapper<Comment> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//对articleId进行判断</span></span><br><span class="line"> queryWrapper.eq(Comment::getArticleId,articleId);</span><br><span class="line"> <span class="comment">//根评论 rootId为-1</span></span><br><span class="line"> queryWrapper.eq(Comment::getRootId,-<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//分页查询</span></span><br><span class="line"> Page<Comment> page = <span class="keyword">new</span> <span class="title class_">Page</span>(pageNum,pageSize);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<CommentVo> commentVoList = toCommentVoList(page.getRecords());</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(<span class="keyword">new</span> <span class="title class_">PageVo</span>(commentVoList,page.getTotal()));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<CommentVo> <span class="title function_">toCommentVoList</span><span class="params">(List<Comment> list)</span>{</span><br><span class="line"> List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);</span><br><span class="line"> <span class="comment">//遍历vo集合</span></span><br><span class="line"> <span class="keyword">for</span> (CommentVo commentVo : commentVos) {</span><br><span class="line"> <span class="comment">//通过creatyBy查询用户的昵称并赋值</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">nickName</span> <span class="operator">=</span> userService.getById(commentVo.getCreateBy()).getNickName();</span><br><span class="line"> commentVo.setUsername(nickName);</span><br><span class="line"> <span class="comment">//通过toCommentUserId查询用户的昵称并赋值</span></span><br><span class="line"> <span class="comment">//如果toCommentUserId不为-1才进行查询</span></span><br><span class="line"> <span class="keyword">if</span>(commentVo.getToCommentUserId()!=-<span class="number">1</span>){</span><br><span class="line"> <span class="type">String</span> <span class="variable">toCommentUserName</span> <span class="operator">=</span> userService.getById(commentVo.getToCommentUserId()).getNickName();</span><br><span class="line"> commentVo.setToCommentUserName(toCommentUserName);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> commentVos;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>CommentVo</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="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentVo</span> {</span><br><span class="line"> <span class="keyword">private</span> Long id;</span><br><span class="line"> <span class="comment">//文章id</span></span><br><span class="line"> <span class="keyword">private</span> Long articleId;</span><br><span class="line"> <span class="comment">//根评论id</span></span><br><span class="line"> <span class="keyword">private</span> Long rootId;</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">//所回复的目标评论的userid</span></span><br><span class="line"> <span class="keyword">private</span> Long toCommentUserId;</span><br><span class="line"> <span class="keyword">private</span> String toCommentUserName;</span><br><span class="line"> <span class="comment">//回复目标评论id</span></span><br><span class="line"> <span class="keyword">private</span> Long toCommentId;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Long createBy;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="3-10-4-2-查询子评论"><a href="#3-10-4-2-查询子评论" class="headerlink" title="3.10.4.2 查询子评论"></a>3.10.4.2 查询子评论</h5><p>CommentVo在之前的基础上增加了 private List<CommentVo> children;</CommentVo></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></pre></td><td class="code"><pre><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">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentVo</span> {</span><br><span class="line"> <span class="keyword">private</span> Long id;</span><br><span class="line"> <span class="comment">//文章id</span></span><br><span class="line"> <span class="keyword">private</span> Long articleId;</span><br><span class="line"> <span class="comment">//根评论id</span></span><br><span class="line"> <span class="keyword">private</span> Long rootId;</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">//所回复的目标评论的userid</span></span><br><span class="line"> <span class="keyword">private</span> Long toCommentUserId;</span><br><span class="line"> <span class="keyword">private</span> String toCommentUserName;</span><br><span class="line"> <span class="comment">//回复目标评论id</span></span><br><span class="line"> <span class="keyword">private</span> Long toCommentId;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Long createBy;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<CommentVo> children;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>CommentServiceImpl</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="meta">@Service("commentService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><CommentMapper, Comment> <span class="keyword">implements</span> <span class="title class_">CommentService</span> {</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> UserService userService;</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_">commentList</span><span class="params">(Long articleId, Integer pageNum, Integer pageSize)</span> {</span><br><span class="line"> <span class="comment">//查询对应文章的根评论</span></span><br><span class="line"> LambdaQueryWrapper<Comment> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//对articleId进行判断</span></span><br><span class="line"> queryWrapper.eq(Comment::getArticleId,articleId);</span><br><span class="line"> <span class="comment">//根评论 rootId为-1</span></span><br><span class="line"> queryWrapper.eq(Comment::getRootId,-<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//分页查询</span></span><br><span class="line"> Page<Comment> page = <span class="keyword">new</span> <span class="title class_">Page</span>(pageNum,pageSize);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<CommentVo> commentVoList = toCommentVoList(page.getRecords());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查询所有根评论对应的子评论集合,并且赋值给对应的属性</span></span><br><span class="line"> <span class="keyword">for</span> (CommentVo commentVo : commentVoList) {</span><br><span class="line"> <span class="comment">//查询对应的子评论</span></span><br><span class="line"> List<CommentVo> children = getChildren(commentVo.getId());</span><br><span class="line"> <span class="comment">//赋值</span></span><br><span class="line"> commentVo.setChildren(children);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(<span class="keyword">new</span> <span class="title class_">PageVo</span>(commentVoList,page.getTotal()));</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"> * 根据根评论的id查询所对应的子评论的集合</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 class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> List<CommentVo> <span class="title function_">getChildren</span><span class="params">(Long id)</span> {</span><br><span class="line"></span><br><span class="line"> LambdaQueryWrapper<Comment> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> queryWrapper.eq(Comment::getRootId,id);</span><br><span class="line"> queryWrapper.orderByAsc(Comment::getCreateTime);</span><br><span class="line"> List<Comment> comments = list(queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<CommentVo> commentVos = toCommentVoList(comments);</span><br><span class="line"> <span class="keyword">return</span> commentVos;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<CommentVo> <span class="title function_">toCommentVoList</span><span class="params">(List<Comment> list)</span>{</span><br><span class="line"> List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);</span><br><span class="line"> <span class="comment">//遍历vo集合</span></span><br><span class="line"> <span class="keyword">for</span> (CommentVo commentVo : commentVos) {</span><br><span class="line"> <span class="comment">//通过creatyBy查询用户的昵称并赋值</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">nickName</span> <span class="operator">=</span> userService.getById(commentVo.getCreateBy()).getNickName();</span><br><span class="line"> commentVo.setUsername(nickName);</span><br><span class="line"> <span class="comment">//通过toCommentUserId查询用户的昵称并赋值</span></span><br><span class="line"> <span class="comment">//如果toCommentUserId不为-1才进行查询</span></span><br><span class="line"> <span class="keyword">if</span>(commentVo.getToCommentUserId()!=-<span class="number">1</span>){</span><br><span class="line"> <span class="type">String</span> <span class="variable">toCommentUserName</span> <span class="operator">=</span> userService.getById(commentVo.getToCommentUserId()).getNickName();</span><br><span class="line"> commentVo.setToCommentUserName(toCommentUserName);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> commentVos;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-11-发表评论接口"><a href="#3-11-发表评论接口" class="headerlink" title="3.11 发表评论接口"></a>3.11 发表评论接口</h3><h4 id="3-11-1-需求"><a href="#3-11-1-需求" class="headerlink" title="3.11.1 需求"></a>3.11.1 需求</h4><p>用户登录后可以对文章发表评论,也可以对评论进行回复。</p><p>用户登录后也可以在友链页面进行评论。</p><h4 id="3-11-2-接口设计"><a href="#3-11-2-接口设计" class="headerlink" title="3.11.2 接口设计"></a>3.11.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/comment</td><td>需要token头</td></tr></tbody></table><h5 id="请求体:"><a href="#请求体:" class="headerlink" title="请求体:"></a>请求体:</h5><p>回复了文章:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span><span class="attr">"articleId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span><span class="attr">"type"</span><span class="punctuation">:</span><span class="number">0</span><span class="punctuation">,</span><span class="attr">"rootId"</span><span class="punctuation">:</span><span class="number">-1</span><span class="punctuation">,</span><span class="attr">"toCommentId"</span><span class="punctuation">:</span><span class="number">-1</span><span class="punctuation">,</span><span class="attr">"toCommentUserId"</span><span class="punctuation">:</span><span class="number">-1</span><span class="punctuation">,</span><span class="attr">"content"</span><span class="punctuation">:</span><span class="string">"评论了文章"</span><span class="punctuation">}</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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span><span class="attr">"articleId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span><span class="attr">"type"</span><span class="punctuation">:</span><span class="number">0</span><span class="punctuation">,</span><span class="attr">"rootId"</span><span class="punctuation">:</span><span class="string">"3"</span><span class="punctuation">,</span><span class="attr">"toCommentId"</span><span class="punctuation">:</span><span class="string">"3"</span><span class="punctuation">,</span><span class="attr">"toCommentUserId"</span><span class="punctuation">:</span><span class="string">"1"</span><span class="punctuation">,</span><span class="attr">"content"</span><span class="punctuation">:</span><span class="string">"回复了某条评论"</span><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><p>如果是友链评论,type应该为1</p><h5 id="响应格式:"><a href="#响应格式:" class="headerlink" title="响应格式:"></a>响应格式:</h5><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"><span class="string">"code"</span>:<span class="number">200</span>,</span><br><span class="line"><span class="string">"msg"</span>:<span class="string">"操作成功"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3-11-3-代码实现"><a href="#3-11-3-代码实现" class="headerlink" title="3.11.3 代码实现"></a>3.11.3 代码实现</h4><p>CommentController</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">addComment</span><span class="params">(<span class="meta">@RequestBody</span> Comment comment)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.addComment(comment);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>CommentService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">addComment</span><span class="params">(Comment comment)</span>;</span><br></pre></td></tr></table></figure><p>CommentServiceImpl</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">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">addComment</span><span class="params">(Comment comment)</span> {</span><br><span class="line"> <span class="comment">//评论内容不能为空</span></span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(comment.getContent())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.CONTENT_NOT_NULL);</span><br><span class="line"> }</span><br><span class="line"> save(comment);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SecurityUtils</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="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 三更 B站: https://space.bilibili.com/663528522</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_">SecurityUtils</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"> * 获取用户</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> LoginUser <span class="title function_">getLoginUser</span><span class="params">()</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> (LoginUser) getAuthentication().getPrincipal();</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"> * 获取Authentication</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> Authentication <span class="title function_">getAuthentication</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> SecurityContextHolder.getContext().getAuthentication();</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> Boolean <span class="title function_">isAdmin</span><span class="params">()</span>{</span><br><span class="line"> <span class="type">Long</span> <span class="variable">id</span> <span class="operator">=</span> getLoginUser().getUser().getId();</span><br><span class="line"> <span class="keyword">return</span> id != <span class="literal">null</span> && <span class="number">1L</span> == id;</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> Long <span class="title function_">getUserId</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> getLoginUser().getUser().getId();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>配置MP字段自动填充</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></pre></td><td class="code"><pre><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_">MyMetaObjectHandler</span> <span class="keyword">implements</span> <span class="title class_">MetaObjectHandler</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_">insertFill</span><span class="params">(MetaObject metaObject)</span> {</span><br><span class="line"> <span class="type">Long</span> <span class="variable">userId</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> userId = SecurityUtils.getUserId();</span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> userId = -<span class="number">1L</span>;<span class="comment">//表示是自己创建</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">"createTime"</span>, <span class="keyword">new</span> <span class="title class_">Date</span>(), metaObject);</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">"createBy"</span>,userId , metaObject);</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">"updateTime"</span>, <span class="keyword">new</span> <span class="title class_">Date</span>(), metaObject);</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">"updateBy"</span>, userId, metaObject);</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> <span class="keyword">void</span> <span class="title function_">updateFill</span><span class="params">(MetaObject metaObject)</span> {</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">"updateTime"</span>, <span class="keyword">new</span> <span class="title class_">Date</span>(), metaObject);</span><br><span class="line"> <span class="built_in">this</span>.setFieldValByName(<span class="string">" "</span>, SecurityUtils.getUserId(), metaObject);</span><br><span class="line"> }</span><br><span class="line">}</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></pre></td><td class="code"><pre><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(fill = FieldFill.INSERT)</span></span><br><span class="line"><span class="keyword">private</span> Long createBy;</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(fill = FieldFill.INSERT)</span></span><br><span class="line"><span class="keyword">private</span> Date createTime;</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(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line"><span class="keyword">private</span> Long updateBy;</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(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line"><span class="keyword">private</span> Date updateTime;</span><br></pre></td></tr></table></figure><h3 id="3-12-友联评论列表"><a href="#3-12-友联评论列表" class="headerlink" title="3.12 友联评论列表"></a>3.12 友联评论列表</h3><h4 id="3-12-1-需求"><a href="#3-12-1-需求" class="headerlink" title="3.12.1 需求"></a>3.12.1 需求</h4><p>友链页面也需要查询对应的评论列表。</p><h4 id="3-12-2-接口设计"><a href="#3-12-2-接口设计" class="headerlink" title="3.12.2 接口设计"></a>3.12.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/comment/linkCommentList</td><td>不需要token请求头</td></tr></tbody></table><p>Query格式请求参数:</p><p>pageNum: 页码</p><p>pageSize: 每页条数</p><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><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"rows"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"articleId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"children"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"articleId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span> <span class="string">"回复友链评论3"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createBy"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createTime"</span><span class="punctuation">:</span> <span class="string">"2022-01-30 10:08:50"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"23"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"rootId"</span><span class="punctuation">:</span> <span class="string">"22"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentId"</span><span class="punctuation">:</span> <span class="string">"22"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserId"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserName"</span><span class="punctuation">:</span> <span class="string">"sg333"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"username"</span><span class="punctuation">:</span> <span class="string">"sg333"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span> <span class="string">"友链评论2"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createBy"</span><span class="punctuation">:</span> <span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"createTime"</span><span class="punctuation">:</span> <span class="string">"2022-01-30 10:08:28"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span> <span class="string">"22"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"rootId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"toCommentUserId"</span><span class="punctuation">:</span> <span class="string">"-1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"username"</span><span class="punctuation">:</span> <span class="string">"sg333"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"total"</span><span class="punctuation">:</span> <span class="string">"1"</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-12-3-代码实现"><a href="#3-12-3-代码实现" class="headerlink" title="3.12.3 代码实现"></a>3.12.3 代码实现</h4><p>CommentController 修改了之前的文章评论列表接口,并且增加了新的友联评论接口</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="meta">@GetMapping("/commentList")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">commentList</span><span class="params">(Long articleId,Integer pageNum,Integer pageSize)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.commentList(SystemConstants.ARTICLE_COMMENT,articleId,pageNum,pageSize);</span><br><span class="line">} </span><br><span class="line"><span class="meta">@GetMapping("/linkCommentList")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">linkCommentList</span><span class="params">(Integer pageNum,Integer pageSize)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.commentList(SystemConstants.LINK_COMMENT,<span class="literal">null</span>,pageNum,pageSize);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SystemConstants增加了两个常量</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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">ARTICLE_COMMENT</span> <span class="operator">=</span> <span class="string">"0"</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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">LINK_COMMENT</span> <span class="operator">=</span> <span class="string">"1"</span>;</span><br></pre></td></tr></table></figure><p>CommentService修改了commentList方法,增加了一个参数commentType</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">commentList</span><span class="params">(String commentType, Long articleId, Integer pageNum, Integer pageSize)</span>;</span><br></pre></td></tr></table></figure><p>CommentServiceImpl修改commentList方法的代码,必须commentType为0的时候才增加articleId的判断,并且增加了一个评论类型的添加。</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></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_">commentList</span><span class="params">(String commentType, Long articleId, Integer pageNum, Integer pageSize)</span> {</span><br><span class="line"> <span class="comment">//查询对应文章的根评论</span></span><br><span class="line"> LambdaQueryWrapper<Comment> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> <span class="comment">//对articleId进行判断</span></span><br><span class="line"> queryWrapper.eq(SystemConstants.ARTICLE_COMMENT.equals(commentType),Comment::getArticleId,articleId);</span><br><span class="line"> <span class="comment">//根评论 rootId为-1</span></span><br><span class="line"> queryWrapper.eq(Comment::getRootId,-<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//评论类型</span></span><br><span class="line"> queryWrapper.eq(Comment::getType,commentType);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//分页查询</span></span><br><span class="line"> Page<Comment> page = <span class="keyword">new</span> <span class="title class_">Page</span>(pageNum,pageSize);</span><br><span class="line"> page(page,queryWrapper);</span><br><span class="line"></span><br><span class="line"> List<CommentVo> commentVoList = toCommentVoList(page.getRecords());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查询所有根评论对应的子评论集合,并且赋值给对应的属性</span></span><br><span class="line"> <span class="keyword">for</span> (CommentVo commentVo : commentVoList) {</span><br><span class="line"> <span class="comment">//查询对应的子评论</span></span><br><span class="line"> List<CommentVo> children = getChildren(commentVo.getId());</span><br><span class="line"> <span class="comment">//赋值</span></span><br><span class="line"> commentVo.setChildren(children);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(<span class="keyword">new</span> <span class="title class_">PageVo</span>(commentVoList,page.getTotal()));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-13-个人信息查询接口"><a href="#3-13-个人信息查询接口" class="headerlink" title="3.13 个人信息查询接口"></a>3.13 个人信息查询接口</h3><h4 id="3-13-1-需求"><a href="#3-13-1-需求" class="headerlink" title="3.13.1 需求"></a>3.13.1 需求</h4><p>进入个人中心的时候需要能够查看当前用户信息</p><h4 id="3-13-2-接口设计"><a href="#3-13-2-接口设计" class="headerlink" title="3.13.2 接口设计"></a>3.13.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/user/userInfo</td><td>需要token请求头</td></tr></tbody></table><p>不需要参数</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"avatar"</span><span class="punctuation">:</span><span class="string">"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2F3bf9c263bc0f2ac5c3a7feb9e218d07475573ec8.gi"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"email"</span><span class="punctuation">:</span><span class="string">"23412332@qq.com"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"nickName"</span><span class="punctuation">:</span><span class="string">"sg333"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"sex"</span><span class="punctuation">:</span><span class="string">"1"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-13-3-代码实现"><a href="#3-13-3-代码实现" class="headerlink" title="3.13.3 代码实现"></a>3.13.3 代码实现</h4><p>UserController</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="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/user")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> {</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> UserService userService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/userInfo")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">userInfo</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> userService.userInfo();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>UserService增加方法定义</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="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><User> {</span><br><span class="line"></span><br><span class="line"> ResponseResult <span class="title function_">userInfo</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>UserServiceImpl实现userInfo方法</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="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">userInfo</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//获取当前用户id</span></span><br><span class="line"> <span class="type">Long</span> <span class="variable">userId</span> <span class="operator">=</span> SecurityUtils.getUserId();</span><br><span class="line"> <span class="comment">//根据用户id查询用户信息</span></span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> getById(userId);</span><br><span class="line"> <span class="comment">//封装成UserInfoVo</span></span><br><span class="line"> <span class="type">UserInfoVo</span> <span class="variable">vo</span> <span class="operator">=</span> BeanCopyUtils.copyBean(user,UserInfoVo.class);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(vo);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SecurityConfig配置该接口必须认证后才能访问</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">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/login"</span>).anonymous()</span><br><span class="line"> <span class="comment">//注销接口需要认证才能访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/logout"</span>).authenticated()</span><br><span class="line"> <span class="comment">//个人信息接口必须登录后才能访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/user/userInfo"</span>).authenticated()</span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//配置异常处理器</span></span><br><span class="line"> http.exceptionHandling()</span><br><span class="line"> .authenticationEntryPoint(authenticationEntryPoint)</span><br><span class="line"> .accessDeniedHandler(accessDeniedHandler);</span><br><span class="line"> <span class="comment">//关闭默认的注销功能</span></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="3-14-头像上传接口"><a href="#3-14-头像上传接口" class="headerlink" title="3.14 头像上传接口"></a>3.14 头像上传接口</h3><h4 id="3-14-1-需求"><a href="#3-14-1-需求" class="headerlink" title="3.14.1 需求"></a>3.14.1 需求</h4><p>在个人中心点击编辑的时候可以上传头像图片。上传完头像后,可以用于更新个人信息接口。</p><h4 id="3-14-2-OSS"><a href="#3-14-2-OSS" class="headerlink" title="3.14.2 OSS"></a>3.14.2 OSS</h4><h5 id="3-14-2-1-为什么要使用OSS"><a href="#3-14-2-1-为什么要使用OSS" class="headerlink" title="3.14.2.1 为什么要使用OSS"></a>3.14.2.1 为什么要使用OSS</h5><p>因为如果把图片视频等文件上传到自己的应用的Web服务器,在读取图片的时候会占用比较多的资源。影响应用服务器的性能。</p><p>所以我们一般使用OSS(Object Storage Service对象存储服务)存储图片或视频。</p><h5 id="3-14-2-2-七牛云基本使用测试"><a href="#3-14-2-2-七牛云基本使用测试" class="headerlink" title="3.14.2.2 七牛云基本使用测试"></a>3.14.2.2 七牛云基本使用测试</h5><p><img src="/post/0/image-20220227224537701.png" alt="image-20220227224537701"></p><p><img src="/post/0/image-20220227224443813.png" alt="image-20220227224443813"></p><p>秘钥</p><p><img src="/post/0/image-20220228230512598.png" alt="image-20220228230512598"></p><p><img src="/post/0/image-20220228230933808.png" alt="image-20220228230933808"></p><h5 id="3-14-2-3-七牛云测试代码编写"><a href="#3-14-2-3-七牛云测试代码编写" class="headerlink" title="3.14.2.3 七牛云测试代码编写"></a>3.14.2.3 七牛云测试代码编写</h5><p>①添加依赖</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"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.qiniu<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>qiniu-java-sdk<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>[7.7.0, 7.7.99]<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><p>②复制修改案例代码</p><p>application.yml</p><figure class="highlight yml"><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="attr">oss:</span></span><br><span class="line"> <span class="attr">accessKey:</span> <span class="string">xxxx</span></span><br><span class="line"> <span class="attr">secretKey:</span> <span class="string">xxxx</span></span><br><span class="line"> <span class="attr">bucket:</span> <span class="string">sg-blog</span></span><br></pre></td></tr></table></figure><p>OSSTest.java</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="meta">@SpringBootTest</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = "oss")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OSSTest</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String accessKey;</span><br><span class="line"> <span class="keyword">private</span> String secretKey;</span><br><span class="line"> <span class="keyword">private</span> String bucket;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAccessKey</span><span class="params">(String accessKey)</span> {</span><br><span class="line"> <span class="built_in">this</span>.accessKey = accessKey;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setSecretKey</span><span class="params">(String secretKey)</span> {</span><br><span class="line"> <span class="built_in">this</span>.secretKey = secretKey;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setBucket</span><span class="params">(String bucket)</span> {</span><br><span class="line"> <span class="built_in">this</span>.bucket = bucket;</span><br><span class="line"> }</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_">testOss</span><span class="params">()</span>{</span><br><span class="line"> <span class="comment">//构造一个带指定 Region 对象的配置类</span></span><br><span class="line"> <span class="type">Configuration</span> <span class="variable">cfg</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Configuration</span>(Region.autoRegion());</span><br><span class="line"> <span class="comment">//...其他参数参考类注释</span></span><br><span class="line"></span><br><span class="line"> <span class="type">UploadManager</span> <span class="variable">uploadManager</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UploadManager</span>(cfg);</span><br><span class="line"> <span class="comment">//...生成上传凭证,然后准备上传</span></span><br><span class="line"><span class="comment">// String accessKey = "your access key";</span></span><br><span class="line"><span class="comment">// String secretKey = "your secret key";</span></span><br><span class="line"><span class="comment">// String bucket = "sg-blog";</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//默认不指定key的情况下,以文件内容的hash值作为文件名</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> <span class="string">"2022/sg.png"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"><span class="comment">// byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");</span></span><br><span class="line"><span class="comment">// ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="type">InputStream</span> <span class="variable">inputStream</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(<span class="string">"C:\\Users\\root\\Desktop\\Snipaste_2022-02-28_22-48-37.png"</span>);</span><br><span class="line"> <span class="type">Auth</span> <span class="variable">auth</span> <span class="operator">=</span> Auth.create(accessKey, secretKey);</span><br><span class="line"> <span class="type">String</span> <span class="variable">upToken</span> <span class="operator">=</span> auth.uploadToken(bucket);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">Response</span> <span class="variable">response</span> <span class="operator">=</span> uploadManager.put(inputStream,key,upToken,<span class="literal">null</span>, <span class="literal">null</span>);</span><br><span class="line"> <span class="comment">//解析上传成功的结果</span></span><br><span class="line"> <span class="type">DefaultPutRet</span> <span class="variable">putRet</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Gson</span>().fromJson(response.bodyString(), DefaultPutRet.class);</span><br><span class="line"> System.out.println(putRet.key);</span><br><span class="line"> System.out.println(putRet.hash);</span><br><span class="line"> } <span class="keyword">catch</span> (QiniuException ex) {</span><br><span class="line"> <span class="type">Response</span> <span class="variable">r</span> <span class="operator">=</span> ex.response;</span><br><span class="line"> System.err.println(r.toString());</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> System.err.println(r.bodyString());</span><br><span class="line"> } <span class="keyword">catch</span> (QiniuException ex2) {</span><br><span class="line"> <span class="comment">//ignore</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (Exception ex) {</span><br><span class="line"> <span class="comment">//ignore</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3-14-2-接口设计"><a href="#3-14-2-接口设计" class="headerlink" title="3.14.2 接口设计"></a>3.14.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/upload</td><td>需要token</td></tr></tbody></table><p>参数:</p><p>img,值为要上传的文件</p><p>请求头:</p><p>Content-Type :multipart/form-data;</p><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">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="string">"文件访问链接"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-14-3-代码实现"><a href="#3-14-3-代码实现" class="headerlink" title="3.14.3 代码实现"></a>3.14.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></pre></td><td class="code"><pre><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_">UploadController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> UploadService uploadService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping("/upload")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">uploadImg</span><span class="params">(MultipartFile img)</span>{</span><br><span class="line"> <span class="keyword">return</span> uploadService.uploadImg(img);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UploadService</span> {</span><br><span class="line"> ResponseResult <span class="title function_">uploadImg</span><span class="params">(MultipartFile img)</span>;</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = "oss")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OssUploadService</span> <span class="keyword">implements</span> <span class="title class_">UploadService</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_">uploadImg</span><span class="params">(MultipartFile img)</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="type">String</span> <span class="variable">originalFilename</span> <span class="operator">=</span> img.getOriginalFilename();</span><br><span class="line"> <span class="comment">//对原始文件名进行判断</span></span><br><span class="line"> <span class="keyword">if</span>(!originalFilename.endsWith(<span class="string">".png"</span>)){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.FILE_TYPE_ERROR);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//如果判断通过上传文件到OSS</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">filePath</span> <span class="operator">=</span> PathUtils.generateFilePath(originalFilename);</span><br><span class="line"> <span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> uploadOss(img,filePath);<span class="comment">// 2099/2/3/wqeqeqe.png</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(url);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String accessKey;</span><br><span class="line"> <span class="keyword">private</span> String secretKey;</span><br><span class="line"> <span class="keyword">private</span> String bucket;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String <span class="title function_">uploadOss</span><span class="params">(MultipartFile imgFile, String filePath)</span>{</span><br><span class="line"> <span class="comment">//构造一个带指定 Region 对象的配置类</span></span><br><span class="line"> <span class="type">Configuration</span> <span class="variable">cfg</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Configuration</span>(Region.autoRegion());</span><br><span class="line"> <span class="comment">//...其他参数参考类注释</span></span><br><span class="line"> <span class="type">UploadManager</span> <span class="variable">uploadManager</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UploadManager</span>(cfg);</span><br><span class="line"> <span class="comment">//默认不指定key的情况下,以文件内容的hash值作为文件名</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> filePath;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">InputStream</span> <span class="variable">inputStream</span> <span class="operator">=</span> imgFile.getInputStream();</span><br><span class="line"> <span class="type">Auth</span> <span class="variable">auth</span> <span class="operator">=</span> Auth.create(accessKey, secretKey);</span><br><span class="line"> <span class="type">String</span> <span class="variable">upToken</span> <span class="operator">=</span> auth.uploadToken(bucket);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">Response</span> <span class="variable">response</span> <span class="operator">=</span> uploadManager.put(inputStream,key,upToken,<span class="literal">null</span>, <span class="literal">null</span>);</span><br><span class="line"> <span class="comment">//解析上传成功的结果</span></span><br><span class="line"> <span class="type">DefaultPutRet</span> <span class="variable">putRet</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Gson</span>().fromJson(response.bodyString(), DefaultPutRet.class);</span><br><span class="line"> System.out.println(putRet.key);</span><br><span class="line"> System.out.println(putRet.hash);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"http://r7yxkqloa.bkt.clouddn.com/"</span>+key;</span><br><span class="line"> } <span class="keyword">catch</span> (QiniuException ex) {</span><br><span class="line"> <span class="type">Response</span> <span class="variable">r</span> <span class="operator">=</span> ex.response;</span><br><span class="line"> System.err.println(r.toString());</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> System.err.println(r.bodyString());</span><br><span class="line"> } <span class="keyword">catch</span> (QiniuException ex2) {</span><br><span class="line"> <span class="comment">//ignore</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (Exception ex) {</span><br><span class="line"> <span class="comment">//ignore</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"www"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>PathUtils</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="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 三更 B站: https://space.bilibili.com/663528522</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_">PathUtils</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">generateFilePath</span><span class="params">(String fileName)</span>{</span><br><span class="line"> <span class="comment">//根据日期生成路径 2022/1/15/</span></span><br><span class="line"> <span class="type">SimpleDateFormat</span> <span class="variable">sdf</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleDateFormat</span>(<span class="string">"yyyy/MM/dd/"</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">datePath</span> <span class="operator">=</span> sdf.format(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"> <span class="comment">//uuid作为文件名</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">uuid</span> <span class="operator">=</span> UUID.randomUUID().toString().replaceAll(<span class="string">"-"</span>, <span class="string">""</span>);</span><br><span class="line"> <span class="comment">//后缀和文件后缀一致</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> fileName.lastIndexOf(<span class="string">"."</span>);</span><br><span class="line"> <span class="comment">// test.jpg -> .jpg</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">fileType</span> <span class="operator">=</span> fileName.substring(index);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>().append(datePath).append(uuid).append(fileType).toString();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-15-更新个人信息接口"><a href="#3-15-更新个人信息接口" class="headerlink" title="3.15 更新个人信息接口"></a>3.15 更新个人信息接口</h3><h4 id="3-15-1-需求"><a href="#3-15-1-需求" class="headerlink" title="3.15.1 需求"></a>3.15.1 需求</h4><p>在编辑完个人资料后点击保存会对个人资料进行更新。</p><h4 id="3-15-2-接口设计"><a href="#3-15-2-接口设计" class="headerlink" title="3.15.2 接口设计"></a>3.15.2 接口设计</h4><p> </p><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>PUT</td><td>/user/userInfo</td><td>需要token请求头</td></tr></tbody></table><p>参数</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"avatar"</span><span class="punctuation">:</span><span class="string">"https://sg-blog-oss.oss-cn-beijing.aliyuncs.com/2022/01/31/948597e164614902ab1662ba8452e106.png"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"email"</span><span class="punctuation">:</span><span class="string">"23412332@qq.com"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span><span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"nickName"</span><span class="punctuation">:</span><span class="string">"sg333"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"sex"</span><span class="punctuation">:</span><span class="string">"1"</span></span><br><span class="line"><span class="punctuation">}</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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-15-3-代码实现"><a href="#3-15-3-代码实现" class="headerlink" title="3.15.3 代码实现"></a>3.15.3 代码实现</h4><p>UserController</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PutMapping("/userInfo")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">updateUserInfo</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">return</span> userService.updateUserInfo(user);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>UserService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">updateUserInfo</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p>UserServiceImpl</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="keyword">public</span> ResponseResult <span class="title function_">updateUserInfo</span><span class="params">(User user)</span> {</span><br><span class="line"> updateById(user);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-16-用户注册"><a href="#3-16-用户注册" class="headerlink" title="3.16 用户注册"></a>3.16 用户注册</h3><h4 id="3-16-1-需求"><a href="#3-16-1-需求" class="headerlink" title="3.16.1 需求"></a>3.16.1 需求</h4><p>要求用户能够在注册界面完成用户的注册。要求用户名,昵称,邮箱不能和数据库中原有的数据重复。如果某项重复了注册失败并且要有对应的提示。并且要求用户名,密码,昵称,邮箱都不能为空。</p><p>注意:密码必须密文存储到数据库中。</p><h4 id="3-16-2-接口设计"><a href="#3-16-2-接口设计" class="headerlink" title="3.16.2 接口设计"></a>3.16.2 接口设计</h4><p> </p><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/user/register</td><td>不需要token请求头</td></tr></tbody></table><p>参数</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"email"</span><span class="punctuation">:</span> <span class="string">"string"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"nickName"</span><span class="punctuation">:</span> <span class="string">"string"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"password"</span><span class="punctuation">:</span> <span class="string">"string"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"userName"</span><span class="punctuation">:</span> <span class="string">"string"</span></span><br><span class="line"><span class="punctuation">}</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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-16-3-代码实现"><a href="#3-16-3-代码实现" class="headerlink" title="3.16.3 代码实现"></a>3.16.3 代码实现</h4><p>UserController</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping("/register")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">register</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">return</span> userService.register(user);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>UserService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">register</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p>UserServiceImpl</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">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> PasswordEncoder passwordEncoder;</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_">register</span><span class="params">(User user)</span> {</span><br><span class="line"> <span class="comment">//对数据进行非空判断</span></span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getUserName())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.USERNAME_NOT_NULL);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getPassword())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.PASSWORD_NOT_NULL);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getEmail())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.EMAIL_NOT_NULL);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getNickName())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.NICKNAME_NOT_NULL);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//对数据进行是否存在的判断</span></span><br><span class="line"> <span class="keyword">if</span>(userNameExist(user.getUserName())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.USERNAME_EXIST);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(nickNameExist(user.getNickName())){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">SystemException</span>(AppHttpCodeEnum.NICKNAME_EXIST);</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="type">String</span> <span class="variable">encodePassword</span> <span class="operator">=</span> passwordEncoder.encode(user.getPassword());</span><br><span class="line"> user.setPassword(encodePassword);</span><br><span class="line"> <span class="comment">//存入数据库</span></span><br><span class="line"> save(user);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">AppHttpCodeEnum</span> {</span><br><span class="line"> <span class="comment">// 成功</span></span><br><span class="line"> SUCCESS(<span class="number">200</span>,<span class="string">"操作成功"</span>),</span><br><span class="line"> <span class="comment">// 登录</span></span><br><span class="line"> NEED_LOGIN(<span class="number">401</span>,<span class="string">"需要登录后操作"</span>),</span><br><span class="line"> NO_OPERATOR_AUTH(<span class="number">403</span>,<span class="string">"无权限操作"</span>),</span><br><span class="line"> SYSTEM_ERROR(<span class="number">500</span>,<span class="string">"出现错误"</span>),</span><br><span class="line"> USERNAME_EXIST(<span class="number">501</span>,<span class="string">"用户名已存在"</span>),</span><br><span class="line"> PHONENUMBER_EXIST(<span class="number">502</span>,<span class="string">"手机号已存在"</span>), EMAIL_EXIST(<span class="number">503</span>, <span class="string">"邮箱已存在"</span>),</span><br><span class="line"> REQUIRE_USERNAME(<span class="number">504</span>, <span class="string">"必需填写用户名"</span>),</span><br><span class="line"> CONTENT_NOT_NULL(<span class="number">506</span>, <span class="string">"评论内容不能为空"</span>),</span><br><span class="line"> FILE_TYPE_ERROR(<span class="number">507</span>, <span class="string">"文件类型错误,请上传png文件"</span>),</span><br><span class="line"> USERNAME_NOT_NULL(<span class="number">508</span>, <span class="string">"用户名不能为空"</span>),</span><br><span class="line"> NICKNAME_NOT_NULL(<span class="number">509</span>, <span class="string">"昵称不能为空"</span>),</span><br><span class="line"> PASSWORD_NOT_NULL(<span class="number">510</span>, <span class="string">"密码不能为空"</span>),</span><br><span class="line"> EMAIL_NOT_NULL(<span class="number">511</span>, <span class="string">"邮箱不能为空"</span>),</span><br><span class="line"> NICKNAME_EXIST(<span class="number">512</span>, <span class="string">"昵称已存在"</span>),</span><br><span class="line"> LOGIN_ERROR(<span class="number">505</span>,<span class="string">"用户名或密码错误"</span>);</span><br><span class="line"> <span class="type">int</span> code;</span><br><span class="line"> String msg;</span><br><span class="line"></span><br><span class="line"> AppHttpCodeEnum(<span class="type">int</span> code, String errorMessage){</span><br><span class="line"> <span class="built_in">this</span>.code = code;</span><br><span class="line"> <span class="built_in">this</span>.msg = errorMessage;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getCode</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> code;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getMsg</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> msg;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="3-17-AOP实现日志记录"><a href="#3-17-AOP实现日志记录" class="headerlink" title="3.17 AOP实现日志记录"></a>3.17 AOP实现日志记录</h3><h4 id="3-17-1-需求"><a href="#3-17-1-需求" class="headerlink" title="3.17.1 需求"></a>3.17.1 需求</h4><p>需要通过日志记录接口调用信息。便于后期调试排查。并且可能有很多接口都需要进行日志的记录。</p><p>接口被调用时日志打印格式如下:</p><p><img src="/post/0/image-20220313133714102.png" alt="image-20220313133714102"></p><h4 id="3-17-2-思路分析"><a href="#3-17-2-思路分析" class="headerlink" title="3.17.2 思路分析"></a>3.17.2 思路分析</h4><p>相当于是对原有的功能进行增强。并且是批量的增强,这个时候就非常适合用AOP来进行实现。</p><p></p><h4 id="3-17-3-代码实现"><a href="#3-17-3-代码实现" class="headerlink" title="3.17.3 代码实现"></a>3.17.3 代码实现</h4><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></pre></td><td class="code"><pre><span class="line">log.info(<span class="string">"=======Start======="</span>);</span><br><span class="line"><span class="comment">// 打印请求 URL</span></span><br><span class="line">log.info(<span class="string">"URL : {}"</span>,);</span><br><span class="line"><span class="comment">// 打印描述信息</span></span><br><span class="line">log.info(<span class="string">"BusinessName : {}"</span>, );</span><br><span class="line"><span class="comment">// 打印 Http method</span></span><br><span class="line">log.info(<span class="string">"HTTP Method : {}"</span>, );</span><br><span class="line"><span class="comment">// 打印调用 controller 的全路径以及执行方法</span></span><br><span class="line">log.info(<span class="string">"Class Method : {}.{}"</span>, );</span><br><span class="line"><span class="comment">// 打印请求的 IP</span></span><br><span class="line">log.info(<span class="string">"IP : {}"</span>,);</span><br><span class="line"><span class="comment">// 打印请求入参</span></span><br><span class="line">log.info(<span class="string">"Request Args : {}"</span>,);</span><br><span class="line"><span class="comment">// 打印出参</span></span><br><span class="line">log.info(<span class="string">"Response : {}"</span>, );</span><br><span class="line"><span class="comment">// 结束后换行</span></span><br><span class="line">log.info(<span class="string">"=======End======="</span> + System.lineSeparator());</span><br></pre></td></tr></table></figure><h3 id="3-18-更新浏览次数"><a href="#3-18-更新浏览次数" class="headerlink" title="3.18 更新浏览次数"></a>3.18 更新浏览次数</h3><h4 id="3-18-1-需求"><a href="#3-18-1-需求" class="headerlink" title="3.18.1 需求"></a>3.18.1 需求</h4><p>在用户浏览博文时要实现对应博客浏览量的增加。</p><h4 id="3-18-2-思路分析"><a href="#3-18-2-思路分析" class="headerlink" title="3.18.2 思路分析"></a>3.18.2 思路分析</h4><p>我们只需要在每次用户浏览博客时更新对应的浏览数即可。</p><p>但是如果直接操作博客表的浏览量的话,在并发量大的情况下会出现什么问题呢?</p><p>如何去优化呢?</p><p></p><p>①在应用启动时把博客的浏览量存储到redis中</p><p>②更新浏览量时去更新redis中的数据</p><p>③每隔10分钟把Redis中的浏览量更新到数据库中</p><p>④读取文章浏览量时从redis读取</p><h4 id="3-18-3-铺垫知识"><a href="#3-18-3-铺垫知识" class="headerlink" title="3.18.3 铺垫知识"></a>3.18.3 铺垫知识</h4><h5 id="3-18-3-1-CommandLineRunner实现项目启动时预处理"><a href="#3-18-3-1-CommandLineRunner实现项目启动时预处理" class="headerlink" title="3.18.3.1 CommandLineRunner实现项目启动时预处理"></a>3.18.3.1 CommandLineRunner实现项目启动时预处理</h5><p>如果希望在SpringBoot应用启动时进行一些初始化操作可以选择使用CommandLineRunner来进行处理。</p><p>我们只需要实现CommandLineRunner接口,并且把对应的bean注入容器。把相关初始化的代码重新到需要重新的方法中。</p><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></pre></td><td class="code"><pre><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_">TestRunner</span> <span class="keyword">implements</span> <span class="title class_">CommandLineRunner</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_">run</span><span class="params">(String... args)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> System.out.println(<span class="string">"程序初始化"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="3-18-3-2-定时任务"><a href="#3-18-3-2-定时任务" class="headerlink" title="3.18.3.2 定时任务"></a>3.18.3.2 定时任务</h5><p>定时任务的实现方式有很多,比如XXL-Job等。但是其实核心功能和概念都是类似的,很多情况下只是调用的API不同而已。</p><p>这里就先用SpringBoot为我们提供的定时任务的API来实现一个简单的定时任务,让大家先对定时任务里面的一些核心概念有个大致的了解。</p><p>实现步骤</p><p>① 使用@EnableScheduling注解开启定时任务功能</p><p>我们可以在配置类上加上@EnableScheduling</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="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan("com.sangeng.mapper")</span></span><br><span class="line"><span class="meta">@EnableScheduling</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SanGengBlogApplication</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> {</span><br><span class="line"> SpringApplication.run(SanGengBlogApplication.class,args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>② 确定定时任务执行代码,并配置任务执行时间</p><p>使用@Scheduled注解标识需要定时执行的代码。注解的cron属性相当于是任务的执行时间。目前可以使用 0/5 * * * * ? 进行测试,代表从0秒开始,每隔5秒执行一次。 </p><p>注意:对应的bean要注入容器,否则不会生效。</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="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestJob</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Scheduled(cron = "0/5 * * * * ?")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testJob</span><span class="params">()</span>{</span><br><span class="line"> <span class="comment">//要执行的代码</span></span><br><span class="line"> System.out.println(<span class="string">"定时任务执行了"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h6 id="3-18-3-2-1-cron-表达式语法"><a href="#3-18-3-2-1-cron-表达式语法" class="headerlink" title="3.18.3.2.1 cron 表达式语法"></a>3.18.3.2.1 cron 表达式语法</h6><p>cron表达式是用来设置定时任务执行时间的表达式。</p><p>很多情况下我们可以用 : <a href="https://www.bejson.com/othertools/cron/">在线Cron表达式生成器</a> 来帮助我们理解cron表达式和书写cron表达式。</p><p>但是我们还是有需要学习对应的Cron语法的,这样可以更有利于我们书写Cron表达式。</p><p>如上我们用到的 0/5 * * * * ? *,cron表达式由七部分组成,中间由空格分隔,这七部分从左往右依次是:</p><p>秒(0<del>59),分钟(0</del>59),小时(0~23),日期(1-月最后一天),月份(1-12),星期几(1-7,1表示星期日),年份(一般该项不设置,直接忽略掉,即可为空值)</p><p>通用特殊字符:, - * / (可以在任意部分使用)</p><blockquote><ul><li></li></ul></blockquote><p>星号表示任意值,例如:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">* * * * * ?</span><br></pre></td></tr></table></figure><p>表示 “ 每年每月每天每时每分每秒 ” 。</p><blockquote><p>, </p></blockquote><p>可以用来定义列表,例如 : </p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1,2,3 * * * * ?</span><br></pre></td></tr></table></figure><p>表示 “ 每年每月每天每时每分的每个第1秒,第2秒,第3秒 ” 。</p><blockquote><ul><li></li></ul></blockquote><p>定义范围,例如:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1-3 * * * * ?</span><br></pre></td></tr></table></figure><p>表示 “ 每年每月每天每时每分的第1秒至第3秒 ”。</p><blockquote><p>/</p></blockquote><p>每隔多少,例如</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">5/10 * * * * ?</span><br></pre></td></tr></table></figure><p>表示 “ 每年每月每天每时每分,从第5秒开始,每10秒一次 ” 。即 “ / ” 的左侧是开始值,右侧是间隔。如果是从 “ 0 ” 开始的话,也可以简写成 “ /10 ” </p><p>日期部分还可允许特殊字符: ? L W</p><p>星期部分还可允许的特殊字符: ? L # </p><blockquote><p>?</p></blockquote><p>只可用在日期和星期部分。表示没有具体的值,使用?要注意冲突。日期和星期两个部分如果其中一个部分设置了值,则另一个必须设置为 “ ? ”。</p><p>例如:</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></pre></td><td class="code"><pre><span class="line">0\* * * 2 * ?</span><br><span class="line"> 和</span><br><span class="line">0\* * * ? * 2</span><br></pre></td></tr></table></figure><p>同时使用?和同时不使用?都是不对的</p><p>例如下面写法就是错的</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></pre></td><td class="code"><pre><span class="line">* * * 2 * 2</span><br><span class="line"> 和</span><br><span class="line">* * * ? * ?</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>W</p></blockquote><p>只能用在日期中,表示当月中最接近某天的工作日</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0 0 0 31W * ?</span><br></pre></td></tr></table></figure><p>表示最接近31号的工作日,如果31号是星期六,则表示30号,即星期五,如果31号是星期天,则表示29号,即星期五。如果31号是星期三,则表示31号本身,即星期三。</p><blockquote><p>L</p></blockquote><p>表示最后(Last),只能用在日期和星期中</p><p>在日期中表示每月最后一天,在一月份中表示31号,在六月份中表示30号</p><p>也可以表示每月倒是第N天。例如: L-2表示每个月的倒数第2天</p><p> 0 0 0 LW * ?<br> LW可以连起来用,表示每月最后一个工作日,即每月最后一个星期五</p><p>在星期中表示7即星期六</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></pre></td><td class="code"><pre><span class="line">0 0 0 ? * L</span><br><span class="line">表示每个星期六</span><br><span class="line">0 0 0 ? * 6L</span><br><span class="line">若前面有其他值的话,则表示最后一个星期几,即每月的最后一个星期五</span><br></pre></td></tr></table></figure><blockquote><h1 id><a href="#" class="headerlink" title></a></h1></blockquote><p>只能用在星期中,表示第几个星期几</p><figure class="highlight plaintext"><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">0 0 0 ? * 6#3</span><br><span class="line">表示每个月的第三个星期五。</span><br></pre></td></tr></table></figure><h4 id="3-18-4-接口设计"><a href="#3-18-4-接口设计" class="headerlink" title="3.18.4 接口设计"></a>3.18.4 接口设计</h4><p> </p><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>PUT</td><td>/article/updateViewCount/{id}</td><td>不需要token请求头</td></tr></tbody></table><p>参数</p><p>请求路径中携带文章id</p><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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="3-18-5-代码实现"><a href="#3-18-5-代码实现" class="headerlink" title="3.18.5 代码实现"></a>3.18.5 代码实现</h4><h5 id="①在应用启动时把博客的浏览量存储到redis中"><a href="#①在应用启动时把博客的浏览量存储到redis中" class="headerlink" title="①在应用启动时把博客的浏览量存储到redis中"></a>①在应用启动时把博客的浏览量存储到redis中</h5><p>实现CommandLineRunner接口,在应用启动时初始化缓存。</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">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ViewCountRunner</span> <span class="keyword">implements</span> <span class="title class_">CommandLineRunner</span> {</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> ArticleMapper articleMapper;</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> RedisCache redisCache;</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_">run</span><span class="params">(String... args)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="comment">//查询博客信息 id viewCount</span></span><br><span class="line"> List<Article> articles = articleMapper.selectList(<span class="literal">null</span>);</span><br><span class="line"> Map<String, Integer> viewCountMap = articles.stream()</span><br><span class="line"> .collect(Collectors.toMap(article -> article.getId().toString(), article -> {</span><br><span class="line"> <span class="keyword">return</span> article.getViewCount().intValue();<span class="comment">//</span></span><br><span class="line"> }));</span><br><span class="line"> <span class="comment">//存储到redis中</span></span><br><span class="line"> redisCache.setCacheMap(<span class="string">"article:viewCount"</span>,viewCountMap);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="②更新浏览量时去更新redsi中的数据"><a href="#②更新浏览量时去更新redsi中的数据" class="headerlink" title="②更新浏览量时去更新redsi中的数据"></a>②更新浏览量时去更新redsi中的数据</h5><p>RedisCache增加方法 </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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">incrementCacheMapValue</span><span class="params">(String key,String hKey,<span class="type">long</span> v)</span>{</span><br><span class="line"> redisTemplate.boundHashOps(key).increment(hKey, v);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>ArticleController中增加方法更新阅读数</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PutMapping("/updateViewCount/{id}")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">updateViewCount</span><span class="params">(<span class="meta">@PathVariable("id")</span> Long id)</span>{</span><br><span class="line"> <span class="keyword">return</span> articleService.updateViewCount(id);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>ArticleService中增加方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">updateViewCount</span><span class="params">(Long id)</span>;</span><br></pre></td></tr></table></figure><p>ArticleServiceImpl中实现方法</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">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">updateViewCount</span><span class="params">(Long id)</span> {</span><br><span class="line"> <span class="comment">//更新redis中对应 id的浏览量</span></span><br><span class="line"> redisCache.incrementCacheMapValue(<span class="string">"article:viewCount"</span>,id.toString(),<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="③定时任务每隔10分钟把Redis中的浏览量更新到数据库中"><a href="#③定时任务每隔10分钟把Redis中的浏览量更新到数据库中" class="headerlink" title="③定时任务每隔10分钟把Redis中的浏览量更新到数据库中"></a>③定时任务每隔10分钟把Redis中的浏览量更新到数据库中</h5><p>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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">Article</span><span class="params">(Long id, <span class="type">long</span> viewCount)</span> {</span><br><span class="line"> <span class="built_in">this</span>.id = id;</span><br><span class="line"> <span class="built_in">this</span>.viewCount = viewCount;</span><br><span class="line">}</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></pre></td><td class="code"><pre><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_">UpdateViewCountJob</span> {</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> RedisCache redisCache;</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> ArticleService articleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Scheduled(cron = "0/5 * * * * ?")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">updateViewCount</span><span class="params">()</span>{</span><br><span class="line"> <span class="comment">//获取redis中的浏览量</span></span><br><span class="line"> Map<String, Integer> viewCountMap = redisCache.getCacheMap(<span class="string">"article:viewCount"</span>);</span><br><span class="line"></span><br><span class="line"> List<Article> articles = viewCountMap.entrySet()</span><br><span class="line"> .stream()</span><br><span class="line"> .map(entry -> <span class="keyword">new</span> <span class="title class_">Article</span>(Long.valueOf(entry.getKey()), entry.getValue().longValue()))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="comment">//更新到数据库中</span></span><br><span class="line"> articleService.updateBatchById(articles);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="④读取文章浏览量时从redis读取"><a href="#④读取文章浏览量时从redis读取" class="headerlink" title="④读取文章浏览量时从redis读取"></a>④读取文章浏览量时从redis读取</h5><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">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">getArticleDetail</span><span class="params">(Long id)</span> {</span><br><span class="line"> <span class="comment">//根据id查询文章</span></span><br><span class="line"> <span class="type">Article</span> <span class="variable">article</span> <span class="operator">=</span> getById(id);</span><br><span class="line"> <span class="comment">//从redis中获取viewCount</span></span><br><span class="line"> <span class="type">Integer</span> <span class="variable">viewCount</span> <span class="operator">=</span> redisCache.getCacheMapValue(<span class="string">"article:viewCount"</span>, id.toString());</span><br><span class="line"> article.setViewCount(viewCount.longValue());</span><br><span class="line"> <span class="comment">//转换成VO</span></span><br><span class="line"> <span class="type">ArticleDetailVo</span> <span class="variable">articleDetailVo</span> <span class="operator">=</span> BeanCopyUtils.copyBean(article, ArticleDetailVo.class);</span><br><span class="line"> <span class="comment">//根据分类id查询分类名</span></span><br><span class="line"> <span class="type">Long</span> <span class="variable">categoryId</span> <span class="operator">=</span> articleDetailVo.getCategoryId();</span><br><span class="line"> <span class="type">Category</span> <span class="variable">category</span> <span class="operator">=</span> categoryService.getById(categoryId);</span><br><span class="line"> <span class="keyword">if</span>(category!=<span class="literal">null</span>){</span><br><span class="line"> articleDetailVo.setCategoryName(category.getName());</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//封装响应返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(articleDetailVo);</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="4-Swagger2"><a href="#4-Swagger2" class="headerlink" title="4. Swagger2"></a>4. Swagger2</h2><h3 id="4-1-简介"><a href="#4-1-简介" class="headerlink" title="4.1 简介"></a>4.1 简介</h3><p>Swagger 是一套基于 OpenAPI 规范构建的开源工具,可以帮助我们设计、构建、记录以及使用 Rest API。</p><h3 id="4-2-为什么使用Swagger"><a href="#4-2-为什么使用Swagger" class="headerlink" title="4.2 为什么使用Swagger"></a>4.2 为什么使用Swagger</h3><p> 当下很多公司都采取前后端分离的开发模式,前端和后端的工作由不同的工程师完成。在这种开发模式下,维持一份及时更新且完整的 Rest API 文档将会极大的提高我们的工作效率。传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,下面我们就来了解一下它的优点:</p><p>1.代码变,文档变。只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。<br>2.跨语言性,支持 40 多种语言。<br>3.Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。</p><h3 id="4-3-快速入门"><a href="#4-3-快速入门" class="headerlink" title="4.3 快速入门"></a>4.3 快速入门</h3><h4 id="4-3-1-引入依赖"><a href="#4-3-1-引入依赖" class="headerlink" title="4.3.1 引入依赖"></a>4.3.1 引入依赖</h4><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger2<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger-ui<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="4-3-2-启用Swagger2"><a href="#4-3-2-启用Swagger2" class="headerlink" title="4.3.2 启用Swagger2"></a>4.3.2 启用Swagger2</h4><p>在启动类上或者配置类加 @EnableSwagger2 注解</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">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan("com.sangeng.mapper")</span></span><br><span class="line"><span class="meta">@EnableScheduling</span></span><br><span class="line"><span class="meta">@EnableSwagger2</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SanGengBlogApplication</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> {</span><br><span class="line"> SpringApplication.run(SanGengBlogApplication.class,args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="4-3-3-测试"><a href="#4-3-3-测试" class="headerlink" title="4.3.3 测试"></a>4.3.3 测试</h4><p>访问:<a href="http://localhost:7777/swagger-ui.html">http://localhost:7777/swagger-ui.html</a> 注意其中localhost和7777要调整成实际项目的域名和端口号。</p><h3 id="4-4-具体配置"><a href="#4-4-具体配置" class="headerlink" title="4.4 具体配置"></a>4.4 具体配置</h3><h4 id="4-4-1-Controller配置"><a href="#4-4-1-Controller配置" class="headerlink" title="4.4.1 Controller配置"></a>4.4.1 Controller配置</h4><h5 id="4-4-1-Api-注解"><a href="#4-4-1-Api-注解" class="headerlink" title="4.4.1 @Api 注解"></a>4.4.1 @Api 注解</h5><p>属性介绍:</p><p>tags 设置标签</p><p>description 设置描述信息</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">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/comment")</span></span><br><span class="line"><span class="meta">@Api(tags = "评论",description = "评论相关接口")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CommentController</span> {</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="4-4-2-接口配置"><a href="#4-4-2-接口配置" class="headerlink" title="4.4.2 接口配置"></a>4.4.2 接口配置</h4><h5 id="4-4-2-1-接口描述配置-ApiOperation"><a href="#4-4-2-1-接口描述配置-ApiOperation" class="headerlink" title="4.4.2.1 接口描述配置@ApiOperation"></a>4.4.2.1 接口描述配置@ApiOperation</h5><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">@GetMapping("/linkCommentList")</span></span><br><span class="line"><span class="meta">@ApiOperation(value = "友链评论列表",notes = "获取一页友链评论")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">linkCommentList</span><span class="params">(Integer pageNum,Integer pageSize)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.commentList(SystemConstants.LINK_COMMENT,<span class="literal">null</span>,pageNum,pageSize);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="4-4-2-2-接口参数描述"><a href="#4-4-2-2-接口参数描述" class="headerlink" title="4.4.2.2 接口参数描述"></a>4.4.2.2 接口参数描述</h5><p> @ApiImplicitParam 用于描述接口的参数,但是一个接口可能有多个参数,所以一般与 @ApiImplicitParams 组合使用。</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="meta">@GetMapping("/linkCommentList")</span></span><br><span class="line"><span class="meta">@ApiOperation(value = "友链评论列表",notes = "获取一页友链评论")</span></span><br><span class="line"><span class="meta">@ApiImplicitParams({</span></span><br><span class="line"><span class="meta"> @ApiImplicitParam(name = "pageNum",value = "页号"),</span></span><br><span class="line"><span class="meta"> @ApiImplicitParam(name = "pageSize",value = "每页大小")</span></span><br><span class="line"><span class="meta">}</span></span><br><span class="line"><span class="meta">)</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">linkCommentList</span><span class="params">(Integer pageNum,Integer pageSize)</span>{</span><br><span class="line"> <span class="keyword">return</span> commentService.commentList(SystemConstants.LINK_COMMENT,<span class="literal">null</span>,pageNum,pageSize);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="4-4-3-实体类配置"><a href="#4-4-3-实体类配置" class="headerlink" title="4.4.3 实体类配置"></a>4.4.3 实体类配置</h4><h5 id="4-4-3-1-实体的描述配置-ApiModel"><a href="#4-4-3-1-实体的描述配置-ApiModel" class="headerlink" title="4.4.3.1 实体的描述配置@ApiModel"></a>4.4.3.1 实体的描述配置@ApiModel</h5><p>@ApiModel用于描述实体类。</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">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@ApiModel(description = "添加评论dto")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AddCommentDto</span>{</span><br><span class="line"> <span class="comment">//..</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="4-4-3-2-实体的属性的描述配置-ApiModelProperty"><a href="#4-4-3-2-实体的属性的描述配置-ApiModelProperty" class="headerlink" title="4.4.3.2 实体的属性的描述配置@ApiModelProperty"></a>4.4.3.2 实体的属性的描述配置@ApiModelProperty</h5><p>@ApiModelProperty用于描述实体的属性</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">@ApiModelProperty(notes = "评论类型(0代表文章评论,1代表友链评论)")</span></span><br><span class="line"><span class="keyword">private</span> String type;</span><br></pre></td></tr></table></figure><h4 id="4-4-4-文档信息配置"><a href="#4-4-4-文档信息配置" class="headerlink" title="4.4.4 文档信息配置"></a>4.4.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></pre></td><td class="code"><pre><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_">SwaggerConfig</span> {</span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> Docket <span class="title function_">customDocket</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2)</span><br><span class="line"> .apiInfo(apiInfo())</span><br><span class="line"> .select()</span><br><span class="line"> .apis(RequestHandlerSelectors.basePackage(<span class="string">"com.sangeng.controller"</span>))</span><br><span class="line"> .build();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> ApiInfo <span class="title function_">apiInfo</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Contact</span> <span class="variable">contact</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Contact</span>(<span class="string">"团队名"</span>, <span class="string">"http://www.my.com"</span>, <span class="string">"my@my.com"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ApiInfoBuilder</span>()</span><br><span class="line"> .title(<span class="string">"文档标题"</span>)</span><br><span class="line"> .description(<span class="string">"文档描述"</span>)</span><br><span class="line"> .contact(contact) <span class="comment">// 联系方式</span></span><br><span class="line"> .version(<span class="string">"1.1.0"</span>) <span class="comment">// 版本</span></span><br><span class="line"> .build();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="5-博客后台"><a href="#5-博客后台" class="headerlink" title="5. 博客后台"></a>5. 博客后台</h2><h3 id="5-0-准备工作"><a href="#5-0-准备工作" class="headerlink" title="5.0 准备工作"></a>5.0 准备工作</h3><p>前端工程启动</p><p>npm install</p><p>npm run dev</p><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></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> 三更 B站: https://space.bilibili.com/663528522</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan("com.sangeng.mapper")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BlogAdminApplication</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> {</span><br><span class="line"> SpringApplication.run(BlogAdminApplication.class, args);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>②创建application.yml配置文件</p><figure class="highlight yml"><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></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">8989</span></span><br><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">url:</span> <span class="string">jdbc:mysql://localhost:3306/sg_blog?characterEncoding=utf-8&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="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"> <span class="attr">servlet:</span></span><br><span class="line"> <span class="attr">multipart:</span></span><br><span class="line"> <span class="attr">max-file-size:</span> <span class="string">2MB</span></span><br><span class="line"> <span class="attr">max-request-size:</span> <span class="string">5MB</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line"> <span class="attr">configuration:</span></span><br><span class="line"> <span class="comment"># 日志</span></span><br><span class="line"> <span class="attr">log-impl:</span> <span class="string">org.apache.ibatis.logging.stdout.StdOutImpl</span></span><br><span class="line"> <span class="attr">global-config:</span></span><br><span class="line"> <span class="attr">db-config:</span></span><br><span class="line"> <span class="attr">logic-delete-field:</span> <span class="string">delFlag</span></span><br><span class="line"> <span class="attr">logic-delete-value:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">logic-not-delete-value:</span> <span class="number">0</span></span><br><span class="line"> <span class="attr">id-type:</span> <span class="string">auto</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>③ SQL语句</p><p>SQL脚本:SGBlog\资源\SQL\sg_tag.sql</p><p>④ 创建实体类,Mapper,Service </p><p>注意思考这些文件应该写在哪个模块下?</p><p>Tag</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><br><span class="line"><span class="meta">@SuppressWarnings("serial")</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@TableName("sg_tag")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Tag</span> {</span><br><span class="line"> <span class="meta">@TableId</span></span><br><span class="line"> <span class="keyword">private</span> Long id;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Long createBy;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Date createTime;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Long updateBy;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">private</span> Date updateTime;</span><br><span class="line"> <span class="comment">//删除标志(0代表未删除,1代表已删除)</span></span><br><span class="line"> <span class="keyword">private</span> Integer delFlag;</span><br><span class="line"> <span class="comment">//备注</span></span><br><span class="line"> <span class="keyword">private</span> String remark;</span><br><span class="line"> <span class="comment">//标签名</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>TagMapper</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="comment">/**</span></span><br><span class="line"><span class="comment"> * 标签(Tag)表数据库访问层</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> makejava</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 2022-07-19 22:33:35</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">TagMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span><Tag> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>TagService</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="comment">/**</span></span><br><span class="line"><span class="comment"> * 标签(Tag)表服务接口</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> makejava</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 2022-07-19 22:33:38</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">TagService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Tag> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>TagServiceImpl</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="comment">/**</span></span><br><span class="line"><span class="comment"> * 标签(Tag)表服务实现类</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> makejava</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 2022-07-19 22:33:38</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service("tagService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TagServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><TagMapper, Tag> <span class="keyword">implements</span> <span class="title class_">TagService</span> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>⑤ 创建Controller测试接口</p><p>注意思考这些文件应该写在哪个模块下?</p><p>TagController /content/tag</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="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/content/tag")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TagController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> TagService tagService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/list")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">list</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(tagService.list());</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>⑥添加security相关类</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></pre></td><td class="code"><pre><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_">SecurityConfig</span> <span class="keyword">extends</span> <span class="title class_">WebSecurityConfigurerAdapter</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> AuthenticationManager <span class="title function_">authenticationManagerBean</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">super</span>.authenticationManagerBean();</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> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> AuthenticationEntryPoint authenticationEntryPoint;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> AccessDeniedHandler accessDeniedHandler;</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">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"><span class="comment">// .antMatchers("/login").anonymous()</span></span><br><span class="line"><span class="comment">// //注销接口需要认证才能访问</span></span><br><span class="line"><span class="comment">// .antMatchers("/logout").authenticated()</span></span><br><span class="line"><span class="comment">// .antMatchers("/user/userInfo").authenticated()</span></span><br><span class="line"><span class="comment">// .antMatchers("/upload").authenticated()</span></span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().permitAll();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//配置异常处理器</span></span><br><span class="line"> http.exceptionHandling()</span><br><span class="line"> .authenticationEntryPoint(authenticationEntryPoint)</span><br><span class="line"> .accessDeniedHandler(accessDeniedHandler);</span><br><span class="line"> <span class="comment">//关闭默认的注销功能</span></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</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> PasswordEncoder <span class="title function_">passwordEncoder</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BCryptPasswordEncoder</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><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_">JwtAuthenticationTokenFilter</span> <span class="keyword">extends</span> <span class="title class_">OncePerRequestFilter</span> {</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> RedisCache redisCache;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doFilterInternal</span><span class="params">(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span> <span class="keyword">throws</span> ServletException, IOException {</span><br><span class="line"> <span class="comment">//获取请求头中的token</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">token</span> <span class="operator">=</span> request.getHeader(<span class="string">"token"</span>);</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(token)){</span><br><span class="line"> <span class="comment">//说明该接口不需要登录 直接放行</span></span><br><span class="line"> filterChain.doFilter(request, response);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//解析获取userid</span></span><br><span class="line"> <span class="type">Claims</span> <span class="variable">claims</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> claims = JwtUtil.parseJWT(token);</span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="comment">//token超时 token非法</span></span><br><span class="line"> <span class="comment">//响应告诉前端需要重新登录</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">String</span> <span class="variable">userId</span> <span class="operator">=</span> claims.getSubject();</span><br><span class="line"> <span class="comment">//从redis中获取用户信息</span></span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> redisCache.getCacheObject(<span class="string">"login:"</span> + userId);</span><br><span class="line"> <span class="comment">//如果获取不到</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(loginUser)){</span><br><span class="line"> <span class="comment">//说明登录过期 提示重新登录</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);</span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//存入SecurityContextHolder</span></span><br><span class="line"> <span class="type">UsernamePasswordAuthenticationToken</span> <span class="variable">authenticationToken</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UsernamePasswordAuthenticationToken</span>(loginUser,<span class="literal">null</span>,<span class="literal">null</span>);</span><br><span class="line"> SecurityContextHolder.getContext().setAuthentication(authenticationToken);</span><br><span class="line"></span><br><span class="line"> filterChain.doFilter(request, response);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="5-1-后台登录"><a href="#5-1-后台登录" class="headerlink" title="5.1 后台登录"></a>5.1 后台登录</h3><p>后台的认证授权也使用SpringSecurity安全框架来实现。</p><h4 id="5-1-0-需求"><a href="#5-1-0-需求" class="headerlink" title="5.1.0 需求"></a>5.1.0 需求</h4><p>需要实现登录功能</p><p>后台所有功能都必须登录才能使用。</p><h4 id="5-1-1-接口设计"><a href="#5-1-1-接口设计" class="headerlink" title="5.1.1 接口设计"></a>5.1.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求路径</th></tr></thead><tbody><tr><td>POST</td><td>/user/login</td></tr></tbody></table><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">{</span></span><br><span class="line"> <span class="attr">"userName"</span><span class="punctuation">:</span><span class="string">"sg"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"password"</span><span class="punctuation">:</span><span class="string">"1234"</span></span><br><span class="line"><span class="punctuation">}</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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span><span class="punctuation">:</span> <span class="string">"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI0ODBmOThmYmJkNmI0NjM0OWUyZjY2NTM0NGNjZWY2NSIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY0Mzg3NDMxNiwiZXhwIjoxNjQzOTYwNzE2fQ.ldLBUvNIxQCGemkCoMgT_0YsjsWndTg5tqfJb77pabk"</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-1-2-思路分析"><a href="#5-1-2-思路分析" class="headerlink" title="5.1.2 思路分析"></a>5.1.2 思路分析</h4><p>登录</p><p>①自定义登录接口 </p><p>调用ProviderManager的方法进行认证 如果认证通过生成jwt</p><p>把用户信息存入redis中</p><p>②自定义UserDetailsService </p><p>在这个实现类中去查询数据库</p><p>注意配置passwordEncoder为BCryptPasswordEncoder</p><p>校验:</p><p>①定义Jwt认证过滤器</p><p>获取token</p><p>解析token获取其中的userid</p><p>从redis中获取用户信息</p><p>存入SecurityContextHolder</p><h4 id="5-1-3-准备工作"><a href="#5-1-3-准备工作" class="headerlink" title="5.1.3 准备工作"></a>5.1.3 准备工作</h4><p>①添加依赖</p><p>前面已经添加过相关依赖,不需要做什么处理</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></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--redis依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-data-redis<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="comment"><!--fastjson依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>fastjson<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.2.33<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="comment"><!--jwt依赖--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.jsonwebtoken<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jjwt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>0.9.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h4 id="5-1-4-登录接口代码实现"><a href="#5-1-4-登录接口代码实现" class="headerlink" title="5.1.4 登录接口代码实现"></a>5.1.4 登录接口代码实现</h4><h5 id="LoginController"><a href="#LoginController" class="headerlink" title="LoginController"></a>LoginController</h5><p>复制一份BlogLoginController ,命名为LoginController,其中注入 LoginService </p><p>请求地址修改为/user/login即可</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">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoginController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> LoginService loginService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping("/user/login")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">login</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getUserName())){</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_">SystemException</span>(AppHttpCodeEnum.REQUIRE_USERNAME);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> loginService.login(user);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="LoginService"><a href="#LoginService" class="headerlink" title="LoginService"></a>LoginService</h5><p>复制一份BlogLoginService命名为LoginService即可</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">public</span> <span class="keyword">interface</span> <span class="title class_">LoginService</span> {</span><br><span class="line"> ResponseResult <span class="title function_">login</span><span class="params">(User user)</span>;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="SecurityConfig-2"><a href="#SecurityConfig-2" class="headerlink" title="SecurityConfig"></a>SecurityConfig</h5><p>之前已经复制过了</p><h5 id="SystemLoginServiceImpl"><a href="#SystemLoginServiceImpl" class="headerlink" title="SystemLoginServiceImpl"></a>SystemLoginServiceImpl</h5><p>复制一份,LoginServiceImpl,命名为SystemLoginServiceImpl 实现 LoginService</p><p>login方法中存redis的key的前缀修改为login</p><p>返回的数据中只要返回token</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="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SystemLoginServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">LoginService</span> {</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> AuthenticationManager authenticationManager;</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> RedisCache redisCache;</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_">login</span><span class="params">(User user)</span> {</span><br><span class="line"> <span class="type">UsernamePasswordAuthenticationToken</span> <span class="variable">authenticationToken</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UsernamePasswordAuthenticationToken</span>(user.getUserName(),user.getPassword());</span><br><span class="line"> <span class="type">Authentication</span> <span class="variable">authenticate</span> <span class="operator">=</span> authenticationManager.authenticate(authenticationToken);</span><br><span class="line"> <span class="comment">//判断是否认证通过</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(authenticate)){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"用户名或密码错误"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//获取userid 生成token</span></span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> (LoginUser) authenticate.getPrincipal();</span><br><span class="line"> <span class="type">String</span> <span class="variable">userId</span> <span class="operator">=</span> loginUser.getUser().getId().toString();</span><br><span class="line"> <span class="type">String</span> <span class="variable">jwt</span> <span class="operator">=</span> JwtUtil.createJWT(userId);</span><br><span class="line"> <span class="comment">//把用户信息存入redis</span></span><br><span class="line"> redisCache.setCacheObject(<span class="string">"login:"</span>+userId,loginUser);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//把token封装 返回</span></span><br><span class="line">Map<String,String> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> map.put(<span class="string">"token"</span>,jwt);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(map);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="UserDetailServiceImpl-1"><a href="#UserDetailServiceImpl-1" class="headerlink" title="UserDetailServiceImpl"></a>UserDetailServiceImpl</h5><p>复用原来的即可</p><h5 id="LoginUser-1"><a href="#LoginUser-1" class="headerlink" title="LoginUser"></a>LoginUser</h5><p>复用原来的即可</p><h3 id="5-2-后台权限控制及动态路由"><a href="#5-2-后台权限控制及动态路由" class="headerlink" title="5.2 后台权限控制及动态路由"></a>5.2 后台权限控制及动态路由</h3><h4 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h4><p>后台系统需要能实现不同的用户权限可以看到不同的功能。</p><p> 用户只能使用他的权限所允许使用的功能。</p><h4 id="功能设计"><a href="#功能设计" class="headerlink" title="功能设计"></a>功能设计</h4><p>之前在我的SpringSecurity的课程中就介绍过RBAC权限模型。没有学习过的可以去看下 <a href="https://www.bilibili.com/video/BV1mm4y1X7Hc?p=28">RBAC权限模型</a> 。这里我们就是在RBAC权限模型的基础上去实现这个功能。</p><p></p><h4 id="表分析"><a href="#表分析" class="headerlink" title="表分析"></a>表分析</h4><p>通过需求去分析需要有哪些字段。</p><p>建表SQL及初始化数据见:SGBlog\资源\SQL\sg_menu.sql</p><h4 id="接口设计"><a href="#接口设计" class="headerlink" title="接口设计"></a>接口设计</h4><h5 id="getInfo接口"><a href="#getInfo接口" class="headerlink" title="getInfo接口"></a>getInfo接口</h5><p>是</p><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/getInfo</td><td>需要token请求头</td></tr></tbody></table><p>请求参数:</p><p>无</p><p>响应格式:</p><p>如果用户id为1代表管理员,roles 中只需要有admin,permissions中需要有所有菜单类型为C或者F的,状态为正常的,未被删除的权限</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><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="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"permissions"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="string">"system:user:list"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="string">"system:role:list"</span><span class="punctuation">,</span></span><br><span class="line"><span class="string">"system:menu:list"</span><span class="punctuation">,</span></span><br><span class="line"><span class="string">"system:user:query"</span><span class="punctuation">,</span></span><br><span class="line"><span class="string">"system:user:add"</span></span><br><span class="line"> <span class="comment">//此次省略1000字</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"roles"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="string">"admin"</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"user"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"avatar"</span><span class="punctuation">:</span><span class="string">"http://r7yxkqloa.bkt.clouddn.com/2022/03/05/75fd15587811443a9a9a771f24da458d.png"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"email"</span><span class="punctuation">:</span><span class="string">"23412332@qq.com"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"nickName"</span><span class="punctuation">:</span><span class="string">"sg3334"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"sex"</span><span class="punctuation">:</span><span class="string">"1"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h5 id="getRouters接口"><a href="#getRouters接口" class="headerlink" title="getRouters接口"></a>getRouters接口</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/getRouters</td><td>需要token请求头</td></tr></tbody></table><p>请求参数:</p><p>无</p><p>响应格式:</p><p>前端为了实现动态路由的效果,需要后端有接口能返回用户所能访问的菜单数据。</p><p>注意:<strong>返回的菜单数据需要体现父子菜单的层级关系</strong></p><p>如果用户id为1代表管理员,menus中需要有所有菜单类型为C或者M的,状态为正常的,未被删除的权限</p><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><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"menus"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"children"</span><span class="punctuation">:</span><span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"component"</span><span class="punctuation">:</span><span class="string">"content/article/write/index"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"createTime"</span><span class="punctuation">:</span><span class="string">"2022-01-08 11:39:58"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"icon"</span><span class="punctuation">:</span><span class="string">"build"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">2023</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuName"</span><span class="punctuation">:</span><span class="string">"写博文"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuType"</span><span class="punctuation">:</span><span class="string">"C"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"orderNum"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"parentId"</span><span class="punctuation">:</span><span class="number">0</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"path"</span><span class="punctuation">:</span><span class="string">"write"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"perms"</span><span class="punctuation">:</span><span class="string">"content:article:writer"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"visible"</span><span class="punctuation">:</span><span class="string">"0"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"children"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"children"</span><span class="punctuation">:</span><span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"component"</span><span class="punctuation">:</span><span class="string">"system/user/index"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"createTime"</span><span class="punctuation">:</span><span class="string">"2021-11-12 18:46:19"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"icon"</span><span class="punctuation">:</span><span class="string">"user"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">100</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuName"</span><span class="punctuation">:</span><span class="string">"用户管理"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuType"</span><span class="punctuation">:</span><span class="string">"C"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"orderNum"</span><span class="punctuation">:</span><span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"parentId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"path"</span><span class="punctuation">:</span><span class="string">"user"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"perms"</span><span class="punctuation">:</span><span class="string">"system:user:list"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"visible"</span><span class="punctuation">:</span><span class="string">"0"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"children"</span><span class="punctuation">:</span><span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"component"</span><span class="punctuation">:</span><span class="string">"system/role/index"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"createTime"</span><span class="punctuation">:</span><span class="string">"2021-11-12 18:46:19"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"icon"</span><span class="punctuation">:</span><span class="string">"peoples"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">101</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuName"</span><span class="punctuation">:</span><span class="string">"角色管理"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuType"</span><span class="punctuation">:</span><span class="string">"C"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"orderNum"</span><span class="punctuation">:</span><span class="string">"2"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"parentId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"path"</span><span class="punctuation">:</span><span class="string">"role"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"perms"</span><span class="punctuation">:</span><span class="string">"system:role:list"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"visible"</span><span class="punctuation">:</span><span class="string">"0"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"children"</span><span class="punctuation">:</span><span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"component"</span><span class="punctuation">:</span><span class="string">"system/menu/index"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"createTime"</span><span class="punctuation">:</span><span class="string">"2021-11-12 18:46:19"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"icon"</span><span class="punctuation">:</span><span class="string">"tree-table"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">102</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuName"</span><span class="punctuation">:</span><span class="string">"菜单管理"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuType"</span><span class="punctuation">:</span><span class="string">"C"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"orderNum"</span><span class="punctuation">:</span><span class="string">"3"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"parentId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"path"</span><span class="punctuation">:</span><span class="string">"menu"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"perms"</span><span class="punctuation">:</span><span class="string">"system:menu:list"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"visible"</span><span class="punctuation">:</span><span class="string">"0"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"createTime"</span><span class="punctuation">:</span><span class="string">"2021-11-12 18:46:19"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"icon"</span><span class="punctuation">:</span><span class="string">"system"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuName"</span><span class="punctuation">:</span><span class="string">"系统管理"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"menuType"</span><span class="punctuation">:</span><span class="string">"M"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"orderNum"</span><span class="punctuation">:</span><span class="string">"1"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"parentId"</span><span class="punctuation">:</span><span class="number">0</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"path"</span><span class="punctuation">:</span><span class="string">"system"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"perms"</span><span class="punctuation">:</span><span class="string">""</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"visible"</span><span class="punctuation">:</span><span class="string">"0"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h4><h5 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h5><p>生成menu和role表对于的类</p><h5 id="getInfo接口-1"><a href="#getInfo接口-1" class="headerlink" title="getInfo接口"></a>getInfo接口</h5><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">@Data</span></span><br><span class="line"><span class="meta">@Accessors(chain = true)</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AdminUserInfoVo</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<String> permissions;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<String> roles;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> UserInfoVo user;</span><br><span class="line">}</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></pre></td><td class="code"><pre><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_">LoginController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> LoginService loginService;</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> MenuService menuService;</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> RoleService roleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping("/user/login")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">login</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">if</span>(!StringUtils.hasText(user.getUserName())){</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_">SystemException</span>(AppHttpCodeEnum.REQUIRE_USERNAME);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> loginService.login(user);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("getInfo")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<AdminUserInfoVo> <span class="title function_">getInfo</span><span class="params">()</span>{</span><br><span class="line"> <span class="comment">//获取当前登录的用户</span></span><br><span class="line"> <span class="type">LoginUser</span> <span class="variable">loginUser</span> <span class="operator">=</span> SecurityUtils.getLoginUser();</span><br><span class="line"> <span class="comment">//根据用户id查询权限信息</span></span><br><span class="line"> List<String> perms = menuService.selectPermsByUserId(loginUser.getUser().getId());</span><br><span class="line"> <span class="comment">//根据用户id查询角色信息</span></span><br><span class="line"> List<String> roleKeyList = roleService.selectRoleKeyByUserId(loginUser.getUser().getId());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取用户信息</span></span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> loginUser.getUser();</span><br><span class="line"> <span class="type">UserInfoVo</span> <span class="variable">userInfoVo</span> <span class="operator">=</span> BeanCopyUtils.copyBean(user, UserInfoVo.class);</span><br><span class="line"> <span class="comment">//封装数据返回</span></span><br><span class="line"></span><br><span class="line"> <span class="type">AdminUserInfoVo</span> <span class="variable">adminUserInfoVo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AdminUserInfoVo</span>(perms,roleKeyList,userInfoVo);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(adminUserInfoVo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>RoleServiceImpl selectRoleKeyByUserId方法</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service("menuService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MenuServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><MenuMapper, Menu> <span class="keyword">implements</span> <span class="title class_">MenuService</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> List<String> <span class="title function_">selectPermsByUserId</span><span class="params">(Long id)</span> {</span><br><span class="line"> <span class="comment">//如果是管理员,返回所有的权限</span></span><br><span class="line"> <span class="keyword">if</span>(id == <span class="number">1L</span>){</span><br><span class="line"> LambdaQueryWrapper<Menu> wrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> wrapper.in(Menu::getMenuType,SystemConstants.MENU,SystemConstants.BUTTON);</span><br><span class="line"> wrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);</span><br><span class="line"> List<Menu> menus = list(wrapper);</span><br><span class="line"> List<String> perms = menus.stream()</span><br><span class="line"> .map(Menu::getPerms)</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="keyword">return</span> perms;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//否则返回所具有的权限</span></span><br><span class="line"> <span class="keyword">return</span> getBaseMapper().selectPermsByUserId(id);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>MenuMapper </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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 菜单权限表(Menu)表数据库访问层</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> makejava</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 2022-08-09 22:32:07</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">MenuMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span><Menu> {</span><br><span class="line"></span><br><span class="line"> List<String> <span class="title function_">selectPermsByUserId</span><span class="params">(Long userId)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><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="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span> ?></span></span><br><span class="line"><span class="meta"><!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">"-//mybatis.org//DTD Mapper 3.0//EN"</span> <span class="string">"http://mybatis.org/dtd/mybatis-3-mapper.dtd"</span> ></span></span><br><span class="line"><span class="tag"><<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"com.sangeng.mapper.MenuMapper"</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectPermsByUserId"</span> <span class="attr">resultType</span>=<span class="string">"java.lang.String"</span>></span></span><br><span class="line"> SELECT</span><br><span class="line"> DISTINCT m.perms</span><br><span class="line"> FROM</span><br><span class="line"> `sys_user_role` ur</span><br><span class="line"> LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`</span><br><span class="line"> LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`</span><br><span class="line"> WHERE</span><br><span class="line"> ur.`user_id` = #{userId} AND</span><br><span class="line"> m.`menu_type` IN ('C','F') AND</span><br><span class="line"> m.`status` = 0 AND</span><br><span class="line"> m.`del_flag` = 0</span><br><span class="line"> <span class="tag"></<span class="name">select</span>></span></span><br><span class="line"><span class="tag"></<span class="name">mapper</span>></span></span><br></pre></td></tr></table></figure><p>MenuServiceImpl selectPermsByUserId方法</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">@Service("roleService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RoleServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><RoleMapper, Role> <span class="keyword">implements</span> <span class="title class_">RoleService</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> List<String> <span class="title function_">selectRoleKeyByUserId</span><span class="params">(Long id)</span> {</span><br><span class="line"> <span class="comment">//判断是否是管理员 如果是返回集合中只需要有admin</span></span><br><span class="line"> <span class="keyword">if</span>(id == <span class="number">1L</span>){</span><br><span class="line"> List<String> roleKeys = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> roleKeys.add(<span class="string">"admin"</span>);</span><br><span class="line"> <span class="keyword">return</span> roleKeys;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//否则查询用户所具有的角色信息</span></span><br><span class="line"> <span class="keyword">return</span> getBaseMapper().selectRoleKeyByUserId(id);</span><br><span class="line"> }</span><br><span class="line">}</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">RoleMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span><Role> {</span><br><span class="line"></span><br><span class="line"> List<String> <span class="title function_">selectRoleKeyByUserId</span><span class="params">(Long userId)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span> ?></span></span><br><span class="line"><span class="meta"><!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">"-//mybatis.org//DTD Mapper 3.0//EN"</span> <span class="string">"http://mybatis.org/dtd/mybatis-3-mapper.dtd"</span> ></span></span><br><span class="line"><span class="tag"><<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"com.sangeng.mapper.RoleMapper"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectRoleKeyByUserId"</span> <span class="attr">resultType</span>=<span class="string">"java.lang.String"</span>></span></span><br><span class="line"> SELECT</span><br><span class="line"> r.`role_key`</span><br><span class="line"> FROM</span><br><span class="line"> `sys_user_role` ur</span><br><span class="line"> LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`</span><br><span class="line"> WHERE</span><br><span class="line"> ur.`user_id` = #{userId} AND</span><br><span class="line"> r.`status` = 0 AND</span><br><span class="line"> r.`del_flag` = 0</span><br><span class="line"> <span class="tag"></<span class="name">select</span>></span></span><br><span class="line"><span class="tag"></<span class="name">mapper</span>></span></span><br></pre></td></tr></table></figure><h5 id="getRouters接口-1"><a href="#getRouters接口-1" class="headerlink" title="getRouters接口"></a>getRouters接口</h5><p>RoutersVo</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="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RoutersVo</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<Menu> menus;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>LoginController</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">@GetMapping("getRouters")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult<RoutersVo> <span class="title function_">getRouters</span><span class="params">()</span>{</span><br><span class="line"> <span class="type">Long</span> <span class="variable">userId</span> <span class="operator">=</span> SecurityUtils.getUserId();</span><br><span class="line"> <span class="comment">//查询menu 结果是tree的形式</span></span><br><span class="line"> List<Menu> menus = menuService.selectRouterMenuTreeByUserId(userId);</span><br><span class="line"> <span class="comment">//封装数据返回</span></span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(<span class="keyword">new</span> <span class="title class_">RoutersVo</span>(menus));</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>MenuService</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="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">MenuService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Menu> {</span><br><span class="line"></span><br><span class="line"> List<String> <span class="title function_">selectPermsByUserId</span><span class="params">(Long id)</span>;</span><br><span class="line"></span><br><span class="line"> List<Menu> <span class="title function_">selectRouterMenuTreeByUserId</span><span class="params">(Long userId)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>MenuServiceImpl</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> List<Menu> <span class="title function_">selectRouterMenuTreeByUserId</span><span class="params">(Long userId)</span> {</span><br><span class="line"> <span class="type">MenuMapper</span> <span class="variable">menuMapper</span> <span class="operator">=</span> getBaseMapper();</span><br><span class="line"> List<Menu> menus = <span class="literal">null</span>;</span><br><span class="line"> <span class="comment">//判断是否是管理员</span></span><br><span class="line"> <span class="keyword">if</span>(SecurityUtils.isAdmin()){</span><br><span class="line"> <span class="comment">//如果是 获取所有符合要求的Menu</span></span><br><span class="line"> menus = menuMapper.selectAllRouterMenu();</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="comment">//否则 获取当前用户所具有的Menu</span></span><br><span class="line"> menus = menuMapper.selectRouterMenuTreeByUserId(userId);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//构建tree</span></span><br><span class="line"> <span class="comment">//先找出第一层的菜单 然后去找他们的子菜单设置到children属性中</span></span><br><span class="line"> List<Menu> menuTree = builderMenuTree(menus,<span class="number">0L</span>);</span><br><span class="line"> <span class="keyword">return</span> menuTree;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> List<Menu> <span class="title function_">builderMenuTree</span><span class="params">(List<Menu> menus, Long parentId)</span> {</span><br><span class="line"> List<Menu> menuTree = menus.stream()</span><br><span class="line"> .filter(menu -> menu.getParentId().equals(parentId))</span><br><span class="line"> .map(menu -> menu.setChildren(getChildren(menu, menus)))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="keyword">return</span> menuTree;</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"> * 获取存入参数的 子Menu集合</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> menu</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> menus</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> List<Menu> <span class="title function_">getChildren</span><span class="params">(Menu menu, List<Menu> menus)</span> {</span><br><span class="line"> List<Menu> childrenList = menus.stream()</span><br><span class="line"> .filter(m -> m.getParentId().equals(menu.getId()))</span><br><span class="line"> .map(m->m.setChildren(getChildren(m,menus)))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"> <span class="keyword">return</span> childrenList;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>MenuMapper.java</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></pre></td><td class="code"><pre><span class="line">List<Menu> <span class="title function_">selectAllRouterMenu</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">List<Menu> <span class="title function_">selectRouterMenuTreeByUserId</span><span class="params">(Long userId)</span>;</span><br></pre></td></tr></table></figure><p>MenuMapper.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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectAllRouterMenu"</span> <span class="attr">resultType</span>=<span class="string">"com.sangeng.domain.entity.Menu"</span>></span></span><br><span class="line"> SELECT</span><br><span class="line"> DISTINCT m.id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, IFNULL(m.perms,'') AS perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time</span><br><span class="line"> FROM</span><br><span class="line"> `sys_menu` m</span><br><span class="line"> WHERE</span><br><span class="line"> m.`menu_type` IN ('C','M') AND</span><br><span class="line"> m.`status` = 0 AND</span><br><span class="line"> m.`del_flag` = 0</span><br><span class="line"> ORDER BY</span><br><span class="line"> m.parent_id,m.order_num</span><br><span class="line"> <span class="tag"></<span class="name">select</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectRouterMenuTreeByUserId"</span> <span class="attr">resultType</span>=<span class="string">"com.sangeng.domain.entity.Menu"</span>></span></span><br><span class="line"> SELECT</span><br><span class="line"> DISTINCT m.id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, IFNULL(m.perms,'') AS perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time</span><br><span class="line"> FROM</span><br><span class="line"> `sys_user_role` ur</span><br><span class="line"> LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`</span><br><span class="line"> LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`</span><br><span class="line"> WHERE</span><br><span class="line"> ur.`user_id` = #{userId} AND</span><br><span class="line"> m.`menu_type` IN ('C','M') AND</span><br><span class="line"> m.`status` = 0 AND</span><br><span class="line"> m.`del_flag` = 0</span><br><span class="line"> ORDER BY</span><br><span class="line"> m.parent_id,m.order_num</span><br><span class="line"> <span class="tag"></<span class="name">select</span>></span></span><br></pre></td></tr></table></figure><p>查询的列:</p><p>SELECT DISTINCT m.id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, IFNULL(m.perms,’’) AS perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time</p><p>注意需要按照parent_id和order_num排序</p><h3 id="5-3-退出登录接口"><a href="#5-3-退出登录接口" class="headerlink" title="5.3 退出登录接口"></a>5.3 退出登录接口</h3><h4 id="5-3-1-接口设计"><a href="#5-3-1-接口设计" class="headerlink" title="5.3.1 接口设计"></a>5.3.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/user/logout</td><td>需要token请求头</td></tr></tbody></table><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">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-3-2-代码实现"><a href="#5-3-2-代码实现" class="headerlink" title="5.3.2 代码实现"></a>5.3.2 代码实现</h4><p>要实现的操作:</p><p>删除redis中的用户信息</p><p>LoginController</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping("/user/logout")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">logout</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> loginServcie.logout();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>LoginService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">logout</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><p>SystemLoginServiceImpl</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="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">logout</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//获取当前登录的用户id</span></span><br><span class="line"> <span class="type">Long</span> <span class="variable">userId</span> <span class="operator">=</span> SecurityUtils.getUserId();</span><br><span class="line"> <span class="comment">//删除redis中对应的值</span></span><br><span class="line"> redisCache.deleteObject(<span class="string">"login:"</span>+userId);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SecurityConfig</p><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">@Override</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> http</span><br><span class="line"> <span class="comment">//关闭csrf</span></span><br><span class="line"> .csrf().disable()</span><br><span class="line"> <span class="comment">//不通过Session获取SecurityContext</span></span><br><span class="line"> .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)</span><br><span class="line"> .and()</span><br><span class="line"> .authorizeRequests()</span><br><span class="line"> <span class="comment">// 对于登录接口 允许匿名访问</span></span><br><span class="line"> .antMatchers(<span class="string">"/user/login"</span>).anonymous()</span><br><span class="line"><span class="comment">// //注销接口需要认证才能访问</span></span><br><span class="line"><span class="comment">// .antMatchers("/logout").authenticated()</span></span><br><span class="line"><span class="comment">// .antMatchers("/user/userInfo").authenticated()</span></span><br><span class="line"><span class="comment">// .antMatchers("/upload").authenticated()</span></span><br><span class="line"> <span class="comment">// 除上面外的所有请求全部不需要认证即可访问</span></span><br><span class="line"> .anyRequest().authenticated();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//配置异常处理器</span></span><br><span class="line"> http.exceptionHandling()</span><br><span class="line"> .authenticationEntryPoint(authenticationEntryPoint)</span><br><span class="line"> .accessDeniedHandler(accessDeniedHandler);</span><br><span class="line"> <span class="comment">//关闭默认的注销功能</span></span><br><span class="line"> http.logout().disable();</span><br><span class="line"> <span class="comment">//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中</span></span><br><span class="line"> http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);</span><br><span class="line"> <span class="comment">//允许跨域</span></span><br><span class="line"> http.cors();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="5-4-查询标签列表"><a href="#5-4-查询标签列表" class="headerlink" title="5.4 查询标签列表"></a>5.4 查询标签列表</h3><h4 id="5-4-0-需求"><a href="#5-4-0-需求" class="headerlink" title="5.4.0 需求"></a>5.4.0 需求</h4><p>为了方便后期对文章进行管理,需要提供标签的功能,一个文章可以有多个标签。</p><p> 在后台需要分页查询标签功能,要求能根据标签名进行分页查询。 <strong>后期可能会增加备注查询等需求</strong>。</p><p>注意:不能把删除了的标签查询出来。</p><h4 id="5-4-1-标签表分析"><a href="#5-4-1-标签表分析" class="headerlink" title="5.4.1 标签表分析"></a>5.4.1 标签表分析</h4><p>通过需求去分析需要有哪些字段。</p><h4 id="5-4-2-接口设计"><a href="#5-4-2-接口设计" class="headerlink" title="5.4.2 接口设计"></a>5.4.2 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求路径</th></tr></thead><tbody><tr><td>Get</td><td>content/tag/list</td></tr></tbody></table><p>Query格式请求参数:</p><p>pageNum: 页码</p><p>pageSize: 每页条数</p><p>name:标签名</p><p>remark:备注</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"rows"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">4</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"Java"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"remark"</span><span class="punctuation">:</span><span class="string">"sdad"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"total"</span><span class="punctuation">:</span><span class="number">1</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-4-3-代码实现"><a href="#5-4-3-代码实现" class="headerlink" title="5.4.3 代码实现"></a>5.4.3 代码实现</h4><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/content/tag")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TagController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> TagService tagService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/list")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult<PageVo> <span class="title function_">list</span><span class="params">(Integer pageNum, Integer pageSize, TagListDto tagListDto)</span>{</span><br><span class="line"> <span class="keyword">return</span> tagService.pageTagList(pageNum,pageSize,tagListDto);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">TagService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Tag> {</span><br><span class="line"></span><br><span class="line"> ResponseResult<PageVo> <span class="title function_">pageTagList</span><span class="params">(Integer pageNum, Integer pageSize, TagListDto tagListDto)</span>;</span><br><span class="line">}</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service("tagService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TagServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span><TagMapper, Tag> <span class="keyword">implements</span> <span class="title class_">TagService</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<PageVo> <span class="title function_">pageTagList</span><span class="params">(Integer pageNum, Integer pageSize, TagListDto tagListDto)</span> {</span><br><span class="line"> <span class="comment">//分页查询</span></span><br><span class="line"> LambdaQueryWrapper<Tag> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> queryWrapper.eq(StringUtils.hasText(tagListDto.getName()),Tag::getName,tagListDto.getName());</span><br><span class="line"> queryWrapper.eq(StringUtils.hasText(tagListDto.getRemark()),Tag::getRemark,tagListDto.getRemark());</span><br><span class="line"></span><br><span class="line"> Page<Tag> page = <span class="keyword">new</span> <span class="title class_">Page</span><>();</span><br><span class="line"> page.setCurrent(pageNum);</span><br><span class="line"> page.setSize(pageSize);</span><br><span class="line"> page(page, queryWrapper);</span><br><span class="line"> <span class="comment">//封装数据返回</span></span><br><span class="line"> <span class="type">PageVo</span> <span class="variable">pageVo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PageVo</span>(page.getRecords(),page.getTotal());</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(pageVo);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="5-5-新增标签"><a href="#5-5-新增标签" class="headerlink" title="5.5 新增标签"></a>5.5 新增标签</h3><h4 id="5-5-0-需求"><a href="#5-5-0-需求" class="headerlink" title="5.5.0 需求"></a>5.5.0 需求</h4><p>点击标签管理的新增按钮可以实现新增标签的功能。</p><h4 id="5-5-1-接口设计"><a href="#5-5-1-接口设计" class="headerlink" title="5.5.1 接口设计"></a>5.5.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/content/tag</td><td>需要token请求头</td></tr></tbody></table><p>请求体格式:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"c#"</span><span class="punctuation">,</span><span class="attr">"remark"</span><span class="punctuation">:</span><span class="string">"c++++"</span><span class="punctuation">}</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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-5-2-测试"><a href="#5-5-2-测试" class="headerlink" title="5.5.2 测试"></a>5.5.2 测试</h4><p>测试时注意,添加到数据库中的记录有没有 创建时间,更新时间,创建人,更新人字段。</p><h3 id="5-6-删除标签"><a href="#5-6-删除标签" class="headerlink" title="5.6 删除标签"></a>5.6 删除标签</h3><h4 id="5-6-1-接口设计"><a href="#5-6-1-接口设计" class="headerlink" title="5.6.1 接口设计"></a>5.6.1 接口设计</h4><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>DELETE</td><td>/content/tag/{id}</td><td>需要token请求头</td></tr></tbody></table><p>请求参数在path中</p><p>例如:content/tag/6 代表删除id为6的标签数据</p><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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-6-2-测试"><a href="#5-6-2-测试" class="headerlink" title="5.6.2 测试"></a>5.6.2 测试</h4><p>注意测试删除后在列表中是否查看不到该条数据</p><p>数据库中该条数据还是存在的,只是修改了逻辑删除字段的值</p><h3 id="5-7-修改标签"><a href="#5-7-修改标签" class="headerlink" title="5.7 修改标签"></a>5.7 修改标签</h3><h4 id="5-7-1-接口设计"><a href="#5-7-1-接口设计" class="headerlink" title="5.7.1 接口设计"></a>5.7.1 接口设计</h4><h5 id="5-7-1-1-获取标签信息"><a href="#5-7-1-1-获取标签信息" class="headerlink" title="5.7.1.1 获取标签信息"></a>5.7.1.1 获取标签信息</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/content/tag/{id}</td><td>需要token请求头</td></tr></tbody></table><p>请求参数在path中</p><p>例如:content/tag/6 代表获取id为6的标签数据</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"id"</span><span class="punctuation">:</span><span class="number">4</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"Java"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"remark"</span><span class="punctuation">:</span><span class="string">"sdad"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h5 id="5-7-1-2-修改标签接口"><a href="#5-7-1-2-修改标签接口" class="headerlink" title="5.7.1.2 修改标签接口"></a>5.7.1.2 修改标签接口</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>PUT</td><td>/content/tag</td><td>需要token请求头</td></tr></tbody></table><p>请求体格式:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">7</span><span class="punctuation">,</span><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"c#"</span><span class="punctuation">,</span><span class="attr">"remark"</span><span class="punctuation">:</span><span class="string">"c++++"</span><span class="punctuation">}</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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h3 id="5-8-写博文"><a href="#5-8-写博文" class="headerlink" title="5.8 写博文"></a>5.8 写博文</h3><h4 id="5-8-1-需求"><a href="#5-8-1-需求" class="headerlink" title="5.8.1 需求"></a>5.8.1 需求</h4><p>需要提供写博文的功能,写博文时需要关联分类和标签。</p><p>可以上传缩略图,也可以在正文中添加图片。</p><p>文章可以直接发布,也可以保存到草稿箱。</p><h4 id="5-8-2-表分析"><a href="#5-8-2-表分析" class="headerlink" title="5.8.2 表分析"></a>5.8.2 表分析</h4><p>标签和文章需要关联所以需要一张关联表。</p><p>SQL脚本:SGBlog\资源\SQL\sg_article_tag.sql</p><h4 id="5-8-2-接口设计"><a href="#5-8-2-接口设计" class="headerlink" title="5.8.2 接口设计"></a>5.8.2 接口设计</h4><p>思考下需要哪些接口才能实现这个功能?</p><h5 id="5-8-2-1-查询所有分类接口"><a href="#5-8-2-1-查询所有分类接口" class="headerlink" title="5.8.2.1 查询所有分类接口"></a>5.8.2.1 查询所有分类接口</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/content/category/listAllCategory</td><td>需要token请求头</td></tr></tbody></table><p>请求参数:</p><p>无</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"description"</span><span class="punctuation">:</span><span class="string">"wsd"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"java"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"description"</span><span class="punctuation">:</span><span class="string">"wsd"</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">2</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"PHP"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h5 id="5-8-2-2-查询所有标签接口"><a href="#5-8-2-2-查询所有标签接口" class="headerlink" title="5.8.2.2 查询所有标签接口"></a>5.8.2.2 查询所有标签接口</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/content/tag/listAllTag</td><td>需要token请求头</td></tr></tbody></table><p>请求参数:</p><p>无</p><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"data"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"Mybatis"</span></span><br><span class="line"><span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"><span class="attr">"id"</span><span class="punctuation">:</span><span class="number">4</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"name"</span><span class="punctuation">:</span><span class="string">"Java"</span></span><br><span class="line"><span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h5 id="5-8-2-3-上传图片"><a href="#5-8-2-3-上传图片" class="headerlink" title="5.8.2.3 上传图片"></a>5.8.2.3 上传图片</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/upload</td><td>需要token请求头</td></tr></tbody></table><p>参数:</p><p>img,值为要上传的文件</p><p>请求头:</p><p>Content-Type :multipart/form-data;</p><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">{</span></span><br><span class="line"> <span class="attr">"code"</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"data"</span><span class="punctuation">:</span> <span class="string">"文件访问链接"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"msg"</span><span class="punctuation">:</span> <span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h5 id="5-8-2-4-新增博文"><a href="#5-8-2-4-新增博文" class="headerlink" title="5.8.2.4 新增博文"></a>5.8.2.4 新增博文</h5><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>POST</td><td>/content/article</td><td>需要token请求头</td></tr></tbody></table><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"title"</span><span class="punctuation">:</span><span class="string">"测试新增博文"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"thumbnail"</span><span class="punctuation">:</span><span class="string">"https://sg-blog-oss.oss-cn-beijing.aliyuncs.com/2022/08/21/4ceebc07e7484beba732f12b0d2c43a9.png"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"isTop"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"isComment"</span><span class="punctuation">:</span><span class="string">"0"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"content"</span><span class="punctuation">:</span><span class="string">"# 一级标题\n## 二级标题\n![Snipaste_20220228_224837.png](https://sg-blog-oss.oss-cn-beijing.aliyuncs.com/2022/08/21/c3af554d4a0f4935b4073533a4c26ee8.png)\n正文"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"tags"</span><span class="punctuation">:</span><span class="punctuation">[</span></span><br><span class="line"> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="number">4</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"categoryId"</span><span class="punctuation">:</span><span class="number">1</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"summary"</span><span class="punctuation">:</span><span class="string">"哈哈"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"status"</span><span class="punctuation">:</span><span class="string">"1"</span></span><br><span class="line"><span class="punctuation">}</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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">200</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"操作成功"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-8-3-代码实现"><a href="#5-8-3-代码实现" class="headerlink" title="5.8.3 代码实现"></a>5.8.3 代码实现</h4><h5 id="5-8-3-1-查询所有分类接口"><a href="#5-8-3-1-查询所有分类接口" class="headerlink" title="5.8.3.1 查询所有分类接口"></a>5.8.3.1 查询所有分类接口</h5><p>CategoryController</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="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 三更 B站: https://space.bilibili.com/663528522</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("/content/category")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CategoryController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> CategoryService categoryService;</span><br><span class="line"> </span><br><span class="line"> <span class="meta">@GetMapping("/listAllCategory")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">listAllCategory</span><span class="params">()</span>{</span><br><span class="line"> List<CategoryVo> list = categoryService.listAllCategory();</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(list);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>CategoryVo修改,增加description属性</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="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CategoryVo</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Long id;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="comment">//描述</span></span><br><span class="line"> <span class="keyword">private</span> String description;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>CategoryService增加listAllCategory方法</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="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">CategoryService</span> <span class="keyword">extends</span> <span class="title class_">IService</span><Category> {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> ResponseResult <span class="title function_">getCategoryList</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> List<CategoryVo> <span class="title function_">listAllCategory</span><span class="params">()</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>SystemConstants中增加常量</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="comment">/** 正常状态 */</span></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">NORMAL</span> <span class="operator">=</span> <span class="string">"0"</span>;</span><br></pre></td></tr></table></figure><p>CategoryServiceImpl增加方法</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="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> List<CategoryVo> <span class="title function_">listAllCategory</span><span class="params">()</span> {</span><br><span class="line"> LambdaQueryWrapper<Category> wrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> wrapper.eq(Category::getStatus, SystemConstants.NORMAL);</span><br><span class="line"> List<Category> list = list(wrapper);</span><br><span class="line"> List<CategoryVo> categoryVos = BeanCopyUtils.copyBeanList(list, CategoryVo.class);</span><br><span class="line"> <span class="keyword">return</span> categoryVos;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="5-8-3-2-查询所有标签接口"><a href="#5-8-3-2-查询所有标签接口" class="headerlink" title="5.8.3.2 查询所有标签接口"></a>5.8.3.2 查询所有标签接口</h5><p>TagVo</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="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TagVo</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="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>TagController</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">@GetMapping("/listAllTag")</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">listAllTag</span><span class="params">()</span>{</span><br><span class="line"> List<TagVo> list = tagService.listAllTag();</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult(list);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>TagService 增加listAllTag方法</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">List<TagVo> <span class="title function_">listAllTag</span><span class="params">()</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>TagServiceImpl</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="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> List<TagVo> <span class="title function_">listAllTag</span><span class="params">()</span> {</span><br><span class="line"> LambdaQueryWrapper<Tag> wrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> wrapper.select(Tag::getId,Tag::getName);</span><br><span class="line"> List<Tag> list = list(wrapper);</span><br><span class="line"> List<TagVo> tagVos = BeanCopyUtils.copyBeanList(list, TagVo.class);</span><br><span class="line"> <span class="keyword">return</span> tagVos;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="5-8-3-3-上传图片接口"><a href="#5-8-3-3-上传图片接口" class="headerlink" title="5.8.3.3 上传图片接口"></a>5.8.3.3 上传图片接口</h5><p>在sangeng-admin中增加UploadController</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="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 三更 B站: https://space.bilibili.com/663528522</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="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UploadController</span> {</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> UploadService uploadService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping("/upload")</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">uploadImg</span><span class="params">(<span class="meta">@RequestParam("img")</span> MultipartFile multipartFile)</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">return</span> uploadService.uploadImg(multipartFile);</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</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">"文件上传上传失败"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="5-8-3-4-新增博文接口"><a href="#5-8-3-4-新增博文接口" class="headerlink" title="5.8.3.4 新增博文接口"></a>5.8.3.4 新增博文接口</h5><p>ArticleController</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="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 三更 B站: https://space.bilibili.com/663528522</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("/content/article")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleController</span> {</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> ArticleService articleService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@PostMapping</span></span><br><span class="line"> <span class="keyword">public</span> ResponseResult <span class="title function_">add</span><span class="params">(<span class="meta">@RequestBody</span> AddArticleDto article)</span>{</span><br><span class="line"> <span class="keyword">return</span> articleService.add(article);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>AddArticleDto</p><p>注意增加tags属性用于接收文章关联标签的id</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">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AddArticleDto</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Long id;</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="keyword">private</span> String content;</span><br><span class="line"> <span class="comment">//文章摘要</span></span><br><span class="line"> <span class="keyword">private</span> String summary;</span><br><span class="line"> <span class="comment">//所属分类id</span></span><br><span class="line"> <span class="keyword">private</span> Long categoryId;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//缩略图</span></span><br><span class="line"> <span class="keyword">private</span> String thumbnail;</span><br><span class="line"> <span class="comment">//是否置顶(0否,1是)</span></span><br><span class="line"> <span class="keyword">private</span> String isTop;</span><br><span class="line"> <span class="comment">//状态(0已发布,1草稿)</span></span><br><span class="line"> <span class="keyword">private</span> String status;</span><br><span class="line"> <span class="comment">//访问量</span></span><br><span class="line"> <span class="keyword">private</span> Long viewCount;</span><br><span class="line"> <span class="comment">//是否允许评论 1是,0否</span></span><br><span class="line"> <span class="keyword">private</span> String isComment;</span><br><span class="line"> <span class="keyword">private</span> List<Long> tags;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>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></pre></td><td class="code"><pre><span class="line"><span class="meta">@TableField(fill = FieldFill.INSERT)</span></span><br><span class="line"><span class="keyword">private</span> Long createBy;</span><br><span class="line"><span class="meta">@TableField(fill = FieldFill.INSERT)</span></span><br><span class="line"><span class="keyword">private</span> Date createTime;</span><br><span class="line"><span class="meta">@TableField(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line"><span class="keyword">private</span> Long updateBy;</span><br><span class="line"><span class="meta">@TableField(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line"><span class="keyword">private</span> Date updateTime;</span><br></pre></td></tr></table></figure><p>ArticleService增加方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ResponseResult <span class="title function_">add</span><span class="params">(AddArticleDto article)</span>;</span><br></pre></td></tr></table></figure><p>创建ArticleTag表相关的实体类,mapper,service,serviceimpl等</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">@TableName(value="sg_article_tag")</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArticleTag</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> {</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">625337492348897098L</span>;</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="keyword">private</span> Long articleId;</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> Long tagId;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>ArticleServiceImpl增加如下代码</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> ArticleTagService articleTagService;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> ResponseResult <span class="title function_">add</span><span class="params">(AddArticleDto articleDto)</span> {</span><br><span class="line"> <span class="comment">//添加 博客</span></span><br><span class="line"> <span class="type">Article</span> <span class="variable">article</span> <span class="operator">=</span> BeanCopyUtils.copyBean(articleDto, Article.class);</span><br><span class="line"> save(article);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> List<ArticleTag> articleTags = articleDto.getTags().stream()</span><br><span class="line"> .map(tagId -> <span class="keyword">new</span> <span class="title class_">ArticleTag</span>(article.getId(), tagId))</span><br><span class="line"> .collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//添加 博客和标签的关联</span></span><br><span class="line"> articleTagService.saveBatch(articleTags);</span><br><span class="line"> <span class="keyword">return</span> ResponseResult.okResult();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="5-9-导出所有分类到Excel"><a href="#5-9-导出所有分类到Excel" class="headerlink" title="5.9 导出所有分类到Excel"></a>5.9 导出所有分类到Excel</h3><h4 id="5-9-1-需求"><a href="#5-9-1-需求" class="headerlink" title="5.9.1 需求"></a>5.9.1 需求</h4><p>在分类管理中点击导出按钮可以把所有的分类导出到Excel文件中。</p><p></p><h4 id="5-9-2-技术方案"><a href="#5-9-2-技术方案" class="headerlink" title="5.9.2 技术方案"></a>5.9.2 技术方案</h4><p>使用EasyExcel实现Excel的导出操作。</p><p><a href="https://github.com/alibaba/easyexcel">https://github.com/alibaba/easyexcel</a></p><p> <a href="https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write#%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81-1">https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write#%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81-1</a></p><h4 id="5-9-3-接口设计"><a href="#5-9-3-接口设计" class="headerlink" title="5.9.3 接口设计"></a>5.9.3 接口设计</h4><p></p><table><thead><tr><th>请求方式</th><th>请求地址</th><th>请求头</th></tr></thead><tbody><tr><td>GET</td><td>/content/category/export</td><td>需要token请求头</td></tr></tbody></table><p>请求参数:</p><p>无</p><p>响应格式:</p><p>成功的话可以直接导出一个Excel文件</p><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">{</span></span><br><span class="line"><span class="attr">"code"</span><span class="punctuation">:</span><span class="number">500</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">"msg"</span><span class="punctuation">:</span><span class="string">"出现错误"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h4 id="5-9-4-代码实现"><a href="#5-9-4-代码实现" class="headerlink" title="5.9.4 代码实现"></a>5.9.4 代码实现</h4><p>工具类方法修改</p><p>WebUtils</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="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">setDownLoadHeader</span><span class="params">(String filename, HttpServletResponse response)</span> <span class="keyword">throws</span> UnsupportedEncodingException {</span><br><span class="line"> response.setContentType(<span class="string">"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"</span>);</span><br><span class="line"> response.setCharacterEncoding(<span class="string">"utf-8"</span>);</span><br><span class="line"> String fname= URLEncoder.encode(filename,<span class="string">"UTF-8"</span>).replaceAll(<span class="string">"\\+"</span>, <span class="string">"%20"</span>);</span><br><span class="line"> response.setHeader(<span class="string">"Content-disposition"</span>,<span class="string">"attachment; filename="</span>+fname);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>CategoryController</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">@GetMapping("/export")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">export</span><span class="params">(HttpServletResponse response)</span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">//设置下载文件的请求头</span></span><br><span class="line"> WebUtils.setDownLoadHeader(<span class="string">"分类.xlsx"</span>,response);</span><br><span class="line"> <span class="comment">//获取需要导出的数据</span></span><br><span class="line"> List<Category> categoryVos = categoryService.list();</span><br><span class="line"></span><br><span class="line"> List<ExcelCategoryVo> excelCategoryVos = BeanCopyUtils.copyBeanList(categoryVos, ExcelCategoryVo.class);</span><br><span class="line"> <span class="comment">//把数据写入到Excel中</span></span><br><span class="line"> EasyExcel.write(response.getOutputStream(), ExcelCategoryVo.class).autoCloseStream(Boolean.FALSE).sheet(<span class="string">"分类导出"</span>)</span><br><span class="line"> .doWrite(excelCategoryVos);</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> <span class="comment">//如果出现异常也要响应json</span></span><br><span class="line"> <span class="type">ResponseResult</span> <span class="variable">result</span> <span class="operator">=</span> ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);</span><br><span class="line"> WebUtils.renderString(response, JSON.toJSONString(result));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>ExcelCategoryVo</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="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExcelCategoryVo</span> {</span><br><span class="line"> <span class="meta">@ExcelProperty("分类名")</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="comment">//描述</span></span><br><span class="line"> <span class="meta">@ExcelProperty("描述")</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">//状态0:正常,1禁用</span></span><br><span class="line"> <span class="meta">@ExcelProperty("状态0:正常,1禁用")</span></span><br><span class="line"> <span class="keyword">private</span> String status;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="5-10-权限控制"><a href="#5-10-权限控制" class="headerlink" title="5.10 权限控制"></a>5.10 权限控制</h3><h4 id="5-10-1-需求"><a href="#5-10-1-需求" class="headerlink" title="5.10.1 需求"></a>5.10.1 需求</h4><p>需要对导出分类的接口做权限控制。</p><p>sg eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJkZGJkNjM5MWJiZTA0NmMzOTc4NDg1ZTcxNWQ3YjQ0MSIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY2MjI0NDE4NywiZXhwIjoxNjYyMzMwNTg3fQ.z4JGwFN3lWyVbOCbhikCe-O4D6SvCQFEE5eQY3jDJkw</p><p>sangeng</p><p>eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI0Y2I1ZjhmMTc0Mjk0NzM0YjI4Y2M1NTQzYjQ2Yjc1YyIsInN1YiI6IjYiLCJpc3MiOiJzZyIsImlhdCI6MTY2MjI0NDQzMywiZXhwIjoxNjYyMzMwODMzfQ.yEkbyGYXBp5ndnyq-3acdgpvqx2mnI8B9fK9f3Y6Jco</p><h4 id="5-10-2-代码实现"><a href="#5-10-2-代码实现" class="headerlink" title="5.10.2 代码实现"></a>5.10.2 代码实现</h4><p>SecurityConfig</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableGlobalMethodSecurity(prePostEnabled = true)</span></span><br></pre></td></tr></table></figure><p>UserDetailsServiceImpl</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDetailsServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UserDetailsService</span> {</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> UserMapper userMapper;</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> MenuMapper menuMapper;</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> UserDetails <span class="title function_">loadUserByUsername</span><span class="params">(String username)</span> <span class="keyword">throws</span> UsernameNotFoundException {</span><br><span class="line"> <span class="comment">//根据用户名查询用户信息</span></span><br><span class="line"> LambdaQueryWrapper<User> queryWrapper = <span class="keyword">new</span> <span class="title class_">LambdaQueryWrapper</span><>();</span><br><span class="line"> queryWrapper.eq(User::getUserName,username);</span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> userMapper.selectOne(queryWrapper);</span><br><span class="line"> <span class="comment">//判断是否查到用户 如果没查到抛出异常</span></span><br><span class="line"> <span class="keyword">if</span>(Objects.isNull(user)){</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"用户不存在"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//返回用户信息</span></span><br><span class="line"> <span class="keyword">if</span>(user.getType().equals(SystemConstants.ADMAIN)){</span><br><span class="line"> List<String> list = menuMapper.selectPermsByUserId(user.getId());</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">LoginUser</span>(user,list);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">LoginUser</span>(user,<span class="literal">null</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>LoginUser</p><p>增加属性</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> List<String> permissions;</span><br></pre></td></tr></table></figure><p>PermissionService</p><p>hasPermisson</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><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">CategoryController</span><br><span class="line"></span><br><span class="line">~~~~java</span><br></pre></td></tr></table></figure>]]></content>
</entry>
<entry>
<title>Hello World</title>
<link href="/post/4a17b156.html"/>
<url>/post/4a17b156.html</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
</entry>
</search>