1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        SpringBoot集成Milton(webdav)應(yīng)用實(shí)例(一)

        共 29510字,需瀏覽 60分鐘

         ·

        2023-05-07 18:16

        有最奇崛的峰巒 成全過(guò)你我張狂

        海上清輝與圓月 盛進(jìn)杯光

        有最孤傲的雪山 靜聽(tīng)過(guò)你我誦章

        世人驚羨的橋段 不過(guò)尋常

        有最奇崛的峰巒 成全過(guò)你我張狂

        海上清輝與圓月 盛進(jìn)杯光

        有最殘破的書(shū)簡(jiǎn) 記載過(guò)光陰漫長(zhǎng)

        無(wú)意拾過(guò)的片瓦 歷數(shù)寒涼

        有最孤傲的雪山 靜聽(tīng)過(guò)你我誦章

        世人驚羨的橋段 不過(guò)尋常


        01

        webdav簡(jiǎn)介


        WebDAV (Web-based Distributed Authoring and Versioning) 一種基于 HTTP 1.1協(xié)議的通信協(xié)議。它擴(kuò)展了HTTP 1.1,在GET、POST、HEAD等幾個(gè)HTTP標(biāo)準(zhǔn)方法以外添加了一些新的方法,使應(yīng)用程序可對(duì)Web Server直接讀寫(xiě),并支持寫(xiě)文件鎖定(Locking)及解鎖(Unlock),還可以支持文件的版本控制。


        簡(jiǎn)單來(lái)說(shuō),webdav是一種協(xié)議,可以通過(guò)這種協(xié)議,對(duì)儲(chǔ)存于云的文件直接進(jìn)行傳輸,和平時(shí)我們用的那個(gè)百度網(wǎng)盤(pán)類(lèi)似,可以在自己的電腦上,直接對(duì)云文件傳輸編輯。



        feed2aa5052b6de538b3957be2796471.webp



        02


        Milton


        Milton.io,是一個(gè)基于Java開(kāi)發(fā)的,支持webdav協(xié)議的開(kāi)源框架。詳情可見(jiàn)官網(wǎng)介紹:https://milton.io/


        此外,還支持CalDav和CardDav


        使用milton開(kāi)發(fā)webdav服務(wù),通??梢酝ㄟ^(guò)2種方式進(jìn)行,一種是注解的方式,這種方式簡(jiǎn)單明了。另外一種是基于milton原生的方式,即實(shí)現(xiàn)milton的原生類(lèi),實(shí)現(xiàn)一些接口方法,從而實(shí)現(xiàn)服務(wù),兩種方式各有各的好處,對(duì)于初學(xué)者來(lái)說(shuō),注解的方式比較友好一些。milton原生方式可能稍微復(fù)雜些,因?yàn)樾枰私鈓ilton每個(gè)資源類(lèi)的邏輯和用法


        2c6c16d81eadc7e33560e29596df776d.webp


        03


        Milton整合Spring


        這里采用注解的方式,將通過(guò)一個(gè)實(shí)際的案例,一步一步來(lái)搭建一個(gè)屬于自己的webdav服務(wù)。


        首先引入項(xiàng)目依賴(lài),milton目前高版本是到4了,由于對(duì)新版本的不是很熟悉,所以這里使用比較熟悉的版本2,項(xiàng)目后續(xù)會(huì)通過(guò)讀取數(shù)據(jù)庫(kù)的文件存儲(chǔ)目錄結(jié)構(gòu),所以引入數(shù)據(jù)庫(kù)支持,目前因?yàn)橛袀€(gè)文件管理系統(tǒng),目錄結(jié)構(gòu)存儲(chǔ)在數(shù)據(jù)庫(kù),文件在文件存儲(chǔ)服務(wù)器上的。



                      
                        
                          <?xml version="1.0" encoding="UTF-8"?>
                        
                      
                      
                        
                          <project xmlns="http://maven.apache.org/POM/4.0.0"
                        
                      
                      
                                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      
                      
                                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
                      
                      
                            <modelVersion>4.0.0</modelVersion>
                      
                      
                        
                          
        <groupId>com.lgli</groupId> <artifactId>webdav-server</artifactId> <version>1.0</version>
        <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target>
        <milton.version>2.8.0.3</milton.version> <springboot.version>2.5.11</springboot.version> <mybatis.plus>3.5.3.1</mybatis.plus> <mysql.connection>8.0.32</mysql.connection> </properties>

        <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>${springboot.version}</version> <optional>true</optional> </dependency>
        <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>${springboot.version}</version> </dependency>
        <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${springboot.version}</version> </dependency>
        <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis.plus}</version> </dependency>
        <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.connection}</version> </dependency>

        <dependency> <groupId>io.milton</groupId> <artifactId>milton-server-ce</artifactId> <version>${milton.version}</version> </dependency>

        <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
        </dependencies>
        <build> <!--保證配置文件和xml通過(guò)編譯--> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.yaml</include> <include>**/*.properties</include> <include>**/banner.txt</include> </includes> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> ????</build> </project>

        milton的大致工作原理是,對(duì)特定的webdav協(xié)議的http請(qǐng)求,有一個(gè)自己的處理方法,即io.milton.http.HttpManager#process方法,所以,首先需要定義一個(gè)攔截器類(lèi),把所需要milton處理的http請(qǐng)求,給予milton來(lái)處理。


        這里定義一個(gè)SpringMiltonFilter攔截器,繼承org.springframework.web.filter.GenericFilterBean類(lèi),并重寫(xiě)doFilter方法,


        6a12dd39de7210a544219ec98a871136.webp


        這里的io.milton.http.HttpManager#process就是milton處理webdav請(qǐng)求的方法,這個(gè)HttpManager是來(lái)自于一個(gè)io.milton.config.HttpManagerBuilder通過(guò) io.milton.config.HttpManagerBuilder #buildHttpManager方法所創(chuàng)建出來(lái)的,所以要獲取HttpManager,首先要獲取到HttpManagerBuilder


        HttpManagerBuilder的獲取,可以通過(guò)new一個(gè)實(shí)例,同時(shí)設(shè)定一些必要的參數(shù),比如這里所用的是注解的方式,那么 需要指定milton的Resource包掃描和一個(gè)ResourceFactory(這倆是必須的) ,還有一些需要或者不需要的權(quán)限認(rèn)證的設(shè)置,首先這里先不考慮權(quán)限,所以權(quán)限全部設(shè)置為false,


        0bcda8cb6f1b278fe8bb863d6825d5da.webp


        這里使用注解的方式,需要的ResourceFactory是一個(gè)io.milton.http.annotated.AnnotationResourceFactory


        即:


        80702d7fc9d18164b131dd05dd88047f.webp


        在構(gòu)建ResourceFactory的時(shí)候,指定的安全管理器,先設(shè)置為null,就是圖例顯示的io.milton.http.fs.NullSecurityManager


        最后,在指定milton的包掃描路徑中(io.milton.config.HttpManagerBuilder#setControllerPackagesToScan),創(chuàng)建一個(gè)自己的Resource管理器,同時(shí)標(biāo)注注解 ResourceController


        ddd6e477d56d1bfec4ca247b731bb293.webp


        寫(xiě)一個(gè)方法,標(biāo)注注解Root,表示根文件夾,這里表示當(dāng)webdav請(qǐng)求服務(wù)的時(shí)候,找到的根文件夾。


        這個(gè)時(shí)候還需要從根文件夾中獲取文件或者文件夾,需要另外寫(xiě)其他的方法,來(lái)表示獲取根文件夾中的文件/文件夾,或者從文件夾中獲取下一級(jí)文件夾(直到遞歸到最后一級(jí)文件夾),這時(shí)候只需要寫(xiě)一個(gè)方法就好了,標(biāo)注注解ChildrenOf


        0bf928e65a19889c520fca6520c08097.webp


        方法傳入了一個(gè)實(shí)體類(lèi),這里可以發(fā)現(xiàn),這個(gè)實(shí)體類(lèi)和Root返回的根文件夾是同一個(gè)類(lèi),然后,如果實(shí)體類(lèi)的ID為空,視為獲取根文件夾下的文件/文件夾,這里返回了2個(gè)文件夾和1個(gè)txt文件:


        962aad2ddb44487c197e0275a26cb8fa.webp



        獲取根文件的文件/文件夾都設(shè)置了有ID,于是后續(xù)調(diào)用這個(gè)方法的時(shí)候,會(huì)根據(jù)ID來(lái)獲取指定文件夾下的文件/文件夾


        那么基于此,一個(gè)簡(jiǎn)單的webdav服務(wù)就實(shí)現(xiàn)了,看下效果:



        86eb55c0fd3fa41e041b9661323bf009.webp



        這里把本次涉及到的核心代碼片段貼在下面:


        SpringMiltonFilter類(lèi):
                    
                      package com.lgli.webdav.config;
                    
                    
                      
                        

        import io.milton.config.HttpManagerBuilder; import io.milton.http.HttpManager; import io.milton.http.Request; import io.milton.http.ResourceFactory; import io.milton.http.Response; import io.milton.http.annotated.AnnotationResourceFactory; import io.milton.http.fs.NullSecurityManager; import io.milton.http.http11.DefaultHttp11ResponseHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.GenericFilterBean;
        import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Optional;
        /** * springboot整合milton過(guò)濾器 * * @author lgli */
        @Configuration public class SpringMiltonFilter extends GenericFilterBean {
        /** * milton配置類(lèi) */ private MiltonProperties miltonProperties;
        /** * milton Http管理構(gòu)建器 * 主要用于生成HttpManager用于處理webdav請(qǐng)求 */ private HttpManagerBuilder httpManagerBuilder;
        /** * milton Http處理webdav */ private HttpManager httpManager;

        @Autowired public void setMiltonProperties(MiltonProperties miltonProperties) { this.miltonProperties = miltonProperties; }

        @Autowired public void setHttpManagerBuilder(HttpManagerBuilder httpManagerBuilder) { this.httpManagerBuilder = httpManagerBuilder; }

        @Bean HttpManagerBuilder httpManagerBuilder(@Autowired ResourceFactory resourceFactory , @Autowired MiltonProperties mp) { HttpManagerBuilder builder = new HttpManagerBuilder(); builder.setResourceFactory(resourceFactory); builder.setBuffering(DefaultHttp11ResponseHandler.BUFFERING.whenNeeded); builder.setEnableCompression(false); builder.setEnableBasicAuth(false); builder.setEnableCookieAuth(false); builder.setControllerPackagesToScan(mp.getController()); builder.setUrlAdapter((re) -> { String s = HttpManager.decodeUrl(re.getAbsolutePath()); List<String> httpUrl = miltonProperties.getHttpUrl(); for (String s1 : httpUrl) { boolean isSatisfy = s.contains(s1); if (isSatisfy) { s = s.replace(s1, ""); } } if( s.contains( "/DavWWWRoot")) { s = s.replace( "/DavWWWRoot", ""); } return s; }); return builder; }

        @Bean ResourceFactory getResourceFactory() { AnnotationResourceFactory factory = new AnnotationResourceFactory(); factory.setSecurityManager(new NullSecurityManager()); return factory; }






        @Override public void destroy() { super.destroy(); Optional.of(httpManager).ifPresent(HttpManager::shutdown); }
        @Override protected void initFilterBean() throws ServletException { super.initFilterBean(); Optional.of(httpManagerBuilder).ifPresent(hmb -> httpManager = hmb.buildHttpManager());
        }
        @Override public void doFilter(ServletRequest servletRequest , ServletResponse servletResponse , FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; String requestURI = request.getRequestURI(); //判斷是否需要milton處理 boolean present = miltonProperties.getHttpUrl() .stream() .anyMatch(requestURI::startsWith); if (!present) { filterChain.doFilter(servletRequest, servletResponse); return; } Request miltonReq = new io.milton.servlet .ServletRequest(request, getServletContext()); Response miltonRes = new io.milton.servlet .ServletResponse((HttpServletResponse) servletResponse); httpManager.process(miltonReq, miltonRes); }

        }


        ResourceManageController類(lèi):
                    
                      package com.lgli.webdav.controller;
                    
                    
                      
                        
        import cn.hutool.core.util.StrUtil; import com.lgli.webdav.entity.FileEntity; import com.lgli.webdav.entity.FolderEntity; import com.lgli.webdav.entity.ResourceEntity; import io.milton.annotations.*;
        import java.io.InputStream; import java.util.ArrayList; import java.util.List;
        /** * ResourceController * * @author lgli */ @ResourceController public class ResourceManageController {
        @Root public FolderEntity getRoot() { FolderEntity folderEntity = new FolderEntity(); folderEntity.setName("root"); return folderEntity; }

        @ChildrenOf public List<ResourceEntity> getList(FolderEntity folder) { List<ResourceEntity> list = new ArrayList<>(); if (StrUtil.isEmpty(folder.getId())) { //根文件夾 FolderEntity folderEntity0 = new FolderEntity(); folderEntity0.setId("0"); folderEntity0.setName("文件夾0"); list.add(folderEntity0); FolderEntity folderEntity1 = new FolderEntity(); folderEntity1.setId("1"); folderEntity1.setName("文件夾1"); list.add(folderEntity1); FileEntity fileEntity0 = new FileEntity(); fileEntity0.setId("2"); fileEntity0.setName("文件1.txt"); list.add(fileEntity0); } else if ("0".equals(folder.getId())) { FolderEntity folderEntity0 = new FolderEntity(); folderEntity0.setId("0-1"); folderEntity0.setName("文件夾0-1"); list.add(folderEntity0); } else if ("1".equals(folder.getId())) { FolderEntity folderEntity0 = new FolderEntity(); folderEntity0.setId("1-1"); folderEntity0.setName("文件夾1-1"); list.add(folderEntity0); } else if ("1-1".equals(folder.getId())) { FolderEntity folderEntity0 = new FolderEntity(); folderEntity0.setId("1-1-1"); folderEntity0.setName("文件夾1-1-1"); list.add(folderEntity0); } return list; ????} }

        后續(xù)將對(duì) demo每個(gè)類(lèi)和Resource類(lèi)做一個(gè)詳細(xì)的介紹,同時(shí)還會(huì)添加權(quán)限認(rèn)證, 請(qǐng)持續(xù)關(guān)注,


        如果你也感興趣,麻煩多多支持。謝謝!


        如有錯(cuò)誤,煩請(qǐng)指正。


        點(diǎn)擊公眾號(hào)獲取更多



        瀏覽 679
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操比片 | 色人阁av | 伊人五月天激情 | 激情无码内射 | 国产jizz18高清视频 | 蜜乳av中文字幕一区二区 | 国产一a毛一级a毛片视频 | 尻骚逼| jizz成熟丰满韩国女人剧情 | 小说图片视频乱伦亚洲欧美 |