WAR包补丁工具

简要:

因目前处于运维历史悠久的WEB项目中,每次需求开发完成需要更打补丁文件,因此编写打补丁工具,以解决手动查找补丁文件的繁琐且重复操作。纯Java代码编写,使用Swing作为界面UI,原有代码只针对特殊使用场景,可以适当加以修改。

适用:

编译工具:Eclipse Luna Release (4.4.0)

运行环境:JDK 1.7

代码:

界面GUI 部分:使用JSplitPane垂直分割布局方式。

public class PatchSwing extends JFrame{
	
	//上部组件
	JPanel jp1;	//定义面板
	JSplitPane jsp;	//定义拆分窗格
	JTextArea jta1;	//定义文本域
	JScrollPane jspane1;	//定义滚动窗格
	JTextArea jta2;	
	JScrollPane jspane2;
	JLabel       label;
	JTextField textField; 
	//下部组件
	JPanel jp2;
	JButton jb1,jb2;    //定义按钮
	JComboBox jcb1;	    //定义下拉框
	
	public PatchSwing() {
		//上部组件
		jp1=new JPanel();	//创建面板
		
		JPanel jpwar = new JPanel();
		label = new JLabel("WAR路径");
		textField = new JTextField(20);
		textField.setFont(new Font(null, Font.PLAIN, 18));
		jpwar.add(label);
		jpwar.add(textField);
		
		jta1=new JTextArea();	//创建多行文本框
		jta1.setLineWrap(true);	//设置多行文本框自动换行
		jta1.setToolTipText("输入需要查找的文件");
		jspane1=new JScrollPane(jta1);	//创建滚动窗格
		
		JSplitPane jspwar=new JSplitPane(JSplitPane.VERTICAL_SPLIT,jpwar,jspane1); //创建拆分窗格
		jspwar.setDividerLocation(40);	//设置拆分窗格分频器初始位置
		jspwar.setDividerSize(1);			//设置分割线的宽度
		
		jta2=new JTextArea();
		jta2.setLineWrap(true);
		jta2.setToolTipText("显示查询结果");
		jspane2=new JScrollPane(jta2);
		
		jsp=new JSplitPane(JSplitPane.VERTICAL_SPLIT,jspwar,jspane2); //创建拆分窗格
		jsp.setDividerLocation(300);	//设置拆分窗格分频器初始位置
		jsp.setDividerSize(1);			//设置分割线的宽度
		//下部组件
		jp2=new JPanel();
		jb1=new JButton("打开");		//创建按钮
		jb2=new JButton("查找");
		String [] name= {".class",".js"};
		jcb1=new JComboBox(name);	//创建下拉框
		//设置布局管理
		jp1.setLayout(new BorderLayout());	//设置面板布局
		jp2.setLayout(new FlowLayout(FlowLayout.RIGHT));
		
		//添加组件
		jp1.add(jsp);
		jp2.add(jcb1);
		jp2.add(jb1);  	addActionListener(jb1);
		jp2.add(jb2);	addActionListener(jb2);
		
		this.add(jp1,BorderLayout.CENTER);
		this.add(jp2,BorderLayout.SOUTH);
		
		//设置窗体实行
		this.setTitle("PatchTool");		//设置界面标题
		this.setIconImage(new ImageIcon("aa.jpg").getImage());    //设置标题图片,就是上面的小企鹅
		this.setSize(400, 500);				//设置界面像素
		this.setLocation(200, 200);			//设置界面初始位置
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	//设置虚拟机和界面一同关闭
		this.setVisible(true);				//设置界面可视化

	}
	
