海量数据处理商用短链接生成器平台 - 4

news2024/11/30 14:26:11

第六章 架构核心技术-池化思想-异步结合 性能优化最佳实践

第1集 RestTemplate里面的存在的问题你知道多少- Broken pipe错误

项目就更新到第六章了,剩下的内容 放百度网盘里面了,需要的来取。
链接:https://pan.baidu.com/s/19LHPw36dsxPB75z_FHS64Q?pwd=8h89
提取码:8h89
在这里插入图片描述


简介: RestTemplate里面的存在的问题你知道多少

  • 还原代码(暂时不用异步)

    • 异步-里面是用线程池-是池化思想的一种应用
  • 同步发送+resttemplate未池化

    • 压测结果 几百吞吐量

    • 错误Caused by: java.io.IOException: Broken pipe

      • 服务端向前端socket连接管道写返回数据时 链接(pipe)却断开了
        • 从应用角度分析,这是因为客户端等待返回超时了,主动断开了与服务端链接
        • 连接数设置太小,并发量增加后,造成大量请求排队等待
        • 网络延迟,是否有丢包
        • 内存是否足够多支持对应的并发量

      在这里插入图片描述

  • 问题分析

    • resttemplate底层是怎样的?
    • 基于之前的认知-池化思想,联想到是否使用了http连接池?
  • 重新认识RestTemplate

    • RestTemplate是Spring提供的用于访问Rest服务的客户端
    • 底层通过使用java.net包下的实现创建HTTP 请求
    • 通过使用ClientHttpRequestFactory指定不同的HTTP请求方式,主要提供了两种实现方式
      • SimpleClientHttpRequestFactory(默认)
        • 底层使用J2SE提供的方式,既java.net包提供的方式,创建底层的Http请求连接
        • 主要createRequest 方法( 断点调试),每次都会创建一个新的连接,每次都创建连接会造成极大的资源浪费,而且若连接不能及时释放,会因为无法建立新的连接导致后面的请求阻塞
      • HttpComponentsClientHttpRequestFactory
        • 底层使用HttpClient访问远程的Http服务
  • 问题解决

    • 客户端每次请求都要和服务端建立新的连接,即三次握手将会非常耗时
    • 通过http连接池可以减少连接建立与释放的时间,提升http请求的性能
    • Spring的restTemplate是对httpclient进行了封装, 而httpclient是支持池化机制
    • 拓展
      • 对httpclient进行封装的有:Apache的Fluent、es的restHighLevelClient、spring的restTemplate等
第2集 高性能RestTemplate连接池封装配置实战

简介: 高性能RestTemplate封装配置实战

  • 配置RestTemplate连接池实战
  @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }


    /**
     * @return
     */
    @Bean
    public HttpClient httpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

        //设置整个连接池最大连接数
        connectionManager.setMaxTotal(500);

        //MaxPerRoute路由是对maxTotal的细分,每个主机的并发,这里route指的是域名
        connectionManager.setDefaultMaxPerRoute(200);
        RequestConfig requestConfig = RequestConfig.custom()
                //返回数据的超时时间
                .setSocketTimeout(20000)
                //连接上服务器的超时时间
                .setConnectTimeout(10000)

                //从连接池中获取连接的超时时间
                .setConnectionRequestTimeout(1000)
                .build();

        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }
第3集 【10倍+QPS提升】Jmeter5.x压测 优化后RestTemplate前后性能对比

简介: 【10倍+提升】Jmeter5.x压测 优化后RestTemplate前后性能对比

  • 同步发送+resttemplate未池化

    • 压测结果 几百 吞吐量
  • 同步发送+resttemplate池化

    • 压测结果

    在这里插入图片描述

  • 检查你自己公司的项目,是否存在对应的问题

在这里插入图片描述

第七章 账号微服务-发送短信验证码-池化+异步结合最佳实践

第1集 调用第三方短信验证码组件性能优化实战

简介:调用第三方短信验证码组件性能优化实战

  • 调整代码

  • 采用异步调用方式

  • 采用 resttemplate池化方式

