Rose手册第三章八节:controller层:门户必备pipe支持

rose

3.8.1 什么是pipe? ------------------
* pipe起源于的工程师对他们网页提速的方案:将网页分解为Pagelets的小块(在rose叫做window的小块),然后通过后端多重管道运行,以达到性能的最佳。
* pipe巧妙使用了http 1.1连接有timeout的机制,充分使用一次http连接来传递数据。
* pipe可使用户在大多数浏览器中感受到延迟减少了一半。

3.8.2 与的bigpipe相比rose pipe如何? --------------------------------------------
* fb并未在开源项目中公布过使用方法
* bigpipe神似是php+js搞定的
* rose pipe可以选择线程池大小,完全出自上一节的portal的基础
* 完全实现bigpipe功能,天然的对业务开发者透明

3.8.3 看实例 ------------

HelloController.java

  1. @Get("/3.8")  
  2. public String pipe(Pipe pipe) {  
  3.     pipe.addWindow("p1""/wp1");  
  4.     pipe.addWindow("p2""/wp2");  
  5.     return "pipe";  
  6. }  

* 长得是不是很像上一节里提供的action?
* 不同在于jsp文件中:

  1. <%@ page contentType="text/html;charset=UTF-8"%>  
  2. <%@ taglib uri="http://paoding.net/rose/pipe" prefix="rosepipe"%>  
  3.   
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  5. <html>  
  6. <head>  
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  8. <title>portal/pipe演示信息</title>  
  9. <script type='text/javascript' src='/js/rosepipe.js'></script>  
  10. </head>  
  11. <body>  
  12.   
  13. portal/pipe演示信息:  
  14. <br>  
  15. <div id="p1"></div>  
  16. <br>  
  17. <div id="p2"></div>  
  18.   
  19. </body>  
  20. </html>  
  21. <rosepipe:write>${p1}</rosepipe:write>  
  22. <rosepipe:write>${p2}</rosepipe:write>  

* 当使用jsp文件时,需要在尾部使用rosepipe:write标签
* 如果是使用vm文件,可以不写这个标签

3.8.4 总结 ----------

* 上述代码中p1 p2两个window会同时在多个线程中执行,如果是portal,那会多个线程执行完成一起返回,而pipe则会用js反写的方式,一个线程一个线程地返回给用户。
* pipe是个好物件
* 使用时jsp一定不要忘记尾部的标签
* 使用时web.xml一定不要忘记声明使用的线程池大小
* 久经考验

文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。
常期更新版本在:https://github.com/XiaoMi/rose/tree/master/chapter_3_8

移动互联网必备:各平台自助渠道打包手段公开

mi 移动互联网做app是个酷毙的事情,同等产品条件下比拼的是渠道。怎么样让渠道人员(非技术)快捷地拿到想到的标识有相关渠道信息的包,是个关键的问题。
因为平台不一样,打包手法也不尽相同,下面总结下54chen在工作过程中遇到的问题和解决的办法:

1.android android下无法将一个apk包修改字节流之后apk还重新生效,因为android加key的过程会使这一过程变得无效。
采取的办法:用ant或者maven在对java代码进行build时传入渠道信息。
简单地说:当你有一个xxx渠道的包需要打的时候,后台要做的事情就是 ant -Dchannel=xxx 或者 mvn -U clean package -Dchannel=xxx

2.iphone iphone的正式渠道很少,先说越狱过的:
一个ipa包就是一个标准的zip包,只要在包里放一个channel.txt,保存渠道信息。
简单地说:当你有一个xxx渠道包需要打的时候,后台要做的事情就是打开这个ipa,修改channel.txt的内容为xxx,重新按zip压缩为ipa。

没有越狱过的iphone(占多数):
安装渠道只有一个,那就是appstore。但是推广渠道可能是多个,用户点击后到达appstore,再从appstore下载。这个过程中,ipa包没有办法携带渠道信息,希望apple公司改进。有人用一次跳转记录用户ip,但是不能准确反馈这个渠道的安装量。

3.塞班 sis/sisx的签名比较弱,签好的包,可以在包末尾写入一些字节达到携带渠道信息。
简单地说:当你有一个xxx渠道包需要打的时候,后台要做的事情就是打开这个文件,在最末尾写入xxx,关闭文件。

