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

news/2024/12/16 22:24:55/文章来源:https://www.cnblogs.com/euler-blog/p/18611246

图片缩略图功能

需要对图片生产缩略图,压缩并保存到不同的介质中。输入端可能是本地图片,也可能是网络图片。保存的位置可能是本地,也有可能是第三方的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@Getterprotected 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 {@Autowiredprotected FileServerConfig fileServerConfig;protected String bucketName = "thumb_images"; //file server bucketeprotected 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@AllArgsConstructorclass 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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一款渗透测试信息收集集成工具--mitan密探

本工具仅供安全测试人员运用于授权测试, 禁止用于未授权测试, 违者责任自负。作者及本公众号相关负责人不对您使用该工具所产生的任何后果负任何法律责任,在扫描模块使用多线程,在测试过程中根据目标的实际情况进行调整,切勿进行大线程低延时的大规模快速扫描,以免对目标服务…

最大网络流基本概念

1. 基本概念 1.1 流网络,不考虑反向边如果存在反向边也没事,不如有u->v和v->u两条边,那么就可以新加入一个点 p,u->v,v->p,p->u,转化为这三条边 1.2 可行流,不考虑反向边 1.2.1 两个条件:容量限制、流量守恒 容量限制:每条边流的不能超过这条边的权值 流量守…

sqli-labs

sqli-labs Less-1 基于错误的GET单引号字符型注入 index.php分析error_reporting(0); 不反馈错误 isset($_GET[id]) 检查($ _GET[id])参数是否设置 LIMIT 0,1 从第一条开始记录,只取一条记录1.推测闭合方式?id=1\输入\ ,后面是 ,推测是单引号闭合 输入 ?id=1 报错 输入 ?…

一文读懂:AI创业和投融资领域常见专有名词缩写详解

=== 预计悦读时间:3分钟 | 📚字数:约1000字——知识满满,不虚此行!🤔为什么你需要这篇神器? 就像由算法推荐给各位好奇的同学一样,我也被这些术语所困扰,想象一下,你正沉浸在一场关于AI的精彩演讲或者播客中,突然,一个神秘的英文缩写从嘉宾口中飞出,像是外星语言般让你瞬…

Simplex Method (单纯形方法)

学习目标:在本节中,我们将学习使用\(\textbf{单纯形法}\)解决线性规划最大化问题:(In this section, we will learn to solve linear programming maximization problems using the Simplex Method:)识别并建立标准的最大化形式的线性规划 (Identify and set up a linear pr…

《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解

《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解@目录二、高级篇(大厂进阶)4.Docker网络4.1Docker网络是什么4.2常用基本命令4.3能干嘛4.4网络模式4.4.1总体介绍4.4.2容器实例内默认网络IP生产规则4.4.3案例说明…

实验6 C++

任务四:Vector.hpp #pragma once #include <iostream> #include <stdexcept>using namespace std;template <typename T> class Vector { public:Vector(int n, int p = 0);Vector(const Vector<T> &v);~Vector();int get_size() const;T& a…

Docker安装Redis和Elasticsearch

本章将和大家分享在Docker中如何安装Redis和Elasticsearch。本章将和大家分享在Docker中如何安装Redis和Elasticsearch。废话不多说,下面我们直接进入主题。 一、Docker安装Redis 1、拉取最新版的 redis 镜像docker pull redis2、查看本地镜像docker images3、从官网获取 redi…

Redis应用—4.在库存里的应用

大纲 1.库存模块设计 2.库存缓存分片和渐进式同步方案 3.基于缓存分片的下单库存扣减方案 4.商品库存设置流程与异步落库的实现 6.库存入库时"缓存分片写入 + 渐进式写入 + 写入失败进行MQ补偿"的实现 7.库存扣减时"基于库存分片依次扣减 + 合并扣减 + 扣不了返…

Learn learn Cython

[SCTF ez_cython]简单分析需要调用一个cy库,找到文件"cy.cp38-win_amd64.pyd"pyd文件生成:编写pyx文件 \#test.pyx def say_hello_world(name): print("Hello world" % name)编写setup \#setup.py from distutils.core import setup from Cython.Build imp…

24.10.31 补充日志分析以及打包压缩

uniq 作用:去重,一般与sort搭配使用,单用uniq,是合并相邻两行相同内容 参数: -c #统计重复行的次数 eg:[root@oldboyedu ~]# cat uniq.txt oldboy lidao lidao lidao lidao oldboy oldboy lidao oldboy pldboy [root@oldboyedu ~]# uniq uniq.txt oldboy lidao oldboy l…

k8s阶段08 k8s扩展(kubectl插件), 调度器(亲和调度, 污点和容忍度调度), 集群日常管理, 高可用集群部署, 集群版本升级

Kubernetes 扩展机制 扩展Kubernetes1.kubectl插件 2.API Server扩展身份认证、鉴权和动态准入控制相关插件 3.API扩展,以支持更多的资源类型 4.调度器扩展以支持更多调度算法 5.控制器扩展以支持更多的Controller或Operator 6.网络插件,扩展Kubelet以配置Pod网络 7.设备插件…