第2集 说说一些薅羊毛的事情+防范解决方案
  • 抢票
  • 稀缺的酒、鞋等

在这里插入图片描述

  • 短信邮箱轰炸机

    • 什么是短信-邮箱轰炸机:
    手机短信轰炸机是批量、循环给手机无限发送各种网站的注册验证码短信的方法。
    
    • 美好的初衷-发明的由来
    最早发明是用来整治街头广告电话号泛滥的一种手段,采用“手机短信轰炸机”软件可无限发送垃圾短信到牛皮癣小广告的手机号码上,使对方的手机快速消耗电量,变成高频率振动棒,且无法正常使用。
    
    “短信轰炸机”可严厉打击城市“牛皮癣”,还城市明净容颜。
    
    • 灰色产业的目光-也就是部分不法分子利用
    某次大型程序员相亲现场-老王得罪了小王, 小王不爽,就道听途说知道了”短信轰炸机“,1天50元,轰炸了5天还打折300元。
    
    一天内接到来自全国各地数千个陌生电话短信的轰炸骚扰,导致个人通讯中断,被工作生活受到严重影响,连刚相亲到的女友没没法联系上了。
    
  • 原理

    很多人都用手机注册一些网站的验证了,比如手机验证码。先填手机号,然后发一条验证码过去,输入验证码,完成验证,注册成功。
    
    * 寻找大量肉鸡网站,寻找发送验证码的请求接口
    
    * 如果找不到接口,也可以使用自动化UI工具触发
    
    * 编写程序和调度任务,相关脚本录入数据库
    
    * 输入目标手机号或者邮箱,触发攻击
    
  • 公司带来的损失

    • 短信一条5分钱,如果被大量盗刷大家自己计算
    • 邮箱通知不用钱,但被大量盗刷,带宽、连接等都被占用,导致无法正常使用
  • 如何避免自己的网站成为”肉鸡“或者被刷呢

    • 增加图形验证码(开发人员)
    • 单IP请求次数限制(开发人员)
    • 限制号码发送(一般短信提供商会做)
  • 是否可以一劳永逸???

    • 没有百分百的安全,验证码是可以破解的,ip也是可以租用代理ip的

    • 攻防永远是有的,只过加大了攻击者的成本,ROI划不过来自然就放弃了

在这里插入图片描述

第3集 图形验证码开发之谷歌kaptcha引入

简介:谷歌开源kaptcha图形验证码开发

  • Kaptcha 框架介绍 谷歌开源的一个可高度配置的实用验证码生成工具

    • 验证码的字体/大小/颜色
    • 验证码内容的范围(数字,字母,中文汉字!)
    • 验证码图片的大小,边框,边框粗细,边框颜色
    • 验证码的干扰线
    • 验证码的样式(鱼眼样式、3D、普通模糊)
  • 聚合工程依赖添加(使用国内baomidou二次封装的springboot整合starter)

            <!--kaptcha依赖包-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>kaptcha-spring-boot-starter</artifactId>
                <version>1.1.0</version>
            </dependency>
  • 账号微服务添加
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>kaptcha-spring-boot-starter</artifactId>
            </dependency>
  • 开发配置(任何框架和springboot整合基本都是)
@Configuration
public class CaptchaConfig {

    /**
     * 验证码配置
     * Kaptcha配置类名
     * 
     * @return
     */
    @Bean
    @Qualifier("captchaProducer")
    public DefaultKaptcha kaptcha() {
        DefaultKaptcha kaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
//    properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
//    properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "220,220,220");
//    //properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "38,29,12");
//    properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "147");
//    properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "34");
//    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "25");
//    //properties.setProperty(Constants.KAPTCHA_SESSION_KEY, "code");
        //验证码个数
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
//    properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Courier");
        //字体间隔
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8");
        //干扰线颜色
//    properties.setProperty(Constants.KAPTCHA_NOISE_COLOR, "white");
        //干扰实现类
        properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
        //图片样式
        properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.WaterRipple");
        //文字来源
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789");
        Config config = new Config(properties);
        kaptcha.setConfig(config);
        return kaptcha;
    }
}

  • 开发一个Controller使用测试
