java从服务器日志截取请求/响应XML报文或截取指定字符串

在做接口自动化过程中,需要获取请求/响应的xml报文,因为是银行系统,服务器组报文了发送到ESB服务器,请求和响应的报文会打印在ESB服务器的日志中,当要截取N个请求的报文时通过人工截取显然效率低下,所有写了一个报文截取工具。

 

<?xml version="1.0" encoding="UTF-8"?>
<service>
<sys-header>
<data name="SYS_HEAD">
<struct>
<data name="field1">
<field type="string" length="17" scale="0">20180000000000000</field>
</data>
<data name="SEQ_NO">
<field type="string" length="52" scale="0">1111111111111111111</field>
</data>
<data name="field3">
<field type="string" length="2" scale="0">AA</field>
</data>
<data name="field4">
<field type="string" length="2" scale="0">00</field>
</data>
<data name="field5">
<field type="string" length="30" scale="0">00000000000</field>
</data>
<data name="field6">
<field type="string" length="30" scale="0">000000</field>
</data>
</struct>
</data>
</sys-header>
<app-header>
<data name="field7">
<struct>
<data name="field8">
<field type="string" length="22" scale="0">000000000000</field>
</data>
</struct>
</data>
</app-header>
<body>      
<data name="field9">
<field type="string" length="3" scale="0">000</field>
</data>
<data name="Bfield10">
<field type="string" length="50" scale="0">000</field>
</data>
<data name="field11">
<field type="string" length="1" scale="0">000</field>
</data>
<data name="TRAN_ARRAY">
<array>
<struct>
<data name="field9">
<field type="string" length="3" scale="0">000</field>
</data>
<data name="field12">
<field type="string" length="10" scale="0">000</field>
</data>
</struct>
</array>
</data>
<data name="field13">
<field type="string" length="60" scale="0">000000</field>
</data>
<data name="field14">
<field type="string" length="6" scale="0"></field>
</data>
</body>
</service>

如上图所示,xml请求报文长这样,我需要在服务器中找到他所在的日志文件,并截取这个报文。

代码如下:

依赖jar包:ganymed-ssh2.jar

一:

此方法是连接服务器,并执行linux命令,多条命令用分好隔开,并将服务器的文件复制到本地

执行顺序是,连接服务器 -> 执行命令如 cd /home/wlt/log/20180730 ; grep -lr 213234234 * ; grep -lr 651254 * (这里三个命令会按照顺序执行,并将返回的执行结果保存在list中 ) ->  执行完查找命令后,会返回包含自定字符串的文件名称,并将文件名称保存下来 -> 遍历list依次从服务器下载对应的文件,并保存在本地

package cn.com;

import ch.ethz.ssh2.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ConnectServer
{
 
    public void connect (final String ip,final int port, final String username, final String password, String cd, String cmd, String localPath)
    {
    	//连接服务器
        Connection conn = new Connection(ip,port);
        Session session = null;
        List<String> resultList = new ArrayList<String>();
        try {
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(username, password);
            if (isAuthenticated == false)
                throw new IOException("连接到服务器时发生异常");
            //执行远程命令,成功
            session = conn.openSession();
            if(cmd.contains(";"))
            {
            	cmd = cmd.replace(";", " ; ");
            }
            System.out.println("正在服务器"+ip+"查找日志文件...");
            System.out.println("执行多条命令:"+"cd "+cd +" ; " + cmd);
            session.execCommand("cd "+cd +" ; " + cmd);//分号";"隔开执行多条命令,会逐条执行,并返回执行结果
            //显示执行命令后的信息
            InputStream stdout = new StreamGobbler(session.getStdout());
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            String lineStr = null;
            int count = 0;
            StringBuffer sb = new StringBuffer();
            while((lineStr = br.readLine()) != null)
            {
            	if(lineStr.trim().length() != 0)
            	{
            		resultList.add(lineStr);
            	}
            	if(lineStr.contains("."))
            	{
            		sb.append(", "+lineStr.trim());
            		count++;
            	}
            }
            if(sb.toString().trim().length() != 0)
            {
            	System.out.println("查找完成,共查到"+count+"个日志文件包含指定字符串, ["+sb.toString().substring(1)+"]");
            }else
            {
            	System.out.println("没有找到相关的日志");
            }
            
            session.close();
            
            SCPClient client = new SCPClient(conn);
            if(resultList.size() != 0)
            {
            	System.out.println("开始复制日志文件到本地...");
            	for(String str : resultList)
            	{
            		String logFileName = cd.replace("cd", "").trim() ;
            		if(str.contains("."))
            		{
            			logFileName = str.endsWith("/") ? logFileName+str : logFileName+"/"+str ;	
            			//System.out.println("logFileName:"+logFileName+"   " +localPath );
            			client.get(logFileName, localPath); //将服务器文件复制到本地
            		}
            		//System.out.println(str);
            	}
            	System.out.println("文件复制完成");
            }
            
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("连接到服务器时发生异常");
            if (conn != null) {
                conn.close();
            }
            if (session != null) {
                session.close();
            }
 
        } finally {
            if (conn != null) {
                conn.close();
            }
            if (session != null) {
                session.close();
            }
        }
        System.out.println("已断开服务器连接");
    }
	
public static void main(String[] args)
{
//测试
	ConnectServer connectServer = new ConnectServer();
	connectServer.connect("192.168.1.1", 22, "username", "000000", "cd /aaa/bbb/ccc/ddd", "grep -lr 213234234 * ; grep -lr aabbcc * ; ", "d:/test");
}
}

 二.

