這篇是承接《輕量級 Java 開發框架 設計》系列Blog文的後續文章,本文將介紹 Hasor 內部主要插件並附帶插件的功能描述和簡單使用 Demo。 css
Hasor 使用的是「微內核 + 插件擴展」這種設計思想。截止到目前爲止 Hasor-Core、Hasor-Web、Hasor-JDBC 中一同提供了 14 個功能插件。本文收集並整理了 Hasor-Core、Hasor-Web 兩個部分中 11個插件的功能說明以及基本 Demo。 java
這 14 個功能模塊分別在開發的各個方面給予開發人員各類便捷。假如你不想要其中的某個模塊能夠將其禁用掉。這比起 Spring 而言無論有用沒用都引一大堆功能而言要更加貼切,若是你不喜歡這些功能模塊大能夠放棄它們僅僅啓動 Hasor 的內核。這樣你會獲得更輕量的框架,由於 Hasor 的核心實現僅有不到 50 個類文件。 git
這裏是一個基於 Hasor 的 WebDemo 工程,工程中還實現了一個 Hessian 插件。地址:http://git.oschina.net/zycgit/hasor/tree/master/examples/SimpleWeb web
@Before(AopInterceptor_2.class)//類級別攔截器 public class TestBean { @Before(AopInterceptor_1.class)//方法級別攔截器 public String println(String msg) { //受到方法級、類級攔截器影響的方法 return "println->" + msg; } public String foo(String msg) { //只受到類級攔截影響的方法 return "foo->" + msg; } }
該插件會將全部標記了 @Bean 的類經過「ApiBinder.defineBean(...)」
代碼將其註冊到 Hasor 容器中。註冊以後能夠經過「AppContext.getBean」
獲取Bean對象。用過 Spring 的話必定不會陌生。例子: json
@Bean(value = { "name1", "name2" }) public class NamesBean { public void foo() { System.out.println("this bean is name1 or name2 type:" + this); } }
該插件自己並不提供緩存功能,可是爲使用緩存提供了統一的接口。緩存功能
的提供須要實現 CacheCreator 接口並經過標記 @Creator 註解以生效。
使用緩存能夠經過在須要緩存的方法上經過標記 @NeedCache 註解以啓用結果緩存。例子: api
@NeedCache public MenuBean findMenuByCode(String code) { return ...; }
@Creator public class MapCacheCreator implements CacheCreator { private Map<String, Cache> cacheMap = new HashMap<String, Cache>(); public Cache getCacheByName(AppContext appContext, String groupName) { Cache cache = cacheMap.get(groupName); if (cache != null) return cache; cache = new MapCache(); cacheMap.put(groupName, cache); return cache; } } public class MapCache extends HashMap<Serializable, Object> implements Cache { public boolean toCache(Serializable key, Object value) { this.put(key, value); return true; } public Object fromCache(Serializable key) { return this.get(key); } public boolean hasCache(Serializable key) { return this.containsKey(key); } public boolean remove(Serializable key) { super.remove(key); return true; } public boolean clearCache() { super.clear(); return true; } public int size() { return super.size(); } public Set<Serializable> keys() { return super.keySet(); } public void close() { super.clear(); } }
AppContext appContext = ...; /*發送異步事件*/ appContext.getEventManager().doAsyn("EventName", ...);
AppContext appContext = ...; /*發送同步事件*/ appContext.getEventManager().doSync("EventName", ...);
@Listener("EventName") public class Type_B_EventListener implements EventListener { public void onEvent(String event, Object[] params) { System.out.println("Type_B onEvent :" + event + " \t" + Hasor.logString(params)); Thread.sleep(1000); } };
經過 @GuiceModule 註解能夠將任意一個基於 Guice 開發的「com.google.inject.Module」
模塊加入到 Hasor 中做爲 Hasor 的一個模塊。例子: 緩存
@GuiceModule public class GuiceMod implements Module { public void configure(Binder binder) { System.out.println("Hello guice"); } }
(未整理...) restful
經過 @Controller 註解提供了 WebMVC 開發所需的支持。該插件還提供了請求響應攔截器功能。
全部控制器都必需要求繼承自 AbstractController 抽象類,若是某個方法不像被髮布成 action,
能夠經過@ControllerIgnore 註解或者配置「hasor-web.controller.globalIgnore」隱藏它們。例子: mvc
@Controller("/mgr/user") public class UserAction extends AbstractController { @Inject private UserService userService; /*獲取用戶列表,轉發到‘/mgr/user/userList.jsp’*/ @Forword public String userList() { List<UserBean> userList = userService.getUserList(); this.setAttr("userList", userList); return "/mgr/user/userList_mvc1.jsp"; } }
請求地址爲:http://127.0.0.1:8080/mgr/user/userList.do app
經過 @RestfulService 註解發佈 Restful 服務的支持,Hasor 的 restful 參考了 JSR-311。
@Any、@AttributeParam、@CookieParam、@Get、@Head、@HeaderParam、@HttpMethod、@Options、@Path、@PathParam、@Post、@Produces、@Put、@QueryParam 這些註解是由這個插件提供的。例子:
@RestfulService public class MenusRestFul { @Inject private MenuServices menuServices; /*使用重定向轉發*/ @Redirect /*映射 restful 服務地址,並定義一個參數*/ @Path("/mgr/menus/nav/{menuCode}") /*取得並參數,並跳轉到對應的頁面*/ public String menuList(@PathParam("menuCode") String menuCode) { MenuBean menuBean = menuServices.findMenuByCode(menuCode); return (menuBean == null) ? "/mgr" : menuBean.getUrl(); } }
請求地址爲:http://127.0.0.1:8080/mgr/menus/nav/<code>
該插件是 Controller、Result兩個插件的擴展插件,它爲上述兩個插件提供了返回值集處理機制。
@Forword、@Include、@Json、@Redirect 就是它提供的,開發者還能夠本身另外自定義擴展。例子:
@Controller("/action") public class SimpleAction extends AbstractController { @Json public Map<String, Object> json() { HashMap<String, Object> returnData = new HashMap<String, Object>(); returnData.put("data1", true); returnData.put("data2", 123); return returnData; } // @Forword public String forwordTo() { return "/index.htm"; } @Redirect public String redirectTo() { return "http://www.baidu.com"; } }
該插件是用來支持Servlet3.0 規範的軟件包,當 Servlet 容器不支持 Servlet3.0 規範時能夠
經過該插件提供的 @WebFilter、@WebServlet、@WebInitParam 來實現 Servlet3.0。例子:
@WebFilter("/*") public class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("before Servlet. from " + request.getRequestURI()); chain.doFilter(request, response); System.out.println("after Servlet. from " + request.getRequestURI()); } public void destroy() {} }
@WebServlet("showname.c") public class HelloWordServlet extends HttpServlet { @Inject private AppContext appContext = null; protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { CustomerBean infoBean = this.appContext.getInstance(CustomerBean.class); infoBean.foo(); // resp.getWriter().write("Call Servlet showname.c"); super.service(req, resp); } }
經過這個插件能夠將位於ClassPath、Zip等位置中的資源用做 Web 請求響應。插件是以
Servlet 方式提供,開發者須要本身註冊它。例子:
@Plugin public class CustomResources extends AbstractWebHasorPlugin { public void loadPlugin(WebApiBinder apiBinder) { // //js,css,gif,ico,jpg,jpeg,png,swf,swc,flv,mp3,wav,avi apiBinder.serve("*.js").with(ResourceHttpServlet.class); apiBinder.serve("*.css").with(ResourceHttpServlet.class); apiBinder.serve("*.wav").with(ResourceHttpServlet.class); apiBinder.serve("*.avi").with(ResourceHttpServlet.class); // apiBinder.getGuiceBinder().bind(ResourceLoaderFactory.class).toInstance(new ResourceLoaderFactory() { public ResourceLoader[] loaderArray(AppContext appContext) { ResourceLoader classLoader = new ClassPathResourceLoader("/META-INF/webapp"); return new ResourceLoader[] { classLoader }; } }); } }
JDBC 的使用參考:http://my.oschina.net/u/1166271/blog/186940