第4集 池化思想应用-Redis6.X配置连接池实战

简介:池化思想应用-Redis6.X配置连接池实战

  • 连接池好处

    • 使用连接池不用每次都走三次握手、每次都关闭Jedis
    • 相对于直连,使用相对麻烦,在资源管理上需要很多参数来保证,规划不合理也会出现问题
    • 如果pool已经分配了maxActive个jedis实例,则此时pool的状态就成exhausted了
  • 连接池配置 common项目

     <!--redis客户端-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>io.lettuce</groupId>
                        <artifactId>lettuce-core</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
    
  • 配置Redis连接

      redis:
        client-type: jedis
        host: 120.79.150.146
        password: class.net
        port: 6379
        jedis:
          pool:
            # 连接池最大连接数(使用负值表示没有限制)
            max-active: 100
            # 连接池中的最大空闲连接
            max-idle: 100
            # 连接池中的最小空闲连接
            min-idle: 100
            # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-wait: 60000
    
  • 序列化配置

    @Configuration
    public class RedisTemplateConfiguration {
        /**
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            // 使用Jackson2JsonRedisSerialize 替换默认序列化
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
            // 设置key和value的序列化规则
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            // 设置hashKey和hashValue的序列化规则
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
            return redisTemplate;
        }
    }
    
第5集 账号微服务开发图形验证码加入缓存+Try-with-resource

简介:账号微服务开发图形验证码接口+Try-with-resource

  • redis做隔离, 多集群:核心集群和非核心集群,高并发集群和非高并发集群

    • 资源隔离
    • 数据保护
    • 提高性能
    • key规范:业务划分,冒号隔离
      • account-service:captcha:xxxx
      • 长度不能过长
  • 验证码接口开发

/**
     *临时使用10分钟有效,方便测试
     */
    private static final long CAPTCHA_CODE_EXPIRED = 60 * 1000 * 10;

    /**
     * 获取图形验证码
     * @param request
     * @param response
     */
    @GetMapping("captcha")
    public void getCaptcha(HttpServletRequest request, HttpServletResponse response) {

        String captchaText = captchaProducer.createText();
        log.info("图形验证码:{}", captchaText);

        //存储
        redisTemplate.opsForValue().set(getCaptchaKey(request),
                captchaText, CAPTCHA_CODE_EXPIRED, TimeUnit.MILLISECONDS);

        BufferedImage bufferedImage = captchaProducer.createImage(captchaText);
        try (ServletOutputStream outputStream = response.getOutputStream()){
            ImageIO.write(bufferedImage, "jpg", outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("获取图形验证码异常:{}", e);
        }

    }

  • 什么是try-with-resources
    • 资源的关闭很多⼈停留在旧的流程上,jdk7新特性就有, 但是很多⼈以为是jdk8的
    • 在try( …)⾥声 明的资源,会在try-catch代码块结束后⾃动关闭掉
    • 注意点
      • 实现了AutoCloseable接⼝的类,在try()⾥声明该类实例的时候,try结束后⾃动调⽤的 close⽅法,这个动作会早于finally⾥调⽤的⽅法
      • 不管是否出现异常,try()⾥的实例都会被调⽤close⽅法
      • try⾥⾯可以声明多个⾃动关闭的对象,越早声明的对象,会越晚被close掉
第6集 账号微服务之注册短信验证码接口开发

简介:注册短信验证码接口开发

  • service层
  @Override
    public JsonData sendCode(SendCodeEnum sendCodeType, String to) {
      
        if(CheckUtil.isEmail(to)){
            //邮箱验证码
           

        }else if(CheckUtil.isPhone(to)){
            //短信验证码
        }

        return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR);
    }
  • 邮箱工具类正则
public class CheckUtil {


    /**
     * 邮箱正则
     */
    private static final Pattern MAIL_PATTERN = Pattern.compile("^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$");

    /**
     * 手机号正则
     */
    private static final Pattern PHONE_PATTERN = Pattern.compile("^((13[0-9])|(14[0-9])|(15[0-9])|(17[0-9])|(18[0-9]))\\d{8}$");

    /**
     * @param email
     * @return
     */
    public static  boolean isEmail(String email) {
        if (null == email || "".equals(email)) {
            return false;
        }
        Matcher m = MAIL_PATTERN.matcher(email);
        return m.matches();
    }

    /**
     * 
     * @param phone
     * @return
     */
    public static boolean isPhone(String phone) {
        if (null == phone || "".equals(phone)) {
            return false;
        }
        Matcher m = PHONE_PATTERN.matcher(phone);
        boolean result = m.matches();
        return result;

    }
}
第7集 关于注册短信验证码防刷设计方案你能想到几个

简介:注册短信验证码防刷方案你能想到几个

在这里插入图片描述

  • 需求:一定时间内禁止重复发送短信,大家想下有哪几种实现方式

    • 两个时间要求
      • 60秒后才可以重新发送短信验证码
      • 发送的短信验证码10分钟内有效
    • 方式一:前端增加校验倒计时,不到60秒按钮不给点击

      • 简单
      • 不安全,存在绕过的情况
    • 方式二:增加Redis存储,发送的时候设置下额外的key,并且60秒后过期

      • 非原子操作,存在不一致性

      • 增加的额外的key - value存储,浪费空间

      • /**
         * 前置:判断是否重复发送
         *
         * 1、存储验证码到缓存
         *
         * 2、发送短信验证码
         *
         * 后置:存储发送记录
         **/
        
    • 方式三:基于原先的key拼装时间戳

      • 好处:满足了当前节点内的原子性,也满足业务需求
第8集 【重要】注册邮箱验证码防刷代码落地+整体测试

简介:注册邮箱验证码防刷落地和整体测试



    @Override
    public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {


        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY,sendCodeEnum.name(),to);


        String cacheValue = redisTemplate.opsForValue().get(cacheKey);


        //如果不为空,再判断是否是60秒内重复发送 0122_232131321314132
        if(StringUtils.isNotBlank(cacheValue)){
            long ttl = Long.parseLong(cacheValue.split("_")[1]);
            //当前时间戳-验证码发送的时间戳,如果小于60秒,则不给重复发送
            long leftTime = CommonUtil.getCurrentTimestamp() - ttl;
            if( leftTime < (1000*60)){
                log.info("重复发送短信验证码,时间间隔:{}秒",leftTime);
                return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
            }
        }


        String code = CommonUtil.getRandomCode(6);
        //生成拼接好验证码
        String value = code+"_"+CommonUtil.getCurrentTimestamp();
        redisTemplate.opsForValue().set(cacheKey,value,CODE_EXPIRED,TimeUnit.MILLISECONDS);


        if(CheckUtil.isEmail(to)){
            //发送邮箱验证码  TODO


        }else if(CheckUtil.isPhone(to)){


            //发送手机验证码
            smsComponent.send(to,smsConfig.getTemplateId(),code);
        }
        return JsonData.buildSuccess();
    }

