本节,我们将介绍如何基于mongodb技术来存高干小说推荐储二进制文件,从而实现一个文件服务器mongodb file rver。
本文件服务器致力于小型文件的存储,比如博客中的图片、普通文档等。由于mongodb支持多种数据格式的存储,对于二进制的存储自然也是不在话下,所以可以很方便地用于存储文件。由于mongodb的bson文档对于数据量大小的限制(每个文档不超过16mb),所以本文件服务器主要针对的是小型文件的存储。对于大型文件的存储(比如超过16mb),mongodb官方已经提供了成熟的产品gridfs,读者朋友可以自行了解。
文件服务器应能够提供与平台无关的rest api供外部系统调用。
文件服务器整体的api设计如下。
·get/files/{pageindex}/{pagesize}:分页查询已经上传了的文件。
·get/files/{id}:下载某个文件。
·get/view/{id}:在线预览某个文件。比如,显示图片。
·post/upload:上传文件。
·delete/{id}:删除文件。
我们创建一个新项目,称之为mongodb-file-rver。
本例子采用的开发技术如下。
·mongodb 3.4.6。·spring boot 2.0.0.m2。
·spring data mongodb 2.0.0.m4。
·thymeleaf 3.0.6.relea。
·thymeleaf layout dialect 2.2.2。
·embedded mongodb 2.0.0。
其中,spring boot用于快速构建一个可独立运行的java项目;
thymeleaf作为前端页面模板,方便展示数据;embedded mongodb则是一款由organization flapdoodle oss出品的内嵌mongodb,可以在不启动mongodb服务器的前提下,方便进行相关的mongodb接口测试。
本文所演示的项目,是采用gradle进行组织以及构建的,如果对gradle不熟悉,也可以自行将项目转为maven项目。
build.gradle文件完整配置内容如下。
buildscript { // buildscript 代码块中脚本优先执行// ext 用于定义动态属性ext {springbootversion = '2.0.0.m2'}// 使用了 maven 的中央仓库(也可以指定其他仓库)repositories {//mavencentral()maven { url "/d/file/titlepic/snapshot" }maven { url "/d/file/titlepic/milestone" }maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }}// 依赖关系dependencies {// classpath 声明说明了在执行其余的脚本时,classloader 可以使用这些依赖项classpath("org.springframework.boot:spring-boot-gradle-plugin:${springbootversion}")}}// 使用插件apply plugin: 'java'apply plugin: 'eclip'apply plugin: 'org.springframework.boot'apply plugin: 'io.spring.dependency-management'// 指定了生成的编译文件的版本,默认是打成了 jar 包version = '1.0.0'// 指定编译 .java 文件的 jdk 版本sourcecompatibility = 1.8// 使用了 maven 的中央仓库(也可以指定其他仓库)repositories {//mavencentral()maven { url "/d/file/titlepic/snapshot" }maven { url "/d/file/titlepic/milestone" }maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }}// 依赖关系dependencies {// 该依赖用于编译阶段compile('org.springframework.boot:spring-boot-starter-web')// 添加 thymeleaf 的依赖compile('org.springframework.boot:spring-boot-starter-thymeleaf')// 添加 spring data mongodb 的依赖compile('org.springframework.boot:spring-boot-starter-data-mongodb')// 添加 embedded mongodb 的依赖用于测试compile('de.flapdoodle.embed:de.flapdoodle.embed.mongo')// 该依赖用于测试阶段testcompile('org.springframework.boot:spring-boot-starter-test')}
该build.gradle文件中的各配置项的注释已经非常详尽了,这里就不再赘述其配置项的含义了。
在mongodb-file-rver项目基础上,我们将实现文件服务器的功能。
1.领域对象
首先,我们要对文件服务器进行建模。相关的领域模型如下。
文档类是类似与jpa中的实体的概念。不同的是jpa是采用@entity注解,而文档类是采用@document注解。
在
com.waylau.spring.boot.filerver.domain包下,我们创建了一个file类。
import org.bson.types.binary;import org.springframework.data.annotation.id;import org.springframework.data.mongodb.core.mapping.document;...@documentpublic class file {@id // 主键private string id;private string name; // 文件名称private string contenttype; // 文件类型private long size;private date uploaddate;private string md5;private binary content; // 文件内容private string path; // 文件路径// 省略 getter/tter 方法protected file() {}public file(string name, s透明头像tring contenttype, long size,binary content) {this.name = name;this.contenttype = contenttype;this.size = size;this.uploaddate = new date();this.content = content;}@overridepublic boolean equals(object object) {if (this == object) {return true;}if (object == null || getclass() != object.getclass()) {return fal;}file fileinfo = (file) object;return java.util.objects.equals(size, fileinfo.size)&& java.util.objects.equals(name, fileinfo.name)&& java.util.objects.equals(contenttype, fileinfo.contenttype)&& java.util.objects.equals(uploaddate, fileinfo.uploaddate)&& java.util.objects.equals(md5, fileinfo.md5)&& java.util.objects.equals(id, fileinfo.id);}@overridepublic int hashcode() {return java.util.objects.hash(name, contenttype, size, uploaddate, md5, id);}@overridepublic string tostring() {return "file{"+ "name='" + name + '''+ ", contenttype='" + contenttype + '''+ ", size=" + size+ ", uploaddate=" + uploaddate+ ", md5='" + md5 + '''+ ", id='" + id + '''+ '}';}}
需要注意以下两点。
·文档类,主要采用的是spring data mongodb中的注解,用于标识这是nosql中的文档概念。
·文件的内容,我们是用org.bson.types.binary类型来进行存储。
2.存储库filerepository
存储库用于提供与数据库“打交道”的常用的数据访问接口。其中filerepository接口继承自
org.springframework.data.mongodb.repository.mongorepository即可,无须自行实现该接口的功能,spring data mongodb会自动实现接口中的方法。
import org.springframework.data.mongodb.repository.mongorepository;import com.waylau.spring.boot.filerver.domain.file;public interface filerepository extends mongorepository<file, string> {}
3.服务接口及实现类
filervice接口定义了对于文件的curd操作,其中查询文件接口是采用的分页处理,以有效提升查询性能。
public interface filervice {/*** 保存文件* @param file* @return*/file savefile(file file);/*** 删除文件* @param file* @return*/void removefile(string id);/*** 根据id获取文件* @param file* @return*/file getfilebyid(string id);/*** 分页查询,按上传时间降序* @param pageindex* @param pagesize* @return*/list<file> listfilesbypage(int pageindex, int pagesize);}filerviceimpl实现了filervice中所有的接口。@rvicepublic class filerviceimpl implements filervice {@autowiredpublic filerepository filerepository;@overridepublic file savefile(file file) {return filerepository.save(file);}@overridepublic void removefile(string id) {filerepository.deletebyid(id);}@overridepublic optional<file> getfilebyid(string id) {return filerepository.findbyid(id);}@overridepublic list<file> listfilesbypage(int pageindex, int pagesize) {page<file> page = null;list<file> list = null;sort sort = new sort(direction.desc,"uploaddate");pageable pageable = pagerequest.of(pageindex, pagesize, sort);page = filerepository.findall(pageable);list = page.getcontent();return list;}}
4.控制层、api资源层
filecontroller控制器作为api的提供者,接收用户的请求及响应。
api的定义符合restful的风格。
@crossorigin(origins = "*", maxagecf图标怎么点亮 = 3600) // 允许所有域名访问@controllerpublic class filecontroller {@autowiredprivate filervice filervice;@value("${rver.address}")private string rveraddress;@value("${rver.port}")private string rverport;@requestmapping(value = "/")public string index(model model) {// 展示最新20条数据model.addattribute("files", filervice.listfilesbypage(0, 20));return "index";}/*** 分页查询文件** @param pageindex* @param pagesize* @return*/@getmapping("files/{pageindex}/{pagesize}")@responbodypublic list<file> listfilesbypage(@pathvariable int pageindex,@pathvariable int pagesize) {return filervice.listfilesbypage(pageindex, pagesize);}/*** 获取文件片信息** @param id* @return*/@getmapping("files/{id}")@responbodypublic responentity<object> rvefile(@pathvariable string id) {optional<file> file = filervice.getfilebyid(id);if (file.isprent()) {return responentity.ok().h世乒赛决赛时间eader(httpheaders.content_disposition, "attachment; filename=""+ file.get().getname() + """).header(httpheaders.content_type, "application/octet-stream").header(httpheaders.content_length, file.get().getsize() + "").header("connection", "clo").body(file.get().getcontent().getdata());} el {return responentity.status(httpstatus.not_found).body("file was notfound");}}/*** 在线显示文件** @param id* @return*/@getmapping("/view/{id}")@responbodypublic responentity<object> rvefileonline(@pathvariable string id) {optional<file> file = filervice.getfilebyid(id);if (file.isprent()) {return responentity.ok().header(httpheaders.content_disposition, "filename=""+ file.get().getname() + """).header(httpheaders.content_type, file.get().getcontenttype()).header(httpheaders.content_length, file.get().getsize() + "").header("connection", "clo").body(file.get().getcontent().getdata());} el {return responentity.status(httpstatus.not_found).body("file was notfound");}}/*** 上传** @param file* @param redirectattributes* @return*/@postmapping("/")public string handlefileupload(@requestparam("file") multipartfile file,redirectattributes redirectattributes) {try {file f = new file(file.getoriginalfilename(), file.getcontenttype(),file.getsize(), new binary(file.getbytes()));f.tmd5(md5util.getmd5(file.getinputstream()));filervice.savefile(f);} catch (ioexception | nosuchalgorithmexception ex) {ex.printstacktrace();redirectattributes.addflashattribute("message", "your "+ file.getoriginalfilename() + " is wrong!");return "redirect:/";}redirectattributes.addflashattribute("message","you successfully uploaded " + file.getoriginalfilename() + "!");return "redirect:/";}/*** 上传接口** @param file* @return*/@postmapping("/upload")@responbodypublic responentity<string> handlefileupload(@requestparam("file") multipartfilefile) {file returnfile = null;try {file f = new file(file.getoriginalfilename(), file.getcontenttype(), file.getsize(),new binary(file.getbytes()));f.tmd5(md5util.getmd5(file.getinputstream()));returnfile = filervice.savefile(f);string path = "//" + rveraddress + ":" + rverport + "/view/" +returnfile.getid();return responentity.status(httpstatus.ok).body(path);} catch (ioexception | nosuchalgorithmexception ex) {ex.printstacktrace();return responentity.status(httpstatus.internal_rver_error).body(ex.getmessage());}}/*** 删除文件** @param id* @return*/@deletemapping("/{id}")@responbodypublic responentity<string> deletefile(@pathvariable string id) {try {filervice.removefile(id);return responentity.status(httpstatus.ok).body("delete success!");} catch (exception e) {return responentity.status(httpstatus.internal_rver_error).body(e.getmessage());}}}
其中@crossorigin(origins=”*”,maxage=3600)注解标识了api可以被跨域请求。
有多种方式可以运行gradle的java项目。使用spring boot gradleplugin插件运行是较为简便的一种方式,只需要执行:
$ gradlew bootrun
项目成功运行后,通过浏览器访问http://localhost:8081即可。如图14-4所示,首页提供了上传的演示界面,上传后,就能看到上传文件的详细信息。
图14-4 上传界面
我们打开application.properties配置文件,可以看到以下配置。
rver.address=localhostrver.port=8081# thymeleafspring.thymeleaf.encoding=utf-8spring.thymeleaf.cache=falspring.thymeleaf.mode=html5# limit upload file sizespring.http.multipart.max-file-size=1024kbspring.http.multipart.max-request-size=1024kb# independent mongodb rver#spring.data.mongodb.uri=mongodb://localhost:27017/test
这些配置的含义如下。
·rver.address和rver.port用来指定文件服务器启动的位置和端口号。
·
spring.http.multipart.max-file-size和spring.http.multipart.max-request-size用来限制上传文件的大小,这里设置最大是1mb。
·当spring.data.mongodb.uri没有被指定的时候,默认会采用内嵌mongodb服务器。如果要使用独立部署的mongodb服务器,那从什么什么流么设置这个配置,并指定mongodb服务器的地址。同时,将内嵌mongodb的依赖注释掉,操作如下。
dependencies {//...// 注释掉内嵌的 mongodb// compile('de.flapdoodle.embed:de.flapdoodle.embed.mongo')//...}
本文发布于:2023-04-05 09:52:39,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/06fd5cbbb9e369b2eeeb9ef4d9c75797.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:mongodb分布式部署(mongodb三种部署方式).doc
本文 PDF 下载地址:mongodb分布式部署(mongodb三种部署方式).pdf
留言与评论(共有 0 条评论) |