首页 > 其他分享 >实际项目中不一样的《桥接模式》

实际项目中不一样的《桥接模式》

时间:2024-12-16 22:31:59浏览次数:3  
标签:java 桥接 模式 实际 supremind new import com public

图片缩略图功能

需要对图片生产缩略图,压缩并保存到不同的介质中。输入端可能是本地图片,也可能是网络图片。保存的位置可能是本地,也有可能是第三方的minio、阿里云oss、七牛云oss。并且这些途径可能随时扩展。为了设计的灵活性,这里就要把输入可输出抽象出来,应用层通过抽象层结偶。这样的抽象和实现分离,实现层可以自由扩展,而应用层依赖于抽象层相对稳定。

整体结构是这样的

image

代码结构是这样的

image

整体实现是这样的

ThumbLoad 图片的输入信息⬇︎⬇︎⬇︎

点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import com.supremind.modules.news.entity.ImageActionVo;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotBlank;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 图片载入
 * 1)图片载入过程不涉及到异常处理,异常自行处理,一切结果以isSuccess为准,具体消息去message
 */
@Slf4j
public abstract class ThumbLoad {
    @Setter
    @Getter
    protected ThumbSave thumbSave;

    public ThumbLoad(ThumbSave thumbSave) {
        this.thumbSave = thumbSave;
    }

    @Getter
    @Setter
    /*load载入结果,默认为false,免去每次异常都赋值.只有操作成功后进行赋值true*/
    protected Boolean isSuccess=false;

    @Getter
    @Setter
    /*错误消息提醒*/
    protected String message =null;

    public abstract ImageActionVo thumb(String filePath);

    /**
     * 验证网络资源是否可以访问
     * @param url 网络资源地址
     * @param checkIsImage 是否强制检测为image类型的资源
     * @return
     */
    protected Boolean checkUrlIsAccess(@NotBlank String url, Boolean checkIsImage){
        log.debug("checkUrlIsAccess start ...");
        log.debug("url:{}",url);
        URL netUrl = null;
        HttpURLConnection httpURLConnection =null;
        Boolean result = true;
        try {
            netUrl = new URL(url);
            httpURLConnection = (HttpURLConnection)netUrl.openConnection();
            httpURLConnection.setConnectTimeout(2000);
            if (httpURLConnection.getResponseCode()==200) {
                String contentType = httpURLConnection.getContentType();
                if (checkIsImage){
                    if (!contentType.split("/")[0].equals("image")) {
                        result = false;
                    }
                }

            }else{
                result = false;
            }
        }catch (Exception e){
            log.error("e :{}", e);
            result = false;
        }finally {
            if (httpURLConnection != null) {
                httpURLConnection.disconnect();
            }
        }
        log.debug("checkUrlIsAccess end.");
        return result;
    }

}

ThumbSave 图片的输入信息⬇︎⬇︎⬇︎

点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import com.supremind.config.FileServerConfig;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.InputStream;

/**
 * 文件保存
 * 1)文件保存到fileServer ,thumburi是fileserver返回的可以直接访问的地址
 * 2)文件保存本地,thumburi表示本地文件的完整路径
 * 注:
 * 1.文件保存类型取决与具体实现,但结构保持一致。最外层控制逻辑,是isSuccess.
 * 2.为了实现最大程度的复用,这里选择使用inputStream 进行对接saveImage.
 * 3.在扩展save策略时,注意异常处理,结果都从ImageSaveResult体现说明
 */
public abstract class ThumbSave {

    @Autowired
    protected FileServerConfig fileServerConfig;

    protected String bucketName = "thumb_images"; //file server buckete
    protected String saveUri; //处理后的文件保存路
    protected Integer width; //图片压缩宽度
    protected Integer height; //图片压缩高度

    public ThumbSave(String saveUri, Integer width, Integer height) {
        this.saveUri = saveUri;
        this.width = width;
        this.height = height;
    }

    abstract ImageSaveResult save(InputStream imageInputStream);

    @Data
    @AllArgsConstructor
    class ImageSaveResult {
        private Boolean isSuccess = false; //操作是否成功
        private String thumbUri; //缩略图文件地址
        private String msg; //消息
    }


}

下面是具体实现
LocalThumbSave 本地保存⬇︎⬇︎⬇︎

点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;

import java.io.IOException;
import java.io.InputStream;

/**
 * 本地保存文件
 */