第八章 账号微服务-阿里云OSS接入实战

第1集 分布式文件存储业界常见解决方案介绍

简介:分布式文件存储常见解决方案介绍

  • 目前业界比较多这个解决方案,这边就挑选几个介绍下

    • MinIO
    是在 Apache License v2.0 下发布的对象存储服务器,学习成本低,安装运维简单,主流语言的客户端整合都有, 号称最强的对象存储文件服务器,且可以和容器化技术docker/k8s等结合,社区活跃但不够成熟,业界参考资料较少
    
    
    官网:https://docs.min.io/cn/
    
    • FastDFS
    一个开源的轻量级分布式文件系统,比较少的客户端可以整合,目前主要是C和java客户端,在一些互联网创业公司中有应用比较多,没有官方文档,社区不怎么活跃.
    架构+部署结构复杂,出问题定位比较难定位,可以说是fastdfs零件的组装过程,需要去理解fastDFS的架构设计,才能够正确的安装部署
    
    • 云厂商

      • 阿里云OSS

      • 七牛云

      • 腾讯云

      • 亚马逊云

      • CDN最强:Akamai https://www.akamai.com/cn

  • 选云厂商理由

    • 优点:开发简单,功能强大,容易维护(不同网络下图片质量、水印、加密策略、扩容、加速)
    • 缺点:要钱, 个性化处理,未来转移比较复杂,不排除有些厂商会提供一键迁移工具
  • 选开源MinIO的理由

    • 优点:功能强大、可以根据业务做二次的定制,新一代分布式文件存储系统,容器化结合强大,更重要的是免费(购买磁盘、内存、带宽)
    • 缺点:自己需要有专门的团队进行维护、扩容等
  • 文件上传流程

    • web控制台
    • 前端->后端程序->阿里云OSS

