畅购02——分布式文件存储

跨域解决方案CORS

什么是跨域?

  出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
  如果跨域调用,会出现如下错误:
No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:9100’ is therefore not allowed access. The response had HTTP status code 400.
  由于我们采用的是前后端分离的编程方式,前端和后端必定存在跨域问题。解决跨域问题可以采用CORS

CORS简介

  CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
  在项目中实现很简单,只需要在Controller类上添加注解@CrossOrigin就可以了。
测试:例:在百度首页f12,打开console,输入命令fetch(“https://www.taobao.com”)会出现这样的错。
在这里插入图片描述

业务模块

根据商品分类名称查询品牌列表

  1. 分析:品牌和商品分类有中间表,从此下手

  2. 代码:

  • dao层:
@Select("SELECT name,image FROM tb_brand WHERE id  IN (SELECT brand_id FROM tb_category_brand WHERE  category_id IN (SELECT id FROM tb_category WHERE NAME=#{name}) )order by seq")
    public List<Map> findListByCategoryName(@Param("name") String categoryName);
  • service层和controller层很简单

根据商品分类名称查询规格列表

  1. 分析:category和spec中都有templete_id

  2. 代码:

  3. dao层:

 @Select("SELECT name,options FROM tb_spec WHERE template_id IN ( SELECT template_id FROM tb_category WHERE NAME=#{categoryName}) order by seq")
    public List<Map> findListByCategoryName(@Param("categoryName") String categoryName); 
  1. service层:需要将options转成字符串数组
@Override
public List<Map> findListByCategoryName(String categoryName) {
    List<Map> specList = specMapper.findListByCategoryName(categoryName);
    for(Map spec:specList){
        String[] options = ((String) spec.get("options")).split(",");//规格选项列表
        spec.put("options",options);
    }
    return specList;
}
  1. controller层很简单,不做赘述

分布式文件存储-FastDFS

FastDfs简介

  FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。
  FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容(加卷) 等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
  为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
在这里插入图片描述

上传流程

在这里插入图片描述
客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

组名:文件上传后所在的 storage 组名称,在文件上传成功后有storage 服务器返回,需要客户端自行保存。

虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。

数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。

文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

文件存储微服务

创建文件管理微服务changgou_service_file,该工程主要用于实现文件上传以及文件删除等功能。

  1. 修改pom.xml,引入依赖
<dependencies>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
       <groupId>net.oschina.zcx7878</groupId>
       <artifactId>fastdfs-client-java</artifactId>
       <version>1.27.0.0</version>
   </dependency>
   <dependency>
       <groupId>com.changgou</groupId>
       <artifactId>changgou_common</artifactId>
       <version>1.0-SNAPSHOT</version>
   </dependency>
</dependencies>
  1. 在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf
connect_timeout = 60
network_timeout = 60
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.200.128:22122
  1. 在resources文件夹下创建application.yml
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
server:
  port: 9008
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
  1. 创建pojo,把两个工具包放进去(代码点击

在这里插入图片描述
6. 文件上传代码

@RestController
@RequestMapping("/file")
public class FileController {
    @PostMapping("/upload")
    public Result uploadFile(MultipartFile file){
        try{
            //判断文件是否存在
            if (file == null){
                throw new RuntimeException("文件不存在");
            }
            //获取文件的完整名称
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isEmpty(originalFilename)){
                throw new RuntimeException("文件不存在");
            }//获取文件的扩展名称  abc.jpg   jpg
            String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);//获取文件内容
            byte[] content = file.getBytes();//创建文件上传的封装实体类
            FastDFSFile fastDFSFile = new FastDFSFile(originalFilename,content,extName);//基于工具类进行文件上传,并接受返回参数  String[]
            String[] uploadResult = FastDFSClient.upload(fastDFSFile);//封装返回结果
            String url = FastDFSClient.getTrackerUrl()+uploadResult[0]+"/"+uploadResult[1];
            return new Result(true,StatusCode.OK,"文件上传成功",url);
        }catch (Exception e){
            e.printStackTrace();
        }
        return new Result(false, StatusCode.ERROR,"文件上传失败");
    }
}
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页