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 标记实现动态数据展示,小编我遇到一些问题,但也也解决了,我截图瞧瞧!

NoSQL + MongoDB + springBoot 2.0.3 + thymeleaf 开发文件服务器

现在我们就看下最终成果!!!

NoSQL + MongoDB + springBoot 2.0.3 + thymeleaf 开发文件服务器

 

NoSQL + MongoDB + springBoot 2.0.3 + thymeleaf 开发文件服务器

 

上传至github 源码!

*******************************

  • 注意小编这里我不会把所有的代码写入博客中,毕竟代码量还是很多的,还有一点一定要安装 MongoDB ,window傻瓜式操作不用多讲!!