在这里插入图片描述

第2集 阿里云OSS分布式对象存储介绍开通

简介:阿里云OSS对象存储介绍和开通

  • 阿里云OSS介绍
对象存储OSS(Object Storage Service)是阿里云提供的海量、安全、低成本、高持久的云存储服务。其数据设计持久性不低于99.9999999999%(12个9),服务设计可用性不低于99.995%。


OSS具有与平台无关的RESTful API接口,您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。


提供标准、低频访问、归档和冷归档四种存储类型,全面覆盖从热到冷的各种数据存储场景:
标准存储类型高持久、高可用、高性能的对象存储服务,支持频繁的数据访问。是各种社交、分享类的图片、音视频应用、大型网站、大数据分析的合适选择。
低频访问存储类型适合长期保存不经常访问的数据(平均每月访问频率1到2次)。存储单价低于标准类型,适合各类移动应用、智能设备、企业数据的长期备份,支持实时数据访问。
归档存储类型适合需要长期保存(建议半年以上)的归档数据,在存储周期内极少被访问,数据进入到可读取状态需要1分钟的解冻时间。适合需要长期保存的档案数据、医疗影像、科学资料、影视素材。
冷归档存储类型适合需要超长时间存放的极冷数据。例如因合规要求需要长期留存的数据、大数据及人工智能领域长期积累的原始数据、影视行业长期留存的媒体资源、在线教育行业的归档视频等。
  • 开通阿里云OSS

    • 有阿里云账号、实名认证

    • OSS介绍:https://www.aliyun.com/product/oss

    • OSS控制台:https://oss.console.aliyun.com/bucket

    • 学习路径:https://help.aliyun.com/learn/learningpath/oss.html

  • 开通后的操作

    • 创建Bucket
    • 上传文件
    • 访问文件
第3集 权限知识 RBAC-ACL模式应用之阿里云RAM访问控制

简介:权限知识 RBAC-ACL模式应用之阿里云RAM访问控制

  • ACL: Access Control List 访问控制列表

    • 以前盛行的一种权限设计,它的核心在于用户直接和权限挂钩
    • 优点:简单易用,开发便捷
    • 缺点:用户和权限直接挂钩,导致在授予时的复杂性,比较分散,不便于管理
    • 例子:常见的文件系统权限设计, 直接给用户加权限
  • RBAC: Role Based Access Control

    • 基于角色的访问控制系统。权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限
    • 优点:简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来
    • 缺点:开发对比ACL相对复杂
    • 例子:基于RBAC模型的权限验证框架与应用 Apache Shiro、spring Security
  • 总结:不能过于复杂,规则过多,维护性和性能会下降, 更多分类 ABAC、PBAC等

  • RAM权限介绍

    • 阿里云用于各个产品的权限,基于RBAC、ACL模型都有,进行简单管理账号、统一分配权限、集中管控资源,从而建立安全、完善的资源控制体系。

    • 众多产品,一般采用子账号进行分配权限,防止越权攻击

      在这里插入图片描述

    • 建立用户,勾选编程访问(保存accessKey和accessSecret,只出现一次)

      • 用户登录名称 dcloud_link@1701673122790560.onaliyun.com AccessKey ID : LTAI5tHVGvYw7twoVFyruB1H AccessKey Secret : r4d0EudzSvPfVMb9Zp0TfmsE32RXmN
    • 为新建用户授权OSS全部权限

