【牛千里幅图指标源码】【datahub源码是什么】【技术栈源码原理】javaeditor源码

时间:2024-12-22 20:00:48 来源:首源码 分类:休闲

1.java编译文本编辑器
2.使用java开发代码编辑器(使用java开发代码编辑器的好处)
3.JarEditor可直接修改jar包的源码IDEA插件
4.如何直接修改jar包(无需解压)

javaeditor源码

java编译文本编辑器

       import java.awt.*;

       import java.awt.event.*;

       import javax.swing.*;

       public class EditorJFrame extends JFrame implements ActionListener, ItemListener, MouseListener

       {

        private JTextField text_size; //字号文本行

        private JCheckBox checkbox_bold, checkbox_italic; //粗体、斜体复选框

        private JButton button_cut,源码 button_copy, button_paste; //剪切、复制、源码粘贴按钮

        private JTextArea textarea; //文本区

        private JPopupMenu popupmenu; //快捷菜单

        private JDialog dialog; //出错提示对话框

        private JLabel label_dialog; //对话框中的源码标签

        public EditorJFrame()

        {

        super("文本编辑器"); //默认BorderLayout布局

        this.setSize(,);

        this.setLocation(,);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE); //单击窗口关闭按钮时,结束程序运行

        textarea = new JTextArea("TextArea");

        textarea.addMouseListener(this); //为文本区注册鼠标事件监听器

        this.add(textarea); //文本区添加到框架的源码中部

        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); //面板为流布局,左对齐

        this.add(panel,源码牛千里幅图指标源码"North"); //面板添加到框架的北部

        text_size = new JTextField("",);

        panel.add(text_size);

        text_size.addActionListener(this); //注册文本行的单击事件监听器

        checkbox_bold = new JCheckBox("粗体"); //复选框

        panel.add(checkbox_bold);

        checkbox_bold.addItemListener(this); //注册复选框的选择事件监听器

        checkbox_italic = new JCheckBox("斜体");

        panel.add(checkbox_italic);

        checkbox_italic.addItemListener(this);

        this.addmyMenu(); //调用自定义方法,添加菜单

        this.setVisible(true);

        }

        private void addmyMenu() //添加主菜单、源码快捷菜单、源码对话框

        {

        JMenuBar menubar = new JMenuBar(); //菜单栏

        this.setJMenuBar(menubar); //框架上添加菜单栏

        JMenu menu_file = new JMenu("文件"); //菜单

        menubar.add(menu_file); //菜单栏中加入菜单

        menu_file.add(new JMenuItem("打开")); //生成菜单项并加入到菜单

        menu_file.add(new JMenuItem("保存"));

        menu_file.addSeparator(); //加分隔线

        JMenuItem menuitem_exit = new JMenuItem("退出");

        menu_file.add(menuitem_exit);

        menuitem_exit.addActionListener(this); //为菜单项注册单击事件监听器

        JMenu menu_edit = new JMenu("编辑");

        menubar.add(menu_edit);

        JMenu menu_style = new JMenu("字形");

        menu_style.add(new JCheckBoxMenuItem("粗体")); //复选菜单项

        menu_style.add(new JCheckBoxMenuItem("斜体"));

        menu_edit.add(menu_style); //菜单加入到菜单中成为二级菜单

        JMenu menu_color = new JMenu("颜色");

        menu_edit.add(menu_color);

        ButtonGroup buttongroup = new ButtonGroup(); //按钮组

        JRadioButtonMenuItem rbmi_red = new JRadioButtonMenuItem("红",源码true); //单选菜单项

        buttongroup.add(rbmi_red); //单选菜单项添加到按钮组

        menu_color.add(rbmi_red); //单选菜单项添加到菜单

        JRadioButtonMenuItem rbmi_green = new JRadioButtonMenuItem("绿",true);

        buttongroup.add(rbmi_green);

        menu_color.add(rbmi_green);

        JRadioButtonMenuItem rbmi_blue = new JRadioButtonMenuItem("蓝",true);

        buttongroup.add(rbmi_blue);

        menu_color.add(rbmi_blue);

        menubar.add(new JMenu("帮助"));

        popupmenu = new JPopupMenu(); //弹出式菜单对象

        JMenuItem menuitem_cut = new JMenuItem("剪切");

        menuitem_cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,InputEvent.CTRL_MASK));//设置快捷键Ctrl+X

        popupmenu.add(menuitem_cut); //加入剪切菜单项

        menuitem_cut.addActionListener(this);

        JMenuItem menuitem_copy = new JMenuItem("复制");

        menuitem_copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));//设置快捷键Ctrl+C

        popupmenu.add(menuitem_copy);

        menuitem_copy.addActionListener(this);

        JMenuItem menuitem_paste = new JMenuItem("粘贴");

        menuitem_paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK));//设置快捷键Ctrl+V

        popupmenu.add(menuitem_paste);

        menuitem_paste.addActionListener(this);

        textarea.add(popupmenu); //文本区添加快捷菜单

        dialog = new JDialog(this,"提示");

        dialog.setSize(,);

        label_dialog = new JLabel("",JLabel.CENTER);

        dialog.add(label_dialog);

        dialog.setDefaultCloseOperation(HIDE_ON_CLOSE); //单击对话框的关闭按钮时,隐藏对话框而不结束程序运行

        }

        public void actionPerformed(ActionEvent e) //单击事件处理程序

        {

        if(e.getActionCommand()=="退出") //不能用switch(int)语句

        System.exit(0); //单击菜单项时结束程序

        if(e.getActionCommand()=="剪切")

        textarea.cut(); //将选中文本剪切送系统剪贴板

        if(e.getActionCommand()=="复制")

        textarea.copy();

        if(e.getActionCommand()=="粘贴")

        textarea.paste();

        if(e.getSource()==text_size) //单击文本行时,源码改变字号

        {

        int size=0;

        try

        {

        size = Integer.parseInt(text_size.getText());

        if (size<=0 || size>)

        throw new Exception("SizeException"); //抛出异常对象

        java.awt.Font font = textarea.getFont();

        textarea.setFont(new Font(font.getName(),源码font.getStyle(),size));

        }

        catch(NumberFormatException nfe)

        {

        label_dialog.setText("\""+text_size.getText()+"\" 不能转换成整数,请重新输入!");

        dialog.setLocation(this.getX()+,源码this.getY()+);

        dialog.setVisible(true);

        }

        catch(Exception ex)

        {

        if (ex.getMessage()=="SizeException") //捕获自己抛出的异常对象

        {

        label_dialog.setText(size+" 字号不合适,请重新输入!");

        dialog.setLocation(this.getX()+,源码datahub源码是什么this.getY()+);

        dialog.setVisible(true);

        }

        }

        finally{ }

        }

        }

        public void itemStateChanged(ItemEvent e) //复选框选择事件处理程序

        { //实现ItemListener接口中的方法

        Font font = textarea.getFont();

        int style = font.getStyle();

        if (e.getSource()==checkbox_bold)

        style = style ^ 1; //整数的位运算,异或^

        if (e.getSource()==checkbox_italic)

        style = style ^ 2;

        textarea.setFont(new Font(font.getName(),源码style,font.getSize()));

        }

        public void mouseClicked(MouseEvent mec) //单击鼠标时触发

        { //实现MouseListener接口中的方法

        if (mec.getModifiers()==mec.BUTTON3_MASK) //单击的是鼠标右键

        popupmenu.show(textarea,mec.getX(),mec.getY());//在鼠标单击处显示快捷菜单

        }

        public void mousePressed(MouseEvent mep) { }

        public void mouseReleased(MouseEvent mer) { }

        public void mouseEntered(MouseEvent mee) { }

        public void mouseExited(MouseEvent mex) { }

        public void mouseDragged(MouseEvent med) { }

        public static void main(String arg[])

        {

        new EditorJFrame();

        }

       }

