NoSQL + MongoDB + springBoot 2.0.3 + thymeleaf 开发文件服务器
NoSQL 简介
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDBMS)来处理。 1970年 E.F.Codd's提出的关系模型的论文 "A relational model of data for large shared data banks",这使得数据建模和应用程序编程更加简单。
通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数
主要特点
- MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
- 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")来实现更快的排序。
- 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
- 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
- Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
- MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
- Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
- Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
- Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
- GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
- MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
- MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
- MongoDB安装简单。
据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。
前面小编我简单摘要关于什么是NoSQL 和 MongoDB 简介与关系
- 下面我们就开始MongoDB + springBoot 2.0.3开发文件服务器
- 既然是基于Springboot2.0.3开发开发文件服务器 ,那我们肯定第一搭建开发环境
application.yml 文件中配置参数
#server 上下文路径 server: port: 8989 address: 127.0.0.1 #配置thymeleaf spring: thymeleaf: encoding: UTF-8 cache: false mode: HTML5 #分割文件上载大小 servlet: multipart: max-file-size: 1024KB max-request-size: 1024KB # 自定义独立配置 MongoDB 服务 # data: # mongodb: # uri: http://localhost:27017 |
pom.xml 添加依赖
<!-- 添加 Spring Data Mongodb 的依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!-- 添加 Embedded MongoDB 的依赖用于测试 --> <dependency> <groupId>de.flapdoodle.embed</groupId> <artifactId>de.flapdoodle.embed.mongo</artifactId> <scope>test</scope> </dependency> <!-- 添加 Thymeleaf 的依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> |
构建文件对象的实体类
/** * File 文档类. * @author Administrator * <br> *注意:这里是非关系数据库 NoSQL 建立映射实体的对象 */ @Document public class File { /** * @param id 主键 * @param name 文件名称 * @param contentType 文件类型 * @param size 文件大小 * @param uploadDate 上载日期 * @param md5 md5 加密 * @param content 文件内容 * @param path 文件路径 */
@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;
public String getPath() { return path; }
public void setPath(String path) { this.path = path; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getContentType() { return contentType; }
public void setContentType(String contentType) { this.contentType = contentType; }
public long getSize() { return size; }
public void setSize(long size) { this.size = size; }
public Date getUploadDate() { return uploadDate; }
public void setUploadDate(Date uploadDate) { this.uploadDate = uploadDate; }
public String getMd5() { return md5; }
public void setMd5(String md5) { this.md5 = md5; }
public Binary getContent() { return content; }
public void setContent(Binary content) { this.content = content; }
protected File() { }
public File(String name, String contentType, long size,Binary content) { this.name = name; this.contentType = contentType; this.size = size; this.uploadDate = new Date(); this.content = content; } /** * 重写equals 方法 */ @Override public boolean equals(Object object) { if (this == object) { return true; } if (object == null || getClass() != object.getClass()) { return false; } 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); } /** * 重写hashCode */ @Override public int hashCode() { return java.util.Objects.hash(name, contentType, size, uploadDate, md5, id); }
@Override public String toString() { return "File{" + "name='" + name + '\'' + ", contentType='" + contentType + '\'' + ", size=" + size + ", uploadDate=" + uploadDate + ", md5='" + md5 + '\'' + ", id='" + id + '\'' + '}'; } } |
编写repository 层,我实现接口应该集成springboot中 MongoDB 提供的接口类
/** * File 存储库.<br> * 采用MongoDB操作 * * @author Administrator * */ public interface FileRepository extends MongoRepository<File, String> { }
|
编写Service层,小编我就主要说要一下 MongoDB 分页查询实现,这里我编写了自己查询Criteria准则,具体实现在文章结尾提供的github开源源码中
/** * File 服务. * @author Administrator * */ @Service public class FileServiceImpl implements FileService { /** * @param fileRepository * @param mongoTemplate */ @Autowired public FileRepository fileRepository; @Autowired protected MongoTemplate mongoTemplate;
/** *分页条件查询,按上传时间降序 * @throws Exception */ @Override public Page<File> listFilesByPage(Pageable pageable, MeCriteria meCriteria) throws Exception {
List<ExprType> expr= meCriteria.get_expr();
//定义查询Criteria链 List<Criteria> criteriaChain = new ArrayList<Criteria>();; for (ExprType exprType : expr) { String property = exprType.get_property(); if(exprType.get_value()!=null) { Object value = exprType.get_value(); //mongoDB模糊查询 Pattern pattern = Pattern.compile("^.*" + value + ".*$"); if("name".equals(property)) { criteriaChain.add(Criteria.where("name").regex(pattern)); }else if("contentType".equals(property)) { criteriaChain.add(Criteria.where("contentType").regex(pattern)); } }else if( exprType.get_min() !=null && exprType.get_max()!=null){ Object min = exprType.get_min(); Object max = exprType.get_max(); if(exprType.get_property().equals("uploadDate")) { if(min !=null && max !=null && !"".equals(min) && !"".equals(max)) { //大于最小时间,小于最大时间 criteriaChain.add( Criteria.where("uploadDate").gt(DateUtils.parseDate((String) min, "yyyy-MM-dd HH:mm")) .lt(DateUtils.parseDate((String) max, "yyyy-MM-dd HH:mm"))); } }else if(exprType.get_property().equals("size")){ if(min !=null && max !=null && !"".equals(min) && !"".equals(max)) { //大于最小size,小于最大size criteriaChain.add(Criteria.where("size").gt(Long.parseLong((String)min)).lt(Long.parseLong((String)max))); } }
} } Criteria criteria =new Criteria(); criteria.andOperator(criteriaChain.toArray(new Criteria[criteriaChain.size()])); //查询,加入criteria组成条件 Query query=new Query(criteria); //分页查询 List<File> list = mongoTemplate.find(query.with(pageable), File.class); //返回分页查询的对象 Page<File> page = new PageImpl<File>(list , pageable, mongoTemplate.count(query, File.class)); return page; } }
|
Controller层摘要部分复杂查询的代码块
/** *文件服务器controller * @author Administrator * */ @CrossOrigin(origins = "*", maxAge = 3600) // 允许所有域名访问,响应最大时间 @Controller public class FileController {
@Autowired private FileService fileService;
@Value("${server.address}") private String serverAddress;
@Value("${server.port}") private String serverPort;
/** * 访问文件服务器首页 * @param model * @return * @throws Exception */ @RequestMapping(value = "/") public String index(@RequestParam(value = "async", required = false) boolean async, @RequestParam(value = "pageIndex", required = false, defaultValue = "0") Integer pageIndex, @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize, Model model) throws Exception { // 展示最新10条数据 Sort sort = new Sort(Direction.DESC,"uploadDate"); Pageable pageable = PageRequest.of(pageIndex, pageSize , sort); Page<File> page = fileService.listFilesByPage(pageable); model.addAttribute("files", page.getContent()); model.addAttribute("page" , page); return "index"; } /** * 分页携带条件查询文件 * @param async * @param pageIndex * @param pageSize * @param criteria * @param model * @return * @throws Exception */ @RequestMapping(value = "/queryAction" , method=RequestMethod.POST) public String index(@RequestParam(value = "async", required = false) boolean async, @RequestParam(value = "pageIndex", required = false, defaultValue = "0") Integer pageIndex, @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize, CriteriaType criteriaType, Model model) throws Exception { // 展示最新二十条数据 Sort sort = new Sort(Direction.DESC,"uploadDate"); Pageable pageable = PageRequest.of(pageIndex, pageSize , sort); Page<File> page = fileService.listFilesByPage(pageable , criteriaType.getMeCriteria()); model.addAttribute("files", page.getContent()); model.addAttribute("page" , page); model.addAttribute("meCriteria", criteriaType.getMeCriteria()); return "index"; } } |
html页面+ thymeleaf 标记实现动态数据展示,小编我遇到一些问题,但也也解决了,我截图瞧瞧!
|
现在我们就看下最终成果!!!
|
|
上传至github 源码!
*******************************
-
注意小编这里我不会把所有的代码写入博客中,毕竟代码量还是很多的,还有一点一定要安装 MongoDB ,window傻瓜式操作不用多讲!!