第4集 阿里云OSS客户端SDK集成和上传组件功能开发

简介:阿里云OSS对象存储客户端集成和测试服务

  • 添加阿里云OSS的SDK

    • 地址:https://help.aliyun.com/document_detail/32008.html

    • 添加maven依赖

      • 底层聚合工程添加版本
       <!-- OSS各个项目单独加依赖,根据需要进行添加-->
                  <dependency>
                      <groupId>com.aliyun.oss</groupId>
                      <artifactId>aliyun-sdk-oss</artifactId>
                      <version>3.10.2</version>
                  </dependency>
      
      • 账号微服务添加
       <!-- OSS各个项目单独加依赖,根据需要进行添加-->
              <dependency>
                  <groupId>com.aliyun.oss</groupId>
                  <artifactId>aliyun-sdk-oss</artifactId>
              </dependency>
      
  • 账号微服务配置OSS

#阿里云OSS配置
aliyun:
  oss:
    endpoint: oss-cn-guangzhou.aliyuncs.com
    access-key-id: LTAI5tHVGvYw7twoVFyruB1H
    access-key-secret: r4d0EudzSvPfVMb9Zp0TfmsE32RXmN
    bucketname: dcloud-link
  • 新建配置类 (配置里面的横杠会,自动转驼峰)
@ConfigurationProperties(prefix = "aliyun.oss")
@Configuration
@Data
public class OSSConfig {


    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketname;
}
  • 开发controller

  • 开发service

@Service
@Slf4j
public class FileServiceImpl implements FileService {


    @Autowired
    private OSSConfig ossConfig;




    @Override
    public String uploadUserImg(MultipartFile file) {


        //获取相关配置
        String bucketname = ossConfig.getBucketname();
        String endpoint = ossConfig.getEndpoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);


        //获取原生文件名  xxx.jpg
        String originalFileName = file.getOriginalFilename();


        //JDK8的日期格式
        LocalDateTime ldt = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");


        //拼装路径,oss上存储的路径  user/2022/12/1/sdfdsafsdfdsf.jpg
        String folder = dtf.format(ldt);
        String fileName = CommonUtil.generateUUID();
        String extension = originalFileName.substring(originalFileName.lastIndexOf("."));


        // 在OSS上的bucket下创建 user 这个文件夹
        String newFileName = "user/"+folder+"/"+fileName+ extension;


        try {
            PutObjectResult putObjectResult = ossClient.putObject(bucketname,newFileName,file.getInputStream());
            //拼装返回路径
            if(putObjectResult != null){
                String imgUrl = "https://"+bucketname+"."+endpoint+"/"+newFileName;
                return imgUrl;
            }


        } catch (IOException e) {
            log.error("文件上传失败:{}",e);
        } finally {
            //oss关闭服务,不然会造成OOM
            ossClient.shutdown();
        }


        return null;
    }
}
第5集 账号微服务头像上传阿里云OSS接口和PostMan测试

简介: 账号微服务头像上传阿里云OSS接口和PostMan测试

  • 文件上传流程
    • 先上传文件,返回url地址,再和普通表单一并提交(推荐这种,更加灵活,失败率低)
    • 文件和普通表单一并提交(设计流程比较多,容易超时和失败)
  • 注意:默认SpringBoot最大文件上传是1M,大家测试的时候记得关注下
  • 开发controller
    • @requestPart注解 接收文件以及其他更为复杂的数据类型
   /**
       * 上传用户头像
       *
       * 默认文件大小 1M,超过会报错
       *
       * @param file
       * @return
       */
   @PostMapping(value = "upload")
   public JsonData uploadHeaderImg(@RequestPart("file") MultipartFile file){
  
          String result = fileService.uploadUserHeadImg(file);
  
          return result != null?JsonData.buildSuccess(result):JsonData.buildResult(BizCodeEnum.FILE_UPLOAD_USER_IMG_FAIL);
  
      }
 } catch (IOException e) {
        log.error("文件上传失败:{}",e);
    } finally {
        //oss关闭服务,不然会造成OOM
        ossClient.shutdown();
    }


    return null;
}

}




