概述

传统的 Maven项目一般将需要被复用的组件做成 Module来进行管理,以便二次调用;而在 Spring Boot项目中我们则可以使用更加优雅的 Spring Boot Starter来完成这一切。

这个开箱即用的魔法特性很大程度上来源于各式各样 Spring Boot Starter的加持,而且随着版本的迭代 Starter家族成员日益庞大,而且各种优秀开源作者也提供了很多非常好用的Spring Boot Starter。

本文尝试自定义一个Spring Boot Starter用于图片链接转换BASE64编码。

构建过程

  1. 在GItHub上创建base64util-spring-boot-starter项目,然后clone下来本地进行开发。

  1. pom.xml文件配置如下
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
</parent>
<groupId>com.github.yehongzhi</groupId>
<artifactId>base64util-spring-boot-starter</artifactId>
<version>0.0.1</version>
<dependencies>
    <!-- 引入SpringBoot自动配置jar包 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
</dependencies>
  1. 业务代码
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author Ye Hongzhi
 * @program Base64Util
 * @description
 * @date 2020-02-17 14:04
 **/
public class Base64Util {

    /**
     * 本地图片转为BASE64编码
     *
     * @param imgFile 本地图片地址
     * @return BASE64 解码后的字符串编码
     * @description: 根据图片地址转换为base64编码字符串
     * @author: Ye Hongzhi
     * @createTime: 2020/02/17
     */
    public static String getImageFile(String imgFile) {
        byte[] data = null;
        try (InputStream inputStream = new FileInputStream(imgFile)) {
            data = new byte[inputStream.available()];
            int length = inputStream.read(data);
            if (length == -1) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 加密
        BASE64Encoder encoder = new BASE64Encoder();
        if (data != null) {
            return encoder.encode(data);
        } else {
            return null;
        }
    }

    public static String image2Base64(String imgUrl) throws Exception {
        URL url = new URL(imgUrl);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        try(InputStream inputStream = urlConnection.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            urlConnection.connect();
            byte[] buffer = new byte[1024];
            int len;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = inputStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
                baos.write(buffer, 0, len);
            }
            // 对字节数组Base64编码
            return Base64.encode(baos.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return imgUrl;
    }

    /**
     * BASE64编码转为图片
     * 注意:"data:image/jpeg;base64," 解码之前得去掉。
     *
     * @param imgStr base64编码字符串
     * @param path   图片路径-具体到文件
     * @return 是否转换成功
     * @description: 将base64编码字符串转换为图片
     * @author: Ye Hongzhi
     * @createTime: 2020/02/17
     */
    public static boolean generateImage(String imgStr, String path) {
        if (imgStr == null) {
            return false;
        }
        try (OutputStream out = new FileOutputStream(path)) {
            BASE64Decoder decoder = new BASE64Decoder();
            // 解密
            byte[] b = decoder.decodeBuffer(imgStr);
            // 处理数据
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
  1. 创建一个service调用,这里为了简单,就不定义为接口的形式
public class Base64Service {

    /**
     * 本地图片转为BASE64编码
     */
    public String getImageFile(String imgFile) {
        return Base64Util.getImageFile(imgFile);
    }

    /**
     * BASE64编码转为图片
     * */
    public boolean generateImage(String imgStr, String path) {
        return Base64Util.generateImage(imgStr,path);
    }
    /**
     * 在线图片转为BASE64编码
     * */
    public String image2Base64(String imgUrl) throws Exception{
        return Base64Util.image2Base64(imgUrl);
    }
}
  1. 关键的一步,使用配置类,把service定义成bean,加入到spring容器中管理
@Configuration
public class Base64AutoConfiguration {
    @Bean
    Base64Service base64Service(){
        return new Base64Service();
    }
}
  1. 最关键一步在于需要在resources文件夹下创建META-INF/spring.factoriesspring.factories里的代码如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lovebilibili.me.config.Base64AutoConfiguration

这一步是重点,因为Spring Boot应用在启动过程中会通过 SpringFactoriesLoader 加载所有 META-INF/spring.factories 文件,通过一系列的处理流程最终将 spring.factories 文件中的定义的各种 beans 装载入 ApplicationContext容器。

至此,自定义的用于base64转码工具的spring-boot-starter就完成了

可以通过使用maven命令mvn install打包,传到私有/公有Maven仓库使用。

形成一个公共的模块,供有需要的项目使用。

  1. 完成后把代码推送到Github仓库中,方便以后继续优化。

测试

  1. 在其他项目中的pom文件加入以下依赖:
<dependency>
    <groupId>com.github.yehongzhi</groupId>
    <artifactId>base64util-spring-boot-starter</artifactId>
    <version>0.0.1</version>
</dependency>
  1. 在Controller层中,我们可以引入base64Service。
@Resource
private Base64Service base64Service;
  1. 然后在Controller层中的@RequestMapping对应的方法中使用
//把在线图片转为BASE64编码
String base64 = base64Service.image2Base64(imgUrl);

后记

能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!



java SpringBoot

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!