使用java开发代码编辑器(使用java开发代码编辑器的好处)

       java编程常用的软件有哪些

       æƒ³è¦åšå¥½Java开发,没有常用的开发工具可不行。而Java初学者往往处于对Java还一知半解的状态,对于Java开发工具的了解也不会太多,常常会为了找开发工具而浪费大量的时间。给大家介绍下Java开发工程师常用的开发工具有哪些。

       ç¬¬ä¸€ä¸ªJava常用的开发工具为JDK,也叫Java软件开发工具包,是一个编写Java的Applet小程序和应用程序的程序开发环境,JDK中还包括了Java的开发环境,所以下载了JDK就包含了Java开发环境。而且JDK之所以被叫做Java软件开发工具包,是因为它包含了其它Java开发工具,如:编译工具(javac.exe)、打包工具(jar.exe)等。

       ç¬¬äºŒä¸ªæ˜¯JavaIDE:Eclipse,Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。而且由于它的平等和一致性,使得其它开发语言也可以在eclipse上使用。

       ç¬¬ä¸‰ä¸ªæ˜¯notepad++,notepad++是一个编译工具,它的优点是即使你把文件删掉了,如果再notepad++中打开过,那么那里就会保留,所以对一些容易误删的人来说比较友好,notepad++可以用来替代notepad。

       ç¬¬å››ä¸ªæ˜¯VisualStudioCode,它是一个运行于MacOSX、Windows和Linux之上的跨平台源代码编辑器。而且这个编辑器支持多种语言和格式的编写。

       ä»¥ä¸Šå°±æ˜¯æ¯”较常用的4种Java开发工具,Java的初学者在对开发工具不了解的情况下,可以根据上述介绍来选择适合自己的开发工具,这样可以减少自己到处找开发工具还可能找到不适合的所浪费的时间。

       å¦‚何用java编写一个简单的文本编辑器?

       importjava.awt.*;\x0d\importjava.awt.event.*;\x0d\importjavax.swing.*;\x0d\importjava.io.*;\x0d\\x0d\publicclassf1extendsFrameimplementsActionListener\x0d\{ \x0d\privateMenuBarmenubar=newMenuBar();\x0d\privateMenufilemenu=newMenu("文件");\x0d\privateMenueditmenu=newMenu("编辑");\x0d\privateMenuformmenu=newMenu("格式");\x0d\privateMenuItem[]itemf=newMenuItem[4];\x0d\privateMenuItem[]iteme=newMenuItem[6];\x0d\privateMenuItem[]items=newMenuItem[2];\x0d\privateTextAreatf=newTextArea();\x0d\\x0d\publicinta=0,b=0,c=0,style=Font.PLAIN,size=;\x0d\publicStrings1="red:"+a+""+"green:"+b+""+"blue"+c,\x0d\s2="宋体";\x0d\\x0d\publicString[]sz1={ "","","","","",""},\x0d\sz2={ "宋体","黑体","幼圆","隶书","行楷","Arial","Georgia"},\x0d\sz3={ "粗体","倾斜","常规","粗斜"};\x0d\\x0d\JDialogdialog=newJDialog(this,"字体",true);\x0d\Containercp=dialog.getContentPane();\x0d\JLabel[]lb=newJLabel[8];\x0d\JLabellb1=newJLabel(s1,JLabel.LEFT);\x0d\JButtonb1=newJButton("确定"),\x0d\b2=newJButton("取消");\x0d\JComboBoxjc1=newJComboBox(),\x0d\jc2=newJComboBox(),\x0d\jc3=newJComboBox();\x0d\JScrollBarjb1=newJScrollBar(JScrollBar.HORIZONTAL,,5,0,);\x0d\JScrollBarjb2=newJScrollBar(JScrollBar.HORIZONTAL,,5,0,);\x0d\JScrollBarjb3=newJScrollBar(JScrollBar.HORIZONTAL,,5,0,);

java源代码编辑器设计用于编写Java源代码的编辑器,基本要求:可以完成源程序的文件打开,编辑和文件保存

       ä¸€.高亮的内容:

       éœ€è¦é«˜äº®çš„内容有:

       1.关键字,如public,int,true等.

       2.运算符,如+,-,*,/等

       3.数字

       4.高亮字符串,如"exampleofstring"

       5.高亮单行注释

       6.高亮多行注释

       äºŒ.实现高亮的核心方法:

       StyledDocument.setCharacterAttributes(intoffset,intlength,AttributeSets,booleanreplace)

       ä¸‰.文本编辑器选择.

       Java中提供的多行文本编辑器有:JTextComponent,JTextArea,JTextPane,JEditorPane等,都可以使用.但是因为语法着色中文本要使用多种风格的样式,所以这些文本编辑器的document要使用StyledDocument.

       JTextArea使用的是PlainDocument,æ­¤document不能进行多种格式的着色.

       JTextPane,JEditorPane使用的是StyledDocument,默认就可以使用.

       ä¸ºäº†å®žçŽ°è¯­æ³•ç€è‰²,可以继承自DefaultStyledDocument,设置其为这些文本编辑器的documet,或者也可以直接使用JTextPane,JEditorPane来做.为了方便,这里就直接使用JTextPane了.

       å››.何时进行着色.

       å½“文本编辑器中有字符被插入或者删除时,文本的内容就发生了变化,这时检查,进行着色.

       ä¸ºäº†ç›‘视到文本的内容发生了变化,要给document添加一个DocumentListener监听器,在他的removeUpdate和insertUpdate中进行着色处理.

       è€ŒchangedUpdate方法在文本的属性例如前景色,背景色,字体等风格改变时才会被调用.

       @Override

       publicvoidchangedUpdate(DocumentEvente){

       }

       @Override

       publicvoidinsertUpdate(DocumentEvente){

       try{

       colouring((StyledDocument)e.getDocument(),e.getOffset(),e.getLength());

       }catch(BadLocationExceptione1){

       e1.printStackTrace();

       }

       }

       @Override

       publicvoidremoveUpdate(DocumentEvente){

       try{

       //因为删除后光标紧接着影响的单词两边,所以长度就不需要了

       colouring((StyledDocument)e.getDocument(),e.getOffset(),0);

       }catch(BadLocationExceptione1){

       e1.printStackTrace();

       }

       }

       äº”.着色范围:

       pos:指变化前光标的位置.

       len:指变化的字符数.

       ä¾‹å¦‚有关键字public,int

       å•è¯"publicint",在"public"和"int"中插入一个空格后变成"publicint",一个单词变成了两个,这时对"public"和"int"进行着色.

       ç€è‰²èŒƒå›´æ˜¯public中p的位置和int中t的位置加1,即是pos前面单词开始的下标和pos+len开始单词结束的下标.所以上例中要着色的范围是"publicint".

       æä¾›äº†æ–¹æ³•indexOfWordStart来取得pos前单词开始的下标,方法indexOfWordEnd来取得pos后单词结束的下标.

       publicintindexOfWordStart(Documentdoc,intpos)throwsBadLocationException{

       //从pos开始向前找到第一个非单词字符.

       for(;pos0isWordCharacter(doc,pos-1);--pos);

       returnpos;

       }

       publicintindexOfWordEnd(Documentdoc,intpos)throwsBadLocationException{

       //从pos开始向前找到第一个非单词字符.

       for(;isWordCharacter(doc,pos);++pos);

       returnpos;

       }

       ä¸€ä¸ªå­—符是单词的有效字符:是字母,数字,下划线.

       publicbooleanisWordCharacter(Documentdoc,intpos)throwsBadLocationException{

       charch=getCharAt(doc,pos);//取得在文档中pos位置处的字符

       if(Character.isLetter(ch)||Character.isDigit(ch)||ch=='_'){ returntrue;}

       returnfalse;

       }

       æ‰€ä»¥ç€è‰²çš„范围是[start,end]:

       intstart=indexOfWordStart(doc,pos);

       intend=indexOfWordEnd(doc,pos+len);

       å…­.关键字着色.

       ä»Žç€è‰²èŒƒå›´çš„开始下标起进行判断,如果是以字母开或者下划线开头,则说明是单词,那么先取得这个单词,如果这个单词是关键字,就进行关键字着色,如果不是,就进行普通的着色.着色完这个单词后,继续后面的着色处理.已经着色过的字符,就不再进行着色了.

       publicvoidcolouring(StyledDocumentdoc,intpos,intlen)throwsBadLocationException{

       //取得插入或者删除后影响到的单词.

       //例如"public"在b后插入一个空格,就变成了:"public",这时就有两个单词要处理:"pub"和"lic"

       //这时要取得的范围是pub中p前面的位置和lic中c后面的位置

       intstart=indexOfWordStart(doc,pos);

       intend=indexOfWordEnd(doc,pos+len);

       charch;

       while(startend){

       ch=getCharAt(doc,start);

       if(Character.isLetter(ch)||ch=='_'){

       //如果是以字母或者下划线开头,说明是单词

       //pos为处理后的最后一个下标

       start=colouringWord(doc,start);

       }else{

       //SwingUtilities.invokeLater(newColouringTask(doc,pos,wordEnd-pos,normalStyle));

       ++start;

       }

       }

       }

       publicintcolouringWord(StyledDocumentdoc,intpos)throwsBadLocationException{

       intwordEnd=indexOfWordEnd(doc,pos);

       Stringword=doc.getText(pos,wordEnd-pos);//要进行着色的单词

       if(keywords.contains(word)){

       //如果是关键字,就进行关键字的着色,否则使用普通的着色.

       //这里有一点要注意,在insertUpdate和removeUpdate的方法调用的过程中,不能修改doc的属性.

       //但我们又要达到能够修改doc的属性,所以把此任务放到这个方法的外面去执行.

       //实现这一目的,可以使用新线程,但放到swing的事件队列里去处理更轻便一点.

       SwingUtilities.invokeLater(newColouringTask(doc,pos,wordEnd-pos,keywordStyle));

       }else{

       SwingUtilities.invokeLater(newColouringTask(doc,pos,wordEnd-pos,normalStyle));

       }

       returnwordEnd;

       }

       å› ä¸ºåœ¨insertUpdate和removeUpdate方法中不能修改document的属性,所以着色的任务放到这两个方法外面,所以使用了SwingUtilities.invokeLater来实现.

       privateclassColouringTaskimplementsRunnable{

       privateStyledDocumentdoc;

       privateStylestyle;

       privateintpos;

       privateintlen;

       publicColouringTask(StyledDocumentdoc,intpos,intlen,Stylestyle){

       this.doc=doc;

       this.pos=pos;

       this.len=len;

       this.style=style;

       }

       publicvoidrun(){

       try{

       //这里就是对字符进行着色

       doc.setCharacterAttributes(pos,len,style,true);

       }catch(Exceptione){ }

       }

       }

       ä¸ƒ:源码

       å…³é”®å­—着色的完成代码如下,可以直接编译运行.对于数字,运算符,字符串等的着色处理在以后的教程中会继续进行详解.

       importjava.awt.Color;

       importjava.util.HashSet;

       importjava.util.Set;

       importjavax.swing.JFrame;

       importjavax.swing.JTextPane;

       importjavax.swing.SwingUtilities;

       importjavax.swing.event.DocumentEvent;

       importjavax.swing.event.DocumentListener;

       importjavax.swing.text.BadLocationException;

       importjavax.swing.text.Document;

       importjavax.swing.text.Style;

       importjavax.swing.text.StyleConstants;

       importjavax.swing.text.StyledDocument;

       publicclassHighlightKeywordsDemo{

       publicstaticvoidmain(String[]args){

       JFrameframe=newJFrame();

       JTextPaneeditor=newJTextPane();

       editor.getDocument().addDocumentListener(newSyntaxHighlighter(editor));

       frame.getContentPane().add(editor);

       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

       frame.setSize(,);

       frame.setVisible(true);

       }

       }

       /

**

       *当文本输入区的有字符插入或者删除时,进行高亮.

       

*

       *要进行语法高亮,文本输入组件的document要是styleddocument才行.所以不要用JTextArea.可以使用JTextPane.

       

*

       *@authorBiao

       

*

       */

       classSyntaxHighlighterimplementsDocumentListener{

       privateSetStringkeywords;

       privateStylekeywordStyle;

       privateStylenormalStyle;

       publicSyntaxHighlighter(JTextPaneeditor){

       //准备着色使用的样式

       keywordStyle=((StyledDocument)editor.getDocument()).addStyle("Keyword_Style",null);

       normalStyle=((StyledDocument)editor.getDocument()).addStyle("Keyword_Style",null);

       StyleConstants.setForeground(keywordStyle,Color.RED);

       StyleConstants.setForeground(normalStyle,Color.BLACK);

       //准备关键字

       keywords=newHashSetString();

       keywords.add("public");

       keywords.add("protected");

       keywords.add("private");

       keywords.add("_int9");

       keywords.add("float");

       keywords.add("double");

       }

       publicvoidcolouring(StyledDocumentdoc,intpos,intlen)throwsBadLocationException{

       //取得插入或者删除后影响到的单词.

       //例如"public"在b后插入一个空格,就变成了:"public",这时就有两个单词要处理:"pub"和"lic"

       //这时要取得的范围是pub中p前面的位置和lic中c后面的位置

       intstart=indexOfWordStart(doc,pos);

       intend=indexOfWordEnd(doc,pos+len);

       charch;

       while(startend){

       ch=getCharAt(doc,start);

       if(Character.isLetter(ch)||ch=='_'){

       //如果是以字母或者下划线开头,说明是单词

       //pos为处理后的最后一个下标

       start=colouringWord(doc,start);

       }else{

       SwingUtilities.invokeLater(newColouringTask(doc,start,1,normalStyle));

       ++start;

       }

       }

       }

       /

**

       *对单词进行着色,并返回单词结束的下标.

       

*

       *@paramdoc

       *@parampos

       *@return

       *@throwsBadLocationException

       */

       publicintcolouringWord(StyledDocumentdoc,intpos)throwsBadLocationException{

       intwordEnd=indexOfWordEnd(doc,pos);

       Stringword=doc.getText(pos,wordEnd-pos);

       if(keywords.contains(word)){

       //如果是关键字,就进行关键字的着色,否则使用普通的着色.

       //这里有一点要注意,在insertUpdate和removeUpdate的方法调用的过程中,不能修改doc的属性.

       //但我们又要达到能够修改doc的属性,所以把此任务放到这个方法的外面去执行.

       //实现这一目的,可以使用新线程,但放到swing的事件队列里去处理更轻便一点.

       SwingUtilities.invokeLater(newColouringTask(doc,pos,wordEnd-pos,keywordStyle));

       }else{

       SwingUtilities.invokeLater(newColouringTask(doc,pos,wordEnd-pos,normalStyle));

       }

       returnwordEnd;

       }

       /

**

JarEditor可直接修改jar包的IDEA插件

       在进行代码开发和维护过程中,常常会遇到需要直接修改jar文件内部类的源码问题,传统的做法是先解压jar文件,再反编译class文件,修改后再重新编译和打包。这一系列操作繁琐且容易出错,耗费大量时间和精力。

       然而,市面上并没有满足直接编辑jar文件的IDEA插件,这促使我着手编写一个名为JarEditor的插件,以实现无需解压即可编辑jar包内部类的功能。

       JarEditor插件的技术栈源码原理使用流程简便高效。首先,IDEA自带的反编译插件可以打开jar文件,并展示反编译后的类代码。随后,通过在插件市场安装JarEditor,用户可以访问插件提供的Jar Editor功能区,直接在反编译的代码上进行修改。

       修改完成后,用户只需点击“Save/Compile”按钮,系统将自动编译修改的java内容,并保存到修改的类文件中。接着,码支付2021源码通过点击“Build Jar”按钮,系统将把修改后的类文件写入到原始jar包中,实现一气呵成的编辑过程,无需再进行复杂的解压和打包操作。

       不仅如此,JarEditor还支持修改jar包内的资源文件。用户只需按照相同的流程操作,即可完成资源文件的编辑和更新。在查看jar包工程展示图时,用户可以通过右键任意文件,选择“New”或“Delete”操作,轻松新增或删除文件。cat 点评源码分析

       总结而言,JarEditor插件大大简化了编辑jar文件的过程,提高了开发效率。用户只需安装插件,并遵循简单操作步骤,即可实现直接在jar文件中进行代码修改,节省了大量时间,减少了出错几率。感兴趣的开发者可以尝试使用,源码地址在GitHub上可供参考。支持IDEA最低版本为.3,兼容更高级别版本。

       欢迎广大开发者交流反馈,共同提升开发体验。

如何直接修改jar包(无需解压)

       有的时候我们需要直接修改Jar包内的某个class,一般的方式是解压->反编译class->修改反编译的class->编译->编译后class拽回jar(或者直接打包jar),中间的流程还是比较繁琐的,解压和打包还需要通过各种命令,反编译还需要用到JD-GUI,写代码还得新建java文件甚至还要用到编辑器或者IDE,编译还得注意设置目标版本。

       这一顿操作猛如虎的过程中,大脑在多种工具、各种命令和各种注意事项中来回切换,我们知道大脑就跟CPU一样,来回切换上下文势必浪费大量脑细胞,集中精力做一个点的事既轻松又效率高。

       于是我想,有没有直接修改Jar包的插件呢?不用解压就能直接修改反编译的class,写完直接增量编译打包,整个过程中全程是自动化的。

       我翻遍了插件市场,并没有找到这样的插件,于是我打算自己写一款这样的IDEA插件JarEditor来实现无需解压直接编译Jar包,包括class和资源文件。

       本质上开发插件还是替换上面的手动修改jar文件的流程,但是又要尽可能复用现有的功能

       于是我在IDEA反编译的jar包编辑页增加一个辅助编辑页(有点类似MavenHelper在pom.xml的编辑页增加辅助页),用来修改反编译的class代码

       这样几乎不费吹灰之力就解决了无需解压和反编译的两个流程点,因为IDEA是自带Jar内class反编译的。

       点击Jar Editor的tab标签辅助页面,我加上了几个操作的UI

       里面有默认的JDK版本和编译目标版本,默认编译版本和要修改的class版本保持一致,当然也可以手动设置。

       然后在Jar Editor的辅助页就可以直接编辑代码了

       考虑到可能要修改多个文件,所以我做了两个按钮,Save/Compile和Build Jar,点击Save/Compile可将当前修改的jar临时编译并写入到jar包所在目录的子目录jar_edit_out中,当点击Build Jar的时候,将修改过的文件增量写入jar内,最后删除临时目录。

       下面是一个完整的修改例子:

       修改资源文件的话也是一样的操作,不过不用编译,也是点击Save直接保存到临时目录,最后Build Jar写入jar内。

       通过简单的几步,就实现了修改Jar内文件的一系列自动化流程。

       有时我们还会新增或者Jar包内的一些文件/文件夹,于是我在Jar包内的文件上加了右键的操作Action

       我已经发布插件到Jetbrains的插件市场,插件市场搜索JarEditor可直接安装使用,也可根据文末源码自己编译自己安装(基于SDK IDEA.3),IDEA最低要求.3,IDEA.3及之后的版本均可安装使用。

       然后就可以直接打包jar包内的文件了,如果是外部jar,需要在File->Project Structure->Libraries中添加jar即可打开jar内的文件。

       另外文章篇幅有限,下面是具体插件源码地址以供学习交流:

       编译和打包的原理都在源码和注释里。

       欢迎交流!