前端分隔符传递数据给后端的通用方案

一、背景

在一些特定场景下需要前端将多个字符串数据用分隔符拼接后传给后端,然后后端通过分隔符拆分字符串然后进行处理。

如果是dubbo调用那没有问题,直接传对象就行,关键是需要通过HTTP的GET方法传入。

但是如何选取这个分隔符非常伤脑筋。

比如可以选择常见的逗号,或者换行符等,在字符串里也很容易出现,肿么办?肿么办?肿么办?

二、方案

2.1 采用ASCII码特定的控制字符

由于回车符、换行符很常见,可见字符更容易重复,我们为啥不选择其他非常见的用户绝对不可能输入的字符呢?
http://ascii.911cha.com/

 

通过查ASCII表,我们找到了RS 记录分隔符、和US单元分隔符,而我们的场景符合是传递『记录』,因此选取RS更适合。

前端使用

String.fromCharCode(30) 获取记录分隔符,用来分隔多条记录

 

后端模拟前端的拼接和后端的解析

对应工具类中的内容:

 

2.2  Base64加密后加非Base64的字符作为分隔符

编码介绍:http://www.ruanyifeng.com/blog/2008/06/base64.html

 

居然选择分隔符容易重复,如果我们把原始的字符串转成Base64编码,然后采用非Base64编码的字符作为分隔符,这样不管之前的字符串是何种形式,甚至是上述的记录分隔符,一律被编码成了base64形式,不可能出现非base64中的字符,我们就可以放心的将其当做分隔符了。

想到这里我们开始写代码

对应的运行结果

 

三、 方法对比

第一种方法简单,且不需要转化,几乎不太可能重复,是一个非常不错的方案。

第二种基于base64的加密解密, 需要加密解密,且传输时字节会增长,但是最安全。

 

三、工具类

我们把这个逻辑封装成工具类,方便使用

import org.springframework.util.Base64Utils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 记录传递工具类
 *
 * @author liuwangyangedu@163.com
 */
public class RecordDeliverUtil {
    /**
     * ASCII的记录分隔符
     */
    private static final char RS = 0x1E;

    /**
     * ASCII的记录分隔符字符串形式
     */
    private static final String RS_STRING = String.valueOf(RS);

    /**
     * BASE64编码记录的分隔符
     */
    private static final String BASE64_SEPARATOR = "|";

    /**
     * BASE64编码记录的分隔符个正则形式
     */
    private static final String BASE64_SEPARATOR_REG = "\\|";

    /**
     * 通过记录分隔符拼接数据的构造
     */
    public static <T> String contactRecordsWithRS(T data, Function<T, List<String>> function) {
        if (data == null) {
            return null;
        }
        return String.join(RS_STRING, function.apply(data));
    }

    /**
     * 通过记录分隔符拼接数据的解析
     */
    public static String[] getOriginRecordSeparateWithRS(String dataWithRs) {
        if (dataWithRs == null) {
            return null;
        }
        return dataWithRs.split(RS_STRING);
    }

    /**
     * 通过base64编码加密每个记录,并且通过BASE64_SEPARATOR_REG拼接
     */
    public static <T> String encodeBase64WithSeparator(T data, Function<T, List<String>> function) {
        if (data == null) {
            return null;
        }
        List<String> records = function.apply(data);
        if (CollectionUtils.isEmpty(records)) {
            return null;
        }
        return records.stream().map(record -> Base64Utils.encodeToString(record.getBytes())).collect(Collectors.joining(BASE64_SEPARATOR));
    }

    /**
     * 解析base64编码并且通过BASE64_SEPARATOR_REG分割
     */
    public static List<String> decodeBase64WithSeparator(String dataWithBase64WithSeparator) {
        if (dataWithBase64WithSeparator == null) {
            return null;
        }
        // 判断是否有分隔符
        if (!dataWithBase64WithSeparator.contains(BASE64_SEPARATOR)) {
            return Collections.singletonList(dataWithBase64WithSeparator);
        }
        // 通过分割
        String[] resultList = dataWithBase64WithSeparator.split(BASE64_SEPARATOR_REG);
        if (ArrayUtils.isEmpty(resultList)) {
            return new ArrayList<>(0);
        }
        // base64解码
        return Arrays.stream(resultList).map(s -> new String(Base64Utils.decodeFromString(s))).collect(Collectors.toList());
    }
}

 

四、思考

类似问题的主要思考角度是

  1. 对字节、字符和字符串的深刻理解
  2. 尝试问题转化,既然找不到不常用的字符,那就去找用户不可能输入的非可见字符,如果还有可能发生,我们利用base64编码就不可能再重复。

另外感谢“无聊之园”的建议

还需要思考的问题是:如果有安全性需求,可能还得考虑加入其他非对称加密算法。

不过大多数前端直接传给后端用分隔符分隔的场景,没有加密的需要,具体根据自己的场景来。

 

如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。

原创作品,转载请注明出处:https://blog.csdn.net/w605283073/article/details/90318627

另外欢迎加入我的知识星球,知识星球ID:15165241 一起交流学习。

https://t.zsxq.com/Z3bAiea  申请时标注来自CSDN。

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明明如月学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值