#### 第5集 账号微服务头像上传阿里云OSS接口和PostMan测试

**简介: 账号微服务头像上传阿里云OSS接口和PostMan测试**

- 文件上传流程
  - 先上传文件,返回url地址,再和普通表单一并提交(推荐这种,更加灵活,失败率低)
  - 文件和普通表单一并提交(设计流程比较多,容易超时和失败)
- 注意:默认SpringBoot最大文件上传是1M,大家测试的时候记得关注下
- 开发controller
  - @requestPart注解 接收文件以及其他更为复杂的数据类型

```java
   /**
       * 上传用户头像
       *
       * 默认文件大小 1M,超过会报错
       *
       * @param file
       * @return
       */
   @PostMapping(value = "upload")
   public JsonData uploadHeaderImg(@RequestPart("file") MultipartFile file){
  
          String result = fileService.uploadUserHeadImg(file);
  
          return result != null?JsonData.buildSuccess(result):JsonData.buildResult(BizCodeEnum.FILE_UPLOAD_USER_IMG_FAIL);
  
      }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1447538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐一门 MIT 的计算机入门课

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 计算机科学及编程导论在MIT的课程编号是6.00.1&#xff0c;是计算机…

Pytorch学习03_TensorBoard使用02

Opencv读取图片&#xff0c;获得numpy型数据类型 复制图片的相对路径 目前这种type不适用&#xff0c;考虑用numpy类型 安装opencv&#xff0c;在pytorch环境下 pip install opencv-python 导入numpy import numpy as np 将PIL类型的img转换为 NumPy 数组 img_arraynp.array…

VC++ 绘制折线学习

win32 有三个绘制折线的函数&#xff1b; Polyline&#xff0c;根据给定点数组绘制折线&#xff1b; PolylineTo&#xff0c;除了绘制也更新当前位置&#xff1b; PolyPolyline&#xff0c;绘制多条折线&#xff0c;第一个参数是点数组&#xff0c;第二个参数是一个数组、指…

【教学类-48-04】202402013“天干地支 六十一甲子”.

背景需求&#xff1a; 2024年是甲辰龙年。 “辛亥革命”“甲午海战”"戊戌变法”都有天干地支的身影。 参观历史建筑&#xff0c;不少书法碑刻上都是用天干地支进行年代记名 所以我用Python来制作60一甲子的所有天干地支组合 60一甲子 天干地支的排序 作者&#xff1a;阿…

【教程】Kotlin语言学习笔记(一)——认识Kotlin(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 文章目录 【Kotlin语言学习】系列文章一、Kotlin介绍二、学习路径 一、…

片上网络NoC(4)——直连拓扑

目录 一、前言 二、直连拓扑 三、总结 一、前言 本文中&#xff0c;我们将继续介绍片上网络中拓扑相关的内容&#xff0c;主要介绍直连拓扑&#xff0c;在此之前&#xff0c;我们已经介绍过了拓扑的指标&#xff0c;这将是继续阅读本文的基础&#xff0c;还没有了解相关内容…

GEE:CART(Classification and Regression Trees)回归教程(样本点、特征添加、训练、精度、参数优化)

作者:CSDN @ _养乐多_ 对于分类问题,这个输出通常是一个类别标签 ,而对于回归问题,输出通常是一个连续的数值。回归可以应用于多种场景,包括预测土壤PH值、土壤有机碳、土壤水分、碳密度、生物量、气温、海冰厚度、不透水面积百分比、植被覆盖度等。 本文将介绍在Google…

Spring Boot 笔记 012 创建接口_添加文章分类

1.1.1 实体类添加校验 package com.geji.pojo;import jakarta.validation.constraints.NotEmpty; import lombok.Data;import java.time.LocalDateTime;Data public class Category {private Integer id;//主键IDNotEmptyprivate String categoryName;//分类名称NotEmptypriva…

华为机考入门python3--(13)牛客13-句子逆序

分类&#xff1a;列表 知识点&#xff1a; 列表逆序&#xff08;和字符串逆序是一样的&#xff09; my_list[::-1] 题目来自【牛客】 def reverse_sentence(sentence): # 将输入的句子分割words sentence.split() # 将单词逆序排列 words words[::-1] # 将单词用空…

车载诊断协议DoIP系列 —— DoIP应用(Application)需求

车载诊断协议DoIP系列 —— DoIP应用(Application)需求 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一…

Java基于微信小程序的电子竞技信息交流平台

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Java并发基础:DelayQueue全面解析!

内容概要 DelayQueue类专为处理延迟任务设计&#xff0c;它允许开发者将任务与指定的延迟时间关联&#xff0c;并在任务到期时自动处理&#xff0c;从而避免了不必要的轮询和资源浪费&#xff0c;此外&#xff0c;DelayQueue内部基于优先队列实现&#xff0c;确保最先到期的任…

MySQL数据库⑧_索引(概念+理解+操作)

目录 1. 索引的概念和价值 1.1 索引的概念 1.2 索引的价值 2. 磁盘的概念 2.1 磁盘的结构 2.2 操作系统与磁盘交互的基本单位 2.3 MySQL与磁盘交互的基本单位 3. 索引的理解 3.1 主键索引现象和推导 3.2 索引采用的数据结构&#xff1a;B树 3.3 聚簇索引和非聚簇索引…

Java加密秘钥

1. Java加密秘钥 您可加密信息,使其避免未经授权的访问。您可通过Java密码技术对数据进行编码来加密。密码技术包含各种用于对网络上发送的数据进行编码和译码的加密秘钥。Java密码架构(JCA)和Java密码扩展(JCE)可让您在Java平台上执行密码。 Java加密秘钥是一连串控制数…

Vue--》深入学习Tailwind CSS掌握优雅而高效的前端样式开发

Tailwind CSS是一个非常强大且灵活的CSS框架&#xff0c;适用于开发者希望高度定制化界面样式的项目。今天博主就 Tailwind CSS 做一个简单介绍以及案例讲解&#xff0c;争取读者阅读文章后入门。 仅靠一篇文章博主也不可能将Tailwind CSS所有内容讲解的面面俱到&#xff0c;在…

【开源】JAVA+Vue+SpringBoot实现毕业生追踪系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登陆注册模块2.2 学生基本配置模块2.3 就业状况模块2.4 学历深造模块2.5 信息汇总分析模块2.6 校友论坛模块 三、系统设计3.1 用例设计3.2 实体设计 四、系统展示五、核心代码5.1 查询我的就业状况5.2 初始化就业状况5.…

线性代数的本质 2 线性组合、张成的空间、基

基于3Blue1Brown视频的笔记 一种新的看待方式 对于一个向量&#xff0c;比如说&#xff0c;如何看待其中的3和-2&#xff1f; 一开始&#xff0c;我们往往将其看作长度&#xff08;从向量的首走到尾部&#xff0c;分别在x和y上走的长度&#xff09;。 在有了数乘后&#xff0…

第二节:轻松玩转书生·浦语大模型趣味Demo

参考教程&#xff1a;https://github.com/InternLM/tutorial/blob/main/helloworld/hello_world.md InternLM-Chat-7B 智能对话 Demo 终端运行 web demo 运行 1.首先启动服务&#xff1a; cd /root/code/InternLM streamlit run web_demo.py --server.address 127.0.0.1 --…

基于matlab的密度散点图绘制

1. 什么是密度散点图&#xff1f; 密度散点图就是在普通散点图的基础上&#xff0c;基于样本点一定范围的样本数计算该样本点的密度&#xff0c;以不同的颜色来显示样本点密度的大小&#xff0c;这样能够直观的显示出数据的空间聚集情况&#xff0c;如下图分别是二维和三维密度…

2024年世界听力日活动的主题是什么?

改变思维模式&#xff1a;让所有人的耳和听力保健成为现实&#xff01; Let’s make ear and hearing care a reality for all! 据 世界卫生组织 报道&#xff1a;在全球范围内&#xff0c;超过 80% 的耳和听力保健需求仍未得到满足 &#xff1b; 未得到解决的听力损失每…