这个类主要是读取服务器下载到的日志文件,找到指定的字符串,并截取字符串所在的xml报文。

如:想要找到包含seq_no=1111111111111111111的所有报文,先找到这个字段所在的行,然后再根据这行截取整个报文。

.....

<data name="SEQ_NO">
<field type="string" length="52" scale="0">1111111111111111111</field>
</data>

.....

三.主运行程序

报文命名、去掉重复报文等等

package cn.com;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReadFile
{	
	//第二次读取文件,并截取xml报文
	public String readFileAgain(int line,int beginLine,File file)
	{
		BufferedReader readerAgain = null;
		int tmpLine = 0;
		StringBuffer stringBuffer = new StringBuffer();
		String messageStr = "";
		FileInputStream in = null;
		boolean boolBegain = false;
		boolean boolEnd = false;
		try
		{
			in = new FileInputStream(file);
			readerAgain = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			//readerAgain = new BufferedReader(new FileReader(file));
			tmpLine = line;	//seq_no
			int lineAgain = 1;  
			int linethree = 0;  
			String tempStringAgain = null;
			while((tempStringAgain = readerAgain.readLine()) != null ) //&& lineAgain <= tmpLine
			{
				
				if(tempStringAgain.contains("<?xml") &&  lineAgain >= beginLine)
				{
					linethree = lineAgain;//上一次seq_no的位置
					boolBegain = true;
				}
				if(linethree != 0 && lineAgain >= linethree && lineAgain <= tmpLine) // 
				{
					//System.out.println(lineAgain + ":   " + tempStringAgain);
					stringBuffer.append(tempStringAgain.trim() );//+ "\r\n"
					if(tempStringAgain.contains("</service>"))
					{
						boolEnd = true;
						break;
					}
				}
				if(lineAgain > tmpLine )
				{
					
					//System.out.println(lineAgain + ":   " + tempStringAgain);
					stringBuffer.append(tempStringAgain.trim() );//+ "\r\n"
					if(tempStringAgain.contains("</service>"))
					{
						boolEnd = true;
						break;
					}
					
				}
				lineAgain ++;
			}
			if(boolBegain && boolEnd)
			{
				messageStr = stringBuffer.toString();
				//System.out.println(messageStr);
				messageStr = messageStr.substring(messageStr.indexOf("<?xml"));
				messageStr = messageStr.substring(0,messageStr.indexOf("</service>")+10);
				//System.out.println(messageStr);
			}else{
				System.out.println("文件第"+tmpLine+"行的seq_no可能不在报文中");
			}
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			try
			{
				in.close();
				readerAgain.close();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return messageStr;
	}
	
	/*
	 *读取文件,找到指定字符的位置
	 **/
	public List<String> getDatagram(String logFilesPath,String target,String fieldName)
	{
		File file = new File(logFilesPath);
		BufferedReader reader = null;
		FileInputStream in = null;
		int line = 1;
		String str = "";
		List<String> list = new ArrayList<String>();
		boolean bool = false;
		int headLine = 1;
		try
		{
			in = new FileInputStream(file);
			reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));	
			String tempString = null;
			while((tempString = reader.readLine()) != null)
			{	
				if(tempString.contains("<?xml"))
				{
					headLine = line;//报文头开始的位置,始终保持最大行
				}
				if(tempString.contains(target) && line >= headLine)
				{
					bool = true;
					str = readFileAgain(line,headLine, file); 
					
					//因为此字符是xml报文中两个字段拼接而成的
					if(fieldName.substring(0, fieldName.indexOf(":")).equalsIgnoreCase("service_code"))//如果根据service_code查找,拼接service_code判断是否是指定的值
					{
						String servicecode = getValue("SERVICE_CODE" , str) + getValue("SERVICE_SCENE" , str);
						//System.out.println(fieldName.substring(fieldName.indexOf(":")+1)+":"+servicecode);
						if(fieldName.substring(fieldName.indexOf(":")+1).equalsIgnoreCase(servicecode))
						{
							list.add(str);
						}
					}else
					{
						list.add(str);
					}
					
					//System.out.println(str);
				}
				
				line ++;
			}
			//System.out.println("line = "+line);
			if(!bool){
				//System.err.println("文件"+logFilesPath.substring(logFilesPath.lastIndexOf("\\")+1)+"中未找到 SEQ_NO:"+target+" 请检查SEQ_NO是否正确");
			}
			
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			try
			{
				reader.close();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return list;
	}
	
	/*
	 * 写入到文件
	 */
	public boolean writeFile(String fileName,String content)
	{
		boolean bool = false;
		createFile(fileName);
		File file = new File(System.getProperty("user.dir")+"\\"+getProperties("datagramfileName")+"\\"+fileName);
		BufferedWriter bufferedWriter = null;
		FileOutputStream fileOutputStream = null;
		try
		{
			fileOutputStream = new FileOutputStream(file,false);
			bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "UTF-8"));
			bufferedWriter.write(content);
			bool = true;			
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (UnsupportedEncodingException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			try
			{
				bufferedWriter.close();
				fileOutputStream.close();				
			} catch (IOException e)
			{
				e.printStackTrace();
			}			
		}
		return bool;
	}
	
	/*
	 * 新建文件
	 */
	public void  createFile(String FileName)
	{
		String dirPath = System.getProperty("user.dir") + "\\datagramfiles";
		File dir = new File(dirPath);
		if (!dir.exists())
		{
			dir.mkdir();
		} else
		{
			File file = new File(dirPath + "\\" + FileName);
			try
			{
				if (!file.exists())
				{
					file.createNewFile();
				}
			} catch (IOException e)
			{
				e.printStackTrace();
			}

		}
	}
	
	/*
	 * 获取目录下所有文件路径+名称
	 */
	public List<String> getFileName(String dirPath)
	{
		File file = new File(dirPath);
		File[] files = file.listFiles();
		List<String> fileNameList = new ArrayList<String>();
		for(File file1 : files)
		{
			if(file1.getName().contains(".")){
				fileNameList.add(file1.getAbsolutePath());
			}			
		}
		file.getAbsolutePath();
		
		return fileNameList;
	}
	
	/*
	 * 查找报文的字段值
	 */
	public String getValue(String key, String datagram)
	{
		if(datagram.trim().length() == 0)
		{
			System.out.println("报文为空");
			return "";
		}
		if(key.trim().length() == 0 || !datagram.contains(key))
		{
			System.out.println("报文中没有字段:"+key);
			return "";
		}
		key = key.toUpperCase();
		int index = datagram.indexOf(key);
		datagram = datagram.substring(index);
		datagram = datagram.substring(datagram.indexOf("<field"),datagram.indexOf("</field>"));
		String fieldValue = datagram.substring(datagram.indexOf(">")+1);
		return fieldValue;
	}
	
	/*
	 * 获取properties文件中的值
	 */
	public String getProperties(String key)
	{
		InputStream in = null;
		String value = "";
		try
		{
			in = new BufferedInputStream(new FileInputStream(System.getProperty("user.dir") + "\\args.properties"));
			Properties properties = new Properties();
			properties.load(in);
			value = properties.getProperty(key);
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return value;
	}
	
	/*
	 *替换空格、换行符等等 
	 */
	public String replaceBlank(String str)
	{
		String dest = "";
		if(str!=null)
		{
			Pattern p = Pattern.compile("\\s*|\t|\r|\n");
			Matcher m = p.matcher(str);
			dest = m.replaceAll("");
		}
		return dest;
	}
	
	/*
	 * 格式化报文
	 */
	public String format(String str)
	{
		
		if(str.trim().length() == 0)
		{
			return "";
		}
		str = str.replace("<", "\r<").replace("\r</field>", "</field>").replace("\r<?xml", "<?xml");
		return str;
	}
	
	/*
	 * 取流水号对应的交易名称
	 */
	public String getDatagramName(String key, String datagramName)
	{
		String value = "";
		if(key != null && datagramName.trim().length() != 0)
		{
			Map<String, String> map = new HashMap<String, String>();
			String[] datagramNameArr = datagramName.contains(",") ? datagramName.split(",") : new String[] { datagramName };
			for (String name : datagramNameArr)
			{
				if (name.contains(":"))
				{
					map.put(name.substring(0, name.indexOf(":")).trim(), name.substring(name.indexOf(":") + 1).trim());
				}else
				{
					System.out.println("datagramName格式错误,例:seq_no1:aaaaaaa,seq_no2:bbbbbbbb");
				}

			}
			if(map != null)
			{
				value = map.get(key);
			}
		}
		
		
		return value;
	}
	

	
}

四.

将相关信息写在配置文件 args.properties

#可查找任何唯一的字段,字段的名称(不区分大小写),一次只能查找一个字段,如:SERVICE_CODE , SEQ_NO , BUSS_SEQ_NO...
fieldName = SEQ_NO
#输入字段的值,一直能查找多个值,多个值用逗号隔开 如:2000001020180310093900000007,201000010201803100930000000
fieldValue =  2049180727001194073486


#存放日志的文件夹,默认logfiles文件夹,不用更改
logfileName = logfiles

#存放报文的文件夹,默认datagramfiles文件夹,不用更改
datagramfileName = datagramfiles

#自定义报文名称,多个用英文逗号隔开, 如果想要流水号05082208461425894的报文名称包含指定名字,写成这样 2018030520180305082208461425894:xxx-xxxx
#报文最终保存的名称, 如:xxx-xxxx&0100100000204(2018030520180305082208461425894)20180725-697070请求报文_1.xml
#datagramName = 2018030520180305082208461425894:xxx-xxxx,2018030520180305082208461425894:yyyy-yy

#是否需要连接服务器获取日志,连接:true/不连接:false
is_connect = true

#服务器地址
ip = 00.000.0.000

#端口号
port = 00

#账号
username = uesrname

#密码
password = 123456

#服务器保存日志的文件夹
logfilesDirPath = /wts/logs/rrylog/Server

#linux命令,多个命令用逗号隔开,如 grep -lr 213234234 * ; grep -lr 651254 * , 
#如果有多个流水号,可用#代替,运行时会自动将#替换成seq_no
#默认此查找命令不用修改
cmd = grep -lr # *

#本地保存日志的路径,如果需要保存在其他地方,可写上路径,默认保存在logfilename文件夹
#localPath=D:/abcdefg

#如果按其他字段查找可增加,格式如:tran_timestamp=<field type="string" length="17" scale="0">#</field> , 字段名小写,字段值用#代替
service_code=<field type="string" length="30" scale="0">#</field>
seq_no=<field type="string" length="52" scale="0">#</field>
buss_seq_no=<field type="string" length="22" scale="0">#</field>

打成jar包,用 .bat运行jar包。效果如下:

 

 

如果要截取其他字符,可以修改getDatagram(String logFilesPath,String target,String fieldName)和readFileAgain(int line,int beginLine,File file)方法

END

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页