如何在Java项目中使用自定义序列化器处理URL

在Java开发中,处理和序列化URL是一个常见的需求,尤其是在涉及到图像资源时。如果项目需要根据特定条件处理图像URL(如添加前缀),可以自定义一个序列化器来简化这一过程。

本文将介绍如何创建一个自定义的ImgJsonSerializer类,处理单个URL和URL列表,并在序列化过程中动态添加前缀。

1. 项目背景

在许多项目中,图像资源的URL可能存储为相对路径或者完整的URL。如果你的应用程序需要统一处理这些URL,可能需要在序列化JSON时添加一个域名或路径前缀。这种处理可以在序列化时自动完成,无需在业务逻辑中重复代码。

2. 需求描述

我们需要一个自定义的JSON序列化器ImgJsonSerializer,能够处理以下两种情况:

  1. 单个URL字符串:对单个图像URL进行序列化,如果URL是相对路径,则添加一个前缀。
  2. URL字符串列表:对URL列表进行序列化,遍历列表并对每个URL进行前缀处理。

3. 自定义序列化器的实现

我们将使用Jackson库自定义序列化器。首先,确保项目中已经添加了Jackson的相关依赖。如果没有,请自行添加。

接下来,创建自定义序列化器ImgJsonSerializer

点击查看MinioProperties代码

"""
application.yml配置如下
minio:
  endpoint: http://localhost:9000  # MinIO服务器的URL
  access-key: adminminio       # 访问密钥
  secret-key: adminminio      # 密钥密码
  bucket-name: works     # 默认的Bucket名称
  secure: false          # 是否使用HTTPS(如果使用HTTPS,请设置为true)
"""
package com.echo.common.minio;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {

    private String endpoint;

    private String accessKey;

    private String secretKey;
    
    private String bucketName;

    private String secure;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

因为我这使用的是Minio对象存储,配置了MinioProperties类

package com.echo.common.ImgJson;

import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.echo.common.minio.MinioProperties;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;

@Component
public class ImgJsonSerializer extends JsonSerializer<Object> {

    @Autowired
    private MinioProperties properties;

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeString(StrUtil.EMPTY);
            return;
        }

        if (value instanceof String) {
            String img = (String) value;
            if (StrUtil.isBlank(img)) {
                gen.writeString(StrUtil.EMPTY);
            } else if (ReUtil.isMatch(PatternPool.URL_HTTP, img)) {
                gen.writeString(img);
            } else {
                gen.writeString(properties.getEndpoint() + img);
            }
        } else if (value instanceof List<?> list) {
            gen.writeStartArray();
            for (Object item : list) {
                if (item instanceof String img) {
                    if (StrUtil.isBlank(img)) {
                        gen.writeString(StrUtil.EMPTY);
                    } else if (ReUtil.isMatch(PatternPool.URL_HTTP, img)) {
                        gen.writeString(img);
                    } else {
                        gen.writeString(properties.getEndpoint() + img);
                    }
                }
            }
            gen.writeEndArray();
        } else {
            throw new IllegalArgumentException("Unsupported value type: " + value.getClass().getName());
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.

4. 如何使用自定义序列化器

在实体类中,将@JsonSerialize(using = ImgJsonSerializer.class)注解添加到需要序列化的字段上。无论是单个字符串还是字符串列表,ImgJsonSerializer将根据实际类型进行处理。

对于单个URL字段

@JsonSerialize(using = ImgJsonSerializer.class)
private String imgUrl;
  • 1.
  • 2.

对于URL列表字段

@JsonSerialize(using = ImgJsonSerializer.class)
private List<String> imgUrls;
  • 1.
  • 2.

5. 测试和验证

确保MinioProperties类配置了正确的前缀,并且在应用程序中正确注入。然后你可以创建测试数据,序列化对象,并验证输出的JSON是否符合预期。

示例测试代码

public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new SimpleModule().addSerializer(Object.class, new ImgJsonSerializer()));

    MyEntity entity = new MyEntity();
    entity.setImgUrl("image.jpg"); // 假设前缀是 http://localhost:9000/
    entity.setImgUrls(Arrays.asList("image1.jpg", "http://example.com/image2.jpg"));

    String json = mapper.writeValueAsString(entity);
    System.out.println(json);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

6. 总结

通过创建自定义的ImgJsonSerializer,我们可以灵活地处理单个URL和URL列表,并在序列化过程中添加必要的前缀。这种方法使得处理图像URL变得更加简洁和统一,有助于保持代码的整洁性和可维护性。