Base64是一种根据ASCII码来进行加密的可逆算法,这类算法简单来说,就等于将每个字符对应一个特定的字符(常常是根据进制进行匹配),一一对应,特别像电台密码本,因为每个字符都必须要加密,加密比较笨重。
加密
解密
/** 工具类实现代码 **/
public class BASE64Util {
private static final Map<Integer, Character> base64CharMap = new HashMap<>();
private static final String base64CharString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static BASE64Util instance;
private BASE64Util() {
for (int i = 0; i < base64CharString.length(); i++) {
char c = base64CharString.charAt(i);
base64CharMap.put(new Integer(i), new Character(c));
}
}
public static BASE64Util getInstance() {
if (instance == null) {
synchronized (BASE64Util.class) {
if (instance == null) {
instance = new BASE64Util();
}
}
}
return instance;
}
/**
* This method is used to encode a normal string to base64 string @param
* origin The String to be encoded @return The String after encoded.
*/
public String encode(String origin) {
if (origin == null) {
return null;
}
if (origin.length() == 0) {
return "";
}
int length = origin.length();
String binaryString = "";
// to binary String
for (int i = 0; i < length; i++) {
int ascii = origin.charAt(i);
String binaryCharString = Integer.toBinaryString(ascii);
while (binaryCharString.length() < 8) {
binaryCharString = "0" + binaryCharString;
}
binaryString += binaryCharString;
}
// to base64 index
int beginIndex = 0;
int endIndex = beginIndex + 6;
String base64BinaryString = "";
String charString = "";
while ((base64BinaryString = binaryString.substring(beginIndex, endIndex)).length() > 0) {
// if length is less than 6, add "0".
while (base64BinaryString.length() < 6) {
base64BinaryString += "0";
}
int index = Integer.parseInt(base64BinaryString, 2);
char base64Char = base64CharMap.get(index);
charString = charString + base64Char;
beginIndex += 6;
endIndex += 6;
if (endIndex >= binaryString.length()) {
endIndex = binaryString.length();
}
if (endIndex < beginIndex) {
break;
}
}
if (length % 3 == 2) {
charString += "=";
}
if (length % 3 == 1) {
charString += "==";
}
return charString;
}
public String decode(String encodedString) {
if (encodedString == null) {
return null;
}
if (encodedString.length() == 0) {
return "";
}
// get origin base64 String
String origin = encodedString.substring(0, encodedString.indexOf("="));
String equals = encodedString.substring(encodedString.indexOf("="));
String binaryString = "";
// convert base64 string to binary string
for (int i = 0; i < origin.length(); i++) {
char c = origin.charAt(i);
int ascii = base64CharString.indexOf(c);
String binaryCharString = Integer.toBinaryString(ascii);
while (binaryCharString.length() < 6) {
binaryCharString = "0" + binaryCharString;
}
binaryString += binaryCharString;
}
// the encoded string has 1 "=", means that the binary string has append
// 2 "0"
if (equals.length() == 1) {
binaryString = binaryString.substring(0, binaryString.length() - 2);
}
// the encoded string has 2 "=", means that the binary string has append
// 4 "0"
if (equals.length() == 2) {
binaryString = binaryString.substring(0, binaryString.length() - 4);
}
// convert to String
String charString = "";
String resultString = "";
int beginIndex = 0;
int endIndex = beginIndex + 8;
while ((charString = binaryString.substring(beginIndex, endIndex)).length() == 8) {
int ascii = Integer.parseInt(charString, 2);
resultString += (char) ascii;
beginIndex += 8;
endIndex += 8;
if (endIndex > binaryString.length()) {
break;
}
}
return resultString;
}
}
“发送确认”模式:即生产者通过MQ发送消息后,MQ需要将“已发送成功/失败”反馈给生产者,告知生产者消息已投递成功,此方式可确保消息正确地发送至RabbitMQ
“消费确认”模式:即消费者监听到MQ中队列的消息并执行完对应的业务逻辑后,需要发送“消息已被成功监听、消费”反馈给MQ,此方式可保证接收方正确接收并消费了消息,消费成功后消息将从队列中移除
“避免消息重复投递”:生产者在生产消息时,MQ内部会针对每条消息生成一个MsgId,该标识可以作为去重的依据(消息投递失败并重传),避免重复的消息进入队列
“消息消费时保证幂等性”:这一点可以利用业务本身的特性来实现,即每个业务实体一般都会有一个唯一的ID,就像数据库表中唯一的主键一样,在监听消费处理时根据ID作为去重的依据
“持久化”:将队列、交换机、消息都设置为持久化模式,确保消息在投递、发送期间出现MQ服务宕机后重启恢复过来时消息依旧存在
“消息消费重试机制”:指的是消费者在监听、消费、处理消息的过程中出现了异常,导致业务逻辑没有处理成功,此时可以开启“消息重入队列”机制,设置消息重入队列N次 进行 重试消费
“消息投递补偿机制”:指的是消息在生产、投递期间出现“投递失败”,也就是“发送不成功”的情况,此时可以将其加入到DB中,并开启定时任务,拉取那些投递不成功的消息,重新投递入队列,如此一来便可以保证消息不丢失且准备被投递
流程图