根据模板提取变量信息

问题来源:
  最近公司要做短信中转服务平台,由于是第一次接触这个业务,中间跳了不少坑,其中有一部分就是:上游通道需要配置信息模板,接口中提供可变信息即可;下游通道则是只能提供完整信息,无法提供可变信息(吐槽一下:就是太LAN,不想弄而已),没有办法,只好由我们自己完成可变信息的提取,然后将可变信息以固定格式提交到上游通道,可变信息后面统称为变量信息。
  经过努力,完成了一个测试类,可以根据完整信息内容和模板来自动提取出内容中的变量信息,并可以根据完整信息的长度来自动将模板分割成两条或更多,以及对应条数的变量信息,话不多说,直接上代码:

package com.hyfd.service;

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);
    }
}

测试结果,可以看到模板分段并完美的获取到了对应的变量信息,效果如下

根据模板提取变量信息

后记
  由于赶时间没有做优化,如果有不当之处,欢迎各位大神指教,谢谢!

猜你喜欢

转载自blog.51cto.com/1197822/2314114
今日推荐