@Slf4j
public class LocalThumbSave extends ThumbSave {
    public LocalThumbSave(String saveUri, Integer width, Integer height) {
        super(saveUri, width, height);
    }

    public ImageSaveResult save(InputStream imageInputStream) {
        try {
            Thumbnails.of(imageInputStream).size(width,height).toFile(saveUri);
            return new ImageSaveResult(true,saveUri,null);
        } catch (IOException e) {
            log.error("Thumbnails toFiles error:{}",e);
            return new ImageSaveResult(false, null, e.getMessage());
        }
    }
}

FileServerThumbSave file server保存文件(这里的fileserver又做了一层抽象,可以接入不同的第三方)⬇︎⬇︎⬇︎

点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import com.supremind.common.SpringContextUtil;
import com.supremind.common.utils.R;
import com.supremind.modules.news.feign.FileFeignClient;
import com.supremind.modules.news.service.impl.G;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * file server保存文件
 */
@Slf4j
public class FileServerThumbSave extends ThumbSave {
    public FileServerThumbSave(String saveUri, Integer width, Integer height) {
        super(saveUri, width, height);
    }

    public ImageSaveResult save(final InputStream imageInputStream) {
        log.debug("FileServerSaveImage start ......");
        try {
            @Cleanup ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Thumbnails.of(imageInputStream).size(width,height).toOutputStream(outputStream);
            @Cleanup ByteArrayInputStream swapStream = new ByteArrayInputStream(outputStream.toByteArray());
            FileFeignClient fileFeignClient = SpringContextUtil.getBean(FileFeignClient.class);
            MockMultipartFile mockMultipartFile = new MockMultipartFile("file.jpg","file.jpg", MediaType.IMAGE_JPEG_VALUE,swapStream);
            R image = fileFeignClient.upload(bucketName, mockMultipartFile);
            log.debug("image :{}", image);
            if (G.isSuccess(image)) {
                return new ImageSaveResult(true, image.get("data").toString(), null);
            }else{
                return new ImageSaveResult(false, null, G.getMsg(image));
            }
        } catch (IOException e) {
            log.error("FileServerSaveImage IOException :{}",e);
            return new ImageSaveResult(false, null, e.getMessage());
        }finally {
            log.debug("FileServerSaveImage end");
        }
    }
}

UriThumbLoad 读取本地资源文件⬇︎⬇︎⬇︎

点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import com.supremind.modules.news.entity.ImageActionVo;
import com.supremind.modules.news.enums.ErrorMsgEnum;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 本地文件载入
 */
@Slf4j
public class UriThumbLoad extends ThumbLoad {
    public UriThumbLoad(ThumbSave thumbSave) {
        super(thumbSave);
    }

    public ImageActionVo thumb(String filePath) {
        //文件检查
        File file = new File(filePath);
        if (!file.exists()) {
            return new ImageActionVo(filePath,false,null, ErrorMsgEnum.FILE_NOT_FIND.getValue());
        }

        try {
            @Cleanup InputStream inputStream = new FileInputStream(file);
            ThumbSave.ImageSaveResult save = thumbSave.save(inputStream);
            return new ImageActionVo(filePath, save.getIsSuccess(), save.getThumbUri(), save.getMsg());
        } catch (Exception e) {
            log.error("FileNotFoundException :{}",e);
            return new ImageActionVo(filePath,false,null,e.getMessage());
        }

    }

}

UrlThumbLoad 读取网络资源文件⬇︎⬇︎⬇︎
点击查看代码
package com.supremind.modules.news.service.impl.thumb;

import com.supremind.modules.news.entity.ImageActionVo;
import com.supremind.modules.news.enums.ErrorMsgEnum;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 网络图片载入
 */
@Slf4j
public class UrlThumbLoad extends ThumbLoad {
    public UrlThumbLoad(ThumbSave thumbSave) {
        super(thumbSave);
    }

    public ImageActionVo thumb(String filePath) {
        HttpURLConnection urlConnection;
        if (!checkUrlIsAccess(filePath,true)) {
            return new ImageActionVo(filePath, false, null, ErrorMsgEnum.FILE_NOT_ACCESS.getValue());
        }
        try {
            URL url = new URL(filePath);
            urlConnection = (HttpURLConnection)url.openConnection();
            urlConnection.setConnectTimeout(5000);
            @Cleanup InputStream inputStream = urlConnection.getInputStream();
            ThumbSave.ImageSaveResult save = thumbSave.save(inputStream);
            return new ImageActionVo(filePath, save.getIsSuccess(), save.getThumbUri(),save.getMsg());
        } catch (Exception e) {
            log.error("FileNotFoundException :{}",e);
            return new ImageActionVo(filePath,false,null,e.getMessage());
        }
    }

}

