<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                {% raw %} # 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3 ## 5.3? SpEL語法 ### 5.3.1? 基本表達式 **一、字面量表達式:**?SpEL支持的字面量包括:字符串、數字類型(int、long、float、double)、布爾類型、null類型。 | 類型 | 示例 | | --- | --- | | 字符串 | String str1 = parser.parseExpression("'Hello World!'").getValue(String.class);String str2 = parser.parseExpression("\"Hello World!\"").getValue(String.class); | | 數字類型 | int int1 = parser.parseExpression("1").getValue(Integer.class);long long1 = parser.parseExpression("-1L").getValue(long.class);float float1 = parser.parseExpression("1.1").getValue(Float.class);double double1 = parser.parseExpression("1.1E+2").getValue(double.class);int hex1 = parser.parseExpression("0xa").getValue(Integer.class);long hex2 = parser.parseExpression("0xaL").getValue(long.class); | | 布爾類型 | boolean true1 = parser.parseExpression("true").getValue(boolean.class);boolean false1 = parser.parseExpression("false").getValue(boolean.class); | | null類型 | Object null1 = parser.parseExpression("null").getValue(Object.class); | **二、算數運算表達式:**?SpEL支持加(+)、減(-)、乘(*)、除(/)、求余(%)、冪(^)運算。 | 類型 | 示例 | | --- | --- | | 加減乘除 | int result1 = parser.parseExpression("1+2-3*4/2").getValue(Integer.class);//-3 | | 求余 | int result2 = parser.parseExpression("4%3").getValue(Integer.class);//1 | | 冪運算 | int result3 = parser.parseExpression("2^3").getValue(Integer.class);//8 | SpEL還提供求余(MOD)和除(DIV)而外兩個運算符,與“%”和“/”等價,不區分大小寫。 **三、關系表達式:**等于(==)、不等于(!=)、大于(&gt;)、大于等于(&gt;=)、小于(&lt;)、小于等于(&lt;=),區間(between)運算,如“parser.parseExpression("1&gt;2").getValue(boolean.class);”將返回false;而“parser.parseExpression("1 between {1, 2}").getValue(boolean.class);”將返回true。 between運算符右邊操作數必須是列表類型,且只能包含2個元素。第一個元素為開始,第二個元素為結束,區間運算是包含邊界值的,即 xxx&gt;=list.get(0) && xxx&lt;=list.get(1)。 SpEL同樣提供了等價的“EQ” 、“NE”、 “GT”、“GE”、 “LT” 、“LE”來表示等于、不等于、大于、大于等于、小于、小于等于,不區分大小寫。 **四、邏輯表達式:**且(and)、或(or)、非(!或NOT)。 1. String?expression1?=?"2&gt;1?and?(!true?or?!false)";?? 2. boolean?result1?=?parser.parseExpression(expression1).getValue(boolean.class);?? 3. Assert.assertEquals(true,?result1);?? 5. String?expression2?=?"2&gt;1?and?(NOT?true?or?NOT?false)";?? 6. boolean?result2?=?parser.parseExpression(expression2).getValue(boolean.class);?? 7. Assert.assertEquals(true,?result2);?? 注:**邏輯運算符不支持?Java中的 &&?和 ||?。** **五、字符串連接及截取表達式:**使用“+”進行字符串連接,使用“'String'[0] [index]”來截取一個字符,目前只支持截取一個,如“'Hello ' + 'World!'”得到“Hello World!”;而“'Hello World!'[0]”將返回“H”。 **六、三目運算及Elivis運算表達式:** 三目運算符?**“表達式1?表達式2:表達式3”**用于構造三目運算表達式,如“2&gt;1?true:false”將返回true; Elivis運算符**“表達式1?:表達式2”**從Groovy語言引入用于簡化三目運算符的,當表達式1為非null時則返回表達式1,當表達式1為null時則返回表達式2,簡化了三目運算符方式“表達式1? 表達式1:表達式2”,如“null?:false”將返回false,而“true?:false”將返回true; **七、正則表達式:**使用“str matches regex,如“'123' matches '\\d{3}'”將返回true; **八、括號優先級表達式:**使用“(表達式)”構造,括號里的具有高優先級。 ### 5.3.3? 類相關表達式 **一、類類型表達式:**使用“T(Type)”來表示java.lang.Class實例,“Type”必須是類全限定名,“java.lang”包除外,即該包下的類可以不指定包名;使用類類型表達式還可以進行訪問類靜態方法及類靜態字段。 具體使用方法如下: 1. @Test?? 2. public?void?testClassTypeExpression()?{?? 3. ExpressionParser?parser?=?new?SpelExpressionParser();?? 4. //java.lang包類訪問?? 5. Class&lt;String&gt;?result1?=?parser.parseExpression("T(String)").getValue(Class.class);?? 6. Assert.assertEquals(String.class,?result1);?? 7. //其他包類訪問?? 8. String?expression2?=?"T(cn.javass.spring.chapter5.SpELTest)";?? 9. Class&lt;String&gt;?result2?=?parser.parseExpression(expression2).getValue(Class.class);????Assert.assertEquals(SpELTest.class,?result2);?? 10. //類靜態字段訪問?? 11. int?result3=parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class);?? 12. Assert.assertEquals(Integer.MAX_VALUE,?result3);?? 13. //類靜態方法調用?? 14. int?result4?=?parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class);?? 15. Assert.assertEquals(1,?result4);?? 16. }?? 對于java.lang包里的可以直接使用“T(String)”訪問;其他包必須是類全限定名;可以進行靜態字段訪問如“T(Integer).MAX_VALUE”;也可以進行靜態方法訪問如“T(Integer).parseInt('1')”。 **二、類實例化:**類實例化同樣使用java關鍵字“new”,類名必須是全限定名,但java.lang包內的類型除外,如String、Integer。 1. @Test?? 2. public?void?testConstructorExpression()?{?? 3. ExpressionParser?parser?=?new?SpelExpressionParser();?? 4. String?result1?=?parser.parseExpression("new?String('haha')").getValue(String.class);?? 5. Assert.assertEquals("haha",?result1);?? 6. Date?result2?=?parser.parseExpression("new?java.util.Date()").getValue(Date.class);?? 7. Assert.assertNotNull(result2);?? 8. }?? 實例化完全跟Java內方式一樣。 **三、instanceof表達式:**SpEL支持instanceof運算符,跟Java內使用同義;如“'haha' instanceof T(String)”將返回true。 **四、變量定義及引用:**變量定義通過EvaluationContext接口的setVariable(variableName, value)方法定義;在表達式中使用“#variableName”引用;除了引用自定義變量,SpE還允許引用根對象及當前上下文對象,使用“#root”引用根對象,使用“#this”引用當前上下文對象; 2. @Test?? 3. public?void?testVariableExpression()?{?? 4. ExpressionParser?parser?=?new?SpelExpressionParser();?? 5. EvaluationContext?context?=?new?StandardEvaluationContext();?? 6. context.setVariable("variable",?"haha");?? 7. context.setVariable("variable",?"haha");?? 8. String?result1?=?parser.parseExpression("#variable").getValue(context,?String.class);?? 9. Assert.assertEquals("haha",?result1);?? 11. context?=?new?StandardEvaluationContext("haha");?? 12. String?result2?=?parser.parseExpression("#root").getValue(context,?String.class);?? 13. Assert.assertEquals("haha",?result2);?? 14. String?result3?=?parser.parseExpression("#this").getValue(context,?String.class);?? 15. Assert.assertEquals("haha",?result3);?? 16. }?? 使用“#variable”來引用在EvaluationContext定義的變量;除了可以引用自定義變量,還可以使用“#root”引用根對象,“#this”引用當前上下文對象,此處“#this”即根對象。 **五、自定義函數:**目前只支持類靜態方法注冊為自定義函數;SpEL使用StandardEvaluationContext的registerFunction方法進行注冊自定義函數,其實完全可以使用setVariable代替,兩者其實本質是一樣的; 1. @Test?? 2. public?void?testFunctionExpression()?throws?SecurityException,?NoSuchMethodException?{?? 3. ExpressionParser?parser?=?new?SpelExpressionParser();?? 4. StandardEvaluationContext?context?=?new?StandardEvaluationContext();?? 5. Method?parseInt?=?Integer.class.getDeclaredMethod("parseInt",?String.class);?? 6. context.registerFunction("parseInt",?parseInt);?? 7. context.setVariable("parseInt2",?parseInt);?? 8. String?expression1?=?"#parseInt('3')?==?#parseInt2('3')";?? 9. boolean?result1?=?parser.parseExpression(expression1).getValue(context,?boolean.class);?? 10. Assert.assertEquals(true,?result1);????????? 11. }?? 此處可以看出“registerFunction”和“setVariable”都可以注冊自定義函數,但是兩個方法的含義不一樣,推薦使用“registerFunction”方法注冊自定義函數。 **六、賦值表達式:**SpEL即允許給自定義變量賦值,也允許給跟對象賦值,直接使用“#variableName=value”即可賦值: 1. @Test?? 2. public?void?testAssignExpression()?{?? 3. ExpressionParser?parser?=?new?SpelExpressionParser();?? 4. //1.給root對象賦值?? 5. EvaluationContext?context?=?new?StandardEvaluationContext("aaaa");?? 6. String?result1?=?parser.parseExpression("#root='aaaaa'").getValue(context,?String.class);?? 7. Assert.assertEquals("aaaaa",?result1);?? 8. String?result2?=?parser.parseExpression("#this='aaaa'").getValue(context,?String.class);?? 9. Assert.assertEquals("aaaa",?result2);?? 11. //2.給自定義變量賦值?? 12. context.setVariable("#variable",?"variable");?? 13. String?result3?=?parser.parseExpression("#variable=#root").getValue(context,?String.class);?? 14. Assert.assertEquals("aaaa",?result3);?? 15. }?? 使用“#root='aaaaa'”給根對象賦值,使用“"#this='aaaa'”給當前上下文對象賦值,使用“#variable=#root”給自定義變量賦值,很簡單。 **七、對象屬性存取及安全導航表達式:**對象屬性獲取非常簡單,即使用如“a.property.property”這種點綴式獲取,SpEL對于屬性名首字母是不區分大小寫的;SpEL還引入了Groovy語言中的安全導航運算符“(對象|屬性)?.屬性”,用來避免但“?.”前邊的表達式為null時拋出空指針異常,而是返回null;修改對象屬性值則可以通過賦值表達式或Expression接口的setValue方法修改。 1. ExpressionParser?parser?=?new?SpelExpressionParser();?? 2. //1.訪問root對象屬性?? 3. Date?date?=?new?Date();?? 4. StandardEvaluationContext?context?=?new?StandardEvaluationContext(date);?? 5. int?result1?=?parser.parseExpression("Year").getValue(context,?int.class);?? 6. Assert.assertEquals(date.getYear(),?result1);?? 7. int?result2?=?parser.parseExpression("year").getValue(context,?int.class);?? 8. Assert.assertEquals(date.getYear(),?result2);????????? 對于**當前上下文對象屬性及方法訪問,可以直接使用屬性或方法名訪問**,比如此處根對象date屬性“year”,注意此處屬性名首字母不區分大小寫。 2. //2.安全訪問?? 3. context.setRootObject(null);?? 4. Object?result3?=?parser.parseExpression("#root?.year").getValue(context,?Object.class);?? 5. Assert.assertEquals(null,?result3);????? SpEL引入了Groovy的安全導航運算符,比如此處根對象為null,所以如果訪問其屬性時肯定拋出空指針異常,而采用“?.”安全訪問導航運算符將不拋空指針異常,而是簡單的返回null。 1. //3.給root對象屬性賦值?? 2. context.setRootObject(date);?? 3. int?result4?=?parser.parseExpression("Year?=?4").getValue(context,?int.class);?? 4. Assert.assertEquals(4,?result4);?? 5. parser.parseExpression("Year").setValue(context,?5);?? 6. int?result5?=?parser.parseExpression("Year").getValue(context,?int.class);?? 7. Assert.assertEquals(5,?result5);?? 給對象屬性賦值可以采用賦值表達式或Expression接口的setValue方法賦值,而且也可以采用點綴方式賦值。 **八、對象方法調用:**對象方法調用更簡單,跟Java語法一樣;如“'haha'.substring(2,4)”將返回“ha”;而對于根對象可以直接調用方法; 1. Date?date?=?new?Date();?? 2. StandardEvaluationContext?context?=?new?StandardEvaluationContext(date);?? 3. int?result2?=?parser.parseExpression("getYear()").getValue(context,?int.class);?? 4. Assert.assertEquals(date.getYear(),?result2);?? 比如根對象date方法“getYear”可以直接調用。 **九、Bean引用:**SpEL支持使用“@”符號來引用Bean,在引用Bean時需要使用BeanResolver接口實現來查找Bean,Spring提供BeanFactoryResolver實現; 1. @Test?? 2. public?void?testBeanExpression()?{?? 3. ClassPathXmlApplicationContext?ctx?=?new?ClassPathXmlApplicationContext();?? 4. ctx.refresh();?? 5. ExpressionParser?parser?=?new?SpelExpressionParser();?? 6. StandardEvaluationContext?context?=?new?StandardEvaluationContext();?? 7. context.setBeanResolver(new?BeanFactoryResolver(ctx));?? 8. Properties?result1?=?parser.parseExpression("@systemProperties").getValue(context,?Properties.class);?? 9. Assert.assertEquals(System.getProperties(),?result1);?? 10. }?? 在示例中我們首先初始化了一個IoC容器,ClassPathXmlApplicationContext 實現默認會把“System.getProperties()”注冊為“systemProperties”Bean,因此我們使用 “@systemProperties”來引用該Bean。 ### 5.3.3? 集合相關表達式 **一、內聯List:**從Spring3.0.4開始支持內聯List,使用{表達式,……}定義內聯List,如“{1,2,3}”將返回一個整型的ArrayList,而“{}”將返回空的List,對于字面量表達式列表,SpEL會使用java.util.Collections.unmodifiableList方法將列表設置為不可修改。 1. //將返回不可修改的空List?? 2. List&lt;Integer&gt;?result2?=?parser.parseExpression("{}").getValue(List.class);?? 1. //對于字面量列表也將返回不可修改的List?? 2. List&lt;Integer&gt;?result1?=?parser.parseExpression("{1,2,3}").getValue(List.class);?? 3. Assert.assertEquals(new?Integer(1),?result1.get(0));?? 4. try?{?? 5. result1.set(0,?2);?? 6. //不可能執行到這,對于字面量列表不可修改?? 7. Assert.fail();?? 8. }?catch?(Exception?e)?{?? 9. }?? 1. //對于列表中只要有一個不是字面量表達式,將只返回原始List,?? 2. //不會進行不可修改處理?? 3. String?expression3?=?"{{1+2,2+4},{3,4+4}}";?? 4. List&lt;List&lt;Integer&gt;&gt;?result3?=?parser.parseExpression(expression3).getValue(List.class);?? 5. result3.get(0).set(0,?1);?? 6. Assert.assertEquals(2,?result3.size());?? 1. //聲明一個大小為2的一維數組并初始化?? 2. int[]?result2?=?parser.parseExpression("new?int[2]{1,2}").getValue(int[].class);?? 1. //定義一維數組但不初始化?? 2. int[]?result1?=?parser.parseExpression("new?int[1]").getValue(int[].class);?? 二、內聯數組:和Java 數組定義類似,只是在定義時進行多維數組初始化。 2. //定義多維數組但不初始化?? 3. int[][][]?result3?=?parser.parseExpression("new int[1][2][3]").getValue(int[][][].class);?? 1. //錯誤的定義多維數組,多維數組不能初始化?? 2. String?expression4?=?"new?int[1][2][3]{{1}{2}{3}}";?? 3. try?{?? 4. int[][][]?result4?=?parser.parseExpression(expression4).getValue(int[][][].class);?? 5. Assert.fail();?? 6. }?catch?(Exception?e)?{?? 7. }?? 三、集合,字典元素訪問:SpEL目前支持所有集合類型和字典類型的元素訪問,使用“集合[索引]”訪問集合元素,使用“map[key]”訪問字典元素; 1. //SpEL內聯List訪問?? 2. int?result1?=?parser.parseExpression("{1,2,3}[0]").getValue(int.class);?? 3. //即list.get(0)?? 4. Assert.assertEquals(1,?result1);?? 1. //SpEL目前支持所有集合類型的訪問?? 2. Collection&lt;Integer&gt;?collection?=?new?HashSet&lt;Integer&gt;();?? 3. collection.add(1);?? 4. collection.add(2);?? 5. EvaluationContext?context2?=?new?StandardEvaluationContext();?? 6. context2.setVariable("collection",?collection);?? 7. int?result2?=?parser.parseExpression("#collection[1]").getValue(context2,?int.class);?? 8. //對于任何集合類型通過Iterator來定位元素?? 9. Assert.assertEquals(2,?result2);?? 1. //SpEL對Map字典元素訪問的支持?? 2. Map&lt;String,?Integer&gt;?map?=?new?HashMap&lt;String,?Integer&gt;();?? 3. map.put("a",?1);?? 4. EvaluationContext?context3?=?new?StandardEvaluationContext();?? 5. context3.setVariable("map",?map);?? 6. int?result3?=?parser.parseExpression("#map['a']").getValue(context3,?int.class);?? 7. Assert.assertEquals(1,?result3);?? 注:**集合元素訪問是通過Iterator遍歷來定位元素位置的**。 **四、列表,字典,數組元素修改:**可以使用賦值表達式或Expression接口的setValue方法修改; 1. //1.修改數組元素值?? 2. int[]?array?=?new?int[]?{1,?2};?? 3. EvaluationContext?context1?=?new?StandardEvaluationContext();?? 4. context1.setVariable("array",?array);?? 5. int?result1?=?parser.parseExpression("#array[1]?=?3").getValue(context1,?int.class);?? 6. Assert.assertEquals(3,?result1);?? 1. //2.修改集合值?? 2. Collection&lt;Integer&gt;?collection?=?new?ArrayList&lt;Integer&gt;();?? 3. collection.add(1);?? 4. collection.add(2);?? 5. EvaluationContext?context2?=?new?StandardEvaluationContext();?? 6. context2.setVariable("collection",?collection);?? 7. int?result2?=?parser.parseExpression("#collection[1]?=?3").getValue(context2,?int.class);?? 8. Assert.assertEquals(3,?result2);?? 9. parser.parseExpression("#collection[1]").setValue(context2,?4);?? 10. result2?=?parser.parseExpression("#collection[1]").getValue(context2,?int.class);?? 11. Assert.assertEquals(4,?result2);?? 1. //3.修改map元素值?? 2. Map&lt;String,?Integer&gt;?map?=?new?HashMap&lt;String,?Integer&gt;();?? 3. map.put("a",?1);?? 4. EvaluationContext?context3?=?new?StandardEvaluationContext();?? 5. context3.setVariable("map",?map);?? 6. int?result3?=?parser.parseExpression("#map['a']?=?2").getValue(context3,?int.class);?? 7. Assert.assertEquals(2,?result3);?? 對數組修改直接對“#array[index]”賦值即可修改元素值,同理適用于集合和字典類型。 **五、集合投影:**在SQL中投影指從表中選擇出列,而在SpEL指根據集合中的元素中通過選擇來構造另一個集合,該集合和原集合具有相同數量的元素;SpEL使用“(list|map).![投影表達式]”來進行投影運算: 1. //1.首先準備測試數據?? 2. Collection&lt;Integer&gt;?collection?=?new?ArrayList&lt;Integer&gt;();?? 3. collection.add(4);???collection.add(5);?? 4. Map&lt;String,?Integer&gt;?map?=?new?HashMap&lt;String,?Integer&gt;();?? 5. map.put("a",?1);????map.put("b",?2);?? 1. //2.測試集合或數組?? 2. EvaluationContext?context1?=?new?StandardEvaluationContext();?? 3. context1.setVariable("collection",?collection);?? 4. Collection&lt;Integer&gt;?result1?=?? 5. parser.parseExpression("#collection.![#this+1]").getValue(context1,?Collection.class);?? 6. Assert.assertEquals(2,?result1.size());?? 7. Assert.assertEquals(new?Integer(5),?result1.iterator().next());?? 對于集合或數組使用如上表達式進行投影運算,其中投影表達式中“#this”代表每個集合或數組元素,可以使用比如“#this.property”來獲取集合元素的屬性,其中“#this”可以省略。 1. //3.測試字典?? 2. EvaluationContext?context2?=?new?StandardEvaluationContext();?? 3. context2.setVariable("map",?map);?? 4. List&lt;Integer&gt;?result2?=?? 5. parser.parseExpression("#map.![?value+1]").getValue(context2,?List.class);?? 6. Assert.assertEquals(2,?result2.size());?? SpEL投影運算還支持Map投影,但Map投影最終只能得到List結果,如上所示,對于投影表達式中的“#this”將是Map.Entry,所以可以使用“value”來獲取值,使用“key”來獲取鍵。 **六、集合選擇:**在SQL中指使用select進行選擇行數據,而在SpEL指根據原集合通過條件表達式選擇出滿足條件的元素并構造為新的集合,SpEL使用“(list|map).?[選擇表達式]”,其中選擇表達式結果必須是boolean類型,如果true則選擇的元素將添加到新集合中,false將不添加到新集合中。 1. //1.首先準備測試數據?? 2. Collection&lt;Integer&gt;?collection?=?new?ArrayList&lt;Integer&gt;();?? 3. collection.add(4);???collection.add(5);?? 4. Map&lt;String,?Integer&gt;?map?=?new?HashMap&lt;String,?Integer&gt;();?? 5. map.put("a",?1);????map.put("b",?2);?? 1. //2.集合或數組測試?? 2. EvaluationContext?context1?=?new?StandardEvaluationContext();?? 3. context1.setVariable("collection",?collection);?? 4. Collection&lt;Integer&gt;?result1?=?? 5. parser.parseExpression("#collection.?[#this&gt;4]").getValue(context1,?Collection.class);?? 6. Assert.assertEquals(1,?result1.size());?? 7. Assert.assertEquals(new?Integer(5),?result1.iterator().next());?? 對于集合或數組選擇,如“#collection.?[#this&gt;4]”將選擇出集合元素值大于4的所有元素。選擇表達式必須返回布爾類型,使用“#this”表示當前元素。 1. //3.字典測試?? 2. EvaluationContext?context2?=?new?StandardEvaluationContext();?? 3. context2.setVariable("map",?map);?? 4. Map&lt;String,?Integer&gt;?result2?=?? 5. parser.parseExpression("#map.?[#this.key?!=?'a']").getValue(context2,?Map.class);?? 6. Assert.assertEquals(1,?result2.size());?? 8. List&lt;Integer&gt;?result3?=?? 9. parser.parseExpression("#map.?[key?!=?'a'].![value+1]").getValue(context2,?List.class);?? 10. Assert.assertEquals(new?Integer(3),?result3.iterator().next());?? 對于字典選擇,如“#map.?[#this.key != 'a']”將選擇鍵值不等于”a”的,其中選擇表達式中“#this”是Map.Entry類型,而最終結果還是Map,這點和投影不同;集合選擇和投影可以一起使用,如“#map.?[key != 'a'].![value+1]”將首先選擇鍵值不等于”a”的,然后在選出的Map中再進行“value+1”的投影。 ### 5.3.4? 表達式模板 模板表達式就是由字面量與一個或多個表達式塊組成。每個表達式塊由“前綴+表達式+后綴”形式組成,如“${1+2}”即表達式塊。在前邊我們已經介紹了使用ParserContext接口實現來定義表達式是否是模板及前綴和后綴定義。在此就不多介紹了,如“Error ${#v0} ${#v1}”表達式表示由字面量“Error ”、模板表達式“#v0”、模板表達式“#v1”組成,其中v0和v1表示自定義變量,需要在上下文定義。 原創內容 轉自請注明私塾在線【[http://sishuok.com/forum/blogPost/list/0/2463.html](http://sishuok.com/forum/blogPost/list/0/2463.html#7129)】 {% endraw %}
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看