	//添加按钮监听
	private void addActionListener(JButton search) {
		search.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String btnName = e.getActionCommand();
				if(btnName.equals("查找")){
					searchBtn();
				}else if(btnName.equals("打开")){
					openBtn();
				}
			}
		});
		
	}
        //查询按钮事件
	private void searchBtn(){
		String warPath = textField.getText().trim();
		String srcFile = jta1.getText().trim();
		if(warPath == null || "".equals(warPath))
			JOptionPane.showMessageDialog(null, "请输入WAR路径!");
		else if(srcFile == null || "".equals(srcFile))
			JOptionPane.showMessageDialog(null, "请输入查找文件!");
		else if(!new File(warPath).exists())
			JOptionPane.showMessageDialog(null, "WAR路径文件不存在!");
		else{
			if(new File(warPath).isDirectory())
				warPath += "\\XXX.war";
			srcFile = srcFile.replace("\n", ",").replace(".java", ".class");
			new PatchFilesGet(warPath, srcFile, jta2);
		}
	}
	//打开按钮事件
	private void openBtn(){
		String warPath = textField.getText().trim();
		if(warPath == null || "".equals(warPath))
			JOptionPane.showMessageDialog(null, "请输入WAR路径!");
		else if(!new File(warPath).exists())
			JOptionPane.showMessageDialog(null, "WAR路径目录不存在!");
		else{
			try {
				if(new File(warPath).isDirectory())
					Desktop.getDesktop().open(new File(warPath));
				else
					Desktop.getDesktop().open(new File(warPath).getParentFile());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
			
	}
	
	public static void main(String[] args) {
		new PatchSwing();
	}
	
}

1.粘贴对应路径URL

2.上半部分的框粘贴需要查找的类文件

3.下半部分框显示查询结果

WAR查询逻辑:

public class PatchFilesGet {
	private String warPath;
	JTextArea jta2; //结果输出
	
	public PatchFilesGet(String warPath,String srcFile,JTextArea jta2) {
		this.warPath = warPath;
		this.jta2 = jta2;
		jta2.setText("");
		try {
			showRes("查询开始...");
			getWarFiles(srcFile,warPath);
			showRes("查询结束!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//查询所有文件
	public void getWarFiles(String srcFile,String path) throws IOException{
		JarFile war = new JarFile(path);
		Enumeration<JarEntry> entries = war.entries(); 
		String parentPath = new File(path).getParent()+File.separator;
		List<File> jarList = new ArrayList<>();
		//遍历条目
		while (entries.hasMoreElements()) { 
			//参考api获取你需要的文件信息
			JarEntry element = entries.nextElement();
			String name = getFileName(element);
			if(name.endsWith(".class")&&srcFile.indexOf(name) != -1){
				showRes("文件已找到!"+name);
				InputStream iw = war.getInputStream(element);
				File file = new File(parentPath+"/"+element);
				createPareDir(file);
				writeFile(iw, file);
				continue;
			}
			getJarFiles(srcFile, element, war, parentPath, jarList);
		}
		war.close();
		deleteJar(jarList); //删除 查询过程中解压出来的 jar
	}
	
	//查询war 中jar文件
	public void getJarFiles(String srcFile,JarEntry element,JarFile war,String parentPath,List<File> jarList) throws IOException{
		
		//判断是否为 jar
		if(element.getName().endsWith("XXX.jar")){
			InputStream in = war.getInputStream(element);
			String jarName = getFileName(element);
			String par =parentPath +jarName;
			File file = new File(par);
			writeFile(in, file); //输出 jar文件包
			in.close();
			if(file.exists() && file.length() > 1L){
				jarList.add(file);
				JarFile jar = new JarFile(par);
				Enumeration<JarEntry> e = jar.entries(); //  遍历jar
				while (e.hasMoreElements()) { 
					JarEntry ele = e.nextElement();
					String eleName = getFileName(ele);
					if(eleName.endsWith(".class")&&srcFile.indexOf(eleName) != -1){//找到目标文件
						showRes("文件已找到!"+eleName);
						InputStream ij = jar.getInputStream(ele);
						File filec = new File(par.replace("XXX.jar", "")+"/"+ele.getName());
						createPareDir(filec);
						writeFile(ij, filec);
					}
				}
				jar.close(); //关闭 jar读取流 否则删除不了  找好久
			}
		}
	}
	
	
	//写入操作
	public void writeFile(InputStream is, File file) throws IOException{
        if(file != null){
            //推荐使用字节流读取,因为虽然读取的是文件,如果是 .exe, .c 这种文件,用字符流读取会有乱码
            OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
            byte[] bytes = new byte[2048]; //这里用小数组读取,使用file.length()来一次性读取可能会出错(亲身试验)
            int len;
            while((len = is.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }
            os.close();
            is.close();
        }
    }
	
	//结束 删除解压出来的 jar 文件
	public void deleteJar(List<File> list){
		showRes("正在删除冗余文件...");
		for (int i = 0; i < list.size(); i++) {
			File file = list.get(i);
			if(!file.delete())
				showRes("文件删除失败!"+file.getName());
		}
	}
	
	
	public void createPareDir(File file){
		if(!file.getParentFile().exists()){
			if(file.getParentFile().mkdirs()){
				showRes("创建目录成功!"+file.getParentFile());
			}else{
				showRes("创建目录失败!"+file.getParentFile());
			}
		}
	}
	
	//获取文件名
	public String getFileName(JarEntry ele){
		return ele.getName().substring(ele.getName().lastIndexOf("/")+1);
	}

	//输出查询结果
	private void showRes(String res){
		if(jta2 != null){
			jta2.setText(jta2.getText() + "\n" +res);;
		}
	}
	
	
}

总结:

编写过程中遇到两个问题:1.WAR包中解压出来的jar文件删除失败问题,关闭所有文件读取流 jar.close();2.创建文件夹失败问题,存在同名文件时,使用java创建以文件名为名称的文件夹时失败。

此代码因个人使用,并不是很完善,还有很多功能可以增加完善。比如添加查询文件过滤,文件查询结果统计返回失败、成功数,补丁对比等功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值