问题来源: 最近公司要做短信中转服务平台,由于是第一次接触这个业务,中间跳了不少坑,其中有一部分就是:上游通道需要配置信息模板,接口中提供可变信息即可;下游通道则是只能提供完整信息,无法提供可变信息(吐槽一下:就是太LAN,不想弄而已),没有办法,只好由我们自己完成可变信息的提取,然后将可变信息以固定格式提交到上游通道,可变信息后面统称为变量信息。 经过努力,完成了一个测试类,可以根据完整信息内容和模板来自动提取出内容中的变量信息,并可以根据完整信息的长度来自动将模板分割成两条或更多,以及对应条数的变量信息,话不多说,直接上代码:
import java.util.ArrayList;
import java.util.List;
public class ArgsGet {
// 满足信息分割条件的长度(这里设置为满100字符即进行分割)
private static final int STR_SPLIT_MAX_LENGTH = 100;
public static void main(String[] args) {
String smsStr = ToDBC("成吉思汗的骑兵,***速度与二十世纪的装甲部队相当;北宋的床弩,射程达"
+ "一千五百米,与二十世纪的狙击×××差不多;但这些仍不过是古代的骑兵与×××而已,不可能与"
+ "现代力量抗衡。基础理论决定一切,未来史学派清楚地看到了这一点。而你们,却被回光返照的"
+ "低级技术蒙住了眼睛。你们躺在现代文明的温床中安于享乐,对即将到来的决定人类命运的终极"
+ "决战完全没有精神上的准备。");
getArgsList(smsStr);
}
/**
* <h5>功能:获取信息拆分后的变量信息</h5>
* @param smsStr 完整信息内容
*/
private static List<String> getArgsList(String smsStr) {
String ptTemplateAll = "#*#的骑兵,***速度与#*#世纪的装甲部队相当;#*#的#*#,射程达#*#米,"
+ "与#*#世纪的#*#差不多;但这些仍不过是古代的#*#与#*#而已,不可能与#*#力量抗衡。#*#决"
+ "定一切,#*#清楚地看到了这一点。而你们,却被回光返照的#*#蒙住了眼睛。你们躺在#*#的温床"
+ "中安于#*#,对即将到来的决定人类命运的#*#完全没有精神上的准备。";
String[] ptTemplate = ptTemplateAll.split("#\\*#");
System.out.println("完整信息[" + smsStr + "]");
System.err.println("完整模板[" + ptTemplateAll + "]");
// 拆分信息内容
List<String> smsList = smsSplit(smsStr, ptTemplate);
// 根据信息内容拆分模板
List<List<String>> templateSplit = templateSplist(smsList, ptTemplate);
for (int i = 0; i < templateSplit.size(); i++) {
System.out.println("第" + (i + 1) + "段拆分模板" + templateSplit.get(i) + "");
}
List<String> argsList = new ArrayList<String>();
// 根据拆分后的信息内容和模板获取对应的变量信息
for (int i = 0; i < smsList.size(); i++) {
String tempSmsStr = smsList.get(i);
List<String> templateSplist = templateSplit.get(i);
for (String template : templateSplist) {
if (!"".equals(template)) {
tempSmsStr = tempSmsStr.replaceFirst(template, ",");
}
}
if (tempSmsStr.endsWith(",")) {
tempSmsStr = tempSmsStr.substring(0, tempSmsStr.length() - 1);
}
argsList.add(tempSmsStr);
System.err.println("第" + (i + 1) + "段变量信息[" + tempSmsStr + "]");
}
return argsList;
}
/**
* <h5>功能:拆分信息内容</h5>
* @param smsStr 完整信息内容
* @param ptTemplate 数组化的模板信息
* @return
*/
private static List<String> smsSplit(String smsStr, String[] ptTemplate){
List<String> smsList = new ArrayList<String>();
StringBuffer sbf = new StringBuffer();
for (String template: ptTemplate) {
if (!"".equals(template)) {
// 一旦信息内容长度超过100,则进行信息拆分
if (sbf.length() > STR_SPLIT_MAX_LENGTH) {
// System.out.println(sbf.toString());
smsList.add(sbf.toString());
sbf.setLength(0);
}
sbf.append(smsStr.substring(0, smsStr.indexOf(template) + template.length()));
smsStr = smsStr.substring(smsStr.indexOf(template)+template.length());
}
}
smsList.add(sbf.toString());
return smsList;
}
/**
* <h5>功能:根据信息内容拆分模板</h5>
* @param smsList 拆分后的信息内容
* @param ptTemplate 模板信息
* @return
*/
private static List<List<String>> templateSplist(List<String> smsList, String[] ptTemplate){
List<List<String>> templateList = new ArrayList<List<String>>();
for (String smsStr : smsList) {
// System.out.println(smsStr);
// 1.获取信息结束标识
String sbf = "";
for (String template : ptTemplate) {
if (!"".equals(template)) {
if (smsStr.endsWith(template)) {
// System.out.println(template+"="+smsStr.indexOf(template));
sbf = template;
}
}
}
// 2.根据信息标识,将信息模板进行对应的拆分
List<String> tempList = new ArrayList<String>();
StringBuffer tempSbf = new StringBuffer();
for (int i = 0; i < ptTemplate.length; i++) {
tempSbf.append(ptTemplate[i]);
if (!"".equals(tempSbf.toString())) {
tempList.add(tempSbf.toString());
if (sbf.equals(tempSbf.toString())) {
ptTemplate[i] = "";
break;
} else {
ptTemplate[i] = "";
}
}
tempSbf.setLength(0);
}
templateList.add(tempList);
// System.out.println(JSONObject.toJSONString(tempList));
// System.out.println("-----------------------------");
}
return templateList;
}
/**
* <h5>功能:全角转半角</h5>
* 这个主要是为了规范信息内容,因此对全角信息做了半角处理,不用的时候从引用的地方直接去掉即可
* @author zhangpj @date 2018年11月5日
* @param str
* @return
*/
public static String ToDBC(String str) {
char[] c = str.toCharArray();
for (int i = 0; i < c.length; i++) {
// 全角空格为12288,半角空格为32
if (c[i] == 12288) {
c[i] = (char) 32;
continue;
}
// 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
if (c[i] > 65280 && c[i] < 65375)
c[i] = (char) (c[i] - 65248);
}
return new String(c);
}
}
测试结果,可以看到模板分段并完美的获取到了对应的变量信息,效果如下