2011-01-16 GWT¤ÇMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á
GWT¤ÇMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á
ÌÀ¤±¤Þ¤·¤Æ¤ª¤á¤Ç¤È¤¦¤´¤¶¤¤¤Þ¤¹¡£ÁêÊѤï¤é¤ºÆÉ¤ß¤Ë¤¯¤¤Ê¸¾Ï¤Ç¤¹¤¬¤è¤í¤·¤¯¤ª´ê¤¤Ãפ·¤Þ¤¹¡£
º£Ç¯¤â¤¢¤Þ¤êµ»ö¤ò½ñ¤«¤Ê¤½¤¦¤Ç¤¹¤¬¡¢´èÄ¥¤ê¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
¤µ¤Æ¤³¤³ºÇ¶á¤Ï¤Ò¤¿¤¹¤éappengine + gwt ¤·¤«¤ä¤Ã¤Æ¤¤¤Ê¤¤¤ï¤±¤Ç¤¹¤¬¡¢
ǯËöÊÕ¤ê¤Ë¤ä¤Ã¤¿GWT ¤ÎMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ë¤Ä¤¤¤Æ½ñ¤¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
Ëè²ó¤Î¤È¤ª¤ê¡¢ËÝÌõǽÎϤ¬Ä㤤¤¿¤á¡¢´Ö°ã¤Ã¤Æ¤¤¤ëÉôʬ¤¬¤¢¤ë¤«¤È»×¤¤¤Þ¤¹¤¬¡¢¸«¼é¤Ã¤Æ¤¤¤¿¤À¤±¤¿¤é¹¬¤¤¤Ç¤¹¡£
¤È¤¤¤¦¤³¤È¤ÇÁ°²óGWT¤ÎActivity + Place ¤Ë¤Ä¤¤¤ÆµºÜ¤·¤Þ¤·¤¿¤¬¡¢º£²ó¤Ï¤½¤ì¤ËGWTÍѤÎDI¥³¥ó¥Æ¥ÊGIN *1 ¤ò´Þ¤á¤Æ¤è¤ê´Êñ¤ËActivity + Place¤ò¼Â¸½¤·¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
GIN¤È¤Ï
GIN¤ÏGWTÍѤ˺îÀ®¤µ¤ì¤¿DI¥³¥ó¥Æ¥Ê*2¤ÇGoogleÀ½¤ÎDI¥³¥ó¥Æ¥Ê Guice¤ò¤â¤È¤ËºîÀ®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
Guice¼«ÂΤÏÀßÄê¥Õ¥¡¥¤¥ë¤Ç¤Ê¤¯Java¤Î¥³¡¼¥É¤ÇÀßÄê¤ò½ñ¤¯DI¥³¥ó¥Æ¥Ê¤È¤·¤Æ¡¢appengine¤Ç¤âÍøÍѤǤ¤ë¤Ê¤É*3
¸Ä¿ÍŪ¤Ë¤Ï¤«¤Ê¤ê¹¥¤¤ÊDI¥³¥ó¥Æ¥Ê¤Ç¤¹¡£
ÍøÍÑÊýË¡¤â¤Û¤Ü¤Û¤ÜGuice¤ÈƱ¤¸¤Ç¤¹¤¬¡¢AOP¤¬È󥵥ݡ¼¥È¤Ê¤ÉGWTÆÃͤÎÊʤ¬¤¢¤Ã¤¿¤ê¤·¤Þ¤¹¡£
ºÙ¤«¤Ê»È¤¤Êý¤Ê¤É¤Ê¤É¤Ï¸ø¼°¥µ¥¤¥È¤ä¥°¥°¥Ã¤Æ¤¯¤À¤µ¤¤¡£
¥Æ¥ó¥·¥ç¥óŪ¤Ë³Æ¸µµ¤¤¬¤¢¤Ã¤¿¤é¤¤¤Ä¤«Â¿Ê¬½ñ¤¤Þ¤¹¡£¡£¡£
¤Ã¤Æ¤³¤È¤Ç¼ÂÁõ¡ª¡ª
º£²ó¤Ï¾åµ¤ÎGIN¤òÍøÍѤ·¤Æ¡¢Activity + Place¤ò³Ú¤Ë¤·¤Æ¤ß¤Þ¤¹¡£ ¤Á¤Ê¤ß¤Ë»²¹Í¤Ë¤·¤¿¤Î¤ÏGWT¤ÎML¤Ç¤¹(¤³¤³)¡£
¤Ê¤ªº£²ó¤Îµ»ö¤ÏGWT2.1¤ÎMVP¤¬Ê¬¤«¤Ã¤Æ¤¤¤ëÁ°Äó¤Ç½ñ¤¯¤Î¤Ç¤¢¤·¤«¤é¤º¡£
¤ï¤«¤é¤Ê¤¤Êý¤ÏÁ°²ó¤Îµ»ö¤òÆÉ¤à¤³¤È¤ò¤ª¤¹¤¹¤á¤·¤Þ¤¹¡£
¤Þ¤º¤ÏDI¤ÎÀßÄê Module¥¯¥é¥¹
¤Þ¤º¤ÏDI¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£Guice¤Ç¤ÏÁ°½Ò¤Î¤È¤ª¤ê¡¢Java¤ÇÀßÄê¤ò½ñ¤¤Þ¤¹¡ÊModule¥¯¥é¥¹¤È¤¤¤¤¤Þ¤¹¡Ë¡£GIN¤Ç¤âƱÍͤËAbstractGinModule¤ò·Ñ¾µ¤·¤¿¡¢¥¯¥é¥¹¤ËÀßÄê¤òµºÜ¤·¤Æ¤¤Þ¤¹¡£
¤¹¤Ù¤Æ¤ÎÀßÄê¤ò1¥¯¥é¥¹¤Ëµ½Ò¤·¤Æ¤·¤Þ¤¦¤È´ÉÍý¤¬¤á¤ó¤É¤¯¤µ¤¤¤Î¤Ç
Guice(GIN)¤Ç¤Ï¤³¤ÎModule¥¯¥é¥¹¤òʬ¤±¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
¤Ê¤Î¤ÇMVP¤ÎÀßÄê¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Þ¤¹¡£
package stk.client.inject; ¢¨import public class MvpModule extends AbstractGinModule { @Override protected void configure() { } @Provides @Singleton public EventBus eventBus() { return new SimpleEventBus(); } @Provides @Singleton @Named("contents") public SimplePanel contentsPanel() { SimplePanel simplePanel = new SimplePanel(); simplePanel.addStyleName(Resources.INSTANCE.site().contentsPanel()); return simplePanel; } @Provides @Singleton public PlaceController placeController(EventBus eventBus) { return new PlaceController(eventBus); } @Provides @Singleton public ActivityMapper activityMapper() { return new AppActivityMapper(); } @Provides @Singleton public ActivityManager activityManager( ActivityMapper mapper,EventBus eventBus,@Named("contents") SimplePanel contentsPanel) { ActivityManager activityManager = new ActivityManager(mapper, eventBus); activityManager.setDisplay(contentsPanel); return activityManager; } @Provides @Singleton public PlaceHistoryHandler placeHistoryHandler( AppPlaceHistoryMapper mapper,PlaceController placeController,EventBus eventBus,TopPlace defaultPlace,MyInjector injector) { mapper.setFactory(injector); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(mapper); historyHandler.register(placeController,eventBus,defaultPlace); return historyHandler; } }
º£²ó¤ÎMvpModule¥¯¥é¥¹¤Ç¤Ï@Provides¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ·¤¿ÊýË¡¤ÇÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¤³¤ÎÊýË¡¤Ï¤¢¤ëDI¤ÎÀßÄê¤ò¹Ô¤¤¤¿¤¤¥¯¥é¥¹¤Ë½é´ü²½½èÍý¤òÆþ¤ì¤¿¤¤¾ì¹ç¤Ê¤É¤ËÈó¾ï¤ËÊØÍø¤Ç¤¹¡£
¤½¤ì¤Ç¤Ï³Æ¥á¥½¥Ã¥É¤Ë¤Ä¤¤¤Æ¤ß¤Æ¤¤¤¤Þ¤¹¡£
configure¥á¥½¥Ã¥É
configure¥á¥½¥Ã¥É¤ÏDI¤ÎÀßÄê¤ò³Æ¥á¥½¥Ã¥É¤Ç¤¹¡£Ä̾ï¤Ï¤³¤³¤Ë¤É¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ë¤É¤Î¥¯¥é¥¹¤òDI¤µ¤»¤ë¤«¤Ê¤É¤òµºÜ¤·¤Æ¤¤¤¤Þ¤¹¡£
¤Þ¤¿¸åµ¤·¤Þ¤¹¤¬¡¢Â¾¤ÎModuleÆÉ¤ß¹þ¤ß¤âconfigure¥á¥½¥Ã¥ÉÆâ¤ÇµºÜ¤·¤Þ¤¹¡£
¤¿¤È¤¨¤Ð¤³¤Î¥¯¥é¥¹Æâ¤ÎeventBus¥á¥½¥Ã¥É¤òconfigure¥á¥½¥Ã¥ÉÆâ¤ÇƱ¤¸ÀßÄê¤ÇµºÜ¤¹¤ë¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
@Override protected void configure() { bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class); }
¤³¤Î¤è¤¦¤ËModule¥¯¥é¥¹¤Ç¤Ï¤¤¤í¤¤¤í¤ÊÀßÄê¤Î½ñ¤Êý¤¬¤¢¤ê¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ëº£²ó¤ï¤¶¤ï¤¶eventBus¥á¥½¥Ã¥É¤ËÀÚ¤ê½Ð¤·¤Æ¤¤¤ë¤Î¤Ï¤Ê¤ó¤È¤Ê¤¯¡Ê¤È¤¤¤¦¤è¤ê²£Ê¤Ӵ¶¡Ë¤Ê¤Î¤Çµ¤¤Ë¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤¡£
¤Þ¤¿Guice¤òÍøÍѤ·¤¿¤³¤È¤¬¤¢¤ëÊý¸þ¤±¤Ç¤¹¤¬¡¢GIN¤Ç¤Ïbind().toInstance()¤¬¤Ê¤¤¤Î¤Ç¡¢toInstance¤òÍøÍѤ¹¤ë¤è¤¦¤Ê¥±¡¼¥¹¤â@Provided¤ÇµºÜ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
eventBus¥á¥½¥Ã¥É
eventBus¥á¥½¥Ã¥É¤Ï¡¢Activity + Place¤ÇÍøÍѤ¹¤ëEventBus¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
@Singleton¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òµ½Ò¤¹¤ë¤³¤È¤Ç¡¢EventBus¤òSingleton¤È¤·¤ÆÀßÄê¤Ç¤¤Þ¤¹¡£
¤Þ¤¿@Provides¥á¥½¥Ã¥É¤òModuleÆâ¤Çµ½Ò¤¹¤ë¤³¤È¤Ë¤è¤ê¾¤Î¥¯¥é¥¹¤ÇDI¤Ç¤¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
contentsPanel¥á¥½¥Ã¥É
contentsPanel¥á¥½¥Ã¥É¤Ç¤ÏView¤òÁÞÆþ¤¹¤ë¤¿¤á¤ÎSimplePanel¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
@Named¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ò»ØÄꤹ¤ë¤³¤È¤Ë¤è¤ê"̾Á°ÉÕ"¤ò¹Ô¤¤¡¢¸åµ¤ÎactivityManager¤Î¤è¤¦¤Ë
DI¤ò¹Ô¤¦ºÝ¡¢Æ±ÍͤΥ¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ¹¤ë¤³¤È¤Ç¡¢
¤³¤Î̾Á°¤ÎÉÕ¤¤¤¿SimplePanel(¤Ä¤Þ¤ê¤³¤³¤ÇºîÀ®¤µ¤ì¤Æ¤¤¤ë¥¤¥ó¥¹¥¿¥ó¥¹¡Ë¤òÍøÍѽÐÍè¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
placeController¥á¥½¥Ã¥É¡¢activityMapper¥á¥½¥Ã¥É
eventBus¤ÈƱ¤¸¤Ç¤¹¡£placeController¤Ç¤ÏEventBus¤òModuleÆâ¤Ç¥á¥½¥Ã¥É¥¤¥ó¥¸¥§¥¯¥·¥ç¥ó¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢
eventBus¥á¥½¥Ã¥É¤ÇºîÀ®¤·¤¿EventBus¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹¡£
activityManager¥á¥½¥Ã¥É
activityManager¥á¥½¥Ã¥É¤Ç¤Ï¡¢°ú¿ô¤Ë@Named("contents")¤òÀßÄꤹ¤ë¤³¤È¤Ç¡¢contentsPanel¥á¥½¥Ã¥É¤ÇºîÀ®¤·¤¿SimplePanel¤òDI¤µ¤»¡¢acitivityManger¤ËÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤êPlace¤¬Êѹ¹¤µ¤ìActivity¤¬¸Æ¤Ó½Ð¤µ¤ì¤ëºÝ¤Ë¤³¤ÎcontentsPanel¤¬ÍøÍѤµ¤ì¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
placeHistoryHandler¥á¥½¥Ã¥É
placeHistoryHandler¤Ç¤Ï¡¢¤Ä¤¤¤Ç¤ËAppPlaceHistoryMapper¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
AppPlaceHistoryMapper¤Ë´Ø¤·¤Æ¤Ï¸å¤Û¤ÉºÙ¤«¤¯½ñ¤¤Þ¤¹¤¬¡¢Place¤ÎFactory¤È¤·¤ÆInjector¤ò»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤Þ¤¿¥Ç¥Õ¥©¥ë¥È¡Ê½é´ü²èÌÌɽ¼¨¤Ê¤É¡ËÍѤÎTopPlace¤Ê¤É¤ÎÀßÄê¤â¤³¤³¤Ç¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
MvpModule¤ÎÆÉ¤ß¹þ¤ß MyModule
¼¡¤Ë¾åµ¤ÇºîÀ®¤·¤¿¡¢MvpModule¤òÆÉ¤ß¹þ¤ß¤¹¤ë¿Æ¤ÎModule¤òºîÀ®¤·¤Þ¤¹¡£
package stk.client.inject; ~ import public class MyModule extends AbstractGinModule { @Override protected void configure() { install(new MvpModule()); //bind displays bind(TopDisplay.class).to(TopView.class).in(Singleton.class); } @Provides @Singleton public LoginInfo loginInfo(){ return new LoginInfo(); } } <|| ><p>configure¥á¥½¥Ã¥É¤Ë¤Æinstall¥á¥½¥Ã¥É¤òÍøÍѤ·¡¢MvpModule¤òÆÉ¤ß¹þ¤ó¤Ç¤¤¤Þ¤¹¡£<br> ¤Þ¤¿MyModule¤Ç¤Ï¥í¥°¥¤¥ó¾ðÊó¤òÊÝ»ý¤¹¤ë¤¿¤á¤ÎLoginInfo¤ÎÀßÄê¤â¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£<br> ¥í¥°¥¤¥ó¾ðÊó¤ò@Singleton¤ÇÀë¸À¤·¤Æ¤¤¤ë¤ÈÉԻ׵Ĥ˴¶¤¸¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¤¬¡¢<br> GWT¤Ç¤¤¤¦Singleton¤Ï³Æ¥¯¥é¥¤¥¢¥ó¥È¤´¤È¤ÎSingleton¤Î°ÙÌäÂꤢ¤ê¤Þ¤»¤ó¡£</p>< ** Injector¤ÈModule¤ÎɳÉÕ¤± ><p>Injector¤ÏGIN¤ÇÀßÄꤷ¤¿³Æ¥¤¥ó¥¹¥¿¥ó¥¹¤ò¼èÆÀ¤¹¤ë¤¿¤á¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ç¤¹¡£<br> »ä¤Î´¶³Ð¤Ç¤¹¤¬¡¢Seasar¤Ç¸À¤¦¤È¤³¤í¤ÎS2SingletonContainer¤ß¤¿¤¤¤Ê¤â¤Î¤Ç¤¹¤¬¡¢<br> Ä̾ï¤ÎDI¥³¥ó¥Æ¥Ê¤È°Û¤Ê¤ê¡¢Injector¤«¤é¥¤¥ó¥¹¥¿¥ó¥¹¤ò¼èÆÀ¤¹¤ë¤¿¤á¤Ë¤Ï<br> Injector¤Ë¥á¥½¥Ã¥É¤òÄêµÁ¤·¤Æ¤¤¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£<br> Gin¤Ç¤Ï¤³¤ÎInjector¤òºîÀ®¤¹¤ë¤Ë¤Ï¡¢GinInjector¤ò·Ñ¾µ¤·¤¿¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òºîÀ®¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£</p>< >|java| package stk.client.inject; ~ import @GinModules(MyModule.class) public interface MyInjector extends Ginjector { LoginInfo getLoginInfo(); PlaceController getPlaceController(); ActivityManager getActivityManager(); EventBus getEventBus(); GwtAuthServiceAsync getAuthService(); TopPlace getTopPlace(); TopPlace.Tokenizer getTopTokenizer(); PlaceHistoryHandler getHistoryHandler(); MainView getMainView(); @Named("contents") SimplePanel getContentsPanel(); TopDisplay getTopDisplay(); }
@GinModules¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ·¤Æ¡¢¾åµ¤ÎMyModule¤ÈInjector¤òɳÉÕ¤±¤Æ¤¤¤Þ¤¹¡£
InjectorÆâ¤Ç¤Ï¡¢³ÆÍøÍѤ¹¤ë¥¯¥é¥¹¤ÎGetter¤òµ½Ò¤·¡¢¤¢¤È¤¢¤ÈÍøÍѽÐÍè¤ë¤è¤¦¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤ÇGIN¦¤ÎÀßÄê¤Ï´°Î»¤Ç¤¹¡£¤³¤ó¤É¤ÏMVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ò¤è¤ê´Êñ¤Ë¤¹¤ë¤¿¤á¤Ë¡¢Place¥¯¥é¥¹¤Ê¤É¤òºîÀ®¤·¤Þ¤¹¡£
Activity¤ÈPlace¤òɳÉÕ¤±¤¹¤ëActivityPlace¤ÎºîÀ®
Á°²ó½ñ¤¤¤¿MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ç¤Ï¡¢AppActivityMapper¤Ë¤Æinstanceof¤òÍøÍѤ¹¤ë¤³¤È¤Ë¤è¤ê¡¢
Place¤ÈActivity¤Î´ØÏ¢ÉÕ¤±¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤·¤¿¡£
º£²ó¤ÏPlace¤ÈActivity¤ò»öÁ°¤Ë¤Ò¤â¤Å¤±¤ë¤³¤È¤Ë¤è¤êinstanceof¤ò¤Û¤È¤ó¤ÉÍøÍѤ»¤º¡¢
AppActivityMapper¤òµ½Ò¤Ç¤¤ë¤è¤¦¤Ë¤·¤Þ¤¹¡£
¤½¤Î¤¿¤á¤Ë¤ÏPlace¥¯¥é¥¹¤ò³ÈÄ¥¤·¤¿Ãê¾Ý¥¯¥é¥¹¡¢ActivityPlace¥¯¥é¥¹¤òºîÀ®¤·¤Þ¤¹¡£
package stk.client.framework; ~ import public abstract class ActivityPlace<T extends Activity> extends Place { @Inject Provider<T> provider; protected String token = ""; public void init(String token){ this.token = token; } public String getToken(){ return this.token; } public T getActivity(){ return provider.get(); } abstract public static class Tokenizer<E extends ActivityPlace<?>> implements PlaceTokenizer<E>{ @Inject Provider<E> provider; @Override public E getPlace(String token) { E place = provider.get(); place.init(token); return place; } @Override public String getToken(E place) { return place.getToken(); } } }
¤Þ¤ºActivityPlace¥¯¥é¥¹¤Ç¤Ï¡¢Generics¤òÍøÍѤ·Place¤ÈActivity¤òɳÉÕ¤±¤Æ¤¤¤Þ¤¹¡£
provider¥Õ¥£¡¼¥ë¥É¤Ë@Inject»ØÄꤷ¡¢Provider¥¯¥é¥¹¤ò¥Õ¥£¡¼¥ë¥É¥¤¥ó¥¸¥§¥¯¥·¥ç¥ó¤·¤Æ¤¤¤Þ¤¹¡£
Provider¥¯¥é¥¹¤Ï¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤¿¤á¤Î¥¯¥é¥¹¤Ç¡¢provider.get()¥á¥½¥Ã¥É¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤ê¡¢
Generics¤Ë¤è¤ê»ØÄꤵ¤ì¤¿¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
º£²ó¤ÏActivity¤ò·Ñ¾µ¤·¤¿T¡ÊT¤ÏActivityPlace¤ò·Ñ¾µ¤·¤¿¥¯¥é¥¹¤ÇǤ°Õ¤ËÀßÄꤷ¤Þ¤¹¡£¡Ë¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
getActivity()¥á¥½¥Ã¥É¤Ç¤Ï¤³¤Îprovider¤òÍøÍѤ·¡¢T¤òÀ¸À®¡¦ÊֵѤ¹¤ë¤³¤È¤Ç¡¢Place¤«¤éActivity¤ÎÀ¸À®¤ò²Äǽ¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
ActivityPlaceÆâ¤ÇÀë¸À¤µ¤ì¤¿¡¢Tokenizer¤Ç¤Ï¤³¤ÎActivityPlace¤ÎÀ¸À®¤ò¹Ô¤¤¤Þ¤¹¡£
Á°½Ò¤ÎMyInjectorÆâ¤Ë¤Æ¸Æ¤Ó½Ð¤·¥á¥½¥Ã¥É¡ÊÎ㤨¤ÐgetTopPlaceTokenizer)¤òºîÀ®¤·¡¢
AppPlaceHistoryMapper¤Ë¤ÆMyInjectorÆâ¤ÎTokenizerºîÀ®¥á¥½¥Ã¥É¤ò¸Æ¤Ö¤³¤È¤Ç¡¢
Tokenizer¤¬ºîÀ®¡¢¤µ¤é¤Ë¤ÏTokenizer¤«¤é¤³¤ÎActivityPlace¤¬ºîÀ®¤µ¤ì¤Þ¤¹¡£
Î㤨¤Ð²¼µ¤Î¤è¤¦¤ÊActivityPlace¤ò·Ñ¾µ¤·¤¿¡¢¥¯¥é¥¹¤òºîÀ®¤·¤Þ¤¹¡£
package stk.client.place; ~ import public class TopPlace extends ActivityPlace<TopActivity> { @Override public String getToken() { return ""; } @Override public void init(String token) { } @Prefix("!top") public static class Tokenizer extends ActivityPlace.Tokenizer<TopPlace> implements PlaceTokenizer<TopPlace> {} }
Place¤«¤éActivity¤ÎºîÀ®¤ò¹Ô¤¦
º£ÅÙ¤ÏPlace¤«¤éActivity¤ÎºîÀ®¤ò¹Ô¤¦ActivityMapper¤ÎºîÀ®¤ò¤·¤Þ¤¹¡£
package stk.client.framework; ~ import public class AppActivityMapper implements ActivityMapper { @Inject public AppActivityMapper() { super(); } @Override public Activity getActivity(Place place) { if (!(place instanceof ActivityPlace<?>)) { return null; } ActivityPlace<?> activityPlace = (ActivityPlace<?>)place; return activityPlace.getActivity(); } }
¤É¤ª¤Ç¤·¤ç¤¦¤«¡¢Á°²ó¤ÎAppActivityMapper¤Ë¤¯¤é¤Ùinstanceof¤Îµ½Ò¤¬¤Û¤Ü¤Ê¤¯¤Ê¤ê¡¢
Èó¾ï¤Ë¤¹¤Ã¤¤ê¤·¤¿¤Î¤Ç¤Ï¤Ê¤¤¤Ç¤·¤ç¤¦¤«¡©
Á°²ó¤ÎAppActivityMapper¤Ç¤ÏPlace¤¬Áý¤¨¤ë¤¿¤Ó¤ËAppActivityMapper¤ò½ñ¤´¹¤¨¤ëɬÍפ¬¤¢¤ê¤Þ¤·¤¿¤¬¡¢
GIN¤òÍøÍѤ·¤¿¤³¤È¤Ë¤è¤ê¡¢¤½¤Î°Í¸¤¬¾Ã¤¨AppActivityMapper¤òÊѹ¹¤¹¤ëɬÍפ¬¤Ê¡¡¤¯¤Ê¤ê¤Þ¤·¤¿¡£
¼¡¤ËHistory Token ¤È Place¤ÎɳÉÕ¤±¤ò¹Ô¤¦¡¢AppPlaceHistoryMapper
Á°²ó¤ÎAppPlaceHistoryMapper¤Ç¤Ï@WithTokenizers¤òÍøÍѤ¹¤ë¤³¤È¤Ë¤è¤ê¡¢History Token¤ÈTokenizer¤ÎɳÉÕ¤±¤ò»ØÄꤷ¤Æ¤¤¤Þ¤·¤¿¡£
º£²ó¤ÏTokenizer¤¬GIN¤Ë¤è¤êºîÀ®¤µ¤ì¤ëɬÍפ¬¤¢¤ë¤¿¤á¡¢WithTokenizers¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤǤ¤Þ¤»¤ó¡£
¤½¤Î¤¿¤á¡¢Á°²óAppPlaceHistoryMapper¤òºîÀ®¤¹¤ë¤¿¤á¤Ë·Ñ¾µ¤·¤¿¡¢PlaceHistoryMapper¤òÍøÍѤ¹¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢
Tokenizer¤ÎFactory¤ò»ØÄê¤Ç¤¤ë¡¢PlaceHistoryMapperWithFactory¤ò·Ñ¾µ¤·¤Þ¤¹¡£
package stk.client.framework; ~ import public interface AppPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyInjector> { }
PlaceHistoryMapperWithFacotry¤Îgenerics¤È¤·¤Æ¡¢MyInjector¤ò»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤êGWT 2.1¤ÎMVP¥Õ¥ì¡¼¥ï¡¼¥¯¤¬Factory¤È¤·¤Æ»ØÄꤵ¤ì¤¿MyInjector¤è¤ê¡¢
PlaceTokenizer¤ò·Ñ¾µ¤·¤¿¥¯¥é¥¹¤òÊֵѤ¹¤ë¥á¥½¥Ã¥É¤òõ¤·½Ð¤·¡¢Tokenizer¤òÀ¸À®¤¹¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
;Ã̤Ǥ¹¤¬¡¢¤³¤Îgenerics¤Ë¤·¤Æ¤¹¤ëFacotry¤ÏÆÃ¤Ë»ØÄꤵ¤ì¤¿¥¯¥é¥¹¤ò·Ñ¾µ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤»¤ó¡£
PlaceHistoryMapperWithFactory¤Ë¤Ï¤³¤ÎFactory¤ÎGetter¤â¤Ê¤¤¤¿¤á¡¢¤â¤Î¤¹¤´¤¯ÉԻ׵Ĥʴ¶¤¸¤¬¤·¤Þ¤¹¡£¡£¡£
ºÙ¤«¤Ê»ÅÁȤߤϤ³¤³¤Ç¤Ï½ñ¤¤Þ¤»¤ó¤¬¡¢¤³¤Î¤Ø¤ó¤¬GWT¤ÎÎ¥¤ì¶È¤Ê¤ó¤Ç¤·¤ç¤¦¤Í¡£
¤¢¤È¤ÏŬÅö¤ËActivity¤ÈPlace¤òºîÀ®
¤¢¤È¤Ï¼ÂºÝ¤ËÍøÍѤ¹¤ë¡¢Activity¤ÈPlace¤òºîÀ®¤·¤Þ¤¹¡£
package stk.client.presenter; ~ import public class TopActivity extends AbstractActivity { private final MyInjector injector; @Inject public TopActivity(MyInjector injector){ this.injector = injector; } @Override public void start(AcceptsOneWidget panel, EventBus eventBus) { TopDisplay topDisplay = injector.getTopDisplay(); panel.setWidget(topDisplay); } }
package stk.client.place; ~ import public class TopPlace extends ActivityPlace<TopActivity> { @Override public String getToken() { return ""; } @Override public void init(String token) { } @Prefix("!top") public static class Tokenizer extends ActivityPlace.Tokenizer<TopPlace> implements PlaceTokenizer<TopPlace> {} }
¤ÇºÇ¸å¤Ë¸Æ¤Ó½Ð¤·
¤µ¤¤¤´¤Ë¤³¤ì¤é¤Î¥¯¥é¥¹¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤¤¤Þ¤¹¡£
¤Þ¤ºgwt.xml¤Ë¤ÆGIN¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤¤¤Þ¤¹¡£
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.3//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.3/distro-source/core/src/gwt-module.dtd"> <module> <inherits name="com.google.gwt.user.User" /> <inherits name='com.google.gwt.user.theme.standard.Standard' /> <inherits name='org.slim3.gwt.emul.S3Emulation' /> <inherits name="com.google.gwt.activity.Activity"/> <inherits name="com.google.gwt.inject.Inject"/> <inherits name="com.google.gwt.logging.Logging" /> <inherits name="com.google.common.collect.Collect"/> <set-property name="gwt.logging.popupHandler" value="DISABLED"/> <script src="/js/jquery-1.4.2.min.js"/> <script src="/js/jquery-ui-1.8.1.custom.min.js"/> <source path="client"> <exclude name="**/*Test.java"/> </source> <source path="shared"> <exclude name="**/*Test.java"/> </source> <entry-point class="stk.client.Index"></entry-point> </module>
¤Á¤Ê¤ß¤Ëcom.google.gwt.inject.Inject¤¬GIN¤ÎÀßÄêÉôʬ¤Ç¤¹¡£
¼¡¤ËGWT¤Î¥â¥¸¥å¡¼¥ë¥¯¥é¥¹¤òµ½Ò¤·¤Þ¤¹¡£
package stk.client; ~ import public class Index implements EntryPoint { Logger logger = Logger.getLogger(Index.class.getName()); @Override public void onModuleLoad() { final MyInjector injector = GWT.create(MyInjector.class); injector.getActivityManager(); Resources.INSTANCE.site().ensureInjected(); injector.getAuthService().loginAuth(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() { @Override public void onSuccess(LoginInfo result) { LoginInfo loginInfo = injector.getLoginInfo(); loginInfo.email = result.email; loginInfo.loggedIn = result.loggedIn; loginInfo.logoutUrl = result.logoutUrl; loginInfo.nickName = result.nickName; loginInfo.loginUrl = result.loginUrl; RootPanel.get("msg").setVisible(false); RootPanel.get("contents").add(injector.getContentsPanel()); injector.getHistoryHandler().handleCurrentHistory(); } @Override public void onFailure(Throwable caught) { } }); } }
º£²ó¤ÎÎã¤Ç¤Ï¥í¥°¥¤¥ó½èÍý¤È¤«¤âÆþ¤Ã¤Æ¤¤¤Þ¤¹¤¬¡¢ÃíÌܤ·¤Æ¤¤¤¿¤À¤¤¿¤¤¤Î¤Ï¡¢
ºÇ½é¤ËGWT.create¤ÇMyInjector¤òÀ¸À®¤·¤Æ¤¤¤ëÉôʬ¤Ç¤¹¡£
¤³¤ì¤Ë¤è¤êMyInjector¤¬½é´ü²½¤µ¤ìMyModule¤Ê¤É¤¬¸Æ¤Ó½Ð¤µ¤ì¡¢¤¹¤Ù¤Æ¤ÎDIÀßÄ꤬¹Ô¤ï¤ì¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ëinjector.getActivityManager();¤ò¼¡¤Ë¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¤Î¤Ï¡¢@Singleton¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤Ç¤Ï¡¢
½é´üºîÀ®¤Ç¤Ï¤Ê¤¯¸Æ¤Ó½Ð¤·»þ¤Ë½é¤á¤ÆSingleton¥¤¥ó¥¹¥¿¥ó¥¹¤¬ºîÀ®¤µ¤ì¤ë¤¿¤á¡¢°ìÅٸƤӽФ·¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¿ʬ¤â¤Ã¤È¥¹¥Þ¡¼¥È¤Ë¤Ç¤¤ëµ¤¤¬¤·¤Þ¤¹¤¬¡£¡£¡£
¤Þ¤¿RootPanel.get("contents").add(injector.getContentsPanel());¤ÇRootPanel¤Ë¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ÇÍøÍѤ¹¤ë
ContentsPanel(@Named("contents")¤ò»ØÄꤷ¤¿SimplePanel)¤òÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤Þ¤È¤á
Èó¾ï¤Ë¥¯¥é¥¹¿ô¤¬Â¿¤¤¤¿¤á¡¢¤á¤ó¤É¤¯¤µ¤¯´¶¤¸¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¤¬¡¢°ìÅÙºî¤Ã¤Æ¤·¤Þ¤¨¤Ð¡¢
Á°²ó¤Îµ»ö¤ËÈæ¤Ù¤Û¤È¤ó¤ÉÊѹ¹¤ÏÍפé¤Ê¤¯¤Ê¤ê¤Þ¤¹¡£
²èÌ̤òÁý¤ä¤¹¾ì¹ç¤ÏPlace¤ÈActivity¤òºîÀ®¤·injector¤ËTokenizer¥á¥½¥Ã¥É¤òÁý¤ä¤¹¤À¤±¤Ç¤è¤¯¤Ê¤ê¤Þ¤¹¡£
¼ÂºÝ¤ËMVP + GIN¤ò»È¤Ã¤Æ¤¤¤ë¥µ¥¤¥È¤È¤·¤Æ¡¢
»ä¤¬¥³¥ß¥Ã¥¿¡¼¤ò¤ä¤é¤µ¤»¤Æ¤¤¤¿¤À¤¤¤Æ¤¤¤ë¡¢id:coolstyle ¤µ¤ó(@yusuke_kokubo)¤Îskillmaps¤¬¤¢¤ê¤Þ¤¹¡£
¥½¡¼¥¹¥³¡¼¥É¤âgithub¤Ç¸ø³«¤µ¤ì¤Æ¤¤¤Þ¤¹¤Î¤Ç*4¡¢À§Èó¤´Í÷¤Ë¤Ê¤Ã¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£
¼¡²óͽ¹ð
¼¡²ó¤Ï¡¢MVP¤ÎÏäǤʤ¯¤Æ¡¢GWT 2.1¤ÇÄɲ䵤줿CellView¤¢¤¿¤ê¤ÎÏäò½ñ¤³¤¦¤«¤È»×¤¤¤Þ¤¹¡£¤¿¤Ö¤ó¤¤¤Ä¤«
¤¢¤È¤Ï¡¢MVP + GWT¤Ç¤ÎGWT.runAsync¤Î¤¦¤Þ¤¤¤ä¤ê¤«¤¿¤ò½ñ¤³¤¦¤«¤È ¤¿¤Ö¤ó¤¤¤Ä¤«
ÄÉ¿
ʸ¾Ï¤¬¥Ø¥¿¥¯¥½¤Ç¿½¤·Ìõ¤´¤¶¤¤¤Þ¤»¤ó¡£¡£¡£*1¡§GIN http://code.google.com/p/google-gin/
*2¡§¥³¥ó¥Æ¥Ê¤Ã¤Æ¸À¤Ã¤Æ¤¤¤¤¤Î¤«Èù̯¤Ç¤¹¤¬
*3¡§¤Ã¤È¤¤¤Ã¤Æ¤âspin upŪ¤Ë¤Á¤ç¤¤¤È¿É¤¤¤Ç¤¹¤¬¡£¡£¡£
2010-10-13
GWT¤ÇMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î2(History¤âAppController¤â¤µ¤è¤¦¤Ê¤é¡Ë
GWT | |
![]()
¤Á¤ç¤¦¤ÉºòÆü´èÄ¥¤Ã¤ÆHisotry¤ÈEventBus¡¢AppController¤ÎÏäò½ñ¤¤¤¿¤Î¤Ë
º£Æüµ¤¤¬¤Ä¤¤¤¿¤éGWT2.1.0-RC1¤¬Íè¤Æ¤¤¤Æ¡¢AppController¤âHistory¤âEventBus¤â¤¤¤é¤Ê¤¯¤Ê¤Ã¤¿¤è
޵ŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿
¤Ï¤¤¡¢°ÕÌ£¥Ê¥Ã¥·¥ó¥°¤Ç¤¹¡£
¤Ç¤â¤¤¤é¤Ê¤¯¤Ê¤Ã¤¿¤Î¤ÏɬÍפʤ¯¤Ê¤Ã¤¿¤Î¤Ç¤Ï¤Ê¤¯¡¢ºî¤é¤Ê¤¯¤Æ¤è¤¯¤Ê¤Ã¤¿¤À¤±¤Ê¤Î¤Ç¡¢
ºòÆü½Ð¤ÆÂ®¹¶¤ÇGWT2.1.0-RC1ÈÇMVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯Âбþ¤ò¹Ô¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
¤À¤Ã¤ÆÃˤλҤÀ¤â¤ó
¤Æ¤³¤È¤ÇºòÆü¤ÈƱ¤¸´¶¤¸¤ÇÁ°Ä󤫤é
»ä¤Ï±Ñ¸ìÎϤâÆüËܸìÎϤâ¤Ê¤¤¤Î¤Ç¡¢
¤ï¤«¤ê¤Ë¤¯¤¤¡¢²ò¼á¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¸Ä½ê¤Ï¿ʬ¤Ë¤¢¤ë¤«¤È»×¤¤¤Þ¤¹¡£
¤½¤¦¤¤¤Ã¤¿¾ì¹ç¤Ï¤ä¤µ¤·¤¯¸«¼é¤Ã¤Æ¤¯¤À¤µ¤¤¡£
º£²óMVP Framework¤òºî¤ë¾å¤Ç»²¹Í¤Ë¤·¤¿¤Î¤ÏGWT¤Î¸ø¼°¥µ¥¤¥È¤Ç¤¹¡£
Google¤µ¤óº£²ó¤ÏÈó¾ï¤Ëʬ¤«¤ê¤ä¤¹¤«¤Ã¤¿¤Ç¤¹¡£
¥µ¥ó¥×¥ë¤Î¥½¡¼¥¹¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¸Ä½ê¤¬¾¯¡¹¤¢¤ê¤Þ¤·¤¿¤¬¡£¡£¡£
¤ÇÃæ¿È¤Ï¤Û¤Ü¼Ì·Ð¤·¤Þ¤·¤¿¡Ê¤á¤ó¤É¤¤¤È¤³¤í¤Ï¥³¥Ô¥Ú¤·¤Þ¤·¤¿¡Ë¡£
¥³¡¼¥É¤Ï¤³¤Á¤é¤Ç¤¹¡£
Á´ÂÎÁü¤Ê¤É¤Ê¤É
ºòÆü¤Îµ»ö¤ò¸«¤Æ²¼¤µ¤¤¡£
¤â¤¦°ì²ó½ñ¤¯¤È¢¤Î¤è¤¦¤Ê²èÌÌÁ«°Ü¤Ç¤¹¡£
https://cacoo.com/diagrams/UmEpII6zMLeG4bRm
¤è¤¯¤¢¤ë
¡Ö°ìÍ÷¡×¢ª¡Ö¿·ºîÀ®ÆþÎϡעª¡Ö°ìÍ÷¡×
¡Ö°ìÍ÷¡×¢ª¡Ö½¤ÀµÆþÎϡעª¡Ö°ìÍ÷¡×
¤Î¤è¤¦¤ÊÁ«°Ü¤Î¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£
º£²ó¤Ï¤³¤ì¤òGWT¤ÇMVP²½¤¹¤ë¤È¤É¤¦¤Ê¤ë¤«¤ò½ñ¤¤Þ¤¹¡£
Ãí°ÕÅÀ
GWT¤Î¥µ¥¤¥È¤À¤È½ñ¤¤¤Æ¤¤¤Þ¤»¤ó¤¬¡¢
Activity¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤òÍøÍѤ¹¤ë¾ì¹ç¤Ï¡¢
gwt.xml¤Ë
<inherits name="com.google.gwt.activity.Activity" />
¤òµ½Ò¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
Åоì¿Íʪ
Activity
Activity¤ÏMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ç¸À¤¦¤È¤³¤í¤ÎPresenter¤ÎÌò³ä¤ò»ý¤Á¤Þ¤¹¡£
¤Ä¤Þ¤êÀÕ̳¤Ï
- Event¤Î½èÍý
- ¥Ç¡¼¥¿¥Ð¥¤¥ó¥Ç¥£¥ó¥°
¤Ç¤¹¡£
GWT MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ç¤Ï
Activity¡ÊMVP¤ÎPresenter)¤È¤Ê¤ë¥¯¥é¥¹¤ÏAbstractActivity¤ò·Ñ¾µ¤·¤Þ¤¹¡£
¤½¤·¤Æstart()¥á¥½¥Ã¥É¤Ç¡¢Ã´Åö¤¹¤ëView¤ËÂФ·¤Æ¡¢¥Ç¡¼¥¿¥Ð¥¤¥ó¥É¤ò¹Ô¤¤¤Þ¤¹¡£
¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç½Ð¤Æ¤¯¤ëPlace¤Ï¸å¤Ç²òÀ⤷¤Þ¤¹¡£
ClientFactory¤Ïñ½ã¤ÊFactory¤Ç¤¹¡£
³ÆgetHoge¤Ë¤Æ¥¤¥ó¥¹¥¿¥ó¥¹¤òºîÀ®¤·¡¢ÊֵѤ·¤Þ¤¹¡£
ListPresenter(Activity)
package com.google.code.stk.client.ui.presenter; import java.util.List; import com.google.appengine.api.datastore.Key; import com.google.code.stk.client.ClientFactory; import com.google.code.stk.client.service.TwitterServiceAsync; import com.google.code.stk.client.ui.display.ListDisplay; import com.google.code.stk.client.ui.place.EditPlace; import com.google.code.stk.client.ui.place.ListPlace; import com.google.code.stk.client.ui.place.NewPlace; import com.google.code.stk.shared.model.AutoTweet; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; public class ListPresenter extends AbstractActivity implements ListDisplay.Presenter{ private final TwitterServiceAsync service; private final ClientFactory clientFactory; private final ListPlace place; private ListDisplay display; public ListPresenter(ListPlace place , ClientFactory clientFactory) { super(); this.place = place; this.clientFactory = clientFactory; this.service = this.clientFactory.getTwitterService(); } @Override public void clickNewButton() { clientFactory.getPlaceController().goTo(new NewPlace()); } @Override public void clickDeleteAnchor(final Key key) { service.delete(key, new AsyncCallback<Void>() { @Override public void onSuccess(Void arg0) { clientFactory.getPlaceController().goTo(new ListPlace("delete" , key.getId())); } @Override public void onFailure(Throwable throwable) { } }); } @Override public void clickEditAnchor(Key key) { clientFactory.getPlaceController().goTo(new EditPlace(key.getId())); } @Override public void savePinCode(String value) { service.registAccessToken(value, new AsyncCallback<Void>() { @Override public void onFailure(Throwable arg0) { } @Override public void onSuccess(Void arg0) { display.getPinCodeInputPanel().setVisible(false); display.getSavePinCodeButton().setEnabled(true); Window.alert("¥Ô¥ó¥³¡¼¥É¤òÊݸ¤·¤Þ¤·¤¿¡£"); } }); } @Override public void start(final AcceptsOneWidget panel, EventBus eventBus) { display = clientFactory.getListDisplay(); display.setPresenter(this); panel.setWidget(display); service.findAll(new AsyncCallback<List<AutoTweet>>() { @Override public void onSuccess(List<AutoTweet> arg0) { display.drowTable(arg0); } @Override public void onFailure(Throwable arg0) { Window.alert(arg0.getMessage()); } }); } }
ClientFactory(Factory)
ClientFactory¤ÏDeferred Binding¤òÍøÍѤ·GWT.create¤Ë¤ÆºîÀ®¤·¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤ê¤´¤Ã¤½¤êView¤Ê¤É¤ò¥â¥Ã¥¯¤ËÊѹ¹¤¹¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
FactoryÃæ¤ÎEventBus¤ÏºòÆüÀâÌÀ¤·¤¿EventBus¤È¤Û¤ÜƱ¤¸¤Ã¤Ý¤¤¤Ç¤¹¡£
¤Ä¤Þ¤êÆÈ¼«Event¤ò½èÍý¤·¤Þ¤¹¡£
PlaceController¤Ï¸å¤Û¤ÉÀâÌÀ¤·¤Þ¤¹¡£
package com.google.code.stk.client; import com.google.code.stk.client.service.TwitterService; import com.google.code.stk.client.service.TwitterServiceAsync; import com.google.code.stk.client.ui.display.AutoTweetDisplay; import com.google.code.stk.client.ui.display.AutoTweetView; import com.google.code.stk.client.ui.display.ListDisplay; import com.google.code.stk.client.ui.display.ListView; import com.google.gwt.core.client.GWT; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; public class ClientFactoryImpl implements ClientFactory { private ListDisplay listDisplay = null; private PlaceController placeController = null; private SimpleEventBus eventBus; private TwitterServiceAsync twitterService; @Override public AutoTweetDisplay getAutoTweetDisplay() { return new AutoTweetView(); } @Override public EventBus getEventBus() { if(eventBus == null){ eventBus = new SimpleEventBus(); } return eventBus; } @Override public ListDisplay getListDisplay() { if(listDisplay == null){ listDisplay = new ListView(); } return listDisplay; } @Override public PlaceController getPlaceController() { if(placeController == null){ placeController = new PlaceController(getEventBus()); } return placeController; } @Override public TwitterServiceAsync getTwitterService() { if(twitterService == null){ twitterService = GWT.create(TwitterService.class); } return twitterService; } }
Display(IsWidget)
MVP¤ÎDisplay¤Ïñ½ã¤ÊView¥¯¥é¥¹¤Ê¤Î¤ÇWidget¤äUiBinder¤¢¤¿¤ê¤Çºî¤ì¤ÐÌäÂꤢ¤ê¤Þ¤»¤ó¤¬¡¢
Activity¤ÇÍøÍѤ¹¤ë¾ì¹ç¤ÏIsWidget¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò·Ñ¾µ¤·¤Æ¤ª¤¯¤È¡¢¤è¤¤¤Ç¤¹¡£
Display¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÎÃæ¤ËPresenter¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò»ý¤Ã¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ï¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤òPresenter¤Ë°Ñ¾ù¤µ¤»¤ë¤¿¤á¤Ë¡¢
Display¤Ë¤È¤Ã¤Æ½èÍý¤·¤Æ¤Û¤·¤¤¤³¤È¤òPresenter¤ËÀÚ¤ê½Ð¤·¡¢
¤½¤ÎPresenter¤ò·Ñ¾µ¤·¤Æ¤¤¤ë¥¯¥é¥¹¤òsetPresenter¤Ë¤ÆÅÐÏ¿¤µ¤»¡¢
¤¹¤Ù¤Æ¤Î¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤òPresenter¤Ë¤â¤¿¤»¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤ê¡¢¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤È¡¢²èÌ̤¬ÀÚ¤êÎ¥¤µ¤ì¡¢
¥Ç¥¹¥¯¥È¥Ã¥×¥¢¥×¥ê¤Ç¤¢¤ê¤¬¤Á¤Ê¡¢BigView¤òËɤ®¤Þ¤¹¡£
¤Þ¤¿¤½¤ì¤¾¤ì¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤È¤·¤Æ¡¢Àë¸À¤µ¤»¡¢
¤½¤ì¤¾¤ì¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò·Ñ¾µ¤µ¤»¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢
Presenter¤ÈDisplay¤Î°Í¸ÅÙ¤¬²¼¤¬¤ê¥Æ¥¹¥È¤Î¤·¤ä¤¹¤µ¤¬¤Þ¤·¤Þ¤¹¡£
º£²ó¤ÎListView¤Ë¤È¤Ã¤Æ¤ÎPresenter¤ÏListPresetner¤Ç¤¹¡£
¤Ê¤Î¤ÇListPresenter¤ÏListDislay.Presenter¤ò·Ñ¾µ¤·¡¢
start¥á¥½¥Ã¥ÉÆâ¤Ç¡¢display.setPresenter(this)¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¤½¤·¤ÆListViewÆâ¤Î³Æ@UiHander¤Î¤Ä¤¤¤¿¥á¥½¥Ã¥É¤Ç¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¡Ê¥Ç¡¼¥¿ÅÐÏ¿¤Ê¤É¡Ë¤ò
Presenter¤Ë°Ñ¾ù¤·¤Æ¤¤¤Þ¤¹¡£
¤Á¤Ê¤ß¤ËMVP¤Î¾ì¹ç¤Ï²èÌÌÁ«°Ü¤âPresenter¦¤Î»Å»ö¤Ê¤Î¤ÇPresenter¤ËǤ¤»¤Æ¤¤¤Þ¤¹¡£
View¤¬¹Ô¤¦¤Î¤Ï¼«¿È¤Î¤â¤ÄWidget¤Î´ÉÍý¤Î¤ß¤Ç¤¹¡£
ListDisplay
package com.google.code.stk.client.ui.display; import java.util.List; import com.google.appengine.api.datastore.Key; import com.google.code.stk.shared.model.AutoTweet; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.IsWidget; public interface ListDisplay extends IsWidget{ void drowTable(List<AutoTweet> tweetList); public interface Presenter{ void clickNewButton(); void clickDeleteAnchor(Key key); void clickEditAnchor(Key key); void savePinCode(String value); } public void setPresenter(Presenter presenter); FlowPanel getPinCodeInputPanel(); Button getSavePinCodeButton(); }
ListView
package com.google.code.stk.client.ui.display; import java.util.List; import com.google.code.stk.shared.model.AutoTweet; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; public class ListView extends Composite implements ListDisplay { @UiField Button newButton; @UiField InlineLabel sizeLabel; @UiField FlexTable table; @UiField Anchor pinCodeLink; @UiField FlowPanel pinCodeInputPanel; @UiField TextBox pinCode; @UiField Button savePinCode; private static ListViewUiBinder uiBinder = GWT .create(ListViewUiBinder.class); private Presenter presenter; interface ListViewUiBinder extends UiBinder<Widget, ListView>{ } @Override public void drowTable(List<AutoTweet> tweetList) { table.removeAllRows(); if (tweetList == null || tweetList.isEmpty()) { table.setText(0, 0, "tweet¤Ê¤·"); return; } table.setText(0, 0, "ID"); table.setText(0, 1, "ÂоÝ"); table.setText(0, 2, "ÆâÍÆ"); table.setText(0, 3, "»þ´Ö"); table.setText(0, 4, "´Ö³Ö"); table.setText(0, 5, "¥Ö¥ì"); table.setText(0, 6, "´ü´Ö"); table.setText(0, 7, "ºÇ½ªTweetÆü"); table.setText(0, 8, "½¤Àµ"); table.setText(0, 9, "ºï½ü"); int row = 1; for (final AutoTweet autoTweet : tweetList) { table.getColumnFormatter().setWidth(1, "140em"); table.getColumnFormatter().setWidth(3, "6em"); table.getColumnFormatter().setWidth(4, "8em"); table.setCellPadding(10); table.setCellSpacing(10); table.setText(row, 0, String.valueOf(autoTweet.getKey().getId())); table.setText(row, 1, autoTweet.getScreenName()); table.setText(row, 2, autoTweet.getTweet()); table.setText(row, 3, autoTweet.getTweetHour() + "»þ"); table.setText(row, 4, autoTweet.getCycle().name()); table.setText(row, 5, autoTweet.getBure().name()); table.setText(row, 6, autoTweet.getStartMMdd() + " ¡Á " + autoTweet.getEndMMdd()); table.setText(row, 7, autoTweet.getLastTweetAt()); Anchor syusei = new Anchor("½¤Àµ"); syusei.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { presenter.clickEditAnchor(autoTweet.getKey()); } }); table.setWidget(row, 8, syusei); Anchor sakujo = new Anchor("ºï½ü"); sakujo.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { presenter.clickDeleteAnchor(autoTweet.getKey()); } }); table.setWidget(row, 9, sakujo); row++; } } @Override public Widget asWidget() { return this; } @Override public void setPresenter(Presenter presenter) { this.presenter = presenter; } @Override public FlowPanel getPinCodeInputPanel(){ return pinCodeInputPanel; } @UiHandler("newButton") void onClickNewButton(ClickEvent e){ presenter.clickNewButton(); } @UiHandler("pinCodeLink") public void onClickPinCodeLink(ClickEvent e){ pinCodeInputPanel.setVisible(true); } @UiHandler("savePinCode") public void onClickSavePinCode(ClickEvent e){ savePinCode.setEnabled(false); presenter.savePinCode(pinCode.getValue()); } public ListView() { initWidget(uiBinder.createAndBindUi(this)); } @Override public Button getSavePinCodeButton() { return savePinCode; } }
Place
Place¤Ï²èÌ̤ä¾õÂÖ¤òɽ¤·¤Þ¤¹¡£
ºòÆüAppController¤ÈEventBus¡¢History¤Ë¤Æ¥Ò¥¹¥È¥ê¡¼Ãæ¿´¤Î²èÌÌÁ«°Ü¤òÀâÌÀ¤·¤Þ¤·¤¿¡£
AppController¤ÈEventBus¡¢History¤Î¤ä¤ë¤³¤È¤ò¤è¤ê¡¢¤ï¤«¤ê¤ä¤¹¤¯¡¢¤½¤·¤ÆÀÕ̳¤ò²èÌÌÁ«°Ü¡¢¾õÂÖÊÝ»ý¤Ë
ÆÃ²½¤µ¤»¤¿¤Î¤¬Place¤Ç¤¹¡£¡Ê¥¿¥Ö¥ó¡Ë
GWT¤Ç¤ÎPlace¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ï²èÌ̤ä¾õÂÖ¤òɽ¤¹Place¥¯¥é¥¹¤È¡¢
¤½¤ì¤é¤òÍøÍѤ·¤ÆHistory¥¤¥Ù¥ó¥È¤òȯ²Ð¤¹¤ëPlaceController¡¢
Place¤ÈHistory¤ò¥Þ¥Ã¥Ô¥ó¥°¤µ¤»¤ëPlaceHistoryMapper¡¢
¤½¤·¤ÆPlace¤ÈActivity¤ò¤Ò¤â¤Å¤±¤ë¡¢ActivityMapper¤òÍøÍѤ·¤Æ¼Â¸½¤·¤Þ¤¹¡£
¤Þ¤º²èÌ̤ä¾õÂÖ¤òɽ¤¹¡¢Place¥¯¥é¥¹¤Î»Ò¥¯¥é¥¹¤«¤é
ListPlace
ListPlace¤Ï°ìÍ÷²èÌ̤òɽ¤¹Place¥¯¥é¥¹¤Î»Ò¥¯¥é¥¹¤Ç¤¹¡£
id¤ästate¤ò»ý¤Ã¤Æ¤¤¤ë¤Î¤Ïºï½ü½èÍý¤«¤é¤â¤É¤Ã¤¿¡¢
½¤Àµ½èÍý¤«¤éÌá¤Ã¤¿¡¢
¿·µ¬ºîÀ®¤«¤éÌá¤Ã¤¿¤Ê¤É¤ò´ÉÍý¤¹¤ë¤¿¤á¤Ç¤¹¡£
ListPlace¤Ë¤ÏListPlace¤Î¾ðÊ󤫤éToken¤òƳ¤½Ð¤¹¡¢
Tokenizer¤ò»ý¤Ã¤Æ¤¤¤Þ¤¹¡£
Tokenizer¤ÏListPlace¤ÎºîÀ®¤È¡¢ListPlace¤«¤étoken¤ÎºîÀ®¤ò¹Ô¤¤¤Þ¤¹¡£
package com.google.code.stk.client.ui.place; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceTokenizer; public class ListPlace extends Place { private final String state; private final Long id; public ListPlace(){ this(null , null); } public ListPlace(String state, Long id) { this.state = state; this.id = id; } public ListPlace(String state) { this(state, null); } public Long getId() { return id; } public String getStringId(){ return id == null?"":id.toString(); } public String getState() { return state == null ? "" :state; } public static class Tokenizer implements PlaceTokenizer<ListPlace>{ @Override public ListPlace getPlace(String token) { if(token.contains("delete")){ return new ListPlace("delete" , Long.parseLong(token.replace("delete/", ""))); } if(token.contains("edit")){ return new ListPlace("edit" , Long.parseLong(token.replace("edit/", ""))); } if(token.contains("new")){ return new ListPlace("new"); } return new ListPlace(); } @Override public String getToken(ListPlace place) { return place.getState() + "/" + place.getStringId(); } } }
PlaceController
PlaceController¤ÏPlace¤òÍøÍѤ·¤Æ¡¢PlaceHistoryChangeEvent¤òȯ²Ð¤·Á«°Ü¤ò¼Â¸½¤·¤Þ¤¹¡£
¤¿¤È¤¨¤ÐListPresenter¤Î²¼µ¥á¥½¥Ã¥É¤Ï½¤Àµ¥¢¥ó¥«¡¼²¡²¼»þ¤Ë¡¢
½¤Àµ²èÌ̤ØÁ«°Ü¤µ¤»¤Þ¤¹¡£
ListPresenter
ListPresetner.java @Override public void clickEditAnchor(Key key) { clientFactory.getPlaceController().goTo(new EditPlace(key.getId())); }
PlaceHistoryMapper
PlaceHistoryMapper¤Ï³ÆPlace¤ÎTokenizer¤òÍøÍѤ·¤Æ¡¢HistoryToken¤ÈPlace¤Î¥Þ¥Ã¥Ô¥ó¥°¤ò¹Ô¤¤¤Þ¤¹¡£
@WithTokenizers¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ËTokenizer¤ò»ØÄꤹ¤ë¤À¤±¤Ç¥Þ¥Ã¥Ô¥ó¥°¤·¤Æ¤¯¤ì¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ëȯ¹Ô¤µ¤ì¤ëHistoryToken¤Ï {Placeû½Ì¥¯¥é¥¹Ì¾}:{Tokenizer.getToken()}¤Î·Á¤Ë¤Ê¤ê¤Þ¤¹¡£¡£¡£
Placeû½Ì¥¯¥é¥¹Ì¾¤¬¥À¥µ¤¤¤Î¤Ç¡¢¼£¤¹ÊýË¡¤¬ÃΤꤿ¤¤¸Â¤ê¤Ç¤¹¡£¡£¡£
package com.google.code.stk.client; import com.google.code.stk.client.ui.place.EditPlace; import com.google.code.stk.client.ui.place.ListPlace; import com.google.code.stk.client.ui.place.NewPlace; import com.google.gwt.place.shared.PlaceHistoryMapper; import com.google.gwt.place.shared.WithTokenizers; @WithTokenizers({ListPlace.Tokenizer.class , EditPlace.Tokenizer.class , NewPlace.Tokenizer.class}) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { }
ActivityMapper
ActivityMapper¤ÏPlace¤ÈActivity¤ò¤Ò¤â¤Å¤±¤Þ¤¹¡£
¤Ò¤â¤Å¤±¤Ï´èÄ¥¤ê¤Þ¤¹¡£¡£¡£
instanceof¤¬Èù̯¤Ê¤Î¤Ç¤¹¤¬¡¢¡¢¡¢
¤É¤¦¤Ë¤«¤·¤¿¤¤¤Ç¤¹¤Í¡£¡£¡£
package com.google.code.stk.client; import com.google.code.stk.client.ui.place.EditPlace; import com.google.code.stk.client.ui.place.ListPlace; import com.google.code.stk.client.ui.place.NewPlace; import com.google.code.stk.client.ui.presenter.EditPresenter; import com.google.code.stk.client.ui.presenter.ListPresenter; import com.google.code.stk.client.ui.presenter.NewPresenter; import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.place.shared.Place; public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { super(); this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { if(place instanceof ListPlace){ return new ListPresenter((ListPlace)place, clientFactory); } if(place instanceof NewPlace){ return new NewPresenter((NewPlace)place , clientFactory); } if(place instanceof EditPlace){ return new EditPresenter((EditPlace)place, clientFactory); } return null; } }
Activity¡¢Place¤Þ¤È¤á
°Ê¾å¤¬Activity¡¢Place¤Î´ØÏ¢¥¯¥é¥¹¤È¤½¤Î¼ÂÁõ¤Ç¤¹¡£
²èÌÌÁ«°Ü¤òHistoryÃæ¿´¤Ç¹Ô¤¦¤³¤È¤¬½ÐÍè¡¢¥Ö¥é¥¦¥¶Back¡¢Ajax¤Ë¤Ä¤è¤ê¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬ºîÀ®¤Ç¤¤Þ¤¹¡£
ºòÆü½ñ¤¤¤¿¡¢AppController¤ä¡¢History¤Ï¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ÎÃæ¤Ë±£¤ì¤¿¾õÂ֤ˤʤäƤ¤¤Þ¤¹¡£
¡Ê¤Þ¤¿¤Ï³ÆMapper¤äPlace¤Ëʬ»¶¤µ¤ì¤Æ¤¤¤ë¡Ë
¾åµ¤Î³ÆMapper¥¯¥é¥¹¤ÏEntryPoint¤¢¤¿¤ê¤Ç³ÆManeger¥¯¥é¥¹¤ËÅÐÏ¿¤·¤Æ¤ª¤¤Þ¤¹
ClientFactory clientFactory = GWT.create(ClientFactory.class); EventBus eventBus = clientFactory.getEventBus(); PlaceController placeController = clientFactory.getPlaceController(); // Start ActivityManager for the main widget with our ActivityMapper ActivityMapper activityMapper = new AppActivityMapper(clientFactory); ActivityManager activityManager = new ActivityManager(activityMapper,eventBus); activityManager.setDisplay(appWidget); // Start PlaceHistoryHandler with our PlaceHistoryMapper AppPlaceHistoryMapper historyMapper = GWT .create(AppPlaceHistoryMapper.class); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper); historyHandler.register(placeController, eventBus, defaultPlace);
¤â¤¦¥Á¥ç¥¤ºÙ¤«¤¤Æ°¤¤Ï¤Þ¤¿º£ÅÙÄɤ¤¤Þ¤¹¡£
¤¢¤È¤¬¤
º£²ó¤Î¤âÁ°²ó¤Î¤âÁ´¤¯MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î¥Ç¥¶¥¤¥ó¥Ñ¥¿¡¼¥ó¤òÀâÌÀ¤·¤Æ¤Ê¤¤¡£¡£¡£
¤Ê¤ó¤ÇHogeDisplay¤¬Presetner»ý¤Ã¤Æ¤ë¤Î¤È¤«ÀâÌÀ¤·¤Ê¤¤¤È¤Ç¤¹¤Í¡£¡£¡£
¤Ç¤âAcitivity¤ÈPlace¤¬½Ð¤Á¤ã¤Ã¤¿¤ó¤À¤â¤ó¡£¡£¡£
¤¦¤ó¡¢Îɤ«¤Ã¤¿¤È»×¤Ã¤Æ¤ë¤è¡£¡£¡£
Data Presenter¤â½ñ¤¤¿¤¤¤Ç¤¹¤Í¡£
2010-10-10
GWT¤ÇMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î1(History¤ÈAppController¡Ë
GWT | |
![]()
µ×¤·¤Ö¤ê¤Ë½ñ¤¤Þ¤¹¡£
ºÇ¶á¤Ï¤â¤Ã¤Ñ¤éGWT¤ò°·¤Ã¤Æ¤Þ¤¹¡£
Ⱦǯ¤°¤é¤¤¿¨¤Ã¤Æ¤ß¤Æ¡¢¤ä¤Ï¤êGWT¤Ç¤ÏMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã¤¬Âç»ö¤Ë¤Ê¤Ã¤Æ¤¯¤ë¤Ê¤È»×¤Ã¤¿¤ê¤·¤Þ¤·¤¿¡£
ËͤâºÇ½é¤Ï¤Þ¤Ã¤¿¤¯Ê¬¤«¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤Ç¤¹¤¬¡¢id:k2junior¤µ¤ó¤Î¤³¤Á¤é¤ÎÆüµ¤ò¤ß¤Æ·ë¹½Íý²ò¤¬¤Ç¤¤Þ¤·¤¿¡£
¤½¤Î¤¢¤ÈGWT¤ÎÂ絬Ìϳ«È¯¤ÎÀâÌÀʸ(?)¤Ë¤ª¤¤¤Æ¤¢¤ë¡¢
¥µ¥ó¥×¥ë¥×¥í¥¸¥§¥¯¥È¤ò¤ß¤Æ²¿¤È¤Ê¤¯Íý²ò¤·¤Æ¡¢
¼«Ê¬¤Ê¤ê¤Ë½ñ¤±¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¿¤Î¤ÇMVP + EventBus¥Ñ¥¿¡¼¥ó¤Ë¤Ä¤¤¤Æ½ñ¤¤¤Æ¤ß¤Þ¤¹¡£
¤Ê¤ª±Ñ¸ì¤ÏÆÉ¤á¤Ê¤¤¡¢Ê¹¤±¤Ê¤¤¤Ê¤Î¤Ç¡¢
Googlge IO 2009¤ÎGoogle Web Toolkit Architecture: Best Practices for Architecting Your GWT App¤ä
GWT¤ÎÂ絬Ìϳ«È¯¤ÎÀâÌÀʸ(?)¤Ï¤Ê¤ó¤È¤Ê¡Á¤¯¤·¤«¤ï¤«¤Ã¤Æ¤¤¤Þ¤»¤ó¡£
¤Ê¤Î¤Ç²ò¼á¤ä¡¢»È¤¤Êý¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¾ì½ê¤Ï¿¡¹¤¢¤ë¤È»×¤¤¤Þ¤¹¤Î¤Ç¡¢
¤´»ØÅ¦¤ò¤ª´ê¤¤¤¤¤¿¤·¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ë¥µ¥ó¥×¥ë¤È¤·¤Æ¤ÏGAE¾å¤Ë¾è¤Ã¤±¤Æ¤¤¤ëTwitter¤ÎBot¡Ê¤Î¥Ç¡¼¥¿ÆþÎϲèÌ̡ˤò»È¤¤¤Þ¤¹¡£
¥³¡¼¥É¡§http://goo.gl/7xPh (Google Code¤Ç¤¹¡£)
ºî¤Ã¤Æ¤¤¤ë¤â¤Î¤ÎÁ´ÂÎÁü¡Ê²èÌÌÁ«°Ü¡Ë
º£²ó¤Ä¤¯¤Ã¤Æ¤¤¤ë²èÌÌÁ«°Ü¤Ï°Ê²¼¤Î¤è¤¦¤Ê´¶¤¸¤Ç¤¹¡£
https://cacoo.com/diagrams/UmEpII6zMLeG4bRm
¤è¤¯¤¢¤ë
¡Ö°ìÍ÷¡×¢ª¡Ö¿·ºîÀ®ÆþÎϡעª¡Ö°ìÍ÷¡×
¡Ö°ìÍ÷¡×¢ª¡Ö½¤ÀµÆþÎϡעª¡Ö°ìÍ÷¡×
¤Î¤è¤¦¤ÊÁ«°Ü¤Î¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£
º£²ó¤Ï¤³¤ì¤òGWT¤ÇMVP²½¤¹¤ë¤È¤É¤¦¤Ê¤ë¤«¤ò½ñ¤¤Þ¤¹¡£
Åоì¿Íʪ
MVP + EventBus¥Ñ¥¿¡¼¥ó¤Ç¤Ï°Ê²¼¤Î¤è¤¦¤ÊÅоì¿Íʪ¤¬¤¤¤Þ¤¹¡£
Model ¥Ñ¥Ã¥±¡¼¥¸¡§com.google.code.stk.share.model
MVC¤ÎModel
¡Ê¥â¥Ç¥ë¤Î²ò¼á¤¬¤¤¤í¤¤¤í¤¢¤ë¤Î¤Ç¾ÜºÙ¤Ï½ü¤¤Þ¤¹¡£¡Ë
»ä¤Î¾ì¹ç¤Ïappengine¤ÎEntity¤¬¤½¤Î¤Þ¤ÞModel¤È¤·¤Æ¤¤¤Þ¤¹¡£
package com.google.code.stk.shared.model; import java.io.Serializable; import com.google.appengine.api.datastore.Key; import com.google.code.stk.shared.Enums; import org.slim3.datastore.Attribute; import org.slim3.datastore.Model; @Model(schemaVersion = 1) public class AutoTweet implements Serializable { private static final long serialVersionUID = 1L; @Attribute(primaryKey = true) private Key key; @Attribute(version = true) private Long version; /** tweet */ @Attribute(unindexed = true) private String tweet; /** bure */ @Attribute(unindexed = true) private Enums.Bure bure; /** cycle */ @Attribute(unindexed = true) private Enums.Cycle cycle; /** startMMdd */ private String startMMdd; /** endMMdd */ private String endMMdd; /** tweetTime(hh) */ @Attribute private String tweetHour; @Attribute(unindexed = true) private String lastTweetAt; private String screenName; /** * key¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return key */ public Key getKey() { return key; } /** * key¤òÀßÄꤷ¤Þ¤¹¡£ * @param key key */ public void setKey(Key key) { this.key = key; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((key == null) ? 0 : key.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } AutoTweet other = (AutoTweet) obj; if (key == null) { if (other.key != null) { return false; } } else if (!key.equals(other.key)) { return false; } return true; } /** * version¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return version */ public Long getVersion() { return version; } /** * version¤òÀßÄꤷ¤Þ¤¹¡£ * @param version version */ public void setVersion(Long version) { this.version = version; } /** * tweet¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return tweet */ public String getTweet() { return tweet; } /** * tweet¤òÀßÄꤷ¤Þ¤¹¡£ * @param tweet tweet */ public void setTweet(String tweet) { this.tweet = tweet; } /** * cycle¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return cycle */ public Enums.Cycle getCycle() { return cycle; } /** * cycle¤òÀßÄꤷ¤Þ¤¹¡£ * @param cycle cycle */ public void setCycle(Enums.Cycle cycle) { this.cycle = cycle; } /** * startMMdd¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return startMMdd */ public String getStartMMdd() { return startMMdd; } /** * startMMdd¤òÀßÄꤷ¤Þ¤¹¡£ * @param startMMdd startMMdd */ public void setStartMMdd(String startMMdd) { this.startMMdd = startMMdd; } /** * endMMdd¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return endMMdd */ public String getEndMMdd() { return endMMdd; } /** * endMMdd¤òÀßÄꤷ¤Þ¤¹¡£ * @param endMMdd endMMdd */ public void setEndMMdd(String endMMdd) { this.endMMdd = endMMdd; } /** * tweetTime(hhmm)¤ò¼èÆÀ¤·¤Þ¤¹¡£ * @return tweetTime(hhmm) */ public String getTweetHour() { return tweetHour; } /** * tweetTime(hhmm)¤òÀßÄꤷ¤Þ¤¹¡£ * @param tweetTime tweetTime(hhmm) */ public void setTweetHour(String tweetTime) { this.tweetHour = tweetTime; } public void setBure(Enums.Bure bure) { this.bure = bure; } public Enums.Bure getBure() { return bure; } public String getLastTweetAt() { return lastTweetAt; } public void setLastTweetAt(String lastTweetAt) { this.lastTweetAt = lastTweetAt; } public String getScreenName() { return screenName; } public void setScreenName(String value) { this.screenName = value; } }
Display ¥Ñ¥Ã¥±¡¼¥¸:com.google.code.stk.client.ui.display
MVP¤ÎView¤Ë¤¢¤¿¤ë¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¡£
¼ÂºÝ¤ÎView¥¯¥é¥¹¡ÊWidgets¤äUiBinder¡Ë¤Î³Æ¹àÌܤò¥á¥½¥Ã¥É¤Ë»ý¤Á¤Þ¤¹¡£
package com.google.code.stk.client.ui.display; import java.util.List; import com.google.appengine.api.datastore.Key; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HasValue; public interface AutoTweetDisplay extends Display { HasValue<String> getKeyId(); HasValue<String> getTweet(); HasValue<String> getBure(); HasValue<String> getCycle(); HasValue<String> getEndMMdd(); HasValue<String> getStartMMdd(); HasValue<String> getTweetHour(); void setPresenter(Presenter presenter); public interface Presenter{ public void regist(); } Button getRegistButton(); void setScreenNames(List<Key> arg0); HasValue<String> getScreenName(); }
Display¤ÏPresenter¤ÈView¤ò¤½·ë¹ç¤Ë¤·¡¢
ºÆÍøÍÑÀ¤È¥Æ¥¹¥È¤ò¤·¤ä¤¹¤¯¤·¤Æ¤¤¤Þ¤¹¡£
¤Û¤È¤ó¤É¤Î¥á¥½¥Ã¥É¤¬Has¡Á¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÇÀë¸À¤µ¤ì¤Æ¤¤¤ë¤Î¤Ï¡¢
¥Æ¥¹¥È»þ¤Ê¤É¤Ë¥â¥Ã¥¯¤òÆþ¤ì¤ä¤¹¤¯¤¹¤ë¤¿¤á¤Ç¤¹¡£
View ¥Ñ¥Ã¥±¡¼¥¸:com.google.code.stk.client.ui.display
View¥¯¥é¥¹¤ÏUiBinder¤äWidgets¤ÇºîÀ®¤µ¤ì¤¿¡¢¡Ö²èÌ̡פò»ý¤Ä¥¯¥é¥¹¤Ç¤¹¡£
View¤ÏDisplay¤ò¼ÂÁõ¤·¡¢²èÌ̤òºîÀ®¤·¤Þ¤¹¡£
package com.google.code.stk.client.ui.display; import java.util.List; import com.google.appengine.api.datastore.Key; import com.google.code.stk.client.ui.base.ValueListBox; import com.google.code.stk.shared.Enums.Bure; import com.google.code.stk.shared.Enums.Cycle; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; public class AutoTweetView extends Composite implements AutoTweetDisplay{ @UiField TextBox tweet; @UiField TextBox startMMdd; @UiField TextBox endMMdd; @UiField ValueListBox cycle; @UiField ValueListBox tweetHour; @UiField ValueListBox bure; @UiField TextBox keyId; @UiField Button registButton; @UiField ValueListBox screenName; private static AutoTweetViewUiBinder uiBinder = GWT .create(AutoTweetViewUiBinder.class); private Presenter presenter; private List<Key> arg0; interface AutoTweetViewUiBinder extends UiBinder<Widget, AutoTweetView> { } public AutoTweetView() { initWidget(uiBinder.createAndBindUi(this)); initDisplay(); } private void initDisplay() { for (Bure b : Bure.values()) { bure.addItem(b.name()); } for(Cycle c : Cycle.values()){ cycle.addItem(c.name()); } for(int i = 0; i < 24 ; i++){ String hour = String.valueOf(i); if(hour.length() < 2){ hour = 0 + hour; } tweetHour.addItem(hour +"»þ" , hour); } } @UiHandler("registButton") public void onRegistButtonClick(ClickEvent e){ registButton.setEnabled(false); presenter.regist(); } @Override public Button getRegistButton(){ return registButton; } @Override public HasValue<String> getBure() { return bure; } @Override public HasValue<String> getCycle() { return cycle; } @Override public HasValue<String> getEndMMdd() { return endMMdd; } @Override public HasValue<String> getKeyId() { return keyId; } @Override public HasValue<String> getStartMMdd() { return startMMdd; } @Override public HasValue<String> getTweetHour() { return tweetHour; } @Override public Widget asWidget() { return this; } @Override public HasValue<String> getTweet() { return tweet; } @Override public void setPresenter(Presenter presenter) { this.presenter = presenter; } @Override public void setScreenNames(List<Key> arg0) { this.arg0 = arg0; for (Key key : this.arg0) { screenName.addItem(key.getName()); } } @Override public HasValue<String> getScreenName() { return screenName; } }
Presenter
MVP¤ÎP¤Ç¡Öµ¡Ç½Ä󶡼ԡפÎÌò³ä¤ò»ý¤Á¤Þ¤¹¡£
¤ä¤ë¤³¤È¤Ï
- ¥¤¥Ù¥ó¥È¤Î½èÍý
- ¥Ç¡¼¥¿¥Ð¥¤¥ó¥É¡ÊView¤ØÅϤ¹¡Ë
¤Ç¤¹¡£
package com.google.code.stk.client.ui.presenter; import java.util.List; import com.google.appengine.api.datastore.Key; import com.google.code.stk.client.event.NewTweetCreatedEvent; import com.google.code.stk.client.service.TwitterServiceAsync; import com.google.code.stk.client.ui.display.AutoTweetDisplay; import com.google.code.stk.client.ui.display.AutoTweetDisplay.Presenter; import com.google.code.stk.shared.Enums.Bure; import com.google.code.stk.shared.Enums.Cycle; import com.google.code.stk.shared.model.AutoTweet; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.user.client.rpc.AsyncCallback; public class NewPresenter extends AbstractPresenter<AutoTweetDisplay> implements Presenter { private final TwitterServiceAsync service; public NewPresenter(AutoTweetDisplay display, HandlerManager eventBus , TwitterServiceAsync service) { super(display, eventBus); this.service = service; display.setPresenter(this); } @Override public void regist() { display.getRegistButton().setEnabled(false); AutoTweet data = new AutoTweet(); data.setBure(Bure.valueOf(display.getBure().getValue())); data.setCycle(Cycle.valueOf(display.getCycle().getValue())); data.setStartMMdd(display.getStartMMdd().getValue()); data.setEndMMdd(display.getEndMMdd().getValue()); data.setTweet(display.getTweet().getValue()); data.setTweetHour(display.getTweetHour().getValue()); data.setScreenName(display.getScreenName().getValue()); service.regist(data, new AsyncCallback<Void>() { @Override public void onSuccess(Void arg0) { display.getRegistButton().setEnabled(true); eventBus.fireEvent(new NewTweetCreatedEvent()); } @Override public void onFailure(Throwable throwable) { } }); } @Override protected void initView() { container.clear(); service.findAllAccessToeknOnlyKey(new AsyncCallback<List<Key>>() { @Override public void onFailure(Throwable arg0) { } @Override public void onSuccess(List<Key> arg0) { display.setScreenNames(arg0); container.add(display.asWidget()); } }); } }
AppController
AppController¤Ï³ÆPresenter¤ÈDisplay¤Î´ÉÍý¡¢
ÆÈ¼«Event¤Î½èÍý¤ò¹Ô¤¤¤Þ¤¹¡£
¤Þ¤¿ValueChangeHandler¤ò¼ÂÁõ¤¹¤ë¤³¤È¤Ç¡¢
Presenter¤ÈHistory¤ò´ÉÍý¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢
²èÌÌÁ«°Ü¤ò¥³¥ó¥È¥í¡¼¥ë¤·¤Æ¤¤¤Þ¤¹¡£
package com.google.code.stk.client; import com.google.code.stk.client.event.DeleteTweetClickEvent; import com.google.code.stk.client.event.DeleteTweetClickHandler; import com.google.code.stk.client.event.EditTweetClickEvent; import com.google.code.stk.client.event.EditTweetClickHandler; import com.google.code.stk.client.event.NewTweetClickEvent; import com.google.code.stk.client.event.NewTweetClickHandler; import com.google.code.stk.client.event.NewTweetCreatedEvent; import com.google.code.stk.client.event.NewTweetCreatedHandler; import com.google.code.stk.client.service.TwitterService; import com.google.code.stk.client.service.TwitterServiceAsync; import com.google.code.stk.client.ui.display.AutoTweetDisplay; import com.google.code.stk.client.ui.display.AutoTweetView; import com.google.code.stk.client.ui.display.ListDisplay; import com.google.code.stk.client.ui.display.ListView; import com.google.code.stk.client.ui.presenter.AbstractPresenter; import com.google.code.stk.client.ui.presenter.EditPresenter; import com.google.code.stk.client.ui.presenter.ListPresenter; import com.google.code.stk.client.ui.presenter.NewPresenter; import com.google.gwt.core.client.GWT; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HasWidgets; public class AppController implements ValueChangeHandler<String> { private final HandlerManager eventBus; private HasWidgets container; private TwitterServiceAsync service = GWT.create(TwitterService.class); public AppController(HandlerManager eventBus) { super(); this.eventBus = eventBus; bind(); } public void go(HasWidgets container){ this.container = container; if(History.getToken() == null || History.getToken().equals("")){ History.newItem("list"); }else{ History.fireCurrentHistoryState(); } } private void bind() { History.addValueChangeHandler(this); eventBus.addHandler(NewTweetClickEvent.TYPE, new NewTweetClickHandler() { @Override public void onClick(NewTweetClickEvent e) { History.newItem("new"); } }); eventBus.addHandler(EditTweetClickEvent.TYPE, new EditTweetClickHandler() { @Override public void onClick(EditTweetClickEvent e) { History.newItem("edit/" + String.valueOf(e.getKey())); } }); eventBus.addHandler(DeleteTweetClickEvent.TYPE, new DeleteTweetClickHandler() { @Override public void onClick(DeleteTweetClickEvent e) { History.newItem("list/deleteComplete/" + String.valueOf(e.getKey())); } }); eventBus.addHandler(NewTweetCreatedEvent.TYPE, new NewTweetCreatedHandler() { @Override public void onCreated(NewTweetCreatedEvent e) { History.newItem("list/newComplete"); } }); } @Override public void onValueChange(ValueChangeEvent<String> arg0) { String token = History.getToken(); if(token == null || token.startsWith("list") || token.equals("")){ ListDisplay display = new ListView(); AbstractPresenter<ListDisplay> presenter = new ListPresenter(display , eventBus , service); presenter.go(container); return; } if(token.equals("new")){ AutoTweetView display = new AutoTweetView(); AbstractPresenter<AutoTweetDisplay> presenter = new NewPresenter(display, eventBus, service); presenter.go(container); return; } if(token.startsWith("edit/")){ long id = Long.parseLong(token.replace("edit/", "")); AutoTweetView display = new AutoTweetView(); AbstractPresenter<AutoTweetDisplay> presenter = new EditPresenter(display, eventBus, service, id); presenter.go(container); } } }
EventBus (HandlerManager)
EventBus(HandlerManager)¤ÏÆÈ¼«ºîÀ®Event¤Î´ÉÍý¤ò¹Ô¤¤¤Þ¤¹¡£
¤³¤ÎEventBus¤ËÆÈ¼«Event¤òÅÐÏ¿¤·¡¢Handler¤Î½èÍý¤òÄêµÁ¤¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
ư¤¤Îή¤ì
¡ »Ï¤Þ¤ê¡ÊEntryPoint ¢ª AppController¡Ë
¤Þ¤ºEntryPoint¤Ç¤ÏEventBus¤ÎºîÀ®¤È¡¢AppController¤ÎºîÀ®¤ò¤ª¤³¤Ê¤¤¤Þ¤¹¡£
¤Þ¤¿AppController¤Ëɽ¼¨¤Îµ¯ÅÀ¡Êcontainer)¤òÄÌÃΤ·¤Þ¤¹¡£
package com.google.code.stk.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.user.client.ui.RootPanel; public class Index implements EntryPoint { @Override public void onModuleLoad() { HandlerManager eventBus = new HandlerManager(null); AppController appController = new AppController(eventBus); appController.go(RootPanel.get("contents")); RootPanel.get("msg").setVisible(false); } }
AppController¤¬new¤µ¤ì¤ë¥¿¥¤¥ß¥ó¥°¤Ç¥³¥ó¥¹¥È¥é¥¯¥¿¤Ë¤Æ¡¢EventBus¤ò¼õ¤±¼è¤ê¡¢
ÆÈ¼«¥¤¥Ù¥ó¥È¤ÎÅÐÏ¿¤ò¹Ô¤¤¤Þ¤¹¡£(bind()¥á¥½¥Ã¥É)
ÆÈ¼«Event¤ÎºîÀ®point¤Ï²èÌÌÁ«°Ü¤¬¹Ô¤ï¤ì¤ë¸Ä½ê¤Ç¤¹¡£
¤Þ¤¿ÆÈ¼«Event¤Î½èÍý¤â²èÌÌÁ«°Ü¤¬¹Ô¤ï¤ì¤¿¤³¤È¤òµÏ¿¤¹¤ë¤¿¤á
History¤ÎÅÐÏ¿¤Î¤ß¤ª¤³¤Ê¤¤¤Þ¤¹¡£
¤Þ¤¿¤³¤Î»þ¡¢AppController¼«¿®¤òHistory¤ÎValueChangeEventHandler¤È¤·¤ÆÅÐÏ¿¤·¤Þ¤¹¡£
@AppController¤Î¥³¥ó¥¹¥È¥é¥¯¥¿
public AppController(HandlerManager eventBus) { super(); this.eventBus = eventBus; bind(); } private void bind() { History.addValueChangeHandler(this); eventBus.addHandler(NewTweetClickEvent.TYPE, new NewTweetClickHandler() { @Override public void onClick(NewTweetClickEvent e) { History.newItem("new"); } }); eventBus.addHandler(EditTweetClickEvent.TYPE, new EditTweetClickHandler() { @Override public void onClick(EditTweetClickEvent e) { History.newItem("edit/" + String.valueOf(e.getKey())); } }); eventBus.addHandler(DeleteTweetClickEvent.TYPE, new DeleteTweetClickHandler() { @Override public void onClick(DeleteTweetClickEvent e) { History.newItem("list/deleteComplete/" + String.valueOf(e.getKey())); } }); eventBus.addHandler(NewTweetCreatedEvent.TYPE, new NewTweetCreatedHandler() { @Override public void onCreated(NewTweetCreatedEvent e) { History.newItem("list/newComplete"); } }); }
EntryPoint¤ÇAppController¤ÎºîÀ®¤¬´°Î»¤·¤¿¤é¡¢AppController#go¤ò¸Æ¤Ó½Ð¤·¡¢
½é´ü²èÌ̤òɽ¼¨¤·¤Þ¤¹¡£
go¥á¥½¥Ã¥É¤Ç¤Ï¡¢½é´üɽ¼¨¤ò¹Ô¤¦¿ÆWidgets¤ò¼õ¤±¼è¤ê¡¢Êݸ¤·¤Þ¤¹¡£
¤½¤·¤Æ¡¢History¤Ë¤Ê¤Ë¤âÀÑ¤Þ¤ì¤Æ¤Ê¤±¤ì¤Ð¡¢½é´ü²èÌ̤òɽ¼¨¤¹¤ë¤¿¤áHistory¤Ëtoken¤òÊݸ¤·¤Þ¤¹¡£
´û¤Ë¡¢History¤Ë²¿¤«¤¢¤Ã¤¿¾ì¹ç¡ÊÄ̾ï¤ÏF5¤Ê¤É¤Ç²èÌ̤ò¹¹¿·¤·¤¿¤Ê¤É¡Ë¤Ï¸½¹Ô¤ÎToken¤Î¾õÂÖ¤ÇValueChangeEvent¤òȯÀ¸¤µ¤»¤Þ¤¹¡£
public void go(HasWidgets container){ this.container = container; if(History.getToken() == null || History.getToken().equals("")){ History.newItem("list"); }else{ History.fireCurrentHistoryState(); } }
go¥á¥½¥Ã¥É¤Ë¤Æ¡¢È¯¹Ô¤µ¤ì¤¿HistoryToken¤Ë¤è¤ê¡¢ValueChangeEvent¤¬È¯À¸¤·¤Þ¤¹¡£
AppController¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ë¤Æ¡¢AppController¼«¿®¤¬History¤ÎValueChangeHandler¤È¤·¤Æ
ÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¤¿¤á¡¢AppController¤ÎonValueChange¥á¥½¥Ã¥É¤¬¸Æ¤Ó½Ð¤µ¤ì¤Þ¤¹¡£
onValueChange¥á¥½¥Ã¥É¤Ç¤ÏHistoryToken¤ò¤â¤È¤Ë¤É¤Î²èÌ̤òɽ¼¨¤¹¤ë¤«¡ÊDisplay¤ÈPresenter¤ò»È¤¦¤«¡Ë¤ò
ȽÄꤷ¤Þ¤¹¡£
½é´ü½èÍý¤Î¾ì¹ç¤Ï¡¢token¤¬"list"¤È¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢ListDisplay¤ÈListPresenter¤¬ÍøÍѤµ¤ì¤Þ¤¹¡£
@Override public void onValueChange(ValueChangeEvent<String> arg0) { String token = History.getToken(); if(token == null || token.startsWith("list") || token.equals("")){ ListDisplay display = new ListView(); AbstractPresenter<ListDisplay> presenter = new ListPresenter(display , eventBus , service); presenter.go(container); return; } if(token.equals("new")){ AutoTweetView display = new AutoTweetView(); AbstractPresenter<AutoTweetDisplay> presenter = new NewPresenter(display, eventBus, service); presenter.go(container); return; } if(token.startsWith("edit/")){ long id = Long.parseLong(token.replace("edit/", "")); AutoTweetView display = new AutoTweetView(); AbstractPresenter<AutoTweetDisplay> presenter = new EditPresenter(display, eventBus, service, id); presenter.go(container); } }
°Ê¾å¤Ë¤Æ¡¢EntryPoint¤«¤éAppController¤Þ¤Ç¤Î½èÍý¤Ï´°Î»¤Ç¤¹¡£
AppController¤¬History¤Ë¤è¤ê²èÌÌÁ«°Ü¤òÀ©¸æ¤¹¤ë¤³¤È¤Ç¡¢
²èÌÌÁ«°Ü=History¤Ø¤ÎÅÐÏ¿¤È¤¤¤¦¾õÂÖ¤¬½ÐÍè¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤êF5¤ä¥Ö¥é¥¦¥¶¥Ð¥Ã¥¯¤Ë¶¯¤¤¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬ºîÀ®¤Ç¤¤Þ¤¹¡£
¤¿¤È¤¨¤Ð¾åµ¤Ë¤Æ°ìÍ÷²èÌ̤¬É½¼¨¤µ¤ì¤¿¸å¡¢¿·µ¬ºîÀ®²èÌ̤òɽ¼¨¤¹¤ë¾ì¹ç¤Ï¡¢
ListPresenter¤Ë¤ÆNewTweetClickEvent¤òEventBus·Ðͳ¤Çȯ²Ð¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢
ºÆ¤ÓAppController¤Ø½èÍý¤¬Ìá¤ê¡¢History¤¬"new"¤ÇÀѤޤ졢
AppController¤ÎonValueChange¥á¥½¥Ã¥É¤¬¸Æ¤Ð¤ì
NewPresetner¤ÈNewDisplay¤¬Áª¤Ð¤ì¤Æ²èÌ̤¬É½¼¨¤µ¤ì¤Þ¤¹¡£
Â絬ÌϤʳ«È¯¤Î¾ì¹ç¤Ï¤³¤ÎAppController¤òÊ£¿ôºîÀ®¤·¡¢Event½èÍý¤òʬ³ä¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡£
¤Þ¤¿onValueChange¤´¤È¤Ç¡¢¥³¡¼¥Éʬ³ä(GWT.runAsync)¤ò¹Ô¤Ã¤Æ²èÌ̤´¤È¤Ë¥³¡¼¥É¤òʬ³ä¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡£
History¤ò»È¤Ã¤¿²èÌÌÁ«°Ü¤Ï´ÉÍý¤â¤·¤ä¤¹¤¯¡¢ÃͲèÌÌÁ«°Ü¤Ë¥Ñ¥é¥á¡¼¥¿¤òɬÍפȤ¹¤ë¾ì¹ç¤â¡¢#hoge/value¤Ê¤É¤È¤·¤Æ¤¦¤Þ¤¯¼èÆÀ¤¹¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£
¢¨¥¿¥Ö¥óGmail¤È¤«¤â¤½¤ó¤Ê´¶¤¸¡©
AppController¤òÍøÍѤ¹¤ë¤³¤È¤Ç¡¢¸«¤ä¤¹¤¤²èÌÌÁ«°Ü¤ÎÀ©¸æ¤òºî¤ë¤³¤È¤¬½Ð¤¤Þ¤¹¡£
¤¢¤È¤¬¤
ʸºÍ¤¬¤Ê¤¤¡£¡£¡£¡£
¼¡²ó¤ÏMVP¥¢¡¼¥¥Æ¥¯¥Á¥ã¤òºÙ¤«¤¯½ñ¤¤Þ¤¹¡£
¥¿¥Ö¥ó¡¢¥½¥Î¥¦¥Á¡¢¥¤¥Ä¥«¥«¥¥Þ¥¹
2010-03-21
Navigation¤ò³ÈÄ¥¤·¤Æ¤ß¤ë¡£
T2 | |
![]()
T2Framework¤ÎÈó¾ï¤Ë»È¤¤¤ä¤¹¤¤¤È¤³¤í¤Î°ì¤Ä¤Ë³ÈÄ¥À¤Î¹â¤µ¤¬¤¢¤ë¤È»×¤¤¤Þ¤¹¡£¤È¤¤¤¦¤³¤È¤Çº£²ó¤ÏNavigation¤ò³ÈÄ¥¤·¤Æ¤ß¤Þ¤¹¡£
¤³¤È¤Îȯü
¸½ºßT2 + Guice + GAE + mobylet + Slim3¤ò»È¤Ã¤Æ²èÁüupload¥µ¥¤¥È¤òºî¤Ã¤Æ¤Þ¤¹¡£
¤Ç¤½¤Î¤Ê¤«¤ÇGAE¤ÏfileSystem¤ò°·¤¨¤Ê¤¤¤¿¤á¡¢Datastore¤ËFile¥Ç¡¼¥¿¤òÆþ¤ì¤ÆÃÖ¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¾õÂ֤Ǥ·¤¿¡£
¤Ä¤Þ¤ê²èÁü¤òUp¤·¤¿¤é¡¢¤½¤ì¤ò¸«¤ë¤Ë¤ÏDatastore¤«¤é°ì²ó°ú¤ÃÄ¥¤ê½Ð¤·¤ÆResponse¥Ü¥Ç¥£¡¼¤Ë½ñ¤½Ð¤¹Åª¤Ê¤³¤È¤ò¤·¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£
T2Framework¤Î¾ì¹ç
T2Framework¤Î¾ì¹çľÀÜResponse¤Ë½ñ¤½Ð¤¹¤Ë¤Ï¡¢Direct¥Ê¥Ó¥²¡¼¥·¥ç¥ó¤òÍøÍѤ·¤Þ¤¹¡£
¤¿¤À¤³¤Î¥¯¥é¥¹¤òÍøÍѤ¹¤ë¾ì¹ç¤ÏHTTP¤ÎContentsType¤ÏPage¦¤Ç»ØÄꤷ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£
¤Ä¤Þ¤ê¤³¤ó¤Ê´¶¤¸
res.setContentType("image/jpeg");
return Direct.from(img.getData());
¤Ç³ÈÄ¥¤·¤è¤¦
contentType¤°¤é¤¤¼«Á°¤Ç´èÄ¥¤ì¤Ð¡©¤È¸À¤ï¤ì¤½¤¦¤Ç¤¹¤¬¡¢¤Þ¤¡¤ä¤Ã¤Æ¤ß¤¿¤¤¤ó¤Ç¤¹¡£Navigation¤Î³ÈÄ¥
¤À¤Ã¤ÆÃˤλҤÀ¤â¤ó¡£¡£¡£
¤È¤¤¤¦¤³¤È¤ÇNavigation¤ò³ÈÄ¥¤·¤Þ¤·¤¿¡£
´ðËÜŪ¤Ë¤ÏDirect¤ò·Ñ¾µ¤·¤Æ¡¢ContentsType¤òȽÄê¤Ç¤¤ë¤è¤¦¤Ë¤·¤è¤¦¤È¹Í¤¨¤Æ¤³¤ó¤Ê´¶¤¸¤Çºî¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
package com.google.code.stk.t2gae.commons.navigation; import java.io.File; import java.io.InputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.t2framework.commons.util.Assertion; import org.t2framework.commons.util.FileUtil; import org.t2framework.commons.util.StreamUtil; import org.t2framework.t2.contexts.WebContext; import org.t2framework.t2.navigation.StreamNavigation; import org.t2framework.t2.spi.Navigation; public class Img extends StreamNavigation { private String contentType; public Img(byte[] bytes) { super(bytes); ImgCodec codec = ImgCodec.getInstance(bytes); Assertion.notNull(codec); contentType = codec.contentType; } public Img(File file) { super(file); ImgCodec codec = ImgCodec.getInstance(FileUtil.getBytes(file)); Assertion.notNull(codec); contentType = codec.contentType; } public Img(InputStream is) { super(is); ImgCodec codec = ImgCodec.getInstance(StreamUtil.getBytes(is)); contentType = codec.contentType; } public Img(byte[] bytes , ImgCodec codec) { super(bytes); Assertion.notNull(codec); contentType = codec.contentType; } public Img(File file , ImgCodec codec) { super(file); Assertion.notNull(codec); contentType = codec.contentType; } public Img(InputStream is , ImgCodec codec) { super(is); Assertion.notNull(codec); contentType = codec.contentType; } public static Navigation jpg(byte[] bytes){ return new Img(bytes , ImgCodec.JPG); } public static Navigation gif(byte[] bytes){ return new Img(bytes , ImgCodec.GIF); } public static Navigation png(byte[] bytes){ return new Img(bytes , ImgCodec.PNG); } public static Navigation jpg(File file){ return new Img(file , ImgCodec.JPG); } public static Navigation gif(File file){ return new Img(file , ImgCodec.GIF); } public static Navigation png(File file){ return new Img(file , ImgCodec.PNG); } public static Navigation jpg(InputStream is){ return new Img(is , ImgCodec.JPG); } public static Navigation gif(InputStream is){ return new Img(is , ImgCodec.GIF); } public static Navigation png(InputStream is){ return new Img(is , ImgCodec.PNG); } public static Navigation from(byte[] bytes){ return new Img(bytes); } public static Navigation from(File file){ return new Img(file); } public static Navigation from(InputStream is){ return new Img(is); } @Override public void execute(WebContext context) throws Exception { final HttpServletResponse res = context.getResponse().getNativeResource(); res.setContentType(contentType); ServletOutputStream sos = res.getOutputStream(); super.writeTo(res, sos); sos.flush(); } public enum ImgCodec{ GIF("image/gif"), PNG("image/gif"), JPG("image/jpg"); private String contentType; private ImgCodec(String contentType){ this.contentType = contentType; } public String getContentType(){ return this.contentType; } public static ImgCodec getInstance(byte[] bytes){ if (bytes != null && bytes.length >= 2) { int b1 = bytes[0] & 0xFF; int b2 = bytes[1] & 0xFF; if (b1 == 0xFF && b2 == 0xD8) { return ImgCodec.JPG; } else if (b1 == 0x47 && b2 == 0x49) { return ImgCodec.GIF; } else if (b1 == 0x89 && b2 == 0x50) { return ImgCodec.PNG; } } return null; } } }
¤Á¤Ê¤ß¤ËImage¤ÎȽÄê½èÍý¤Ïmobylet¤ò»²¹Í¤Ë¤µ¤»¤Æ¤¤¤¿¤À¤¤Þ¤·¤¿¡£
¤Ç¤¢¤È¤ÏImage¥Ç¡¼¥¿¤òFile or Stream or byte ¤Ç¼è¤Ã¤Æ¤³¤ÎImg.from()¤È¤«¸Æ¤Ù¤ÐOK¤Ç¤¹¡£
byte[]¤Î½ñ¤½Ð¤·¤Î¤È¤³¤í¡¢BufferedOutputStream¤È¤«¤Ä¤«¤Ã¤¿¤Û¤¦¤¬¤¤¤¤¤Î¤«¤Ê¡©
¤Á¤Ê¤ß¤Ëgoogle code ¤Ë¸ø³«¤·¤¿¤Î¤Ç¡¢¤´ÍøÍѤÎÊý¤Ï¤É¤¦¤¾¡ª
JavaDoc¤Ï¤Þ¤¡¤½¤Î¤¦¤Á¡£¡£¡£
T2¤ÇSlim3¤Î¥Ð¥ê¥Ç¡¼¥·¥ç¥ó¤ò»È¤¤¤¿¤¤
¸½ºßºî¤Ã¤Æ¤¤¤ë¥µ¥¤¥È¤ÏWeb·Ï¤ÎÉôʬ¤Ït2¡¢±Ê³²½¼þ¤ê¤Ïslim3-datastore¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£
¤¿¤Àt2¤Ë¤ÏValidation¤Ï¤Ê¤¤¤Î¤Ç(t2¤Ë¤Ï¤Ê¤¯¤Æ¤¤¤¤¤È»×¤¤¤Þ¤¹ ¤½¤ÎÇö¤µ¤¬¤È¤Æ¤âÁÇŨ¤Ê¤Î¤Ç¡£)¤É¤¦¤·¤è¤¦¤«¤Ê¤È»×¤Ã¤Æ¤¤¤¿¤Î¤Ç¤¹¤¬¡¢
¤¢¤ë¤¸¤ã¤Ê¤¤¤Ç¤¹¤«Slim3¤Ë¡ªvalidators¤¬¡ª
¤Ã¤Æ¤³¤È¤Çslim3¤ÎValidators¤òT2¤Ç»È¤¨¤Ê¤¤¤«¤ä¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
¤È¤ê¤¢¤¨¤º¤Ê¤ó¤â¹Í¤¨¤Ê¤¤¤Ç¤Ä¤«¤Ã¤Æ¤ß¤¿¡£¡£¡£
¤È¤ê¤¢¤¨¤º²¿¤â¹Í¤¨¤Ê¤¤¤Ç¡¢»È¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
/** * ¥¤¥á¡¼¥¸¥Ç¡¼¥¿¤òÊݸ¤·¤Þ¤¹¡£ * @param context context * @param request request * @param file ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥¡¥¤¥ë * @param title ¥¿¥¤¥È¥ë * @param updaterComment Åê¹Æ¼Ô¥³¥á¥ó¥È * @return À®¸ù»þ´°Î»²èÌÌ */ @POST @ActionParam("store") public Navigation store( WebContext context ,HttpServletRequest request ,UploadFile file ,@RequestParam("title") String title ,@RequestParam("updaterComment") String updaterComment ){ //¤³¤³¤«¤éValidation Validators v = new Validators(request); v.add(ImageMeta.get().title, v.required()); v.add("img", v.byteType()); v.add(ImageMeta.get().updaterComment , v.maxlength(500)); if(v.validate() == false){ //v.validate()¤¬false¤Ê¤é½ªÎ» return index(context); } if(file.get().length > StkConst.MAX_IMAGE_BYTES){ return index(context); } if(!ArrayUtil.contains(StkConst.getSupportedExtensions() , FilenameUtils.getExtension(file.getName()).toLowerCase())){ return index(context); } Image image = new Image(); GlobalTransaction tx =Datastore.beginGlobalTransaction(); try{ image.setKey(Datastore.allocateId(Image.class)); image.getUpdaterRef().setModel((Member)context.getSession().getAttribute(StkConst.SESSION_KEY_MEMBER)); image.setTitle(title); image.setUpdaterComment(updaterComment); image.setCreateDate(new Date()); image.setFileName(file.getName()); List<ImgUnit> imgUnits = image.setImage(file.get()); tx.put(imgUnits); tx.put(image); tx.commit(); }catch (Exception e){ tx.rollback(); v.getErrors().put("put", e.getMessage()); } return Redirect.to("/top"); }
¤Ç¼Â¹Ô¤¹¤ë¤È¡¢²¼µ¤Î¤è¤¦¤ÊException
Caused by: java.lang.NullPointerException
at org.slim3.jsp.Functions.errors(Functions.java:403)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.commons.el.FunctionInvocation.evaluate(FunctionInvocation.java:172)
at org.apache.commons.el.ExpressionEvaluatorImpl.evaluate(ExpressionEvaluatorImpl.java:263)
at org.apache.commons.el.ExpressionEvaluatorImpl.evaluate(ExpressionEvaluatorImpl.java:190)
at org.apache.jasper.runtime.PageContextImpl$13.run(PageContextImpl.java:884)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:880)
at org.apache.jsp.upload.index_jsp._jspx_meth_c_forEach_0(index_jsp.java:153)
at org.apache.jsp.upload.index_jsp._jspService(index_jsp.java:86)
... 66 more
¤Ê¤ó¤«É¬Íפ餷¤¤¡£¡£¡£
¤Ç³ºÅö¤Î¾ì½ê¤ò¤ß¤ë¤È
@slim3 Functions
/**
* Returns errors iterator.
*
* @return errors iterator
*/
@SuppressWarnings("unchecked")
public static Iterator<String> errors() {
HttpServletRequest request = RequestLocator.get();¢«¤³¤³¤ÇNull¤¬µ¢¤ë¡£
Map<String, String> errors = ¢«¤³¤³¤ÇNullPointer
(Map<String, String>) request
.getAttribute(ControllerConstants.ERRORS_KEY);
if (errors != null) {
return errors.values().iterator();
}
return null;
}
¤³¤ó¤Ê´¶¤¸¤é¤·¤¯¡¢RequestLocator¤Ërequest¤¬Æþ¤Ã¤Æ¤¤¤Ê¤¤¤È¤¤¤±¤Ê¤¤¤é¤·¤¤¡£¡£¡£
¤¢¤ÈÊ·°Ïµ¤Åª¤ËRequest¤Î¤Ê¤«¤ËControllerConstrants.ERRORS_KEY¤Ç¤Ê¤ó¤«¤Ï¤¤¤Ã¤Æ¤ë¤é¤·¤¤¡£
¤Ç¤¤¤í¤¤¤í¸«¤Æ¤Ã¤ÆPlugin¤òºî¤Ã¤Æ¤ß¤¿¡£
¤Ç¤¤¤í¤¤¤í¸«¤Æ¤Ã¤ÆPlugin¤òºî¤Ã¤Æ¤ß¤¿¡£
¤³¤ó¤Ê´¶¤¸¤Ç¤¹¡£
package com.google.code.stk.t2gae.commons.plugin; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slim3.controller.ControllerConstants; import org.slim3.controller.validator.Errors; import org.slim3.util.ApplicationMessage; import org.slim3.util.RequestLocator; import org.slim3.util.ResponseLocator; import org.t2framework.t2.plugin.AbstractPlugin; /** * slim3¤Î³Æ¼ïµ¡Ç½¤òÍøÍѤ¹¤ë¤¿¤á¤ÎPlugin * @author keisuke.oohashi * */ public class Slim3Plugin extends AbstractPlugin { //TODO 2010/03/21 16:37:53 keisuke.oohashi:ThreadSafe¤¸¤ã¤Ê¤µ¤½¤¦¡£¡£¡£ /** previousRequest */ private HttpServletRequest previousRequest; /** previousResponse */ private HttpServletResponse previousResponse; /** * slim3¤Î¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹¤ÎÂå¤ï¤ê¤ËRequest¡¢Response¡¢Errors¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£ * * @param request Request * @param response Response * * @see org.slim3.controller.FrontController * @see org.t2framework.t2.plugin.AbstractPlugin#beginRequestProcessing(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) * */ @Override public void beginRequestProcessing(HttpServletRequest request, HttpServletResponse response) { previousRequest = RequestLocator.get(); RequestLocator.set(request); previousResponse = ResponseLocator.get(); ResponseLocator.set(response); ApplicationMessage.setBundle(ControllerConstants.DEFAULT_LOCALIZATION_CONTEXT, request.getLocale()); Errors errors = (Errors) request.getAttribute(ControllerConstants.ERRORS_KEY); if (errors == null) { errors = new Errors(); request.setAttribute(ControllerConstants.ERRORS_KEY, errors); } super.beginRequestProcessing(request, response); } /** * slim3¤Î¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹¤ÎÂå¤ï¤ê¤ËRequest¡¢Response¡¢Errors¤Î¥¯¥ê¥¢¤ò¹Ô¤¤¤Þ¤¹¡£ * * @param request Request * @param response Response * * @see org.slim3.controller.FrontController * @see org.t2framework.t2.plugin.AbstractPlugin#endRequestProcessing(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public void endRequestProcessing(HttpServletRequest request, HttpServletResponse response) { ApplicationMessage.clearBundle(); ResponseLocator.set(previousResponse); RequestLocator.set(previousRequest); super.endRequestProcessing(request, response); } }
¤³¤ó¤Ê´¶¤¸¤Çºî¤Ã¤Æ¤ß¤¿¤Î¤Ç¤¹¤¬¡¢TODO¤Ë¤â½ñ¤¤¤Æ¤ëÄ̤ꡢThreadSafe¤¸¤ã¤Ê¤µ¤½¤¦¡£¡£¡£
Plugin¥¯¥é¥¹¤ÏGuice¤ÎRequestScoped¤ÇÊݸ¤Ç¤¤Ê¤¤¤Ã¤Ý¤¤¤Î¤Ç¤È¤ê¤¢¤¨¤ºSINGLETON¤Ë¤·¤Æ¤Þ¤¹¡£
¤«¤Ê¤ê²ø¤·¤¤¡£
¤Ç¤¢¤È¤Ï¤³¤Î¥¯¥é¥¹¤òGuice¥â¥¸¥å¡¼¥ë¤ÇÅÐÏ¿¤·¤Æ¤ª¤¤Þ¤¹¡£
bind(Plugin.class).annotatedWith(Names.named("slim3Plugin")).to(Slim3Plugin.class).in(Scopes.SINGLETON);
¤³¤ì¤ÇºÇ½é¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ù¤ÐValidator¤¬¼Â»Ü¤µ¤ì¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ë¥½¡¼¥¹¤Ï¤³¤Î¤Ø¤ó¤Ç¤¹¡£
ÊäÂ
º£²ó¤Î¤ÏSlim3¤ÎFilter¥¯¥é¥¹(FrontController)¤òÆþ¤ì¤ì¤Ð¤È¤¯¤ËÀßÄꤹ¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡£
¤¿¤À»äŪ¤Ë¡¢WebÁؤΥե졼¥à¥ï¡¼¥¯¤¬º®ºß¤¹¤ë¾õ¶·¤Ï¤¢¤Þ¤ê¤è¤¯¤Ê¤¤¤Î¤«¤Ê¤È»×¤Ã¤Æºî¤ê¤Þ¤·¤¿¡£
T2¤ÎÎɤµ¤Ï¤½¤ÎÇö¤µ¤Ë¤¢¤ë¤È»×¤Ã¤Æ¤¤¤Þ¤¹¡£
Çö¤¤¤«¤é¤³¤½¡¢µ¡Ç½³ÈÄ¥À¤¬¹â¤¯¡¢Â¾¤Î¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ò¼ÙË⤷¤Þ¤»¤ó¡£¤à¤·¤í°ú¤Î©¤Æ¤Þ¤¹¡£
T2»È¤Ã¤Æ»Å»ö¤¬½ÐÍ褿¤é¤¹¤Æ¤¤À¤Ê¤¡¡Á
2010-02-17
T2+GAE+guice ¤ÎPage¥¯¥é¥¹ÍÑGuiceModule¤òAnnotation Processing Tool¤ÇºîÀ®¤·¤Þ¤¹¡£
T2 GuiceÏ¢·È¤À¤ÈPage¥¯¥é¥¹¤òModule¤Ç°ì¤Ä¤º¤ÄÆÉ¤ß¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡£
°Õ³°¤È¤³¤ì¤¬ÌÌÅݤʺî¶È¤Ç¡¢Pageºî¤Ã¤¿¤±¤ÉModule¤Ë½ñ¤Ëº¤ì¤Æ¤â¤Ã¤«¤¤ApplicationServerºÆµ¯Æ°¤Ê¤ó¤Æ¤³¤È¤Ï¤è¤¯¤¢¤ê¤Þ¤¹¡£
¤Æ¤³¤È¤Ç¤á¤ó¤É¤¯¤µ¤¤ºî¶È¤ÏTool¤òºî¤Ã¤Æ¤·¤Þ¤¨¤È»×¤¤¤Þ¤·¤¿¡£¤½¤³¤ÇºÇ¶á¤è¤¯¸«¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¿Annotation Processing Tool(°Ê²¼ APT)¤Ç
Page¥¯¥é¥¹ÍÑModule¤òºîÀ®¤·¤Æ¤ß¤Þ¤¹¡£
¤Þ¤ºAnnotation¤ò½èÍý¤¹¤ëProcessor¥¯¥é¥¹
package jp.stk.tools.apt.processor; import java.util.List; import java.util.Map; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedOptions; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import jp.stk.tools.apt.AptConst; import jp.stk.tools.apt.generator.T2GuiceModuleGenerator; import org.t2framework.t2.tool.apt.PageMirror; import org.t2framework.t2.tool.apt.PageSettingsGenerator; import org.t2framework.t2.tool.apt.PageSettingsProcessor; /** * t2 page module processor * <pre> * t2¤ÎPage¥¯¥é¥¹ÍÑModule¥¯¥é¥¹¤òºîÀ®¤¹¤ëProcessor¥¯¥é¥¹¤Ç¤¹¡£ * </pre> * @author soundTricker * */ @SupportedSourceVersion(SourceVersion.RELEASE_6) @SupportedAnnotationTypes("org.t2framework.t2.annotation.core.Page") @SupportedOptions({AptConst.OPTIONS_GENERATE_MODULE_NAME , AptConst.OPTIONS_OUTPUT_PACKAGE}) public class T2GuiceModuleProcessor extends PageSettingsProcessor { /** * GuiceModule¤òºîÀ®¤·¤Þ¤¹¡£ * <pre> * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¤è¤ê¡¢GuiceModule¤òºîÀ®¤·¤Þ¤¹¡£ * </pre> * @see org.t2framework.t2.tool.apt.PageSettingsProcessor#generate(java.util.Map<java.lang.String,java.util.List<org.t2framework.t2.tool.apt.PageMirror>>, javax.annotation.processing.ProcessingEnvironment) */ @Override protected void generate(Map<String, List<PageMirror>> pageMetaMap,ProcessingEnvironment processingEnv) { PageSettingsGenerator generator = new T2GuiceModuleGenerator(pageMetaMap, processingEnv); generator.generate(); } }
PageSettingsProcessor ¤ÏT2framework 0.6.3-cr1¤ËÆþ¤Ã¤Æ¤¤¤¿page.properties¤òºî¤ëAPT¤ÎProcessor¥¯¥é¥¹¤Ç¤¹¡£
¤Û¤È¤ó¤É¤Î½èÍý¤Ï¤³¤ì¤¬¤ä¤Ã¤Æ¤¯¤ì¤Á¤ã¤Ã¤Æ¤Þ¤¹¤Í¡£¡£¡£
¤Ç¤â¥Ð¡¼¥¸¥ç¥ó¤¬cr¤Ê¤Î¤Ç¤Ê¤¯¤Ê¤Ã¤Á¤ã¤Ã¤¿¤é¤É¤¦¤·¤è¤¦¡£
¼¡¤Ë¼ÂºÝ¤ËGuiceModule¤òºîÀ®¤¹¤ëGenerator¥¯¥é¥¹
package jp.stk.tools.apt.generator; import java.io.IOException; /** * Page¥¯¥é¥¹ÍѤÎGuiceModule¤òºîÀ®¤¹¤ëGenerator¥¯¥é¥¹¤Ç¤¹¡£ * @author soundTricker * */ public class T2GuiceModuleGenerator implements PageSettingsGenerator { //====================================================================== // ¥×¥í¥Ñ¥Æ¥£ //====================================================================== /** * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¥Þ¥Ã¥× * <pre> * key:package̾ * value:key¤Î¥Ñ¥Ã¥±¡¼¥¸ÆâPage¥¯¥é¥¹¥á¥¿¥Ç¡¼¥¿¤Î¥ê¥¹¥È */ protected Map<String, List<PageMirror>> pageMetaMap; /** APT¤Î¼Â¹Ô¾ðÊó */ protected ProcessingEnvironment processingEnv; /** writer */ protected PrintWriter writer; /** GuiceModule¤Î½ÐÎÏÀè¥Ñ¥Ã¥±¡¼¥¸ */ protected String outputPackage = ""; /** ºîÀ®¤¹¤ëGuiceModule̾ */ protected String generateModuleName = AptConst.DEFAULT_MODULE_NAME; //====================================================================== // ¥³¥ó¥¹¥È¥é¥¯¥¿ //====================================================================== /** * ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿ * <pre> * writer¤Ê¤É¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£ * </pre> * @param pageMetaMap Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¥Þ¥Ã¥× * @param processingEnv APT¤Î¼Â¹Ô¾ðÊó */ public T2GuiceModuleGenerator(Map<String, List<PageMirror>> pageMetaMap,ProcessingEnvironment processingEnv) { this.pageMetaMap = pageMetaMap; this.processingEnv = processingEnv; Filer filer = this.processingEnv.getFiler(); Map<String , String> options = this.processingEnv.getOptions(); if(options.containsKey(AptConst.OPTIONS_OUTPUT_PACKAGE)){ outputPackage = options.get(AptConst.OPTIONS_OUTPUT_PACKAGE); } if(options.containsKey(AptConst.OPTIONS_GENERATE_MODULE_NAME)){ generateModuleName = options.get(AptConst.OPTIONS_GENERATE_MODULE_NAME); } FileObject fileObject = null; try { fileObject = filer.createSourceFile(outputPackage + AptConst.PACKAGE_SEPARATOR + generateModuleName); final Writer filerWriter = FilerUtil.openWriter(fileObject); this.writer = WriterUtil.createPrintWriter(filerWriter); } catch (IOException e) { CloseableUtil.close(this.writer); throw new IORuntimeException(e); } } //====================================================================== // ¥á¥¤¥ó //====================================================================== /** * ¥½¡¼¥¹¤òºîÀ®¤·¤Þ¤¹¡£ * @see org.t2framework.t2.tool.apt.PageSettingsGenerator#generate() */ @Override public void generate() { try{ makeClassDefinition(); makeConfigureMethodDefinition(); for (Entry<String, List<PageMirror>> pageMetaEntry : pageMetaMap.entrySet()) { for (PageMirror pageMirror : pageMetaEntry.getValue()) { makeBindLogic(pageMirror); } } makeConfigureMethodFutter(); makeClassFutter(); FlushableUtil.flush(writer); }finally{ CloseableUtil.close(writer); } } //====================================================================== // ²¼ÀÁ¤± //====================================================================== /** * ¥¯¥é¥¹ÄêµÁ¤òºîÀ®¤·¤Þ¤¹¡£ */ private void makeClassDefinition() { writer.format("package %s;\n" , outputPackage); writer.format("public class %s extends %s {\n", generateModuleName , AbstractModule.class.getName()); } /** * ¥á¥½¥Ã¥ÉÄêµÁ¤òºîÀ®¤·¤Þ¤¹¡£ */ private void makeConfigureMethodDefinition(){ writer.format(" @Override\n"); writer.format(" protected void configure() {\n"); } /** * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¤è¤êbind¥í¥¸¥Ã¥¯¤òºîÀ®¤·¤Þ¤¹¡£ * @param pageMirror */ private void makeBindLogic(PageMirror pageMirror) { writer.format(" bind(%s.%s.class).in(com.google.inject.servlet.ServletScopes.REQUEST);\n" , pageMirror.getPackageName() , pageMirror.getPageClassName()); } /** * ¥á¥½¥Ã¥É¤Î¥Õ¥Ã¥¿¡¼¤òºîÀ®¤·¤Þ¤¹¡£ */ private void makeConfigureMethodFutter() { writer.format(" }\n"); } /** * ¥¯¥é¥¹¤Î¥Õ¥Ã¥¿¡¼¤òºîÀ®¤·¤Þ¤¹¡£ */ private void makeClassFutter() { writer.format("}\n"); } }
¤¢¤ÈÄê¿ôÄêµÁ¥¯¥é¥¹¡£
package jp.stk.tools.apt; public class AptConst { public static final String OPTIONS_GENERATE_MODULE_NAME = "generateModuleName"; public static final String OPTIONS_OUTPUT_PACKAGE = "outputPackage"; public static final String DEFAULT_MODULE_NAME = "PageModule"; public static final String PACKAGE_SEPARATOR = "."; }
¤¿¤À¥Æ¥¹¥È¤Î»ÅÊý¤¬¤ï¤«¤é¤Ê¤¯¤Æ¡¢
Ä´¤Ù¤Æ¤¤¤¿¤é¡¢Seasar¤Îsandbox¤Ëaptina¤È¤¤¤¦APTÍÑ¤Î¥×¥í¥¸¥§¥¯¥È¤¬¤¢¤ê¤Þ¤·¤¿¤Î¤Ç¡¢
¤³¤Á¤é¤Îhttp://aptina.sandbox.seasar.org/aptina-unit/index.html:Aptina Unit]¤ò»È¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
¤Ç¤³¤ì¤¬Test¥¯¥é¥¹
package jp.stk.tools.apt.processor; import java.io.IOException; import javax.tools.ToolProvider; import jp.stk.tools.apt.AptConst; import jp.stk.tools.apt.testpage.TestPage; import org.seasar.aptina.unit.AptinaTestCase; public class T2GuiceModuleProcessorTest extends AptinaTestCase { private static final String OPTION_FORMAT = "-A%s=%s"; protected void setUp() throws Exception { super.setUp(); addSourcePath("src/test/java"); } public void testProcess() throws IOException { ToolProvider.getSystemJavaCompiler().getClass(); T2GuiceModuleProcessor processor = new T2GuiceModuleProcessor(); addProcessor(processor); setCharset("UTF-8"); addOption(String.format(OPTION_FORMAT, AptConst.OPTIONS_OUTPUT_PACKAGE , "jp.stk.gae.module")); addCompilationUnit(TestPage.class); compile(); //TODO ¤á¤ó¤É¤¯¤µ¤¤¤Î¤Çɽ¼¨¤À¤±³Îǧ¡£¡£¡£¤Á¤ã¤ó¤Èºî¤é¤Ê¤¯¤Á¤ã¡£¡£¡£ System.out.println(getGeneratedSource("jp.stk.gae.module." + AptConst.DEFAULT_MODULE_NAME)); } }
¤³¤ì¤Ç¥Æ¥¹¥È¤·¤Þ¤·¤¿¡£
º£²ó¤ÏAPT¤ò¤ä¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
»äŬÅö¤ÊSVN¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¤Î¤Çjar¤ò¸ø³«¤Ç¤¤Þ¤»¤ó¤¬¡¢
¼ÁÌ䤬¤¢¤ê¤Þ¤·¤¿¤é¤´Ï¢Íí¤¯¤À¤µ¤¤¡£
¤Á¤Ê¤ß¤ËºÇ½éVelocity¤Ç¥½¡¼¥¹¤ò¤Ä¤¯¤ë¤Î¡Ê¥Æ¥ó¥×¥ì¡¼¥È¤ÎÊѹ¹¤â²Äǽ¡Ë¤â½ñ¤¤¤Æ¤¤¤¿¤Î¤Ç¤¹¤¬¡¢
¤ï¤¶¤ï¤¶APT¤Î¤¿¤á¤Ë¥é¥¤¥Ö¥é¥ê¤òÍî¤È¤¹¤Î¤â·ù¤«¤Ê¤È»×¤Ã¤Æ¤Ù¤¿½ñ¤ÈǤòºÜ¤»¤Þ¤·¤¿¡£
Í×˾¤¬¤¢¤Ã¤¿¤éºÜ¤»¤Þ¤¹¡£
Äɲá§
¤³¤Î¥½¡¼¥¹¤À¤ÈAPT¤Ë°ú¿ô¤òÍ¿¤¨¤Ê¤¤¤È¤³¤±¤Þ¤¹¡£¡£¡£
»þ´Ö¤¬¤¢¤Ã¤¿¤é¼£¤·¤Þ¤¹¡£
cr¤È¤Ï¤¤¤¨¡¢»È¤Ã¤Æ¤¯¤ì¤Æ¤ë¿Í¤¬¤¤¤ì¤Ð¾Ã¤¹¤Ê¤ó¤Æ¤³¤È¤·¤Ê¤¤¤Î¤Ç°Â¿´¤·¤Æ¤¯¤À¤µ¤¤¡£
soundTrick¤µ¤ó¤Îgmail¥¢¥É¥ì¥¹Á÷¤Ã¤Æ¤¤¤¿¤À¤±¤Þ¤¹¤«¡©
¤¢¤ê¤¬¤È¤¦¸æºÂ¤¤¤Þ¤¹¡ª
¤¹¤°Á÷¤ê¤Þ¤¹¡ª