4.winphone xap包与ipa包极像,不一样的地方在于,xap包在windows下打出来的zip,文件分隔符是反斜线风格,在linux下解压压缩一定要用ant来做不容易写错。
简单地说:当你有一个xxx渠道包需要打的时候,后台要做的事情和iphone一样。不同在于要引入ant.jar。

周末愉快!

Rose手册第三章七节:controller层:门户必备portal支持

rose

3.7.1 什么是portal? --------------------

*字面意思,做门户用的。
*简单来说,把一个网页分成了N个区域,每个区域由不同的action去执行,多线程并行提高cpu使用率。

3.7.2 使用例子 -----------

*要使用portal,必须先在web.xml里声明所使用的线程池大小:

  1. <context-param>  
  2.         <param-name>portalExecutorCorePoolSize</param-name>  
  3.         <param-value>1024</param-value>  
  4. </context-param>  

*然后看示例代码:

  1. @Get("/3.7")  
  2. public String portal(Portal portal) {  
  3.     portal.addWindow("p1""/wp1");  
  4.     portal.addWindow("p2""/wp2");  
  5.     return "portal";  
  6. }  
  7.   
  8. @Get("/wp1")  
  9. public String portal1() {  
  10.     return "@this is p1";  
  11. }  
  12.   
  13. @Get("/wp2")  
  14. public String portal2() {  
  15.     return "@this is p2";  
  16. }  

*然后在第一个action中的portal.jsp中写到:

  1. <%@ page contentType="text/html;charset=UTF-8"%>  
  2. portal演示信息:  
  3. <br>  
  4. ${p1}  
  5. <br>  
  6. ${p2}  

*当我们部属好了之后,访问http://127.0.0.1/3.7
*将从浏览器中得到:
*portal演示信息:
*this is p1
*this is p2

3.7.3 这样子做的好处 --------------------

*更加充分地使用多核cpu。
*更加方便多人协作时对项目进行模块划分,搞的时候,按照url一分,一个url一个模块,>所有的页面都可以切成小的豆腐块,所以,你。

3.7.4 过去的经典事迹 --------------------

* 2010年的6月9日晚上7点"圣战"
* http://www.54chen.com/architecture/rose-open-source-portal-framework.html

[文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。]

常期更新版本在:https://github.com/XiaoMi/rose/tree/master/chapter_3_7

Rose手册第三章六节:controller层:一闪而过的信息,flash支持

rose

3.6.1 需求描述

上,做web的需求时,经常遇到一个情况:在A页面修改/添加/删除了信息,提交,提示“修改/添加/删除成功!”。
rose的flash(并非你所想象的adobe的flash)建设性地使这一需求在开发过程中简单快捷化。 3.6.2 使用过程

使用过程会很愉快,在两个action之间,通过return "r:/xxx"来跳转(实际是301),只需要在第一个action里使用flash.put,在第二个action里使用flash.get即可。

  1. @Get("/flash1")  
  2.   public String flashStep1(Flash flash) {  
  3.       flash.add("msg""修改成功!");  
  4.       return "r:/flash2";  
  5.   }  
  6.   
  7.   @Get("/flash2")  
  8.   public String flashStep2(Invocation inv, Flash flash) {  
  9.       inv.addModel("info", flash.get("msg"));  
  10.       return "flash";  
  11.   }  

上述两个action中,当访问flash1时,一句flash信息被写入,快速跳转到flash2的地址。
flash2地址中接收到这个flash信息后写到model中。
还需要在flash2的模板里去显示这个变量。

提示信息:${info}

3.6.3 注意事项

flash功能利用了浏览器的cookies功能,如果用户的环境不能使用cookies将不会有任何效果。

文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。
文档持续修改版本在 https://github.com/XiaoMi/rose/tree/master/chapter_3_6

Rose手册第三章五节:controller层:统一的参数验证办法

rose 3.5.1 用来做什么 ----------------
* 我们把的参数验证办法叫ParamValidator
* 一般来说,像比如说验证http传来的参数是不是为空呀啥的(发挥你的想象力)。
* 好处在于不用再重复地写if else

3.5.2 怎么用 ------------
* 来看一个例子,验证用户的参数不可为空(灰常灰常的实用):

  1. public class NotBlankParamValidator implements ParamValidator {  
  2.   
  3.     @Override  
  4.     public boolean supports(ParamMetaData metaData) {  
  5.         return metaData.getAnnotation(NotBlank.class) != null;  
  6.     }  
  7.   
  8.     @Override  
  9.     public Object validate(ParamMetaData metaData, Invocation inv, Object target, Errors errors) {  
  10.         String paramName = metaData.getParamName();  
  11.         String value = inv.getParameter(paramName);  
  12.         if (StringUtils.isBlank(value)) {  
  13.             return "@参数不能为空";  
  14.         }  
  15.         return null;  
  16.     }  
  17. }  

