<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>lyhcc博客</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://lyhcc.github.io/"/>
  <updated>2021-01-11T07:59:26.146Z</updated>
  <id>https://lyhcc.github.io/</id>
  
  <author>
    <name>John Doe</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>HDFSAPI</title>
    <link href="https://lyhcc.github.io/post/ad365e02.html"/>
    <id>https://lyhcc.github.io/post/ad365e02.html</id>
    <published>2021-01-03T09:21:47.830Z</published>
    <updated>2021-01-11T07:59:26.146Z</updated>
    
    <content type="html"><![CDATA[<h3 id="HDFS文件上传"><a href="#HDFS文件上传" class="headerlink" title="HDFS文件上传"></a>HDFS文件上传</h3><ol><li>Java代码<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">putFileToHDFS</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//1、创建配置信息对象</span></span><br><span class="line"></span><br><span class="line">    Configuration conf = <span class="hljs-keyword">new</span> Configuration();<span class="hljs-comment">//hjhj</span></span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//2、设置部分参数</span></span><br><span class="line">    conf.set(<span class="hljs-string">"dfs.replication"</span>,<span class="hljs-string">"2"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//3、找到HDFS地址</span></span><br><span class="line">    <span class="hljs-comment">//final URI uri, final Configuration conf, String user</span></span><br><span class="line">    FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://vmaster:9000"</span>), conf, <span class="hljs-string">"root"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//4、上传本地文件路径</span></span><br><span class="line">    Path src = <span class="hljs-keyword">new</span> Path(<span class="hljs-string">"F:\\Course\\aliyun\\transaction_details.csv"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//5、要上传的HDFS的路径</span></span><br><span class="line">    Path dest = <span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://vmaster:9000/"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//6、以拷贝的方式上传，从src -&gt; dest</span></span><br><span class="line">    fs.copyFromLocalFile(src,dest);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//7、关闭</span></span><br><span class="line">    fs.close();</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//</span></span><br><span class="line">    System.out.println(<span class="hljs-string">"OK了"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><a id="more"></a><ol start="2"><li>命令</li></ol><figure class="highlight shell hljs"><table><tr><td class="gutter"><pre><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">hadoop fs -put ./p /</span><br><span class="line">./p 源文件 localsrc</span><br><span class="line">/    上传到对应目录，这里表示HDFS的根目录 dst</span><br><span class="line"></span><br><span class="line">-put [-f] [-p] [-l] [-d] &lt;localsrc&gt; ... &lt;dst&gt; :</span><br><span class="line">  Copy files from the local file system into fs. Copying fails if the file already</span><br><span class="line">  exists, unless the -f flag is given.</span><br><span class="line">  Flags:</span><br><span class="line">                                                                       </span><br><span class="line">  -p  Preserves access and modification times, ownership and the mode. </span><br><span class="line">  -f  Overwrites the destination if it already exists.                 </span><br><span class="line">  -l  Allow DataNode to lazily persist the file to disk. Forces        </span><br><span class="line">         replication factor of 1. This flag will result in reduced</span><br><span class="line">         durability. Use with care.</span><br><span class="line">                                                        </span><br><span class="line">  -d  Skip creation of temporary file(&lt;dst&gt;._COPYING_).</span><br></pre></td></tr></table></figure><ol start="3"><li>使用RESTFUL API上传<ul><li>使用PUT方法发送一个请求，这里-X 后面加PUT就是以PUT发起请求</li><li>然后使用返回的Location，在发送一个PUT请求</li></ul></li></ol><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">Step1: </span><br><span class="line">curl -i -X PUT  &quot;http://vmaster:50070/webhdfs/v1/1234.txt?op=create&amp;noredirect=true&quot;</span><br><span class="line">HTTP/1.1 100 Continue</span><br><span class="line"></span><br><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Cache-Control: no-cache</span><br><span class="line">Expires: Mon, 11 Jan 2021 02:20:57 GMT</span><br><span class="line">Date: Mon, 11 Jan 2021 02:20:57 GMT</span><br><span class="line">Pragma: no-cache</span><br><span class="line">Expires: Mon, 11 Jan 2021 02:20:57 GMT</span><br><span class="line">Date: Mon, 11 Jan 2021 02:20:57 GMT</span><br><span class="line">Pragma: no-cache</span><br><span class="line">X-FRAME-OPTIONS: SAMEORIGIN</span><br><span class="line">Content-Type: application/json</span><br><span class="line">Transfer-Encoding: chunked</span><br><span class="line"></span><br><span class="line">&#123;&quot;Location&quot;:&quot;http://vslave2:50075/webhdfs/v1/1234.txt?op=CREATE&amp;namenoderpcaddress=vmaster:9000&amp;createflag=&amp;createparent=true&amp;overwrite=false&quot;&#125;</span><br><span class="line"></span><br><span class="line">Step2:</span><br><span class="line">curl -i -X PUT -T &quot;F:\\Course\\BigData\\H.txt&quot; &quot;http://vslave2:50075/webhdfs/v1/1234.txt?op=CREATE&amp;namenoderpcaddress=vmaster:9000&amp;createflag=&amp;createparent=true&amp;overwrite=false&quot;</span><br><span class="line">HTTP/1.1 100 Continue</span><br><span class="line"></span><br><span class="line">HTTP/1.1 201 Created</span><br><span class="line">Location: hdfs://vmaster:9000/1234.txt</span><br><span class="line">Content-Length: 0</span><br><span class="line">Access-Control-Allow-Origin: *</span><br><span class="line">Connection: close</span><br></pre></td></tr></table></figure><hr><p>如何将curl的命令转为直接发送请求，比如在程序中如何发起，<a href="https://zhuanlan.zhihu.com/p/33481273" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/33481273</a></p><hr><h3 id="HDFS目录创建"><a href="#HDFS目录创建" class="headerlink" title="HDFS目录创建"></a>HDFS目录创建</h3><ol><li>Java代码</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">mkdirHDFS</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line">        <span class="hljs-comment">//1、创建配置对象</span></span><br><span class="line">        Configuration conf = <span class="hljs-keyword">new</span> Configuration();</span><br><span class="line">        <span class="hljs-comment">//2、获取文件系统</span></span><br><span class="line">        FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://vmaster:9000"</span>), conf, <span class="hljs-string">"root"</span>);</span><br><span class="line">        <span class="hljs-comment">//3、创建目录</span></span><br><span class="line">        fs.mkdirs(<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://vmaster:9000/Good"</span>));</span><br><span class="line">        <span class="hljs-comment">//4、关闭文件系统</span></span><br><span class="line">        fs.close();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>命令</li></ol><figure class="highlight shell hljs"><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">hadoop fs -mkdir /dir</span><br><span class="line">递归创建</span><br><span class="line">hadoop fs -mkdir -p  /dir/1/2/3</span><br></pre></td></tr></table></figure><ol start="3"><li>RESTful API</li></ol><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -i -X PUT  &quot;http://vmaster:50070/webhdfs/v1/dir?op=mkdirs&quot;</span><br></pre></td></tr></table></figure><h3 id="HDFS目录，文件删除"><a href="#HDFS目录，文件删除" class="headerlink" title="HDFS目录，文件删除"></a>HDFS目录，文件删除</h3><ol><li>Java代码</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">delHDFS</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line">    <span class="hljs-comment">//1、创建配置对象</span></span><br><span class="line">    Configuration conf = <span class="hljs-keyword">new</span> Configuration();</span><br><span class="line">    <span class="hljs-comment">//2、获取文件系统</span></span><br><span class="line">    FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://vmaster:9000"</span>), conf, <span class="hljs-string">"root"</span>);</span><br><span class="line">    <span class="hljs-comment">//3、删除文件</span></span><br><span class="line">    <span class="hljs-comment">//Path var1,删除的路径</span></span><br><span class="line">    <span class="hljs-comment">// boolean var2//是否递归删除</span></span><br><span class="line">    fs.delete(<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://vmaster:9000/Good"</span>),<span class="hljs-keyword">true</span>);</span><br><span class="line">    <span class="hljs-comment">//4、关闭系统</span></span><br><span class="line">    fs.close();</span><br><span class="line">    System.out.println(<span class="hljs-string">"del"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>命令</li></ol><figure class="highlight shell hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hadoop fs -rm  /LICENSE.txt</span><br></pre></td></tr></table></figure><ol start="3"><li>RESTful </li></ol><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -i -X DELETE &quot;http://vmaster:50070/webhdfs/v1/12.txt?op=DELETE&quot;</span><br></pre></td></tr></table></figure><h3 id="HDFS文件下载"><a href="#HDFS文件下载" class="headerlink" title="HDFS文件下载"></a>HDFS文件下载</h3><ol><li>Java代码</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span>  <span class="hljs-title">getFileFromHDFS</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line">    <span class="hljs-comment">//1、创建配置信息对象</span></span><br><span class="line">    Configuration conf = <span class="hljs-keyword">new</span> Configuration();</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//2、找到文件系统</span></span><br><span class="line">    FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://vmaster:9000"</span>),conf,<span class="hljs-string">"root"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//3、下载文件</span></span><br><span class="line">    <span class="hljs-comment">//boolean delSrc,是否将源文件删除</span></span><br><span class="line">    <span class="hljs-comment">// Path src,要下载的路径</span></span><br><span class="line">    <span class="hljs-comment">// Path dst, 要下载到那</span></span><br><span class="line">    <span class="hljs-comment">// boolean useRawLocalFileSystem：是否校验文件</span></span><br><span class="line">    <span class="hljs-comment">//</span></span><br><span class="line">    fs.copyToLocalFile(<span class="hljs-keyword">false</span>,<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://vmaster:9000/transaction_details.csv"</span>),<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"F:\\Course\\BigData"</span>),<span class="hljs-keyword">true</span>);</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//4、关闭文件系统</span></span><br><span class="line">    fs.close();</span><br><span class="line">    System.out.println(<span class="hljs-string">"OKl"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>命令</li></ol><figure class="highlight shell hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hadoop fs -get /NOTICE.txt</span><br></pre></td></tr></table></figure><h3 id="查看文件信息"><a href="#查看文件信息" class="headerlink" title="查看文件信息"></a>查看文件信息</h3><ol><li>Java代码</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">readLsitFile</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line">        <span class="hljs-comment">//1、创建配置对象</span></span><br><span class="line">        Configuration conf = <span class="hljs-keyword">new</span> Configuration();</span><br><span class="line">        <span class="hljs-comment">//2、获取文件系统</span></span><br><span class="line">        FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://vmaster:9000"</span>), conf, <span class="hljs-string">"root"</span>);</span><br><span class="line">        <span class="hljs-comment">//3、迭代器</span></span><br><span class="line">        RemoteIterator&lt;LocatedFileStatus&gt; listFiles = fs.listFiles(<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://vmaster:9000/"</span>), <span class="hljs-keyword">true</span>);</span><br><span class="line">        <span class="hljs-comment">//4、遍历迭代器</span></span><br><span class="line">        <span class="hljs-keyword">while</span>(listFiles.hasNext())&#123;</span><br><span class="line">            LocatedFileStatus fileStatus = listFiles.next();</span><br><span class="line"></span><br><span class="line">            <span class="hljs-comment">//路径名</span></span><br><span class="line">            System.out.println(<span class="hljs-string">"文件名"</span> + fileStatus.getPath().getName());</span><br><span class="line">            <span class="hljs-comment">//块的大小</span></span><br><span class="line">            System.out.println(<span class="hljs-string">"大小"</span> + fileStatus.getBlockSize());</span><br><span class="line">            <span class="hljs-comment">//权限</span></span><br><span class="line">            System.out.println(<span class="hljs-string">"权限"</span> + fileStatus.getPermission());</span><br><span class="line">            <span class="hljs-comment">//</span></span><br><span class="line">            System.out.println(fileStatus.getLen());</span><br><span class="line"></span><br><span class="line">            BlockLocation[] locations = fileStatus.getBlockLocations();</span><br><span class="line">            <span class="hljs-keyword">for</span>(BlockLocation bl:locations)&#123;</span><br><span class="line">                System.out.println(<span class="hljs-string">"block-offset"</span> + bl.getOffset());</span><br><span class="line">                String[] hosts = bl.getHosts();</span><br><span class="line">                <span class="hljs-keyword">for</span>(String host:hosts)&#123;</span><br><span class="line">                    System.out.println(host);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(<span class="hljs-string">"----------------------------------------"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h3 id="文件，目录判断"><a href="#文件，目录判断" class="headerlink" title="文件，目录判断"></a>文件，目录判断</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">checkFile</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> URISyntaxException, IOException, InterruptedException </span>&#123;</span><br><span class="line">    <span class="hljs-comment">//1、创建配置对象</span></span><br><span class="line">    Configuration conf = <span class="hljs-keyword">new</span> Configuration();</span><br><span class="line">    <span class="hljs-comment">//2、获取文件系统</span></span><br><span class="line">    FileSystem fs = FileSystem.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"hdfs://nna:9000"</span>), conf, <span class="hljs-string">"root"</span>);</span><br><span class="line">    <span class="hljs-comment">//3、遍历所有文件</span></span><br><span class="line">    FileStatus[] status = fs.listStatus(<span class="hljs-keyword">new</span> Path(<span class="hljs-string">"/"</span>));</span><br><span class="line">    <span class="hljs-keyword">for</span>(FileStatus status1:status)&#123;</span><br><span class="line">        <span class="hljs-comment">//判断是否为文件</span></span><br><span class="line">        <span class="hljs-keyword">if</span>(status1.isFile())&#123;</span><br><span class="line">            System.out.println(<span class="hljs-string">"文件："</span> + status1.getPath().getName());</span><br><span class="line">        &#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="hljs-string">"目录："</span> + status1.getPath().getName());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="hljs-comment">//4、关闭文件系统</span></span><br><span class="line">    fs.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p>RESTful 更多查看 <a href="https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/WebHDFS.html" target="_blank" rel="noopener">https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/WebHDFS.html</a><br>Java 文档  <a href="https://hadoop.apache.org/docs/r2.9.2/api/index.html" target="_blank" rel="noopener">https://hadoop.apache.org/docs/r2.9.2/api/index.html</a><br>命令使用<font color="red">hadoop fs -help</font> 查看</p><hr>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;HDFS文件上传&quot;&gt;&lt;a href=&quot;#HDFS文件上传&quot; class=&quot;headerlink&quot; title=&quot;HDFS文件上传&quot;&gt;&lt;/a&gt;HDFS文件上传&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Java代码&lt;figure class=&quot;highlight java hljs&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;putFileToHDFS&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; URISyntaxException, IOException, InterruptedException &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//1、创建配置信息对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Configuration conf = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Configuration();&lt;span class=&quot;hljs-comment&quot;&gt;//hjhj&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//2、设置部分参数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    conf.set(&lt;span class=&quot;hljs-string&quot;&gt;&quot;dfs.replication&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;2&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//3、找到HDFS地址&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//final URI uri, final Configuration conf, String user&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    FileSystem fs = FileSystem.get(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; URI(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hdfs://vmaster:9000&quot;&lt;/span&gt;), conf, &lt;span class=&quot;hljs-string&quot;&gt;&quot;root&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//4、上传本地文件路径&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Path src = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Path(&lt;span class=&quot;hljs-string&quot;&gt;&quot;F:\\Course\\aliyun\\transaction_details.csv&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//5、要上传的HDFS的路径&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Path dest = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Path(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hdfs://vmaster:9000/&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//6、以拷贝的方式上传，从src -&amp;gt; dest&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    fs.copyFromLocalFile(src,dest);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//7、关闭&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    fs.close();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    System.out.println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;OK了&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="BigData" scheme="https://lyhcc.github.io/categories/BigData/"/>
    
      <category term="Hadoop" scheme="https://lyhcc.github.io/categories/BigData/Hadoop/"/>
    
    
      <category term="Hadoop" scheme="https://lyhcc.github.io/tags/Hadoop/"/>
    
  </entry>
  
  <entry>
    <title>环境配置</title>
    <link href="https://lyhcc.github.io/post/b1c45f58.html"/>
    <id>https://lyhcc.github.io/post/b1c45f58.html</id>
    <published>2021-01-03T06:52:50.672Z</published>
    <updated>2021-01-03T07:13:56.124Z</updated>
    
    <content type="html"><![CDATA[<h3 id="maven环境配置"><a href="#maven环境配置" class="headerlink" title="maven环境配置"></a>maven环境配置</h3><p><font color="red">位置在于下载好的maven目录下apache-maven-3.5.2\conf</font></p><ol><li>更改本地库位置（防止C盘撑爆）搜索即可找到<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;localRepository&gt;D:\Repository&lt;/localRepository&gt;</span><br></pre></td></tr></table></figure></li><li>换阿里云镜像（加速下载）在mirrors下<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">&lt;mirror&gt;</span><br><span class="line">        &lt;id&gt;nexus-aliyun&lt;/id&gt;</span><br><span class="line">        &lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br><span class="line">        &lt;name&gt;Nexus aliyun&lt;/name&gt;</span><br><span class="line">        &lt;url&gt;http://maven.aliyun.com/nexus/content/groups/public&lt;/url&gt;</span><br><span class="line">    &lt;/mirror&gt;</span><br></pre></td></tr></table></figure></li><li>配置JDK版本，profiles下<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">&lt;profile&gt;</span><br><span class="line">&lt;id&gt;jdk18&lt;/id&gt;</span><br><span class="line">&lt;activation&gt;</span><br><span class="line">&lt;jdk&gt;1.8&lt;/jdk&gt;</span><br><span class="line">&lt;activeByDefault&gt;true&lt;/activeByDefault&gt;</span><br><span class="line">&lt;/activation&gt;</span><br><span class="line">&lt;properties&gt;</span><br><span class="line">&lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;</span><br><span class="line">&lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;</span><br><span class="line">&lt;maven.compiler.compilerVersion&gt;1.8&lt;/maven.compiler.compilerVersion&gt;</span><br><span class="line">&lt;/properties&gt;</span><br><span class="line">&lt;/profile&gt;</span><br></pre></td></tr></table></figure></li><li>配置环境变量<br><font color="red">文件夹-&gt;此电脑右键-&gt;属性-&gt;高级系统设置-&gt;环境变量-&gt;新建系统环境变量</font><br><img src="https://gitee.com/lyhcc/Images/raw/master//img/20210103151008.png" alt><br><img src="https://gitee.com/lyhcc/Images/raw/master//img/20210103151126.png" alt></li><li>IDEA中的Maven配置<br><img src="https://gitee.com/lyhcc/Images/raw/master//img/20210103150820.png" alt></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;maven环境配置&quot;&gt;&lt;a href=&quot;#maven环境配置&quot; class=&quot;headerlink&quot; title=&quot;maven环境配置&quot;&gt;&lt;/a&gt;maven环境配置&lt;/h3&gt;&lt;p&gt;&lt;font color=&quot;red&quot;&gt;位置在于下载好的maven目录下apache-m
      
    
    </summary>
    
    
      <category term="others" scheme="https://lyhcc.github.io/categories/others/"/>
    
    
  </entry>
  
  <entry>
    <title>CentOS配置</title>
    <link href="https://lyhcc.github.io/post/f245a8ad.html"/>
    <id>https://lyhcc.github.io/post/f245a8ad.html</id>
    <published>2021-01-02T10:48:50.725Z</published>
    <updated>2021-01-02T14:42:27.266Z</updated>
    
    <content type="html"><![CDATA[<h3 id="连网配置"><a href="#连网配置" class="headerlink" title="连网配置"></a>连网配置</h3><h4 id="防火墙"><a href="#防火墙" class="headerlink" title="防火墙"></a>防火墙</h4><ul><li>关闭防火墙：systemctl stop firewalld.service</li><li>禁用防火墙：systemctl disable firewalld.service</li><li>查看防火墙：systemctl status firewalld.service</li></ul><figure class="highlight plain hljs"><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">关闭Selinux：vi /etc/selinux/config</span><br><span class="line">将SELINUX=enforcing改为SELINUX=disabled</span><br></pre></td></tr></table></figure><a id="more"></a><h4 id="自定义IP"><a href="#自定义IP" class="headerlink" title="自定义IP"></a>自定义IP</h4><p><font color="red">vi /etc/sysconfig/network-scripts/ifcfg-ens33</font></p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">BOOTPROTO=&quot;static&quot; # 默认DHCP自动获取IP地址</span><br><span class="line">ONBOOT=&quot;yes&quot;</span><br><span class="line"></span><br><span class="line">IPADDR=192.168.37.129  # 自定义的IP地址</span><br><span class="line">GATEWAY=192.168.37.2   # 默认网关</span><br><span class="line">DNS1=8.8.8.8           # DNS服务器,google</span><br><span class="line">DNS2=8.8.4.4           # DNS服务器,baidu</span><br><span class="line">NETMASK=255.255.255.0  # 子网掩码</span><br></pre></td></tr></table></figure><p><font color="red">vi /etc/resolv.conf</font></p><figure class="highlight plain hljs"><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">nameserver 8.8.8.8</span><br><span class="line">nameserver 8.8.4.4</span><br></pre></td></tr></table></figure><p>重启网卡：service network restart<br>修改主机名（可选）：hostnamectl set-hostname aaa<br>配置好后就可以使用Xshell连接了，这样也就可以避免了IP地址的动态分配，造成IP地址每次启动都不一样，下面来看一下DHCP的过程</p><hr><ol><li>主机广播服务器广播DHCP报文(询问：有没有DHCP服务器)</li><li>DHCP服务器广播DHCP报文（回答：有，有，有）</li><li>主机广播DHCP请求报文（我现在要使用你的IP地址了）</li><li>DHCP服务器广播DHCP确认报文（用吧）</li></ol><p><a href="https://www.zyops.com/dhcp-working-procedure/" target="_blank" rel="noopener">更详细的过程</a></p><h3 id="文件上传下载命令"><a href="#文件上传下载命令" class="headerlink" title="文件上传下载命令"></a>文件上传下载命令</h3><p><font color="red">yum install lrzsz </font></p><h3 id="JDK安装"><a href="#JDK安装" class="headerlink" title="JDK安装"></a>JDK安装</h3><ol><li>查询是否安装java软件：<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -qa|grep java</span><br></pre></td></tr></table></figure></li><li>如果安装的版本低于1.7，卸载该jdk：<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -e 软件包名字</span><br></pre></td></tr></table></figure></li><li>在/opt目录下创建两个子文件（可选）<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir /opt/module /opt/software</span><br></pre></td></tr></table></figure></li><li>解压jdk到/opt/module目录下<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -zxvf jdk-8u144-linux-x64.tar.gz -C /opt/module/</span><br></pre></td></tr></table></figure></li><li>配置jdk环境变量<br><font color="red">vi /etc/profile</font><figure class="highlight plain hljs"><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">export JAVA_HOME=/opt/module/jdk1.8.0_144</span><br><span class="line">export PATH=$PATH:$JAVA_HOME/bin</span><br></pre></td></tr></table></figure><font color="red">source /etc/profile</font></li><li>测试jdk安装成功<figure class="highlight plain hljs"><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">java -version</span><br><span class="line">java version &quot;1.8.0_144&quot;</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;连网配置&quot;&gt;&lt;a href=&quot;#连网配置&quot; class=&quot;headerlink&quot; title=&quot;连网配置&quot;&gt;&lt;/a&gt;连网配置&lt;/h3&gt;&lt;h4 id=&quot;防火墙&quot;&gt;&lt;a href=&quot;#防火墙&quot; class=&quot;headerlink&quot; title=&quot;防火墙&quot;&gt;&lt;/a&gt;防火墙&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;关闭防火墙：systemctl stop firewalld.service&lt;/li&gt;
&lt;li&gt;禁用防火墙：systemctl disable firewalld.service&lt;/li&gt;
&lt;li&gt;查看防火墙：systemctl status firewalld.service&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight plain hljs&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;关闭Selinux：vi /etc/selinux	/config&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;将SELINUX=enforcing改为SELINUX=disabled&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="https://lyhcc.github.io/categories/Linux/"/>
    
    
      <category term="Linux" scheme="https://lyhcc.github.io/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>软件测试方法</title>
    <link href="https://lyhcc.github.io/post/bd735dfe.html"/>
    <id>https://lyhcc.github.io/post/bd735dfe.html</id>
    <published>2020-05-14T06:55:25.518Z</published>
    <updated>2020-12-31T13:52:34.842Z</updated>
    
    <content type="html"><![CDATA[<h2 id="等价类划分"><a href="#等价类划分" class="headerlink" title="等价类划分"></a>等价类划分</h2><blockquote><p>属于黑盒测试，它将不能穷举的测试过程进行分类，从而保证完整性和代表性；思考步骤：</p><ol><li>确定有效等价类和无效等价类</li><li>有效等价类划分（题目条件，还要注意边界值（极值），中间甲堕意找个值)</li><li>无效等价类划分（跟有效等价类相反，其他特殊的情况【中文、英文、特殊符号、空格、空】）</li></ol><p><strong>注意:</strong> 两个框要一个正确，一个错误，这样才能准确的判断；一定要根据需求来判断预期结  </p></blockquote><a id="more"></a><p><strong><a href="http://qukuailine.com/的注册页面" target="_blank" rel="noopener">http://qukuailine.com/的注册页面</a></strong><br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200514154933.png" alt></p><h3 id="等价类细节考虑"><a href="#等价类细节考虑" class="headerlink" title="等价类细节考虑"></a>等价类细节考虑</h3><blockquote><p>1、考虑输入长度2、考库输入类型3、组成规则4、是否为空5、是否区分大小写…<br>6、是否重复7、是否去除空格</p></blockquote><h2 id="边界值划分"><a href="#边界值划分" class="headerlink" title="边界值划分"></a>边界值划分</h2><ol><li>如果输入条件规定了值得范围，则应取刚到到这个范围的边界值，以及刚刚超越这个范围边界的值作为输入数据。<ul><li>两位整数加法器数的范围为99-99，则应测试99，-100和099,100<ol start="2"><li>输入条件规定了值得个数</li></ol><ul><li>姓名要求1-20个字符，需要测试0、1、2个字符和19、20、21个字符</li><li>某商品信息查询系统，每页最多呈示10条商品信息，我们就应该准备商品信息，使能够查询出10条、11条、1条、0条商品记录</li><li><font color="red">边界值和等价类区别：边界值分析不是从某等价类中随便挑一个作为代表，而是这个等价类的每个边界都要作为测试条件</font></li></ul></li></ul></li></ol><p><strong>银行密码案例</strong>  </p><blockquote><p>需求：<br>密码必须是数字密码组合<br>且长度在8-24<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200514162517.png" alt></p></blockquote><h3 id="常见的边界值"><a href="#常见的边界值" class="headerlink" title="常见的边界值"></a>常见的边界值</h3><ul><li>文本框接收字符个数，比如用户名长度，密码长度等</li><li>报表的第1行和最后1行；</li><li>数值元素的第1个和最后1个；</li><li>循环的第1次、2次和倒数第1次、2次。</li></ul><h2 id="因果图法"><a href="#因果图法" class="headerlink" title="因果图法"></a>因果图法</h2><blockquote><p>因果图法是一种利用图解法分析输入的各种组合情况，从而设计测试用例的方法，它适合于检查程序输入条件的各种组合情况<br>因果图法比较适合输入条件比较多的情况，测试所有的输入条件的排列组合。所谓的原因就是输入，所谓的结果就是输出。</p></blockquote><figure class="highlight plain hljs"><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><br><span class="line"> 因果图的“果”—输出结果因果图法要注意考虑：</span><br></pre></td></tr></table></figure><p>所有输入/输出条件的相互制约关系以及组合关系输出结果对输入条件的依赖关系，也就是什么样的输入组合会产生怎样的输出结果，即“因果关系”</p><p><strong>特点：</strong>  </p><ul><li>考虑输入条件的相互制约及<mark>组合关系</mark></li><li>考虑输条件对输入条件的<mark>依赖关系</mark><h3 id="因果图中的符号"><a href="#因果图中的符号" class="headerlink" title="因果图中的符号"></a>因果图中的符号</h3><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200514165545.png" alt></li></ul><ol><li>恒等一有因就有果，没有因就没有果</li><li>非一有因没有果，没有因有果</li><li>或一条件有一个是真，结果就是真，条件都是假，结果才是假</li><li>且（与）-条件都为真，结果才为真<h3 id="因果图中的约束条件"><a href="#因果图中的约束条件" class="headerlink" title="因果图中的约束条件"></a>因果图中的约束条件</h3><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200514165607.png" alt></li></ol><ul><li>E(互斥、排他)。a、b两个原因不会同时出现，最多只有一个出现。</li><li>I(包含、或)。a、b、c三个原因至少有一个出现。</li><li>O(唯一)。a、b两个原因必须有一个出现，且仅有一个出现。</li><li>R(需求)。a出现时b必定出现。<br> 从结果方面考虑主要有1种约束条件：</li><li>M(屏蔽)。a出现时，b必定不出现；a不出现时，b则不确定。</li></ul><h3 id="因果图导出测试用例"><a href="#因果图导出测试用例" class="headerlink" title="因果图导出测试用例"></a>因果图导出测试用例</h3><p>利用因果图导出测试用例需要经过以下几个步骤  </p><ol><li>找出所有的原因，原因即输入条件或输入条件的等价类。</li><li>找出所有的结果，结果即输出条件。</li><li>明确所有输入条件之间的制约关系以及组合关系。<ul><li>哪些条件不能组合到一起，哪些条件可以组合到一起 </li></ul></li><li>明确所有输出条件之间的制约关系以及组合关系。<ul><li>哪些输出结果不能同时输出，哪些输出结果可以同时输出</li></ul></li><li>找出什么样的输入条件组合会产生哪种输出结果</li><li>把因果图转换成判定表/决策表。</li><li>为判定表/决策表中的每一列表示的情况设计测试用例。</li></ol><p><a href="https://zhuanlan.zhihu.com/p/129342944" target="_blank" rel="noopener">案例参考</a></p><h3 id="交通一卡通案例"><a href="#交通一卡通案例" class="headerlink" title="交通一卡通案例"></a>交通一卡通案例</h3><ul><li>系统只接收50或100元纸币，一次只能使用一张纸币，一次充值金额只能为50元或100元</li><li>若输入50元纸币，并选择充值50元，完成充值后退卡，提示充值成功；</li><li>若输入50元纸币，并选择充值100元，提示输入金额不足并退回50元；</li><li>若输入100元纸币，并选择充值50元，完成充值后退卡，提示充值成功，找零50元；</li><li>若输入100元纸币，并选择充值100元，完成充值后退卡，提示充值成功；</li><li>若输入纸币后在规定时间内不选择充值按钮，退回输入的纸币，并提示错误；</li><li>若选择充值按钮后不输入纸币，提示错误<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200514195827.png" alt></li></ul><h2 id="判定表"><a href="#判定表" class="headerlink" title="判定表"></a>判定表</h2><h3 id="判定表的组成"><a href="#判定表的组成" class="headerlink" title="判定表的组成"></a>判定表的组成</h3><ul><li>条件桩:问题的所有条件</li><li>动作桩:问题的所有输出</li><li>条件项:针对条件桩的取值</li><li>动作项:条件项的各种取值情况下的输出结果<blockquote><p>相当于将<font color="red">输入改为条件装桩，输出改为动作桩</font></p></blockquote></li></ul><h3 id="判定表法的步骤"><a href="#判定表法的步骤" class="headerlink" title="判定表法的步骤"></a>判定表法的步骤</h3><ol><li>列出所有条件桩和条件桩</li><li>填入条件项</li><li>填入动作项</li><li>简化判定表（合并相同或相似规则）</li></ol><p><strong>案例</strong>  </p><blockquote><p>怎样称为一个好学生？遵纪守法的前提下，学习成绩好是一个好学生、品德高尚也是一个好学生；（只要违法乱纪就绝对不是一个好学生；成绩和品德有一项，再加遵纪守法也是好学生）<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200519103627.png" alt><br><font color="red">-代表任意值</font></p></blockquote><h2 id="场景法"><a href="#场景法" class="headerlink" title="场景法"></a>场景法</h2><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><blockquote><p>场景法就是模拟用户操作软件时的场景，主要用于测试系统的业务流程。  </p></blockquote><ul><li>当拿到一个测试任务时，我们不是先关注某个控件的边界值、等价类是否满足要求而是先要关注它的主要功能和业务流程是否正确实现，这就需要使用场景法来完成测试</li><li>当业务淘程测试没有问题，也就是该软件的主要功能没有问题时，我重点从边界值、等价<blockquote><p><strong>在冒烟测试时也主要采用场景法进行测试</strong><br><a href="https://blog.csdn.net/wang122188/article/details/7106619" target="_blank" rel="noopener">案例</a></p></blockquote><h3 id="用例场景的定义"><a href="#用例场景的定义" class="headerlink" title="用例场景的定义"></a>用例场景的定义</h3></li><li>场景法中两个重要的概念<ul><li>基本流：按照正确的业务流程来实现的一条操作路径（模拟正确的操作流程</li><li>备选流：导致程序出现错误的操作流程（模拟错误的操作流程）</li><li>还有补充一些异常情况</li></ul></li><li>用例场景是用来描述流经用例路径的过程，这个过程从开始到结束遍方用例中所有基本流和备选流。</li><li>场景法设计测试用例时，需要覆盖系统用例中的<font color="red">主成功场景</font>和<font color="red">扩展场景</font></li><li>事件的触发时的情景便形成<strong>场景</strong></li><li>同一事件的不同触发顺序和处理结果形成了<strong>事件流</strong></li></ul><p><strong>案例</strong>  </p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">使用场景法测试QQ登录功能。</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><span class="line">- 输入错误的账号，正确的密码，点击“登录”按钮，程序应给出错误提示</span><br><span class="line">（更多……）</span><br><span class="line">*********列出测试用例矩阵*************</span><br></pre></td></tr></table></figure><h2 id="流程分析法"><a href="#流程分析法" class="headerlink" title="流程分析法"></a>流程分析法</h2><blockquote><p>流程分析法主要是针对测试场景类型属于流程测试场景的测试项下的测试子项进行设计，是从白盒测试设计方法中的路径覆盖分析法借鉴过来的一种方法。</p></blockquote><ul><li>在白盒测试中，路径就是指函数代码的某个分支组合，路径覆盖法需要构造足够的用例覆盖函数的所有代码路径。(就是测试所有分支)</li><li>在黑盒测试中，若将软件系统的某个流程看成路径的话，则可以针对该路径使用路径分析的方法设计测试用例</li></ul><p><strong>优点</strong>  </p><ul><li>降低了测试用例设计难度，只要搞清楚各种流程，就可以设计出高质量的测试用例来，而不需要太多测试方面的经验</li><li>在测试时间较迫的情况下，可以有的放矢的选择测试用例，而不用完全根据经来取舍<h3 id="流程分析法步骤"><a href="#流程分析法步骤" class="headerlink" title="流程分析法步骤"></a>流程分析法步骤</h3></li><li>第一步：详细了解需求；</li><li>第二步：根据需求说明或界面原型，找出业务流程的各个页面以及各页面之间的流转关系；</li><li>第三步：画出业务流程（产品经理使用 Axure软件制作）；</li><li>第四步：写用例，覆盖所有的路径分支<br><a href="https://zhuanlan.zhihu.com/p/130490121" target="_blank" rel="noopener">案例</a></li></ul><h3 id="流程分析法的总结"><a href="#流程分析法的总结" class="headerlink" title="流程分析法的总结"></a>流程分析法的总结</h3><blockquote><p>流程分析法适用于有先后顺序的测试:常用于业务流程、安装流程等<br>流程测试没有问题并不能说明系统功能没有问题<br>还需要针对每步功能进行测试。对于包含复杂流程的系统，只有功能点和处理流程都进行测试覆盖，才算是比较充分的测试。  </p></blockquote><h2 id="错误推测法"><a href="#错误推测法" class="headerlink" title="错误推测法"></a>错误推测法</h2><blockquote><p>错误推测法是指利用直觉和经验猜测出出错的可能类型，有针对性列举出程序中所有可能的错误和容易发生错误的情况，它是测试经验丰富的测试人员喜欢使用的一种测试用例设计方法</p></blockquote><h2 id="正交表"><a href="#正交表" class="headerlink" title="正交表"></a>正交表</h2><blockquote><p>正交试验设计是研究多因素多水平的一种设计方法，它是根据正交性从全面试验中挑选出部分有代表性的点进行试验，这些有代表性的点具备了“<mark>均匀分散，齐整可比</mark>”的特点，正交试验设计是一种基于正交表的、高效率、快速、经济的试验设计方法</p></blockquote><h3 id="正交表的概述"><a href="#正交表的概述" class="headerlink" title="正交表的概述"></a>正交表的概述</h3><p>正交表：一种特制的表，一般的正交表记为：L<sub>n</sub>（m<sup>k</sup><!--  -->）</p><ul><li>n是表的行数，也就是需要测试组合的次数+</li><li>K是表的列数，表示控件的个数（因素的个数，或因子个数）</li><li>m是每个控件包含的取值个数（各因素的水平数，即各因素的状态数）<br>如：L<sub>9</sub>(3<sup>4</sup>）</li><li>有4个控件</li><li>每个控件有3个取值</li><li>9为需要测试的组合个数</li><li><font color="red">叫4因素3水平</font><br><a href="https://wenku.baidu.com/view/0f68ec88d0d233d4b14e69f9.html" target="_blank" rel="noopener">常用正交表</a></li></ul><h3 id="正交表使用步骤"><a href="#正交表使用步骤" class="headerlink" title="正交表使用步骤"></a>正交表使用步骤</h3><ol><li>根据所测程序千控件的个数（因素）以每个控件的取值个数（水平），选取适的正交排</li><li>把控件及其取值列举出来，并对其进行编号</li><li>把控件及其取值映射到正交排列表中<ol><li>把正交排列表中的ABCD（因子）分别替换成4个控件</li><li>把每列中的1.2.3（状态）分别换成这个控件的3个取值（水平），排列顺序要按照表中给出的顺序</li></ol></li><li>根据映射好的正交排列表编写测试用例<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200519115810.png" alt></li></ol><ul><li>使用正交排列法的局限性 目前常见的正交排列表只有前面附录文件中给出的几种即使是已有的正交排列表，基本都要求每个控件中取值的个数要相等，这在实际软件中很少遇到。</li><li>没有现成的正交排列表怎么办？<blockquote><p>通过正交排列法的学习，我们更多的应该学习到一种测试思想，也就是在从所有组合集合中选取测试数据时，应该均匀的选取其中的组合作为测试用例，而不要只在某个局部选取数据。</p></blockquote><h3 id="混合正交表"><a href="#混合正交表" class="headerlink" title="混合正交表"></a>混合正交表</h3><h4 id="正交表生成工具Allpairs"><a href="#正交表生成工具Allpairs" class="headerlink" title="正交表生成工具Allpairs"></a>正交表生成工具Allpairs</h4>很对多情况下无法找到合适的正交表，就要使用正交表生成工具使用步骤  <figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">1、制作取值表（只列出数据即可，不用编号）</span><br><span class="line">2、复制取值表的数据，放到文本文档中保存</span><br><span class="line">    （注意不要更改任何格式，例如文件叫Test2.txt）</span><br><span class="line">3、把文本文档放在 allpairs文件夹中</span><br><span class="line">4、 win+r后输入cnd进入控制台</span><br><span class="line">5、进入 allpairs文件夹6、在控制台中输入</span><br><span class="line">    allpairs. exe Test2.txt&gt;Test21.txt</span><br><span class="line">    （Test21是自己起的名字，用来存放生成的组合用例，</span><br><span class="line">    可以自动生成，不必提前建好）</span><br></pre></td></tr></table></figure><h2 id="测试方法的选择"><a href="#测试方法的选择" class="headerlink" title="测试方法的选择"></a>测试方法的选择</h2>在确定测试方法时，应遵循以下原则</li><li>根据程序的重要性和一旦发生故障将造成的损失来确定测试等级和测试重点。</li><li><font color="red">认真选择测试策略</font>，以便能尽可能少的使用测试用例，发现尽可能多的程序错误。因为一次完整的软件测试过后，如果程序中遗留的错误过多并且严重，则表明该次测试是不足的，而测试不足则意味着让用户承担隐藏错误带来的危险，但测试过度又会带来资源的浪费。因此测试需要找到一个平衡点。</li><li>（1）拿到一个测试任务时，先关注它的<font color="red">主要功能和业务流程</font>、业务逻辑是否正确实现，考虑使用<font color="red">场景法</font>。</li><li>（2）需要输入数据的地方，考虑采用<font color="red">等价类划分法</font>，包括输入条件和输出条件的等价划分，将无限测试变成有限测试。</li><li>（3）在任何情况下都必须采用<font color="red">边界值分析法</font>。这种方法设计出的测试用例发现程序错误的能力最强。</li><li>（4）如果程序的功能说明中含有输入条件的<font color="red">组合情况</font>，则一开始就应考虑选用<font color="red">因果图和判定表法</font>。</li><li>（5）对于参数配置类的软件，需要考虑参数之间的组合情况，考虑使用<font color="red">正交排列法选择较少的组合方式</font>（最少的测试用例获得最大的的测试覆盖率）。<br>（6）对照程序逻辑，检查已设计出的测试用例的逻辑覆盖程度。<br>如果<font color="red">没有达到要求</font>的覆盖标准，则应当再<font color="red">补充</font>更多的测试用例。<br>（7）采用<font color="red">错误推断法</font>再追加测试用例—依靠测试工程师的经验和智慧。</li></ul><p><strong>如何选择？</strong>  </p><ol><li>如果测试功能和流程，要使用场景法</li><li>需要输入数据的地方，我们使用等价类划分法，要注意配置边界值划分来测试</li><li>如果有条件组合的情况，我们需要使用因果图法制作判定表</li><li>配置类软件，组合比较多的。我们使用正交表来科学的选择测试用例</li><li>如果没有达到覆盖标准，就增加一些测试用例</li><li>依靠经验追加一些测试用例（错误推断法）</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;等价类划分&quot;&gt;&lt;a href=&quot;#等价类划分&quot; class=&quot;headerlink&quot; title=&quot;等价类划分&quot;&gt;&lt;/a&gt;等价类划分&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;属于黑盒测试，它将不能穷举的测试过程进行分类，从而保证完整性和代表性；思考步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;确定有效等价类和无效等价类&lt;/li&gt;
&lt;li&gt;有效等价类划分（题目条件，还要注意边界值（极值），中间甲堕意找个值)&lt;/li&gt;
&lt;li&gt;无效等价类划分（跟有效等价类相反，其他特殊的情况【中文、英文、特殊符号、空格、空】）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;注意:&lt;/strong&gt; 两个框要一个正确，一个错误，这样才能准确的判断；一定要根据需求来判断预期结  &lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="SoftwareTesting" scheme="https://lyhcc.github.io/categories/SoftwareTesting/"/>
    
    
      <category term="软件测试之软件测试方法" scheme="https://lyhcc.github.io/tags/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E4%B9%8B%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>创建型设计模式</title>
    <link href="https://lyhcc.github.io/post/fcd38b5a.html"/>
    <id>https://lyhcc.github.io/post/fcd38b5a.html</id>
    <published>2020-04-02T04:06:50.257Z</published>
    <updated>2020-04-02T14:30:07.619Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h2><h3 id="单例设计模式介绍"><a href="#单例设计模式介绍" class="headerlink" title="单例设计模式介绍"></a>单例设计模式介绍</h3><blockquote><p>所谓类的单例设计模式，就是采取一定的方法保证在整个的软件系统中，<font color="red">对某个类只能存在一个对象实例</font>，并且该类只提供一个取得其对象实例的方法(静态方法)。<br>比如Hibernate的SessionFactory，它充当数据存储源的代理，并负责创建Session对象。 SessionFactory并不是轻量级的，一般情况下，一个项目通常只需要一个SessionFactory就够，这是就会使用到单例模式。</p></blockquote><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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><br><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></tr></table></figure><h4 id="饿汉式-静态常量"><a href="#饿汉式-静态常量" class="headerlink" title="饿汉式(静态常量)"></a>饿汉式(静态常量)</h4><ol><li>构造器私有化</li><li>类的内部创建对象</li><li>向外暴露一个静态的公共方法<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> Singleton instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><p><strong>优缺点说明：</strong>  </p><ol><li>优点：这种写法比较简单，就是在类装载的时候就完成实例化。避免了线程同步问题。</li><li>缺点：在类装载的时候就完成实例化，<font color="red">没有达到Lazy Loading的效果</font>。如果从始至终从未使用过这个实例，则会<font color="red">造成内存的浪费</font></li><li>这种方式基于classloder机制避免了多线程的同步问题，不过， instance在类装载时就实例化，在单例模式中大多数都是调用getInstance方法， 但是导致类装载的原因有很多种， 因此不能确定有其他的方式（或者其他的静态方法）导致类装载，这时候初始化instance就没有达到lazy loading的效果</li><li>结论：这种单例模式可用， 可能造成内存浪费</li></ol><h4 id="饿汉式（静态代码块）应用实例"><a href="#饿汉式（静态代码块）应用实例" class="headerlink" title="饿汉式（静态代码块）应用实例"></a>饿汉式（静态代码块）应用实例</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">static</span> Singleton instance;</span><br><span class="line"><span class="hljs-keyword">static</span> &#123; </span><br><span class="line">instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点说明：</strong>  </p><p>1) 这种方式和上面的方式其实类似，只不过将类实例化的过程放在了静态代码块中，也是在类装载的时候，就执行静态代码块中的代码，初始化类的实例。优缺点和上面是一样的。<br>2) 结论： 这种单例模式可用，但是可能造成内存浪费</p><h4 id="懒汉式-线程不安全"><a href="#懒汉式-线程不安全" class="headerlink" title="懒汉式(线程不安全)"></a>懒汉式(线程不安全)</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(instance == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点说明：</strong>    </p><p>1) 起到了Lazy Loading的效果，但是只能在单线程下使用。<br>2) 如果在多线程下，一个线程进入了if (singleton == null)判断语句块，还未来得及往下执行，另一个线程也通过了这个判断语句，这时便会产生多个实例。所以在<font color="red">多线程环境下不可使用</font>这种方式<br>3) 结论：在实际开发中，<font color="red">不要使用这种方式</font></p><h4 id="懒汉式-线程安全，同步方法"><a href="#懒汉式-线程安全，同步方法" class="headerlink" title="懒汉式(线程安全，同步方法)"></a>懒汉式(线程安全，同步方法)</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(instance == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>优缺点说明：</p><p>1) 解决了线程不安全问题<br>2) <font color="red">效率太低</font>了，每个线程在想获得类的实例时候，执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了，后面的想获得该类实例，直接return就行了。方法进行同步效率太低<br>3) 结论： 在实际开发中， <font color="red">不推荐使用这种方式</font></p><h4 id="懒汉式-线程安全，同步代码块"><a href="#懒汉式-线程安全，同步代码块" class="headerlink" title="懒汉式(线程安全，同步代码块)"></a>懒汉式(线程安全，同步代码块)</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(instance == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">synchronized</span> (Singleton.class) &#123;</span><br><span class="line">    instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点说明：</strong>  </p><p>1) 这种方式，本意是想对第四种实现方式的改进，因为前面同步方法效率太低，改为同步产生实例化的的代码块<br>2) 但是这种同步并<font color="red">不能起到线程同步的作用</font>。跟第3种实现方式遇到的情形一致，假如一个线程进入了if (singleton == null)判断语句块，还未来得及往下执行，另一个线程也通过了这个判断语句，这时便会产生多个实例<br>3) 结论：在实际开发中， <font color="red">不能使用这种方式</font></p><h4 id="双重检查"><a href="#双重检查" class="headerlink" title="双重检查"></a>双重检查</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> Singleton instance;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(instance == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">synchronized</span> (Singleton.class) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(instance == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">instance = <span class="hljs-keyword">new</span> Singleton();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> instance;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>volatile关键字在Java中，实现变量共享，当一个变量被多个线程使用时，且有一个线程修改，会立刻刷新到主存中，已达到数据同步的效果</p></blockquote><p><strong>优缺点说明：</strong>  </p><p>1) Double-Check概念是多线程开发中常使用到的， 如代码中所示，我们进行了两次if (singleton == null)检查，这样就可以保证线程安全了。<br>2) 这样，实例化代码只用执行一次，后面再次访问时，判断if (singleton == null)，直接return实例化对象，也避免的反复进行方法同步.<br>3) 线程安全；延迟加载；效率较高<br>4) 结论：在实际开发中，<font color="red">推荐使用</font>这种单例设计模式</p><h4 id="静态内部类"><a href="#静态内部类" class="headerlink" title="静态内部类"></a>静态内部类</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>&#123;&#125;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SingletonInstance</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Singleton INSTANCE = <span class="hljs-keyword">new</span> Singleton(); </span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> SingletonInstance.INSTANCE;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点说明：</strong>  </p><p>1) 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。<br>2) <font color="red">静态内部类方式在Singleton类被装载时并不会立即实例化</font>，而是在需要实例化时，调用getInstance方法，才会装载SingletonInstance类，从而完成Singleton的实例化。<br>3) 类的静态属性只会在第一次加载类的时候初始化，所以在这里， JVM帮助我们保证了线程的安全性，在类进行初始化时，别的线程是无法进入的。<br>4) 优点：避免了线程不安全，利用静态内部类特点实现延迟加载，效率高<br>5) 结论：<font color="red">推荐使用</font></p><h4 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h4><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">enum</span> Singleton &#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sayHello</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"Hello"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点说明：</strong></p><p>1) 这借助JDK1.5中添加的枚举来实现单例模式。不仅<font color="red">能避免多线程同步</font>问题，而且还<font color="red">能防止反序列化重新创建新的对象</font>。<br>2) 这种方式是Effective Java作者Josh Bloch 提倡的方式<br>3) 结论：<font color="red">推荐使用</font></p><h3 id="单例模式在JDK中的应用"><a href="#单例模式在JDK中的应用" class="headerlink" title="单例模式在JDK中的应用"></a>单例模式在JDK中的应用</h3><blockquote><p>我们JDK中， java.lang.Runtime就是经典的单例模式(饿汉式)<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200402222751.png" alt></p></blockquote><h3 id="单例模式注意事项和细节说明"><a href="#单例模式注意事项和细节说明" class="headerlink" title="单例模式注意事项和细节说明"></a>单例模式注意事项和细节说明</h3><p>1) 单例模式保证了 系统内存中该类<font color="red">只存在一个对象</font>，节省了系统资源，对于一些需要频繁创建销毁的对象，使用单例模式可以<font color="red">提高系统性能</font><br>2) 当想实例化一个单例类的时候，必须要记住使用相应的获取对象的方法，而不使用new<br>3) 单例模式使用的场景：需要<mark>频繁的进行创建和销毁的对象</mark>、<mark>创建对象时耗时过或耗费资源过多</mark>(即：重量级对象)， 但<mark>又经常用到的对象、工具类对象、频繁访问数据库或文件的对象</mark>(比如数据源、 session工厂等)</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- toc --&gt;

&lt;h2 id=&quot;单例模式&quot;&gt;&lt;a href=&quot;#单例模式&quot; class=&quot;headerlink&quot; title=&quot;单例模式&quot;&gt;&lt;/a&gt;单例模式&lt;/h2&gt;&lt;h3 id=&quot;单例设计模式介绍&quot;&gt;&lt;a href=&quot;#单例设计模式介绍&quot; class=&quot;header
      
    
    </summary>
    
    
      <category term="Java设计模式" scheme="https://lyhcc.github.io/categories/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
    
      <category term="创建型设计模式" scheme="https://lyhcc.github.io/tags/%E5%88%9B%E5%BB%BA%E5%9E%8B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>Java设计模式之设计模式七大原则</title>
    <link href="https://lyhcc.github.io/post/7e3cde45.html"/>
    <id>https://lyhcc.github.io/post/7e3cde45.html</id>
    <published>2020-03-20T01:35:36.311Z</published>
    <updated>2020-03-30T09:39:33.690Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200330173922.png" alt></p><h2 id="单一职责原则"><a href="#单一职责原则" class="headerlink" title="单一职责原则"></a>单一职责原则</h2><h3 id="基本介绍"><a href="#基本介绍" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>对类来说的，即一个类应该只负责一项职责。如类A负责两个不同职责：职责1，职责2。<br>当职责1需求变更而改变A时，可能造成职责2执行错误， 所以需要将类A的粒度分解为A1， A2</p></blockquote><a id="more"></a><h3 id="应用实例"><a href="#应用实例" class="headerlink" title="应用实例"></a>应用实例</h3><ol><li>以水果类为例</li><li>方案一<blockquote><ol><li>在方式1中的eat方法中，违反了单一职责原则</li><li>解决方案非常简单，根据水果的方法不同，分解成不同的类</li></ol></blockquote></li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SingleResposibility01</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">Fruit fruit = <span class="hljs-keyword">new</span> Fruit();</span><br><span class="line">fruit.eat(<span class="hljs-string">"苹果"</span>);</span><br><span class="line">fruit.eat(<span class="hljs-string">"葡萄"</span>);</span><br><span class="line">fruit.eat(<span class="hljs-string">"菠萝"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fruit</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">(String fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在红色的"</span> + fruit);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li>方案二<blockquote><ol><li>遵守单一职责原则</li><li>但是这样做的改动很多大，即将类的分解同时更改客户端</li></ol></blockquote></li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SingleResponsibility02</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">RedFriut redFriut = <span class="hljs-keyword">new</span> RedFriut();</span><br><span class="line">redFriut.eat(<span class="hljs-string">"苹果"</span>);</span><br><span class="line">GreenFruit greenFruit = <span class="hljs-keyword">new</span> GreenFruit();</span><br><span class="line">greenFruit.eat(<span class="hljs-string">"葡萄"</span>);</span><br><span class="line">YellowFruit yellowFruit = <span class="hljs-keyword">new</span> YellowFruit();</span><br><span class="line">yellowFruit.eat(<span class="hljs-string">"菠萝"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RedFriut</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">(String fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在红色的"</span> + fruit);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GreenFruit</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">(String fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在绿色的"</span> + fruit);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">YellowFruit</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">(String fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在黄色的"</span> + fruit);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="4"><li>方案三<blockquote><ol><li>这种修改方法没有对原来的类做大的修改，只是增加方法</li><li>这里虽然没有在类这个级别上遵守单一职责原则，但在方法级别上仍然是遵守单一职责原则</li></ol></blockquote></li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SingleResposibility03</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">MyFruit fruit = <span class="hljs-keyword">new</span> MyFruit();</span><br><span class="line">fruit.eatRedFruit(<span class="hljs-string">"苹果"</span>);</span><br><span class="line">fruit.eatGreenFruit(<span class="hljs-string">"葡萄"</span>);</span><br><span class="line">fruit.eatYellowFruit(<span class="hljs-string">"菠萝"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyFruit</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eatRedFruit</span><span class="hljs-params">(String Fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在吃红色的"</span> + Fruit);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eatGreenFruit</span><span class="hljs-params">(String Fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在吃绿色的"</span> + Fruit);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eatYellowFruit</span><span class="hljs-params">(String Fruit)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"正在吃黄色的"</span> + Fruit);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="单一职责原则注意事项和细节"><a href="#单一职责原则注意事项和细节" class="headerlink" title="单一职责原则注意事项和细节"></a>单一职责原则注意事项和细节</h3><ol><li>降低类的复杂度，一个类只负责一项职责。</li><li>提高类的可读性，可维护性</li><li>降低变更引起的风险</li><li>通常情况下， 我们应当遵守单一职责原则，只有逻辑足够简单，才可以在代码级违反单一职责原则；只有类中方法数量足够少，可以在方法级别保持单一职责原则</li></ol><h2 id="接口隔离原则"><a href="#接口隔离原则" class="headerlink" title="接口隔离原则"></a>接口隔离原则</h2><h3 id="应用实例-1"><a href="#应用实例-1" class="headerlink" title="应用实例"></a>应用实例</h3><blockquote><p>类A通过接口Interface1依赖类C，<br>类B通过接口Interface1依赖类D，<br>请编写代码完成此应用实例<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200320105610.png" alt></p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">interface1</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method3</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method4</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method5</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">interface1</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法1"</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法2"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method3</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法3"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method4</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法4"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method5</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法5"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">D</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">interface1</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法1"</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法2"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method3</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法3"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method4</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法4"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method5</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法5"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend1</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method1();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend2</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method2();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend3</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method3();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend1</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method1();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend4</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method4();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend5</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method5();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="应传统方法的问题和使用接口隔离原则改进"><a href="#应传统方法的问题和使用接口隔离原则改进" class="headerlink" title="应传统方法的问题和使用接口隔离原则改进"></a>应传统方法的问题和使用接口隔离原则改进</h3><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200320104727.png" alt></p><ol><li>类A通过接口Interface1依赖类B，类C通过接口Interface1依赖类D，如果接口<br>Interface1对于类A和类B来说不是最小接口，那么类C和类D必须去实现他们不<br>需要的方法</li><li>将接口Interface1拆分为独立的几个接口，类A和类B分别与他们需要的接口建立<br>依赖关系。也就是采用接口隔离原则</li><li>接口Interface1中出现的方法，根据实际情况拆分为三个接口</li><li>代码实现<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Segregation</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">A a = <span class="hljs-keyword">new</span> A();</span><br><span class="line">C c = <span class="hljs-keyword">new</span> C();</span><br><span class="line">a.depend1(c);</span><br><span class="line">a.depend2(c);</span><br><span class="line">a.depend3(c);</span><br><span class="line"></span><br><span class="line">B b = <span class="hljs-keyword">new</span> B();</span><br><span class="line">D d = <span class="hljs-keyword">new</span> D();</span><br><span class="line">b.depend1(d);</span><br><span class="line">b.depend4(d);</span><br><span class="line">b.depend5(d);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">interface1</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">interface2</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method3</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">interface3</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method4</span><span class="hljs-params">()</span></span>;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method5</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">interface1</span>,<span class="hljs-title">interface2</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口1的方法1"</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口2的方法2"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method3</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"C 实现了接口2的方法3"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">D</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">interface1</span>,<span class="hljs-title">interface3</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口1的方法1"</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method4</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口3的方法4"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method5</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"D 实现了接口3的方法5"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend1</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method1();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend2</span><span class="hljs-params">(interface2 i)</span> </span>&#123;</span><br><span class="line">i.method2();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend3</span><span class="hljs-params">(interface2 i)</span> </span>&#123;</span><br><span class="line">i.method3();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend1</span><span class="hljs-params">(interface1 i)</span> </span>&#123;</span><br><span class="line">i.method1();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend4</span><span class="hljs-params">(interface3 i)</span> </span>&#123;</span><br><span class="line">i.method4();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">depend5</span><span class="hljs-params">(interface3 i)</span> </span>&#123;</span><br><span class="line">i.method5();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="依赖倒转原则"><a href="#依赖倒转原则" class="headerlink" title="依赖倒转原则"></a>依赖倒转原则</h2><h3 id="基本介绍-1"><a href="#基本介绍-1" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>依赖倒转原则(Dependence Inversion Principle)是指：<br>1) 高层模块不应该依赖低层模块，二者都应该依赖其抽象<br>2) 抽象不应该依赖细节，细节应该依赖抽象<br>3) 依赖倒转(倒置)的中心思想是面向接口编程<br>4) 依赖倒转原则是基于这样的设计理念：相对于细节的多变性，抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中，抽象指的是接口或抽象类，细节就是具体的实现类<br>5) 使用接口或抽象类的目的是制定好规范，而不涉及任何具体的操作，把展现细节的任务交给他们的实现类去完成</p></blockquote></li></ol><h3 id="应用实例-2"><a href="#应用实例-2" class="headerlink" title="应用实例"></a>应用实例</h3><ol><li>接口传递</li><li>构造方法传递</li><li>setter方法传递</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DInversion</span> </span>&#123;</span><br><span class="line">Food food;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="hljs-comment">//1. 接口传递</span></span><br><span class="line">Fruit fruit = <span class="hljs-keyword">new</span> Fruit();</span><br><span class="line">Operation operation = <span class="hljs-keyword">new</span> Operation();</span><br><span class="line">operation.operate(fruit);</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">//2. 构造方法传递</span></span><br><span class="line">Operation operation2 = <span class="hljs-keyword">new</span> Operation(<span class="hljs-keyword">new</span> Vegetable());</span><br><span class="line">operation2.operate();</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">//3. setter方法传递</span></span><br><span class="line">Operation operation3 = <span class="hljs-keyword">new</span> Operation();</span><br><span class="line">operation3.setFood(fruit);</span><br><span class="line">operation3.operate();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Operation</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> Food food;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Operation</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Operation</span><span class="hljs-params">(Food food)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.food = food;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setFood</span><span class="hljs-params">(Food food)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.food = food;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operate</span><span class="hljs-params">(Food food)</span> </span>&#123;</span><br><span class="line">food.eat();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operate</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">food.eat();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Food</span></span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vegetable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Food</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"吃蔬菜..."</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fruit</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Food</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"吃水果.."</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="依赖转换原则的注意事项和细节"><a href="#依赖转换原则的注意事项和细节" class="headerlink" title="依赖转换原则的注意事项和细节"></a>依赖转换原则的注意事项和细节</h3><blockquote><p>1) 低层模块尽量都要有抽象类或接口，或者两者都有，程序稳定性更好.<br>2) 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间，就存在一个缓冲层，利于程序扩展和优化<br>3) 继承时遵循里氏替换原则</p></blockquote><h2 id="里氏替换原则"><a href="#里氏替换原则" class="headerlink" title="里氏替换原则"></a>里氏替换原则</h2><h3 id="OO中的继承性的思考和说明"><a href="#OO中的继承性的思考和说明" class="headerlink" title="OO中的继承性的思考和说明"></a>OO中的继承性的思考和说明</h3><blockquote><p>1) 继承包含这样一层含义：父类中凡是已经实现好的方法， 实际上是在设定规范和契约，虽然它不强制要求所有的子类必须遵循这些契约，但是如果子类对这些已经实现的方法任意修改，就会对整个继承体系造成破坏。<br>2) 继承在给程序设计带来便利的同时，也带来了弊端。比如使用继承会给程序带来侵入性，程序的可移植性降低，增加对象间的耦合性，如果一个类被其他的类所继承，则当这个类需要修改时，必须考虑到所有的子类，并且父类修改后，所有涉及到子类的功能都有可能产生故障<br>3) 问题提出：在编程中，如何正确的使用继承? =&gt; 里氏替换原则</p></blockquote><h3 id="基本介绍-2"><a href="#基本介绍-2" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>1) 里氏替换原则 <strong>(Liskov Substitution Principle)</strong> 在1988年，由麻省理工学院的以为姓里的女士提出的。<br>2) 如果对每个类型为T1的对象o1，都有类型为T2的对象o2，使得以T1定义的所有程序P在所有的对象o1都代换成o2时，程序P的行为没有发生变化，那么类型T2类型T1的子类型。换句话说，所有引用基类的地方必须能透明地使用其子类的对象。<br>3) 在使用继承时，遵循里氏替换原则，在子类中尽量不要重写父类的方法<br>4) 里氏替换原则告诉我们，继承实际上让两个类耦合性增强了， <strong>在适当的情况下</strong>，可以通过 <strong>聚合，组合，依赖</strong> 来解决问题。</p></blockquote><h3 id="一个程序引出问题思考"><a href="#一个程序引出问题思考" class="headerlink" title="一个程序引出问题思考"></a>一个程序引出问题思考</h3><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200323124246.png" alt><br><strong>解决方法</strong>  </p><blockquote><p>1) 我们发现原来运行正常的相减功能发生了错误。原因就是类B无意中重写了父类的方法，造成原有功能出现错误。在实际编程中，我们常常会通过重写父类的方法完成新的功能，这样写起来虽然简单，但整个继承体系的复用性会比较差。特别是运行多态比较频繁的时候<br>2) 通用的做法是：原来的父类和子类都继承一个更通俗的基类，原有的继承关系去掉，采用依赖，聚合，组合等关系代替<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200324102205.png" alt></p></blockquote><h2 id="开闭原则"><a href="#开闭原则" class="headerlink" title="开闭原则"></a>开闭原则</h2><h3 id="基本介绍-3"><a href="#基本介绍-3" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>1) 开闭原则（Open Closed Principle） 是编程中最基础、最重要的设计原则<br>2) 一个软件实体如类，模块和函数应该对扩展开放(对提供方)， 对修改关闭(对使用方)。 用抽象构建框架，用实现扩展细节。  ( <strong>这里的使用放是指调用</strong> )<br>3) 当软件需要变化时，尽量通过扩展软件实体的行为来实现变化，而不是通过修改已有的代码来实现变化。<br>4) 编程中遵循其它原则，以及使用设计模式的目的就是遵循开闭原则</p></blockquote><h3 id="看下面一段代码"><a href="#看下面一段代码" class="headerlink" title="看下面一段代码"></a>看下面一段代码</h3><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200325102253.png" alt></p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Test</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">GraphicEditor graphicEditor = <span class="hljs-keyword">new</span> GraphicEditor();</span><br><span class="line">graphicEditor.drawCircle(<span class="hljs-keyword">new</span> Circle());</span><br><span class="line">graphicEditor.drawRectangle(<span class="hljs-keyword">new</span> Rectangle());</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GraphicEditor</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawShape</span><span class="hljs-params">(Shape s)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (s.m_type == <span class="hljs-number">1</span>)</span><br><span class="line">drawRectangle(s);</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (s.m_type == <span class="hljs-number">2</span>)</span><br><span class="line">drawCircle(s);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawRectangle</span><span class="hljs-params">(Shape r)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"矩形"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawCircle</span><span class="hljs-params">(Shape r)</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"圆形"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">int</span> m_type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line">Rectangle() &#123;</span><br><span class="line"><span class="hljs-keyword">super</span>.m_type = <span class="hljs-number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line">Circle() &#123;</span><br><span class="line"><span class="hljs-keyword">super</span>.m_type = <span class="hljs-number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>优缺点</strong>    </p><blockquote><p>1) 优点是比较好理解，简单易操作。<br>2) 缺点是违反了设计模式的ocp原则，即对扩展开放(提供方)，对修改关闭(使用方)。即当我们给类增加新功能的时候，尽量不修改代码，或者尽可能少修改代码.<br>3) 比如我们这时要新增加一个图形种类 三角形，我们需要做如下修改， 修改的地方较多</p></blockquote><h3 id="代码改进改进"><a href="#代码改进改进" class="headerlink" title="代码改进改进"></a>代码改进改进</h3><p><font color="red">改进的思路分析</font><br><strong>思路：</strong>  把创建Shape类做成抽象类，并提供一个抽象的draw方法，让子类去实现即可，这样我们有新的图形种类时，只需要让新的图形类继承Shape，并实现draw方法即可，<br>使用方的代码就不需要修 -&gt; <font color="red">满足了开闭原则</font></p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OCP</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">GraphicEditor graphicEditor = <span class="hljs-keyword">new</span> GraphicEditor();</span><br><span class="line">graphicEditor.drawShape(<span class="hljs-keyword">new</span> Rectangle());</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">//增加图形而不更改调用的方法，（使用方）</span></span><br><span class="line"><span class="hljs-comment">//正在运行的方法位置（提供方）</span></span><br><span class="line">graphicEditor.drawShape(<span class="hljs-keyword">new</span> Triangle());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 使用方</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GraphicEditor</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawShape</span><span class="hljs-params">(Shape s)</span> </span>&#123;</span><br><span class="line">s.draw();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">int</span> m_type;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line">Rectangle() &#123;</span><br><span class="line"><span class="hljs-keyword">super</span>.m_type = <span class="hljs-number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"画矩形"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>&#123;</span><br><span class="line">Circle() &#123;</span><br><span class="line"><span class="hljs-keyword">super</span>.m_type = <span class="hljs-number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"画圆"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Triangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Triangle</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>.m_type = <span class="hljs-number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"画三角形"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="迪米特法则"><a href="#迪米特法则" class="headerlink" title="迪米特法则"></a>迪米特法则</h2><h3 id="基本介绍-4"><a href="#基本介绍-4" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>1) 一个对象应该对其他对象保持最少的了解<br>2) 类与类关系越密切，耦合度越大<br>3) 迪米特法则(Demeter Principle)又叫<strong>最少知道原则</strong>，即<strong>一个类对自己依赖的类知道的越少越好</strong>。也就是说，对于被依赖的类不管多么复杂，都尽量将逻辑封装在类的内部。对外除了提供的public 方法，不对外泄露任何信息<br>4) 迪米特法则还有个更简单的定义：*<em>只与直接的朋友通信  *</em><br>5) 直接的朋友：每个对象都会与其他对象有耦合关系，只要两个对象之间有耦合关系，我们就说这两个对象之间是朋友关系。耦合的方式很多，依赖，关联，组合，聚合等。其中，我们称出现<font color="red">成员变量，方法参数，方法返回值</font>中的类为直接的朋友，而出现在局部变量中的类不是直接的朋友。也就是说，陌生的类最好不要以局部变量的形式出现在类的内部</p></blockquote><h3 id="应用实例-3"><a href="#应用实例-3" class="headerlink" title="应用实例"></a>应用实例</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demeter</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">new</span> PoisonousAirMaking().make(<span class="hljs-keyword">new</span> GeneralAirMaking());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GeneralAirMaking</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> ArrayList&lt;GeneralAir&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> ArrayList&lt;GeneralAir&gt; <span class="hljs-title">retrieve</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"氧气"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"二氧化碳"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"氮气"</span>));</span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoisonousAirMaking</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> ArrayList&lt;PoisonousAir&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> ArrayList&lt;PoisonousAir&gt; <span class="hljs-title">retrieve</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"一氧化碳"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"氨气"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"二氧化硫"</span>));</span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">make</span><span class="hljs-params">(GeneralAirMaking sub)</span> </span>&#123;</span><br><span class="line">retrieve();</span><br><span class="line"><span class="hljs-keyword">for</span>(PoisonousAir paAir:list) &#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"有毒气体--"</span>+paAir.getType());</span><br><span class="line">&#125;</span><br><span class="line">System.out.println(<span class="hljs-string">"---"</span>);</span><br><span class="line">ArrayList&lt;GeneralAir&gt; list2 = sub.retrieve();</span><br><span class="line"><span class="hljs-keyword">for</span>(GeneralAir gAir: list2) &#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"普通气体--"</span> + gAir.getType());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GeneralAir</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> String type;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">GeneralAir</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setType</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoisonousAir</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> String type;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PoisonousAir</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setType</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="应用实例改进"><a href="#应用实例改进" class="headerlink" title="应用实例改进"></a>应用实例改进</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demeter</span> </span>&#123;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">new</span> PoisonousAirMaking().make(<span class="hljs-keyword">new</span> GeneralAirMaking());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GeneralAirMaking</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> ArrayList&lt;GeneralAir&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> ArrayList&lt;GeneralAir&gt; <span class="hljs-title">retrieve</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"氧气"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"二氧化碳"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> GeneralAir(<span class="hljs-string">"氮气"</span>));</span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">make</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">retrieve();</span><br><span class="line"><span class="hljs-keyword">for</span>(GeneralAir gAir: list) &#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"普通气体--"</span> + gAir.getType());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoisonousAirMaking</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> ArrayList&lt;PoisonousAir&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> ArrayList&lt;PoisonousAir&gt; <span class="hljs-title">retrieve</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"一氧化碳"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"氨气"</span>));</span><br><span class="line">list.add(<span class="hljs-keyword">new</span> PoisonousAir(<span class="hljs-string">"二氧化硫"</span>));</span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">make</span><span class="hljs-params">(GeneralAirMaking sub)</span> </span>&#123;</span><br><span class="line">retrieve();</span><br><span class="line"><span class="hljs-keyword">for</span>(PoisonousAir paAir:list) &#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"有毒气体--"</span>+paAir.getType());</span><br><span class="line">&#125;</span><br><span class="line">System.out.println(<span class="hljs-string">"---"</span>);</span><br><span class="line">sub.make();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GeneralAir</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> String type;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">GeneralAir</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setType</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoisonousAir</span></span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> String type;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PoisonousAir</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> type;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setType</span><span class="hljs-params">(String type)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.type = type;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="迪米特法则注意事项和细节"><a href="#迪米特法则注意事项和细节" class="headerlink" title="迪米特法则注意事项和细节"></a>迪米特法则注意事项和细节</h3><blockquote><p>1) 迪米特法则的核心是*<em>降低类之间的耦合  *</em><br>2) 但是注意：由于每个类都减少了不必要的依赖，因此迪米特法则只是要求降低类间(对象间)耦合关系， 并不是要求完全没有依赖关系</p></blockquote><h2 id="合成复用原则（Composite-Reuse-Principle）"><a href="#合成复用原则（Composite-Reuse-Principle）" class="headerlink" title="合成复用原则（Composite Reuse Principle）"></a>合成复用原则（Composite Reuse Principle）</h2><h3 id="基本介绍-5"><a href="#基本介绍-5" class="headerlink" title="基本介绍"></a>基本介绍</h3><blockquote><p>原则是尽量使用合成/聚合的方式，而不是使用继承<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200328114628.png" alt></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;p&gt;&lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200330173922.png&quot; alt&gt;&lt;/p&gt;
&lt;h2 id=&quot;单一职责原则&quot;&gt;&lt;a href=&quot;#单一职责原则&quot; class=&quot;headerlink&quot; title=&quot;单一职责原则&quot;&gt;&lt;/a&gt;单一职责原则&lt;/h2&gt;&lt;h3 id=&quot;基本介绍&quot;&gt;&lt;a href=&quot;#基本介绍&quot; class=&quot;headerlink&quot; title=&quot;基本介绍&quot;&gt;&lt;/a&gt;基本介绍&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;对类来说的，即一个类应该只负责一项职责。如类A负责两个不同职责：职责1，职责2。&lt;br&gt;当职责1需求变更而改变A时，可能造成职责2执行错误， 所以需要将类A的粒度分解为A1， A2&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
    
      <category term="Java设计模式之设计模式七大原则" scheme="https://lyhcc.github.io/tags/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%83%E5%A4%A7%E5%8E%9F%E5%88%99/"/>
    
  </entry>
  
  <entry>
    <title>Java设计模式面试题</title>
    <link href="https://lyhcc.github.io/post/9174d842.html"/>
    <id>https://lyhcc.github.io/post/9174d842.html</id>
    <published>2020-03-18T02:25:27.268Z</published>
    <updated>2020-03-20T02:01:19.932Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><ol><li>有请使用UML类图画出原型模式核心角色</li><li>原型设计模式的深拷贝和浅拷贝是什么，并写出深拷贝的两种方式的源码(重写<br>clone方法实现深拷贝、 使用序列化来实现深拷贝)</li><li>在Spring框架中哪里使用到原型模式，并对源码进行分析<blockquote><p>beans.xml</p></blockquote><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"id01"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.atguigu.spring.bean.Monster"</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"prototype"</span>/&gt;</span></span><br></pre></td></tr></table></figure></li></ol><a id="more"></a><ol start="4"><li><p>Spring中原型bean的创建，就是原型模式的应用</p></li><li><p>代码分析+Debug源码<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318110520.png" alt></p></li><li><p><strong>设计模式的七大原则</strong> : 要求： 1) 七大设计原则核心思想 2) 能够以类图的说明设计原则 3) 在项目实际开发中，你在哪里使用到了ocp原则</p><blockquote><p><strong>设计模式常用的七大原则有:</strong> </p></blockquote><ol><li>单一职责原则</li><li>接口隔离原则</li><li>依赖倒转原则</li><li>里氏替换原则</li><li>开闭原则ocp</li><li>迪米特法则</li><li>合成复用原则<blockquote><p> <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318110744.png" alt></p></blockquote></li></ol></li><li><p>给定案例让你解释对应的设计模式</p><blockquote><p> <strong>金融借贷平台项目：</strong>  借贷平台的订单，有审核-发布-抢单 等等 步骤，随着操作的不同，会改变订单的状态, 项目中的这个模块实现就会使用到状态模式，请你使用状态模式进行设计，并完成实际代码<br><strong>问题分析 ：</strong><br>这类代码难以应对变化，在添加一种状态时，我们需要手动添加if/else，在添加一种功能时，要对所有的状态进行判断。因此代码会变得越来越臃肿，并且一旦没有处理某个状态，便会发生极其严重的BUG，难以维护<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318111057.png" alt><br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318111121.png" alt></p></blockquote></li><li><p>解释器设计模式</p><blockquote><p>1) 介绍解释器设计模式是什么?<br>2) 画出解释器设计模式的UML类图,分析设计模式中的各个角色是什么?<br>3) 请说明Spring的框架中，哪里使用到了解释器设计模式，并做源码级别的分析<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318111248.png" alt></p></blockquote></li><li><p>解释器模式在Spring框架应用的源码剖析<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318111345.png" alt></p></li><li><p>单例设计模式一共有几种实现方式？请分别用代码实现，并说明各个实现方式的优点和缺点?</p><blockquote><p>单例设计模式一共有8种写法，<br>1) 饿汉式 两种<br>2) 懒汉式 三种<br>3) 双重检查<br>4) 静态内部类<br>5) 枚举</p></blockquote></li></ol><hr><p><strong>设计模式的重要性</strong>  </p><ol><li>软件工程中， 设计模式（design pattern）是对软件设计中普遍存在（反复出现）<br>的各种问题，所提出的解决方案。这个术语是由埃里希·伽玛（Erich Gamma）等人<br>在1990年代从建筑设计领域引入到计算机科学的</li><li>大厦 VS 简易房<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200318111608.png" alt></li><li>拿实际工作经历来说, 当一个项目开发完后，如果客户提出增新功能，怎么办?。<mark>可扩展性，使用设计模式，使软件具有更好的扩展性</mark></li><li>如果项目开发完后，原来程序员离职，你接手维护该项目怎么办? (维护性[可读性、规范性])</li><li>目前程序员门槛越来越高，一线IT公司(大厂)，都会问你在实际项目中使用过什么设计模式，怎样使用的，解决了什么问题。</li><li>设计模式在软件中哪里？<mark>面向对象(oo)=&gt;功能模块[设计模式+算法(数据结构)]=&gt;框架[使用到多种设计模式]=&gt;架构 [服务器集群]</mark></li><li>如果想成为合格软件 <strong>工程师</strong> ， 那就花时间来研究下设计模式是非常必要的</li></ol><hr>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;ol&gt;
&lt;li&gt;有请使用UML类图画出原型模式核心角色&lt;/li&gt;
&lt;li&gt;原型设计模式的深拷贝和浅拷贝是什么，并写出深拷贝的两种方式的源码(重写&lt;br&gt;clone方法实现深拷贝、 使用序列化来实现深拷贝)&lt;/li&gt;
&lt;li&gt;在Spring框架中哪里使用到原型模式，并对源码进行分析&lt;blockquote&gt;
&lt;p&gt;beans.xml&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;highlight xml hljs&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;bean&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;id01&quot;&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;com.atguigu.spring.bean.Monster&quot;&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;scope&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;prototype&quot;&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="Java设计模式" scheme="https://lyhcc.github.io/categories/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
    
      <category term="Java设计模式面试题" scheme="https://lyhcc.github.io/tags/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E9%9D%A2%E8%AF%95%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>56. Merge Intervals</title>
    <link href="https://lyhcc.github.io/post/15fe401e.html"/>
    <id>https://lyhcc.github.io/post/15fe401e.html</id>
    <published>2020-03-09T15:20:47.250Z</published>
    <updated>2020-03-09T15:25:33.752Z</updated>
    
    <content type="html"><![CDATA[<h1 id="56-Merge-Intervals"><a href="#56-Merge-Intervals" class="headerlink" title="56. Merge Intervals"></a>56. Merge Intervals</h1><p><a href="https://leetcode.com/problems/merge-intervals/" target="_blank" rel="noopener">题目</a></p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[][] merge(<span class="hljs-keyword">int</span>[][] a) &#123;</span><br><span class="line">  <span class="hljs-comment">//1. 先去除a为空的情况</span></span><br><span class="line">  <span class="hljs-keyword">if</span>(a.length==<span class="hljs-number">0</span>)<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[][]&#123;&#125;;</span><br><span class="line">  Integer[][] intervals = <span class="hljs-keyword">new</span> Integer[a.length][a[<span class="hljs-number">0</span>].length];</span><br><span class="line">  <span class="hljs-comment">//2. 为了方便排序，将其转换为Integer数组</span></span><br><span class="line">  cpy(a, intervals);</span><br><span class="line">  </span><br><span class="line">  <span class="hljs-comment">//3. 排序</span></span><br><span class="line">  Arrays.sort(intervals, <span class="hljs-keyword">new</span> Comparator&lt;Integer[]&gt;() &#123;</span><br><span class="line"></span><br><span class="line">   <span class="hljs-meta">@Override</span></span><br><span class="line">              <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Integer[] x, Integer[] y)</span> </span>&#123;</span><br><span class="line">                  <span class="hljs-keyword">if</span>(x[<span class="hljs-number">0</span>] &lt; y[<span class="hljs-number">0</span>])&#123;</span><br><span class="line">                      <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;</span><br><span class="line">                  &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(x[<span class="hljs-number">0</span>] &gt; y[<span class="hljs-number">0</span>])&#123;</span><br><span class="line">                      <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;</span><br><span class="line">                  &#125; <span class="hljs-keyword">else</span> &#123;</span><br><span class="line">                      <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">&#125;);</span><br><span class="line"><span class="hljs-comment">//4. 遍历查找是否相交</span></span><br><span class="line">  ArrayList&lt;Integer[]&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;intervals.length;i++) &#123;</span><br><span class="line">  <span class="hljs-keyword">int</span> j = i;</span><br><span class="line">  Integer[] tIntegers = <span class="hljs-keyword">new</span> Integer[<span class="hljs-number">2</span>];</span><br><span class="line">  tIntegers[<span class="hljs-number">0</span>] = intervals[i][<span class="hljs-number">0</span>];</span><br><span class="line">  tIntegers[<span class="hljs-number">1</span>] = intervals[i][<span class="hljs-number">1</span>];</span><br><span class="line">  <span class="hljs-comment">//有相交的情况</span></span><br><span class="line">  <span class="hljs-keyword">while</span>(i+<span class="hljs-number">1</span>&lt;=intervals.length-<span class="hljs-number">1</span>&amp;&amp;intervals[i+<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]&lt;=tIntegers[<span class="hljs-number">1</span>]) &#123;</span><br><span class="line">  <span class="hljs-keyword">if</span>(intervals[i+<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]&gt;tIntegers[<span class="hljs-number">1</span>]) &#123;</span><br><span class="line">  tIntegers[<span class="hljs-number">1</span>] = intervals[i+<span class="hljs-number">1</span>][<span class="hljs-number">1</span>];</span><br><span class="line">  &#125;</span><br><span class="line">  i++;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  list.add(tIntegers);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="hljs-comment">//5. 转换为int[][]返回</span></span><br><span class="line">  <span class="hljs-keyword">int</span>[][] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[list.size()][<span class="hljs-number">2</span>];</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;list.size();i++) &#123;</span><br><span class="line">  Integer[] integers = list.get(i);</span><br><span class="line">  res[i][<span class="hljs-number">0</span>] = integers[<span class="hljs-number">0</span>];</span><br><span class="line">  res[i][<span class="hljs-number">1</span>] = integers[<span class="hljs-number">1</span>];</span><br><span class="line">  &#125;</span><br><span class="line"><span class="hljs-keyword">return</span> res;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;56-Merge-Intervals&quot;&gt;&lt;a href=&quot;#56-Merge-Intervals&quot; class=&quot;headerlink&quot; title=&quot;56. Merge Intervals&quot;&gt;&lt;/a&gt;56. Merge Intervals&lt;/h1&gt;&lt;p&gt;&lt;a h
      
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>Leetcode/55. Jump Game</title>
    <link href="https://lyhcc.github.io/post/630c2358.html"/>
    <id>https://lyhcc.github.io/post/630c2358.html</id>
    <published>2020-03-03T14:33:20.937Z</published>
    <updated>2020-03-03T14:41:22.622Z</updated>
    
    <content type="html"><![CDATA[<h1 id="55-Jump-Game"><a href="#55-Jump-Game" class="headerlink" title="55. Jump Game"></a>55. Jump Game</h1><p><a href="https://leetcode.com/problems/jump-game/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><ol><li>判断是否到达或者不能到达</li><li>继续遍历<ol><li>如果当前位置到当前位置可到达最远位置之间，所有点都满足这种情况，就跳到可以跳到的最远位置<br> <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200303223904.png" alt></li><li>不满足，则找最后一个满足的点，这点就是下一步的点</li></ol></li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">canJump</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="hljs-keyword">return</span> jump(nums, <span class="hljs-number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">jump</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> current)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span>(current+nums[current]&gt;=nums.length-<span class="hljs-number">1</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span>(nums[current]==<span class="hljs-number">0</span>)<span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;</span><br><span class="line"><span class="hljs-comment">//找最大</span></span><br><span class="line"><span class="hljs-keyword">int</span> maxi = current+<span class="hljs-number">1</span>;</span><br><span class="line"><span class="hljs-keyword">while</span>(maxi+nums[maxi]&lt;current+nums[current])maxi++;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span>(maxi&lt;current+nums[current]) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> jump(nums, maxi);</span><br><span class="line">&#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> jump(nums, current+nums[current]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;55-Jump-Game&quot;&gt;&lt;a href=&quot;#55-Jump-Game&quot; class=&quot;headerlink&quot; title=&quot;55. Jump Game&quot;&gt;&lt;/a&gt;55. Jump Game&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.co
      
    
    </summary>
    
    
    
  </entry>
  
  <entry>
    <title>54. Spiral Matrix</title>
    <link href="https://lyhcc.github.io/post/f8e18060.html"/>
    <id>https://lyhcc.github.io/post/f8e18060.html</id>
    <published>2020-03-03T12:33:26.824Z</published>
    <updated>2020-03-03T13:39:56.522Z</updated>
    
    <content type="html"><![CDATA[<h1 id="54-Spiral-Matrix"><a href="#54-Spiral-Matrix" class="headerlink" title="54. Spiral Matrix"></a>54. Spiral Matrix</h1><p><a href="https://leetcode.com/problems/spiral-matrix/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><blockquote><p>直接模拟</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">spiralOrder</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">    ArrayList&lt;Integer&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>,j=<span class="hljs-number">0</span>;</span><br><span class="line">    <span class="hljs-keyword">int</span> n=matrix.length;</span><br><span class="line">        <span class="hljs-keyword">if</span>(n==<span class="hljs-number">0</span>)<span class="hljs-keyword">return</span> list;</span><br><span class="line">    <span class="hljs-keyword">int</span> m = matrix[<span class="hljs-number">0</span>].length;</span><br><span class="line">    <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>,loop=<span class="hljs-number">0</span>;</span><br><span class="line">    <span class="hljs-keyword">while</span>(cnt&lt;m*n) &#123;</span><br><span class="line">    <span class="hljs-keyword">while</span>(cnt&lt;n*m&amp;&amp;j&lt;m-loop) &#123;</span><br><span class="line">    list.add(matrix[i][j]);</span><br><span class="line">    cnt++;</span><br><span class="line">    j++;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    j--;</span><br><span class="line">    i++;</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">while</span>(cnt&lt;m*n&amp;&amp;i&lt;n-loop) &#123;</span><br><span class="line">    list.add(matrix[i][j]);</span><br><span class="line">    </span><br><span class="line">    i++;</span><br><span class="line">    cnt++;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    i--;</span><br><span class="line">    j--;</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">while</span>(cnt&lt;m*n&amp;&amp;j&gt;=loop) &#123;</span><br><span class="line">    list.add(matrix[i][j]);</span><br><span class="line">    cnt++;</span><br><span class="line">    j--;</span><br><span class="line">    &#125;</span><br><span class="line">    j++;</span><br><span class="line">    i--;</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">while</span>(cnt&lt;m*n&amp;&amp;i&gt;loop) &#123;</span><br><span class="line">    list.add(matrix[i][j]);</span><br><span class="line">    i--;</span><br><span class="line">    cnt++;</span><br><span class="line">    &#125;</span><br><span class="line">    i++;</span><br><span class="line">    j++;</span><br><span class="line">    loop++;</span><br><span class="line">    <span class="hljs-comment">//System.out.println(list);</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>整理后</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">spiralOrder</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">  ArrayList&lt;Integer&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  </span><br><span class="line">  <span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>,j=<span class="hljs-number">0</span>;</span><br><span class="line">  <span class="hljs-keyword">int</span> m=matrix.length;</span><br><span class="line">      <span class="hljs-keyword">if</span>(m==<span class="hljs-number">0</span>)<span class="hljs-keyword">return</span> list;</span><br><span class="line">  <span class="hljs-keyword">int</span> n = matrix[<span class="hljs-number">0</span>].length;</span><br><span class="line">  <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>,loop=<span class="hljs-number">0</span>;</span><br><span class="line">  <span class="hljs-keyword">while</span>(cnt&lt;m*n) &#123;</span><br><span class="line">  i=loop;</span><br><span class="line">  j=loop;</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=j; k&lt;n-loop;k++,cnt++) &#123;</span><br><span class="line">  list.add(matrix[i][k]);</span><br><span class="line">  &#125;</span><br><span class="line">  j += n-loop-<span class="hljs-number">1</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=i+<span class="hljs-number">1</span>;k&lt;m-loop;k++,cnt++) &#123;</span><br><span class="line">  list.add(matrix[k][j]);</span><br><span class="line">  &#125;</span><br><span class="line">  i += m-loop-<span class="hljs-number">1</span>;</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=j-<span class="hljs-number">1</span>; k&gt;=loop;k--,cnt++) &#123;</span><br><span class="line">  list.add(matrix[i][k]);</span><br><span class="line">  &#125;</span><br><span class="line">  j = loop;</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=i-<span class="hljs-number">1</span>;k&gt;loop;k--,cnt++) &#123;</span><br><span class="line">  list.add(matrix[k][j]);</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  loop++;</span><br><span class="line">  <span class="hljs-comment">//System.out.println(list);</span></span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">      </span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure><blockquote><p>直接使用一个循环</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">spiralOrder</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">  ArrayList&lt;Integer&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  </span><br><span class="line">  <span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>,j=<span class="hljs-number">0</span>;</span><br><span class="line">  <span class="hljs-keyword">int</span> m=matrix.length;</span><br><span class="line">      <span class="hljs-keyword">if</span>(m==<span class="hljs-number">0</span>)<span class="hljs-keyword">return</span> list;</span><br><span class="line">  <span class="hljs-keyword">int</span> n = matrix[<span class="hljs-number">0</span>].length;</span><br><span class="line">  </span><br><span class="line">  <span class="hljs-keyword">int</span>[][] dirs = &#123;&#123;<span class="hljs-number">0</span>,<span class="hljs-number">1</span>&#125;,&#123;<span class="hljs-number">1</span>,<span class="hljs-number">0</span>&#125;,&#123;<span class="hljs-number">0</span>,-<span class="hljs-number">1</span>&#125;,&#123;-<span class="hljs-number">1</span>,<span class="hljs-number">0</span>&#125;&#125;;</span><br><span class="line">  <span class="hljs-keyword">int</span> idx = <span class="hljs-number">0</span>;</span><br><span class="line">  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=<span class="hljs-number">0</span>;k&lt;m*n;k++) &#123;</span><br><span class="line">  </span><br><span class="line">  list.add(matrix[i][j]);</span><br><span class="line">  matrix[i][j] = <span class="hljs-number">1000</span>;</span><br><span class="line">  <span class="hljs-keyword">int</span> x = i + dirs[idx][<span class="hljs-number">0</span>];</span><br><span class="line">  <span class="hljs-keyword">int</span> y = j + dirs[idx][<span class="hljs-number">1</span>];</span><br><span class="line">  <span class="hljs-keyword">if</span>(x&lt;<span class="hljs-number">0</span> || y&lt;<span class="hljs-number">0</span> || x&gt;=m || y&gt;=n || (matrix[x][y]^<span class="hljs-number">1000</span>)==<span class="hljs-number">0</span>) &#123;</span><br><span class="line">  idx = (idx + <span class="hljs-number">1</span>)%<span class="hljs-number">4</span>;</span><br><span class="line">  x = i + dirs[idx][<span class="hljs-number">0</span>];</span><br><span class="line">  y = j + dirs[idx][<span class="hljs-number">1</span>];</span><br><span class="line">  &#125;</span><br><span class="line">  i=x;</span><br><span class="line">  j=y;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">      </span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;54-Spiral-Matrix&quot;&gt;&lt;a href=&quot;#54-Spiral-Matrix&quot; class=&quot;headerlink&quot; title=&quot;54. Spiral Matrix&quot;&gt;&lt;/a&gt;54. Spiral Matrix&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;htt
      
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>51. N-Queens</title>
    <link href="https://lyhcc.github.io/post/7040787d.html"/>
    <id>https://lyhcc.github.io/post/7040787d.html</id>
    <published>2020-02-29T13:19:45.795Z</published>
    <updated>2020-03-01T02:10:02.766Z</updated>
    
    <content type="html"><![CDATA[<h1 id="51-N-Queens"><a href="#51-N-Queens" class="headerlink" title="51. N-Queens"></a>51. N-Queens</h1><p><a href="https://leetcode.com/problems/n-queens/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200229212627.png" alt></p><ol><li>根据上图的方式是否位于同一对角线</li><li>开始按行遍历，在此过程性需要定义一个数组标明是否在对角线，列上已有皇后</li><li>这也就是回朔法，先试着走，不合适回退</li></ol><a id="more"></a><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">boolean</span>[][] visited;</span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;List&lt;String&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;List&lt;String&gt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">public</span> List&lt;List&lt;String&gt;&gt; solveNQueens(<span class="hljs-keyword">int</span> n) &#123;</span><br><span class="line"></span><br><span class="line">        List&lt;StringBuffer&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;StringBuffer&gt;();</span><br><span class="line">        visited = <span class="hljs-keyword">new</span> <span class="hljs-keyword">boolean</span>[<span class="hljs-number">3</span>][n*<span class="hljs-number">2</span>];</span><br><span class="line">        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i&lt;n;i++) &#123;</span><br><span class="line">            StringBuffer sbuf = <span class="hljs-keyword">new</span> StringBuffer();</span><br><span class="line">            <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>;j&lt;n;j++)&#123;</span><br><span class="line">                sbuf.append(<span class="hljs-string">'.'</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        list.add(sbuf);</span><br><span class="line">        &#125;</span><br><span class="line">        search(list, <span class="hljs-number">0</span>, n);</span><br><span class="line">        </span><br><span class="line">        <span class="hljs-keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">search</span><span class="hljs-params">(List&lt;StringBuffer&gt; list, <span class="hljs-keyword">int</span> cur, <span class="hljs-keyword">int</span> n)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(cur==n) &#123;</span><br><span class="line">ArrayList&lt;String&gt; list2 = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="hljs-keyword">for</span>(StringBuffer sb: list) &#123;</span><br><span class="line">list2.add(sb.toString());</span><br><span class="line">&#125;</span><br><span class="line">res.add(list2);</span><br><span class="line"><span class="hljs-keyword">return</span> ;</span><br><span class="line">&#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;n;i++) &#123;</span><br><span class="line"><span class="hljs-comment">//System.out.println(cur-i+n+";;"+visited[0].length);</span></span><br><span class="line"><span class="hljs-keyword">if</span>(!visited[<span class="hljs-number">0</span>][i]&amp;&amp;!visited[<span class="hljs-number">1</span>][cur+i]</span><br><span class="line">&amp;&amp;!visited[<span class="hljs-number">2</span>][cur-i+n]) &#123;</span><br><span class="line">list.get(cur).setCharAt(i, <span class="hljs-string">'Q'</span>);</span><br><span class="line">visited[<span class="hljs-number">0</span>][i] = visited[<span class="hljs-number">1</span>][cur+i] = visited[<span class="hljs-number">2</span>][cur-i+n]=<span class="hljs-keyword">true</span>;</span><br><span class="line">search(list, cur+<span class="hljs-number">1</span>, n);</span><br><span class="line"></span><br><span class="line">list.get(cur).setCharAt(i, <span class="hljs-string">'.'</span>);</span><br><span class="line">visited[<span class="hljs-number">0</span>][i] = visited[<span class="hljs-number">1</span>][cur+i] = visited[<span class="hljs-number">2</span>][cur-i+n] = <span class="hljs-keyword">false</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="更快速的方法"><a href="#更快速的方法" class="headerlink" title="更快速的方法"></a>更快速的方法</h2><p><a href="https://www.cnblogs.com/1625--H/p/11664546.html" target="_blank" rel="noopener">参考链接</a></p><hr>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;51-N-Queens&quot;&gt;&lt;a href=&quot;#51-N-Queens&quot; class=&quot;headerlink&quot; title=&quot;51. N-Queens&quot;&gt;&lt;/a&gt;51. N-Queens&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/n-queens/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;题目&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;解题思路&quot;&gt;&lt;a href=&quot;#解题思路&quot; class=&quot;headerlink&quot; title=&quot;解题思路&quot;&gt;&lt;/a&gt;解题思路&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200229212627.png&quot; alt&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;根据上图的方式是否位于同一对角线&lt;/li&gt;
&lt;li&gt;开始按行遍历，在此过程性需要定义一个数组标明是否在对角线，列上已有皇后&lt;/li&gt;
&lt;li&gt;这也就是回朔法，先试着走，不合适回退&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>49. Group Anagrams</title>
    <link href="https://lyhcc.github.io/post/7ed42f60.html"/>
    <id>https://lyhcc.github.io/post/7ed42f60.html</id>
    <published>2020-02-29T08:39:59.339Z</published>
    <updated>2020-02-29T08:43:52.689Z</updated>
    
    <content type="html"><![CDATA[<h1 id="49-Group-Anagrams"><a href="#49-Group-Anagrams" class="headerlink" title="49. Group Anagrams"></a>49. Group Anagrams</h1><p><a href="https://leetcode.com/problems/group-anagrams/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><ol><li>把相应的字符串转为字符数组，然后排序，并将该数组转为字符串和当前数据种类的索引存入map</li><li>没遍历一个查看map是否已存在索引，不存在创建一个List并存进去</li><li>存在则获得，并将对应的字符串存入获得的List中</li></ol><a id="more"></a><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">public</span> List&lt;List&lt;String&gt;&gt; groupAnagrams(String[] strs) &#123;</span><br><span class="line">    List&lt;List&lt;String&gt;&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;List&lt;String&gt;&gt;();</span><br><span class="line">    Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;strs.length;i++) &#123;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    String current = sortString(strs[i]);</span><br><span class="line">    Integer index;</span><br><span class="line">    <span class="hljs-keyword">if</span>((index = map.get(current))==<span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">    ArrayList&lt;String&gt; list2 = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    map.put(current, list.size());</span><br><span class="line">    list2.add(strs[i]);</span><br><span class="line">    list.add(list2);</span><br><span class="line">    </span><br><span class="line">    &#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line">    <span class="hljs-comment">//System.out.println(strs[i]+",index="+index);</span></span><br><span class="line">    List&lt;String&gt; list2 = list.get(index);</span><br><span class="line">    list2.add(strs[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">sortString</span><span class="hljs-params">(String str)</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">char</span>[] cs = str.toCharArray();</span><br><span class="line">Arrays.sort(cs);</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">return</span> Arrays.toString(cs);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    </span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line">String[] input = &#123;<span class="hljs-string">"eat"</span>,<span class="hljs-string">"tea"</span>, <span class="hljs-string">"tan"</span>, <span class="hljs-string">"ate"</span>, <span class="hljs-string">"nat"</span>, <span class="hljs-string">"bat"</span>&#125;;</span><br><span class="line">System.out.println(<span class="hljs-keyword">new</span> Solution().groupAnagrams(input));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;49-Group-Anagrams&quot;&gt;&lt;a href=&quot;#49-Group-Anagrams&quot; class=&quot;headerlink&quot; title=&quot;49. Group Anagrams&quot;&gt;&lt;/a&gt;49. Group Anagrams&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/group-anagrams/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;题目&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;解题思路&quot;&gt;&lt;a href=&quot;#解题思路&quot; class=&quot;headerlink&quot; title=&quot;解题思路&quot;&gt;&lt;/a&gt;解题思路&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;把相应的字符串转为字符数组，然后排序，并将该数组转为字符串和当前数据种类的索引存入map&lt;/li&gt;
&lt;li&gt;没遍历一个查看map是否已存在索引，不存在创建一个List并存进去&lt;/li&gt;
&lt;li&gt;存在则获得，并将对应的字符串存入获得的List中&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>48. Rotate Image</title>
    <link href="https://lyhcc.github.io/post/bb40d963.html"/>
    <id>https://lyhcc.github.io/post/bb40d963.html</id>
    <published>2020-02-29T07:47:21.163Z</published>
    <updated>2020-02-29T07:49:41.561Z</updated>
    
    <content type="html"><![CDATA[<h1 id="leetcode48"><a href="#leetcode48" class="headerlink" title="leetcode48"></a>leetcode48</h1><p><a href="https://leetcode.com/problems/rotate-image/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><blockquote><p>新建一个等大小的数组，然后换一种形式为原先的数组赋值<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200229154655.png" alt></p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">rotate</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">int</span>[][] tmp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[matrix.length][matrix.length];</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;matrix.length;i++) &#123;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>;j&lt;matrix.length;j++) &#123;</span><br><span class="line">tmp[i][j] = matrix[i][j];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;matrix.length;i++) &#123;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>;j&lt;matrix.length;j++) &#123;</span><br><span class="line">matrix[j][matrix.length-i-<span class="hljs-number">1</span>] = tmp[i][j];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;leetcode48&quot;&gt;&lt;a href=&quot;#leetcode48&quot; class=&quot;headerlink&quot; title=&quot;leetcode48&quot;&gt;&lt;/a&gt;leetcode48&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems
      
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>47. Permutations II</title>
    <link href="https://lyhcc.github.io/post/2bffc4f2.html"/>
    <id>https://lyhcc.github.io/post/2bffc4f2.html</id>
    <published>2020-02-29T05:37:09.575Z</published>
    <updated>2020-02-29T05:45:30.727Z</updated>
    
    <content type="html"><![CDATA[<h1 id="leetcode47"><a href="#leetcode47" class="headerlink" title="leetcode47"></a>leetcode47</h1><p><a href="https://leetcode.com/problems/permutations-ii/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><blockquote><p>分析：要求获得可重集全排列<br>该题通过递归解决，实现时需要注意几点</p><blockquote><ol><li>同一层的重复元素不进行递归  </li><li>查看是否已经使用完当前元素，如果全部使用完了，也不进行递归</li></ol></blockquote></blockquote><a id="more"></a><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;List&lt;Integer&gt;&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; permuteUnique(<span class="hljs-keyword">int</span>[] nums) &#123;</span><br><span class="line">    Arrays.sort(nums);</span><br><span class="line">    </span><br><span class="line">    permute(nums,<span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[nums.length], <span class="hljs-number">0</span>);</span><br><span class="line">    </span><br><span class="line"><span class="hljs-keyword">return</span> list;</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">permute</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums,<span class="hljs-keyword">int</span>[] A, <span class="hljs-keyword">int</span> cur)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(cur==nums.length) &#123;</span><br><span class="line"><span class="hljs-comment">//System.out.println("nums[cur]="+nums[cur]);</span></span><br><span class="line">list.add(toList(A));</span><br><span class="line">&#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;nums.length;i++) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>||nums[i]!=nums[i-<span class="hljs-number">1</span>]) &#123;</span><br><span class="line"><span class="hljs-keyword">int</span> c1 = <span class="hljs-number">0</span>;</span><br><span class="line"><span class="hljs-keyword">int</span> c2 = <span class="hljs-number">0</span>;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j&lt;cur;j++) &#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"cur="</span>+cur+<span class="hljs-string">","</span>+A[j]);</span><br><span class="line"><span class="hljs-keyword">if</span>(nums[i]==A[j])c1++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>;j&lt;nums.length;j++) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(nums[i]==nums[j])c2++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span>(c1&lt;c2) &#123;</span><br><span class="line">A[cur] = nums[i];</span><br><span class="line">permute(nums, A, cur+<span class="hljs-number">1</span>);</span><br><span class="line"><span class="hljs-comment">//tmp.remove(i);</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> List <span class="hljs-title">toList</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    ArrayList&lt;Object&gt; arrayList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">for</span>(Integer e: nums) &#123;</span><br><span class="line">    arrayList.add(e);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="hljs-keyword">return</span> arrayList;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">int</span>[] nums = &#123;<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>&#125;;</span><br><span class="line"></span><br><span class="line">System.out.println(<span class="hljs-keyword">new</span> Solution().permuteUnique(nums).toString());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;leetcode47&quot;&gt;&lt;a href=&quot;#leetcode47&quot; class=&quot;headerlink&quot; title=&quot;leetcode47&quot;&gt;&lt;/a&gt;leetcode47&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/permutations-ii/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;题目&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;解题思路&quot;&gt;&lt;a href=&quot;#解题思路&quot; class=&quot;headerlink&quot; title=&quot;解题思路&quot;&gt;&lt;/a&gt;解题思路&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;分析：要求获得可重集全排列&lt;br&gt;该题通过递归解决，实现时需要注意几点&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;同一层的重复元素不进行递归  &lt;/li&gt;
&lt;li&gt;查看是否已经使用完当前元素，如果全部使用完了，也不进行递归&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>Leetcode/leetcode46</title>
    <link href="https://lyhcc.github.io/post/5cf8f464.html"/>
    <id>https://lyhcc.github.io/post/5cf8f464.html</id>
    <published>2020-02-29T04:54:39.106Z</published>
    <updated>2020-02-29T05:44:55.578Z</updated>
    
    <content type="html"><![CDATA[<h1 id="46-Permutations"><a href="#46-Permutations" class="headerlink" title="46. Permutations"></a>46. Permutations</h1><p><a href="https://leetcode.com/problems/permutations/" target="_blank" rel="noopener">题目</a></p><h2 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h2><ol><li>先将一个数组从小到大排序</li><li>从有向左查找第一个递减的数</li><li>再次2找的的数右边查比该数大的最小的数</li><li>步骤2,3找到的数互换位置</li><li>步骤找到的数的后面的数，进行逆转（可以进行排序O(nlogn)，也可以逆转O(n)），逆转的时间复杂度比较小</li></ol><a id="more"></a><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; permute(<span class="hljs-keyword">int</span>[] nums) &#123;</span><br><span class="line">    Arrays.sort(nums);</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">int</span> rht = nums.length - <span class="hljs-number">1</span>;</span><br><span class="line">    <span class="hljs-keyword">int</span> j = rht;</span><br><span class="line">    </span><br><span class="line">    list.add(toList(nums));</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">while</span>(j &gt;= <span class="hljs-number">0</span>) &#123;</span><br><span class="line">    </span><br><span class="line">    j = rht;</span><br><span class="line">    <span class="hljs-keyword">while</span>(j-<span class="hljs-number">1</span> &gt;=<span class="hljs-number">0</span> &amp;&amp; nums[j] &lt; nums[j-<span class="hljs-number">1</span>])j--;</span><br><span class="line">    <span class="hljs-keyword">if</span>(j-<span class="hljs-number">1</span> &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> list;</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-keyword">int</span> i = j;</span><br><span class="line">    <span class="hljs-keyword">while</span>(i&lt;=rht &amp;&amp; nums[i] &gt; nums[j-<span class="hljs-number">1</span>]) i++;</span><br><span class="line">    <span class="hljs-keyword">if</span>(i&gt;rht)i=rht+<span class="hljs-number">1</span>;</span><br><span class="line">    swap(nums, i-<span class="hljs-number">1</span>, j-<span class="hljs-number">1</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="hljs-comment">//Arrays.sort(nums, j, rht+1);</span></span><br><span class="line">    </span><br><span class="line">    reverse(nums, j, rht);</span><br><span class="line">    list.add(toList(nums));</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">reverse</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">int</span> mid = (i+j)/<span class="hljs-number">2</span>;</span><br><span class="line">    <span class="hljs-keyword">if</span>(mid==nums.length-<span class="hljs-number">1</span>)<span class="hljs-keyword">return</span>;</span><br><span class="line">    <span class="hljs-keyword">if</span>((i+j)%<span class="hljs-number">2</span>==<span class="hljs-number">1</span>) &#123;</span><br><span class="line">    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> a = mid; a&gt;=i;a--) &#123;</span><br><span class="line">    swap(nums, a, <span class="hljs-number">2</span>*mid-a+<span class="hljs-number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line">    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> a = mid-<span class="hljs-number">1</span>; a&gt;=i;a--) &#123;</span><br><span class="line">    swap(nums, a, <span class="hljs-number">2</span>*mid-a);</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> List <span class="hljs-title">toList</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    ArrayList&lt;Object&gt; arrayList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="hljs-keyword">for</span>(Integer e: nums) &#123;</span><br><span class="line">    arrayList.add(e);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="hljs-keyword">return</span> arrayList;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span> </span>&#123;</span><br><span class="line">    <span class="hljs-keyword">int</span> tmp = nums[i];</span><br><span class="line">    nums[i] = nums[j];</span><br><span class="line">    nums[j] = tmp;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">int</span>[] nums = &#123;<span class="hljs-number">2</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>&#125;;</span><br><span class="line"></span><br><span class="line">System.out.println(<span class="hljs-keyword">new</span> Solution().permute(nums).toString());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;46-Permutations&quot;&gt;&lt;a href=&quot;#46-Permutations&quot; class=&quot;headerlink&quot; title=&quot;46. Permutations&quot;&gt;&lt;/a&gt;46. Permutations&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/permutations/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;题目&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;解题思路&quot;&gt;&lt;a href=&quot;#解题思路&quot; class=&quot;headerlink&quot; title=&quot;解题思路&quot;&gt;&lt;/a&gt;解题思路&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;先将一个数组从小到大排序&lt;/li&gt;
&lt;li&gt;从有向左查找第一个递减的数&lt;/li&gt;
&lt;li&gt;再次2找的的数右边查比该数大的最小的数&lt;/li&gt;
&lt;li&gt;步骤2,3找到的数互换位置&lt;/li&gt;
&lt;li&gt;步骤找到的数的后面的数，进行逆转（可以进行排序O(nlogn)，也可以逆转O(n)），逆转的时间复杂度比较小&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="Leetcode" scheme="https://lyhcc.github.io/categories/Leetcode/"/>
    
    
  </entry>
  
  <entry>
    <title>SpringMVC之RESTful实现CRUD</title>
    <link href="https://lyhcc.github.io/post/14dd2a73.html"/>
    <id>https://lyhcc.github.io/post/14dd2a73.html</id>
    <published>2020-02-25T07:59:19.941Z</published>
    <updated>2020-03-18T02:18:04.835Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="RESTRUL-CRUD-需求"><a href="#RESTRUL-CRUD-需求" class="headerlink" title="RESTRUL_CRUD_需求"></a>RESTRUL_CRUD_需求</h2><h3 id="显示所有员工信息"><a href="#显示所有员工信息" class="headerlink" title="显示所有员工信息"></a>显示所有员工信息</h3><ul><li>URI: emps</li><li>请求方式：GET</li><li>显示效果<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225160721.png" alt></li></ul><a id="more"></a><h3 id="添加员工信息"><a href="#添加员工信息" class="headerlink" title="添加员工信息"></a>添加员工信息</h3><ul><li><p>显示添加页面：</p></li><li><p>URI：emp</p></li><li><p>请求方式：GET</p></li><li><p>显示效果<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225160845.png" alt></p></li><li><p>添加员工信息：</p></li><li><p>URI：emp</p></li><li><p>请求方式：POST</p></li><li><p>显示效果：完成添加，重定向到 list 页面。<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225161024.png" alt></p></li></ul><h3 id="删除操作"><a href="#删除操作" class="headerlink" title="删除操作"></a>删除操作</h3><ul><li>URL：emp/{id}</li><li>请求方式：DELETE</li><li>删除后效果：对应记录从数据表中删除</li></ul><h3 id="修改操作：lastName-不可修改！"><a href="#修改操作：lastName-不可修改！" class="headerlink" title="修改操作：lastName 不可修改！"></a>修改操作：lastName 不可修改！</h3><ol><li>显示修改页面<ul><li>URI：emp/{id}</li><li>请求方式：GET</li><li>显示效果：回显表单。</li></ul></li><li>修改员工信息</li></ol><ul><li>URI：emp </li><li>请求方式：PUT</li><li>显示效果：完成修改，重定向到 list 页面。<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225161311.png" alt></li></ul><h3 id="相关的类"><a href="#相关的类" class="headerlink" title="相关的类"></a>相关的类</h3><ul><li>省略了Service层</li><li>实体类：Employee、Department</li><li>Controller：EmployeeController</li><li>Dao：EmployeeDao、DepartmentDao<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225161532.png" alt></li></ul><h3 id="相关页面"><a href="#相关页面" class="headerlink" title="相关页面"></a>相关页面</h3><ul><li>list.jsp</li><li>input.jsp</li><li>edit.jsp</li></ul><h2 id="RESTRUL-CRUD-显示所有员工信息"><a href="#RESTRUL-CRUD-显示所有员工信息" class="headerlink" title="RESTRUL_CRUD_显示所有员工信息"></a>RESTRUL_CRUD_显示所有员工信息</h2><h3 id="搭建开发环境"><a href="#搭建开发环境" class="headerlink" title="搭建开发环境"></a>搭建开发环境</h3><ol><li><p>导包</p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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">com.springsource.net.sf.cglib-2.2.0.jar</span><br><span class="line">com.springsource.org.aopalliance-1.0.0.jar</span><br><span class="line">com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar</span><br><span class="line">spring-aop-4.0.0.RELEASE.jar</span><br><span class="line">spring-aspects-4.0.0.RELEASE.jar</span><br><span class="line">commons-logging-1.1.3.jar</span><br><span class="line">spring-beans-4.0.0.RELEASE.jar</span><br><span class="line">spring-context-4.0.0.RELEASE.jar</span><br><span class="line">spring-core-4.0.0.RELEASE.jar</span><br><span class="line">spring-expression-4.0.0.RELEASE.jar</span><br><span class="line">spring-jdbc-4.0.0.RELEASE.jar</span><br><span class="line">spring-orm-4.0.0.RELEASE.jar</span><br><span class="line">spring-tx-4.0.0.RELEASE.jar</span><br><span class="line">spring-web-4.0.0.RELEASE.jar</span><br><span class="line">spring-webmvc-4.0.0.RELEASE.jar</span><br></pre></td></tr></table></figure></li><li><p>创建配置文件:springmvc.xml  增加context,mvc,beans名称空间。</p></li><li><p>配置核心控制器</p><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">servlet</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">servlet-name</span>&gt;</span>springDispatcherServlet<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-name</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">servlet-class</span>&gt;</span>org.springframework.web.servlet.DispatcherServlet<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-class</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>contextConfigLocation<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>classpath:springmvc.xml<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">load-on-startup</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">load-on-startup</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">servlet</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">&lt;!-- Map all requests to the DispatcherServlet for handling --&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">servlet-mapping</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">servlet-name</span>&gt;</span>springDispatcherServlet<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-name</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">url-pattern</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">url-pattern</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">servlet-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>将 POST 请求转换为 PUT 或 DELETE 请求以及字符过滤器</p><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">filter</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>CharacterEncodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-class</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>encoding<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>utf-8<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>forceEncoding<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">filter</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">filter-mapping</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>CharacterEncodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">url-pattern</span>&gt;</span>/*<span class="hljs-tag">&lt;/<span class="hljs-name">url-pattern</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">filter-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>创建相关页面</p><figure class="highlight plain hljs"><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">/WEB-INF/views/list.jsp</span><br><span class="line">index.jsp</span><br></pre></td></tr></table></figure></li><li><p>增加实体类<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225165708.png" alt><br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200225165726.png" alt></p></li><li><p>增加Dao</p><ol><li>EmployeeDao <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">package</span> xyz.lyhcc.dao;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">import</span> java.util.Collection;</span><br><span class="line"><span class="hljs-keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="hljs-keyword">import</span> java.util.Map;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.stereotype.Repository;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">import</span> xyz.lyhcc.bean.Department;</span><br><span class="line"><span class="hljs-keyword">import</span> xyz.lyhcc.bean.Employee;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Repository</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeDao</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map&lt;Integer, Employee&gt; employees = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-meta">@Autowired</span></span><br><span class="line"><span class="hljs-keyword">private</span> DepartmentDao departmentDao;</span><br><span class="line"><span class="hljs-keyword">static</span>&#123;</span><br><span class="line">employees = <span class="hljs-keyword">new</span> HashMap&lt;Integer, Employee&gt;();</span><br><span class="line">employees.put(<span class="hljs-number">1001</span>, <span class="hljs-keyword">new</span> Employee(<span class="hljs-number">1001</span>, <span class="hljs-string">"E-AA"</span>, <span class="hljs-string">"aa@163.com"</span>, <span class="hljs-number">1</span>, <span class="hljs-keyword">new</span> Department(<span class="hljs-number">101</span>, <span class="hljs-string">"D-AA"</span>)));</span><br><span class="line">employees.put(<span class="hljs-number">1002</span>, <span class="hljs-keyword">new</span> Employee(<span class="hljs-number">1002</span>, <span class="hljs-string">"E-BB"</span>, <span class="hljs-string">"bb@163.com"</span>, <span class="hljs-number">1</span>, <span class="hljs-keyword">new</span> Department(<span class="hljs-number">102</span>, <span class="hljs-string">"D-BB"</span>)));</span><br><span class="line">employees.put(<span class="hljs-number">1003</span>, <span class="hljs-keyword">new</span> Employee(<span class="hljs-number">1003</span>, <span class="hljs-string">"E-CC"</span>, <span class="hljs-string">"cc@163.com"</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">new</span> Department(<span class="hljs-number">103</span>, <span class="hljs-string">"D-CC"</span>)));</span><br><span class="line">employees.put(<span class="hljs-number">1004</span>, <span class="hljs-keyword">new</span> Employee(<span class="hljs-number">1004</span>, <span class="hljs-string">"E-DD"</span>, <span class="hljs-string">"dd@163.com"</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">new</span> Department(<span class="hljs-number">104</span>, <span class="hljs-string">"D-DD"</span>)));</span><br><span class="line">employees.put(<span class="hljs-number">1005</span>, <span class="hljs-keyword">new</span> Employee(<span class="hljs-number">1005</span>, <span class="hljs-string">"E-EE"</span>, <span class="hljs-string">"ee@163.com"</span>, <span class="hljs-number">1</span>, <span class="hljs-keyword">new</span> Department(<span class="hljs-number">105</span>, <span class="hljs-string">"D-EE"</span>)));</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Integer initId = <span class="hljs-number">1006</span>;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">(Employee employee)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (employee.getId() == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">employee.setId(initId++);</span><br><span class="line">&#125;</span><br><span class="line">employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));</span><br><span class="line">employees.put(employee.getId(), employee);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> Collection&lt;Employee&gt; <span class="hljs-title">getAll</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> employees.values();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> Employee <span class="hljs-title">get</span><span class="hljs-params">(Integer id)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> employees.get(id);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">delete</span><span class="hljs-params">(Integer id)</span> </span>&#123;</span><br><span class="line">employees.remove(id);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>DeaprtmentDao<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">package</span> xyz.lyhcc.bean;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Department</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> Integer id;</span><br><span class="line"><span class="hljs-keyword">private</span> String departmentName;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Department</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Department</span><span class="hljs-params">(Integer id, String departmentName)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">super</span>();</span><br><span class="line"><span class="hljs-keyword">this</span>.id = id;</span><br><span class="line"><span class="hljs-keyword">this</span>.departmentName = departmentName;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> Integer <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> id;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(Integer id)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.id = id;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDepartmentName</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> departmentName;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setDepartmentName</span><span class="hljs-params">(String departmentName)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.departmentName = departmentName;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol></li></ol><h3 id="显示所有员工信息-1"><a href="#显示所有员工信息-1" class="headerlink" title="显示所有员工信息"></a>显示所有员工信息</h3><ol><li><p>页面链接</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"empList"</span>&gt;</span>To Employee List<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>增加处理器</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@Controller</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Autowired</span></span><br><span class="line">EmployeeDao employeeDao;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/retrieveEmps"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">retrieveEmps</span><span class="hljs-params">(Map&lt;String, Object&gt; map)</span> </span>&#123;</span><br><span class="line">map.put(<span class="hljs-string">"empList"</span>, employeeDao.getAll());</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"list"</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>SpringMVC中没遍历的标签，需要使用jstl标签进行集合遍历增加jstl标签库jar包</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">border</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">cellpadding</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">cellspacing</span>=<span class="hljs-string">"0"</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>EmpId<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>LastName<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Gender<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>DepartmentName<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Edit<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">c:forEach</span> <span class="hljs-attr">items</span>=<span class="hljs-string">"$&#123;requestScope.empList &#125;"</span> <span class="hljs-attr">var</span>=<span class="hljs-string">"emp"</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>$&#123;emp.id &#125; <span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>$&#123;emp.lastName &#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>$&#123;emp.gender==0?"女": "男" &#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>$&#123;emp.email &#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>$&#123;emp.department.departmentName &#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">""</span>&gt;</span>Edit<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">""</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">c:forEach</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"toaddpage"</span>&gt;</span>Add Employee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h2 id="使用-Spring的表单标签"><a href="#使用-Spring的表单标签" class="headerlink" title="使用 Spring的表单标签"></a>使用 Spring的表单标签</h2><ul><li>通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定，以实现表单数据更便捷编辑和表单值的回显</li><li>form 标签<ul><li>一般情况下，通过 GET 请求获取表单页面，而通过 POST 请求提交表单页面，因此获取表单页面和提交表单页面的 URL 是相同的。</li><li>只要满足该最佳条件的契约，<a href="form:form" target="_blank" rel="noopener">form:form</a> 标签就无需通过 action 属性指定表单提交的 URL</li><li>可以通过 modelAttribute 属性指定绑定的模型属性，若没有指定该属性，则默认从 request 域对象中读取 command 的表单 bean，如果该属性值也不存在，则会发生错误。</li></ul></li><li>SpringMVC 提供了多个表单组件标签，如 <a href="form:input/" target="_blank" rel="noopener">form:input/</a>、<a href="form:select/" target="_blank" rel="noopener">form:select/</a> 等，用以绑定表单字段的属性值，它们的共有属性如下：<ul><li>path：表单字段，对应 html 元素的 name 属性，支持级联属性</li><li>htmlEscape：是否对表单值的 HTML 特殊字符进行转换，默认值为 true</li><li>cssClass：表单组件对应的 CSS 样式类名</li><li>cssErrorClass：表单组件的数据存在错误时，采取的 CSS 样式</li></ul></li><li>form:input、form:password、form:hidden、form:textarea：对应 HTML 表单的 text、password、hidden、textarea 标签</li><li>form:radiobutton：单选框组件标签，当表单 bean 对应的属性值和 value 值相等时，单选框被选中</li><li>form:radiobuttons：单选框组标签，用于构造多个单选框<ul><li>items：可以是一个 List、String[] 或 Map</li><li>itemValue：指定 radio 的 value 值。可以是集合中 bean 的一个属性值</li><li>itemLabel：指定 radio 的 label 值</li><li>delimiter：多个单选框可以通过 delimiter 指定分隔符</li></ul></li><li>form:checkbox：复选框组件。用于构造单个复选框</li><li>form:checkboxs：用于构造多个复选框。使用方式同 form:radiobuttons 标签</li><li>form:select：用于构造下拉框组件。使用方式同 form:radiobuttons 标签</li><li>form:option：下拉框选项组件标签。使用方式同 form:radiobuttons 标签</li><li>form:errors：显示表单组件或数据校验所对应的错误<ul><li>&lt;form:errors path= “*” /&gt; ：显示表单所有的错误</li><li>&lt;form:errors path= “user*” /&gt; ：显示所有以 user 为前缀的属性对应的错误</li><li>&lt;form:errors path= “username” /&gt; ：显示特定表单对象属性的错误</li></ul></li></ul><h2 id="RESTRUL-CRUD-添加操作-amp-表单标签"><a href="#RESTRUL-CRUD-添加操作-amp-表单标签" class="headerlink" title="RESTRUL_CRUD_添加操作&amp;表单标签"></a>RESTRUL_CRUD_添加操作&amp;表单标签</h2><ol><li><p>在list.jsp上增加连接</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"empInput"</span>&gt;</span>Add Employee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>增加处理器方法</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(value=<span class="hljs-string">"toaddpage"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">addEmpPage</span><span class="hljs-params">(Model model)</span> </span>&#123;</span><br><span class="line">Collection&lt;Department&gt; departments = departmentDao.getDepartments();</span><br><span class="line">model.addAttribute(<span class="hljs-string">"depts"</span>, departments);</span><br><span class="line"><span class="hljs-comment">//增加一个属性</span></span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"add"</span>;</span><br><span class="line">&#125;</span><br><span class="line"> <span class="hljs-meta">@RequestMapping</span>(value=<span class="hljs-string">"increaseEmp"</span>,method=RequestMethod.POST)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">increaseEmp</span><span class="hljs-params">(Employee employee, Map&lt;String, Object&gt;map)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">employeeDao.save(employee);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/retrieveEmps"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>显示添加页面</p><ol><li>非SpringMVC的form标签 <figure class="highlight hljs"><table><tr><td class="gutter"><pre><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">&lt;% pageContext.setAttribute(<span class="hljs-string">"ctp"</span>, request.getContextPath()); %&gt;</span><br><span class="line">&lt;form action=<span class="hljs-string">"increaseEmp"</span> method=<span class="hljs-string">"POST"</span>&gt;</span><br><span class="line"></span><br><span class="line">lastName: &lt;input type=<span class="hljs-string">"text"</span> name=<span class="hljs-string">"lastName"</span> /&gt;</span><br><span class="line">email: &lt;input type=<span class="hljs-string">"text"</span> name=<span class="hljs-string">"email"</span> /&gt;</span><br><span class="line">gender: </span><br><span class="line">男&lt;input type=<span class="hljs-string">"radio"</span> name=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"1"</span>/&gt;</span><br><span class="line">女&lt;input type=<span class="hljs-string">"radio"</span> name=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"0"</span>/&gt;</span><br><span class="line">&lt;select name=<span class="hljs-string">"department.id"</span>&gt;</span><br><span class="line">&lt;c:forEach items=<span class="hljs-string">"$&#123;depts &#125;"</span> <span class="hljs-keyword">var</span>=<span class="hljs-string">"dept"</span>&gt;</span><br><span class="line">&lt;option value="$&#123;dept.id &#125;"&gt;$&#123;dept.departmentName &#125;&lt;/option&gt;</span><br><span class="line">&lt;/c:forEach&gt;</span><br><span class="line">&lt;/select&gt;</span><br><span class="line">&lt;input type=<span class="hljs-string">"submit"</span> value=<span class="hljs-string">"提交"</span> /&gt;</span><br><span class="line">&lt;/form&gt;</span><br></pre></td></tr></table></figure><ol start="2"><li>SpringMVC的form标签<figure class="highlight hljs"><table><tr><td class="gutter"><pre><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">         &lt;form:form action=<span class="hljs-string">"increaseEmp"</span> method=<span class="hljs-string">"POST"</span> modelAttribute=<span class="hljs-string">"employee"</span>&gt;</span><br><span class="line">&lt;!-- java.lang.IllegalStateException: Neither BindingResult nor plain target object <span class="hljs-keyword">for</span> bean name <span class="hljs-string">'command'</span> available as request attribute --&gt;</span><br><span class="line">LastName: &lt;form:input path="lastName"/&gt;&lt;/br&gt;&lt;/br&gt;</span><br><span class="line">Email:    &lt;form:input path="email"/&gt;&lt;/br&gt;&lt;/br&gt;</span><br><span class="line">Gender:  男&lt;form:radiobutton path=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"1"</span>/&gt;</span><br><span class="line">  女&lt;form:radiobutton path=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"0"</span>/&gt;</span><br><span class="line">&lt;br/&gt;</span><br><span class="line">&lt;br/&gt;</span><br><span class="line">Department：&lt;form:select path="department.id" items="$&#123;depts &#125;" itemLabel="departmentName" itemValue="id"&gt;&lt;/form:select&gt;</span><br><span class="line">&lt;br/&gt;</span><br><span class="line">&lt;input type=<span class="hljs-string">"submit"</span> value=<span class="hljs-string">"提交"</span> /&gt;</span><br><span class="line">&lt;/form:form&gt;</span><br></pre></td></tr></table></figure></li></ol></li></ol></li></ol><hr><p><strong>注意：</strong>  注意modelAttribute的使用，这里没有在域中使用添加对应的属性会报错<br>ava.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name ‘command’ available as request attribute</p><hr><h2 id="RESTRUL-CRUD-删除操作-amp-处理静态资源"><a href="#RESTRUL-CRUD-删除操作-amp-处理静态资源" class="headerlink" title="RESTRUL_CRUD_删除操作&amp;处理静态资源"></a>RESTRUL_CRUD_删除操作&amp;处理静态资源</h2><ol><li>页面链接</li></ol><h2 id="RESTRUL-CRUD-修改操作"><a href="#RESTRUL-CRUD-修改操作" class="headerlink" title="RESTRUL_CRUD_修改操作"></a>RESTRUL_CRUD_修改操作</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200226084536.png" alt></p><h3 id="根据id查询员工对象，表单回显"><a href="#根据id查询员工对象，表单回显" class="headerlink" title="根据id查询员工对象，表单回显"></a>根据id查询员工对象，表单回显</h3><ol><li><p>页面链接</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"empEdit/$&#123;emp.id &#125;"</span>&gt;</span>Edit<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>控制器方法</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(value=<span class="hljs-string">"empEdit/&#123;id&#125;"</span>, method=RequestMethod.GET)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">editEmp</span><span class="hljs-params">(@PathVariable(value=<span class="hljs-string">"id"</span>)</span> Integer id, Map&lt;String, Object&gt;map) </span>&#123;</span><br><span class="line">map.put(<span class="hljs-string">"employee"</span>, employeeDao.get(id));</span><br><span class="line">map.put(<span class="hljs-string">"depts"</span>, departmentDao.getDepartments());</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"edit"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>修改页面</p><figure class="highlight hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line">&lt;%@ page language=<span class="hljs-string">"java"</span> contentType=<span class="hljs-string">"text/html; charset=UTF-8"</span></span><br><span class="line">    pageEncoding=<span class="hljs-string">"UTF-8"</span>%&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="hljs-string">"form"</span> uri=<span class="hljs-string">"http://www.springframework.org/tags/form"</span> %&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="hljs-string">"c"</span> uri=<span class="hljs-string">"http://java.sun.com/jsp/jstl/core"</span> %&gt;</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;</span><br><span class="line">&lt;title&gt;员工信息修改界面&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;form:form action=<span class="hljs-string">"$&#123;pageContext.request.contextPath &#125;/empUpdate"</span></span><br><span class="line">method=<span class="hljs-string">"POST"</span> modelAttribute=<span class="hljs-string">"employee"</span>&gt;</span><br><span class="line">  &lt;input type=<span class="hljs-string">"hidden"</span> name=<span class="hljs-string">"id"</span> value=<span class="hljs-string">"$&#123;employee.id &#125;"</span> /&gt;</span><br><span class="line">          &lt;input type=<span class="hljs-string">"hidden"</span> name=<span class="hljs-string">"_method"</span> value=<span class="hljs-string">"PUT"</span>&gt;</span><br><span class="line"> Email : &lt;form:input path=<span class="hljs-string">"email"</span> /&gt;</span><br><span class="line">&lt;br&gt;</span><br><span class="line">&lt;br&gt;</span><br><span class="line"> Gender:  男&lt;form:radiobutton path=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"1"</span>/&gt;</span><br><span class="line">  女&lt;form:radiobutton path=<span class="hljs-string">"gender"</span> value=<span class="hljs-string">"0"</span>/&gt;</span><br><span class="line">&lt;br/&gt;</span><br><span class="line">&lt;br/&gt;</span><br><span class="line"> DeptName : </span><br><span class="line">                 &lt;form:select path="department.id" items="$&#123;depts &#125;" itemLabel="departmentName" itemValue="id"&gt;&lt;/form:select&gt;</span><br><span class="line">&lt;br&gt;</span><br><span class="line">&lt;br&gt;</span><br><span class="line">&lt;input type=<span class="hljs-string">"submit"</span> value=<span class="hljs-string">"Submit"</span>&gt;&lt;br&gt;&lt;br&gt;</span><br><span class="line">&lt;/form:form&gt;</span><br><span class="line">      </span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li></ol><h3 id="提交表单，修改数据"><a href="#提交表单，修改数据" class="headerlink" title="提交表单，修改数据"></a>提交表单，修改数据</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(value=<span class="hljs-string">"empUpdate"</span>,method=RequestMethod.PUT)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">updateEmp</span><span class="hljs-params">(Employee employee)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">System.out.println(employee);</span><br><span class="line">employeeDao.save(employee);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/retrieveEmps"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@ModelAttribute</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">myModelAttribute</span><span class="hljs-params">(@RequestParam(value=<span class="hljs-string">"id"</span>, required=<span class="hljs-keyword">false</span>)</span> Integer id,</span></span><br><span class="line"><span class="hljs-function">Model model</span></span><br><span class="line"><span class="hljs-function">) </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span>(id!=<span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">Employee employee = employeeDao.get(id);</span><br><span class="line">model.addAttribute(<span class="hljs-string">"employee"</span>, employee);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="RESTRUL-CRUD-删除操作-amp-处理静态资源-1"><a href="#RESTRUL-CRUD-删除操作-amp-处理静态资源-1" class="headerlink" title="RESTRUL_CRUD_删除操作&amp;处理静态资源"></a>RESTRUL_CRUD_删除操作&amp;处理静态资源</h2><h3 id="删除实验代码"><a href="#删除实验代码" class="headerlink" title="删除实验代码"></a>删除实验代码</h3><ol><li><p>页面链接</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/empDelete/$&#123;emp.id &#125;"</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>控制器方法</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(value=<span class="hljs-string">"delEmp/&#123;id&#125;"</span>, method=RequestMethod.DELETE)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">delEmp</span><span class="hljs-params">(@PathVariable(value=<span class="hljs-string">"id"</span>)</span> Integer id) </span>&#123;</span><br><span class="line">employeeDao.delete(id);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/retrieveEmps"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><h3 id="HiddenHttpMethodFilter过滤器"><a href="#HiddenHttpMethodFilter过滤器" class="headerlink" title="HiddenHttpMethodFilter过滤器"></a>HiddenHttpMethodFilter过滤器</h3><ul><li><mark>发起请求，无法执行，因为delete请求必须通过post请求转换为delete请求，借助：HiddenHttpMethodFilter过滤器</mark></li></ul><h3 id="需要使用jQuery来转换请求方式"><a href="#需要使用jQuery来转换请求方式" class="headerlink" title="需要使用jQuery来转换请求方式"></a>需要使用jQuery来转换请求方式</h3><ol><li>加入jQuery库文件<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/scripts/jquery-1.9.1.min.js</span><br></pre></td></tr></table></figure></li><li>jQuery库文件不起作用<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">警告: No mapping found for HTTP request with URI [/SpringMVC_03_RESTFul_CRUD/scripts/jquery-1.9.1.min.js] in DispatcherServlet with name &apos;springDispatcherServlet&apos;</span><br></pre></td></tr></table></figure></li><li>解决方法，SpringMVC 处理静态资源<blockquote><p>SpringMVC 处理静态资源:</p><blockquote><p>a)为什么会有这样的问题:</p><pre><code>优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀  若将 DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。</code></pre><p>b)解决: 在 SpringMVC 的配置文件中配置 <a href="mvc:default-servlet-handler/" target="_blank" rel="noopener">mvc:default-servlet-handler/</a></p></blockquote></blockquote></li><li>配置后，原来的请求又不好使了<figure class="highlight xml hljs"><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="hljs-comment">&lt;!-- 在前端控制器对应的配置文件，增加 --&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">mvc:annotation-driven</span> /&gt;</span></span><br></pre></td></tr></table></figure><h3 id="关于mvc-default-servlet-handler-作用"><a href="#关于mvc-default-servlet-handler-作用" class="headerlink" title="关于mvc:default-servlet-handler/作用"></a>关于<a href="mvc:default-servlet-handler/" target="_blank" rel="noopener">mvc:default-servlet-handler/</a>作用</h3></li></ol><blockquote><p><a href="mvc:default-servlet-handler/" target="_blank" rel="noopener">mvc:default-servlet-handler/</a> 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler，<br>它会对进入 DispatcherServlet 的请求进行筛查，如果发现是没有经过映射的请求，<br>就将该请求交由 WEB 应用服务器默认的 Servlet 处理，如果不是静态资源的请求，才由 DispatcherServlet 继续处理<br>一般 WEB 应用服务器默认的 Servlet 的名称都是 default。<br>若所使用的 WEB 服务器的默认 Servlet 名称不是 default，则需要通过 default-servlet-name 属性显式指定<br>参考：CATALINA_HOME/config/web.xml</p></blockquote><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">servlet</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">servlet-name</span>&gt;</span>default<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">servlet-class</span>&gt;</span>org.apache.catalina.servlets.DefaultServlet<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-class</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">        <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>debug<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">        <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">        <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>listings<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">        <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">load-on-startup</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">load-on-startup</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">servlet</span>&gt;</span></span><br></pre></td></tr></table></figure><p>该标签属性default-servlet-name默认值是”default”,可以省略。<br><a href="mvc:default-servlet-handler/" target="_blank" rel="noopener">mvc:default-servlet-handler/</a>        </p><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">mvc:default-servlet-handler</span> <span class="hljs-attr">default-servlet-name</span>=<span class="hljs-string">"default"</span>/&gt;</span></span><br></pre></td></tr></table></figure><h3 id="通过jQuery转换为DELETE请求"><a href="#通过jQuery转换为DELETE请求" class="headerlink" title="通过jQuery转换为DELETE请求"></a>通过jQuery转换为DELETE请求</h3><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"delete"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"empDelete/$&#123;emp.id &#125;"</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_method"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"DELETE"</span>/&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"scripts/jquery-1.9.1.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="hljs-javascript">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</span></span><br><span class="line"><span class="hljs-javascript">$(<span class="hljs-string">".delete"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</span></span><br><span class="line"><span class="hljs-javascript"><span class="hljs-keyword">var</span> href = $(<span class="hljs-keyword">this</span>).attr(<span class="hljs-string">"href"</span>);</span></span><br><span class="line"><span class="hljs-javascript">$(<span class="hljs-string">"form"</span>).attr(<span class="hljs-string">"action"</span>,href).submit();</span></span><br><span class="line"><span class="hljs-actionscript"><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span> ;</span></span><br><span class="line">&#125;);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;h2 id=&quot;RESTRUL-CRUD-需求&quot;&gt;&lt;a href=&quot;#RESTRUL-CRUD-需求&quot; class=&quot;headerlink&quot; title=&quot;RESTRUL_CRUD_需求&quot;&gt;&lt;/a&gt;RESTRUL_CRUD_需求&lt;/h2&gt;&lt;h3 id=&quot;显示所有员工信息&quot;&gt;&lt;a href=&quot;#显示所有员工信息&quot; class=&quot;headerlink&quot; title=&quot;显示所有员工信息&quot;&gt;&lt;/a&gt;显示所有员工信息&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;URI: emps&lt;/li&gt;
&lt;li&gt;请求方式：GET&lt;/li&gt;
&lt;li&gt;显示效果&lt;br&gt;  &lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200225160721.png&quot; alt&gt;&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="Spring MVC" scheme="https://lyhcc.github.io/categories/Spring-MVC/"/>
    
    
      <category term="SpringMVC之RESTful实现CRUD" scheme="https://lyhcc.github.io/tags/SpringMVC%E4%B9%8BRESTful%E5%AE%9E%E7%8E%B0CRUD/"/>
    
  </entry>
  
  <entry>
    <title>SpringMVC之视图解析器</title>
    <link href="https://lyhcc.github.io/post/652cd08.html"/>
    <id>https://lyhcc.github.io/post/652cd08.html</id>
    <published>2020-02-22T04:19:24.133Z</published>
    <updated>2020-02-23T15:12:49.917Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="SpringMVC如何解析视图概述"><a href="#SpringMVC如何解析视图概述" class="headerlink" title="SpringMVC如何解析视图概述"></a>SpringMVC如何解析视图概述</h2><blockquote><ol><li>不论控制器返回一个String,ModelAndView,View都会转换为ModelAndView对象，由视图解析器解析视图，然后，进行页面的跳转。<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165150.png" alt>  </li><li>视图解析源码分析：重要的两个接口<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165245.png" alt><br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165318.png" alt></li><li>断点调式<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165414.png" alt><br>流程图<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165500.png" alt></li></ol></blockquote><h2 id="视图和视图解析器"><a href="#视图和视图解析器" class="headerlink" title="视图和视图解析器"></a>视图和视图解析器</h2><ul><li>请求处理方法执行完成后，最终返回一个 ModelAndView 对象。对于那些返回 String，View 或 ModeMap 等类型的处理方法，<strong>Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象</strong> ，它包含了逻辑名和模型对象的视图</li><li>Spring MVC 借助 <strong>视图解析器（ViewResolver）</strong> 得到最终的视图对象（View），最终的视图可以是 JSP ，也可能是 Excel、JFreeChart等各种表现形式的视图</li><li>对于最终究竟采取何种视图对象对模型数据进行渲染，处理器并不关心，处理器工作重点聚焦在生产模型数据的工作上，从而实现 MVC 的充分解耦</li></ul><h2 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h2><ul><li><p>视图的作用是渲染模型数据，将模型里的数据以某种形式呈现给客户。</p></li><li><p>为了实现视图模型和具体实现技术的解耦，Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口：<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165837.png" alt></p></li><li><p>视图对象由视图解析器负责实例化。由于视图是无状态的，所以他们不会有线程安全的问题</p></li></ul><h2 id="常用的视图实现类"><a href="#常用的视图实现类" class="headerlink" title="常用的视图实现类"></a>常用的视图实现类</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223165950.png" alt></p><h2 id="视图解析器"><a href="#视图解析器" class="headerlink" title="视图解析器"></a>视图解析器</h2><ul><li>SpringMVC 为逻辑视图名的解析提供了不同的策略，可以在 Spring WEB 上下文中配置一种或多种解析策略，并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。</li><li>视图解析器的作用比较单一：将逻辑视图解析为一个具体的视图对象。</li><li>所有的视图解析器都必须实现 ViewResolver 接口：<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223170057.png" alt></li></ul><h2 id="常用的视图解析类实现类"><a href="#常用的视图解析类实现类" class="headerlink" title="常用的视图解析类实现类"></a>常用的视图解析类实现类</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223170146.png" alt></p><ul><li>程序员可以选择一种视图解析器或混用多种视图解析器</li><li>每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性，可以通过 order 属性指定解析器的优先顺序，order  越小优先级越高。</li><li>SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析，直到解析成功并返回视图对象，否则将抛出 ServletException 异常</li><li>InternalResourceViewResolver<ul><li>JSP 是最常见的视图技术，可以使用 InternalResourceViewResolve作为视图解析器：<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223171501.png" alt></li></ul></li></ul><h2 id="Spring-MVC视图解析器之前缀"><a href="#Spring-MVC视图解析器之前缀" class="headerlink" title="Spring MVC视图解析器之前缀"></a>Spring MVC视图解析器之前缀</h2><h3 id="forward"><a href="#forward" class="headerlink" title="forward"></a>forward</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"hello"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"---------------------"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"./success"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 转发到页面</span></span><br><span class="line"><span class="hljs-comment"> * /success.jsp转发到当前项目的success</span></span><br><span class="line"><span class="hljs-comment"> * 一定要加上/，如果不加就是相对路径</span></span><br><span class="line"><span class="hljs-comment"> * forward:/hello.jsp</span></span><br><span class="line"><span class="hljs-comment"> forward前缀不会有配置的前缀后缀拼接</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@return</span></span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"handle01"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">handle01</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"handle01"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"forward:/success.jsp"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"handle02"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">handle02</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"handle02"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"forward:/handle01"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="重定向redirect"><a href="#重定向redirect" class="headerlink" title="重定向redirect"></a>重定向redirect</h3><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 重定向到success.jsp页面</span></span><br><span class="line"><span class="hljs-comment"> * 转发 forward: 转发的路径</span></span><br><span class="line"><span class="hljs-comment"> * 重定向 redirect： 重定向的路径</span></span><br><span class="line"><span class="hljs-comment"> * /success.jsp代表就是从当前项目下开始，SpringMVC会为路径自动的拼接上项目名</span></span><br><span class="line"><span class="hljs-comment"> * </span></span><br><span class="line"><span class="hljs-comment"> *  原生的servlet重定向需要添加项目名</span></span><br><span class="line"><span class="hljs-comment"> * response.sendRedirect("/success.jsp")</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@return</span></span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/handle03"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">handle03</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"handle03"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/success.jsp"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/handle04"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">handle04</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"handle04"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/handle03"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="JstlView"><a href="#JstlView" class="headerlink" title="JstlView"></a>JstlView</h2><ul><li>导包导入jstl的时候自动创建为一个jstlView，可以快速方便支持国际化<ul><li>JavaWeb国际化步骤</li><li>得到一个Locale对象</li><li>使用ResourceBundle绑定国际化资源文件</li><li>使用ResourceBundle.getString(key);获取到国际化配置文件中的值</li><li>Web页面国际化，fmt标签来做<figure class="highlight plain hljs"><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">&lt; fmt:setLocale&gt;</span><br><span class="line">&lt; fmt:setBundle &gt;</span><br><span class="line">&lt;fmt:message&gt;</span><br></pre></td></tr></table></figure></li></ul></li><li>使用jstlView<ul><li>让Spring管理国际化资源</li><li>去页面取值</li></ul></li></ul><hr><ul><li>若项目中使用了JSTL，则SpringMVC 会自动把视图由InternalResourceView转为 JstlView  （断点调试，将JSTL的jar包增加到项目中，视图解析器会自动修改为JstlView）</li><li>若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件</li><li>若希望直接响应通过 SpringMVC 渲染的页面，可以使用 mvc:view-controller 标签实现</li></ul><p>*<em>注意：使用jstl国际化是，页面映射不能带前缀 *</em>  </p><h2 id="实验代码"><a href="#实验代码" class="headerlink" title="实验代码"></a>实验代码</h2><table><thead><tr><th align="center">i18n.properties</th><th align="center">i18n_en_US.properties</th><th align="center">i18n_zh_CN.properties</th></tr></thead><tbody><tr><td align="center">i18n.username=username</td><td align="center">i18n.password=password</td><td align="center">i18n.username=Username</td></tr><tr><td align="center">i18n.password=Password</td><td align="center">i18n.username=\u7528\u6237\u540D</td><td align="center">i18n.password=\u5BC6\u7801</td></tr><tr><td align="center">1. 增加jstl标签 jar包（断点调试，这时的View对象就是JstlView）</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223172451.png" alt></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">2. 设置国际化资源文件</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight xml hljs"><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="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"messageSource"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"org.springframework.context.support.ResourceBundleMessageSource"</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"basename"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"i18n"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">3. 控制器代码</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/login"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">login</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"login"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">4. 成功页面(/success.jsp)使用fmt标签库</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight hljs"><table><tr><td class="gutter"><pre><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">   &lt;form action=<span class="hljs-string">""</span>&gt;</span><br><span class="line">&lt;fmt:message key="i18n.username"&gt;&lt;/fmt:message&gt;：&lt;input /&gt;</span><br><span class="line">&lt;fmt:message key="i18n.password"&gt;&lt;/fmt:message&gt;： &lt;input /&gt;</span><br><span class="line">&lt;input type=<span class="hljs-string">"submit"</span> value=<span class="hljs-string">'&lt;fmt:message key='</span>i18n.login<span class="hljs-string">'&gt;&lt;/fmt:message&gt;'</span> /&gt;</span><br><span class="line">&lt;/form&gt;</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">## mvc:view-controller标签</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 若希望直接响应通过 SpringMVC 渲染的页面，可以使用 mvc:view-controller 标签实现</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight xml hljs"><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="hljs-comment">&lt;!-- 直接配置响应的页面：无需经过控制器来执行结果 --&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">mvc:view-controller</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/success"</span> <span class="hljs-attr">view-name</span>=<span class="hljs-string">"success"</span>/&gt;</span></span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 请求的路径：</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8080/SpringMVC_02_View/success</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 配置<a href="mvc:view-controller" target="_blank" rel="noopener">mvc:view-controller</a>会导致其他请求路径失效</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 解决办法：</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight xml hljs"><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="hljs-comment">&lt;!-- 在实际开发过程中都需要配置mvc:annotation-driven标签，后面讲，这里先配置上 --&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">mvc:annotation-driven</span>/&gt;</span></span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">##  自定义视图</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 自定义视图（需要加入SpringMVC，那么，一定需要实现框架的接口）</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 若希望使用 Excel 展示数据列表，仅需要扩展 SpringMVC 提供的 AbstractExcelView 或 AbstractJExcelView 即可。</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 实现 buildExcelDocument() 方法，在方法中使用模型数据对象构建 Excel 文档就可以了。</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- AbstractExcelView 基于 POI API，而 AbstractJExcelView 是基于 JExcelAPI 的。</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 视图对象需要配置 IOC 容器中的一个 Bean，使用 BeanNameViewResolver 作为视图解析器即可</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">- 若希望直接在浏览器中直接下载 Excel 文档，则可以设置响应头 Content-Disposition 的值为 attachment;filename=xxx.xls</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223224845.png" alt></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">## 实验代码</td><td align="center"></td><td align="center"></td></tr><tr><td align="center">1. 测试链接</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8200/SpringMVC_voewResolver/definitionView</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">2. 控制方法</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/definitionView"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">test</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"definitionView"</span>);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"hello:time"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">3. 自定义视图</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyView</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">View</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getContentType</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"text/html"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">render</span><span class="hljs-params">(Map&lt;String, ?&gt; model, HttpServletRequest request, HttpServletResponse response)</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line">response.getWriter().write(<span class="hljs-string">"This is MyView, And Time is "</span> + <span class="hljs-keyword">new</span> Date().toString());</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">4. 自定义视图解析器</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyResourceResolver</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ViewResolver</span>, <span class="hljs-title">Ordered</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> order;</span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> View <span class="hljs-title">resolveViewName</span><span class="hljs-params">(String viewName, Locale locale)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (viewName.startsWith(<span class="hljs-string">"hello:"</span>)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MyView();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getOrder</span><span class="hljs-params">()</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.order;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOrder</span><span class="hljs-params">(<span class="hljs-keyword">int</span> order)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.order = order;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">5. 声明视图解析器</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><figure class="highlight xml hljs"><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="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"xyz.lyhcc.MyResourceResolver"</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"order"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"10"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></td><td align="center"></td><td align="center"></td></tr><tr><td align="center">——</td><td align="center"></td><td align="center"></td></tr><tr><td align="center"><strong>注意：InternalResourceViewResolver默认的优先级：private int order = Integer.MAX_VALUE;</strong></td><td align="center"></td><td align="center"></td></tr></tbody></table><h2 id="视图解析器源码解析"><a href="#视图解析器源码解析" class="headerlink" title="视图解析器源码解析"></a>视图解析器源码解析</h2><ol><li>方法执行后的返回值会作为页面地址参考，转发或者重定向到页面</li><li>视图解析器可能会进行页面地址拼串</li></ol><hr><ol><li><p>任何方法的返回值，最终都会被包装成ModelAndView对象</p></li><li><p>processDispatchResult(HttpServletRequest request, HttpServletResponse response,HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception)</p><blockquote><p>视图渲染流程：将域中的数据页面显示，页面就是渲染模型数据</p></blockquote></li><li><p>render(mv, request, response);</p></li><li><p>View与ViewResolver:</p><blockquote><p>ViewResolver对象就是根据视图名返回View对象<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223124301.png" alt></p></blockquote></li><li><p>怎么能根据方法的返回值得到View对象？</p> <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">protected</span> View <span class="hljs-title">resolveViewName</span><span class="hljs-params">(String viewName, Map&lt;String, Object&gt; model, Locale locale,</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">HttpServletRequest request)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">       <span class="hljs-comment">//遍历所有resolver</span></span><br><span class="line"><span class="hljs-keyword">for</span> (ViewResolver viewResolver : <span class="hljs-keyword">this</span>.viewResolvers) &#123;</span><br><span class="line">    <span class="hljs-comment">//ViewResolver视图解析器根据方法的返回值，得到一个View对象</span></span><br><span class="line">View view = viewResolver.resolveViewName(viewName, locale);</span><br><span class="line"><span class="hljs-keyword">if</span> (view != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> view;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>viewResolver.resolveViewName细节 <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line">   <span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> View <span class="hljs-title">resolveViewName</span><span class="hljs-params">(String viewName, Locale locale)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (!isCache()) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> createView(viewName, locale);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">Object cacheKey = getCacheKey(viewName, locale);</span><br><span class="line">View view = <span class="hljs-keyword">this</span>.viewAccessCache.get(cacheKey);</span><br><span class="line"><span class="hljs-keyword">if</span> (view == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>.viewCreationCache) &#123;</span><br><span class="line">view = <span class="hljs-keyword">this</span>.viewCreationCache.get(cacheKey);</span><br><span class="line"><span class="hljs-keyword">if</span> (view == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-comment">// Ask the subclass to create the View object.</span></span><br><span class="line"><span class="hljs-comment">/*****创建******/</span></span><br><span class="line">view = createView(viewName, locale);</span><br><span class="line"><span class="hljs-keyword">if</span> (view == <span class="hljs-keyword">null</span> &amp;&amp; <span class="hljs-keyword">this</span>.cacheUnresolved) &#123;</span><br><span class="line">view = UNRESOLVED_VIEW;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (view != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.viewAccessCache.put(cacheKey, view);</span><br><span class="line"><span class="hljs-keyword">this</span>.viewCreationCache.put(cacheKey, view);</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isTraceEnabled()) &#123;</span><br><span class="line">logger.trace(<span class="hljs-string">"Cached view ["</span> + cacheKey + <span class="hljs-string">"]"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> (view != UNRESOLVED_VIEW ? view : <span class="hljs-keyword">null</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>创建View的细节 <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@Override</span></span><br><span class="line">    <span class="hljs-function"><span class="hljs-keyword">protected</span> View <span class="hljs-title">createView</span><span class="hljs-params">(String viewName, Locale locale)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"><span class="hljs-comment">// If this resolver is not supposed to handle the given view,</span></span><br><span class="line"><span class="hljs-comment">// return null to pass on to the next resolver in the chain.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (!canHandle(viewName, locale)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">// Check for special "redirect:" prefix.</span></span><br><span class="line"><span class="hljs-comment">/********/</span></span><br><span class="line"><span class="hljs-keyword">if</span> (viewName.startsWith(REDIRECT_URL_PREFIX)) &#123;</span><br><span class="line">String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());</span><br><span class="line">RedirectView view = <span class="hljs-keyword">new</span> RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());</span><br><span class="line"><span class="hljs-keyword">return</span> applyLifecycleMethods(viewName, view);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">// Check for special "forward:" prefix.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (viewName.startsWith(FORWARD_URL_PREFIX)) &#123;</span><br><span class="line">String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> InternalResourceView(forwardUrl);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">// Else fall back to superclass implementation: calling loadView.</span></span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.createView(viewName, locale);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><pre><code>**视图解析器得到View的流程**    &gt; 所有配置的视图解析器都来尝试根据视图名（返回值）得到View对象      &gt; 如果能得到就返回，得不到就换下一个视图解析器      &gt; 再调用View对象的Render,</code></pre></li></ol></li><li><p>View中的render得到</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@Override</span></span><br><span class="line">  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">render</span><span class="hljs-params">(Map&lt;String, ?&gt; model, HttpServletRequest request, HttpServletResponse response)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line">   <span class="hljs-keyword">if</span> (logger.isTraceEnabled()) &#123;</span><br><span class="line">   logger.trace(<span class="hljs-string">"Rendering view with name '"</span> + <span class="hljs-keyword">this</span>.beanName + <span class="hljs-string">"' with model "</span> + model +</span><br><span class="line">   <span class="hljs-string">" and static attributes "</span> + <span class="hljs-keyword">this</span>.staticAttributes);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   Map&lt;String, Object&gt; mergedModel = createMergedOutputModel(model, request, response);</span><br><span class="line"></span><br><span class="line">   prepareResponse(request, response);</span><br><span class="line">   <span class="hljs-comment">//渲染页面输出的所有数据</span></span><br><span class="line">   renderMergedOutputModel(mergedModel, request, response);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>renderMergedOutputModel位于InternalResourceView</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line">       <span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">renderMergedOutputModel</span><span class="hljs-params">(</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">Map&lt;String, Object&gt; model, HttpServletRequest request, HttpServletResponse response)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Determine which request handle to expose to the RequestDispatcher.</span></span><br><span class="line">HttpServletRequest requestToExpose = getRequestToExpose(request);</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// *** Expose the model object as request attributes.</span></span><br><span class="line"><span class="hljs-comment">//将模型的数据放到request域中</span></span><br><span class="line">exposeModelAsRequestAttributes(model, requestToExpose);</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Expose helpers as request attributes, if any.</span></span><br><span class="line">exposeHelpers(requestToExpose);</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Determine the path for the request dispatcher.</span></span><br><span class="line">String dispatcherPath = prepareForRendering(requestToExpose, response);</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Obtain a RequestDispatcher for the target resource (typically a JSP).</span></span><br><span class="line">RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);</span><br><span class="line"><span class="hljs-keyword">if</span> (rd == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(<span class="hljs-string">"Could not get RequestDispatcher for ["</span> + getUrl() +</span><br><span class="line"><span class="hljs-string">"]: Check that the corresponding file exists within your web application archive!"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// If already included or response already committed, perform include, else forward.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (useInclude(requestToExpose, response)) &#123;</span><br><span class="line">response.setContentType(getContentType());</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Including resource ["</span> + getUrl() + <span class="hljs-string">"] in InternalResourceView '"</span> + getBeanName() + <span class="hljs-string">"'"</span>);</span><br><span class="line">&#125;</span><br><span class="line">rd.include(requestToExpose, response);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line"><span class="hljs-comment">// Note: The forwarded resource is supposed to determine the content type itself.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Forwarding to resource ["</span> + getUrl() + <span class="hljs-string">"] in InternalResourceView '"</span> + getBeanName() + <span class="hljs-string">"'"</span>);</span><br><span class="line">&#125;</span><br><span class="line">rd.forward(requestToExpose, response);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>为什么数据可以在请求域中获得</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">exposeModelAsRequestAttributes</span><span class="hljs-params">(Map&lt;String, Object&gt; model, HttpServletRequest request)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"><span class="hljs-keyword">for</span> (Map.Entry&lt;String, Object&gt; entry : model.entrySet()) &#123;</span><br><span class="line">String modelName = entry.getKey();</span><br><span class="line">Object modelValue = entry.getValue();</span><br><span class="line"><span class="hljs-keyword">if</span> (modelValue != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">request.setAttribute(modelName, modelValue);</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Added model object '"</span> + modelName + <span class="hljs-string">"' of type ["</span> + modelValue.getClass().getName() +</span><br><span class="line"><span class="hljs-string">"] to request in view with name '"</span> + getBeanName() + <span class="hljs-string">"'"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">request.removeAttribute(modelName);</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Removed model object '"</span> + modelName +</span><br><span class="line"><span class="hljs-string">"' from request in view with name '"</span> + getBeanName() + <span class="hljs-string">"'"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><hr><p>视图解析器只是为了获得视图对象；视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面<br>视图对象才能真正渲染视图<br>源码执行流程<br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200223132633.png" alt></p><hr>]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- toc --&gt;

&lt;h2 id=&quot;SpringMVC如何解析视图概述&quot;&gt;&lt;a href=&quot;#SpringMVC如何解析视图概述&quot; class=&quot;headerlink&quot; title=&quot;SpringMVC如何解析视图概述&quot;&gt;&lt;/a&gt;SpringMVC如何解析视图概述&lt;/h2
      
    
    </summary>
    
    
      <category term="Spring MVC" scheme="https://lyhcc.github.io/categories/Spring-MVC/"/>
    
    
      <category term="SpringMVC之视图解析器" scheme="https://lyhcc.github.io/tags/SpringMVC%E4%B9%8B%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>SpringMVC之ModelAttribute</title>
    <link href="https://lyhcc.github.io/post/548d7f45.html"/>
    <id>https://lyhcc.github.io/post/548d7f45.html</id>
    <published>2020-02-20T08:34:13.329Z</published>
    <updated>2020-02-20T11:53:08.282Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="ModelAttribute实验场景"><a href="#ModelAttribute实验场景" class="headerlink" title="@ModelAttribute实验场景"></a>@ModelAttribute实验场景</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200220163630.png" alt><br><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200220163657.png" alt></p><a id="more"></a><h2 id="ModelAttribute注解之示例代码"><a href="#ModelAttribute注解之示例代码" class="headerlink" title="@ModelAttribute注解之示例代码"></a>@ModelAttribute注解之示例代码</h2><ul><li>在方法定义上使用 @ModelAttribute 注解：Spring MVC 在调用目标处理方法前，会先逐个调用在方法级上标注了 @ModelAttribute 的方法。</li><li>在方法的入参前使用 @ModelAttribute 注解：可以从隐含对象中获取隐含的模型数据中获取对象，再将请求参数绑定到对象中，再传入入参</li><li>将方法入参对象添加到模型中<ol><li>页面表单代码 <figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">" testPOJO"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span></span><br><span class="line">       <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"id"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"1"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">       username: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">       password: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"pwd"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">       </span><br><span class="line">       gender: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"gender"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">   </span><br><span class="line">       <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit"</span>/&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li>增加ModelAttribute注解 <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"testPOJO"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">testPOJO</span><span class="hljs-params">(@ModelAttribute(<span class="hljs-string">"person"</span>)</span> Person person) </span>&#123;</span><br><span class="line">    System.out.println(person);</span><br><span class="line">    <span class="hljs-keyword">return</span> <span class="hljs-string">"success"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-meta">@ModelAttribute</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getPerson</span><span class="hljs-params">(@RequestParam(value=<span class="hljs-string">"id"</span>,required=<span class="hljs-keyword">false</span>)</span>String id,Map&lt;String, Object&gt; map) </span>&#123;</span><br><span class="line">    System.out.println(<span class="hljs-string">"ModelAttribute方法运行..."</span>);</span><br><span class="line">    Person person = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"as"</span>, <span class="hljs-string">"12"</span>, <span class="hljs-string">"qw"</span>, <span class="hljs-string">"asas"</span>);</span><br><span class="line">    System.out.println(person);</span><br><span class="line">    map.put(<span class="hljs-string">"person"</span>, person);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol></li></ul><h3 id="ModelAttribute的运行流程"><a href="#ModelAttribute的运行流程" class="headerlink" title="ModelAttribute的运行流程"></a>ModelAttribute的运行流程</h3><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200220163259.png" alt></p><h2 id="ModelAttribute源码参考"><a href="#ModelAttribute源码参考" class="headerlink" title="@ModelAttribute源码参考"></a>@ModelAttribute源码参考</h2><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@Target</span>(&#123;ElementType.PARAMETER, ElementType.METHOD&#125;)</span><br><span class="line"><span class="hljs-meta">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="hljs-meta">@Documented</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-meta">@interface</span> ModelAttribute &#123;</span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * The name of the model attribute to bind to.</span></span><br><span class="line"><span class="hljs-comment"> * &lt;p&gt;The default model attribute name is inferred from the declared</span></span><br><span class="line"><span class="hljs-comment"> * attribute type (i.e. the method parameter type or method return type),</span></span><br><span class="line"><span class="hljs-comment"> * based on the non-qualified class name:</span></span><br><span class="line"><span class="hljs-comment"> * e.g. "orderAddress" for class "mypackage.OrderAddress",</span></span><br><span class="line"><span class="hljs-comment"> * or "orderAddressList" for "List&amp;lt;mypackage.OrderAddress&amp;gt;".</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-function">String <span class="hljs-title">value</span><span class="hljs-params">()</span> <span class="hljs-keyword">default</span> ""</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="ModelAttribute注解之源码分析"><a href="#ModelAttribute注解之源码分析" class="headerlink" title="@ModelAttribute注解之源码分析"></a>@ModelAttribute注解之源码分析</h2><blockquote><p>源代码分析的流程</p><p>① 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.</p><p>② 解析请求处理器的目标参数, 实际上该目标参数来自于 WebDataBinder 对象的 target 属性</p><ol><li><p>创建 WebDataBinder 对象:</p><ol><li><p>确定 objectName 属性: 若传入的 attrName 属性值为 “”, 则objectName 为类名第一个字母小写. </p><ul><li>注意: attrName. 若目标方法的 POJO 属性使用了 @ModelAttribute 来修饰, 则 attrName 值即为 @ModelAttribute 的 value 属性值   </li></ul></li><li><p>确定 target 属性:</p><blockquote><p> 在 implicitModel 中查找 attrName 对应的属性值. 若存在, ok</p><p>若不存在: 则验证当前 Handler 是否使用了 @SessionAttributes 进行修饰, 若使用了, 则尝试从 Session 中获取 attrName 所对应的属性值. </p></blockquote><blockquote><p>若 session 中没有对应的属性值, 则抛出了异常. </p></blockquote><blockquote><p>若 Handler 没有使用 @SessionAttributes 进行修饰, 或 @SessionAttributes 中没有使用 value 值指定的 key和 attrName 相匹配, 则通过反射创建了 POJO 对象  </p></blockquote></li></ol></li><li><p>. SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性. </p></li><li><p>SpringMVC 会把 WebDataBinder 的 attrName 和 target 给到 implicitModel. 进而传到 request 域对象中.</p></li><li><p>把 WebDataBinder 的 target 作为参数传递给目标方法的入参. </p></li></ol></blockquote><h2 id="SpringMVC-确定目标方法POJO类型入参的过程"><a href="#SpringMVC-确定目标方法POJO类型入参的过程" class="headerlink" title="SpringMVC 确定目标方法POJO类型入参的过程"></a>SpringMVC 确定目标方法POJO类型入参的过程</h2><p>① 确定一个 key:</p><p>​      1). 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写</p><p>​      2). 若使用了@ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值. </p><p>② 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入</p><ul><li>若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 ① 确定的 key 一致, 则会获取到. </li></ul><p>③ 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, </p><p>④ 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常. </p><p>⑤ 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数</p><p>⑥ SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中. </p><h2 id="sessionAttributes注解引发的异常"><a href="#sessionAttributes注解引发的异常" class="headerlink" title="@sessionAttributes注解引发的异常"></a>@sessionAttributes注解引发的异常</h2><ol><li><p>由@SessionAttributes引发的异常</p><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200220194314.png" alt></p></li><li><p>① 果在处理类定义处标注了@SessionAttributes(“xxx”)，则尝试从会话中获取该属性，并将其赋给该入参，然后再用请求消息填充该入参对象。如果在会话中找不到对应的属性，则抛出 HttpSessionRequiredException 异常</p><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200220194505.png" alt></p></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;h2 id=&quot;ModelAttribute实验场景&quot;&gt;&lt;a href=&quot;#ModelAttribute实验场景&quot; class=&quot;headerlink&quot; title=&quot;@ModelAttribute实验场景&quot;&gt;&lt;/a&gt;@ModelAttribute实验场景&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200220163630.png&quot; alt&gt;&lt;br&gt;&lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200220163657.png&quot; alt&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="Sprig MVC" scheme="https://lyhcc.github.io/categories/Sprig-MVC/"/>
    
    
      <category term="SpringMVC之ModelAttribute" scheme="https://lyhcc.github.io/tags/SpringMVC%E4%B9%8BModelAttribute/"/>
    
  </entry>
  
  <entry>
    <title>SpringMVC源码分析</title>
    <link href="https://lyhcc.github.io/post/eaa9b691.html"/>
    <id>https://lyhcc.github.io/post/eaa9b691.html</id>
    <published>2020-02-19T11:04:57.382Z</published>
    <updated>2020-02-21T16:37:55.587Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="Spring-MVC中DispatchServlet运行流程"><a href="#Spring-MVC中DispatchServlet运行流程" class="headerlink" title="Spring MVC中DispatchServlet运行流程"></a>Spring MVC中DispatchServlet运行流程</h2><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200219190425.png" alt></p><p>​    <a id="more"></a></p><ol><li><p>doDispatch()详细细节</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doDispatch</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line">HttpServletRequest processedRequest = request;</span><br><span class="line">HandlerExecutionChain mappedHandler = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> multipartRequestParsed = <span class="hljs-keyword">false</span>;</span><br><span class="line"></span><br><span class="line">WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line">ModelAndView mv = <span class="hljs-keyword">null</span>;</span><br><span class="line">Exception dispatchException = <span class="hljs-keyword">null</span>;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line">                <span class="hljs-comment">//1、 检查是否文件上传请求</span></span><br><span class="line">processedRequest = checkMultipart(request);</span><br><span class="line">multipartRequestParsed = processedRequest != request;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/****** Determine handler for the current request.*/</span></span><br><span class="line">                <span class="hljs-comment">//2、根据当前的请求地址找到那个类能来处理</span></span><br><span class="line">mappedHandler = getHandler(processedRequest);</span><br><span class="line"><span class="hljs-keyword">if</span> (mappedHandler == <span class="hljs-keyword">null</span> || mappedHandler.getHandler() == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">                    <span class="hljs-comment">//3、如果没有找到处理器可以处理当前请求，抛出异常</span></span><br><span class="line">noHandlerFound(processedRequest, response);</span><br><span class="line"><span class="hljs-keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Determine handler adapter for the current request.</span></span><br><span class="line">                <span class="hljs-comment">//4、拿到可以执行这个处理器类的所有方法的适配器（反射工具）</span></span><br><span class="line">HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Process last-modified header, if supported by the handler.</span></span><br><span class="line">String method = request.getMethod();</span><br><span class="line"><span class="hljs-keyword">boolean</span> isGet = <span class="hljs-string">"GET"</span>.equals(method);</span><br><span class="line"><span class="hljs-keyword">if</span> (isGet || <span class="hljs-string">"HEAD"</span>.equals(method)) &#123;</span><br><span class="line"><span class="hljs-keyword">long</span> lastModified = ha.getLastModified(request, mappedHandler.getHandler());</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">String requestUri = urlPathHelper.getRequestUri(request);</span><br><span class="line">logger.debug(<span class="hljs-string">"Last-Modified value for ["</span> + requestUri + <span class="hljs-string">"] is: "</span> + lastModified);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">new</span> ServletWebRequest(request, response).checkNotModified(lastModified) &amp;&amp; isGet) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (!mappedHandler.applyPreHandle(processedRequest, response)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line">                    </span><br><span class="line">                    </span><br><span class="line">                    </span><br><span class="line">                    <span class="hljs-comment">/************</span></span><br><span class="line"><span class="hljs-comment">                    ***注意：控制器执行*******</span></span><br><span class="line"><span class="hljs-comment">                    *************</span></span><br><span class="line"><span class="hljs-comment">                    */</span></span><br><span class="line">                    <span class="hljs-comment">//5、适配器来回显目标方法：将目标方法执行完成后的返回值作为视图名，设置保存到ModelAndView</span></span><br><span class="line">                    <span class="hljs-comment">//目标方法无论怎么写，最终适配器执行完后，都会封装为ModelAndView</span></span><br><span class="line"><span class="hljs-comment">// Actually invoke the handler.</span></span><br><span class="line">mv = ha.handle(processedRequest, response, mappedHandler.getHandler());</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><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">finally</span> &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (asyncManager.isConcurrentHandlingStarted()) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">applyDefaultViewName(request, mv);<span class="hljs-comment">//如果没有视图名，取默认</span></span><br><span class="line">mappedHandler.applyPostHandle(processedRequest, response, mv);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (Exception ex) &#123;</span><br><span class="line">dispatchException = ex;</span><br><span class="line">&#125;</span><br><span class="line">             <span class="hljs-comment">/************</span></span><br><span class="line"><span class="hljs-comment">              ***注意：转发目标页面执行*******</span></span><br><span class="line"><span class="hljs-comment">              *************</span></span><br><span class="line"><span class="hljs-comment">             */</span></span><br><span class="line">            <span class="hljs-comment">//6、根据方法最终执行完成后封装的ModelAndView，转发到对应页面，而且ModelAndView中的数据可以从请求域中获取</span></span><br><span class="line">processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (Exception ex) &#123;</span><br><span class="line">triggerAfterCompletion(processedRequest, response, mappedHandler, ex);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (Error err) &#123;</span><br><span class="line">triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">finally</span> &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (asyncManager.isConcurrentHandlingStarted()) &#123;</span><br><span class="line"><span class="hljs-comment">// Instead of postHandle and afterCompletion</span></span><br><span class="line">mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);</span><br><span class="line"><span class="hljs-keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">// Clean up any resources used by a multipart request.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (multipartRequestParsed) &#123;</span><br><span class="line">cleanupMultipart(processedRequest);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><ol><li><p>所有请求过来DispatchServlet收到请求</p></li><li><p>调用doDispatch() 方法进行处理</p><ol><li><p>getHandler():  根据当前请求地址找到能处理这个请求的的目标的类（处理器）</p><p>​    根据当前请求在HandlerMapping中找到这个请求的映射信息，获取到目标处理器类</p></li><li><p>getHandlerAdapter(）：根据当前处理器获取到能执行这个处理器方法的适配器</p><p>根据当前处理器类，找到当前类的HandlerAdapter</p></li><li><p>使用当前获取到的适配器（RequestMappingHandlerAdapter）执行目标方法</p></li><li><p>目标方法执行后会返回一个ModelAndView对象</p></li><li><p>根据ModelAndView的信息转发到具体的页面，并可以在请求域中取出ModelAndView中的模型数据</p></li></ol></li></ol><hr></li></ol><ol start="2"><li><p>getHandler()细节：怎么根据当前请求就能找到哪个类能处理</p><blockquote><p>getHandler() 会返回目标处理器类的执行链</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">protected</span> HandlerExecutionChain <span class="hljs-title">getHandler</span><span class="hljs-params">(HttpServletRequest request)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line">    <span class="hljs-comment">//HandlerMappings处理器映射：他里面保存了每一个处理器能处理那些方法的映射信息</span></span><br><span class="line"><span class="hljs-keyword">for</span> (HandlerMapping hm : <span class="hljs-keyword">this</span>.handlerMappings) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isTraceEnabled()) &#123;</span><br><span class="line">logger.trace(</span><br><span class="line"><span class="hljs-string">"Testing handler map ["</span> + hm + <span class="hljs-string">"] in DispatcherServlet with name '"</span> + getServletName() + <span class="hljs-string">"'"</span>);</span><br><span class="line">&#125;</span><br><span class="line">HandlerExecutionChain handler = hm.getHandler(request);</span><br><span class="line"><span class="hljs-keyword">if</span> (handler != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> handler;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200221140852.png" alt></p><blockquote><p>handlerMap: ioc容器自动创建Controller对象的时候扫描每个处理器都能处理什么请求，保存在HandlerMapping的handlerMap属性中：下一次请求过来就来查看那个handlerMapping中有相应的请求映射信息</p></blockquote></li><li><p>getHandlerAdapter() 细节(如何找到目标处理器类的适配器？)</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">protected</span> HandlerAdapter <span class="hljs-title">getHandlerAdapter</span><span class="hljs-params">(Object handler)</span> <span class="hljs-keyword">throws</span> ServletException </span>&#123;</span><br><span class="line"><span class="hljs-keyword">for</span> (HandlerAdapter ha : <span class="hljs-keyword">this</span>.handlerAdapters) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isTraceEnabled()) &#123;</span><br><span class="line">logger.trace(<span class="hljs-string">"Testing handler adapter ["</span> + ha + <span class="hljs-string">"]"</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (ha.supports(handler)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> ha;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(<span class="hljs-string">"No adapter for handler ["</span> + handler +</span><br><span class="line"><span class="hljs-string">"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://gitee.com//lyhcc/Images/raw/master/img/20200221141931.png" alt></p></li></ol><ol start="4"><li><p>研究HandlerMappings和HandlerAdapters如何获取值，</p><blockquote><p>可以在web.xml中修改DispatchServlet某些属性的默认配置</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initHandlerMappings</span><span class="hljs-params">(ApplicationContext context)</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.handlerMappings = <span class="hljs-keyword">null</span>;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.detectAllHandlerMappings) &#123;</span><br><span class="line"><span class="hljs-comment">// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.</span></span><br><span class="line">Map&lt;String, HandlerMapping&gt; matchingBeans =</span><br><span class="line">BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>);</span><br><span class="line"><span class="hljs-keyword">if</span> (!matchingBeans.isEmpty()) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.handlerMappings = <span class="hljs-keyword">new</span> ArrayList&lt;HandlerMapping&gt;(matchingBeans.values());</span><br><span class="line"><span class="hljs-comment">// We keep HandlerMappings in sorted order.</span></span><br><span class="line">OrderComparator.sort(<span class="hljs-keyword">this</span>.handlerMappings);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line">HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);</span><br><span class="line"><span class="hljs-keyword">this</span>.handlerMappings = Collections.singletonList(hm);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (NoSuchBeanDefinitionException ex) &#123;</span><br><span class="line"><span class="hljs-comment">// Ignore, we'll add a default HandlerMapping later.</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Ensure we have at least one HandlerMapping, by registering</span></span><br><span class="line"><span class="hljs-comment">// a default HandlerMapping if no other mappings are found.</span></span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.handlerMappings == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);</span><br><span class="line"><span class="hljs-keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"No HandlerMappings found in servlet '"</span> + getServletName() + <span class="hljs-string">"': using default"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>组件的初始化：</p><p>​    有些组件是通过类型找，有些是通过id</p><p>​    去容器中找这个组件，如果没有找到就用默认配置</p></blockquote></li><li><p>如何调用目标方法？</p><ol><li>DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 945    </li><li>AnnotationMethodHandlerAdapter.handle(HttpServletRequest, HttpServletResponse, Object) line: 406    </li><li></li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">protected</span> ModelAndView <span class="hljs-title">invokeHandlerMethod</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"><span class="hljs-comment">//拿到方法解析器</span></span><br><span class="line">ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);</span><br><span class="line">    <span class="hljs-comment">//方法解析器根据当前请求地址找到真正的方法</span></span><br><span class="line">Method handlerMethod = methodResolver.resolveHandlerMethod(request);</span><br><span class="line">    <span class="hljs-comment">//创建方法执行器</span></span><br><span class="line">ServletHandlerMethodInvoker methodInvoker = <span class="hljs-keyword">new</span> ServletHandlerMethodInvoker(methodResolver);</span><br><span class="line">    <span class="hljs-comment">//包装原生的response和request</span></span><br><span class="line">ServletWebRequest webRequest = <span class="hljs-keyword">new</span> ServletWebRequest(request, response);</span><br><span class="line">    <span class="hljs-comment">//创建隐含模型</span></span><br><span class="line">ExtendedModelMap implicitModel = <span class="hljs-keyword">new</span> BindingAwareModelMap();</span><br><span class="line"><span class="hljs-comment">//真正执行目标方法</span></span><br><span class="line">    <span class="hljs-comment">//目标方法执行期间利用反射执行期间确定参数值</span></span><br><span class="line">Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);</span><br><span class="line">ModelAndView mav =</span><br><span class="line">methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);</span><br><span class="line">methodInvoker.updateModelAttributes(handler, (mav != <span class="hljs-keyword">null</span> ? mav.getModel() : <span class="hljs-keyword">null</span>), implicitModel, webRequest);</span><br><span class="line"><span class="hljs-keyword">return</span> mav;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="4"><li><p>AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker(HandlerMethodInvoker).invokeHandlerMethod</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> Object <span class="hljs-title">invokeHandlerMethod</span><span class="hljs-params">(Method handlerMethod, Object handler,</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">NativeWebRequest webRequest, ExtendedModelMap implicitModel)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);</span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line"><span class="hljs-keyword">boolean</span> debug = logger.isDebugEnabled();</span><br><span class="line"><span class="hljs-keyword">for</span> (String attrName : <span class="hljs-keyword">this</span>.methodResolver.getActualSessionAttributeNames()) &#123;</span><br><span class="line">Object attrValue = <span class="hljs-keyword">this</span>.sessionAttributeStore.retrieveAttribute(webRequest, attrName);</span><br><span class="line"><span class="hljs-keyword">if</span> (attrValue != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">implicitModel.addAttribute(attrName, attrValue);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">            <span class="hljs-comment">/*************/</span></span><br><span class="line">            <span class="hljs-comment">/*     获取Modelattribute标注的方法    */</span></span><br><span class="line">            <span class="hljs-comment">/*           */</span></span><br><span class="line">            <span class="hljs-comment">/*************/</span></span><br><span class="line"><span class="hljs-keyword">for</span> (Method attributeMethod : <span class="hljs-keyword">this</span>.methodResolver.getModelAttributeMethods()) &#123;</span><br><span class="line">                <span class="hljs-comment">//先确定modelattribute方法执行是要使用的每一个参数的值</span></span><br><span class="line">Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);</span><br><span class="line">                <span class="hljs-comment">//args</span></span><br><span class="line">Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);</span><br><span class="line"><span class="hljs-keyword">if</span> (debug) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Invoking model attribute method: "</span> + attributeMethodToInvoke);</span><br><span class="line">&#125;</span><br><span class="line">String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();</span><br><span class="line"><span class="hljs-keyword">if</span> (!<span class="hljs-string">""</span>.equals(attrName) &amp;&amp; implicitModel.containsAttribute(attrName)) &#123;</span><br><span class="line"><span class="hljs-keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line">ReflectionUtils.makeAccessible(attributeMethodToInvoke);</span><br><span class="line">Object attrValue = attributeMethodToInvoke.invoke(handler, args);</span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-string">""</span>.equals(attrName)) &#123;</span><br><span class="line">Class&lt;?&gt; resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());</span><br><span class="line">attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (!implicitModel.containsAttribute(attrName)) &#123;</span><br><span class="line">implicitModel.addAttribute(attrName, attrValue);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);</span><br><span class="line"><span class="hljs-keyword">if</span> (debug) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Invoking request handler method: "</span> + handlerMethodToInvoke);</span><br><span class="line">&#125;</span><br><span class="line">ReflectionUtils.makeAccessible(handlerMethodToInvoke);</span><br><span class="line"><span class="hljs-keyword">return</span> handlerMethodToInvoke.invoke(handler, args);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (IllegalStateException ex) &#123;</span><br><span class="line"><span class="hljs-comment">// Internal assertion failed (e.g. invalid signature):</span></span><br><span class="line"><span class="hljs-comment">// throw exception with full handler method context...</span></span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HandlerMethodInvocationException(handlerMethodToInvoke, ex);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (InvocationTargetException ex) &#123;</span><br><span class="line"><span class="hljs-comment">// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...</span></span><br><span class="line">ReflectionUtils.rethrowException(ex.getTargetException());</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="5"><li>确定方法运行时使用的每一个参数值</li></ol><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">private</span> Object[] resolveHandlerArguments(Method handlerMethod, Object handler,</span><br><span class="line">NativeWebRequest webRequest, ExtendedModelMap implicitModel) <span class="hljs-keyword">throws</span> Exception &#123;</span><br><span class="line"></span><br><span class="line">Class&lt;?&gt;[] paramTypes = handlerMethod.getParameterTypes();</span><br><span class="line">    <span class="hljs-comment">//创建了一个和参数个数一样多的数组，用来保存每一个参数的值</span></span><br><span class="line">Object[] args = <span class="hljs-keyword">new</span> Object[paramTypes.length];</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; args.length; i++) &#123;</span><br><span class="line">MethodParameter methodParam = <span class="hljs-keyword">new</span> MethodParameter(handlerMethod, i);</span><br><span class="line">methodParam.initParameterNameDiscovery(<span class="hljs-keyword">this</span>.parameterNameDiscoverer);</span><br><span class="line">GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());</span><br><span class="line">String paramName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String headerName = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> requestBodyFound = <span class="hljs-keyword">false</span>;</span><br><span class="line">String cookieName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String pathVarName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String attrName = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> required = <span class="hljs-keyword">false</span>;</span><br><span class="line">String defaultValue = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> validate = <span class="hljs-keyword">false</span>;</span><br><span class="line">Object[] validationHints = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">int</span> annotationsFound = <span class="hljs-number">0</span>;</span><br><span class="line">Annotation[] paramAnns = methodParam.getParameterAnnotations();</span><br><span class="line"><span class="hljs-comment">//拿到所有注解，解析注解</span></span><br><span class="line"><span class="hljs-keyword">for</span> (Annotation paramAnn : paramAnns) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (RequestParam.class.isInstance(paramAnn)) &#123;</span><br><span class="line">RequestParam requestParam = (RequestParam) paramAnn;</span><br><span class="line">paramName = requestParam.value();</span><br><span class="line">required = requestParam.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (RequestHeader.class.isInstance(paramAnn)) &#123;</span><br><span class="line">RequestHeader requestHeader = (RequestHeader) paramAnn;</span><br><span class="line">headerName = requestHeader.value();</span><br><span class="line">required = requestHeader.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (RequestBody.class.isInstance(paramAnn)) &#123;</span><br><span class="line">requestBodyFound = <span class="hljs-keyword">true</span>;</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (CookieValue.class.isInstance(paramAnn)) &#123;</span><br><span class="line">CookieValue cookieValue = (CookieValue) paramAnn;</span><br><span class="line">cookieName = cookieValue.value();</span><br><span class="line">required = cookieValue.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (PathVariable.class.isInstance(paramAnn)) &#123;</span><br><span class="line">PathVariable pathVar = (PathVariable) paramAnn;</span><br><span class="line">pathVarName = pathVar.value();</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ModelAttribute.class.isInstance(paramAnn)) &#123;</span><br><span class="line">ModelAttribute attr = (ModelAttribute) paramAnn;</span><br><span class="line">attrName = attr.value();</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Value.class.isInstance(paramAnn)) &#123;</span><br><span class="line">defaultValue = ((Value) paramAnn).value();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paramAnn.annotationType().getSimpleName().startsWith(<span class="hljs-string">"Valid"</span>)) &#123;</span><br><span class="line">validate = <span class="hljs-keyword">true</span>;</span><br><span class="line">Object value = AnnotationUtils.getValue(paramAnn);</span><br><span class="line">validationHints = (value <span class="hljs-keyword">instanceof</span> Object[] ? (Object[]) value : <span class="hljs-keyword">new</span> Object[] &#123;value&#125;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (annotationsFound &gt; <span class="hljs-number">1</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Handler parameter annotations are exclusive choices - "</span> +</span><br><span class="line"><span class="hljs-string">"do not specify more than one such annotation on the same parameter: "</span> + handlerMethod);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">//没有找到注解的情况</span></span><br><span class="line"><span class="hljs-keyword">if</span> (annotationsFound == <span class="hljs-number">0</span>) &#123;</span><br><span class="line">                <span class="hljs-comment">//解析普通参数</span></span><br><span class="line">Object argValue = resolveCommonArgument(methodParam, webRequest);--&gt;解析标准参数</span><br><span class="line"><span class="hljs-keyword">if</span> (argValue != WebArgumentResolver.UNRESOLVED) &#123;</span><br><span class="line">args[i] = argValue;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (defaultValue != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveDefaultValue(defaultValue);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">Class&lt;?&gt; paramType = methodParam.getParameterType();</span><br><span class="line"><span class="hljs-keyword">if</span> (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (!paramType.isAssignableFrom(implicitModel.getClass())) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Argument ["</span> + paramType.getSimpleName() + <span class="hljs-string">"] is of type "</span> +</span><br><span class="line"><span class="hljs-string">"Model or Map but is not assignable from the actual model. You may need to switch "</span> +</span><br><span class="line"><span class="hljs-string">"newer MVC infrastructure classes to use this argument."</span>);</span><br><span class="line">&#125;</span><br><span class="line">args[i] = implicitModel;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (SessionStatus.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line">args[i] = <span class="hljs-keyword">this</span>.sessionStatus;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (HttpEntity.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line">args[i] = resolveHttpEntityRequest(methodParam, webRequest);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Errors.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Errors/BindingResult argument declared "</span> +</span><br><span class="line"><span class="hljs-string">"without preceding model attribute. Check your handler method signature!"</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (BeanUtils.isSimpleProperty(paramType)) &#123;</span><br><span class="line">paramName = <span class="hljs-string">""</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">attrName = <span class="hljs-string">""</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (paramName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (headerName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (requestBodyFound) &#123;</span><br><span class="line">args[i] = resolveRequestBody(methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cookieName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pathVarName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (attrName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">WebDataBinder binder =</span><br><span class="line">resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);</span><br><span class="line"><span class="hljs-keyword">boolean</span> assignBindingResult = (args.length &gt; i + <span class="hljs-number">1</span> &amp;&amp; Errors.class.isAssignableFrom(paramTypes[i + <span class="hljs-number">1</span>]));</span><br><span class="line"><span class="hljs-keyword">if</span> (binder.getTarget() != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">doBind(binder, webRequest, validate, validationHints, !assignBindingResult);</span><br><span class="line">&#125;</span><br><span class="line">args[i] = binder.getTarget();</span><br><span class="line"><span class="hljs-keyword">if</span> (assignBindingResult) &#123;</span><br><span class="line">args[i + <span class="hljs-number">1</span>] = binder.getBindingResult();</span><br><span class="line">i++;</span><br><span class="line">&#125;</span><br><span class="line">implicitModel.putAll(binder.getBindingResult().getModel());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">return</span> args;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p><strong>如果没有注解：</strong> </p><ol><li>resolveCommonArgument)先看是否普通参数，确定当前的参数是否是原生API</li><li>如果是Map或者Map子类，将之前创建的隐含模型赋值过去</li></ol><hr><hr><p>方法上标注的ModelAttribute注解如果有value值</p><p>@ModelAttribute(value=”as”)</p><p>attrName=value标注值</p><p>标了：attrName=”abc”</p><p>没标：attrName=””;attrName就会变为返回值类型首字母小写</p><p>@ModelAttribute标在方法的另一个作用；可以把方法运行后的返回值按照@ModelAttribute(“abc”)放到隐含模型中，如果没有key就用返回值类型void</p><p>{person=Person [name=as, pwd=12, gender=qw, email=asas], void=null}</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> Object <span class="hljs-title">invokeHandlerMethod</span><span class="hljs-params">(Method handlerMethod, Object handler,</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">NativeWebRequest webRequest, ExtendedModelMap implicitModel)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);</span><br><span class="line"><span class="hljs-keyword">try</span> &#123;</span><br><span class="line"><span class="hljs-keyword">boolean</span> debug = logger.isDebugEnabled();</span><br><span class="line"><span class="hljs-keyword">for</span> (String attrName : <span class="hljs-keyword">this</span>.methodResolver.getActualSessionAttributeNames()) &#123;</span><br><span class="line">Object attrValue = <span class="hljs-keyword">this</span>.sessionAttributeStore.retrieveAttribute(webRequest, attrName);</span><br><span class="line"><span class="hljs-keyword">if</span> (attrValue != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">implicitModel.addAttribute(attrName, attrValue);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">for</span> (Method attributeMethod : <span class="hljs-keyword">this</span>.methodResolver.getModelAttributeMethods()) &#123;</span><br><span class="line">Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);</span><br><span class="line">Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);</span><br><span class="line"><span class="hljs-keyword">if</span> (debug) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Invoking model attribute method: "</span> + attributeMethodToInvoke);</span><br><span class="line">&#125;</span><br><span class="line">String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();</span><br><span class="line"><span class="hljs-keyword">if</span> (!<span class="hljs-string">""</span>.equals(attrName) &amp;&amp; implicitModel.containsAttribute(attrName)) &#123;</span><br><span class="line"><span class="hljs-keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line">ReflectionUtils.makeAccessible(attributeMethodToInvoke);</span><br><span class="line">                <span class="hljs-comment">//@ModelAttribute标注的方法先运行</span></span><br><span class="line">Object attrValue = attributeMethodToInvoke.invoke(handler, args);</span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-string">""</span>.equals(attrName)) &#123;</span><br><span class="line">Class&lt;?&gt; resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());</span><br><span class="line">attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (!implicitModel.containsAttribute(attrName)) &#123;</span><br><span class="line">implicitModel.addAttribute(attrName, attrValue);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);</span><br><span class="line"><span class="hljs-keyword">if</span> (debug) &#123;</span><br><span class="line">logger.debug(<span class="hljs-string">"Invoking request handler method: "</span> + handlerMethodToInvoke);</span><br><span class="line">&#125;</span><br><span class="line">ReflectionUtils.makeAccessible(handlerMethodToInvoke);</span><br><span class="line">            <span class="hljs-comment">//相应目标的方法运行</span></span><br><span class="line"><span class="hljs-keyword">return</span> handlerMethodToInvoke.invoke(handler, args);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (IllegalStateException ex) &#123;</span><br><span class="line"><span class="hljs-comment">// Internal assertion failed (e.g. invalid signature):</span></span><br><span class="line"><span class="hljs-comment">// throw exception with full handler method context...</span></span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HandlerMethodInvocationException(handlerMethodToInvoke, ex);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">catch</span> (InvocationTargetException ex) &#123;</span><br><span class="line"><span class="hljs-comment">// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...</span></span><br><span class="line">ReflectionUtils.rethrowException(ex.getTargetException());</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol></li></ol><ol start="6"><li><p>如何确定方法的每一个参数的值</p><blockquote><p>标了注解：</p><p>&emsp;保存时哪个注解的信息确定值</p><p>&emsp;拿到ModelAttribute注解的值让attrName保存</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">private</span> Object[] resolveHandlerArguments(Method handlerMethod, Object handler,</span><br><span class="line">NativeWebRequest webRequest, ExtendedModelMap implicitModel) <span class="hljs-keyword">throws</span> Exception &#123;</span><br><span class="line"></span><br><span class="line">Class&lt;?&gt;[] paramTypes = handlerMethod.getParameterTypes();</span><br><span class="line">Object[] args = <span class="hljs-keyword">new</span> Object[paramTypes.length];</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; args.length; i++) &#123;</span><br><span class="line">MethodParameter methodParam = <span class="hljs-keyword">new</span> MethodParameter(handlerMethod, i);</span><br><span class="line">methodParam.initParameterNameDiscovery(<span class="hljs-keyword">this</span>.parameterNameDiscoverer);</span><br><span class="line">GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());</span><br><span class="line">String paramName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String headerName = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> requestBodyFound = <span class="hljs-keyword">false</span>;</span><br><span class="line">String cookieName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String pathVarName = <span class="hljs-keyword">null</span>;</span><br><span class="line">String attrName = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> required = <span class="hljs-keyword">false</span>;</span><br><span class="line">String defaultValue = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">boolean</span> validate = <span class="hljs-keyword">false</span>;</span><br><span class="line">Object[] validationHints = <span class="hljs-keyword">null</span>;</span><br><span class="line"><span class="hljs-keyword">int</span> annotationsFound = <span class="hljs-number">0</span>;</span><br><span class="line">Annotation[] paramAnns = methodParam.getParameterAnnotations();</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">for</span> (Annotation paramAnn : paramAnns) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (RequestParam.class.isInstance(paramAnn)) &#123;</span><br><span class="line">RequestParam requestParam = (RequestParam) paramAnn;</span><br><span class="line">paramName = requestParam.value();</span><br><span class="line">required = requestParam.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (RequestHeader.class.isInstance(paramAnn)) &#123;</span><br><span class="line">RequestHeader requestHeader = (RequestHeader) paramAnn;</span><br><span class="line">headerName = requestHeader.value();</span><br><span class="line">required = requestHeader.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (RequestBody.class.isInstance(paramAnn)) &#123;</span><br><span class="line">requestBodyFound = <span class="hljs-keyword">true</span>;</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (CookieValue.class.isInstance(paramAnn)) &#123;</span><br><span class="line">CookieValue cookieValue = (CookieValue) paramAnn;</span><br><span class="line">cookieName = cookieValue.value();</span><br><span class="line">required = cookieValue.required();</span><br><span class="line">defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (PathVariable.class.isInstance(paramAnn)) &#123;</span><br><span class="line">PathVariable pathVar = (PathVariable) paramAnn;</span><br><span class="line">pathVarName = pathVar.value();</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ModelAttribute.class.isInstance(paramAnn)) &#123;</span><br><span class="line">ModelAttribute attr = (ModelAttribute) paramAnn;</span><br><span class="line">attrName = attr.value();</span><br><span class="line">annotationsFound++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Value.class.isInstance(paramAnn)) &#123;</span><br><span class="line">defaultValue = ((Value) paramAnn).value();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paramAnn.annotationType().getSimpleName().startsWith(<span class="hljs-string">"Valid"</span>)) &#123;</span><br><span class="line">validate = <span class="hljs-keyword">true</span>;</span><br><span class="line">Object value = AnnotationUtils.getValue(paramAnn);</span><br><span class="line">validationHints = (value <span class="hljs-keyword">instanceof</span> Object[] ? (Object[]) value : <span class="hljs-keyword">new</span> Object[] &#123;value&#125;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (annotationsFound &gt; <span class="hljs-number">1</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Handler parameter annotations are exclusive choices - "</span> +</span><br><span class="line"><span class="hljs-string">"do not specify more than one such annotation on the same parameter: "</span> + handlerMethod);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (annotationsFound == <span class="hljs-number">0</span>) &#123;</span><br><span class="line">Object argValue = resolveCommonArgument(methodParam, webRequest);</span><br><span class="line"><span class="hljs-keyword">if</span> (argValue != WebArgumentResolver.UNRESOLVED) &#123;</span><br><span class="line">args[i] = argValue;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (defaultValue != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveDefaultValue(defaultValue);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">Class&lt;?&gt; paramType = methodParam.getParameterType();</span><br><span class="line"><span class="hljs-keyword">if</span> (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line"><span class="hljs-keyword">if</span> (!paramType.isAssignableFrom(implicitModel.getClass())) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Argument ["</span> + paramType.getSimpleName() + <span class="hljs-string">"] is of type "</span> +</span><br><span class="line"><span class="hljs-string">"Model or Map but is not assignable from the actual model. You may need to switch "</span> +</span><br><span class="line"><span class="hljs-string">"newer MVC infrastructure classes to use this argument."</span>);</span><br><span class="line">&#125;</span><br><span class="line">args[i] = implicitModel;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (SessionStatus.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line">args[i] = <span class="hljs-keyword">this</span>.sessionStatus;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (HttpEntity.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line">args[i] = resolveHttpEntityRequest(methodParam, webRequest);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Errors.class.isAssignableFrom(paramType)) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Errors/BindingResult argument declared "</span> +</span><br><span class="line"><span class="hljs-string">"without preceding model attribute. Check your handler method signature!"</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (BeanUtils.isSimpleProperty(paramType)) &#123;</span><br><span class="line">paramName = <span class="hljs-string">""</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">attrName = <span class="hljs-string">""</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (paramName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (headerName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (requestBodyFound) &#123;</span><br><span class="line">args[i] = resolveRequestBody(methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cookieName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pathVarName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);</span><br><span class="line">&#125;</span><br><span class="line">            <span class="hljs-comment">//确定自定义类型参数的值，还要讲七扭去中的每一个参数赋值给这个对象</span></span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (attrName != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">WebDataBinder binder =</span><br><span class="line">resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);</span><br><span class="line"><span class="hljs-keyword">boolean</span> assignBindingResult = (args.length &gt; i + <span class="hljs-number">1</span> &amp;&amp; Errors.class.isAssignableFrom(paramTypes[i + <span class="hljs-number">1</span>]));</span><br><span class="line"><span class="hljs-keyword">if</span> (binder.getTarget() != <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">doBind(binder, webRequest, validate, validationHints, !assignBindingResult);</span><br><span class="line">&#125;</span><br><span class="line">args[i] = binder.getTarget();</span><br><span class="line"><span class="hljs-keyword">if</span> (assignBindingResult) &#123;</span><br><span class="line">args[i + <span class="hljs-number">1</span>] = binder.getBindingResult();</span><br><span class="line">i++;</span><br><span class="line">&#125;</span><br><span class="line">implicitModel.putAll(binder.getBindingResult().getModel());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">return</span> args;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>没有标注解   </p><ol><li><p>先看是否为普通参数（是否为原生API）</p><p>再看是否Model或者Map，如果是传入隐含模型</p></li><li><p>自定义类型的参数没有注解没有ModelAttribute注解</p><ol><li>先看原生API</li><li>在看是否是Map或ModelMap</li><li>在看看是不是其他类型，比如SessionStatus、HttpEntity、Errors</li><li>是否为简单属性，是否Integer、String基本类型<ol><li>如果paramName=“”</li></ol></li><li>AttrName=””</li></ol></li></ol><p>如果是自定义类型对象，最终会产生两个效果</p><ol><li>如果这个参数标注了ModelAttribute注解就给attrName赋值，为这个注解Value值</li><li>如果没有，就为“”</li></ol></blockquote></li><li><p>确定自定义类型的值（POJO)</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doBind</span><span class="hljs-params">(WebDataBinder binder, NativeWebRequest webRequest, <span class="hljs-keyword">boolean</span> validate,</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">Object[] validationHints, <span class="hljs-keyword">boolean</span> failOnErrors)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">doBind(binder, webRequest);</span><br><span class="line"><span class="hljs-keyword">if</span> (validate) &#123;</span><br><span class="line">binder.validate(validationHints);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">if</span> (failOnErrors &amp;&amp; binder.getBindingResult().hasErrors()) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BindException(binder.getBindingResult());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-function"><span class="hljs-keyword">private</span> WebDataBinder <span class="hljs-title">resolveModelAttribute</span><span class="hljs-params">(String attrName, MethodParameter methodParam,</span></span></span><br><span class="line"><span class="hljs-function"><span class="hljs-params">ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">// Bind request parameter onto object...</span></span><br><span class="line">String name = attrName;</span><br><span class="line"><span class="hljs-keyword">if</span> (<span class="hljs-string">""</span>.equals(name)) &#123;</span><br><span class="line">name = Conventions.getVariableNameForParameter(methodParam);</span><br><span class="line">&#125;</span><br><span class="line">Class&lt;?&gt; paramType = methodParam.getParameterType();</span><br><span class="line">    <span class="hljs-comment">//如果隐含模型有这个key（标了ModelAttribute注解就是注解标定的值，没标就是参数类型首字母小写）指定的值</span></span><br><span class="line">Object bindObject;</span><br><span class="line"><span class="hljs-keyword">if</span> (implicitModel.containsKey(name)) &#123;</span><br><span class="line">bindObject = implicitModel.get(name);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.methodResolver.isSessionAttribute(name, paramType)) &#123;</span><br><span class="line">bindObject = <span class="hljs-keyword">this</span>.sessionAttributeStore.retrieveAttribute(webRequest, name);</span><br><span class="line"><span class="hljs-keyword">if</span> (bindObject == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line">raiseSessionRequiredException(<span class="hljs-string">"Session attribute '"</span> + name + <span class="hljs-string">"' required - not found in session"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> &#123;</span><br><span class="line">bindObject = BeanUtils.instantiateClass(paramType);</span><br><span class="line">&#125;</span><br><span class="line">WebDataBinder binder = createBinder(webRequest, bindObject, name);</span><br><span class="line">initBinder(handler, name, binder, webRequest);</span><br><span class="line"><span class="hljs-keyword">return</span> binder;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li><p>如果隐含模型有这个key（标了ModelAttribute注解就是注解标定的值，没标就是参数类型首字母小写）指定的值</p><p>如果有将这个值赋值给bindObject</p></li><li><p>如果是SessionAttributes标注的属性，就从Session中拿</p></li><li><p>如果都不是，就用反射创建一个</p></li></ol></li></ol><hr><ol><li><p>确定方法每个参数的值</p><ol><li><p>标注解：保存注解信息；最终得到这个注解应该对应解析的值</p></li><li><p>没标注解</p><ol><li><p>先看是否是否为原生API</p></li><li><p>是否为Model或Map</p></li><li><p>看是否为简单类型</p></li><li><p>给attrName赋值，参数标了ModelAttribute就是指定的，没标就位空串</p><p>确定自定义类型参数</p><ol><li><p>attrName使用参数类型首字母小写；或者使用之前@ModelAttribute的值</p></li><li><p>先看隐含模型中是否有这个attrName对应的值；如果有就从隐含模型中获取并赋值</p></li><li><p>看是否SessionAttrinute标注的属性，如果是从Session中拿</p><p>拿不到抛异常</p></li><li><p>不是SessionAttributes标注的值，利用反射创建一个</p></li></ol></li><li><p>拿到之前创建好的对象，使用数据绑定器（WebDataBinder）将请求的么个数据绑定到这个对象中</p></li></ol></li></ol></li></ol><hr><h2 id="SpringMVC九大组件"><a href="#SpringMVC九大组件" class="headerlink" title="SpringMVC九大组件"></a>SpringMVC九大组件</h2><blockquote><p>在DispatchServlet中有几个引用类型属性。关键位置都是由这些组件完成的</p><p><strong>共同点：</strong> 九大组件都是接口：接口就是规范，提供了强大的扩展性</p></blockquote><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-comment">/** MultipartResolver used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//文件上传解析器</span></span><br><span class="line"><span class="hljs-keyword">private</span> MultipartResolver multipartResolver;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** LocaleResolver used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//区域信息析器与国际化有关</span></span><br><span class="line"><span class="hljs-keyword">private</span> LocaleResolver localeResolver;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** ThemeResolver used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//主题解析器：主题效果更换</span></span><br><span class="line"><span class="hljs-keyword">private</span> ThemeResolver themeResolver;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** List of HandlerMappings used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//Handler映射信息：HandlerMapping</span></span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;HandlerMapping&gt; handlerMappings;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** List of HandlerAdapters used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//Handler适配器</span></span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;HandlerAdapter&gt; handlerAdapters;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** List of HandlerExceptionResolvers used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//SpringMVC强大的异常解析功能</span></span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;HandlerExceptionResolver&gt; handlerExceptionResolvers;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** RequestToViewNameTranslator used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//</span></span><br><span class="line"><span class="hljs-keyword">private</span> RequestToViewNameTranslator viewNameTranslator;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** FlashMapManager used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//SpringMVC中运行重定向携带数据的功能</span></span><br><span class="line"><span class="hljs-keyword">private</span> FlashMapManager flashMapManager;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/** List of ViewResolvers used by this servlet */</span></span><br><span class="line"><span class="hljs-comment">//视图解析器</span></span><br><span class="line"><span class="hljs-keyword">private</span> List&lt;ViewResolver&gt; viewResolvers;</span><br></pre></td></tr></table></figure><p><strong>DispatchServlet中onRefresh方法</strong></p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRefresh</span><span class="hljs-params">(ApplicationContext context)</span> </span>&#123;</span><br><span class="line">initStrategies(context);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initStrategies</span><span class="hljs-params">(ApplicationContext context)</span> </span>&#123;</span><br><span class="line">initMultipartResolver(context);</span><br><span class="line">initLocaleResolver(context);</span><br><span class="line">initThemeResolver(context);</span><br><span class="line">initHandlerMappings(context);</span><br><span class="line">initHandlerAdapters(context);</span><br><span class="line">initHandlerExceptionResolvers(context);</span><br><span class="line">initRequestToViewNameTranslator(context);</span><br><span class="line">initViewResolvers(context);</span><br><span class="line">initFlashMapManager(context);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;h2 id=&quot;Spring-MVC中DispatchServlet运行流程&quot;&gt;&lt;a href=&quot;#Spring-MVC中DispatchServlet运行流程&quot; class=&quot;headerlink&quot; title=&quot;Spring MVC中DispatchServlet运行流程&quot;&gt;&lt;/a&gt;Spring MVC中DispatchServlet运行流程&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://gitee.com//lyhcc/Images/raw/master/img/20200219190425.png&quot; alt&gt;&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
    
    </summary>
    
    
      <category term="Spring MVC" scheme="https://lyhcc.github.io/categories/Spring-MVC/"/>
    
    
      <category term="SpringMVC源码分析" scheme="https://lyhcc.github.io/tags/SpringMVC%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/"/>
    
  </entry>
  
  <entry>
    <title>SpringMVC 请求数据传入</title>
    <link href="https://lyhcc.github.io/post/4c7891d3.html"/>
    <id>https://lyhcc.github.io/post/4c7891d3.html</id>
    <published>2020-02-19T04:29:43.643Z</published>
    <updated>2020-02-19T06:15:00.989Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><h2 id="请求处理方法签名"><a href="#请求处理方法签名" class="headerlink" title="请求处理方法签名"></a>请求处理方法签名</h2><ul><li>Spring MVC 对控制器处理方法签名的限制是很宽松的，几乎可以按喜欢的任何方式对方法进行签名。 </li><li>必要时可以对方法及方法入参标注相应的注解（ @PathVariable 、@RequestParam、@RequestHeader 等）、</li><li>Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中，并根据方法的返回值类型做出相应的后续处理。</li></ul><a id="more"></a><h2 id="RequestParam注解"><a href="#RequestParam注解" class="headerlink" title="@RequestParam注解"></a>@RequestParam注解</h2><ul><li>在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法</li><li>value：参数名</li><li>required：是否必须。默认为 true, 表示请求参数中必须包含对应的参数，若不存在，将抛出异常</li><li>defaultValue: 默认值，当没有传递参数时使用该值</li></ul><h2 id="实验代码"><a href="#实验代码" class="headerlink" title="实验代码"></a>实验代码</h2><ol><li>增加控制方法<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"testRequestParam"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">testRequestParam</span><span class="hljs-params">(@RequestParam(value=<span class="hljs-string">"username"</span>)</span>String username, @<span class="hljs-title">RequestParam</span><span class="hljs-params">(value=<span class="hljs-string">"age"</span>)</span>Integer age) </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"testRequestParam---username:"</span>+username+<span class="hljs-string">",age:"</span>+age);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"success"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>页面链接代码<figure class="highlight hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href="testRequestParam?username=atguigu&amp;age=10"&gt;testRequestParam&lt;/a&gt;</span><br></pre></td></tr></table></figure></li></ol><h2 id="RequestHeader注解"><a href="#RequestHeader注解" class="headerlink" title="@RequestHeader注解"></a>@RequestHeader注解</h2><ul><li>使用 @RequestHeader 绑定请求报头的属性值</li><li>请求头包含了若干个属性，服务器可据此获知客户端的信息，通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中 </li><li>也有三个参数value、defaultValue、required</li></ul><h2 id="实验代码-1"><a href="#实验代码-1" class="headerlink" title="实验代码"></a>实验代码</h2><ol><li>控制器代码<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"testRequestHeader"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">testRequestHeader</span><span class="hljs-params">(@RequestHeader(value=<span class="hljs-string">"User-Agent"</span>)</span>String aa) </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"testRequestHeader---UserAgent"</span> + aa);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"success"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>页面链接<figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"testRequestHeader"</span>&gt;</span>testRequestHeader<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h2 id="CookieValue注解"><a href="#CookieValue注解" class="headerlink" title="@CookieValue注解"></a>@CookieValue注解</h2><ul><li>使用 @CookieValue 绑定请求中的 Cookie 值</li><li>@CookieValue 可让处理方法入参绑定某个 Cookie 值</li></ul><ol><li>控制器代理<figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"testCookieMethod"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">private</span> String <span class="hljs-title">testCookieMethod</span><span class="hljs-params">(@CookieValue(value=<span class="hljs-string">"JSESSIONID"</span>)</span>String sessionID) </span>&#123;</span><br><span class="line">System.out.println(<span class="hljs-string">"Cookie:JSESSIONID="</span>+sessionID);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"success"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>页面链接<figure class="highlight html hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"testCookieMethod"</span>&gt;</span>testCookieMethod<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h2 id="使用POJO作为参数"><a href="#使用POJO作为参数" class="headerlink" title="使用POJO作为参数"></a>使用POJO作为参数</h2><ul><li>使用 POJO 对象绑定请求参数值</li><li>Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配，自动为该对象填充属性值。支持级联属性。如：dept.deptId、dept.address.tel 等</li></ul><ol><li><p>控制器方法</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"testPOJO"</span>)</span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">testPOJO</span><span class="hljs-params">(Person person)</span> </span>&#123;</span><br><span class="line">System.out.println(person);</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-string">"success"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>表单页面代码</p><figure class="highlight html hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">" testPOJO"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span></span><br><span class="line">username: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">password: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"pwd"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">email: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line">gender: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"gender"</span>/&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit"</span>/&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>增加实体类</p><figure class="highlight java hljs"><table><tr><td class="gutter"><pre><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="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>&#123;</span><br><span class="line"><span class="hljs-keyword">private</span> String name;</span><br><span class="line"><span class="hljs-keyword">private</span> String pwd;</span><br><span class="line"><span class="hljs-keyword">private</span> String gender;</span><br><span class="line"><span class="hljs-keyword">private</span> String email;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">//getter/setter</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><hr><p><strong>使用POJO出现乱码如何解决？</strong>  </p><ul><li>如果中文有乱码，需要配置字符编码过滤器，且配置其他过滤器之前，<br>如（HiddenHttpMethodFilter），否则不起作用。（思考method=”get”请求的乱码问题怎么解决的）<figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><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><br><span class="line">   GET请求： 改server.xml，在8080端口处URIEncoding=”UTF-8”</span><br><span class="line">   POST请求： 在第一次请求参数之前设置</span><br><span class="line">               Request.setCharacterEncoding(“UTF-8”)</span><br><span class="line">               自定义Filter, SpringMVC</span><br><span class="line">封装有org.springframework.web.filter.CharacterEncodingFilter</span><br><span class="line">响应乱码：</span><br><span class="line">   Response.setContentType(“text/html;charset=utf-8”)</span><br></pre></td></tr></table></figure></li></ul><p><strong>过滤器配置</strong>  </p><figure class="highlight xml hljs"><table><tr><td class="gutter"><pre><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="hljs-tag">&lt;<span class="hljs-name">filter</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>encodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-class</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>encoding<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>UTF-8<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>forceEncoding<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">filter</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;<span class="hljs-name">filter-mapping</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>encodingFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="hljs-tag">&lt;<span class="hljs-name">url-pattern</span>&gt;</span>/*<span class="hljs-tag">&lt;/<span class="hljs-name">url-pattern</span>&gt;</span></span><br><span class="line"><span class="hljs-tag">&lt;/<span class="hljs-name">filter-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure><hr><h2 id="使用Servlet原生API作为参数"><a href="#使用Servlet原生API作为参数" class="headerlink" title="使用Servlet原生API作为参数"></a>使用Servlet原生API作为参数</h2><ul><li><p>MVC 的 Handler 方法可以接受哪些 ServletAPI 类型的参数<br>  1) HttpServletRequest<br>  2) HttpServletResponse<br>  3) HttpSession<br>  4) java.security.Principal<br>  5) Locale<br>  6) InputStream<br>  7) OutputStream<br>  8) Reader<br>  9) Writer</p></li><li><p>源码参考：AnnotationMethodHandlerAdapter L866<br>  <img src="https://gitee.com//lyhcc/Images/raw/master/img/20200219135356.png" alt></p>  <figure class="highlight java hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">      <span class="hljs-meta">@Override</span></span><br><span class="line"><span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">resolveStandardArgument</span><span class="hljs-params">(Class&lt;?&gt; parameterType, NativeWebRequest webRequest)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;</span><br><span class="line">HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);</span><br><span class="line">HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">if</span> (ServletRequest.class.isAssignableFrom(parameterType) ||</span><br><span class="line">MultipartRequest.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line">Object nativeRequest = webRequest.getNativeRequest(parameterType);</span><br><span class="line"><span class="hljs-keyword">if</span> (nativeRequest == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(</span><br><span class="line"><span class="hljs-string">"Current request is not of type ["</span> + parameterType.getName() + <span class="hljs-string">"]: "</span> + request);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> nativeRequest;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ServletResponse.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.responseArgumentUsed = <span class="hljs-keyword">true</span>;</span><br><span class="line">Object nativeResponse = webRequest.getNativeResponse(parameterType);</span><br><span class="line"><span class="hljs-keyword">if</span> (nativeResponse == <span class="hljs-keyword">null</span>) &#123;</span><br><span class="line"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(</span><br><span class="line"><span class="hljs-string">"Current response is not of type ["</span> + parameterType.getName() + <span class="hljs-string">"]: "</span> + response);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> nativeResponse;</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (HttpSession.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> request.getSession();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Principal.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> request.getUserPrincipal();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Locale.class.equals(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> RequestContextUtils.getLocale(request);</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (InputStream.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> request.getInputStream();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Reader.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">return</span> request.getReader();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (OutputStream.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.responseArgumentUsed = <span class="hljs-keyword">true</span>;</span><br><span class="line"><span class="hljs-keyword">return</span> response.getOutputStream();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Writer.class.isAssignableFrom(parameterType)) &#123;</span><br><span class="line"><span class="hljs-keyword">this</span>.responseArgumentUsed = <span class="hljs-keyword">true</span>;</span><br><span class="line"><span class="hljs-keyword">return</span> response.getWriter();</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.resolveStandardArgument(parameterType, webRequest);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h2 id="实验代码-2"><a href="#实验代码-2" class="headerlink" title="实验代码"></a>实验代码</h2>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;h2 id=&quot;请求处理方法签名&quot;&gt;&lt;a href=&quot;#请求处理方法签名&quot; class=&quot;headerlink&quot; title=&quot;请求处理方法签名&quot;&gt;&lt;/a&gt;请求处理方法签名&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Spring MVC 对控制器处理方法签名的限制是很宽松的，几乎可以按喜欢的任何方式对方法进行签名。 &lt;/li&gt;
&lt;li&gt;必要时可以对方法及方法入参标注相应的注解（ @PathVariable 、@RequestParam、@RequestHeader 等）、&lt;/li&gt;
&lt;li&gt;Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中，并根据方法的返回值类型做出相应的后续处理。&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="Spring MVC" scheme="https://lyhcc.github.io/categories/Spring-MVC/"/>
    
    
      <category term="SpringMVC 请求数据传入" scheme="https://lyhcc.github.io/tags/SpringMVC-%E8%AF%B7%E6%B1%82%E6%95%B0%E6%8D%AE%E4%BC%A0%E5%85%A5/"/>
    
  </entry>
  
</feed>
