GEF入门实例_总结_04_Eclipse插件启动流程分析
一、前言
本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏
注意到app目录下的6个类文件。
这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们将通过这几个文件来了解Eclipse插件的启动过程。
二、Eclipse工作台层次结构
1.Eclipse工作台示例
(1)运行Eclipse之后,出现下图所示界面,其中顶层窗口就是Eclipse的工作台窗口。
(2)每个工作台窗口又包括菜单栏、工具栏、状态栏 和 多个工作台页面
(3)每个工作台页面又包含多个视图、编辑器
顶层窗口就是Eclipse的工作台窗口
三、6个类文件的作用
这六个类文件的作用如下:
序号 | 类名 | 作用 |
1 | Application | RCP应用程序的入口 |
2 | ApplicationWorkbenchAdvisor | 负责应用程序生命周期管理 |
3 | ApplicationWorkbenchWindowAdvisor | 负责窗口生命周期管理。控制窗口界面的UI元素 |
4 | ApplicationActionBarAdvisor | 负责定义创建窗口的行为。 负责创建菜单栏、工具栏、状态行 |
5 | Perspective | 默认透视图,负责界面布局的安排 |
6 | Activator | 控制插件的生命周期 |
1.Application
- package gef.tutorial.step.app;
- import org.eclipse.equinox.app.IApplication;
- import org.eclipse.equinox.app.IApplicationContext;
- import org.eclipse.swt.widgets.Display;
- import org.eclipse.ui.IWorkbench;
- import org.eclipse.ui.PlatformUI;
- /**
- * This class controls all aspects of the application's execution
- */
- public class Application implements IApplication {
- @Override
- public Object start(IApplicationContext context) throws Exception {
- Display display = PlatformUI.createDisplay();
- try {
- //========工作台打开之前,可做登录操作
- //即将打开工作台
- int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
- if (returnCode == PlatformUI.RETURN_RESTART)
- return IApplication.EXIT_RESTART;
- else
- return IApplication.EXIT_OK;
- } finally {
- display.dispose();
- }
- }
- @Override
- public void stop() {
- if (!PlatformUI.isWorkbenchRunning())
- return;
- final IWorkbench workbench = PlatformUI.getWorkbench();
- final Display display = workbench.getDisplay();
- display.syncExec(new Runnable() {
- public void run() {
- if (!display.isDisposed())
- workbench.close();
- }
- });
- }
- }
(1)Application类是RCP程序的入口,它实现了IApplication接口,在RCP程序启动时会执行该接口的start方法。
(2)事件循环:工作台启动之后,会处于持续打开状态。这时,应用程序开始处理用户的鼠标单击、移动、按键等各种事件,一直到用户关闭程序退出,这就是所谓的事件循环。
2.ApplicationWorkbenchAdvisor
- package gef.tutorial.step.app;
- import org.eclipse.ui.application.IWorkbenchConfigurer;
- import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
- import org.eclipse.ui.application.WorkbenchAdvisor;
- import org.eclipse.ui.application.WorkbenchWindowAdvisor;
- public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor {
- private static final String PERSPECTIVE_ID = "gef.tutorial.step.perspective"; //$NON-NLS-1$
- @Override
- public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
- return new ApplicationWorkbenchWindowAdvisor(configurer);
- }
- /**1.在工作台开始运行之前执行初始化操作。
- * 在打开任何窗口之前,在工作台初始化期间调用此方法。
- *
- */
- @Override
- public void initialize(IWorkbenchConfigurer configurer) {
- super.initialize(configurer);
- //1.1 设置应用程序每次退出时保存当前窗口状态
- configurer.setSaveAndRestore(true);
- }
- /**
- * 2.指定工作台的初始透视图
- */
- @Override
- public String getInitialWindowPerspectiveId() {
- return PERSPECTIVE_ID;
- }
- }
(1)负责应用程序生命周期管理。
(2)可以在该类中实现程序启动或关闭时的某种处理
(3)主要方法
序号 | 方法名 | 生命周期 | 用法 |
1 | initialize | 最先调用。在工作台开始运行之前执行一些初始化操作。 | 可用来处理初始化配置操作 |
2 | preStartup | initialize之后、第一个窗口打开之前调用 | 可以用来处理临时或者可选处理操作 |
3 | postStartup | 第一个窗口打开之后但启动事件循环之前调用 | 可以用来进行那些需要自动处理的动作 |
4 | preShutdown | 事件循环结束之后但工作台关闭之前调用 | 可以用来进行保存数据、关闭数据库服务器等操作 |
5 | postShutdown | 工作台关闭之后调用 | 可以用来进行保存应用程序 |
3.ApplicationWorkbenchWindowAdvisor
- package gef.tutorial.step.app;
- import org.eclipse.swt.graphics.Point;
- import org.eclipse.ui.application.ActionBarAdvisor;
- import org.eclipse.ui.application.IActionBarConfigurer;
- import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
- import org.eclipse.ui.application.WorkbenchWindowAdvisor;
- public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
- public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
- super(configurer);
- }
- /**
- * 1.创建一个新的action bar advisor
- * 指定由ApplicationActionBarAdvisor来配置窗口的操作条。
- */
- @Override
- public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
- return new ApplicationActionBarAdvisor(configurer);
- }
- /**
- * 2.在窗口打开之前执行
- */
- @Override
- public void preWindowOpen() {
- IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
- //1.设置窗口初始化大小
- configurer.setInitialSize(new Point(700, 550));
- //2.显示工具栏
- configurer.setShowCoolBar(true);
- //3.不显示状态栏
- configurer.setShowStatusLine(false);
- //4.设置窗口标题
- configurer.setTitle("GEF入门实例"); //$NON-NLS-1$
- }
- }
(1)负责应用程序窗口生命周期管理。
(2)该类扩展自WorkbenchWindowAdvisor。每个应用程序都需要一个WorkbenchWindowAdvisor 来控制窗口界面的UI元素。
开发人员可以控制窗口创建时(或其他生命周期时)的大小、标题、位置等。
(3)主要方法
序号 | 方法名 | 生命周期 | 用法 |
1 | preWindowOpen | 窗口控件创建之前调用 | 可用于设置窗口的初始大小、状态栏、工具栏等的可视性 |
2 | postWindowRestore | 当窗口根据上一次的保存状态恢复创建之后调用 | 可用于调整窗口的恢复状态 |
3 | postWindowCreate | 窗口创建之后调用 | 可用于调整窗口 |
4 | postWindowOpen | 窗口已经打开之后调用 | 可用于注册窗口监听,例如在此方法中实现系统托盘 |
4.ApplicationActionBarAdvisor
- package gef.tutorial.step.app;
- import org.eclipse.jface.action.ICoolBarManager;
- import org.eclipse.jface.action.IMenuManager;
- import org.eclipse.jface.action.MenuManager;
- import org.eclipse.jface.action.Separator;
- import org.eclipse.jface.action.ToolBarManager;
- import org.eclipse.swt.SWT;
- import org.eclipse.ui.IWorkbenchWindow;
- import org.eclipse.ui.actions.ActionFactory;
- import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
- import org.eclipse.ui.application.ActionBarAdvisor;
- import org.eclipse.ui.application.IActionBarConfigurer;
- import gef.tutorial.step.action.DiagramAction;
- public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
- private IWorkbenchAction exitAction;
- private IWorkbenchAction aboutAction;
- private DiagramAction diagramAction;
- public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
- super(configurer);
- }
- /**
- * 1.注册菜单或者工具栏的Action。Action只有注册后才能添加到菜单中。
- *
- */
- @Override
- protected void makeActions(IWorkbenchWindow window) {
- //退出
- exitAction = ActionFactory.QUIT.create(window);
- register(exitAction);
- //关于
- aboutAction = ActionFactory.ABOUT.create(window);
- register(aboutAction);
- //绘图
- diagramAction = new DiagramAction(window);
- register(diagramAction);
- }
- /**
- * 2.填充菜单栏。用Action来填充菜单
- *
- * (1) 菜单管理器负责管理菜单项、设置菜单行为、创建级联菜单或者对菜单项进行分组。
- * (2) MenuManager构造函数:菜单项文本、菜单项ID
- * (3) new Separator() 为一条分割线
- */
- @Override
- protected void fillMenuBar(IMenuManager menuBar) {
- //(1)一级菜单 File
- MenuManager fileMenuManager= new MenuManager("File", "fileMenuManager");
- //加入绘图动作,是叶子节点菜单,也是二级菜单。点击之后将执行Action的run方法
- fileMenuManager.add(diagramAction);
- //加入分隔符
- fileMenuManager.add(new Separator());
- //加入退出动作
- fileMenuManager.add(exitAction);
- //(2)一级菜单 Help
- MenuManager helpMenuManager = new MenuManager("Help", "helpMenuManager");
- helpMenuManager.add(aboutAction);
- //加入二级菜单
- helpMenuManager.add(fileMenuManager);
- //(3)将菜单加入菜单栏
- menuBar.add(fileMenuManager);
- menuBar.add(helpMenuManager);
- }
- /**
- * 3.填充工具栏。用Action来填充工具栏
- * (1) 工具栏默认是不显示。在 ApplicationWorkbenchWindowAdvisor 类中的
- * preWindowOpen方法中有一句 configurer.setShowCoolBar(false);将false改为true即可显示工具栏
- * (2) 工具栏管理器负责工具栏的分类管理
- * (3) SWT.FLAT将工具栏设置成平滑方式,SWT.SHADOW_OUT用于在工具栏和菜单栏之间加一条分割线
- *
- */
- @Override
- protected void fillCoolBar(ICoolBarManager coolBar) {
- //1.生成工具栏
- ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT | SWT.SHADOW_OUT);
- //2.将工具放入工具栏
- toolBarManager.add(diagramAction);
- //3.将工具栏放入
- coolBar.add(toolBarManager);
- }
- }
(1)负责定义创建窗口的行为。
(2)该类扩展自ActionBarAdvisor,用于创建菜单栏、工具栏、状态行
(3)主要方法
序号 | 方法名 | 用法 |
1 | makeActions | 注册菜单或者工具栏的工作 |
2 | fillMenuBar | 添加菜单栏 |
3 | fillCoolBar | 添加工具栏 |
4 | fillStatusLine | 添加状态栏 |
5.Perspective
- package gef.tutorial.step.app;
- import org.eclipse.ui.IFolderLayout;
- import org.eclipse.ui.IPageLayout;
- import org.eclipse.ui.IPerspectiveFactory;
- public class Perspective implements IPerspectiveFactory {
- public void createInitialLayout(IPageLayout layout) {
- //一、基本配置
- //1.1 获取布局的编辑器
- final String editorArea = layout.getEditorArea();
- //1.2 设置显示编辑区
- layout.setEditorAreaVisible(true);
- //二、添加各种视图
- //2.1 添加属性视图
- IFolderLayout bottomFolder = layout.createFolder("bottom",IPageLayout.BOTTOM, 0.75f, editorArea);
- bottomFolder.addView(IPageLayout.ID_PROP_SHEET);
- //2.2 添加大纲视图
- IFolderLayout rightBottomFolder = layout.createFolder("right",IPageLayout.RIGHT, 0.75f, editorArea);
- rightBottomFolder.addView(IPageLayout.ID_OUTLINE);
- }
- }
(1)是程序默认的透视图
(2)负责初始页面布局并显示
(3)主要方法
方法名 | 用法 |
createInitialLayout |
创建页面的初始布局。此方法的实现人员可以向透视图添加其他视图。 |
6.Activator
- package gef.tutorial.step.app;
- import org.eclipse.jface.resource.ImageDescriptor;
- import org.eclipse.ui.plugin.AbstractUIPlugin;
- import org.osgi.framework.BundleContext;
- /**
- * The activator class controls the plug-in life cycle
- */
- public class Activator extends AbstractUIPlugin {
- // The plug-in ID
- public static final String PLUGIN_ID = "gef.tutorial.step"; //$NON-NLS-1$
- // The shared instance
- private static Activator plugin;
- /**
- * The constructor
- */
- public Activator() {
- }
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- public void start(BundleContext context) throws Exception {
- super.start(context);
- plugin = this;
- }
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- public void stop(BundleContext context) throws Exception {
- plugin = null;
- super.stop(context);
- }
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static Activator getDefault() {
- return plugin;
- }
- /**
- * Returns an image descriptor for the image file at the given
- * plug-in relative path
- *
- * @param path the path
- * @return the image descriptor
- */
- public static ImageDescriptor getImageDescriptor(String path) {
- return imageDescriptorFromPlugin(PLUGIN_ID, path);
- }
- }
(1)是插件类,控制插件的生命周期
(2)见第二节: GEF入门实例_总结_02_新建初始RCP空项目 ,如下图,
若2处勾选 "This plug-in will make contributions to the UI",表示插件对UI进行添加,则此类将扩展自AbstractUIPlugin。
否则,该类扩展自 AbstractUIPlugin 的父类 Plugin。
(3)主要方法
序号 | 方法名 | 作用 |
1 | start | 插件启动时的处理 |
2 | stop | 插件停止时的处理 |
3 | getDefault | 获取默认的插件类实例。单例模式。 |
4 | getImageDescriptor | 根据插件相对路径返回图片描述符,可用于获取图片 |
四、Eclipse插件启动流程图
有问题的地方:第9步的实际的具体流程我暂时还不清楚。
Eclipse启动流程图如下,都是自己总结的,所以可能有不当之处,希望读者能解惑并将其完善。
温馨提示:可将下图拖入浏览器中查看原图
五、Eclipse插件启动流程分析
以下流程与上述流程图步骤对应,通过进行断点调试,可发现启动流程如下:
0.run
首先是运行插件,可参见: GEF入门实例_总结_02_新建初始RCP空项目 的 “三、启动项目” 部分。
(1)其中注意上图:run an application ,这里主要是设置程序的入口,这里我们选择的是 “gef.tutorial.step.application”,含义为(插件ID).(扩展点 runtime.applications 的ID)。
(2)打开plugin.xml,在overview页,可以看到插件id为gef.tutorial.step
(3)在 Extensions 页,可以看到扩展点“org.eclipse.core.runtime.applications”的 ID 为 application。
(4)至此,我们知道插件启动时,执行这个扩展点,那为啥会执行到Application类中去呢?如下图:
1.插件启动
Application.start
如上所述,因为Run Configuration 中 run an application 配置的入口程序为 Application 类,因此程序启动时,会执行到 Application 的 start 方法中来。
- int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
然后由此处代码创建一个 ApplicationWorkbenchAdvisor ,并进行到第二步
2.获取工作台窗口初始透视标识
ApplicationWorkbenchAdvisor.getInitialWindowPerspectiveId
- /**
- * 2.指定工作台的初始透视图
- */
- @Override
- public String getInitialWindowPerspectiveId() {
- return PERSPECTIVE_ID;
- }
3.创建workbench window advisor
ApplicationWorkbenchAdvisor.createWorkbenchWindowAdvisor
- @Override
- public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
- return new ApplicationWorkbenchWindowAdvisor(configurer);
- }
在这一步去创建了 ApplicationWorkbenchWindowAdvisor ,通过这个Advisor 可以配置工作台窗口。
4.窗口打开前的处理
ApplicationWorkbenchWindowAdvisor.preWindowOpen
- /**
- * 2.在窗口打开之前执行
- */
- @Override
- public void preWindowOpen() {
- IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
- //1.设置窗口初始化大小
- configurer.setInitialSize(new Point(700, 550));
- //2.显示工具栏
- configurer.setShowCoolBar(true);
- //3.不显示状态栏
- configurer.setShowStatusLine(false);
- //4.设置窗口标题
- configurer.setTitle("GEF入门实例"); //$NON-NLS-1$
- }
在窗口打开前,设置了窗口大小、标题、工具栏与状态栏的可视性
5.创建 ActionBarAdvisor
ApplicationWorkbenchWindowAdvisor.createActionBarAdvisor
- /**
- * 1.创建一个新的action bar advisor
- * 指定由ApplicationActionBarAdvisor来配置窗口的操作条。
- */
- @Override
- public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
- return new ApplicationActionBarAdvisor(configurer);
- }
6.注册菜单或者工具栏的Action
ApplicationActionBarAdvisor.makeActions
- /**
- * 1.注册菜单或者工具栏的Action。Action只有注册后才能添加到菜单中。
- *
- */
- @Override
- protected void makeActions(IWorkbenchWindow window) {
- //退出
- exitAction = ActionFactory.QUIT.create(window);
- register(exitAction);
- //关于
- aboutAction = ActionFactory.ABOUT.create(window);
- register(aboutAction);
- //绘图
- diagramAction = new DiagramAction(window);
- register(diagramAction);
- }
7.填充菜单栏
ApplicationActionBarAdvisor.fillMenuBar
- /**
- * 2.填充菜单栏。用Action来填充菜单
- *
- * (1) 菜单管理器负责管理菜单项、设置菜单行为、创建级联菜单或者对菜单项进行分组。
- * (2) MenuManager构造函数:菜单项文本、菜单项ID
- * (3) new Separator() 为一条分割线
- */
- @Override
- protected void fillMenuBar(IMenuManager menuBar) {
- //(1)一级菜单 File
- MenuManager fileMenuManager= new MenuManager("File", "fileMenuManager");
- //加入绘图动作,是叶子节点菜单,也是二级菜单。点击之后将执行Action的run方法
- fileMenuManager.add(diagramAction);
- //加入分隔符
- fileMenuManager.add(new Separator());
- //加入退出动作
- fileMenuManager.add(exitAction);
- //(2)一级菜单 Help
- MenuManager helpMenuManager = new MenuManager("Help", "helpMenuManager");
- helpMenuManager.add(aboutAction);
- //加入二级菜单
- helpMenuManager.add(fileMenuManager);
- //(3)将菜单加入菜单栏
- menuBar.add(fileMenuManager);
- menuBar.add(helpMenuManager);
- }
8.填充工具栏
ApplicationActionBarAdvisor.fillCoolBar
- /**
- * 3.填充工具栏。用Action来填充工具栏
- * (1) 工具栏默认是不显示。在 ApplicationWorkbenchWindowAdvisor 类中的
- * preWindowOpen方法中有一句 configurer.setShowCoolBar(false);将false改为true即可显示工具栏
- * (2) 工具栏管理器负责工具栏的分类管理
- * (3) SWT.FLAT将工具栏设置成平滑方式,SWT.SHADOW_OUT用于在工具栏和菜单栏之间加一条分割线
- *
- */
- @Override
- protected void fillCoolBar(ICoolBarManager coolBar) {
- //1.生成工具栏
- ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT | SWT.SHADOW_OUT);
- //2.将工具放入工具栏
- toolBarManager.add(diagramAction);
- //3.将工具栏放入
- coolBar.add(toolBarManager);
- }
9.getInitialWindowPerspectiveId(有疑问)
ApplicationWorkbenchAdvisor.getInitialWindowPerspectiveId
- /**
- * 2.指定工作台的初始透视图
- */
- @Override
- public String getInitialWindowPerspectiveId() {
- return PERSPECTIVE_ID;
- }
断点调试时是又走了一遍此方法,
至于为啥走了两遍,怎么走到第10步的,这个还不清楚。
希望读者能为我解惑,不胜感激。
10.创建默认透视图的初始布局
Perspective.createInitialLayout
- package gef.tutorial.step.app;
- import org.eclipse.ui.IFolderLayout;
- import org.eclipse.ui.IPageLayout;
- import org.eclipse.ui.IPerspectiveFactory;
- public class Perspective implements IPerspectiveFactory {
- public void createInitialLayout(IPageLayout layout) {
- //一、基本配置
- //1.1 获取布局的编辑器
- final String editorArea = layout.getEditorArea();
- //1.2 设置显示编辑区
- layout.setEditorAreaVisible(true);
- //二、添加各种视图
- //2.1 添加属性视图
- IFolderLayout bottomFolder = layout.createFolder("bottom",IPageLayout.BOTTOM, 0.75f, editorArea);
- bottomFolder.addView(IPageLayout.ID_PROP_SHEET);
- //2.2 添加大纲视图
- IFolderLayout rightBottomFolder = layout.createFolder("right",IPageLayout.RIGHT, 0.75f, editorArea);
- rightBottomFolder.addView(IPageLayout.ID_OUTLINE);
- }
- }
在这一步创建工作台默认透视图的初始布局,可在此方法中添加其他视图。
这样窗口就创建好了
11.窗口创建之后
ApplicationWorkbenchWindowAdvisor.postWindowCreate
在窗口创建完毕之后,会执行此方法。可用此方法来调整窗口
六、参考资料
1.《Eclipse RCP 应用系统开发方法与实践》
2.《Eclipse插件开发学习笔记》
3.本系列总结配套PDF教程《GEF开发简单实例.pdf》
GEF入门实例_总结_04_Eclipse插件启动流程分析的更多相关文章
- GEF入门实例_总结_05_显示一个空白编辑器
一.前言 本文承接上一节:GEF入门实例_总结_04_Eclipse插件启动流程分析 在第三节( GEF入门实例_总结_03_显示菜单和工具栏 ),我们创建了菜单和工具栏. 这一节,我们来实现:点击 ...
- GEF入门实例_总结_02_新建初始RCP空项目
一.前言 本节承接上一节: GEF入门实例_总结_01_教程.源码.开发环境准备 这一节我们来创建一个空的RCP项目. 二.新建RCP项目 1. New 一个 Plug-in Project 2.输入 ...
- GEF入门实例_总结_06_为编辑器添加内容
一.前言 本文承接上一节:GEF入门实例_总结_05_显示一个空白编辑器 在上一节我们为我们的插件添加了一个空白的编辑器,这一节我们将为此编辑器添加内容. 二.GEF的MVC模式 在此只简单总结一下, ...
- GEF入门实例_总结_03_显示菜单和工具栏
一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar 含义 a ...
- GEF入门实例_总结_01_教程、源码、开发环境准备
一.前言 最近在学Eclipse插件开发,发现了一个比较好的GEF入门教程,并且按照教程上的操作,一步步实现了一个入门Demo,在此感谢作者的贡献. 好记性不如烂笔头,故决定总结一下这段时间的学习心得 ...
- u-boot启动流程分析(2)_板级(board)部分
转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...
- u-boot启动流程分析(1)_平台相关部分
转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...
- Netty 拆包粘包和服务启动流程分析
Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...
- 【转】Netty 拆包粘包和服务启动流程分析
原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...
随机推荐
- 如何配置一个路径,能够既适合Linux平台,又适合Windows平台,可以从这个路径中读取文件
如何配置一个路径,能够既适合Linux平台,又适合Windows平台,可以从这个路径中读取文件? 目的:就是希望在项目的配置文件中配上一样的路径,不管协作者使用的是什么平台,都能够读到文件. 比如:L ...
- equal?, == and eql?, ===,
1.BasicObject中定义了 == 和equal?这两个方法,两个方法等价,用来比较两个对象是否是同一个对象,是的话结果就为true. 既然两者相同,为何要定义两个呢?只是为了再命名一个别名吗? ...
- Loadrunder之脚本篇——参数类型
Internal data Date/Time,Group Name,Iteration Number,Load Generator Name,Ramdom Number,Table,Unique N ...
- yii异常处理架构
使用方法: use \yii\base\ErrorException; try { exec("curl http://xxx",$out,$retno); if(0 !== $r ...
- BFC与边距重叠详解
1.什么是BFC? 在解释 BFC 是什么之前,需要先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位Box 是 CSS 布局的对象和基本单位, 直观点来说, ...
- P3825 [NOI2017]游戏
题目 P3825 [NOI2017]游戏 做法 \(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\pri ...
- linux创建指定大小的文件
一.生成文件大小和实际占空间大小一样的文件 dd if=/dev/zero of=50M.file bs=1M count=50 dd if=/dev/zero of=20G.file bs=1G c ...
- Scrapy安装方法
Scrapy安装在Python2.7环境下 1.配置环境变量: 2.安装基础软件 4个(64位系统) 安装twisted: C:\Users\Administrator>pip install ...
- etcd 安装部署
etcd 是coreos团队开发的分布式服务发现键值存储仓库. github地址: https://github.com/coreos/etcd 安装: 1.下载etcd最新版本 https://gi ...
- Python 条件判断语句(if ,elif, else)
条件判断可以分: 单分支判断:只有一个if语句 双分支判断:if else 的格式 多分支判断:if elif else 的格式 条件语句嵌套判断 # 下面是个条件多分支判断 score = 85 ...