zoukankan      html  css  js  c++  java
  • 动静分离-静态资源缓存控制

    一、静态资源服务与动态资源服务的区别

    首先动静分离非前后端分离,关于两者的介绍如下:

    • 动静分离:动态资源(jsp、ftl)与静态资源(js、img、css)分开
    • 前后端分离:接口与视图分开独立开发部署

    二、为什么静态资源需要实现CDN内容加速

    在一个网站中,请求是比较占宽带资源的。

    其主要加载内容为静态资源,如: css、js、img

    我们知道,一个1兆带宽服务器 = 128kb/s,如果存在一个 512/kb 的静态资源需要请求 4s 左右,而动态资源(json)占带宽很小(几十B),几乎可以忽略不计。

    既然带宽影响网站访问速度,那就加带宽好了?

    但是!带宽价格不是贵的一点点…

    所以市场上出现了一些静态资源服务器平台(对象文件存储) 。

    比如七牛云、阿里云(oss)、腾讯云(内置CDN内容分发)。

    什么是CDN内容分发?

    CDN内容分发,就是将静态资源服务器会部署全国各个服务器节点,用户访问的时候,遵循就近原则。比如你的所在地在济南,那么你在访问资源文件时,会分配给你距离济南最近的CDN网点。

    三、七牛云创建静态资源存储空间

    官方地址:https://developer.qiniu.com/

    注册之后就可以去创建对象存储空间了,详细步骤建议看官方文档。

    创建好空间后需要绑定一个自己的域名,如果不绑定则使用默认提供的域名,提供的域名有默认的使用时长:

    如下是我的存储空间域名绑定截图:

    如下是我之前涂涂影院存放的一些静态资源:

    四、动静分离架构系统缺点

    使用CDN内容分发确实提高了网站的访问速度,但是动静分离架构模式有什么缺点呢?

    跨域问题

    比如域名访问的是:www.sscai.club

    而静态资源访问的则是:cdn.sscai.club

    如何解决跨域问题?

    nginx转发

    将 www.sscai.club 转发到 cdn.sscai.club

    五、代码中实现七牛云文件上传

    引入pom依赖

    <!-- 七牛云SDK -->
    <dependency>
        <groupId>com.qiniu</groupId>
        <artifactId>qiniu-java-sdk</artifactId>
        <version>[7.2.0, 7.2.99]</version>
    </dependency>

    主要代码:

    @RequestMapping(value = "/file", method = RequestMethod.POST)
    @ApiOperation(value = "文件上传")
    public Result<Object> upload(
        @RequestParam(required = false) MultipartFile file,
        @RequestParam(required = false) String base64,
        HttpServletRequest request) {

        // 判断上传类型 */
        if(StrUtil.isNotBlank(base64)){
            // base64上传 */
            file = Base64DecodeMultipartFile.base64Convert(base64);
        }
        String result = "";
        String fKey = renamePic(file.getOriginalFilename());
        File f = new File();
        try {
            // 获取文件流
            InputStream inputStream = file.getInputStream();

            /* 上传至第三方云服务——七牛云 */
            result = qiniuInputStreamUpload(inputStream, fKey);
            f.setLocation(CommonConstant.OSS_QINIU);

            /* 保存数据信息至数据库 */
            f.setName(file.getOriginalFilename());
            f.setSize(file.getSize());
            f.setType(file.getContentType());
            f.setFKey(fKey);
            f.setUrl(result);
            fileService.save(f);
        } catch (Exception e) {
            log.error(e.toString());
            return new ResultUtil<Object>().setErrorMsg(e.toString());
        }
        if(used.equals(SettingConstant.LOCAL_OSS)){
            OssSetting os = fileUtil.getOssSetting();
            result = os.getHttp() + os.getEndpoint() + "/" + f.getId();
        }
        return new ResultUtil<Object>().setData(result);
    }

    public static String renamePic(String fileName) {
        String extName = fileName.substring(fileName.lastIndexOf("."));
        return UUID.randomUUID().toString().replace("-""") + extName;
    }


    /**
     * 文件流上传
     * @param inputStream
     * @param key  文件名
     * @return
     */

    public String qiniuInputStreamUpload(InputStream inputStream, String key) {

        OssSetting os = getOssSetting();
        Auth auth = Auth.create(os.getAccessKey(), os.getSecretKey());
        String upToken = auth.uploadToken(os.getBucket());
        try {
            Response response = getUploadManager(getConfiguration(os.getZone())).put(inputStream, key, upToken, nullnull);
            /* 解析上传成功的结果 */
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            return os.getHttp() + os.getEndpoint() + "/" + putRet.key;
        } catch (QiniuException ex) {
            Response r = ex.response;
            throw new XbootException("上传文件出错,请检查七牛云配置," + r.toString());
        }
    }


    @Data
    public class OssSetting implements Serializable{

        @ApiModelProperty(value = "服务商")
        private String serviceName;

        @ApiModelProperty(value = "ak")
        private String accessKey;

        @ApiModelProperty(value = "sk")
        private String secretKey;

        @ApiModelProperty(value = "endpoint域名")
        private String endpoint;

        @ApiModelProperty(value = "bucket空间")
        private String bucket;

        @ApiModelProperty(value = "http")
        private String http;

        @ApiModelProperty(value = "zone存储区域")
        private Integer zone;

        @ApiModelProperty(value = "bucket存储区域")
        private String bucketRegion;

        @ApiModelProperty(value = "本地存储路径")
        private String filePath;

        @ApiModelProperty(value = "是否改变secrectKey")
        private Boolean changed;
    }

    Base64转为MultipartFile工具类:

    /**
     * base64转为multipartFile工具类
     * @author nikou
     */

    public class Base64DecodeMultipartFile implements MultipartFile {

        private final byte[] imgContent;
        private final String header;

        public Base64DecodeMultipartFile(byte[] imgContent, String header) {
            this.imgContent = imgContent;
            this.header = header.split(";")[0]; 
        }

        @Override
        public String getName() {
            return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
        }

        @Override
        public String getOriginalFilename() {
            return System.currentTimeMillis() + (int)Math.random() * 10000 + "." + header.split("/")[1];
        }

        @Override
        public String getContentType() {
            return header.split(":")[1];
        }

        @Override
        public boolean isEmpty() {
            return imgContent == null || imgContent.length == 0;
        }

        @Override
        public long getSize() {
            return imgContent.length;
        }

        @Override
        public byte[] getBytes() throws IOException {
            return imgContent;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(imgContent);
        }

        @Override
        public void transferTo(File dest) throws IOException, IllegalStateException {
            new FileOutputStream(dest).write(imgContent);
        }


        public static MultipartFile base64Convert(String base64) {

            String[] baseStrs = base64.split(",");
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            try {
                b = decoder.decodeBuffer(baseStrs[1]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            return new Base64DecodeMultipartFile(b, baseStrs[0]);
        }
    }

    我创建了一个java相关的公众号,用来记录自己的学习之路,感兴趣的小伙伴可以关注一下微信公众号哈:niceyoo

  • 相关阅读:
    C#连接手机安装软件和发送信息
    asp.net 简单分页打印
    asp.net 下载的几种方式
    js 刷新后不提示并保留控件状态
    JAVA 基础编程练习题2 【程序 2 输出素数】
    JAVA 基础编程练习题1 【程序 1 不死神兔】
    setMaxActive和setMaxWait方法
    java.lang.UnsupportedClassVersionError: com/mysql/jdbc/Driver : Unsupported major.minor version 52.0
    java.lang.RuntimeException: org.dom4j.DocumentException: 1 字节的 UTF-8 序列的字节 1 无效。
    HTML DOM firstChild lastChild nextSibling previousSibling 属性_获取属性值的undefined问题
  • 原文地址:https://www.cnblogs.com/niceyoo/p/11258239.html
Copyright © 2011-2022 走看看