文件压缩也是同样的实现

image

标签:java,桥接,模式,实际,supremind,new,import,com,public
From: https://www.cnblogs.com/euler-blog/p/18611246

相关文章

  • java观察者模式多人上线下线2.0
    packageorg.wangbiao.es.restclient.util.onlin;importjava.util.Observable;importjava.util.Observer;/***接受者*/publicclassMyObserverimplementsObserver,Player{privateStringname;publicMyObserver(Stringname){this.name......
  • 《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、
    @目录二、高级篇(大厂进阶)4.Docker网络4.1Docker网络是什么4.2常用基本命令4.3能干嘛4.4网络模式4.4.1总体介绍4.4.2容器实例内默认网络IP生产规则4.4.3案例说明bridgehostnonecontainer自定义网络4.5Docker平台架构图解本人其他相关文章链接二、高级篇(大厂进阶)4.Docker网络......
  • 实际项目中不一样的《建造者模式》
    builder真的是为了创建复杂的对象而产生的,实际使用场景更侧重复杂对象的构建。记录一下ES检索复杂对象场景的使用:首先是抽象层的builder点击查看代码//构建查询where条件interfaceBuildWhere{QueryBuilderbuild();publicstaticvoidsetDelWhere......
  • 使用方法重载实现Python访问者模式
    Python上的访问者模式,看了一下网上其他人的例子,一般都是类似下面的代码。fromabcimportABC,abstractmethod#抽象访问者classAnimalVisitor(ABC):@abstractmethoddefvisit_dog(self,dog:"Dog"):pass@abstractmethodd......
  • 读书笔记:C++20设计模式
    C++20设计模式:可复用的面向对象设计方法:reusableapproachesforobject-orientedsoftwaredesign,secondedition(俄)德米特里·内斯特鲁克(DmitriNesteruk)著,冯强国译译者序你需要有C++基础,了解C++新特性(lambda,auto,override)第1章引论1《设计模式:可复用面向对象软件......
  • 设计模式之工厂模式
    工厂模式目录定义分类工厂模式核心角色简单工厂模式定义特点优点缺点应用场景代码实现工厂方法模式定义特点优点缺点应用场景代码实现抽象工厂模式定义特点优点缺点应用场景代码实现工厂模式小结定义工厂模式属于创建型设计模式,它用于解耦对象的创建和使用。通......
  • seata TCC 模式 快速demo笔记
    之前笔记整理过AT模式:分布式事务seata(AT)与nacos整合-笔记2-CSDN博客对于TCC模式是类似的。相对于AT更灵活。1TCC模式原理官方介绍:SeataTCC模式|ApacheSeata这个介绍比较简单,demo可以快速体验下。实际落地根据自己业务模式来考虑,核心关注点有3个:幂等、允许空回......
  • 国标GB28181视频平台EasyCVR网络传输技巧:使用无源光网络传输做监控架构的实际表现如何
    在现代通信网络的快速发展中,PON(PassiveOpticalNetwork,无源光网络)技术因其高带宽、低成本和易于扩展的特点,成为了构建新一代接入网的关键技术。本文将详细介绍PON设备的网络规划,包括OLT(OpticalLineTerminal,光线路终端)的部署、分光器的部署、ONU(OpticalNetworkUnit,光网络单元)......
  • 大话《权限设计》全篇,领略不同设计模式的魅力
    说明  该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。   该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。   说明:OverallAuth2.0是一个简单、易懂、功能强大的权限+可视化流程管理系统。友情提醒:本篇文章是属于系......
  • Sigrity System Explorer ViaWizard模式进行过孔建模和仿真分析操作指导
    SigritySystemExplorerViaWizard模式进行过孔建模和仿真分析操作指导SigritySystemExplorerViaWizard模式可以用于过孔建模用于前仿真分析,建模好过孔进行3D全波仿真分析评估过孔结构的性能,同样以差分模板为例具体操作如下双击打开SystemExplorer软件界面打开如......