整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Spring Boot實戰之 輕松掌握3種靜態資源處

          Spring Boot實戰之 輕松掌握3種靜態資源處理方式

          作者:liuxiaopeng

          鏈接:https://www.cnblogs.com/paddix/p/8365558.html

          前兩章我們分享了Spring boot對Restful 的支持,不過Restful的接口通常僅僅返回數據。而做web開發的時候,我們往往會有很多靜態資源,如html、圖片、css等。那如何向前端返回靜態資源呢?以前做過web開發的同學應該知道,我們以前創建的web工程下面會有一個webapp的目錄,我們只要把靜態資源放在該目錄下就可以直接訪問。但是,基于Spring boot的工程并沒有這個目錄,那我們應該怎么處理?



          一、最笨的方式

            我們首先來分享一種最笨的辦法,就是將靜態資源通過流直接返回給前端,我們在maven工程的resources的根目錄下建立一個html的目錄,然后我們把html文件放在該目錄下,并且規定任何訪問路徑以/static/開頭的即訪問該目錄下的靜態資源,其實現如下:

          
          @Controller
          public class StaticResourceController {
           
              @RequestMapping("/static/**")
              public void getHtml(HttpServletRequest request, HttpServletResponse response) {
                  String uri=request.getRequestURI();
                  String[] arr=uri.split("static/");
                  String resourceName= "index.html";
                  if (arr.length > 1) {
                      resourceName=arr[1];
                  }
                  String url=StaticResourceController.class.getResource("/").getPath() + "html/" + resourceName;
                  try {
                      FileReader reader= new FileReader(new File(url));
                      BufferedReader br= new BufferedReader(reader);
                      StringBuilder sb= new StringBuilder();
                      String line=br.readLine();
                      while (line != null) {
                          sb.append(line);
                          line=br.readLine();
                      }
                      response.getOutputStream().write(sb.toString().getBytes());
                      response.flushBuffer();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }

            其實現過程很簡單,就是先從路徑中分離出來資源uri,然后從static目錄下讀取文件,并輸出到前端。因為只做簡單演示,所以這里只處理了文本類型的文件,圖片文件可以做類似的處理。當然,我們在實際中肯定不會這么做,Spring boot也肯定有更好的解決辦法。不過這個辦法雖然有點笨,但確是最本質的東西,無論框架如何方便的幫我們處理了這類問題,但是拋開框架,我們依然要能夠熟練的寫出一個web項目,只有知道其實現原理,你才會在遇到問題時能得心應手。現在我們再來看看Spring boot對靜態資源的支持。

          二、Spring boot默認靜態資源訪問方式

            Spring boot默認對/**的訪問可以直接訪問四個目錄下的文件:

              classpath:/public/

              classpath:/resources/

              classpath:/static/

              classpath:/META-INFO/resouces/

            我們現在就在資源文件resources目錄下建立如下四個目錄:

            注意藍色條下的資源文件夾resources與類路徑下的文件夾classpath:/resources是不同的,藍色條下的resources代表的是該目錄下的文件為資源文件,在打包的時候會將該目錄下的文件全部打包的類路徑下,這個名稱是可以改的,在pom.xml指定資源目錄即可:

          <resources>
               <resource>
                   <directory>src/main/resources</directory>
               </resource>
          </resources>

            而類路徑下的resources是spring boot默認的靜態資源文件夾之一,和public、static以及MEAT-INFO/resources的功能相同。現在我們重啟Spring boot就可以通過

              http://localhost:8080/1.html

              http://localhost:8080/2.html

              http://localhost:8080/3.html

              http://localhost:8080/4.html

            四個URL訪問到四個目錄下的靜態資源了。

          三、自定義靜態資源目錄

            通過第二節內容我們已經知道了Spring boot默認可以訪問的靜態資源的目錄,但是大家肯定會想,這個目錄是固定的嗎?我們可不可以自己定義靜態資源目錄?答案是肯定的,我們現在就來自定義一個靜態資源目錄,我們定義一個images的目錄來存放圖片,所有/image/**的路徑都會訪問images目錄下的資源:

          @Configuration
          public class ImageMvcConfig extends WebMvcConfigurerAdapter {
           
              @Override
              public void addResourceHandlers(ResourceHandlerRegistry registry) {
                  registry.addResourceHandler("/image/**")
                          .addResourceLocations("classpath:/images/");
              }
          }

            這段代碼應該比較簡單,@Configuration標識一個配置類,這個在前面的文章中提到過多次。WebMvcConfigurerAdapter是Spring提供的一個配置mvc的適配器,里面有很多配置的方法,addResourceHandlers就是專門處理靜態資源的方法,其他方法后續我們還會講到。現在我們在驗證上面的配置是否有效。我在images目錄下放了一張spring.jpg的圖片,現在我們通過http://localhost:8080/image/spring.jpg來訪問圖片:



            其實除了上面的辦法還有一種更簡單的辦法,就是直接在application.yml中配置即可:

          spring:
            mvc:
              static-path-pattern: /image/**
            resources:
              static-locations: classpath:/images/

            static-path-pattern:訪問模式,默認為/**,多個可以逗號分隔

            static-locations:資源目錄,多個目錄逗號分隔,默認資源目錄為classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

            注意,這個配置會覆蓋Spring boot默認的靜態資源目錄,例如如果按示例中配置,則無法再訪問static、public、resources等目錄下的資源了。

          四、總結

            本文主要給大家分享了Spring boot 對靜態資源的處理方式,Spring boot 默認可以訪問classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/四個目錄下的靜態資源,我們也可以根據自己的需要進行個性化配置。最后,需要說明一點的是,如果這四個目錄中存在相同名稱的資源,那會優先返回哪個目錄下的資源呢?大家通過static-locations的默認值順序應該能猜到,默認情況下,Spring boot會優先返回/META-INF/resources下的資源。當然,因為我們可以自定義static-locations的值,所以這個優先順序也是可以調整的。

          . 前言

          在之前的4篇的內容里,我們較為詳細的介紹了路由以及控制器還有視圖之間的關系。也就是說,系統如何從用戶的HTTP請求解析到控制器里,然后在控制器里處理數據,并返回給視圖,在視圖中顯示出來。這一篇我將為大家介紹基礎的最后一部分,布局頁和靜態資源引入。



          1. 布局頁

          在控制器和視圖那一篇,我們了解到_ViewStart 里設置了一個Layout屬性的值,這個值正是用來設置布局頁的。所謂的布局頁,就是視圖的公用代碼。在實際開發中,布局頁通常存放我們為整個系統定義的頁面框架,視圖里寫每個視圖的頁面。

          回顧一下,默認的_ViewStart里的內容是:

          @{
              Layout="_Layout";
          }
          

          默認的布局頁指定的是名為_Layout的布局頁,在本系列第三篇中,我們得知這個視圖應當在Shared文件夾下,那我們進去看一下這個視圖有什么內容:

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="utf-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>@ViewData["Title"] - MvcWeb</title>
              <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
              <link rel="stylesheet" href="~/css/site.css" />
          </head>
          <body>
              <header>
                  <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
                      <div class="container">
                          <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcWeb</a>
                          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                                  aria-expanded="false" aria-label="Toggle navigation">
                              <span class="navbar-toggler-icon"></span>
                          </button>
                          <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                              <ul class="navbar-nav flex-grow-1">
                                  <li class="nav-item">
                                      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                                  </li>
                                  <li class="nav-item">
                                      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                                  </li>
                              </ul>
                          </div>
                      </div>
                  </nav>
              </header>
              <div class="container">
                  <main role="main" class="pb-3">
                      @RenderBody()
                  </main>
              </div>
          
              <footer class="border-top footer text-muted">
                  <div class="container">
                      ? 2020 - MvcWeb - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                  </div>
              </footer>
              <script src="~/lib/jquery/dist/jquery.min.js"></script>
              <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
              <script src="~/js/site.js" asp-append-version="true"></script>
              @RenderSection("Scripts", required: false)
          </body>
          </html>

          這是默認的布局頁內容,看著挺多的,但是除了一些html代碼,里面還有一些關鍵的地方需要注意。



          1.1 RenderSection

          RenderSection 分部渲染,在頁面中創建一個標記,表示這個頁面塊將在子視圖(或者是路由的實際渲染視圖)中添加內容。

          來,我們看一下微軟官方給的注釋:

          In layout pages, renders the content of the section named name.

          意思就是在布局頁中,渲染名稱為name的分部內容。

          新創建一個分布頁,名稱為_Layout1:

          <html>
              <head>
                  <title>Render 測試</title>
              </head>
              <body>
                  @RenderSection("SectionDemo")
              </body>
          </html>

          這個布局頁里什么都沒有,只有一個RenderSection。現在我們新建一個控制器:

          using Microsoft.AspNetCore.Mvc;
          
          namespace MvcWeb.Controllers
          {
              public class RenderTestController : Controller
              {
                  public IActionResult Index()
                  {
                      return View();
                  }
              }
          }

          創建對應的視圖:

          Views / RenderTest/Index.cshtml

          先設置布局頁為_Layout1:

          @{
              Layout="_Layout1";
          }

          先試試啟動應用,訪問:

          http://localhost:5006/RenderTest/Index

          正常情況下,你應該能看到這個頁面:

          仔細看一下信息,意思是在 RenderTest/Index.cshtml 視圖中沒有找到 SectionDemo 的分部內容。

          那么,如何在視圖中設置分部內容呢?

          @{
              Layout="_Layout1";
          }
          @section SectionDemo{
              <h1>你好</h1>
          
          }

          使用 @section <Section 名稱> 后面跟一對大括號,在大括號中間的內容就是這個section(分部)的內容。

          重啟應用,然后刷新頁面,你能看到這樣的頁面:

          如果不做特殊要求的話,定義在布局頁中的分部塊,視圖必須實現。當然,RenderSection還有一個參數,可以用來設置分部不是必須的:

          public HtmlString RenderSection(string name, bool required);

          1.2 RenderBody

          先看下微軟給的官方注釋:

          In a Razor layout page, renders the portion of a content page that is not within a named section.

          簡單講,如果在布局頁中設置了@RenderBody,那么在使用了這個布局頁的視圖里所有沒被分部塊包裹的代碼都會渲染到布局頁中聲明了@RenderBody的地方。

          修改_Layout1.cshtml:

          <html>
              <head>
                  <title>Render 測試</title>
              </head>
              <body>
                  <h1>RenderBody 測試 -之前</h1>
                  @RenderBody()
                  <h1>RenderBody 測試 -之后</h1>
              </body>
          </html>

          修改RenderTest/Index.cshtml:

          @{
              Layout="_Layout1";
          }
          
          RenderBody測試
          <h1>我是視圖的內容!</h1>

          重啟應用,刷新剛剛訪問的頁面:

          可以看出,RenderBody渲染的位置。

          2. 靜態資源引入

          通常情況下,靜態資源的引入與HTML引用js和css等資源是一致的,但是對于我們在編寫系統時自己創建的腳本和樣式表,asp.net core提供了不同的處理方式。那就是服務器端壓縮功能。

          asp.net core 3.0 的mvc 默認項目是不啟動這個功能的,需要我們額外的開啟支持。



          2.1 開啟支持

          先引入 BuildBundleMinifier

          cd MvcWeb # 切換目錄到MvcWeb項目下
          dotnet add package BuildBundleMinifier

          創建 bundleconfig.json

          [
              {
                  "outputFileName": "wwwroot/css/site.min.css",
                  "inputFiles": [
                      "wwwroot/css/site.css"
                  ]
              },
                {
                  "outputFileName": "wwwroot/js/site.min.js",
                  "inputFiles": [
                    "wwwroot/js/site.js"
                  ],
                  "minify": {
                    "enabled": true,
                    "renameLocals": true
                  },
                  "sourceMap": false
                }
          ]

          每個節點允許設置項:

          • outputFileName 生成的捆綁壓縮文件,通常路徑攜帶wwwroot
          • inputFiles 數組,包含要壓縮到此次輸出文件的文件路徑,會按照添加的順序依次加入
          • minify 輸出類型的縮小選項,可選。 默認是 enabled: true
          • sourceMap 表示是否為捆綁的文件生成源映射的標記
          • sourceMapRootPath 源映射文件的路徑

          2.2 使用

          正常情況下在布局頁中,把壓縮后的文件路徑引入即可。不過在開發中,通常按照以下方式引用:

          <environment exclude="Development">
              <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
          </environment>
          <environment include="Development">
              <link rel="stylesheet" href="~/css/site.css" />
          </environment>

          注: asp-append-version 表示在引用路徑追加一個版本號,這是針對html靜態資源緩存的問題的一個解決方案,這一步是由程序決定的。

          environment表示環境,現在大家知道這個寫法就行,在接下來的篇幅會講。

          3. 靜態資源目錄

          我們知道到目前為止,我們的靜態資源都是在wwwroot目錄下。那么我們是否可以修改或者添加別的目錄作為靜態資源目錄呢?

          在Startup.cs文件內的Configure方法下有這樣一行代碼:

          app.UseStaticFiles();

          這行代碼的意思就是啟用靜態文件,程序自動從 wwwroot尋找資源。那么,我們就可以從這個方法入手,設置我們自己的靜態資源:

          public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options);

          我們找到了這個方法的另一個重載版本,里面有一個參數類:

          public class StaticFileOptions : SharedOptionsBase
          {
              public StaticFileOptions();
              public StaticFileOptions(SharedOptions sharedOptions);
              public IContentTypeProvider ContentTypeProvider { get; set; }
              public string DefaultContentType { get; set; }
              public HttpsCompressionMode HttpsCompression { get; set; }
              public Action<StaticFileResponseContext> OnPrepareResponse { get; set; }
              public bool ServeUnknownFileTypes { get; set; }
          }

          并沒有發現我們想要的,先別慌,它還有個父類。我們再去它的父類里看看:

          public abstract class SharedOptionsBase
          {
              protected SharedOptionsBase(SharedOptions sharedOptions);
              public IFileProvider FileProvider { get; set; }
              public PathString RequestPath { get; set; }
              protected SharedOptions SharedOptions { get; }
          }

          這下就比較明了了,需要我們提供一個文件提供器,那么我們來找一個合適的IFileProvider實現類吧:

          public class PhysicalFileProvider : IFileProvider, IDisposable

          這個類可以滿足我們的要求,它位于命名空間:

          namespace Microsoft.Extensions.FileProviders

          那么,添加一組我們自己的配置吧:

          using Microsoft.Extensions.FileProviders;
          
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              // 省略其他代碼,僅添加以下代碼
              app.UseStaticFiles(new StaticFileOptions
              {
                  FileProvider=new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"OtherStatic")),
              });
          }

          在項目的根目錄創建名為OtherStatic的文件夾,然后在里面創建個文件夾,例如: files,并在這個文件夾里隨便添加一個文件。

          然后啟動應用訪問:

          http://localhost:5006/files/<你添加的文件(包括后綴名)>

          然后能在瀏覽器中看到這個文件被正確響應。

          當然,這里存在一個問題,如果在 OtherStatic中的文件在wwwroot也有相同目錄結構的文件存在,這樣訪問就會出現問題。這時候,可以為我們新加的這個配置設置一個請求前綴:

          app.UseStaticFiles(new StaticFileOptions
          {
              FileProvider=new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"OtherStatic")),
              RequestPath="/other"
          });

          重啟程序,然后訪問:

          http://localhost:5006/other/files/<你添加的文件(包括后綴名)>

          然后就能看到剛才響應的文件,重新訪問之前的路徑,發現瀏覽器提示404。



          4. 總結

          在這一篇,我們講解了布局頁的內容,靜態資源的壓縮綁定以及添加一個新的靜態資源目錄。通過這幾篇內容,讓我們對asp.net core mvc有了一個基本的認知。下一篇,我們將重新創建一個項目,并結合之前的內容,以實戰為背景,帶領大家完成一個功能完備的web系統。

          求關注,求點贊,求轉發~~有啥可以評論喲

          jango并不象其他WEB語言,可以在前端頁面指定圖片,CSS等靜態資源的路徑就能直接訪問。

          要使用靜態資源,還需要一些必要的設置。


          1,在項目app目錄中新建一個static目錄

          static目錄再創建一個css目錄,放一個style.css文件

          在static目錄放一個 1.png 圖片


          2,配置項目的settings.py文件


          STATIC_URL='/static/'

          STATICFILES_DIRS=(

          os.path.join(BASE_DIR, 'static').replace('\', '/'),

          )


          3,配置urls.py文件

          加入如下url:

          url(r'^static/(?P<path>.*)', serve, {'document_root': '/myweb/web/static'}),



          配置完后就可以在前端頁面使用靜態資源了,

          比如引用css文件:<link rel="stylesheet" href="./static/css/style.css">

          比如引用圖片:<img src="static/1.png">


          主站蜘蛛池模板: 三上悠亚一区二区观看| 亚洲欧美国产国产综合一区| 国产伦一区二区三区高清 | 国产av福利一区二区三巨 | 国产AV天堂无码一区二区三区| 2014AV天堂无码一区| 国产视频一区在线播放| 2020天堂中文字幕一区在线观 | 在线观看国产一区二三区| 男人的天堂亚洲一区二区三区| 日韩人妻一区二区三区蜜桃视频 | 日韩国产一区二区| 亚洲日韩一区精品射精| 久久精品国产一区二区三区不卡| 97精品国产一区二区三区| 精品国产一区二区三区在线观看| 日本一区高清视频| 国产一区二区好的精华液| 国产精品高清视亚洲一区二区| 久久久久一区二区三区| 精品一区二区三区免费 | 一区二区中文字幕| 国产精品熟女一区二区| 亚洲Aⅴ无码一区二区二三区软件| 免费无码一区二区三区蜜桃大| 国产精品久久久久久一区二区三区| 在线播放一区二区| 国产欧美一区二区精品仙草咪| 波多野结衣在线观看一区| 一区二区三区日本电影| 国产亚洲自拍一区| 高清一区二区三区免费视频| 亚洲av无码一区二区三区网站| 久久国产精品免费一区| 国产一区二区在线看| 久久se精品一区二区国产| 99久久精品国产一区二区成人| 人妻无码一区二区三区免费| 日本免费一区二区三区四区五六区 | 国产精品无码一区二区三区毛片| 精品人妻一区二区三区四区 |