这篇是承接《》系列Blog文的后续文章,本文将介绍 Hasor 内部主要插件并附带插件的功能描述和简单使用 Demo。
Hasor 使用的是“微内核 + 插件扩展”这种设计思想。截止到目前为止 Hasor-Core、Hasor-Web、Hasor-JDBC 中一同提供了 14 个功能插件。本文收集并整理了 Hasor-Core、Hasor-Web 两个部分中 11个插件的功能说明以及基本 Demo。
这 14 个功能模块分别在开发的各个方面给予开发人员各种便捷。假如你不想要其中的某个模块可以将其禁用掉。这比起 Spring 而言不管有用没用都引一大堆功能而言要更加贴切,如果你不喜欢这些功能模块大可以放弃它们仅仅启动 Hasor 的内核。这样你会得到更轻量的框架,因为 Hasor 的核心实现仅有不到 50 个类文件。
这里是一个基于 Hasor 的 WebDemo 工程,工程中还实现了一个 Hessian 插件。地址:
Hasor-Core 软件包
Aop 插件
通过 @Aop、@GlobalAop 两个注解提供声明 Aop 切面。@Aop 可以标记到 方法或类上,根据标记的位置来决定 Aop 切面作用的范围。@GlobalAop 注解 是标记到拦截器上的,用于配置全局拦截器,拦截范围可以通过注解进行配置。 支持表达式配置;支持 Aop 链。 例子:@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 插件
该插件会将所有标记了 @Bean 的类通过“ApiBinder.defineBean(...)”
代码将其注册到 Hasor 容器中。注册之后可以通过“AppContext.getBean” 获取Bean对象。用过 Spring 的话一定不会陌生。例子:@Bean(value = { "name1", "name2" })public class NamesBean { public void foo() { System.out.println("this bean is name1 or name2 type:" + this); }}
Cache 插件
该插件本身并不提供缓存功能,但是为使用缓存提供了统一的接口。缓存功能 的提供需要实现 CacheCreator 接口并通过标记 @Creator 注解以生效。 使用缓存可以通过在需要缓存的方法上通过标记 @NeedCache 注解以启用结果缓存。例子:
@NeedCachepublic MenuBean findMenuByCode(String code) { return ...;}
@Creatorpublic class MapCacheCreator implements CacheCreator { private MapcacheMap = new HashMap (); 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 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 keys() { return super.keySet(); } public void close() { super.clear(); }}
Event 插件
通过标记 @Listener 注解声明一个 “net.hasor.core.EventListener”类型的 事件监听器。通过“EventManager.doSync or .doAsync”可以引发事件。 Hasor 中事件的处理分为同步(Sync)和异步(Async)。例子: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); }};
Guice 插件
通过 @GuiceModule 注解可以将任意一个基于 Guice 开发的“com.google.inject.Module”
模块加入到 Hasor 中作为 Hasor 的一个模块。例子:@GuiceModulepublic class GuiceMod implements Module { public void configure(Binder binder) { System.out.println("Hello guice"); }}
Setting 插件
通过 @Settings 注解声明一个配置文件改变监听器。Hasor 在启动之后会持续 监听配置文件是否改变,如发生改变 Hasor 会自动重载它。标记了 @Settings 注解的 SettingsListener监听器会收到这个通知。例子:(未整理...)
Hasor-Web 软件包
Controller 插件
通过 @Controller 注解提供了 WebMVC 开发所需的支持。该插件还提供了请求响应拦截器功能。
所有控制器都必须要求继承自 AbstractController 抽象类,如果某个方法不像被发布成 action, 可以通过@ControllerIgnore 注解或者配置“hasor-web.controller.globalIgnore”隐藏它们。例子:@Controller("/mgr/user")public class UserAction extends AbstractController { @Inject private UserService userService; /*获取用户列表,转发到‘/mgr/user/userList.jsp’*/ @Forword public String userList() { ListuserList = userService.getUserList(); this.setAttr("userList", userList); return "/mgr/user/userList_mvc1.jsp"; }}
请求地址为:http://127.0.0.1:8080/mgr/user/userList.do
Restful 插件
通过 @RestfulService 注解发布 Restful 服务的支持,Hasor 的 restful 参考了 JSR-311。
@Any、@AttributeParam、@CookieParam、@Get、@Head、@HeaderParam、@HttpMethod、@Options、@Path、@PathParam、@Post、@Produces、@Put、@QueryParam 这些注解是由这个插件提供的。例子:@RestfulServicepublic 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>
Result 插件
该插件是 Controller、Result两个插件的扩展插件,它为上述两个插件提供了返回值集处理机制。
@Forword、@Include、@Json、@Redirect 就是它提供的,开发者还可以自己另外自定义扩展。例子:@Controller("/action")public class SimpleAction extends AbstractController { @Json public Mapjson() { HashMap returnData = new HashMap (); 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 插件
该插件是用来支持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); }}
Resource 插件
通过这个插件可以将位于ClassPath、Zip等位置中的资源用作 Web 请求响应。插件是以
Servlet 方式提供,开发者需要自己注册它。例子:@Pluginpublic 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 }; } }); }}
Hasor-JDBC 软件包
JDBC 的使用参考: