-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
78 lines (36 loc) · 55.1 KB
/
search.xml
File metadata and controls
78 lines (36 loc) · 55.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>emf持久化框架</title>
<link href="/2023/04/03/emf-kuang-jia/emf-chi-jiu-hua/"/>
<url>/2023/04/03/emf-kuang-jia/emf-chi-jiu-hua/</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="EMF框架"><a href="#EMF框架" class="headerlink" title="EMF框架"></a>EMF框架</h1><h2 id="持久化(Persistence)"><a href="#持久化(Persistence)" class="headerlink" title="持久化(Persistence)"></a>持久化(Persistence)</h2><p> EMF拥有一个强大的模型持久化框架。通过一个高度可定制资源实现(resource implementation)来支持XML序列化。<br> EMF不要求持久化是基于XML或者是基于流(stream)。这个框架提供的API灵活到足以支持任何种类的存储,甚至在不同类型的存储中保存对象,其中包含引用。</p><p>持久化框架的概述<br> EMF中持久化的基本单元叫做资源(resource),它是一个或多个与其内容一起持久化的对象的容器。<br> EMF对象由Resource接口来进行持久化,方法是将对象添加到资源的内容列表中,然后调用save()方法,例子如下:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">PurchaseOrder</span> po <span class="token operator">=</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token class-name">Resource</span> resource <span class="token operator">=</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>resource<span class="token punctuation">.</span><span class="token function">getContents</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>po<span class="token punctuation">)</span><span class="token punctuation">;</span>resource<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p> 这个例子中,这里,purchaseOrder被添加到resource的内容中,然后被保存。如果purchaseOrder包含任何其他对象,例如,一个item list,默认情况下,它们将与其一起保存在同一资源中。如果它通过非包含引用(non-containment reference)引用任何其他对象,我们有责任确保其他对象包含在资源中:它可以直接添加到同一个资源或另一个资源中,或者它可以直接或间接包含在资源中的对象中。否则,当资源被持久化时,引用将被丢弃。<br> 如果我们想要指定一些要在保存操作中使用的选项,save()的参数(a Map)将是非空的。<br> 持久化的逆操作,从持久化形式中在内存中重建活动(actiive)的对象。使用load()方法从资源的内容列表中访问对象:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">Resource</span> resource <span class="token operator">=</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>resource<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">PurchaseOrder</span> po <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">PurchaseOrder</span><span class="token punctuation">)</span>resource<span class="token punctuation">.</span><span class="token function">getContents</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><p> Resource接口的详细说明在15.2.3。<br> 前面的代码片段至少提出了几个问题:XML序列化在哪里被写入或读取,以及我们最初是如何获得resource的。<br> 为了管理不同资源中对象之间的引用,EMF的持久性框架包括另一个接口,称为ResourceSet,它充当资源的容器。getResources()方法返回集合中的资源列表。通常,Resource是通过ResourceSet创建的,可以显式创建,也可以作为按需加载的一部分自动创建。例如:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">ResourceSet</span> resourceSet <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ResourceSetImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> uri <span class="token operator">=</span> <span class="token constant">URI</span><span class="token punctuation">.</span><span class="token function">createURI</span><span class="token punctuation">(</span><span class="token string">"file:/c:/data/out.epo2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">Resource</span> resource <span class="token operator">=</span> resourceSet<span class="token punctuation">.</span><span class="token function">createResource</span><span class="token punctuation">(</span>uri<span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><p> 在这里,我们创建一个resource set[1],然后在其上调用createResource()显式地创建一个资源。我们将分配给资源的统一资源标识符(URI)传递给这个方法,以便在资源集中标识它。稍后,当我们调用save()或load()时,资源可以使用这个URI来确定向何处写入或从何处读取。这里,我们使用了一个简单的文件模式URI来直接指定本地文件系统中的一个位置。我们将在15.2.1节讨论其他支持的URI类型。<br> [1]EMF没有为资源集提供factory。由用户来实例化适当的实现。ResourceSetImpl是一个功能性的、灵活的实现,通常应该足够了。但是,如果需要,可以对其进行扩展和定制。<br> 传递给createResource()的URI还有另一个用途。资源集维护resource set的注册表。为了创建一个资源,它查询这个注册中心,根据指定的URI获得一个合适的factory。正是这个factory实际上创建了resource ,并因此决定了如何持久化对象。<br> 注册表根据模式(scheme)或者文件扩展名(file extension)来选择资源工厂。我们可以对.epo2文件扩展名注册EMF的默认XMI资源工厂:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java">resourceSet<span class="token punctuation">.</span><span class="token function">getResourceFactoryRegistry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getExtensionToFactoryMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"epo2"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">XMIResourceFactoryImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p> 当使用Eclipse里生成的模型时,这种注册不是必要的,因为相似的注册会通过模型插件(model plug-in)的清单文件(manifest file)中指定的扩展名来自动地执行。然而,当独立运行时,注册必须被明确地执行。否则,createResource()将无法创建资源并且会返回null。详见15.2.4的Resource的嵌套工厂和Registry接口以及15.2.5的ResourceSet<br> 现在已经有了对持久化框架的足够理解,来编写简单但有效的程序来保存PurchaseOrder:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">PurchaseOrder</span> po <span class="token operator">=</span> <span class="token function">createPurchaseOrder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">ResourceSet</span> resourceSet <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ResourceSetImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>resourceSet<span class="token punctuation">.</span><span class="token function">getResourceFactoryRegistry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getExtensionToFactoryMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"epo2"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">XMIResourceFactoryImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> uri <span class="token operator">=</span> <span class="token constant">URI</span><span class="token punctuation">.</span><span class="token function">createURI</span><span class="token punctuation">(</span><span class="token string">"file:/c:/data/out.epo2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">Resource</span> resource <span class="token operator">=</span> resourceSet<span class="token punctuation">.</span><span class="token function">createResource</span><span class="token punctuation">(</span>uri<span class="token punctuation">)</span><span class="token punctuation">;</span>resource<span class="token punctuation">.</span><span class="token function">getContents</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>po<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">try</span><span class="token punctuation">{</span> resource<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"saved"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"failed to write "</span> <span class="token operator">+</span> uri<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p> 这里的createPurchaseOrder()返回的是我们想要持久化的PurchaseOrder。我们将假设它创建了PurchaseOrder的实例并且向其中加入一组Items,在out.epo2的最终的序列化结果如下:</p><pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token prolog"><?xml version="1.0" encoding="ASCII"?></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">epo2:</span>PurchaseOrder</span> <span class="token attr-name"><span class="token namespace">xmi:</span>version</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>2.0<span class="token punctuation">"</span></span><span class="token attr-name"><span class="token namespace">xmlns:</span>xmi</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.omg.org/XMI<span class="token punctuation">"</span></span><span class="token attr-name"><span class="token namespace">xmlns:</span>epo2</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.example.com/epo2.ecore<span class="token punctuation">"</span></span><span class="token attr-name">comment</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rush order<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>items</span> <span class="token attr-name">productName</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>apple<span class="token punctuation">"</span></span> <span class="token attr-name">quantity</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token attr-name">partNum</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>3313<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>items</span> <span class="token attr-name">productName</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>orange<span class="token punctuation">"</span></span> <span class="token attr-name">quantity</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token attr-name">partNum</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>9145<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token namespace">epo2:</span>PurchaseOrder</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p> 从其持久化形式中加载采购清单的程序如下:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">EPO2Package</span> epo2Package <span class="token operator">=</span> <span class="token class-name">EPO2Package</span><span class="token punctuation">.</span>eINSTANCE<span class="token punctuation">;</span><span class="token class-name">ResourceSet</span> resourceSet <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ResourceSetImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>resourceSet<span class="token punctuation">.</span><span class="token function">getResourceFactoryRegistry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getExtensionToFactoryMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"epo2"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">XMIResourceFactoryImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> uri <span class="token operator">=</span> <span class="token constant">URI</span><span class="token punctuation">.</span><span class="token function">createURI</span><span class="token punctuation">(</span><span class="token string">"file:/c:/data/out.epo2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">Resource</span> resource <span class="token operator">=</span> resourceSet<span class="token punctuation">.</span><span class="token function">createResource</span><span class="token punctuation">(</span>uri<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">try</span><span class="token punctuation">{</span> resource<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">PurchaseOrder</span> po <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">PurchaseOrder</span><span class="token punctuation">)</span>resource<span class="token punctuation">.</span><span class="token function">getContents</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"loaded: "</span> <span class="token operator">+</span> po<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"failed to read "</span> <span class="token operator">+</span> uri<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>第一行访问采购订单模型的包,将包注册为副作用(side effect)。如14.1.2节中所讨论的,生成的包在被第一次访问时会自动在全局包注册表中注册。资源依赖于能够找到一个注册的包来反射性地实例化它所描述的类。然而,像资源工厂(resource factory)一样,只有在独立运行时(stand-alone)才需要这个显式注册步骤,因为它是通过Eclipse下的扩展点(扩展指针(extension point)?)自动完成的。我们将在第20章进一步讨论独立运行(stand-alone)应用程序。</p><p>思考:存在文件名的问题,使用diagram name 作为文件名应该可行。</p><h2 id="EMF持久化API"><a href="#EMF持久化API" class="headerlink" title="EMF持久化API"></a>EMF持久化API</h2><p> EMF持久化框架以四个基础接口为中心:Resource,ResourceSet, Resource.Factory, URIConverter。在本节中,我们将描述每个接口,指出其设计中最重要的方面,并描述其基本实现的行为以及如何扩展它们。 然而,在我们开始描述这些接口之前,我们应该了解一些关于URIs的细节,它在持久性框架中起着至关重要的作用。</p><h3 id="URI"><a href="#URI" class="headerlink" title="URI"></a>URI</h3><p>EMF在其持久性框架中广泛使用了URIs。正如我们在15.1节中看到的,URIs被用来唯一地标识资源。EMF还使用URIs来引用资源中的对象和标识包。URI是一个用于识别和定位各种类型数据的开放式标准。数据可以是文件系统或互联网上的某个文件,文件中的某个对象,或者某种数据库中的某个对象,或者可以想象的任何其他类型的数据。</p><p>URI是由三个基本部分组成的字符串: scheme、scheme-specific部分、可选片段。EMF包括一个URI实现类org.eclipse.emf.common.util.URI,它提供了使用和操作URI及其部件(part)的便捷方式。</p><ol><li>schema</li></ol><p>URI scheme标识用于访问资源的协议。一些常见的是“file”和“jar”,前者直接标识文件的位置,后者标识在JAR文件中归档的文件。在Eclipse中,我们使用URIs的“platform” scheme来识别Eclipse特定位置的资源,例如工作区或运行工作台中的外部插件。</p><p>scheme是URI的第一个part,通过“:”字符与其余part分隔开。例如,platform:/resource/data/po.xml是一个platform-scheme URI。</p><ol start="2"><li>schema-specific</li></ol><p>schema-specific包括schema和fragment之间的所有内容。EMF所关注的schema倾向于为这一部分使用一种通用的层次格式。这种格式可以包括授权(authority)、设备和任意数量的片段(segment)。如果包括授权(authority),则使用“//”将其与方案分开。它通常指定网络环境中的主机。设备(如果包含)是 以“/”开头。最后,这些段(如果有的话)也以“/”开头或彼此分开。设备和段一起构成了资源位置的本地路径。例如,下面是一个不包含授权的file-schema类型URI,有一个设备和三个段:file:/c:/dir1/dir2/myfile.xml[3]</p><p>[3] 您可能以前见过稍微不同的文件模式URIs,比如file:///c:/dir 1/dir 2/my file.XML。因为有了额外的“//”,这个URI指定一个空字符串作为它的授权,而另一个则根本没有指定任何授权。两者指的是同一个资源,但从URIs的角度相比较,它们是不同的。</p><p>前面提到的platform-schema也为其schema-specific的部分使用分层格式。platform URI没有授权和设备字段,但对路径的第一段赋予了特殊的意义。例如,它可以是“resource”来标识工作区中的资源,或者是“plugin”来标识外部插件中的资源。路径的剩余部分是工作区或插件路径,分别以项目名或插件ID开头。[4]</p><p>[4] 正如我们将在本章后面看到的,EMF提供了一些工具,即使在独立的应用程序中,这些工具也能为平台资源URIs赋予意义。</p><p>URI片段标识由schema和schema-specific部分指定的资源内容的一部分。它通过“#”字符与URI的其他部分分开。例如,URI文件:/c:/dir1/dir2/myfile.xml#loc标识myfile.xml中的某个内容,使用片段“loc”可以找到该内容。正如我们将在下一节看到的,EMF使用URIs和片段来引用资源中的EObjects。</p><p>URI的实例通常是通过解析字符串来创建的。一个factory方法createURI(),采用完整的URI字符串,并且提供了方便的factory方法createFileURI()和createPlatformResourceURI()来将文件路径和工作区路径转换为URIs。[5]</p><p>[5] 事实上,有多种形式的URI.createURI()和 URI.createPlatformResourceURI()。多参数形式支持对URI中不允许的任何字符(如空格)进行自动编码。一般来说,强烈建议启用这种自动编码。createURI()的单参数形式应仅用于解析已知不包含此类不允许字符的字面定义的字符串。完全不鼓励使用createPlatformResourceURI()的单参数形式。</p><p>不幸的是,EMF的URI类早于Java 1.4中标准java.net.URI实现的出现。尽管这两种表示形式不是类型兼容的,但只要在任一种形式上调用toString(),然后使用另一种形式重新解析结果字符串,就可以实现互换。</p><p>关于URI语法的更多细节,请参考因特网工程任务组RFC 3986,统一资源标识符(URI):通用语法:<a href="http://www.ietf.org/rfc/rfc3986.txt">http://www.ietf.org/rfc/rfc3986.txt</a>.</p><h4 id="创建URIs的factory方法"><a href="#创建URIs的factory方法" class="headerlink" title="创建URIs的factory方法"></a>创建URIs的factory方法</h4><table><thead><tr><th>序号</th><th>方法</th><th>用途</th></tr></thead><tbody><tr><td>1</td><td>createURI()</td><td>创建完整的URI字符串</td></tr><tr><td>2</td><td>createFileURI()</td><td>将文件路径转化为file类型字符串</td></tr><tr><td>3</td><td>createPlatformResourceURI()</td><td>将workspace路径转化为标准URIs</td></tr></tbody></table><h3 id="URIConverter"><a href="#URIConverter" class="headerlink" title="URIConverter"></a>URIConverter</h3><p> 该框架使用URIConverter接口来使URIs规范化:将一个URI转换成另一个,然后用来访问资源。它可以用于提供从命名空间URIs(例如,<a href="http://www.example.com/epo2.ecore)%E5%88%B0%E4%BB%A3%E8%A1%A8%E7%89%A9%E7%90%86URIs%E7%9A%84URIs%E7%9A%84%E6%98%A0%E5%B0%84%EF%BC%8C%E6%88%96%E8%80%85%E5%B0%86%E6%97%A7%E7%9A%84%E6%88%96%E5%88%AB%E5%90%8DURI%E5%BC%95%E7%94%A8%E9%87%8D%E5%AE%9A%E5%90%91%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BD%8D%E7%BD%AE%E3%80%82">http://www.example.com/epo2.ecore)到代表物理URIs的URIs的映射,或者将旧的或别名URI引用重定向到不同的位置。</a></p><p>URIConverter维护一组URI到URI的映射,这些映射可以由客户端指定。normalize()方法用于根据任何可能适用的映射将URI转换为其规范化形式。例如,我们可以使用URI转换器将EPackage的命名空间URI映射到物理资源,如下所示:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">URIConverter</span> converter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">URIConverterImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> uri1 <span class="token operator">=</span> <span class="token constant">URI</span><span class="token punctuation">.</span><span class="token function">createURI</span><span class="token punctuation">(</span><span class="token string">"http://www.example.com/epo2.ecore"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> uri2 <span class="token operator">=</span> <span class="token constant">URI</span><span class="token punctuation">.</span><span class="token function">createURI</span><span class="token punctuation">(</span><span class="token string">"platform:/resource/models/epo2.ecore"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>converter<span class="token punctuation">.</span><span class="token function">getURIMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>uri1<span class="token punctuation">,</span> uri2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">URI</span> normalized <span class="token operator">=</span> converter<span class="token punctuation">.</span><span class="token function">normalize</span><span class="token punctuation">(</span>uri1<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>normalized<span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>output:</p><pre class="line-numbers language-java" data-language="java"><code class="language-java">platform<span class="token operator">:</span><span class="token operator">/</span>resource<span class="token operator">/</span>models<span class="token operator">/</span>epo2<span class="token punctuation">.</span>ecore<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>如果normalize()在URIConverter的URI映射中找到逻辑URI作为关键字,它只返回相关的值。如果命名空间为URI·<a href="http://www.example.com/epo2.ecore%E7%9A%84EPackage%E5%9C%A8%E5%B7%A5%E4%BD%9C%E5%8C%BA%E4%B8%AD%E8%A2%AB%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%BA/models/epo2.ecore%EF%BC%8C%E5%88%99%E5%9C%A8%E5%8A%A0%E8%BD%BD%E6%A8%A1%E5%9E%8B%E5%AE%9E%E4%BE%8B%E6%97%B6%EF%BC%8C%E6%AD%A4%E6%98%A0%E5%B0%84%E5%85%81%E8%AE%B8%E6%A1%86%E6%9E%B6%E6%A0%B9%E6%8D%AE%E9%9C%80%E8%A6%81%E8%87%AA%E5%8A%A8%E8%AF%BB%E5%85%A5%E6%AD%A4%E5%85%83%E6%95%B0%E6%8D%AE%E3%80%82%E6%88%91%E4%BB%AC%E5%B0%86%E5%9C%A8%E7%AC%AC15.3.2%E8%8A%82%E4%B8%AD%E6%9B%B4%E8%AF%A6%E7%BB%86%E5%9C%B0%E4%BA%86%E8%A7%A3%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E6%98%AF%E5%A6%82%E4%BD%95%E5%8F%91%E7%94%9F%E7%9A%84%E3%80%82">http://www.example.com/epo2.ecore的EPackage在工作区中被序列化为/models/epo2.ecore,则在加载模型实例时,此映射允许框架根据需要自动读入此元数据。我们将在第15.3.2节中更详细地了解这种情况是如何发生的。</a></p><p>Resource<br> 前面已经说过,EMF中持久化的基本单元叫做资源(resource)。尽管资源直接关系到EObjects,但是不像从第5章描述的元模型中生成的各种Ecore接口,Resource接口事实上不会来描述模型化的类。然而,它表现的像重要的方式之一:</p><p>public interface Resource extends Notifier<br>{<br> int RESOURCE__RESOURCE_SET = 0;<br> int RESOURCE__URI = 1;<br> int RESOURCE__CONTENTS = 2;<br> …<br> ResourceSet getResourceSet();<br> URI getURI();<br> void setURI(URI uri);<br> EList getContents();<br> …<br>}</p><p> 首先,资源是通知器(notifier):多个适配器(adapter)可以被附加于一个资源,当资源改变时,将会给适配器们发送通知。可以看到,接口定义了“虚拟特征(virtual features)”,比如resourceSet,URI和内容,它们都被使用于通知中。<br> 其次,getContents()返回的列表,描绘了资源的内容,表现的十分像一个模型化的双向的引用,相反的引用由EObject中的eResource()方法实现。需要注意的是,这种关系实际上并不是真正的模式化,而是概念上的,情况如下图:</p><p> 值得强调的是,当内容虚拟特征(contents virtual feature)期望getContents()访问器时,其相反的访问器的名字,eResource(),毫无疑问是非常规的(unconventional)。这是因为它反而遵循EObject中所有其他方法使用的模式,被选择以避免与在模型化子类中生成的访问器的名称相冲突。还值得注意的是,对于eResource()没有相应的设置(set)方法,所以这个虚拟特征只能从Resource end来设置,通过将对象加入到内容列表。<br> 在URI这一节,资源默认地包含其内容列表中每个对象所包含的整个对象树。这影响到eResource()的返回值。<br> 内容虚拟特征表现的像一个普通双向特征,相反的是multiplicity-one。这就是说,如果一个对象已经存在于一个资源的内容中,将其添加到另一个则会自动地从第一个中移除。<br> 此外,内容虚拟特征展示了遏制(contaiment)语义,但仅涉及不是代理解析(proxy resolving)的模型化的遏制引用。换句话说,如果一个对象已经存在于任一模式化的非代理解析的遏制引用,把它添加到一个资源的内容中则会自动的将其从它的容器中移除。回顾第10章中遏制语义默认不是代理解析。因此,它就表现出默认阻止跨资源(cross-resource)遏制:一个对象只可以被直接放置在一个容器对象中,或者直接放置在一个资源内容中,而不能两者都放置。<br> “遏制代理”详见13.8.2。<br> 一个资源通常被一个资源集合所包含,getResourceSet()来获取。资源在集合中通过URI来唯一标识。通常在资源创建时指定URI,但是只能分别通过getURI()和setURI来访问和设置。URI通常决定资源的持久化形式将要存贮的位置。</p><p> save()和load()方法将资源从活动的内存形式复制到持久化存储,反之亦然。每个都有两种形式:</p><p>void save(Map options) throws IOException;<br>void load(Map options) throws IOException;</p><p>void save(OutputStream outputStream, Map options) throws IOException;<br>void load(InputStream inputStream, Map options) throws IOException;</p><p> EMF为资源提供了一个基础类,ResourceImpl,它通过从资源集合中获取一个URIConverter来实现每个单参数的方法,这个URIConverter用来打开资源的URI的输出或输入流,还能将流传到对应的双参数方法。因此,特定子类的作用是提供有意义的,特定于存储(storage-specific)的保存和加载实现。<br> 通过调用unload()方法可以卸载资源。卸载会将资源中所有的对象变为代理(proxy),这样的结果是,下次这些对象中之一从其他资源通过跨引用(cross-reference)被访问时,资源的请求重新加载(通过EcoreUtil.resolve())。这就可以把一个资源更新,比如自上次加载以来,底层文件( underlying file )发生了变化。isLoaded() 方法表明资源当前是否被加载。<br> 资源可以通过isModified(),来跟踪对其完整内容的任何更改,并且返回自从最近保存和加载后的变更。默认情况下,这个特性是无效的,因为它的实现昂贵而且对撤销命令是无效的,由于撤销看起来像变更。适当时候,setTrackingModification() 可以使其生效。</p><p> URI Fragments,是资源基于ResourceImpl使用类似XPath的方式来定位对象。Resource接口定义getEObject() 方法,可以根据给出的段路径(fragment path)来检索对象:</p><p>Resource resource = …<br>Item item = (Item)resource.getEObject(“//@orders.0/@items.2”);</p><p> 相反,也可以获取段路径:</p><p>Item item = …<br>String fragment = resource.getURIFragment(item);<br>1<br>2<br>Resource.Factory和Resource.Factory.Registry<br> 嵌套在Resource接口中的是Factory接口,它定义了资源如何被创建:</p><p>public interface Resource extends Notifier<br>{<br> …<br> interface Factory<br> {<br> Resource createResource(URI uri);<br> interface Descriptor<br> {<br> Factory createFactory();<br> }</p><pre><code> interface Registry { Factory getFactory(URI uri); Map getProtocolToFactoryMap(); Map getExtensionToFactoryMap(); String DEFAULT_EXTENSION = "*"; Registry INSTANCE = new ResourceFactoryRegistryImpl(); }}</code></pre><p>}</p><p> 正如这个接口建议的那样,资源工厂只是简单地知道如何去创建资源的一种类型。通过使用合适的资源工厂,就可以确定被产生的和被使用的持久化形式。<br> 嵌套在Factory中的是Registry接口,它基于特定URI,提供了选择合适资源工厂的机制。资源工厂注册表维护着两个可以注册资源工厂的map。这些map被getFactory方法咨询,以获取适合于给定URI的工厂。<br> ResourceFactoryRegistryImpl(),按照以下步骤来获取资源工厂:</p><ol><li>检查getProtocolToFactoryMap()返回的map,使用URI的模式作为关键字。</li><li>如果没有找到任何东西,检查getExtensionToFactoryMap()返回的map,使用URI的文件扩展名作为关键字。</li><li>如果仍然没有找到,就检查getExtensionToFactoryMap()返回的*map的默认值,使用DEFAULT_EXTENSION作为关键字。</li><li>如果没有找到相应的匹配,调用受保护的(protected)delegatedGetFactory()方法。默认情况下,它没有做任何事,但可以被重写(override)。</li></ol><p> 资源集合维护(maintain)着资源工厂注册表,当其需要创建资源时,就要咨询(consult)来获取工厂。此外,有一个可用的全局注册表Resource.Factory.Registry.INSTANCE,它可以注册系统中的所有资源集合。默认资源集合中注册表的实现重写了delegatedGetFactory() 来委托给全局注册表。所以仅当根据URI的模式,在局部没有找到合适的工厂时,才会根据文件扩展名(file extension)来咨询全局注册表。<br> 在持久化框架概述中说道,在Eclipse环境下运行时,资源工厂可以通过Eclipse的扩展指针机制,来被自动地注册。这样的注册是在全局注册表中完成的。<br> org.eclipse.emf.ecore.xmi 插件清单文件包含以下扩展:</p><extension point="org.eclipse.emf.ecore.extension_parser"> <parser type="*" class="org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl"></parser></extension><p> 它默认注册了XMIResoureFactoryImpl资源工厂实现。这就是为什么EMF的XMI序列化作为默认持久化格式,以及为什么在Eclipse下运行时没有要求显式的注册。<br> 如果你创建了自己的资源实现类,你需要为其创建工厂然后进行注册,以相似的方式,在你自己的插件(plug-in)中。例如,设想你已经创建了自己的资源实现类,EPO2ResourceImpl,你想要使用它来持久化.epo2资源。为此,需要创建资源工厂:</p><p>public class EPO2ResourceFactoryImpl implements Resource.Factory<br>{<br> public Resource createResource(URI uri)<br> {<br> return new EPO2ResourceImpl(uri);<br> }<br>}<br> 然后,你可以向plugin.xml文件中添加以下扩展:</p><extension point="org.eclipse.emf.ecore.extension_parser"> <parser type="epo2" class="com.example.epo2.util.EPO2ResourceFactoryImpl"></parser></extension><p> 事实上,这就是在为生成器中的包选择“资源类型(Resource Type)”时发生的事情。从以XML Schema描述的模型开始尤为重要,因为默认XML资源将不能读和写符合模式的序列化。如果注册不能完成或者你试图加载没有合适文件扩展名(file extension)的资源,Resource.load()将会抛出ClassNotFoundException。对于独立的应用程序,需要在代码进行以下等价的注册:</p><p>Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(<br> “epo2”, new EPO2ResourceFactoryImpl());</p><p> 尽管等价,这两个资源工厂注册表(registration)还是有细微差别的。后者,显式注册,工厂的实例被创建并且被注册表中的一个map直接注册。然而,前者,基于扩展名(extension-based)的注册表,实际注册的是描述符(Descriptor)。<br> 描述符,另一个嵌套在Resource.Factory中的接口,在创建资源工厂时提供了额外的间接层(indirection)的级别(level)。在完成之前所述的4步枚举型之后,如果注册获取了描述符而不是资源工厂,它将调用createFactory()并返回结果。这项功能使EMF能够推迟加载特定的资源工厂类直到这个类被真正需要时。这对基于扩展名的注册表很重要,其发生在平台启动时。</p><p>ResourceSet<br> ResourceSet是持久化API中最高级别的接口,作用相当于资源的容器,以便允许它们之间的引用。它提供了访问这些资源的途径,从模型或者一组相关联的模型中,定义了对象的上下文(context)。此外,它维护这URI转换器,资源工厂注册(resource factory registry),以及它自己使用的和用于资源的包注册(package registry)<br> 类似于Resource,ResourceSet并不表示模型化的类,但是它实现Notifier接口:</p><p>public interface ResourceSet extends Notifier<br>{<br> int RESOURCE_SET__RESOURCES = 0;<br> EList getResources();<br> …<br>}</p><p> 由getResource()返回的资源的列表,构成了它仅有的虚拟特征,表现得像个遏制引用(containment reference)。换句话说,资源每次只能在一个资源集合中。<br> ResourceSet为创建新资源提供了用户级别(user-level)的接口。在URI那一节,我们使用最简单的方法来实现这个目的,createResource(),它授权(delegate)给集合的资源工厂注册返回的资源工厂。回顾这个注册,是getResourceFactoryRegistry()返回的,当它不能定位适当的资源工厂时,就授权给全局资源工厂。createResource()方法在内存中创建资源,并且将其添加到资源集合中,毫不费力就能读入和写出持久化表示。在它盲目地创建资源前,也不会检查集合是否已经包含给出的URI的资源,这就有可能使集合处于无效状态。<br> 一个更强大的方法,getResource(),首先规范化给出的URI,检查资源集合中是否有资源拥有与其匹配的规范化URI,如果有,返回这个资源。如果这个资源没有加载,它将会被要求加载(demand-loaded),如果此方法的第二个布尔参数为真的话。如果资源没有找到并且第二个参数为真,资源将会被要求创建(demand-created)和要求加载。使用getURIConverter()返回的URI 转换器来规范化URI,使用getLoadOptions()返回的map中指定的选项来完成要求的加载。<br> 注意的是,资源的持久化形式不会被要求创建。如果因为持久化形式无法找到而导致要求的加载失败,getResource()会抛出异常。<br> 所以,在持久化框架的概述中最后的例子可以被简化。在设置资源集合和<strong>创建</strong>URI之后,两行就足以创建资源,加载,并且访问其中的对象:</p><p>…<br>Resource resource = resourceSet.getResource(uri, true);<br>PurchaseOrder po = (PurchaseOrder)resource.getContents().get(0);<br>System.out.println(“loaded: “ + po);</p><p> ResourceSet中的另一种简便方法,getEObject(),允许我们进一步简化,替换获取资源和使用单个声明检索其中对象的两行:</p><p>…<br>PurchaseOrder po =<br> (PurchaseOrder)resourceSet.getEObject(uri.appendFragment(“/“),true);<br>…<br> getEObject()方法简单地调用getResource()来获取资源,必要的话进行要求的创建和要求的加载,然后使用指定URI的分段(fragment)来定位和返回资源里面的对象。<br> 包注册,提供了一种手段来定位描述任一特殊包的元数据。有个全局包注册,EPackage.Registry.INSTANCE,在其中生成的包会被自动地注册。在其他情况下,特定语境(context-specific)的包注册会更合适些。<br> 事实上,正是资源集合提供了语境(context)。ResourceSet定义了getPackageRegistry()方法,其返回局部的(local)注册。这个局部注册只在局部不能找到包时,授权给全局注册。因此,加载到给定资源集合的资源已经检索的包,可以在不污染全局注册的情况下被注册。甚至有可能,针对同一个命名空间URI,仅仅通过局部注册一个不同的包,来重写一个全局注册表。<br> 资源集合的主要目的是支持不同资源中对象之间的引用。特别的事,它们对要求的加载(demand-loading)和代理解析(proxy resolution)至关重要。例如,考虑资源如下序列化:</p><!--?xml version="1.0" encoding="ASCII"?--><p><epo2:Supplier … ><br> <orders><br> <previousorder href="sample.epo2#//@orders.1"><br> </previousorder></orders><br></p><p> 可以看出资源中的Supplier包含一个PurchaseOrder引用了另一个资源中Supplier中序列化的PurchaseOrder*。href属性表示的是跨文档(cross-document)的引用,属性的值是标识其他资源中引用的URI。<br> 当加载这个资源时,代理被创建作为previousOrder引用的目标,指定对象的URI(例如:platform:/resource/project/sample.epo2#//@orders.1)。如果想要访问采购清单的上个清单,可以调用 getPreviousOrder(),EcoreUtil.resolve()被调用以便解析代理(resolve proxy)。</p><p>XML资源<br> EMF针对基于XML资源的基础接口,XMLResource,扩展Resource加入了数个与持久化形式相关的方法。基础实现,XMLResourceImpl,可以用来将任一EMF 序列化为XML。它产生和消耗(consume)的XML格式,以及它的性能特征,可以有很多种方式来控制。</p><p>EMF资源和资源工厂实现<br>性能考量<br>主动对象的定制存储</p><p>第十五章 持久化<br>该框架提供了一个足够灵活的API来支持任何类型的存储,甚至跨不同种类的存储持久化对象。</p>]]></content>
<tags>
<tag> EMF </tag>
</tags>
</entry>
<entry>
<title></title>
<link href="/2023/04/03/bianyiyuanli/di-yi-zhang-yin-lun/bian-yi-yuan-li-1.1/"/>
<url>/2023/04/03/bianyiyuanli/di-yi-zhang-yin-lun/bian-yi-yuan-li-1.1/</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="引论"><a href="#引论" class="headerlink" title="引论"></a>引论</h1><h2 id="语言处理器"><a href="#语言处理器" class="headerlink" title="语言处理器"></a>语言处理器</h2><ol><li><p>编译器(compiler):编程语言=>可执行文件 </p></li><li><p>解释器(interpreter):直接利用输入执行操作,进行输出</p></li><li><p>预处理器(preprocessor):将源程序聚合在一起,还负责将宏转换为源语言。</p></li><li><p>链接器(linker):解决外部内存地址的指向和链接。</p></li><li><p>加载器(loader):将所有的可执行文件放到内存中执行</p></li></ol><h2 id="一个编译器的结构"><a href="#一个编译器的结构" class="headerlink" title="一个编译器的结构"></a>一个编译器的结构</h2><ol><li>编译器的映射由分析部分(analysis)和综合部分(synthesis)构成<br> 1.词法分析(lexical analysis/scanning)<br> 读入字符流,组织成词素(lexeme)序列。词素=<token,name,attribute-value>,其中token-name为抽象符号,第二个指向符号表中关于该词法单元的条目。其中,分割词素用的空格会被词法分析器忽略掉。<br> 2.语法分析(parsing/syntax analysis)<br> 使用由词法分析产生的词素列表的第一个分量来创建树的中间表示,该中间表示给出词法分析产生的词法单元流的语法结构。常用的表示方法是语法树。树的每个内部节点表示一个运算.<br> 3.语义分析(semantic analysis)<br> 使用语法树和符号表中的信息来检查源程序是否和语言定义的语义一致。同时手机类型信息,并将这些信息存放在语法书或符号表中,以便在中间代码生成过程中使用。其中一个重要的步骤为类型检查(type checking)和自动类型转换(coercion)。<br> 4.中间代码生成(optional)<br> 生成一个明确的地基或者类机器语言的中间表示,可以看做某个抽象机器的程序。具备两个重要性质:易于生成,能轻松的翻译为目标机器的语言。<br> 5.代码优化(optional)<br> 机器无关的代码优化视图改进中间代码。一个合理的方法是使用一个简单的中间代码生成算法,在进行优化。<br> 6.代码生成<br> 源程序的中间表示形式作为输入,并把它映射到目标语言。如果目标语言是机器代码,就必须为程序上使用的每个变量选择寄存器或内存位置,然后翻译成能完成任务的机器指令序列。重要的方面是合理分配寄存器以存放变量的值。<br> 7.符号表管理<br> 记录源程序中使用的变量的名字,并收集和每个名字有关的信息(存储分配、类型、作用域,参数变量和类型、参数的传递方法、返回类型)<br> 8.将多个步骤合成趟(pass)<br> 特定的实现中,多个步骤的活动可以被组合成一趟。<br> 9.编译器构造工具<ul><li>语法分析器的生成器:可根据程序语言描述自动生成语法分析器。</li><li>扫描器的生成器:语言的语法单元的正则表达式生成词法分析。</li><li>语法制导的翻译引擎:用于遍历分析书并生成中间代码的例程。</li><li>数据流分析引擎</li><li>编译器构造工具集</li></ul></li></ol>]]></content>
</entry>
<entry>
<title>参数传递</title>
<link href="/2023/04/03/bianyiyuanli/di-yi-zhang-yin-lun/can-shu-chuan-di-ji-zhi/"/>
<url>/2023/04/03/bianyiyuanli/di-yi-zhang-yin-lun/can-shu-chuan-di-ji-zhi/</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>参数传递主要为实在参数如何与形式参数进行绑定的,主要有值调用和引用调用两种方式,历史上还有名调用的方式。</p><h2 id="值调用"><a href="#值调用" class="headerlink" title="值调用"></a>值调用</h2>]]></content>
</entry>
<entry>
<title>编译原理课程</title>
<link href="/2023/04/03/bianyiyuanli/readme/"/>
<url>/2023/04/03/bianyiyuanli/readme/</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="bianyiyuanli"><a href="#bianyiyuanli" class="headerlink" title="bianyiyuanli"></a>bianyiyuanli</h1><p>龙书第二版笔记 编译原理课程</p>]]></content>
</entry>
<entry>
<title>Hello World</title>
<link href="/2023/03/31/hello-world/"/>
<url>/2023/03/31/hello-world/</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">$ hexo new <span class="token string">"My New Post"</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">$ hexo server<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">$ hexo generate<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">$ hexo deploy<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
</entry>
</search>