解读:

* 放到controllers下
* 实现ParamValidator
* 实现supports方法,这个方法用来做判断是否要验证当前得到的http参数,一般都用个注解来判断比较文艺
* 实现validate方法,这里是主要逻辑
* metaData里放的是参数的原型
* inv是rose的基础调用
* target是这个参数的最后解析结果,参看上一节里提到的东西
* errors是这个参数解析时出来的错误
* NotBlank是一个自己定义的annotation

3.5.3 使用时action长什么样? ----------------------
* 下面的代码是action中使用时长的样子:

  1. @Get("/notBlank")  
  2. public String notBlank(@NotBlank @Param("messages") String messages) throws Exception {  
  3.     return "@hello world";  
  4. }  

解读: * 当遇到NotBlank注解的参数时,会自动执行参数判断
* 如果messages为空,则会得到“参数不能为空”的返回

文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。
文档持续修改版本在 https://github.com/XiaoMi/rose/tree/master/chapter_3_5

Rose手册第三章四节:controller层:自定义http参数支持

rose 3.4.1 http参数支持的一些前言 -----------------------------------------
* 我们把一个controller的类里的一个方法叫做action,它实际对应用户看到的一个url。
* 在action里可以接收各种各样的参数,也可以自己定义需要的参数。
* rose自己定义了一些常见的类型,基本上很有机会会用到自己定义,但是在某些情况下,也是个不错的选择:
* 用来对指定的参数类型的值进行固定的修改和赋值。

3.4.2 看一个例子 --------------------------

ChenBeanResolver.java放在controllers目录下:

  1. public class ChenBeanResolver implements ParamResolver {  
  2.   
  3.     @Override  
  4.     public Object resolve(Invocation inv, ParamMetaData metaData) throws Exception {  
  5.         for (String paramName : metaData.getParamNames()) {  
  6.             if (paramName != null) {  
  7.                 Chen chen = new Chen();  
  8.                 String value1 = inv.getParameter("chen1");  
  9.                 String value2 = inv.getParameter("chen2");  
  10.                 chen.setChen1(value1);  
  11.                 chen.setChen2(value2);  
  12.                 return chen;  
  13.             }  
  14.         }  
  15.         return null;  
  16.   
  17.     }  
  18.   
  19.     @Override  
  20.     public boolean supports(ParamMetaData metaData) {  
  21.         return Chen.class == metaData.getParamType();  
  22.     }  
  23.   
  24. }  

* 上述代码的意思:
* 如果在action里一个参数的类型是Chen(com.chen.model.Chen),就会走这个resolver,这里对两个参数进行了组装。
* 用户如果访问的参数里传入了chen1和chen2的值,则会直接组装出来一个Chen对象。

* 配合上述resolver的action代码为:

  1. @Get("/param")  
  2.    public String param(Chen chen) throws Exception {  
  3.        return "@hello world:" + chen.getChen1() + ":" + chen.getChen2();  
  4.    }  

* 用户访问:http://127.0.0.1/param?chen1=1&chen2=2 将会返回:
** hello world:1:2

3.4.2 rose内置的参数支持 ------------------------------
除了上述的自定义resolver外,rose还内置了丰富的resolver,都是大家的经验总结,使用起来会非常方便,它们是:
* 所有的基础java类型,都可以直接使用,rose进行自动转换,比如在action中的类型为long id,则id可以转为数字,不再需要从string转为long。
* array/map/bean同样可用,它们的接收参数规则为:
* ?id=1,2,3,4 或者 ?id=1&id=2&id=3 对应 @Param("id") int[] idArray
* ?map:1=paoding&map:2=rose 对应 @Param("map") Map map
* POST http://127.0.0.1/user?id=1&name=rose&level.id=3 对应接收代码:

  1. @Post  
  2.  public String post(User user) {  
  3.       return "@" + user.getId() + "; level.id=" + user.getLevel().getId();  
  4.  }  

* 代码中User是一个自定义的bean,有属性id,name,level等。

文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。
文档持续修改版本在 https://github.com/XiaoMi/rose/tree/master/chapter_3_4