IntelliJIDEA培训.pdf

上传人:赵** 文档编号:50071180 上传时间:2022-10-12 格式:PDF 页数:20 大小:310.65KB
返回 下载 相关 举报
IntelliJIDEA培训.pdf_第1页
第1页 / 共20页
IntelliJIDEA培训.pdf_第2页
第2页 / 共20页
点击查看更多>>
资源描述

《IntelliJIDEA培训.pdf》由会员分享,可在线阅读,更多相关《IntelliJIDEA培训.pdf(20页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、IntelliJ IDEA插件开发入门指南插件开发入门指南 Alexey EfimovNote:这篇文章将帮助你了解IntelliJ IDEA插件开发的基础知识,快速开发自己的插件。它讲解了日常插件开发的基本原则、语法描述和插件发布,同时包含了一个插件例子,一步步教你如何去开发插件。当你读完这篇文章后,你可以试用一下文章中开发的插件:SampleProject.zip(242 Kb)你需要依据如何开始段落中的步骤1和2建立IntelliJ IDEA JDK.这篇文章假设你正在使用IntelliJ IDEA 5.1或更高版本,或者是高于EAP#4121的版本。文章中涉及到的一些IntelliJ

2、IDEA Open API 中特性或类可能在以前的版本中并不存在。IntelliJ IDEA插件开发基础插件开发基础内容内容约束条件 介绍 获取插件 如何开始 步骤1 步骤2 步骤3 步骤4 插件是如何工作的?IntelliJ IDEA的组件模型 加载组件 卸载组件 组件容器 HelloWorld 插件 创建组件 创建 Action 第一个插件 添加配置 插件的结构描述 插件标识 插件间的依赖关系 版本和编译版本号 组件注册 本地化 插件发布 创建归档 上传插件至插件库 通报新插件 总结和常用链接 约束条件约束条件在IntelliJ IDEA中,插件是独立的模块,它可以通过手动和内置工具的方式

3、加载到IntelliJ IDEA中。IntelliJ IDEA的插件依据他们的功能可以进行分组,主要包括:代码审查和重构(Inspection Gadgets,Intension Power Pack,Refactor-J,Refactor-X等等)自定义编辑器(例如 Images)和工具窗口(SQLQuery,PsiViewer等)其他语言支持(Groovy,JavaScript等)应用服务器整合(Resin,JBoss,Tomcat等)版本控制系统整合(CVS,Clearcase等)框架和其他技术支持(Hibernate Tools,IdeaSpring,XPathView,Struts等

4、)外部应用整合(Jira Browser,JFormdesigner等)用户界面提升,各种工具栏和菜单(TabSwitch,CVS bar等)自定义编译器(Native2Ascii)其他:包括各种工具插件和游戏(IdeaJad,simpleUML,Tetris,Sokoban等)目前IntelliJ IDEA为插件开发人员提供了各种特性和功能,因此IDEA很多的特性都可以被扩展。在IntelliJ IDEA 5.0之前版本,没有提供对其他语言的支持,现在IDEA可以以插件的方式支持各种语言,如JavaScript,CSS,Groovy,SQL等等.渐渐地,通过版本 更新,IntelliJ ID

5、EA将为插件开发人员提供特性,这些将通过 IntelliJ IDEA Open API 呈现出来。下面就是一些比较受欢迎的IntelliJ IDEA插件:TabSwitch:小巧,但非常实用。它允许你在打开的各个文件中进行切换,就象使用Alt+Table快捷键切换Windows应用一样。SQL Query:在IDE工具就可以编写并执行数据库查询语句,有时该工具就象呼吸一样非常必要。Regex:运行你在IDEA中校验各种正则表达式。XPathView:在编辑窗口中提供了XML文件的XPath处理能力.获取插件获取插件 已经在插件库中注册过的插件可以点击File-Settings-Plugins

6、菜单,插件管理器将会添加、更新和删除相关插件。如果你做了相关的操作,需要你重新启动IDEA使其生效。介绍介绍首先下载插件列表,只需点击Available标签。如果你是通过代理服务器联到Internet,请点击 HTTP Proxy Settings按钮,输入正确的信息。IntelliJ IDEA会向插件库(http:/)发出请求,列出适用当前版本IDEA的所有插件。你只需在列表中选择该插件,然后点击下载图标,就可以安装该插件。以这种方式,你可以安装更多的插件。假想你现在决定开发一个插件来满足你同事的强烈需求,行,让我们开始吧。首先需要创建一个项目来包含你的插件。步骤步骤 1 如果你还没有下载P

7、lugin Development Package,请先下载此开发包.如果你使用EAP版本进行插件,你可以下载EAP的插件开发包,文件如idea4121-dev.zip,该文件位于IntelliJ IDEA EAP Access页面(4121是EAP的编译版本号)。如果你想下载发布版本的插件开发包,请访问IntelliJ IDEA Plugin Developers页面,点击Plugin Development链接去下载开发包文件,解压下载的开发包文件至IntelliJ IDEA的安装目录。注意注意:开发包仅包括插件源码和IntelliJ IDEA Open API 的Javadoc文档,所以

8、及时没有该开发包你同样进行插件开发。然后我们推荐你下载并安装该开发包,它会让你的开发更加便捷。步骤步骤 2 解压插件开发包以后,我们需要创建一个项目来编写我们的插件。点击File-New Project菜单项,输入项目名称,如idea-plugins,然后设定项目的存储路径,点击Next。插件开发需要特定类型的JavaTM SDK(JDK):IntelliJ IDEA SDK,它是Jdk标准库和IntelliJ IDEA Open API库的整合体,你可以设置该SDK的JavaDoc和Source Code,这些信息可以在插件开发包找到。点击Configure按钮,将会弹处Jdk设置窗口,点击

9、Add IntelliJ IDEA SDK按钮(包含IDEA 图标的那个按钮),该按钮如下所示:如何开始插件开发如何开始插件开发?选择IntelliJ IDEA的安装目录(实际上IDEA会自动选择),然后点击OK按钮。接着,将该SDK的名称改为 idea,Sandbox Home是保存运行IDEA各种配置参数和缓存的目录,IDEA会将插件拷贝到该目录下进行调试,如果可能的话,请更改目录的sandbox存储目录。注意注意:这里我们推荐你不要使用IntelliJ IDEA的SDK版本号,如果你使用EAP版本的话,这可能引起混乱,如IDEA 4121名称可能在更高版本的IDEA的插件开发中引起误解。

10、点击OK按钮,你会看到IntelliJ IDEA SDK会被显示在项目可用JDK的列表中。设置JDK你只需做一次,今后你只需从列表中选择即可。点击Next按钮。步骤步骤 3 在下一个对话框中,选择Create single-module project选项,然后点击Next按钮。这是我们需要设定module类型,这里需要选择Plugin Module。接着我们需要设定module的名称和路径,如果我们是初学者,就让我们创建传统的HelloWorld插件,这里module名称最好能表达插件所代表的含义。点击Next 按下;在下一个对话框中点击Finish即可。步骤步骤 4 恭喜你!你已经完成了插

11、件项目的创建,。在Project工具窗口中展开项目菜单树,找到plugin.xml文件(在 META-INF 目录下),这是插件的描述文件,包含插件的各种信息,如插件名称、描述、适用的IDEA版本号等等,同时包含component和action描述信息,该描述文件是IntelliJ IDEA加载插件的依据。如果你创建了一个component,而没有在该描述文件中声明的话,IDEA并不会加载该component,请注意这点。plugin.xml文件包含各种信息,请不要忘记设定。解下来让我们设定插件的描述文件,让其工作起来。这里我们设定插件名称,描述和其他信息。让我们看一下since-build属

12、性,在后面的我们会进行具体描述,现在我们只需设置为Help-About对话框中的编译版本号即可。META-INF/plugin.xml文件内容如下:文件内容如下:HelloWorld This plugin does nothing 1.0 JetBrains 现在我们可以开始编写我们第一个插件啦。在进行Hello World插件开发之前,我们想向大家介绍一下插件工作的原理。所有的class和interface都来自于IntelliJ IDEA Open API 开发包,你可以在插件开发包中找到。IntelliJ IDEA component模型模型 IntelliJ IDEA 包含多种组件模

13、型,这些组件模型都是基于PicoContainer,组件都包含在这些容器中,但容器有不同的级别。有三种级别的容器:有三种级别的容器:application,project,和 module.在application级别上可以包含多个project级别的容器;而project级别包含多个module级别容器。Application Component 在IntelliJ IDEA程序中,Application Conponent仅以一个实例存在。创建application component,只需实现ApplicationComponent 接口,然后在plugin.xml文件的applicat

14、ion-components区域进行声明。Project components.在每一个打开项目中,仅包含一个project component实例,因此在IntelliJ IDEA中可能包含多个Project component实例。创建一个project component,只需实现ProjectComponent 接口,然后在plugin.xml文件的project-components 区域进行声明即可。Module components.在没一个项目的module中,仅有一个module component实例,因此在一个项目中包含多个module-level component实例

15、,实例的数量就是项目中加载的module的数量。创建module component,只需实现ModuleComponent 接口,然后在plugin.xml 文件的module-components 区域进行声明。project component的实例数并不等于IntelliJ IDEA打开的项目数量,而是大于打开的项目数。除了打开的项目包含项目组件,另一个项目是Template Project,它是一个隐藏的项目,IDEA一直加载这个项目。Component加载加载 插件是如何工作的插件是如何工作的?Application Component在IDEA启动时加载。Project和modu

16、le component在项目启动时共同加载。一个组件通过调用以下函数来实例化:1.首先加载Component的构造函数。2.如果组件实现JDOMExternalizable接口,将会调用 readExternal 函数。3.接下来initComponent 函数将被调用。4.如果是project或module component,projectOpened 函数将会被调用。如果是module component,moduleAdded 函数会被调用。如果希望在component中访问其他component,我们只需在该component的构造函数声明即可,在这种情况下,IntelliJ ID

17、EA自动实例化所依赖的component,因此在构造函数中,所依赖的组件依据被实例化啦。有依赖关系的有依赖关系的component实例化样例实例化样例 package com.intellij.tutorial.helloWorld;import.public class MyComponent implements ApplicationComponent private final MyOtherComponent otherComponent;public MyComponent(MyOtherComponent otherComponent)this.otherComponent=ot

18、herComponent;.Component卸载卸载 Application component在IDEA关闭时被卸载,Project和module component在项目关闭时被卸载。在卸载component是,以下函数将会被调用:1.如果component实现了 JDOMExternalizable 接口,component的状态将会通过调用writeExternal 函数保存到xml文件中。2.如果是project 或 module component,projectClosed 将会被调用。3.接下来disposeComponent将会被调用。Component 容器容器 前面我们

19、提到有三种不同的容器,application container实现Application 接口;project container 实现Project接口;module 容器实现Module接口。每一个容器都有自己的函数去获取容器内的component。从从application容器中获取组件例子:容器中获取组件例子:Application application=ApplicationManager.getApplication();MyOtherComponent otherComponent=application.getComponent(MyOtherComponent.class

20、);获取application容器是非常容易的,在IDEA中application容器仅有一个(上面的例子就说明啦)。获取project和module容器可能有点困难。通常我们在component构造函数声明或从action的事件处理的context的获取。将容器以构造参数方式引入到将容器以构造参数方式引入到component中中 import.public class MyProjectComponent implements ProjectComponent private final Project project;public MyProjectComponent(Project pr

21、oject)this.project=project;.public void foo()MyOtherProjectComponent otherProjectComponent=project.getComponent(MyOtherProjectComponent.class);在这个例子中,组件在构造函数中获取了容器对象,将其保存,然后在component其他方面进行引用。但是还是要注意这一点。Be careful when passing this reference to other components(especially application-level ones).If

22、an application-level component does not release the reference,but saves it inside itself,all the resources used by a project or module will not be unloaded from the memory on the project closing.一个稍微复杂的例子就是在事件处理中获取容器,请看下面的例子。DataContex类可以为action提供获取容器的方法,这个class应该引起足够的注意。在在Action的事件处理中获取容器对象:的事件处理中获

23、取容器对象:import.public class MyAction extends AnAction public void actionPerformed(AnActionEvent e)DataContext dataContext=e.getDataContext();Project project=(Project)dataContext.getData(DataConstants.PROJECT);Module module=(Module)dataContext.getData(DataConstants.MODULE);现在让我们回到我们的HelloWorld插件,我们将增加一

24、个新的component,它将弹处一个对话框显示Hello World!文本。创建创建 Component 在项目中创建com.intellij.tutorial.helloWorld package。在该package点击鼠标右键,在弹出的菜单中点击New-Application Component菜单项,输入component名称:HelloWorldApplicationComponent。HelloWorld 插件插件点击 OK按钮,IntelliJ IDEA 将会创建该组件同时会在plugin.xml文件中自动注册。接下来让我们在该组件中添加sayHello 函数。我们将使用Mess

25、ages 工具类去显示特定信息。文件文件:/com/intellij/tutorial/helloWorld/HelloWorldApplicationComponent.java package com.intellij.tutorial.helloWorld;import.public class HelloWorldApplicationComponent implements ApplicationComponent public void initComponent()public void disposeComponent()public String getComponentNa

26、me()return HelloWorldApplicationComponent;public void sayHello()/Show dialog with message Messages.showMessageDialog(Hello World!,Sample,Messages.getInformationIcon();创建创建 Action 我们已经创建了Hello World component,接下来我们需要添加一个菜单项来体验其功能。右击 helloWorld package,在弹出的菜单中选择New-Action菜单项,输入Action的ID和类名,在Groups 列表中

27、选择WindowMenu(Window)(请参考下面的截屏)。点击OK按钮,IntelliJ IDEA将会创建Action类,同时在plugin.xml中进行声明。现在我们需要在Action调用component的sayHello。文件文件:/com/intellij/tutorial/helloWorld/SayHelloAction.java package com.intellij.tutorial.helloWorld;import.public class SayHelloAction extends AnAction public void actionPerformed(AnAc

28、tionEvent e)Application application=ApplicationManager.getApplication();HelloWorldApplicationComponent helloWorldComponent=application.getComponent(HelloWorldApplicationComponent.class);helloWorldComponent.sayHello();启动第一个插件启动第一个插件 接下来我们需要设定配置去运行或调试我们的第一个插件,点击Run-Edit Configurations菜单,在Run/Debug Con

29、figuration对话框中,点击Plugin 标签,创建一个新的配置项,然后点击OK按钮。现在我们只需按下Shift+F9(或点击 Run-Debug 菜单项)就可以启动该插件。注意注意:为了调试或测试插件,我们需要在IntelliJ IDEA中启动另一个IDEA实例,在这个实例中,插件已经被加载了,我们可以进行各种操作。IntelliJ IDEA 使用 sandbox 文件夹保存该实例的各种配置信息,并将相关的插件拷贝到该目录下进行调试和测试。IntelliJ IDEA调试实例启动后,切换到新的窗口,点击Window菜单,选择Say Hello!菜单项。添加插件配置项添加插件配置项 到目前

30、为止,我们的插件仅仅显示Hello World!,显的优点幼稚。下面我们希望我们的插件更专业点。为了做到这点,我们需要为插件创建一个Form,来保存插件的配置信息,这个配置Form包含一个文本输入框。在helloWorld package上右击鼠标,在弹出的菜单中选择New-GUIForm项。输入Form名称:HelloWorldConfiguration.在Form编辑窗口中,拖动 JLabel 和 JTextField 元素,放在Form窗口中。将元素按以下屏幕布局,然后选择这些元素,点击Lay Out Horizontally 按钮。IntelliJ IDEA将会创建一个水平面板,包含选

31、定的各个元素。在编辑窗口中选择面板,在面板的左边会出现一个箭头图标,点击该箭头图标,选择 Insert row after this 将会创建一个新的格子。接下来在元素面板中选择 Vertical Spacer 元素,拖放至新创建的格子中。在元素的树行菜单中(在form 编辑窗口的左边),选择 JPanel 元素,在属性面板中,设置JPanel的 binding属性为rootComponent名称,对于输入框(JTextField)将其 binding 属性设为phraseField名称。对于标签(JLabel)将其设置为 phraseLabel。现在Form已经完成啦,我们需要将Form绑定

32、到指定的Java类。在同样的package下创建一个新的类,命名为HelloWorldConfigurationForm。切换回Form编辑窗口,将Form的binding 属性值设定为该类的名称。这一切做完后,IntelliJ IDEA 将会在元素树中高亮显示这些元素,提示你在HelloWorldConfigurationForm类去创建对应的字段。你只需按下Alt+Enter快捷键就可以解决这些问题。当所有的冲突被解决后,点击 Data Binding Wizard 按钮(如以下屏幕所示).向导将会创建相关的代码来读取和设置Form的各种元素的信息。选择Bind to existing b

33、ean选项,将其设置为 HelloWorldApplicationComponent 类,然后点击Next按钮。在Bean Property 列表项中,设置类的字段名称:phrase,然后点击Finish按钮。IntelliJ IDEA会自动创建相关的代码去读取HelloWorldConfigurationForm 类的字段值(i.e.the phrase 字段),同时会添加isModified 函数。现在我们需要更改HelloWorldConfigurationForm 类,添加一个方法可以获取form的根元素getRootComponent。文件文件:/com/intellij/tutor

34、ial/helloWorld/HelloWorldConfigurationForm.java public class HelloWorldConfigurationForm private JPanel rootComponent;private JTextField phraseField;private JLabel phraseLabel;public HelloWorldConfigurationForm()/Enable mnemonic action phraseLabel.setLabelFor(phraseField);/Method returns the root co

35、mponent of the form public JComponent getRootComponent()return rootComponent;public void setData(HelloWorldApplicationComponent data)phraseField.setText(data.getPhrase();public void getData(HelloWorldApplicationComponent data)data.setPhrase(phraseField.getText();public boolean isModified(HelloWorldA

36、pplicationComponent data)return phraseField.getText()!=null?!phraseField.getText().equals(data.getPhrase():data.getPhrase()!=null;现在,我们有了一个图形化的Form,通过该Form的phrase 字段可以设置HelloWorldApplicationComponent 类的字段信息。现在我们需要更改sayHello 方法,依据phrase字段来显示特定的文本值。修改修改HelloWorldApplicationComponent类的类的sayHello方法方法 pu

37、blic void sayHello()/Show dialog with message Messages.showMessageDialog(phrase,Sample,Messages.getInformationIcon();为了将该组件注册到IntelliJ IDEA设置面板中(通过File-Settings菜单项),我们需要对插件的component进行调整。现在我们需要让component实现Configurable 接口。在下面的代码,你可以看到该接口的实现。Configurable 接口在接口在HelloWorldApplicationComponent类中的实现类中的实现

38、import.public class HelloWorldApplicationComponent implements ApplicationComponent,Configurable private HelloWorldConfigurationForm form;private String phrase;public void initComponent()public void disposeComponent()public String getComponentName()return HelloWorldApplicationComponent;public void sa

39、yHello()/Show dialog with message Messages.showMessageDialog(phrase,Sample,Messages.getInformationIcon();public String getDisplayName()/Return name of configuration icon in Settings dialog return HelloWorld;public Icon getIcon()return null;public String getHelpTopic()return null;public JComponent cr

40、eateComponent()if(form=null)form=new HelloWorldConfigurationForm();return form.getRootComponent();public boolean isModified()return form!=null&form.isModified(this);public void apply()throws ConfigurationException if(form!=null)/Get data from form to component form.getData(this);public void reset()i

41、f(form!=null)/Reset form data from component form.setData(this);public void disposeUIResources()form=null;public String getPhrase()return phrase;public void setPhrase(final String phrase)this.phrase=phrase;为了实现 Configurable 接口,我们需要了解一下component的Form的工作原理,例如,在createComponent 方法中我们需要创建一个Form,返回其根元素。当F

42、orm被显示时,apply,reset 和 isModified 方法将被激活。当用户点击 OK按钮或Apply按钮,apply 函数将会被调用,form中的文本框将自动会更新 HelloWorldApplicationComponent 类的字段。当form被实例化后,用户点击Cancel按钮,reset 函数将会被调用,form的文本框中的值将会被重置。Form会定期调用isModified 函数更新component状态。如果函数返回 false,Apply 按钮将不会生效。当用户关闭Form时,disposeUIResources 函数将会被调用。在该方法中,你需要释放Form中涉及的

43、各种资源(在这个例子我们需要将form置为 null)。注意注意:在这个例子中,可能你已经注意到在createComponent 函数中创建Form,在disposeUIResources 函数中释放。在下一次操作中,createComponent 函数会再次创建Form,这是因为IntelliJ IDEA并未在每次调用createComponent后设置当前Look&Feel,所以保证Form和其他form的Look&Feel一样,在每次调用 createComponent 函数时,你需要重新创建Form。Configurable接口同时添加了三个函数:getDisplayName 函数显示

44、该component在设置面板中的名称,getIcon 函数提供图标,getHelpTopic返回对应帮助文档中的ID。如果返回值不为空,Help按钮就会呈现。现在还需要对component进行一次更改,我们希望将component的配置信息保存起来,如保存 HelloWorldApplicationComponent类的phrase字段值。为了能够保存和恢复当前的component状态,我们的component还需实现JDOMExternalizable 接口。在 IntelliJ IDEA中,我们可以快速产生各种函数保存component的配置信息,打开 HelloWorldApplica

45、tionComponent类,按下 Alt+Insert快捷键,在弹出的菜单中选择Generate Externalization选项。注意:注意:整个操作仅当component没有实现JDOMExternalizable 接口时有效。执行操作后,IntelliJ IDEA 将会实现JDOMExternalizable 接口,并添加基本的实现代码,如readExternal函数和writeExternal函数。Generate Externalization操作产生的结果:操作产生的结果:package com.intellij.tutorial.helloWorld;import.publi

46、c class HelloWorldApplicationComponent implements ApplicationComponent,Configurable,JDOMExternalizable .public void readExternal(Element element)throws InvalidDataException DefaultJDOMExternalizer.readExternal(this,element);public void writeExternal(Element element)throws WriteExternalException Defa

47、ultJDOMExternalizer.writeExternal(this,element);从以上的例子我们可以看出,DefaultJDOMExternalizer 工具类可以保存和恢复component的状态。这个类可以保存指定对象的所有public字段值。现在,phrase字段是private,这个字段会被忽略,所以为了保存phrase值,我们需要将phrase字段的private改为public,同时需要给phrase设定默认值。将将HelloWorldApplicationComponent类的类的phrase字字段设为段设为public package com.intellij.

48、tutorial.helloWorld;import.public class HelloWorldApplicationComponent implements ApplicationComponent,Configurable,JDOMExternalizable .public String phrase=Hello World!;.注意注意:如果不可能将字段设为public,而又要保存这些值,你可以只需使用JDOM 模型保存和恢复这些字段值(或使用JDOMExternalizerUtil 类),而不必使用DefaultJDOMExternalizer 类。JDOMExternalize

49、rUtil 类可以让你使用writeField函数 和 readField函数写入和读取JDOM模型的属性值。现在已经可以启动插件啦,请按下Shift+F9,切换到新的IntelliJ IDEA 实例窗口,点击 File-Settings 菜单项。注意注意:目前我们还没有设置component的图标(getIcon 函数返回值null),IntelliJ IDEA 会自动显示默认的yellow star图标。在Form输入新的字符串,而不是Hello World!,例如,Caramba!Corrida!,保存更改。回到主界面,点击 Window-Say Hello 菜单项。如果你想验证IDEA

50、是否真正保存component信息,你可以重新启动IDEA的debug实例,再点击 Window-Say Hello菜单项,将会呈现以下对话框。我们已经创建和启动了插件,但是我们还没有对plugin.xml进行任何编辑,IntelliJ IDEA帮我们完成了这一切。在某些情况下,我们可能需要手动编辑该文件,这也是我们要在这部分讲诉的。插件插件标识标识 除了设置插件的名称,你可能还需要设置插件的标识,只需设置 id元素即可。和插件名称不一样,标识符不能包含空格,标识符可以用于插件之间的依赖关系。插件插件之间之间的依赖关系的依赖关系 如果你的插件要使用其他插件的API,可以在 plugin.xml

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