<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->在项目ä¸ä½¿ç”¨Spring的注解,关于spring的注解,ç”׃¸¤¿U注解方å¼ï¼Œ
åŸÞZºŽæ³¨é‡ŠåQˆAnnotationåQ‰çš„é…置有越æ¥è¶Š‹¹è¡Œçš„趋势,Spring 2.5 ™åºåº”˜q™ç§‘‹åŠ¿åQŒæä¾›äº†(ji¨£n)完全åŸÞZºŽæ³¨é‡Šé…ç½® Beanã€è£…é…?Bean 的功能,æ‚(zh¨¨n)¨å¯ä»¥ä‹É用基于注释的 Spring IoC 替æ¢åŽŸæ¥åŸÞZºŽ XML 的酾|®ã€‚本文通过实例详细讲述äº?Spring 2.5 åŸÞZºŽæ³¨é‡Š IoC 功能的ä‹É用ã€?/p>
注释é…置相对äº?XML é…ç½®å…ähœ‰å¾ˆå¤šçš„优势:(x¨¬)
å› æ¤åœ¨å¾ˆå¤šæƒ…况下åQŒæ³¨é‡Šé…¾|®æ¯” XML é…置更嗋Ƣ迎åQŒæ³¨é‡Šé…¾|®æœ‰˜q›ä¸€æ¥æµè¡Œçš„‘‹åŠ¿ã€‚Spring 2.5 的一大增强就是引入了(ji¨£n)很多注释¾c»ï¼ŒçŽ°åœ¨æ‚(zh¨¨n)¨å·²¾lå¯ä»¥ä‹É用注释酾|®å®Œæˆå¤§éƒ¨åˆ† XML é…置的功能。在˜q™ç¯‡æ–‡ç« 里,我们ž®†å‘æ‚(zh¨¨n)¨è®²˜qîC‹É用注释进è¡?Bean 定义和ä¾èµ–注入的内容ã€?/p>
Spring 2.5 引入�@Autowired
注释åQŒå®ƒå¯ä»¥å¯¹ç±»æˆå‘˜å˜é‡ã€æ–¹æ³•åŠ(qi¨¢ng)æž„é€ å‡½æ•°è¿›è¡Œæ ‡æ³¨ï¼Œå®Œæˆè‡ªåŠ¨è£…é…的工作ã€?/p>
Spring 通过一�BeanPostProcessor
�@Autowired
˜q›è¡Œè§£æžåQŒæ‰€ä»¥è¦è®?@Autowired
起作用必™åÖMº‹å…ˆåœ¨ Spring 容器ä¸å£°æ˜?AutowiredAnnotationBeanPostProcessor
Bean�/p>
在Springä¸é…¾|®å¦‚下:(x¨¬)
<!-- è¯?BeanPostProcessor ž®†è‡ªåЍè“v作用åQŒå¯¹æ ‡æ³¨ @Autowired çš?Bean ˜q›è¡Œè‡ªåŠ¨æ³¨å…¥ -->
<bean class="org.springframework.beans.factory.annotation.
AutowiredAnnotationBeanPostProcessor"/>
å½?Spring 容器å¯åЍæ—Óž¼ŒAutowiredAnnotationBeanPostProcessor
ž®†æ‰«æ?Spring 容噍䏿‰€æœ?BeanåQŒå½“å‘现 Bean 䏿‹¥æœ?@Autowired
注释时就扑ֈ°å’Œå…¶åŒšw…åQˆé»˜è®¤æŒ‰¾cÕdž‹åŒšw…åQ‰çš„ BeanåQŒåƈ注入到对应的地方ä¸åŽ»ã€?/p>
按照上é¢çš„é…¾|®ï¼ŒSpring ž®†ç›´æŽ¥é‡‡ç”?Java å射机制å¯?Boss ä¸çš„ car
å’?office
˜q™ä¸¤ä¸ªç§æœ‰æˆå‘˜å˜é‡è¿›è¡Œè‡ªåŠ¨æ³¨å…¥ã€‚æ‰€ä»¥å¯¹æˆå‘˜å˜é‡ä½¿ç”¨ @Autowired
åŽï¼Œæ‚(zh¨¨n)¨å¤§å¯å°†å®ƒä»¬çš?setter æ–ÒŽ(gu¨©)³•åQ?code>setCar() å’?setOffice()
åQ‰ä»Ž Boss ä¸åˆ 除ã€?/p>
当然åQŒæ?zh¨¨n)¨ä¹Ÿå¯ä»¥é€šè¿‡ @Autowired
å¯ÒŽ(gu¨©)–¹æ³•æˆ–æž„é€ å‡½æ•°è¿›è¡Œæ ‡æ³¨ï¼Œ
当候é€?Bean æ•°ç›®ä¸äØ“(f¨´) 1 时的应对æ–ÒŽ(gu¨©)³•
在默认情况下使用 @Autowired
注释˜q›è¡Œè‡ªåŠ¨æ³¨å…¥æ—Óž¼ŒSpring 容器ä¸åŒ¹é…的候é€?Bean 数目必须有且仅有一个。当找ä¸åˆîC¸€ä¸ªåŒ¹é…çš„ Bean æ—Óž¼ŒSpring 容器ž®†æŠ›å‡?BeanCreationException
异常åQŒåƈ指出必须臛_°‘拥有一个匹é…çš„ Beanã€?/p>
当ä¸èƒ½ç¡®å®?Spring 容器ä¸ä¸€å®šæ‹¥æœ‰æŸä¸ªç±»çš?Bean æ—Óž¼Œå¯ä»¥åœ¨éœ€è¦è‡ªåŠ¨æ³¨å…¥è¯¥¾c?Bean 的地方å¯ä»¥ä‹Éç”?@Autowired(required = false)
åQŒè¿™½{‰äºŽå‘Šè¯‰ SpringåQšåœ¨æ‰¾ä¸åˆ°åŒ¹é…?Bean æ—¶ä¹Ÿä¸æŠ¥é”™ã€?/p>
一般情况下åQŒä‹Éç”?@Autowired
的地斚wƒ½æ˜¯éœ€è¦æ³¨å…?Bean 的,使用äº?ji¨£n)自动注入而åˆå…è®¸ä¸æ³¨å…¥çš„æƒ…况一般仅ä¼?x¨¬)åœ¨å¼€å‘æœŸæˆ–测试期¼„°åˆ°åQˆå¦‚ä¸ÞZº†(ji¨£n)快速å¯åŠ?Spring 容器åQŒä»…引入一些模å—çš„ Spring é…置文äšgåQ‰ï¼Œæ‰€ä»?@Autowired(required = false)
ä¼?x¨¬)很ž®‘用到ã€?/p>
和找ä¸åˆ°ä¸€ä¸ªç±»åž‹åŒ¹é…?Bean 相å的一个错误是åQšå¦‚æž?Spring 容噍䏿‹¥æœ‰å¤šä¸ªå€™é€?BeanåQŒSpring 容器在å¯åŠ¨æ—¶ä¹Ÿä¼š(x¨¬)抛出 BeanCreationException
异常�/p>
Spring å…许我们通过 @Qualifier
注释指定注入 Bean çš„å¿UŽÍ¼Œ˜q™æ ·æ§ä¹‰ž®±æ¶ˆé™¤äº†(ji¨£n)åQŒå¯ä»¥é€šè¿‡ä¸‹é¢çš„æ–¹æ³•解军_¼‚常:(x¨¬)
æ¸…å• 13. 使用 @Qualifier 注释指定注入 Bean çš„å¿U?/strong>
@Autowired public void setOffice(@Qualifier("office")Office office) { this.office = office; } |
@Qualifier("office")
ä¸çš„ office
æ˜?Bean çš„å¿UŽÍ¼Œæ‰€ä»?@Autowired
å’?@Qualifier
¾l“åˆä½¿ç”¨æ—Óž¼Œè‡ªåŠ¨æ³¨å…¥çš„ç–略就ä»?byType è½¬å˜æˆ?byName äº?ji¨£n)ã€?code>@Autowired å¯ä»¥å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡ã€æ–¹æ³•以å?qi¨¢ng)æž„é€ å‡½æ•°è¿›è¡Œæ³¨é‡Šï¼Œè€?@Qualifier
çš„æ ‡æ³¨å¯¹è±¡æ˜¯æˆå‘˜å˜é‡ã€æ–¹æ³•å…¥å‚ã€æž„é€ å‡½æ•°å…¥å‚ã€‚æ£æ˜¯ç”±äºŽæ³¨é‡Šå¯¹è±¡çš„ä¸åŒåQŒæ‰€ä»?Spring ä¸å°† @Autowired
å’?@Qualifier
¾lŸä¸€æˆä¸€ä¸ªæ³¨é‡Šç±»ã€‚䏋颿˜¯å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡å’Œæž„é€ å‡½æ•°å…¥å‚进行注释的代ç åQ?/p>
å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡è¿›è¡Œæ³¨é‡Šï¼š(x¨¬)
å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡ä‹Éç”?@Qualifier 注释
public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; … } |
å¯ÒŽ(gu¨©)ž„é€ å‡½æ•°å…¥å‚进行注释:(x¨¬)
æ¸…å• 15. å¯ÒŽ(gu¨©)ž„é€ å‡½æ•°å˜é‡ä‹Éç”?@Qualifier 注释
public class Boss { private Car car; private Office office; @Autowired public Boss(Car car , @Qualifier("office")Office office){ this.car = car; this.office = office ; } } |
@Qualifier
åªèƒ½å’?@Autowired
¾l“åˆä½¿ç”¨åQŒæ˜¯å¯?@Autowired
有益的补充。一般æ¥è®ÔŒ¼Œ@Qualifier
å¯ÒŽ(gu¨©)–¹æ³•ç¾åä¸å…¥å‚˜q›è¡Œæ³¨é‡Šä¼?x¨¬)é™ä½Žä»£ç çš„å¯è¯»æ€§ï¼Œè€Œå¯¹æˆå‘˜å˜é‡æ³¨é‡Šåˆ™ç›¸å¯¹å¥½ä¸€äº›ã€?/p>
使用 JSR-250 的注�/span>
Spring ä¸ä½†æ”¯æŒè‡ªå·±å®šä¹‰çš?@Autowired
的注释,˜q˜æ”¯æŒå‡ 个由 JSR-250 规范定义的注释,它们分别æ˜?@Resource
ã€?code>@PostConstruct 以åŠ(qi¨¢ng) @PreDestroy
�/p>
@Resource
的作用相当于 @Autowired
åQŒåªä¸è¿‡ @Autowired
æŒ?byType 自动注入åQŒé¢ @Resource
默认æŒ?byName 自动注入¾|¢äº†(ji¨£n)ã€?code>@Resource 有两个属性是比较é‡è¦çš„,分别æ˜?name å’?typeåQŒSpring ž®?@Resource
注释çš?name 属性解æžäØ“(f¨´) Bean çš„åå—,è€?type 属性则解æžä¸?Bean 的类型。所以如果ä‹Éç”?name 属性,则ä‹Éç”?byName 的自动注入ç–略,而ä‹Éç”?type 属性时则ä‹Éç”?byType 自动注入½{–ç•¥ã€‚å¦‚æžœæ—¢ä¸æŒ‡å®?name ä¹Ÿä¸æŒ‡å®š type 属性,˜q™æ—¶ž®†é€šè¿‡å射机制使用 byName 自动注入½{–ç•¥ã€?/p>
Resource 注释¾cÖM½äº?Spring å‘布包的 lib/j2ee/common-annotations.jar ¾cÕdŒ…ä¸ï¼Œå› æ¤åœ¨ä‹É用之å‰å¿…™åÕd°†å…¶åŠ å…¥åˆ°™å¹ç›®çš„类库ä¸ã€‚æ¥çœ‹ä¸€ä¸ªä‹Éç”?@Resource
的例å:(x¨¬)
æ¸…å• 16. 使用 @Resource 注释çš?Boss.java
package com.baobaotao; import javax.annotation.Resource; public class Boss { // 自动注入¾cÕdž‹ä¸?Car çš?Bean @Resource private Car car; // 自动注入 bean åç§°ä¸?office çš?Bean @Resource(name = "office") private Office office; } |
一般情况下åQŒæˆ‘ä»¬æ— éœ€ä½¿ç”¨¾cÖM¼¼äº?@Resource(type=Car.class)
的注释方å¼ï¼Œå› 䨓(f¨´) Bean 的类型信æ¯å¯ä»¥é€šè¿‡ Java å射从代ç ä¸èŽ·å–ã€?/p>
è¦è®© JSR-250 的注释生效,除了(ji¨£n)åœ?Bean ¾cÖM¸æ ‡æ³¨˜q™äº›æ³¨é‡Šå¤–,˜q˜éœ€è¦åœ¨ Spring 容噍䏿³¨å†Œä¸€ä¸ªè´Ÿè´£å¤„ç†è¿™äº›æ³¨é‡Šçš„ BeanPostProcessor
åQ?/p>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> |
CommonAnnotationBeanPostProcessor
实现�BeanPostProcessor
接å£åQŒå®ƒè´Ÿè´£æ‰«æä½¿ç”¨äº?JSR-250 注释çš?BeanåQŒåƈ对它们进行相应的æ“作ã€?/p>
Spring 容器ä¸çš„ Bean 是有生命周期的,Spring å…许åœ?Bean 在åˆå§‹åŒ–完æˆåŽä»¥å?Bean 销æ¯å‰æ‰§è¡Œç‰¹å®šçš„æ“ä½œï¼Œæ‚(zh¨¨n)¨æ—¢å¯ä»¥é€šè¿‡å®žçް InitializingBean/DisposableBean æŽ¥å£æ¥å®šåˆ¶åˆå§‹åŒ–ä¹‹åŽ / 销æ¯ä¹‹å‰çš„æ“ä½œæ–ÒŽ(gu¨©)³•åQŒä¹Ÿå¯ä»¥é€šè¿‡ <bean> å…ƒç´ çš?init-method/destroy-method 属性指定åˆå§‹åŒ–ä¹‹åŽ / 销æ¯ä¹‹å‰è°ƒç”¨çš„æ“ä½œæ–ÒŽ(gu¨©)³•。关äº?Spring 的生命周期,½W”者在《精é€?Spring 2.x—ä¼ä¸šåº”用开å‘精解》第 3 ç« è¿›è¡Œäº†(ji¨£n)详细的æ˜qŽÍ¼Œæœ‰å…´‘£çš„读者å¯ä»¥æŸ¥é˜…ã€?/p>
JSR-250 为åˆå§‹åŒ–之åŽ/销æ¯ä¹‹å‰æ–¹æ³•的指定定义äº?ji¨£n)两个注释类åQŒåˆ†åˆ«æ˜¯ @PostConstruct å’?@PreDestroyåQŒè¿™ä¸¤ä¸ªæ³¨é‡Šåªèƒ½åº”ç”¨äºŽæ–¹æ³•ä¸Šã€‚æ ‡æ³¨äº†(ji¨£n) @PostConstruct 注释的方法将在类实例化åŽè°ƒç”¨åQŒè€Œæ ‡æ³¨äº†(ji¨£n) @PreDestroy 的方法将在类销æ¯ä¹‹å‰è°ƒç”¨ã€?/p>
æ¸…å• 17. 使用 @PostConstruct å’?@PreDestroy 注释çš?Boss.java
package com.baobaotao; import javax.annotation.Resource; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class Boss { @Resource private Car car; @Resource(name = "office") private Office office; @PostConstruct public void postConstruct1(){ System.out.println("postConstruct1"); } @PreDestroy public void preDestroy1(){ System.out.println("preDestroy1"); } … } |
æ‚(zh¨¨n)¨åªéœ€è¦åœ¨æ–ÒŽ(gu¨©)³•剿 ‡æ³?@PostConstruct
�@PreDestroy
åQŒè¿™äº›æ–¹æ³•å°±ä¼?x¨¬)åœ?Bean åˆå§‹åŒ–åŽæˆ–销æ¯ä¹‹å‰è¢« Spring 容器执行äº?ji¨£n)ã€?/p>
我们知é“åQŒä¸½Ž¡æ˜¯é€šè¿‡å®žçް InitializingBean
/DisposableBean
接å£åQŒè¿˜æ˜¯é€šè¿‡ <bean> å…ƒç´ çš?init-method/destroy-method
属性进行酾|®ï¼Œéƒ½åªèƒ½äØ“(f¨´) Bean 指定一个åˆå§‹åŒ– / 销æ¯çš„æ–ÒŽ(gu¨©)³•。但是ä‹Éç”?@PostConstruct
å’?@PreDestroy
注释å´å¯ä»¥æŒ‡å®šå¤šä¸ªåˆå§‹åŒ– / é”€æ¯æ–¹æ³•ï¼Œé‚£äº›è¢«æ ‡æ³?@PostConstruct
�@PreDestroy
注释的方法都ä¼?x¨¬)在åˆå§‹å?/ é”€æ¯æ—¶è¢«æ‰§è¡Œã€?/p>
通过以下的测试代ç ,æ‚(zh¨¨n)¨å°†å¯ä»¥çœ‹åˆ° Bean çš„åˆå§‹åŒ– / é”€æ¯æ–¹æ³•是如何被执行的åQ?/p>
æ¸…å• 18. ‹¹‹è¯•¾cÖM»£ç ?/strong>
package com.baobaotao; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AnnoIoCTest { public static void main(String[] args) { String[] locations = {"beans.xml"}; ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(locations); Boss boss = (Boss) ctx.getBean("boss"); System.out.println(boss); ctx.destroy();// å…³é— Spring 容器åQŒä»¥è§¦å‘ Bean é”€æ¯æ–¹æ³•的执行 } } |
˜q™æ—¶åQŒæ?zh¨¨n)¨ž®†çœ‹åˆ°æ ‡æ³¨äº?ji¨£n) @PostConstruct
çš?postConstruct1()
æ–ÒŽ(gu¨©)³•ž®†åœ¨ Spring 容器å¯åЍæ—Óž¼Œåˆ›å¾ Boss
Bean çš„æ—¶å€™è¢«è§¦å‘æ‰§è¡ŒåQŒè€Œæ ‡æ³¨äº†(ji¨£n) @PreDestroy
注释�preDestroy1()
æ–ÒŽ(gu¨©)³•ž®†åœ¨ Spring 容器关é—å‰é”€æ¯?Boss
Bean çš„æ—¶å€™è¢«è§¦å‘æ‰§è¡Œã€?/p>
![]() ![]() |
![]()
|
使用 <context:annotation-config/> ½Ž€åŒ–é…¾|?/span>
Spring 2.1 æ·ÕdŠ äº?ji¨£n)一个新çš?context çš?Schema 命å½Iºé—´åQŒè¯¥å‘½å½Iºé—´å¯ÒŽ(gu¨©)³¨é‡Šé©±åЍã€å±žæ€§æ–‡ä»¶å¼•å…¥ã€åŠ è½½æœŸ¾l‡å…¥½{‰åŠŸèƒ½æä¾›äº†(ji¨£n)便æ·çš„é…¾|®ã€‚æˆ‘ä»¬çŸ¥é“æ³¨é‡Šæœ¬íw«æ˜¯ä¸ä¼š(x¨¬)åšä“Q何事情的åQŒå®ƒä»…æä¾›å…ƒæ•°æ®ä¿¡æ¯ã€‚è¦ä½¿å…ƒæ•°æ®ä¿¡æ¯çœŸæ£èµ·ä½œç”¨ï¼Œå¿…须让负责处ç†è¿™äº›å…ƒæ•°æ®çš„处ç†å™¨å·¥ä½œèµäh¥ã€?
而我们å‰é¢æ‰€ä»‹ç»çš?AutowiredAnnotationBeanPostProcessor
å’?CommonAnnotationBeanPostProcessor
ž®±æ˜¯å¤„熘q™äº›æ³¨é‡Šå…ƒæ•°æ®çš„处ç†å™¨ã€‚但是直接在 Spring é…置文äšgä¸å®šä¹‰è¿™äº?Bean 昑־—比较½W¨æ‹™ã€‚Spring 为我们æä¾›äº†(ji¨£n)一¿U方便的注册˜q™äº› BeanPostProcessor
的方å¼ï¼Œ˜q™å°±æ˜?<context:annotation-config/>。请看下é¢çš„é…ç½®åQ?/p>
æ¸…å• 19. 调整 beans.xml é…置文äšg
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="boss" class="com.baobaotao.Boss"/> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" ¾U¢æ—— CA72"/> <property name="price" value="2000"/> </bean> </beans> |
<context:annotationconfig/> ž®†éšå¼åœ°å?Spring 容器注册 AutowiredAnnotationBeanPostProcessor
ã€?code>CommonAnnotationBeanPostProcessorã€?code>PersistenceAnnotationBeanPostProcessor 以åŠ(qi¨¢ng) equiredAnnotationBeanPostProcessor
˜q?4 ä¸?BeanPostProcessorã€?/p>
在酾|®æ–‡ä»¶ä¸ä½¿ç”¨ context 命å½Iºé—´ä¹‹å‰åQŒå¿…™åÕdœ¨ <beans> å…ƒç´ ä¸å£°æ˜?context 命å½Iºé—´ã€?/p>
![]() ![]() |
![]()
|
虽然我们å¯ä»¥é€šè¿‡ @Autowired
�@Resource
åœ?Bean ¾cÖM¸ä½¿ç”¨è‡ªåŠ¨æ³¨å…¥åŠŸèƒ½åQŒä½†æ˜?Bean ˜q˜æ˜¯åœ?XML æ–‡äšgä¸é€šè¿‡ <bean> ˜q›è¡Œå®šä¹‰ —â€?也就是说åQŒåœ¨ XML é…置文äšgä¸å®šä¹?BeanåQŒé€šè¿‡ @Autowired
�@Resource
ä¸?Bean çš„æˆå‘˜å˜é‡ã€æ–¹æ³•入傿ˆ–æž„é€ å‡½æ•°å…¥å‚æä¾›è‡ªåŠ¨æ³¨å…¥çš„åŠŸèƒ½ã€‚èƒ½å¦ä¹Ÿé€šè¿‡æ³¨é‡Šå®šä¹‰ BeanåQŒä»Ž XML é…置文äšgä¸å®Œå…¨ç§»é™?Bean 定义的酾|®å‘¢åQŸç”案是肯定的,我们通过 Spring 2.5 æä¾›çš?@Component
注释ž®±å¯ä»¥è¾¾åˆ°è¿™ä¸ªç›®æ ‡äº†(ji¨£n)ã€?/p>
下é¢åQŒæˆ‘们完全ä‹É用注释定ä¹?Bean òq¶å®Œæˆ?Bean 之间装é…åQ?/p>
æ¸…å• 20. 使用 @Component 注释çš?Car.java
package com.baobaotao; import org.springframework.stereotype.Component; @Component public class Car { … } |
仅需è¦åœ¨¾cÕd®šä¹‰å¤„åQŒä‹Éç”?@Component
注释ž®±å¯ä»¥å°†ä¸€ä¸ªç±»å®šä¹‰äº?Spring 容器ä¸çš„ Bean。下é¢çš„ä»£ç ž®?Office
定义ä¸ÞZ¸€ä¸?BeanåQ?/p>
æ¸…å• 21. 使用 @Component 注释çš?Office.java
package com.baobaotao; import org.springframework.stereotype.Component; @Component public class Office { private String officeNo = "001"; … } |
˜q™æ ·åQŒæˆ‘们就å¯ä»¥åœ?Boss ¾cÖM¸é€šè¿‡ @Autowired
注入å‰é¢å®šä¹‰çš?Car
å’?Office Bean
äº?ji¨£n)ã€?/p>
æ¸…å• 22. 使用 @Component 注释çš?Boss.java
package com.baobaotao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("boss") public class Boss { @Autowired private Car car; @Autowired private Office office; … } |
@Component
有一个å¯é€‰çš„å…¥å‚åQŒç”¨äºŽæŒ‡å®?Bean çš„å¿UŽÍ¼Œåœ?Boss ä¸ï¼Œæˆ‘们ž®±å°† Bean å称定义ä¸?#8220;boss
”。一般情况下åQŒBean 都是 singleton çš„ï¼Œéœ€è¦æ³¨å…?Bean 的地方仅需è¦é€šè¿‡ byType ½{–ç•¥ž®±å¯ä»¥è‡ªåŠ¨æ³¨å…¥äº†(ji¨£n)åQŒæ‰€ä»¥å¤§å¯ä¸å¿…指å®?Bean çš„å¿U°ã€?/p>
在ä‹Éç”?@Component
注释åŽï¼ŒSpring 容器必须å¯ç”¨¾cÀL‰«ææœºåˆ¶ä»¥å¯ç”¨æ³¨é‡Šé©±åЍ Bean 定义和注释驱åŠ?Bean 自动注入的ç–略。Spring 2.5 å¯?context 命å½Iºé—´˜q›è¡Œäº?ji¨£n)扩展,æä¾›äº†(ji¨£n)这一功能åQŒè¯·çœ‹ä¸‹é¢çš„é…ç½®åQ?/p>
æ¸…å• 23. ½Ž€åŒ–版çš?beans.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.baobaotao"/> </beans> |
˜q™é‡ŒåQŒæ‰€æœ‰é€šè¿‡ <bean> å…ƒç´ å®šä¹‰ Bean 的酾|®å†…容已¾l被¿U»é™¤åQŒä»…éœ€è¦æ·»åР䏀è¡?<context:component-scan/> é…ç½®ž®Þp§£å†Ïx(ch¨®ng)‰€æœ‰é—®é¢˜ä(sh¨´)º†(ji¨£n)——Spring XML é…置文äšg得到äº?ji¨£n)æžè‡´çš„½Ž€åŒ–(当然é…置元数æ®è¿˜æ˜¯éœ€è¦çš„åQŒåªä¸è¿‡ä»¥æ³¨é‡ŠåÅžå¼å˜åœ¨çÅžäº?ji¨£n)ï¼?j¨ª)ã€?lt;context:component-scan/> çš?base-package 属性指定了(ji¨£n)éœ€è¦æ‰«æçš„¾cÕdŒ…åQŒç±»åŒ…åŠ(qi¨¢ng)å…‰™€’å½’ååŒ…ä¸æ‰€æœ‰çš„¾c»éƒ½ä¼?x¨¬)被处ç†ã€?/p>
<context:component-scan/> ˜q˜å…许定义过滤器ž®†åŸºåŒ…下的æŸäº›ç±»¾U›_…¥æˆ–排除。Spring 支æŒä»¥ä¸‹ 4 ¿U类型的˜q‡æ×o(h¨´)æ–¹å¼åQŒé€šè¿‡ä¸‹è¡¨è¯´æ˜ŽåQ?/p>
˜q‡æ×o(h¨´)器类åž?/th> | 说明 |
---|---|
注释 | å‡å¦‚ com.baobaotao.SomeAnnotation 是一个注释类åQŒæˆ‘们å¯ä»¥å°†ä½¿ç”¨è¯¥æ³¨é‡Šçš„¾c»è¿‡æ»¤å‡ºæ¥ã€?/td> |
¾cÕd指定 | 通过全é™å®šç±»å进行过滤,如æ?zh¨¨n)¨å¯ä»¥æŒ‡å®šž?com.baobaotao.Boss ¾U›_…¥æ‰«æåQŒè€Œå°† com.baobaotao.Car 排除在外ã€?/td> |
æ£åˆ™è¡¨è¾¾å¼?/td> | 通过æ£åˆ™è¡¨è¾¾å¼å®šä¹‰è¿‡æ»¤çš„¾c»ï¼Œå¦‚下所½Cºï¼š(x¨¬) com\.baobaotao\.Default.* |
AspectJ 表达å¼?/td> | 通过 AspectJ 表达å¼å®šä¹‰è¿‡æ»¤çš„¾c»ï¼Œå¦‚下所½Cºï¼š(x¨¬) com. baobaotao..*Service+ |
䏋颿˜¯ä¸€ä¸ªç®€å•的例ååQ?/p>
<context:component-scan base-package="com.baobaotao"> <context:include-filter type="regex" expression="com\.baobaotao\.service\..*"/> <context:exclude-filter type="aspectj" expression="com.baobaotao.util..*"/> </context:component-scan> |
值得注æ„的是 <context:component-scan/> é…ç½®™å¹ä¸ä½†å¯ç”¨äº†(ji¨£n)对类包进行扫æä»¥å®žæ–½æ³¨é‡Šé©±åЍ Bean å®šä¹‰çš„åŠŸèƒ½ï¼ŒåŒæ—¶˜q˜å¯ç”¨äº†(ji¨£n)注释驱动自动注入的功能(匙¿˜éšå¼åœ°åœ¨å†…部注册äº?AutowiredAnnotationBeanPostProcessor
å’?CommonAnnotationBeanPostProcessor
åQ‰ï¼Œå› æ¤å½“ä‹Éç”?<context:component-scan/> åŽï¼Œž®±å¯ä»¥å°† <context:annotation-config/> ¿U»é™¤äº?ji¨£n)ã€?/p>
默认情况下通过 @Component
定义çš?Bean 都是 singleton 的,如果需è¦ä‹É用其它作用范围的 BeanåQŒå¯ä»¥é€šè¿‡ @Scope
注释æ¥è¾¾åˆ°ç›®æ ‡ï¼Œå¦‚ä»¥ä¸‹ä»£ç æ‰€½Cºï¼š(x¨¬)
æ¸…å• 24. 通过 @Scope 指定 Bean 的作用范å›?/strong>
package com.baobaotao; import org.springframework.context.annotation.Scope; … @Scope("prototype") @Component("boss") public class Boss { … } |
˜q™æ ·åQŒå½“ä»?Spring 容器ä¸èŽ·å?boss
Bean æ—Óž¼Œæ¯æ¬¡˜q”回的都是新的实例了(ji¨£n)ã€?/p>
![]() ![]() |
![]()
|
采用å…ähœ‰ç‰ÒŽ(gu¨©)®Šè¯ä¹‰çš„æ³¨é‡?/span>
Spring 2.5 ä¸é™¤äº?ji¨£n)æä?@Component
注释外,˜q˜å®šä¹‰äº†(ji¨£n)å‡ ä¸ªæ‹¥æœ‰ç‰ÒŽ(gu¨©)®Šè¯ä¹‰çš„æ³¨é‡Šï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯ï¼š(x¨¬)@Repository
�code>@Service �@Controller
。在目å‰çš?Spring 版本ä¸ï¼Œ˜q?3 个注释和 @Component
æ˜¯ç‰æ•ˆçš„åQŒä½†æ˜¯ä»Žæ³¨é‡Š¾cÈš„命å上,很容易看å‡?gu¨®)™¿?3 个注释分别和æŒä¹…层ã€ä¸šåŠ¡å±‚å’ŒæŽ§åˆ¶å±‚åQˆWeb 层)(j¨ª)相对应。虽然目å‰è¿™ 3 个注释和 @Component
相比没有什么新æ„,ä½?Spring ž®†åœ¨ä»¥åŽçš„版本ä¸ä¸ºå®ƒä»¬æ·»åŠ ç‰¹ŒDŠçš„功能。所以,如果 Web 应用½E‹åºé‡‡ç”¨äº?ji¨£n)ç»å…¸çš„三层分层¾l“构的è¯åQŒæœ€å¥½åœ¨æŒä¹…层ã€ä¸šåŠ¡å±‚å’ŒæŽ§åˆ¶å±‚åˆ†åˆ«é‡‡ç”¨ @Repository
�code>@Service �@Controller
对分层ä¸çš„ç±»˜q›è¡Œæ³¨é‡ŠåQŒè€Œç”¨ @Component
寚w‚£äº›æ¯”较ä¸ç«‹çš„¾c»è¿›è¡Œæ³¨é‡Šã€?/p>
![]() ![]() |
![]()
|
注释é…ç½®å’?XML é…置的适用场åˆ
æ˜¯å¦æœ‰äº†(ji¨£n)˜q™äº› IOC 注释åQŒæˆ‘们就å¯ä»¥å®Œå…¨æ‘’é™¤åŽŸæ¥ XML é…置的方å¼å‘¢åQŸç”案是å¦å®šçš„ã€‚æœ‰ä»¥ä¸‹å‡ ç‚¹åŽŸå› åQ?/p>
JdbcTemplate
ã€?code>SessionFactoryBean ½{‰ï¼‰(j¨ª)åQŒæ³¨é‡Šé…¾|®å°†æ— 法实施åQŒæ¤æ—?XML é…置是唯一å¯ç”¨çš„æ–¹å¼ã€?@Transaction
事务注释åQŒä‹Éç”?aop/tx 命å½Iºé—´çš„事务酾|®æ›´åŠ çµ‹zÕd’Œ½Ž€å•ã€?所以在实现应用ä¸ï¼Œæˆ‘们往往需è¦åŒæ—¶ä‹É用注释酾|®å’Œ XML é…ç½®åQŒå¯¹äºŽç±»¾U§åˆ«ä¸”ä¸ä¼?x¨¬)å‘生å˜åŠ¨çš„é…ç½®å¯ä»¥ä¼˜å…ˆè€ƒè™‘注释é…ç½®åQ›è€Œå¯¹äºŽé‚£äº›ç¬¬ä¸‰æ–¹¾cÖM»¥å?qi¨¢ng)容易å‘生调整的é…置则应优先考虑使用 XML é…置。Spring ä¼?x¨¬)在具体实æ–?Bean 创å¾å’?Bean 注入之剞®†è¿™ä¸¤ç§é…置方å¼çš„元信æ¯èžåˆåœ¨ä¸€èµ—÷€?/p>
![]() ![]() |
![]()
|
Spring åœ?2.1 以åŽå¯ÒŽ(gu¨©)³¨é‡Šé…¾|®æä¾›äº†(ji¨£n)强力的支æŒï¼Œæ³¨é‡Šé…置功能æˆäØ“(f¨´) Spring 2.5 的最大的亮点之一。åˆç†åœ°ä½¿ç”¨ Spring 2.5 的注释酾|®ï¼Œå¯ä»¥æœ‰æ•ˆå‡å°‘é…置的工作é‡åQŒæé«˜ç¨‹åºçš„å†…èšæ€§ã€‚但是这òq¶ä¸æ„味ç€ä¼ 统 XML é…ç½®ž®†èµ°å‘消亡,在第三方¾c?Bean 的酾|®ï¼Œä»¥åŠ(qi¨¢ng)é‚£äº›è¯¸å¦‚æ•°æ®æºã€ç¼“å˜æ± ã€æŒä¹…层æ“作模濾c…R€äº‹åŠ¡ç®¡ç†ç‰å†…容的酾|®ä¸ŠåQŒXML é…ç½®ä¾ç„¶æ‹¥æœ‰ä¸å¯æ›¿ä»£çš„地ä½ã€?/p>
FreeMarkeråŸÞZºŽè®¾è®¡è€…å’Œ½E‹åºå‘˜æ˜¯å…ähœ‰ä¸åŒä¸“业技能的ä¸åŒä¸ªä½“的观念他们是分工力_Š¨çš„ï¼š(x¨¬)
设计者专注于表示——创建HTMLæ–‡äšgã€å›¾ç‰‡ã€Web™åµé¢çš„其它å¯è§†åŒ–æ–šw¢åQ?br />
½E‹åºå‘˜åˆ›å»ºç³»¾lŸï¼Œç”Ÿæˆè®¾è®¡™åµé¢è¦æ˜¾½Cºçš„æ•°æ®ã€?br />
¾l常ä¼?x¨¬)é‡åˆ°çš„问题是ï¼?x¨¬)在Web™åµé¢åQˆæˆ–其它¾cÕdž‹çš„æ–‡æ¡£ï¼‰(j¨ª)䏿˜¾½Cºçš„ä¿¡æ¯åœ¨è®¾è®¡é¡µé¢æ—¶æ˜¯æ— 效的åQŒæ˜¯åŸÞZºŽåŠ¨æ€æ•°æ®çš„。在˜q™é‡ŒåQŒä½ å¯ä»¥åœ¨HTMLåQˆæˆ–其它è¦è¾“出的文本åQ‰ä¸åŠ å…¥ä¸€äº›ç‰¹å®šæŒ‡ä»¤ï¼ŒFreeMarkerä¼?x¨¬)在输出™åµé¢¾l™æœ€¾lˆç”¨æˆäh—¶åQŒç”¨é€‚å½“çš„æ•°æ®æ›¿ä»£è¿™äº›ä»£ç ã€?/p>
å…ˆæ¥è§£é‡Šä¸€ä¸‹freemakerçš„åŸºæœ¬è¯æ³•了(ji¨£n)åQ?br />
<# ... > ä¸å˜æ”¾æ‰€æœ‰freemakerçš„å†…å®¹ï¼Œä¹‹å¤–çš„å†…å®¹å…¨éƒ¨åŽŸæ ¯‚¾“出ã€?br />
<@ ... /> 是函数调�br />
两个定界½W¦å†…的内容ä¸åQŒç¬¬ä¸€ä¸ªç¬¦å¯‚¡¨½CºæŒ‡ä»¤æˆ–者函数ååQŒå…¶åŽçš„è·Ÿéšå‚数。freemakeræä¾›çš„æŽ§åˆ¶åŒ…括如下:(x¨¬)
<#if condition><#elseif condition><#else> æ¡äšg判æ–
<#list hash_or_seq as var> é历hash表或者collectionåQˆfreemaker¿UîC½œsequenceåQ‰çš„æˆå‘˜
<#macro name param1 param2 ... ><#nested param> å®ï¼Œæ— è¿”å›žå‚æ•?br />
<#function name param1 param2><#return val>函数åQŒæœ‰˜q”å›žå‚æ•°
var?member_function(...) 用函数对var˜q›è¡Œè½¬æ¢åQŒfreemaker¿UîCØ“(f¨´)build-ins。实际内部实现类似member_function(var, ...)
stringA[M .. N] å–åå—符ä¸ÔŒ¼Œ¾cÖM¼¼substring(stringA, M, N)
{key:value, key2:value2 ...} 直接定义一个hash�br />
[item0, item1, item2 ...] 直接定义一个åºåˆ?br />
hash0[key0] å˜å–hash表ä¸key对应的元ç´?br />
seq0[5] å˜å–åºåˆ—æŒ‡å®šä¸‹æ ‡çš„å…ƒç´?br />
<@function1 param0 param1 ... /> 调用函数function1
<@macro0 param0 param1 ; nest_param0 nest_param1 ...> nest_body </@macro> 调用å®ï¼Œòq¶å¤„ç†å®çš„嵌å¥?br />
<#assign var = value > 定义å˜é‡òq¶åˆå§‹åŒ–
<#local var = value> åœ?macro 或è€?function ä¸å®šä¹‰å±€éƒ¨å˜é‡åƈåˆå§‹åŒ?br />
<#global var = value > 定义全局å˜é‡òq¶åˆå§‹åŒ–
${var} 输出òq¶æ›¿æ¢äØ“(f¨´)表达å¼çš„å€?br />
<#visit xmlnode> 调用macro匚w…xmlnode本èínå?qi¨¢ng)å…¶å节ç?br />
<#recurse xmlnode> 调用macro匚w…xmlnodeçš„å节点
䏋颿˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<html>˜q™ä¸ªä¾‹å是在½Ž€å•çš„HTMLä¸åŠ å…¥äº†(ji¨£n)一些由${…}包围的特定代ç ,˜q™äº›ç‰¹å®šä»£ç 是FreeMarker的指令,而包å«FreeMarker的指令的文äšgž®Þq§°ä¸ºæ¨¡æ¿ï¼ˆTemplateåQ‰ã€?br /> 至于userã€latestProduct.urlå’ŒlatestProduct.nameæ¥è‡ªäºŽæ•°æ®æ¨¡åž‹ï¼ˆdata modelåQ‰ã€?br /> æ•°æ®æ¨¡åž‹ç”Þq¨‹åºå‘˜¾~–程æ¥åˆ›å»ºï¼Œå‘æ¨¡æ¿æä¾›å˜åŒ–的信æ¯åQŒè¿™äº›ä¿¡æ¯æ¥è‡ªäºŽæ•°æ®åº“ã€æ–‡ä»Óž¼Œç”šè‡³äºŽåœ¨½E‹åºä¸ç›´æŽ¥ç”Ÿæˆã€?br /> 模æ¿è®¾è®¡è€…ä¸å…›_¿ƒ(j¨©)æ•°æ®ä»Žé‚£å„¿æ¥åQŒåªçŸ¥é“使用已ç»å»ºç«‹çš„æ•°æ®æ¨¡åž‹ã€?br />
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
䏋颿˜¯ä¸€ä¸ªå¯èƒ½çš„æ•°æ®æ¨¡åž‹åQ?
(root)æ•°æ®æ¨¡åž‹¾cÖM¼¼äºŽè®¡½Ž—机的文件系¾lŸï¼ŒlatestProductå¯ä»¥çœ‹ä½œæ˜¯ç›®å½•ã€?
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
在快速入门ä¸ä»‹ç»äº?ji¨£n)在模æ¿ä¸ä‹É用的三ç§åŸºæœ¬å¯¹è±¡¾cÕdž‹åQšscalarsã€hashes å’ŒsequencesåQŒå…¶å®žè¿˜å¯ä»¥æœ‰å…¶å®ƒæ›´å¤šçš„能力åQ?
通常æ¯ä¸ªå˜é‡åªå…·æœ‰ä¸Š˜q°çš„一¿U能力,但一个å˜é‡å¯ä»¥å…·æœ‰å¤šä¸ªä¸Š˜q°èƒ½åŠ›ï¼Œå¦‚ä¸‹é¢çš„例ååQ?
(root)mouse既是scalarsåˆæ˜¯hashesåQŒå°†ä¸Šé¢çš„æ•°æ®æ¨¡åž‹åˆòq¶åˆ°ä¸‹é¢çš„æ¨¡æ¿ï¼š(x¨¬)
|
+- mouse = "Yerri"
|
+- age = 12
|
+- color = "brown">
${mouse} <#-- use mouse as scalar -->输出¾l“果是:(x¨¬)
${mouse.age} <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash -->
Yerri
12
brown
Scalarå˜é‡å˜å‚¨å•å€û|¼Œå¯ä»¥æ˜¯ï¼š(x¨¬)
有些å˜é‡ä¸åŒ…å«ä“Q何坿˜„¡¤ºçš„å†…å®¹ï¼Œè€Œæ˜¯ä½œäØ“(f¨´)容器包å«å…¶å®ƒå˜é‡åQŒè€…有两秾cÕdž‹åQ?
集åˆå˜é‡é€šå¸¸¾cÖM¼¼sequencesåQŒé™¤éžæ— 法访问它的大ž®å’Œä¸èƒ½ä½¿ç”¨ç´¢å¼•æ¥èŽ·å¾—å®ƒçš„åå˜é‡åQ›é›†åˆå¯ä»¥çœ‹ä½œåªèƒ½ç”±<#list …>指ä×o(h¨´)使用的å—é™sequences
æ–ÒŽ(gu¨©)³•å˜é‡é€šå¸¸æ˜¯åŸºäºŽç»™å‡ºçš„傿•°è®¡ç®—倹{€?
下é¢çš„例åå‡è®„¡¨‹åºå‘˜å·²ç»ž®†æ–¹æ³•å˜é‡avg攑ֈ°æ•°æ®æ¨¡åž‹ä¸ï¼Œç”¨æ¥è®¡ç®—æ•°å—òq›_‡å€û|¼š(x¨¬)
The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is:
${avg(animals.python.price, animals.elephant.price)}
å®å’Œå˜æ¢å™¨å˜é‡æ˜¯ç”¨æˆ·è‡ªå®šä¹‰æŒ‡ä»¤ï¼ˆè‡ªå®šä¹‰FTLæ ‡è®°åQ‰ï¼Œä¼?x¨¬)在åŽé¢è®²è¿°˜q™äº›é«˜çñ”ç‰ÒŽ(gu¨©)€?
节点å˜é‡è¡¨ç¤ºä¸ºæ ‘(w¨¨i)型结构ä¸çš„一个节点,通常在XML处ç†ä¸ä‹É用,ä¼?x¨¬)在åŽé¢çš„ä¸“é—¨ç« èŠ‚ä¸è?
模æ¿ä½¿ç”¨FTLåQˆF(tu¨¢n)reeMarker模æ¿è¯è¨€åQ‰ç¼–写,是下é¢å„部分的一个组åˆï¼š(x¨¬)
䏋颿˜¯ä»¥ä¸€ä¸ªå…·ä½“模æ¿ä¾‹å:(x¨¬)
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<#-- Greet the user with his/her name -->
<h1>Welcome ${user}!</h1>
<p>We have these animals:
<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
</#list>
</ul>
</body>
</html>
注æ„事项åQ?
<#if <#include 'foo'>='bar'>...</if>
<h1>Welcome ${user <#-- The name of user -->}!</h1>
<p>We have these animals:
<ul>
<#list <#-- some comment... --> animals as <#-- again... --> being>
...
在FreeMarkerä¸ï¼Œä½¿ç”¨FTLæ ‡è®°å¼•ç”¨æŒ‡ä×o(h¨´)。有三ç§FTLæ ‡è®°åQŒè¿™å’ŒHTMLæ ‡è®°æ˜¯ç±»ä¼¼çš„åQ?
有两¿U类型的指ä×o(h¨´)åQšé¢„定义指ä×o(h¨´)和用户定义指令ã€?
用户定义指ä×o(h¨´)è¦ä‹É用@替æ¢#åQŒå¦‚<@mydirective>...</@mydirective>åQˆä¼š(x¨¬)在åŽé¢è®²˜qŽÍ¼‰(j¨ª)ã€?
FTLæ ‡è®°ä¸èƒ½å¤Ÿäº¤å‰ï¼Œè€Œåº”该棼‹®çš„嵌套åQŒå¦‚下é¢çš„ä»£ç æ˜¯é”™è¯¯çš„:(x¨¬)
<ul>如果使用ä¸å˜åœ¨çš„æŒ‡ä×o(h¨´)åQŒFreeMarkerä¸ä¼š(x¨¬)使用模æ¿è¾“出åQŒè€Œæ˜¯äº§ç”Ÿä¸€ä¸ªé”™è¯¯æ¶ˆæ¯ã€?
<#list animals as being>
<li>${being.name} for ${being.price} Euros
<#if use = "Big Joe">
(except for you)
</#list>
</#if> <#-- WRONG! -->
</ul>
FreeMarkerä¼?x¨¬)忽略FTLæ ‡è®°ä¸çš„½Iºç™½å—符åQŒå¦‚下é¢çš„例å:(x¨¬)
<#list但是åQ?lt;ã€?lt;/和指令之间ä¸å…许有空白嗽W¦ã€?
animals as
being
>
${being.name} for ${being.price} Euros
</#list >
直接指定�/strong>
如果包å«ç‰ÒŽ(gu¨©)®Šå—符需è¦è{义,如下é¢çš„例ååQ?
${"It's \"quoted\" and输出¾l“果是:(x¨¬)
this is a backslash: \\"}
${'It\'s "quoted" and
this is a backslash: \\'}
It's "quoted" and䏋颿˜¯æ”¯æŒçš„转义åºåˆ—åQ?
this is a backslash: \
It's "quoted" and
this is a backslash: \
转义åºåˆ— | å«ä¹‰ |
---|---|
\" | åŒå¼•å?u0022) |
\' | å•引å?u0027) |
åæ–œæ?u005C) | |
\n | æ¢è¡Œ(u000A) |
\r | Return (u000D) |
\t | Tab (u0009) |
\b | Backspace (u0008) |
\f | Form feed (u000C) |
\l | < |
\g | > |
\a | & |
\{ | { |
\xCode | 4ä½?6˜q›åˆ¶Unicode代ç |
有一¾cȉ¹ŒDŠçš„å—符串称为rawå—符ä¸ÔŒ¼Œè¢«è®¤ä¸ºæ˜¯¾U¯æ–‡æœ¬ï¼Œå…¶ä¸çš„\å’Œ{½{‰ä¸å…ähœ‰ç‰ÒŽ(gu¨©)®Šå«ä¹‰åQŒè¯¥¾cÕd—½W¦ä¸²åœ¨å¼•å·å‰é¢åŠ råQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
${r"${foo}"}输出的结果是åQ?
${r"C:\foo\bar"}
${foo}
C:\foo\bar
直接输入åQŒä¸éœ€è¦å¼•å?
¾_‘Öº¦æ•°å—使用“.”分隔åQŒä¸èƒ½ä‹É用分¾l„符å?
ç›®å‰ç‰ˆæœ¬ä¸æ”¯æŒç§‘å¦è®¡æ•°æ³•åQŒæ‰€ä»?#8220;1E3”是错误的
ä¸èƒ½çœç•¥ž®æ•°ç‚¹å‰é¢çš„0åQŒæ‰€ä»?#8220;.5”是错误的
æ•°å—8ã€?8ã€?8å’?.00都是相åŒçš?
trueå’ŒfalseåQŒä¸ä½¿ç”¨å¼•å·
由逗å·åˆ†éš”çš„åå˜é‡åˆ—表åQŒç”±æ–ÒŽ(gu¨©)‹¬å·é™å®šï¼Œä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#list ["winter", "spring", "summer", "autumn"] as x>输出的结果是åQ?
${x}
</#list>
winter列表的项目是表达å¼ï¼Œæ‰€ä»¥å¯ä»¥æœ‰ä¸‹é¢çš„例å:(x¨¬)
spring
summer
autumn
[2 + 2, [1, 2, 3, 4], "whatnot"]å¯ä»¥ä½¿ç”¨æ•°å—范围定义数å—åºåˆ—åQŒä¾‹å¦?..5½{‰åŒäºŽ[2, 3, 4, 5]åQŒä½†æ˜¯æ›´æœ‰æ•ˆçŽ‡ï¼Œæ³¨æ„æ•°å—范围没有æ–ÒŽ(gu¨©)‹¬å?
å¯ä»¥å®šä¹‰å递增的数å—范å›ß_(d¨¢)¼Œå¦?..2
{"name":"green mouse", "price":150}键和值都是表辑ּåQŒä½†æ˜¯é”®å¿…须是嗽W¦ä¸²
获å–å˜é‡
å¯ä»¥ä½¿ç”¨ç‚¹è¯æ³•或æ–ÒŽ(gu¨©)‹¬å¯‚¯æ³•,å‡è®¾æœ‰ä¸‹é¢çš„æ•°æ®æ¨¡åž‹åQ?
(root)下é¢éƒ½æ˜¯½{‰äh(hu¨¢n)的:(x¨¬)
|
+- book
| |
| +- title = "Breeding green mouses"
| |
| +- author
| |
| +- name = "Julia Smith"
| |
| +- info = "Biologist, 1923-1985, Canada"
|
+- test = "title"
book.author.nameä½¿ç”¨ç‚¹è¯æ³•,å˜é‡åå—æœ‰é¡¶å±‚å˜é‡ä¸€æ ïL(f¨¥ng)š„é™åˆ¶åQŒä½†æ–ÒŽ(gu¨©)‹¬å¯‚¯æ³•没有该é™åˆ¶åQŒå› 为åå—æ˜¯ä»ÀL„表达å¼çš„¾l“æžœ
book["author"].name
book.author.["name"]
book["author"]["name"]
åºåˆ—片æ–åQšä‹É用[startIndex..endIndex]è¯æ³•åQŒä»Žåºåˆ—ä¸èŽ·å¾—åºåˆ—片æ–(也是åºåˆ—åQ‰ï¼›startIndexå’ŒendIndexæ˜¯ç»“æžœäØ“(f¨´)æ•°å—的表辑ּ
å—符串æ“ä½?
å¯ä»¥ä½¿ç”¨${..}åQˆæˆ–#{..}åQ‰åœ¨æ–‡æœ¬éƒ¨åˆ†æ’入表达å¼çš„å€û|¼Œä¾‹å¦‚åQ?
${"Hello ${user}!"}å¯ä»¥ä½¿ç”¨+æ“作½W¦èŽ·å¾—åŒæ ïL(f¨¥ng)š„¾l“æžœ
${"${user}${user}${user}${user}"}
${"Hello " + user + "!"}${..}åªèƒ½ç”¨äºŽæ–‡æœ¬éƒ¨åˆ†åQŒä¸‹é¢çš„ä»£ç æ˜¯é”™è¯¯çš„åQ?
${user + user + user + user}
<#if ${isBig}>Wow!</#if>应该写æˆåQ?
<#if "${isBig}">Wow!</#if>
<#if isBig>Wow!</#if>
例ååQˆå‡è®¾userçš„å€égØ“(f¨´)“Big Joe”åQ‰ï¼š(x¨¬)
${user[0]}${user[4]}¾l“果是(注愽W¬ä¸€ä¸ªå—½W¦çš„索引æ˜?åQ‰ï¼š(x¨¬)
${user[1..4]}
BJåºåˆ—æ“作
ig J
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>输出¾l“果是:(x¨¬)
- ${user}
</#list>
- Joe散列æ“作
- Fred
- Julia
- Kate
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>输出¾l“果是:(x¨¬)
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}
- Joe is 30½Ž—术˜qç®—
- Fred is 25
- Julia is 18
${x * x - 100}输出¾l“果是(å‡è®¾xä¸?åQ‰ï¼š(x¨¬)
${x / 2}
${12 % 10}
-75æ“作½W¦ä¸¤è¾¹å¿…™åÀL˜¯æ•°å—åQŒå› æ¤ä¸‹é¢çš„ä»£ç æ˜¯é”™è¯¯çš„åQ?
2.5
2
${3 * "5"} <#-- WRONG! -->使用+æ“作½W¦æ—¶åQŒå¦‚果一è¾ÒŽ(gu¨©)˜¯æ•°å—åQŒä¸€è¾ÒŽ(gu¨©)˜¯å—符ä¸ÔŒ¼Œž®×ƒ¼š(x¨¬)自动ž®†æ•°å—è{æ¢äØ“(f¨´)å—符ä¸ÔŒ¼Œä¾‹å¦‚åQ?
${3 + "5"}输出¾l“果是:(x¨¬)
35使用内å¾çš„intåQˆåŽé¢è®²˜qŽÍ¼‰(j¨ª)获得整数部分åQŒä¾‹å¦‚:(x¨¬)
${(x/2)?int}输出¾l“果是(å‡è®¾xä¸?åQ‰ï¼š(x¨¬)
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}
2
1
1
-1
-1
使用=åQˆæˆ–==åQŒå®Œå…¨ç›¸½{‰ï¼‰(j¨ª)‹¹‹è¯•两个值是å¦ç›¸½{‰ï¼Œä½¿ç”¨!= ‹¹‹è¯•两个值是å¦ä¸ç›¸ç‰
=å’?=两边必须是相åŒç±»åž‹çš„å€û|¼Œå¦åˆ™ä¼?x¨¬)äñ”生错误,例å¦?lt;#if 1 = "1">ä¼?x¨¬)引起错è?
Freemarker是精¼‹®æ¯”较,所以对"x"ã€?x "å’?X"是ä¸ç›¸ç‰çš?
å¯ÒŽ(gu¨©)•°å—和日期å¯ä»¥ä½¿ç”¨<ã€?lt;=ã€?gt;å’?gt;=åQŒä½†ä¸èƒ½ç”¨äºŽå—符ä¸?
ç”׃ºŽFreemarkerä¼?x¨¬)å°?gt;解释æˆFTLæ ‡è®°çš„ç»“æŸå—½W¦ï¼Œæ‰€ä»¥å¯¹äº?gt;å’?gt;=å¯ä»¥ä½¿ç”¨æ‹¬å·æ¥é¿å…è¿™¿U情况,例如<#if (x > y)>
å¦ä¸€¿U替代的æ–ÒŽ(gu¨©)³•是,使用ltã€lteã€gtå’Œgteæ¥æ›¿ä»?lt;ã€?lt;=ã€?gt;å’?gt;=
&&åQˆandåQ‰ã€||åQˆoråQ‰ã€?åQˆnotåQ‰ï¼Œåªèƒ½ç”¨äºŽå¸ƒå°”å€û|¼Œå¦åˆ™ä¼?x¨¬)äñ”生错è?
例ååQ?
<#if x < 12 && color = "green">
We have less than 12 things, and they are green.
</#if>
<#if !hot> <#-- here hot must be a boolean -->
It's not hot.
</#if>
内å¾å‡½æ•°çš„ç”¨æ³•ç±»ä¼ÆD®¿é—®æ•£åˆ—çš„åå˜é‡ï¼Œåªæ˜¯ä½¿ç”¨“?”替代“.”åQŒä¸‹é¢åˆ—出常用的一些函æ•?
htmlåQšå¯¹å—符串进行HTML¾~–ç
cap_firståQšä‹Éå—ç¬¦ä¸²ç¬¬ä¸€ä¸ªå—æ¯å¤§å†?
lower_caseåQšå°†å—符串è{æ¢æˆž®å†™
upper_caseåQšå°†å—符串è{æ¢æˆå¤§å†™
trimåQšåŽ»æŽ‰å—½W¦ä¸²å‰åŽçš„空白嗽W?
sizeåQšèŽ·å¾—åºåˆ—ä¸å…ƒç´ 的数ç›?
intåQšå–å¾—æ•°å—的整数部分åQˆå¦‚-1.9?int的结果是-1åQ?
例ååQˆå‡è®¾testä¿å˜å—符ä¸?Tom & Jerry"åQ‰ï¼š(x¨¬)
${test?html}输出¾l“果是:(x¨¬)
${test?upper_case?html}
Tom & Jerry
TOM & JERRY
æ“作½W¦ç»„ | æ“作½W? |
---|---|
åŽç¼€ | [subvarName] [subStringRange] . (methodParams) |
一� | +expr�expr� |
å†…å¾ | ? |
乘法 | *�/ � |
åŠ æ³• | +ã€? |
关系 | <ã€?gt;ã€?lt;=ã€?gt;=åQˆltã€lteã€gtã€gteåQ? |
ç›¸ç‰ | ==åQ?åQ‰ã€?= |
逻辑and | && |
逻辑or | åŒç«–¾U?/td> |
æ•°å—范围 | .. |
Interpolation有两¿U类型:(x¨¬)
注æ„åQšInterpolationåªèƒ½ç”¨äºŽæ–‡æœ¬éƒ¨åˆ†
æ’å…¥å—符串å€û|¼š(x¨¬)直接输出表达å¼ç»“æž?
æ’入数å—å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{æ¢æˆæ–‡æœ¬è¾“出åQ›å¯ä»¥ä‹É用内建函数stringæ ¼å¼åŒ–å•个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#setting number_format="currency"/>输出¾l“果是:(x¨¬)
<#assign answer=42/>
${answer}
${answer?string} <#-- the same as ${answer} -->
${answer?string.number}
${answer?string.currency}
${answer?string.percent}
$42.00æ’入日期å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{æ¢æˆæ–‡æœ¬è¾“出åQ›å¯ä»¥ä‹É用内建函数stringæ ¼å¼åŒ–å•个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä‹Éç”¨æ ¼å¼æ¨¡å¼çš„例ååQ?
$42.00
42
$42.00
4,200%
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}输出的结果类ä¼ég¸‹é¢çš„æ ¼å¼åQ?
${lastUpdated?string("EEE, MMM d, ''yy")}
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}
2003-04-08 21:24:44 Pacific Daylight Timeæ’入布尔å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{æ¢æˆæ–‡æœ¬è¾“出åQ›å¯ä»¥ä‹É用内建函数stringæ ¼å¼åŒ–å•个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
Tue, Apr 8, '03
Tuesday, April 08, 2003, 09:24:44 PM (PDT)
<#assign foo=true/>输出¾l“果是:(x¨¬)
${foo?string("yes", "no")}
yes
mXåQšå°æ•°éƒ¨åˆ†æœ€ž®Xä½?
MXåQšå°æ•°éƒ¨åˆ†æœ€å¤§Xä½?
例ååQ?
<#-- If the language is US English the output is: -->
<#assign x=2.582/>
<#assign y=4/>
#{x; M2} <#-- 2.58 -->
#{y; M2} <#-- 4 -->
#{x; m1} <#-- 2.6 -->
#{y; m1} <#-- 4.0 -->
#{x; m1M2} <#-- 2.58 -->
#{y; m1M2} <#-- 4.0 -->
å®å’Œå˜æ¢å™¨å˜é‡æ˜¯ä¸¤ç§ä¸åŒ¾cÕdž‹çš„ç”¨æˆ·å®šä¹‰æŒ‡ä»¤ï¼Œå®ƒä»¬ä¹‹é—´çš„åŒºåˆ«æ˜¯å®æ˜¯åœ¨æ¨¡æ¿ä¸ä½¿ç”¨macro指ä×o(h¨´)定义åQŒè€Œå˜æ¢å™¨æ˜¯åœ¨æ¨¡æ¿å¤–ç”±½E‹åºå®šä¹‰åQŒè¿™é‡Œåªä»‹ç»å®?
宿˜¯å’ŒæŸä¸ªå˜é‡å…³è”的模æ¿ç‰‡æ–åQŒä»¥ä¾¿åœ¨æ¨¡æ¿ä¸é€šè¿‡ç”¨æˆ·å®šä¹‰æŒ‡ä×o(h¨´)使用该å˜é‡ï¼Œä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#macro greet>ä½œäØ“(f¨´)用户定义指ä×o(h¨´)使用å®å˜é‡æ—¶åQŒä‹É用@替代FTLæ ‡è®°ä¸çš„#
<font size="+2">Hello Joe!</font>
</#macro>
<@greet></@greet>如果没有体内容,也å¯ä»¥ä‹É用:(x¨¬)
<@greet/>
在macro指ä×o(h¨´)ä¸å¯ä»¥åœ¨å®å˜é‡ä¹‹åŽå®šä¹‰å‚敎ͼŒå¦‚:(x¨¬)
<#macro greet person>å¯ä»¥˜q™æ ·ä½¿ç”¨˜q™ä¸ªå®å˜é‡ï¼š(x¨¬)
<font size="+2">Hello ${person}!</font>
</#macro>
<@greet person="Fred"/> and <@greet person="Batman"/>输出¾l“果是:(x¨¬)
<font size="+2">Hello Fred!</font>
and <font size="+2">Hello Batman!</font>
å®çš„傿•°æ˜¯FTL表达å¼ï¼Œæ‰€ä»¥ä¸‹é¢çš„代ç å…ähœ‰ä¸åŒçš„æ„æ€ï¼š(x¨¬)
<@greet person=Fred/>˜q™æ„味瀞®†Fredå˜é‡çš„å€ég¼ ¾l™person傿•°åQŒè¯¥å€ég¸ä»…是å—符ä¸ÔŒ¼Œ˜q˜å¯ä»¥æ˜¯å…¶å®ƒ¾cÕdž‹åQŒç”šè‡Ïx(ch¨®ng)˜¯å¤æ‚的表辑ּ
å¯ä»¥æœ‰å¤šå‚æ•°åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#macro greet person color>å¯ä»¥˜q™æ ·ä½¿ç”¨è¯¥å®å˜é‡åQ?
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
<@greet person="Fred" color="black"/>å…¶ä¸å‚æ•°çš„æ¬¡åºæ˜¯æ— å…³çš„ï¼Œå› æ¤ä¸‹é¢æ˜¯ç‰ä»ïL(f¨¥ng)š„åQ?
<@greet color="black" person="Fred"/>åªèƒ½ä½¿ç”¨åœ¨macro指ä×o(h¨´)ä¸å®šä¹‰çš„傿•°åQŒåÆˆä¸”å¯¹æ‰€æœ‰å‚æ•°èµ‹å€û|¼Œæ‰€ä»¥ä¸‹é¢çš„ä»£ç æ˜¯é”™è¯¯çš„åQ?
<@greet person="Fred" color="black" background="green"/>å¯ä»¥åœ¨å®šä¹‰å‚数时指定¾~ºçœå€û|¼Œå¦‚:(x¨¬)
<@greet person="Fred"/>
<#macro greet person color="black">˜q™æ ·<@greet person="Fred"/>ž®±æ£¼‹®äº†(ji¨£n)
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
å®çš„傿•°æ˜¯å±€éƒ¨å˜é‡ï¼Œåªèƒ½åœ¨å®å®šä¹‰ä¸æœ‰æ•?
用户定义指ä×o(h¨´)å¯ä»¥æœ‰åµŒå¥—内容,使用<#nested>指ä×o(h¨´)执行指ä×o(h¨´)开始和¾l“æŸæ ‡è®°ä¹‹é—´çš„æ¨¡æ¿ç‰‡æ–?
例ååQ?
<#macro border>˜q™æ ·ä½¿ç”¨è¯¥å®å˜é‡åQ?
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
<@border>The bordered text</@border>输出¾l“æžœåQ?
<table border=4 cellspacing=0 cellpadding=4><tr><td>
The bordered text
</tr></td></table>
<#nested>指ä×o(h¨´)å¯ä»¥è¢«å¤š‹Æ¡è°ƒç”¨ï¼Œä¾‹å¦‚åQ?
<#macro do_thrice>输出¾l“æžœåQ?
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>
Anything.嵌套内容å¯ä»¥æ˜¯æœ‰æ•ˆçš„FTLåQŒä¸‹é¢æ˜¯ä¸€ä¸ªæœ‰äº›å¤æ‚的例ååQ?<@border> <ul> <@do_thrice> <li><@greet person="Joe"/> </@do_thrice> </ul> </@border> }}} 输出¾l“æžœåQ?
Anything.
Anything.
<table border=4 cellspacing=0 cellpadding=4><tr><td>å®å®šä¹‰ä¸çš„局部å˜é‡å¯¹åµŒå¥—内容是ä¸å¯è§çš„,例如åQ?
<ul>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
</ul>
</tr></td></table>
<#macro repeat count>输出¾l“æžœåQ?
<#local y = "test">
<#list 1..count as x>
${y} ${count}/${x}: <#nested>
</#list>
</#macro>
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>
test 3/1: ? ? ?
test 3/2: ? ? ?
test 3/3: ? ? ?
用户定义指ä×o(h¨´)å¯ä»¥æœ‰åó@环å˜é‡ï¼Œé€šå¸¸ç”¨äºŽé‡å¤åµŒå¥—内容åQŒåŸºæœ¬ç”¨æ³•是åQšä½œä¸ºnested指ä×o(h¨´)çš„å‚æ•îC¼ 递åó@环å˜é‡çš„实际å€û|¼Œè€Œåœ¨è°ƒç”¨ç”¨æˆ·å®šä¹‰æŒ‡ä×o(h¨´)æ—Óž¼Œåœ?lt;@…>å¼€å§‹æ ‡è®°çš„å‚æ•°åŽé¢æŒ‡å®šå¾ªçޝå˜é‡çš„åå?
例ååQ?
<#macro repeat count>输出¾l“æžœåQ?
<#list 1..count as x>
<#nested x, x/2, x==count>
</#list>
</#macro>
<@repeat count=4 ; c, halfc, last>
${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
1. 0.5
2. 1
3. 1.5
4. 2 Last!
指定的åó@环å˜é‡çš„æ•°ç›®å’Œç”¨æˆ·å®šä¹‰æŒ‡ä»¤å¼€å§‹æ ‡è®°æŒ‡å®šçš„ä¸åŒä¸ä¼š(x¨¬)有问é¢?
调用时少指定循环å˜é‡åQŒåˆ™å¤šæŒ‡å®šçš„å€ég¸å¯è§
调用时多指定循环å˜é‡åQŒå¤šä½™çš„循环å˜é‡ä¸ä¼š(x¨¬)被创å»?
在模æ¿ä¸å®šä¹‰çš„å˜é‡æœ‰ä¸‰ç§¾cÕdž‹åQ?
å®çš„傿•°æ˜¯å±€éƒ¨å˜é‡ï¼Œè€Œä¸æ˜¯åó@环å˜é‡ï¼›å±€éƒ¨å˜é‡éšè—ï¼ˆè€Œä¸æ˜¯è¦†ç›–)(j¨ª)åŒåçš„plainå˜é‡åQ›åó@环å˜é‡éšè—åŒå的局部å˜é‡å’Œplainå˜é‡åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#assign x = "plain">输出¾l“æžœåQ?
1. ${x} <#-- we see the plain var. here -->
<@test/>
6. ${x} <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
7. ${x} <#-- now the loop var. hides the plain var. -->
<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
8. ${x} <#-- it still hides the plain var. -->
</#list>
9. ${x} <#-- the new value of plain var. -->
<#macro test>
2. ${x} <#-- we still see the plain var. here -->
<#local x = "local">
3. ${x} <#-- now the local var. hides it -->
<#list ["loop"] as x>
4. ${x} <#-- now the loop var. hides the local var. -->
</#list>
5. ${x} <#-- now we see the local var. again -->
</#macro>
1. plain
2. plain
3. local
4. loop
5. local
6. plain
7. loop
8. loop
9. plain2
内部循环å˜é‡éšè—åŒå的外部åó@环å˜é‡ï¼Œå¦‚:(x¨¬)
<#list ["loop 1"] as x>输出¾l“æžœåQ?
${x}
<#list ["loop 2"] as x>
${x}
<#list ["loop 3"] as x>
${x}
</#list>
${x}
</#list>
${x}
</#list>
loop 1模æ¿ä¸çš„å˜é‡ä¼?x¨¬)éšè—ï¼ˆè€Œä¸æ˜¯è¦†ç›–)(j¨ª)æ•°æ®æ¨¡åž‹ä¸åŒåå˜é‡ï¼Œå¦‚果需è¦è®¿é—®æ•°æ®æ¨¡åž‹ä¸çš„åŒåå˜é‡ï¼Œä½¿ç”¨ç‰ÒŽ(gu¨©)®Šå˜é‡globalåQŒä¸‹é¢çš„例åå‡è®¾æ•°æ®æ¨¡åž‹ä¸çš„user的值是Big JoeåQ?
loop 2
loop 3
loop 2
loop 1
<#assign user = "Joe Hider">
${user} <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->
通常情况åQŒåªä½¿ç”¨ä¸€ä¸ªåå—空é—ß_(d¨¢)¼Œ¿UîCØ“(f¨´)ä¸Õdå—空é—?
ä¸ÞZº†(ji¨£n)创å¾å¯é‡ç”¨çš„å®ã€å˜æ¢å™¨æˆ–其它å˜é‡çš„集åˆåQˆé€šå¸¸¿U°åº“åQ‰ï¼Œå¿…须使用多åå—空é—ß_(d¨¢)¼Œå…¶ç›®çš„æ˜¯é˜²æ¢åŒå冲çª
䏋颿˜¯ä¸€ä¸ªåˆ›å»ºåº“的例å(å‡è®¾ä¿å˜åœ¨lib/my_test.ftlä¸ï¼‰(j¨ª)åQ?
<#macro copyright date>使用import指ä×o(h¨´)导入库到模æ¿ä¸ï¼ŒFreemarkerä¼?x¨¬)äØ?f¨´)å¯¼å…¥çš„åº“åˆ›å¾æ–°çš„åå—½Iºé—´åQŒåƈå¯ä»¥é€šè¿‡import指ä×o(h¨´)䏿Œ‡å®šçš„æ•£åˆ—å˜é‡è®‰K—®åº“ä¸çš„å˜é‡ï¼š(x¨¬)
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
<#import "/lib/my_test.ftl" as my>输出¾l“æžœåQ?
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.å¯ä»¥çœ‹åˆ°ä¾‹åä¸ä‹É用的两个åŒåå˜é‡òq¶æ²¡æœ‰å†²½Hï¼Œå› äØ“(f¨´)它们ä½äºŽä¸åŒçš„åå—空é—?
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com
å¯ä»¥ä½¿ç”¨assign指ä×o(h¨´)在导入的åå—½Iºé—´ä¸åˆ›å»ºæˆ–替代å˜é‡åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å:(x¨¬)
<#import "/lib/my_test.ftl" as my>输出¾l“æžœåQ?
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}
jsmith@acme.comæ•°æ®æ¨¡åž‹ä¸çš„å˜é‡ä»ÖM½•地方都å¯è§ï¼Œä¹ŸåŒ…括ä¸åŒçš„åå—½Iºé—´åQŒä¸‹é¢æ˜¯ä¿®æ”¹çš„库åQ?
jsmith@other.com
<#macro copyright date>å‡è®¾æ•°æ®æ¨¡åž‹ä¸çš„userå˜é‡çš„值是FredåQŒåˆ™ä¸‹é¢çš„代ç :(x¨¬)
<p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>
<#assign mail = "${user}@acme.com">
<#import "/lib/my_test.ftl" as my>输出¾l“æžœåQ?
<@my.copyright date="1999-2002"/>
${my.mail}
<p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>
Fred@acme.com
补充åQˆé™(r¨´n)æ€æ–¹æ³•的调用åQ‰ï¼š(x¨¬)
æ–ÒŽ(gu¨©)³•1åQ?/strong>
##定义é…置文äšg freemarkerstatic.properties
_Validator=com.longyou.util.Validator
_Functions=com.longyou.util.Functions
_EscapeUtils=com.longyou.util.EscapeUtils
/调用代ç
${_Functions.toUpperCase("Hello")}<br>
${_EscapeUtils.escape("狼的原野")}
æ–ÒŽ(gu¨©)³•2åQ?/strong>
${stack.findValue("@package.ClassName@method")}
补充åQšå¸¸ç”¨è¯æ³?/strong>
EG.一个对象BOOK
1.输出 ${book.name}
½Iºå€¼åˆ¤æ–:(x¨¬)${book.name?if_exists },
${book.name?default(‘xxx’)}//默认值xxx
${ book.name!"xxx"}//默认值xxx
æ—¥æœŸæ ¼å¼åQ?{book.date?string('yyyy-MM-dd')}
æ•°å—æ ¼å¼åQ?{book?string.number}--20
${book?string.currency}--<#-- $20.00 -->
${book?string.percent}�lt;#-- 20% -->
æ’入布尔å€û|¼š(x¨¬)
<#assign foo=ture />
${foo?string("yes","no")} <#-- yes -->
2åQŽé€»è¾‘判æ–
a:
<#if condition>...
<#elseif condition2>...
<#elseif condition3>......
<#else>...
其丽Iºå€¼åˆ¤æ–å¯ä»¥å†™æˆ?lt;#if book.name?? >
b:
<#switch value>
<#case refValue1>
...
<#break>
<#case refValue2>
...
<#break>
...
<#case refValueN>
...
<#break>
<#default>
...
3åQŽåó@环读å?/p>
<#list sequence as item>
...
½Iºå€¼åˆ¤æ–?lt;#if bookList?size = 0>
e.g.
<#list employees as e>
${e_index}. ${e.name}
输出:
1. Readonly
2. Robbin
freemarkerçš„Eclipseæ’äšg