Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15843 articles
Browse latest View live

亚马逊入驻自贸区将改变什么?境外代购哪种更省钱?

$
0
0

8 月 20 日, 亚马逊宣布将入驻自贸区的消息在国内外引发了广泛讨论,同时也将海淘、境外代购推上了风口浪尖。事实上,真正参与海淘、境外代购的人数仅占普通消费人群的极小部分,但随着全球市场的不断发展,跨境购物势必将成为不可避免的大趋势。那么,亚马逊入驻自贸区到底意味着什么,它与海淘、境外代购之间又有着什么样的区别?作为普通消费者的我们,应该做何选择呢?


亚马逊入驻自贸区:开启全新跨境购物模式

在亚马逊正式入驻自贸区之前,国人跨境购物主要有两种形式,一是海淘,一是境外代购。海淘是消费者亲自上境外购物网站(例如美亚、eBay)购买商品,并委托转运公司将商品邮回国内;境外代购则是委托在境外的他人为自己购买商品(例如淘宝的 全球购)并邮寄回国。尽管两者的渠道不同,但都是由于购物不便、省钱、对国内产品质量不信任等原因而产生。

而亚马逊入驻自贸区,便意味着我们有了一种全新的、官方认可的跨境购物方式。它将包括两种模式:一是 直邮,即商品在境外,亚马逊通过国际物流直接将其送到消费者手中;二是 自贸区仓储模式,即亚马逊在自贸区内建立境外商品仓库,商品的运送通过自有物流完成。总体看来,直邮模式将作为亚马逊在初期的主要方式,而未来,自贸区仓储模式则会成为主流。毕竟,亚马逊在上海自贸区设立的可不只是仓库,更是国际贸易总部,它将成为亚马逊全球业务的中心所在。


那么,海淘、境外代购以及未来的亚马逊跨境购物模式到底有什么不同呢?我们用一张图来让大家更直观清晰的看到整个购物流程:

从上图可以看到,亚马逊跨境购物优势在于它将大大缩短物流时间,也不用操心物品在运输途中损坏、赔偿的问题,更不必担忧它可能会被海关查税、甚至扣押。当然,这也意味着你不可避免的需要付出一些行邮税,而这些税费将根据你的商品品类和价值来收取。与之相比,海淘与境外代购的优势,则是可能避免掉税务上的支出,且在当下看来,实际被抽税的商品也并不算多。

关于“行邮税”:指海关对入境旅客行李物品和个人邮递物品征收的进口税。

长远来看,全球市场的商品价格差异终将逐渐缩小,而国内高昂的税率也并不一定会永久存在,所以我们尝试着排除掉价格和不可控的税务因素,只是把购物的安全与便捷性作为考量标准,对上述几种跨境购物模式做了一个比较:

无疑, 亚马逊自贸区仓储模式将是最为安全、便捷的,事实上就像直接通过中国亚马逊购物一样;与之相比, 亚马逊直邮模式则需耗费更多时间(根据官方测试来看,从美国直邮中国,大约需要 7-10 天),且由于直邮多采用空运,在邮费方面的负担也会更大,加上商品运输时间越长,安全性自然也会降低。

再看看当下我们常用的海淘与境外代购模式:选择 海淘,意味着我们不得不让商品通过转运公司来邮递,增加的一层运输过程将带来商品的安全保障降低、费用增加等可能存在的问题,并且往往需要等上一个月才可能收到商品;选择 境外代购,则必须给代购人支付一定的“辛苦费”,代购服务水平、商品的物流渠道与运输时长更是参差不齐。如此看来,海淘与境外代购在购物安全和便捷性方面的存在着不少不可控的问题,而两者在价格方面的优势,也意味着还需面临海关抽税、扣押的风险。


如何聪明的跨境购物?

据悉,亚马逊入驻自贸区后,并不打算搞价格战,所有商品都将按照商品品类与售价收取相应的行邮税。依据中国海关总署的 相关规定,行邮税分为 10%、20%、30%、50% 四档税率,详细的划分可以看看下图:

值得一提的是,凡是税费在 50 元以下的,可直接减免。至于最终实施的细则,无论是亚马逊还是自贸区方面,都暂未作出回应。

这里,我们回到一开始的话题:境外代购哪种更省钱: 当需要购买一些日常生活用品时,通过亚马逊跨境购物渠道完成,既快又安全,并且能尽可能的避免和节省税费; 当需要购买稍贵一些的数码、家电类产品时,则可以考虑在海淘与亚马逊跨境购物渠道间进行对比, 倘若愿意接受亚马逊跨境渠道需要多支付的金额,来保证商品的安全性(尤其数码类),则不妨选择从自贸区拿货或是直邮当购买的商品已是高端腕表、化妆品等高税率级别(30-50%),海淘或许会是一个更为经济省钱的方式(即便被海关抽税,税费也可能相差不多),这时你需要的将是找一家靠谱的转运公司来保障物品的安全;而 当你需要购买一些限量的、非亚马逊商品时,代购或许能帮助你更多


总的来说,尽管亚马逊跨境购物渠道尚未正式开启,但其影响力已经开始显现。它天生具备的方便、快速、安全优势将改变当下跨境购物格局,让更多的消费者参与进来,去消费和挑选更好更满意的商品。同时,也可能促进国内海淘与境外代购市场的规范与转型。

我们认为,未来的海淘将变得更为系统化、专业化,在细分市场下有针对性的发展下去;而境外代购党们,也将经历一次大浪淘沙,那些靠着赚差价过活的代购人将很难再维持,而真正活下来的则会走向小众与精品化,从普通代购转型为买手,为国内消费者提供更多精致限量的、一定要加入人的审美眼光才能买到的商品。


android回调函数总结

$
0
0
android回调函数总结

回调函数就是那些自己写的,但是不是自己来调,而是给别人来掉的函数。

消息响应函数就可以看成是回调函数,因为是让系统在合适的时候去调用。这不过消息响应函数就是为了处理消息的,
所以就拿出来单做一类了。其实本质上就是回调函数。

但是回调函数不是只有消息响应函数一种,比如在内核编程中,驱动程序就要提供一些回调函数,
当一个设备的数据读写完成后,让系统调用这些回调函数来执行一些后续工作。

回调函数赋予程序员这样一种能力,让自己编写的代码能够跳出正常的程序控制流,
适应具体的运行环境在正确的时间执行。

回调函数总结

别人给回调的定义:

所谓回调,就是对象A调用另一对象B中的某个方法b,然后B又在某个时候反过来调用A中的某个函数c,对于B来说,这个c便叫做回调函数。
回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口.



我的理解, 和一般的类之间的组合类似。就只是A对象调用B对象的一个方法b。只不过方法b是抽象的,是后期绑定的。



java回调代码。

    1,定义回调接口。
复制代码

package  com.smart;  
/**  
* 定义回调接口  
*/   
public   interface  CallBack {  
    void  execute();  
}  






package com.smart;  
/** 
* 定义回调接口 
*/ 
public interface CallBack {  
    void execute();  










package  com.smart;  
/**  
* 工具类  
*/   
public   class  Tools {  
    public   void  test(CallBack callBack){  
        long  begin = System.currentTimeMillis(); //测试起始时间      
        callBack.execute();///进行回调操作      
        long  end = System.currentTimeMillis(); //测试结束时间      
        System.out.println("[use time]:"  + (end - begin)); //打印使用时间      
  
    }  
    public   static   void  main(String[] args){  
        Tools tools = new  Tools();  
        tools.test(new  CallBack(){  
            public   void  execute() {  
                //A.method();  测试类A的某个方法执行的时间   
                //B.method();  测试类B的某个方式执行的时间   
                System.out.print("回调" );  
            }  
        });  
    }  
}  















package com.smart;  
/** 
* 工具类 
*/ 
public class Tools {  
    public void test(CallBack callBack){  
        long begin = System.currentTimeMillis();//测试起始时间     
        callBack.execute();///进行回调操作     
        long end = System.currentTimeMillis();//测试结束时间     
        System.out.println("[use time]:" + (end - begin));//打印使用时间     
 
    }  
    public static void main(String[] args){  
        Tools tools = new Tools();  
        tools.test(new CallBack(){  
            public void execute() {  
                //A.method();  测试类A的某个方法执行的时间  
                //B.method();  测试类B的某个方式执行的时间  
                System.out.print("回调");  
            }  
        });  
    }  

















   优点:我个人认为优点主要是将代码中变与不变的部分相分离,从而大大提高了程序的重用性和扩展性。

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



约架完毕,罗永浩扒下测评行业的底裤

$
0
0

经过几周的预热和三个多小时唇枪舌剑,罗永浩、王自如的吵架终于完毕。锤子确实又制造了一个新热点。Zealer也得到了宣传,不过这个宣传的效果恐怕是王自如始料未及的。

这个关注度很高的视频,让评测的一些黑幕公之于众,未必不是一件好事,只是Zealer 团队的公信力就会被质疑了。

一、互联网评测的乱象

其实,早期有评测的不是智能手机,而是电脑,最早的评测是在服务器上,为了评估服务器的性能有人专门写软件,是为了实际应用。后来PC进入家庭,也就有了相应的PC类评测软件。今天手机上的评测软件,很多前身就是PC上的评测软件。

有个评测工具以后,就有了对产品的评测。现在的汽车之家老板李想,当年做的网站叫显卡之家,后来改名叫PCPOP。在飞翔鸟之后,和小熊在线,Gzeasy、ZOL、Pconline都算是知名的网站。

应该说早年这些评测都是有一定水平的,Gzeasy的CHO甚至可以与芯片厂商的技术人员直接讨论技术细节问题,就差自己设计GPU了。

后来进入智能手机时代,各种爱好者自媒体出现,评测就变了。以前的媒体网站成立没有那么容易,早期甚至还要挂靠一个正规单位,有上级部门,不能乱来。

而新时代自媒体都是自己来,没有管理者,本身对产品的理解就是爱好者水平。更关键是没有管理、唯利是图,甚至给厂商利用当工具,这就乱了。

二、Zealer的问题

Zealer 初期是王自如作为一个爱好者的个人评测。做评测的很多,有的网站明码标价收评测费,有的爱好者只要求提供测试机,但是无论什么方式,各个厂商都应该一视同仁,你给我测试机,我给你出评测,优点缺点都说到,语气用词可以尽量不得罪你。

目前来看,Zealer 所做的已经不仅仅只是个发烧友,它需要盈利。所以玩的就有点出圈了。一方面标明自己公正、客观、独立、第三方,一方面拿厂家的咨询费,拿厂家的投资;一方面要建立评测标准,一方面标准是个黑箱,得分和表现完全对不起来,不可重复,不可验证。

这次被罗永浩吊打,根本原因还是收了锤子的咨询费不干活,反而替给钱更多的出力倒打一耙。这都能忍就不是罗永浩了。谁给钱,就帮谁打击竞争对手,甚至已经交了保护费的也不放过。

其实,我个人也不喜欢罗永浩的风格,对锤子产品本身也不好看,也写过一些文章分析问题。罗永浩看过,但只是让他的公关经理做技术上澄清,把商榷之处提出来,把确认的地方反馈给开发人员。

有网站也做锤子的跌落测试,锤子并没有做任何干预。

其实原因也很简单,某网站没拿锤子和其他厂商一分钱投资,测试用的锤子手机是自己花钱买的。而Zealer 是拿过小米等厂商投资,还拿了锤子咨询费的。

一段时间,Zealer 是被厂商投资的,也就是罗永浩说的被包养。经济不独立,人格难免被怀疑。

三、媒体应该有良心

辩论会后,某网站主编发博客,“我也想要有人投资,我也喜欢有人养我,我也收车马费。面对金主,我的原则是:我可以大量夸赞你优秀的地方,我可以对你的缺陷闭口不提,但是我真心做不到把你的缺陷包装成优点去夸赞。”

我个人认为,这个标准不算高,应该是缺点必须要提,但是注意语气婉转。绝口不提对消费者也会构成误导。

收钱了说好话,也说坏话,是良心;收了钱只说好话,不说坏话,是本分;收了钱,只替收钱的说话,打击没给钱的,甚至给钱少的也不放过,是黑社会,还是不讲规矩的那种。

希望这次罗永浩和王自如的辩论,能让不讲规矩的黑社会少一点。

Spring MVC 3 深入总结

$
0
0

一、前言:

大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了。Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀。

官方的下载网址是: http://www.springsource.org/download   (本文使用是的Spring 3.0.5版本)

 

Struts2也是比较优秀的MVC构架,优点非常多比如良好的结构。但这里想说的是缺点,Struts2由于采用了值栈、OGNL表达式、struts2标签库等,会导致应用的性能下降。Struts2的多层拦截器、多实例action性能都很好。可以参考我写的一篇关于Spring MVC与Struts2与Servlet比较的文章  http://elf8848.iteye.com/admin/blogs/698217

 

Spring3 MVC的优点:

1、Spring3 MVC的学习难度小于Struts2,Struts2用不上的多余功能太多。呵呵,当然这不是决定因素。

2、Spring3 MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)

3、Spring3 MVC的灵活是你无法想像的,Spring的扩展性有口皆碑,Spring3 MVC当然也不会落后,不会因使用了MVC框架而感到有任何的限制。

 

Struts2的众多优点:略...   (呵呵,是不是不公平?)

 

众多文章开篇时总要吹些牛,吸引一下读者的眼球,把读者的胃口调起来,这样大家才有兴趣接着往后看。本文也没能例外。不过保证你看了之后不会后悔定有收获。

 

 

二、核心类与接口:

 

先来了解一下,几个重要的接口与类。现在不知道他们是干什么的没关系,先混个脸熟,为以后认识他们打个基础。

 

DispatcherServlet   -- 前置控制器

 

HandlerMapping接口 -- 处理请求的映射

HandlerMapping接口的实现类:

SimpleUrlHandlerMapping  通过配置文件,把一个URL映射到Controller

DefaultAnnotationHandlerMapping  通过注解,把一个URL映射到Controller类上

 

HandlerAdapter接口 -- 处理请求的映射

AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

 

Controller接口 -- 控制器

由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,

所以我们并没有用到这个接口。

 

 

 

HandlerInterceptor 接口--拦截器

无图,我们自己实现这个接口,来完成拦截的器的工作。

 

 

ViewResolver接口的实现类

UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理

InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

 

View接口

JstlView类

 

LocalResolver接口

 

HandlerExceptionResolver接口 --异常处理

SimpleMappingExceptionResolver实现类

 

 

ModelAndView类

无图。

 

 

 

 

 

三、核心流程图

 

本图是我个人画的,有不严谨的地方,大家对付看吧。总比没的看强。

 

 

 


四、DispatcherServlet说明

 

使用Spring MVC,配置DispatcherServlet是第一步。

DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。

DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。

 

“某某规则”:是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。

 

先来看第一个例子:

Xml代码 
  1. <web-app>  
  2.      <servlet>  
  3.          <servlet-name>example </servlet-name>  
  4.          <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>  
  5.          <load-on-startup>1 </load-on-startup>  
  6.      </servlet>  
  7.      <servlet-mapping>  
  8.          <servlet-name>example </servlet-name>  
  9.          <url-pattern>*.form </url-pattern>  
  10.      </servlet-mapping>  
  11. </web-app>  

 <load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servletp容器一起启动。

 <url-pattern>*.form</url-pattern> 会拦截*.form结尾的请求。

 

 <servlet-name>example</servlet-name>这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中,关于key,以后说明。

 

在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。

 

 

第二个例子:

Xml代码 
  1. <servlet>  
  2.      <servlet-name>springMVC </servlet-name>  
  3.      <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>  
  4.      <init-param>  
  5.          <param-name>contextConfigLocation </param-name>  
  6.          <param-value>classpath*:/springMVC.xml </param-value>  
  7.      </init-param>  
  8.      <load-on-startup>1 </load-on-startup>  
  9. </servlet>  
  10. <servlet-mapping>  
  11.      <servlet-name>springMVC </servlet-name>  
  12.      <url-pattern>/ </url-pattern>  
  13. </servlet-mapping>  

指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。

其中<param-value>**.xml</param-value> 这里可以使用多种写法
1、不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
3、<param-value>classpath*:springMVC-mvc.xml</param-value>
4、多个值用逗号分隔

 


Servlet拦截匹配规则可以自已定义,Servlet拦截哪种URL合适? 

当映射为@RequestMapping("/user/add")时:
1、拦截*.do,例如:/user/add.do,弊端:所有的url都要以.do结尾。不会影响访问静态文件。
2、拦截/app/*,例如:/app/user/add,弊端:请求的url都要包含/app,@RequestMapping("/user/add")中不须要包含/app。
3、拦截/,例如:/user/add,弊端:对jpg,js,css静态文件的访问也被拦截不能正常显示。后面有解决办法。
4、拦截/*,可以走到Action中,但转发到jsp时再次被拦截,不能访问到jsp。

 

 

五、双亲上下文的说明

 

如果你使用了listener监听器来加载配置,一般在Struts+Spring+Hibernate的项目中都是使用listener监听器的。如下

Java代码 
  1. <listener>   
  2.   <listener- class>org.springframework.web.context.ContextLoaderListener</listener- class>   
  3. </listener>   

Spring会创建一个全局的WebApplicationContext上下文,称为 根上下文 ,保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性的值。可以使用工具类取出上下文:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

 

DispatcherServlet是一个Servlet,可以同时配置多个,每个 DispatcherServlet有一个自己的 WebApplicationContext上下文,这个上下文继承了  根上下文 中所有东西。 保存在 ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一个Request对象产生时,会把这个WebApplicationContext上下文保存在Request对象中,key是DispatcherServlet.class.getName() + ".CONTEXT"。可以使用工具类取出上下文:RequestContextUtils.getWebApplicationContext(request);

 

Spring中的 ApplicationContext实例可以被限制在不同的作用域(scope)中。
在web MVC框架中,每个 DispatcherServlet有它自己的WebApplicationContext ,这个context继承了根 WebApplicationContext 的所有bean定义。
这些继承的bean也可以在每个serlvet自己的所属的域中被覆盖(override),覆盖后的bean 可以被设置上只有这个servlet实例自己使用的属性。

 

总结:不使用listener监听器来加载spring的配置,改用DispatcherServlet来加载spring的配置,不要双亲上下文,只使用一个DispatcherServlet,事情就简单了,什么麻烦事儿也没有了。

 

 

六、springMVC-mvc.xml 配置文件片段讲解 (未使用默认配置文件名)

 

Xml代码 
  1.    <!-- 自动扫描的包名 -->  
  2.     <context:component-scan base-package="com.app,com.core,JUnit4"  ></context:component-scan>  
  3.      
  4.    <!-- 默认的注解映射的支持 -->  
  5.     <mvc:annotation-driven  />  
  6.      
  7.    <!-- 视图解释类 -->  
  8.     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >  
  9.      <property name="prefix" value="/WEB-INF/jsp/" />  
  10.      <property name="suffix" value=".jsp" /><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->  
  11.      <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"  />  
  12.     </bean>  
  13.      
  14. <!-- 拦截器 -->  
  15.     <mvc:interceptors>  
  16.      <bean class="com.core.mvc.MyInteceptor"  />  
  17. </mvc:interceptors>       
  18.   
  19.     <!-- 对静态资源文件的访问  方案一 (二选一) -->  
  20.      <mvc:default-servlet-handler/>  
  21.       
  22.     <!-- 对静态资源文件的访问  方案二 (二选一)-->  
  23. <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926" />  
  24. <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926" />  
  25. <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926" />  

 

<context:component-scan/> 扫描指定的包中的类上的注解,常用的注解有:

@Controller 声明Action组件
@Service    声明Service组件    @Service("myMovieLister") 
@Repository 声明Dao组件
@Component   泛指组件, 当不好归类时. 
@RequestMapping("/menu")  请求映射
@Resource  用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName") 
@Autowired 用于注入,(srping提供的) 默认按类型装配 
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype")   设定bean的作用域

 

<mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。
并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
后面,我们处理响应ajax请求时,就使用到了对json的支持。
后面,对action写JUnit单元测试时,要从spring IOC容器中取DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,来完成测试,取的时候要知道是<mvc:annotation-driven />这一句注册的这两个bean。

 

<mvc:interceptors/> 是一种简写形式。通过看前面的大图,知道,我们可以配置多个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也可以手动配置为每个HandlerMapping注入一个拦截器。

 

<mvc:default-servlet-handler/> 使用默认的Servlet来响应静态文件。

 

<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> 匹配URL  /images/**  的URL被当做静态资源,由Spring读出到内存中再响应http。

 

 
七、如何访问到静态的文件,如jpg,js,css?

 

如何你的 DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题。如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg的访问也就被拦截了。

 

目的:可以正常访问静态文件,不要找不到静态文件报404。
 
方案一:激活Tomcat的defaultServlet来处理静态文件

Xml代码 
  1. <servlet-mapping>   
  2.      <servlet-name>default </servlet-name>  
  3.      <url-pattern>*.jpg </url-pattern>     
  4. </servlet-mapping>    
  5. <servlet-mapping>       
  6.      <servlet-name>default </servlet-name>    
  7.      <url-pattern>*.js </url-pattern>    
  8. </servlet-mapping>    
  9. <servlet-mapping>        
  10.      <servlet-name>default </servlet-name>       
  11.      <url-pattern>*.css </url-pattern>      
  12. </servlet-mapping>    
  13. 要配置多个,每种文件配置一个   

要写在DispatcherServlet的前面, 让 defaultServlet先拦截,这个就不会进入Spring了,我想性能是最好的吧。

 

Tomcat, Jetty, JBoss, and GlassFish  默认 Servlet的名字 -- "default"
Google App Engine 默认 Servlet的名字 -- "_ah_default"
Resin 默认 Servlet的名字 -- "resin-file"
WebLogic 默认 Servlet的名字  -- "FileServlet"
WebSphere  默认 Servlet的名字 -- "SimpleFileServlet" 

 

 


方案二: 在spring3.0.4以后版本提供了mvc:resources 
mvc:resources 的使用方法:

Xml代码 
  1. <!-- 对静态资源文件的访问 -->    
  2. <mvc:resources mapping="/images/**" location="/images/"  />  

  
/images/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache 
 
如果出现下面的错误,可能是没有配置<mvc:annotation-driven />的原因。 
报错WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

 

使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,
key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,
这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问.
另外需要注意的一点是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对static uri的defaultHandler就是ResourceHttpRequestHandler,
否则无法处理static resources request.

 

 

方案三 ,使用<mvc:default-servlet-handler/>

 

Xml代码 
  1. <mvc:default-servlet-handler/>  

 

会把"/**" url,注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的访问由HandlerMapping转到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler处理并返回.
DefaultServletHttpRequestHandler使用就是各个Servlet容器自己的默认Servlet.

 

 

补充说明:多个HandlerMapping的执行顺序问题:

DefaultAnnotationHandlerMapping的order属性值是:0

<mvc:resources/ >自动注册的 SimpleUrlHandlerMapping的order属性值是: 2147483646

 

<mvc:default-servlet-handler/>自动注册 的SimpleUrlHandlerMapping 的order属性值是: 2147483647

 

spring会先执行order值比较小的。当访问一个a.jpg图片文件时,先通过 DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,我们没有叫a.jpg的Action。再 按order值升序找,由于最后一个 SimpleUrlHandlerMapping 是匹配 "/**"的,所以一定会匹配上,再响应图片。

 

访问一个图片,还要走层层匹配。真不知性能如何?改天做一下压力测试,与Apache比一比。

 

最后再说明一下,如何你的 DispatcherServlet拦截 *.do这样的URL,就不存上述问题了。

 

 


八、请求如何映射到具体的Action中的方法?
方案一:基于xml配置映射,可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping进行Url映射和拦截请求。
配置方法略。
 
方案二:基于注解映射,可以使用DefaultAnnotationHandlerMapping。

Xml代码 
  1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" >   </bean>   

 

但前面我们配置了<mvc:annotation-driven />,他会自动注册这个bean,就不须要我们显示的注册这个bean了。  

 

 
以上都可以注入interceptors,实现权限控制等前置工作。
我们使用第2种,基于注解来使用spring MVC

 

 

 并在action类上使用:
@Controller
@RequestMapping("/user")
 
 
 
九、Spring中的拦截器:
Spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口,

org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,
实现这个接口或继承此类,可以非常方便的实现自己的拦截器。
 
有以下三个方法:
 
Action之前执行:
 public boolean preHandle(HttpServletRequest request,
   HttpServletResponse response, Object handler);
 
生成视图之前执行
 public void postHandle(HttpServletRequest request,
   HttpServletResponse response, Object handler,
   ModelAndView modelAndView);
 
最后执行,可用于释放资源
 public void afterCompletion(HttpServletRequest request,
   HttpServletResponse response, Object handler, Exception ex)
 
 
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面) 
在preHandle中,可以进行编码、安全控制等处理; 
在postHandle中,有机会修改ModelAndView; 
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。 
参数中的Object handler是下一个拦截器。
 


十、如何使用拦截器?
自定义一个拦截器,要实现HandlerInterceptor接口:

Java代码 
  1. public  class MyInteceptor  implements HandlerInterceptor {     
  2.     略。。。  
  3. }    

 

Spring MVC并没有总的拦截器,不能对所有的请求进行前后拦截。
Spring MVC的拦截器,是属于HandlerMapping级别的,可以有多个HandlerMapping ,每个HandlerMapping可以有自己的拦截器。
当一个请求按Order值从小到大,顺序执行HandlerMapping接口的实现类时,哪一个先有返回,那就可以结束了,后面的HandlerMapping就不走了,本道工序就完成了。就转到下一道工序了。
拦截器会在什么时候执行呢? 一个请求交给一个HandlerMapping时,这个HandlerMapping先找有没有处理器来处理这个请求,如何找到了,就执行拦截器,执行完拦截后,交给目标处理器。
如果没有找到处理器,那么这个拦截器就不会被执行。

 


在spring MVC的配置文件中配置有三种方法:


方案一,(近似)总拦截器,拦截所有url

Java代码 
  1.    <mvc:interceptors>  
  2.     <bean  class="com.app.mvc.MyInteceptor" />  
  3. </mvc:interceptors>  

为什么叫“近似”,前面说了,Spring没有总的拦截器。

<mvc:interceptors/>会为每一 个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是可以找到处理器的,最多也只找到一个处理器,所以这个拦截器总会被执行的。起到了总拦截器的作用。

 

 
方案二, (近似) 总拦截器, 拦截匹配的URL。

Xml代码 
  1. <mvc:interceptors  >    
  2.    <mvc:interceptor>    
  3.          <mvc:mapping path="/user/*"  /> <!-- /user/*  -->    
  4.          <bean class="com.mvc.MyInteceptor" ></bean>    
  5.      </mvc:interceptor>    
  6. </mvc:interceptors>    

就是比 方案一多了一个URL匹配。

 

 

 

方案三,HandlerMappint上的拦截器

Xml代码 
  1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" >       
  2.   <property name="interceptors" >       
  3.       <list>       
  4.           <bean class="com.mvc.MyInteceptor" ></bean>      
  5.       </list>       
  6.   </property>       
  7. </bean>   

  如果使用了<mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。

当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。

 

其实我也不建议使用<mvc:annotation-driven />,而建议手动写配置文件,来替代 <mvc:annotation-driven />,这就控制力就强了。

 

 

 

 

十一、如何实现全局的异常处理?

在spring MVC的配置文件中:

Xml代码 
  1. <!-- 总错误处理-->  
  2. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" >  
  3.      <property name="defaultErrorView" >    
  4.          <value>/error/error </value>  
  5.      </property>  
  6.      <property name="defaultStatusCode" >    
  7.          <value>500 </value>  
  8.      </property>     
  9. <property name="warnLogCategory" >    
  10.          <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver </value>  
  11.      </property>     
  12. </bean>   

 

这里主要的类是SimpleMappingExceptionResolver类,和他的父类AbstractHandlerExceptionResolver类。

具体可以配置哪些属性,我是通过查看源码知道的。

你也可以实现HandlerExceptionResolver接口,写一个自己的异常处理程序。spring的扩展性是很好的。

 

 

通过SimpleMappingExceptionResolver我们可以将不同的异常映射到不同的jsp页面(通过exceptionMappings属性的配置)。

 

同时我们也可以为所有的异常指定一个默认的异常提示页面(通过defaultErrorView属性的配置),如果所抛出的异常在exceptionMappings中没有对应的映射,则Spring将用此默认配置显示异常信息。

注意这里配置的异常显示界面均仅包括主文件名,至于文件路径和后缀已经在viewResolver中指定。如/error/error表示/error/error.jsp

 

 

显示错误的jsp页面:

Html代码 
  1. <%@ page language="java" contentType="text/html; charset=GBK"  
  2.     pageEncoding="GBK"% >  
  3. <%@ page import="java.lang.Exception"% >  
  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=GBK" >  
  8. <title>错误页面 </title>  
  9. </head>  
  10. <body>  
  11. <h1>出错了 </h1>  
  12. <%  
  13. Exception e = (Exception)request.getAttribute("exception");  
  14. out.print(e.getMessage());  
  15. % >  
  16. </body>  
  17. </html>  

其中一句:request.getAttribute("exception"),key是exception,也是在SimpleMappingExceptionResolver类默认指定的,是可能通过配置文件修改这个值的,大家可以去看源码。

 

 参考文章:

http://www.blogjava.net/wuxufeng8080/articles/191150.html

http://fangjunai.blog.163.com/blog/static/1124970520108102013839/

 

 

 

十二、如何把全局异常记录到日志中?

在前的配置中,其中有一个属性warnLogCategory,值是“SimpleMappingExceptionResolver类的全限定名”。我是在SimpleMappingExceptionResolver类父类AbstractHandlerExceptionResolver类中找到这个属性的。查看源码后得知:如果warnLogCategory不为空,spring就会使用apache的org.apache.commons.logging.Log日志工具,记录这个异常,级别是warn。

值:“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”,是“SimpleMappingExceptionResolver类的全限定名”。这个值不是随便写的。  因为我在log4j的配置文件中还要加入log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN,保证这个级别是warn的日志一定会被记录,即使log4j的根日志级别是ERROR。

 

 

 

 

  十三、如何给spring3 MVC中的Action做JUnit单元测试?

 使用了spring3 MVC后,给action做单元测试也很方便,我以前从来不给action写单元测试的,再在不同了,方便了,所以一定要写。

 

 JUnitActionBase类是所有JUnit的测试类的父类

 

Java代码 
  1. package test;  
  2. import javax.servlet.http.HttpServletRequest;  
  3. import javax.servlet.http.HttpServletResponse;  
  4. import org.junit.BeforeClass;  
  5. import org.springframework.mock.web.MockServletContext;  
  6. import org.springframework.web.context.WebApplicationContext;  
  7. import org.springframework.web.context.support.XmlWebApplicationContext;  
  8. import org.springframework.web.servlet.HandlerAdapter;  
  9. import org.springframework.web.servlet.HandlerExecutionChain;  
  10. import org.springframework.web.servlet.HandlerMapping;  
  11. import org.springframework.web.servlet.ModelAndView;  
  12. import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;  
  13. import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;  
  14. /**  
  15. * 说明: JUnit测试action时使用的基类 
  16. *  
  17. * @author  Kipa
  18. * @version 创建时间:2011-2-2 下午10:27:03   
  19. */   
  20. public  class JUnitActionBase {  
  21.      private  static HandlerMapping handlerMapping;  
  22.      private  static HandlerAdapter handlerAdapter;  
  23.     /** 
  24.      * 读取spring3 MVC配置文件 
  25.      */  
  26.     @BeforeClass  
  27.   public  static  void setUp() {  
  28.          if (handlerMapping ==  null) {  
  29.             String[] configs = { "file:src/springConfig/springMVC.xml" };  
  30.             XmlWebApplicationContext context =  new XmlWebApplicationContext();  
  31.             context.setConfigLocations(configs);  
  32.             MockServletContext msc =  new MockServletContext();  
  33.             context.setServletContext(msc);         context.refresh();  
  34.             msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);  
  35.             handlerMapping = (HandlerMapping) context  
  36.                     .getBean(DefaultAnnotationHandlerMapping. class);  
  37.             handlerAdapter = (HandlerAdapter) context.getBean(context.getBeanNamesForType(AnnotationMethodHandlerAdapter. class)[0]);     
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 执行request对象请求的action 
  43.      *  
  44.      * @param request 
  45.      * @param response 
  46.      * @return 
  47.      * @throws Exception 
  48.      */  
  49.      public ModelAndView excuteAction(HttpServletRequest request, HttpServletResponse response)  
  50.   throws Exception {  
  51.         HandlerExecutionChain chain = handlerMapping.getHandler(request);  
  52.          final ModelAndView model = handlerAdapter.handle(request, response,  
  53.                 chain.getHandler());  
  54.          return model;  
  55.     }  
  56. }  

 

 

 

 

 

 

这是个JUnit测试类,我们可以new Request对象,来参与测试,太方便了。给request指定访问的URL,就可以请求目标Action了。

 

Java代码 
  1. package test.com.app.user;  
  2. import org.junit.Assert;  
  3. import org.junit.Test;  
  4. import org.springframework.mock.web.MockHttpServletRequest;  
  5. import org.springframework.mock.web.MockHttpServletResponse;  
  6. import org.springframework.web.servlet.ModelAndView;  
  7.   
  8. import test.JUnitActionBase;  
  9.   
  10. /**  
  11. * 说明: 测试OrderAction的例子 
  12. *  
  13. * @author  Kipa
  14. * @version 创建时间:2011-2-2 下午10:26:55   
  15. */   
  16.   
  17. public  class TestOrderAction  extends JUnitActionBase {  
  18.     @Test  
  19.      public  void testAdd()  throws Exception {  
  20.     MockHttpServletRequest request =  new MockHttpServletRequest();  
  21.         MockHttpServletResponse response =  new MockHttpServletResponse();  
  22.         request.setRequestURI("/order/add");  
  23.         request.addParameter("id", "1002");  
  24.         request.addParameter("date", "2010-12-30");  
  25.         request.setMethod("POST");  
  26.         // 执行URI对应的action  
  27.          final ModelAndView mav =  this.excuteAction(request, response);  
  28.         // Assert logic  
  29.         Assert.assertEquals("order/add", mav.getViewName());  
  30.         String msg=(String)request.getAttribute("msg");  
  31.         System.out.println(msg);  
  32.     }  
  33. }  

  需要说明一下 :由于当前最想版本的Spring(Test) 3.0.5还不支持@ContextConfiguration的注解式context file注入,所以还需要写个setUp处理下,否则类似于Tiles的加载过程会有错误,因为没有ServletContext。3.1的版本应该有更好的解决方案,参见:  https://jira.springsource.org/browse/SPR-5243 

参考 : http://www.iteye.com/topic/828513

 

 

 

 

  十四、转发与重定向

可以通过redirect/forward:url方式转到另一个Action进行连续的处理。

可以通过redirect:url 防止表单重复提交 。

写法如下:

return "forward:/order/add";

return "redirect:/index.jsp";

 

 

 

 

 十五、处理ajax请求

 

1、引入下面两个jar包,我用的是1.7.2,好像1.4.2版本以上都可以,下载地址:  http://wiki.fasterxml.com/JacksonDownload

jackson-core-asl-1.7.2.jar 

jackson-mapper-asl-1.7.2.jar

 

2、spring的配置文件中要有这一行,才能使用到spring内置支持的json转换。如果你手工把POJO转成json就可以不须要使用spring内置支持的json转换。

<mvc:annotation-driven />

 

3、使用@ResponseBody注解

 

Java代码 
  1. /** 
  2.  * ajax测试 
  3. * http://127.0.0.1/mvc/order/ajax 
  4.  */  
  5.   
  6. @RequestMapping("/ajax")  
  7. @ResponseBody  
  8. public Object ajax(HttpServletRequest request){  
  9.     List<String> list= new ArrayList<String>();  
  10.     list.add("电视");  
  11. nbsp;       list.add("洗衣机");  
  12.     list.add("冰箱");  
  13.     list.add("电脑");  
  14.     list.add("汽车");  
  15.     list.add("空调");  
  16.     list.add("自行车");  
  17.     list.add("饮水机");  
  18.     list.add("热水器");  
  19.      return list;  


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Android4.4支持使用DevTools对原生Android应用程序WebViews内容进行调试

$
0
0

从Android4.4(KitKat)开始,可以使用DevTools对原生Android应用程序的Android WebViews内容进行调试。

调试WebViews要求:

1.在Android设备或模拟器运行Android4.4或更高版本,并且Android设备上启用USB调试模式。
2.Chrome 30或更高版本。更强大的WebView界面调试功能需要Chrome31或更高版本。
3.Android应用程序中的WebView配置为可调试模式。


配置WebViews为可调试:

在Chrome中启用设置“USB web debugging”不会影响WebViews。在WebView中进行调试,需要通过在应用程序中以编程方式调用WebView类的静态方法setWebContentsDebuggingEnabled。

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
   WebView.setWebContentsDebuggingEnabled(true);
}


注意web调测不受app manifest文件中debuggable标记状态的影响,如果希望仅debuggable为true时才能使用web调测,那么运行时检测此标记。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
   if ( 0 != ( getApplcationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE ) ) {
   WebView.setWebContentsDebuggingEnabled(true);
   }
}


在DevTools中打开 WebView

在DevTools调试WebView:

1.使用USB数据线将移动设备连接到开发机器。
将移动设备连接到开发机器时,可能会看到USB调试警报“设备请求权限”。
为了避免每次调试时看到此警告,勾选“总是允许从这台计算机”,并单击“确定”。

2.在开发机器的Chrome上,打开检查about:inspect。

3.就能看到应用程序和调试的WebView列表的名称。单击旁边标签中inspect链接,就能在DevTools查看WebView的内容。



注:在Chrome 31及更高版本,about:inspect页面提供了一个图形表示WebView的大小和相对设备屏幕的位置。在Chrome 31之前:about:inspect页面仅支持提供的WebView的标题。设置WebViews标题的过程中,选择正确的WebView。

作者:offbye 发表于2014-8-28 13:46:35 原文链接
阅读:56 评论:0 查看评论

浅谈过载保护

$
0
0

浅谈过载保护

 

雪球:对于时延敏感的服务,当外部请求超过系统处理能力,如果系统没有做相应保护,可能导致历史累计的超时请求达到一定规模,像雪球一样形成恶性循环。由于系统处理的每个请求都因为超时而无效,系统对外呈现的服务能力为0,且这种情况下不能自动恢复。

作者bison,腾讯后台开发技术总监。

 

  过载保护,看似简单,但是要做好并不容易。这里用两个曾经经历的反面案例,给出过载保护的直观展现,并附上一点感想。


案例一基本情况

  如下图,进程A是一个单进程系统,通过udp套接字接收前端请求进行处理。在处理过程中,需要访问后端系统B,是同步的方式访问后端系统B,根据后端系统B的SLA,超时时间设置是100ms。前端用户请求的超时时间是1s。

 

  进程A的时序是:

 

Step1: 从socket接收缓冲区接收用户请求

 

Step2: 进行本地逻辑处理

 

Step3: 发送请求到后端系统B

 

Step4: 等待后端系统B返回

 

Step5: 接收后端系统B的应答

 

Step6: 应答前端用户,回到step1处理下一个请求

 



正常情况下的负载

  正常情况下:

 

1、前端请求报文大小约100Bytes。前端请求的峰值每分钟1800次,即峰值每秒30次。

 

2、后端系统B并行能力较高,每秒可以处理10000次以上,绝大多数请求处理时延在20ms内。

 

3、进程A在处理请求的时候,主要时延是在等待后端系统B,其他本地运算耗时非常少,小于1ms

 

  这个时候,我们可以看出,系统工作良好,因为处理时延在20ms内,每秒进程A每秒中可以处理50个请求,足以将用户每秒峰值30个请求及时处理完。


导火索

  某天,后端系统B进行了新特性发布,由于内部逻辑变复杂,导致每个请求处理时延从20ms延长至50ms,根据sla的100ms超时时间,这个时延仍然在正常范围内。当用户请求达到峰值时间点时,灾难出现了,用户每次操作都是“服务器超时无响应”,整个服务不可用。


过载分析

  当后端系统B处理时延延长至50ms的时候,进程A每秒只能处理20个请求(1s / 50ms = 20 )。小于正常情况下的用户请求峰值30次/s。这个时候操作失败的用户往往会重试,我们观察到前端用户请求增加了6倍以上,达到200次/s,是进程A最大处理能力(20次/s)的10倍!

 

   这个时候为什么所有用户发现操作都是失败的呢? 为什么不是1/10的用户发现操作能成功呢? 因为请求量和处理能力之间巨大的差异使得5.6s内就迅速填满了socket接收缓冲区(平均能缓存1000个请求,1000/(200-20)=5.6s),并且该缓冲区将一直保持满的状态。这意味着,一个请求被追加到缓冲区里后,要等待50s(缓存1000个请求,每秒处理20个,需要50s)后才能被进程A 取出来处理,这个时候用户早就看到操作超时了。换句话说,进程A每次处理的请求,都已经是50s以前产生的,进程A一直在做无用功。雪球产生了。


案例二基本情况

  前端系统C通过udp访问后端serverD,后端server D的udp套接字缓冲区为4MB,每个请求大小约400字节。后端serverD偶尔处理超时情况下,前端系统C会重试,最多重试2次。

 


正常情况下的负载

  正常情况,后端serverD单机收到请求峰值为300次/s,后端serverD单机处理能力是每秒1500次,时延10ms左右。这个时候工作正常。


导火索

  由于产品特性(例如提前通知大量用户,未来某某时刻将进行一项秒杀活动;类似奥运门票,大量用户提前得知信息:某日开始发售门票),大量的用户聚集在同一时刻发起了大量请求,超出了后台serverD的最大负载能力。操作响应失败的用户又重试, 中间系统的重试,进一步带来了更大量的请求(正常情况下的9倍)。导致所有用户操作都是失败的。


过载分析

  只是导火索不一样,同案例一,巨大的请求和处理能力之间的鸿沟,导致后端serverD的4M大小的接收缓冲区迅速填满(4秒就填满),且过载时间内,接收缓冲区一直都是满的。而处理完缓冲区内的请求,ServerD需要6秒以上(4MB / 400 / 1500 = 6.7S)。所以serverD处理的请求都是6s之前放入缓冲区的,而该请求在最前端早已经超时。雪球形成了。


启示

1、  每个系统,自己的最大处理能力是多少要做到清清楚楚。例如案例一中的前端进程A,他的最大处理能力不是50次/s,也不是20次/S,而是10次/S。因为它是单进程同步的访问后端B, 且访问后端B的超时时间是100ms,所以他的处理能力就是1S/100ms=10次/S。而平时处理能力表现为50次/S,只是运气好。

 

2、  每个系统要做好自我保护,量力而为,而不是尽力而为。对于超出自己处理能力范围的请求,要勇于拒绝。

 

3、  每个系统要有能力发现哪些是有效的请求,哪些是无效的请求。上面两个案例中,过载的系统都不具备这中慧眼,逮着请求做死的处理,雪球时其实是做无用功。

 

4、  前端系统有保护后端系统的义务,sla中承诺多大的能力,就只给到后端多大的压力。这就要求每一个前后端接口的地方,都有明确的负载约定,一环扣一环。

 

5、  当过载发生时,该拒绝的请求(1、超出整个系统处理能力范围的;2、已经超时的无效请求)越早拒绝越好。就像上海机场到市区的高速上,刚出机场就有电子公示牌显示,进入市区某某路段拥堵,请绕行。

 

6、  对于用户的重试行为,要适当的延缓。例如登录发现后端响应失败,再重新展现登录页面前,可以适当延时几秒钟,并展现进度条等友好界面。当多次重试还失败的情况下,要安抚用户。

 

7、  产品特性设计和发布上,要尽量避免某个时刻导致大量用户集体触发某些请求的设计。发布的时候注意灰度。

 

8、  中间层server对后端发送请求,重试机制要慎用,一定要用的话要有严格频率控制。

 

9、  当雪球发生了,直接清空雪球队列(例如重启进程可以清空socket 缓冲区)可能是快速恢复的有效方法。

 

10、过载保护很重要的一点,不是说要加强系统性能、容量,成功应答所有请求,而是保证在高压下,系统的服务能力不要陡降到0,而是顽强的对外展现最大有效处理能力。

 

  对于“每个系统要有能力发现哪些是有效的请求,哪些是雪球无效的请求”,这里推荐一种方案:在该系统每个机器上新增一个进程:interface进程。Interface进程能够快速的从socket缓冲区中取得请求,打上当前时间戳,压入channel。业务处理进程从channel中获取请求和该请求的时间戳,如果发现时间戳早于当前时间减去超时时间(即已经超时,处理也没有意义),就直接丢弃该请求,或者应答一个失败报文。

 

  Channel是一个先进先出的通信方式,可以是socket,也可以是共享内存、消息队列、或者管道,不限。

 

  Socket缓冲区要设置合理,如果过大,导致及时interface进程都需要处理长时间才能清空该队列,就不合适了。建议的大小上限是:缓存住超时时间内interface进程能够处理掉的请求个数(注意考虑网络通讯中的元数据)。

 

 

作者:keda8997110 发表于2014-8-28 13:39:05 原文链接
阅读:11 评论:0 查看评论

JAVA爬虫Nutch、WebCollector的正则约束

$
0
0

爬虫爬取时,需要约束爬取的范围。基本所有的爬虫都是通过正则表达式来完成这个约束。

最简单的,正则:

http://www.xinhuanet.com/.*
代表"http://www.xinhuanet.com/"后加任意个任意字符(可以是0个)。

通过这个正则可以约束爬虫的爬取范围,但是这个正则并不是表示爬取新华网所有的网页。新华网并不是只有www.xinhuanet.com这一个域名,还有很多子域名,类似:news.xinhuanet.com

这个时候我们需要定义这样一个正则:

http://([a-z0-9]*\.)*xinhuanet.com/
这样就可以限制爬取新华网所有的网页了。

每种爬虫的正则约束系统都有一些区别,这里拿Nutch、WebCollector两家爬虫的正则系统做对比:

Nutch官网: http://nutch.apache.org/

WebCollector官网: http://crawlscript.github.io/WebCollector/

1.Nutch:

nutch的正则约束是依赖一个配置文件 conf/regex-urlfilter.txt 来实现的。例如:


+^http://www.xinhuanet.com/
+^http://news.xinhuanet.com/
-^http://blog.xinhuanet.com/

nutch的正则约束原则是:

1)逐行扫描,对每一行进行如下操作:

       去掉正则前面的加号或减号,获取正则式。看待爬取网页的url中是否包含当前正则的模式。如果包含,看正则前的符合。如果为+,则当前url无需过滤,返回当前url,如果为-,则当前url需要过滤,返回null。如果待爬取网页url中不包含当前正则的模式,则跳过(继续下一行操作)。

2)如果扫描到文件结尾,都没有返回:

       返回null。


有2个地方需要注意:

1)nutch的正则过滤时,采用的匹配函数式Patterm.matcher,而不是Patterm.matches。

   Patterm.mather在匹配时,只要找到待爬取网页的url的子串和正则匹配,就通过。

   Patterm.matcher要求待爬取网页的url和regex完全匹配。例如:

    待爬取网页的网址是  http://www.xinhuanet.com/index.html

    正则是^http://([a-z0-9]*\.)*xinhuanet.com

    这个正则用Patterm.matcher和网页url可以匹配。因为网页url的字串http://www.xinhuanet.com和正则能匹配。

    但是用Patterm.matches就不能匹配。正则需要改成^http://([a-z0-9]*\.)*xinhuanet.com.*才可以和网页的URL匹配。

    也就是说nutch的正则其实是和找url中是否有字串符合正则。所以做nutch的正则配置文件时,要在http前加入^符号,如果正则没有加^符号,例如+http://www.xinhuanet.com ,下面网址也是可以匹配的:

    http://www.abc.com/index.php?name=http://www.xinhuanet.com

   

2)nutch正则过滤时,是逐行扫描,一旦扫描到匹配行就返回结果。所以正则式的顺序很重要。例如可以通过下面的配置文件来完成全网爬取(需要过滤图片等文件为不爬取):

-\.(gif|GIF|jpg|JPG|ico|ICO|css|sit|eps|wmf|zip|ppt|mpg|xls|gz|rpm|tgz|mov|MOV|exe)$
+.
先扫描第一行,遇到gif、JPG等文件,会匹配正则,由于前面符号是-,所以返回null,url被过滤。

如果当前url不对应gif、JPG等文件,会继续扫描第二行,第二行可以匹配任意字符串。由于前面符号是+,所以返回当前url,当前url被接受。


2.WebCollector:

WebCollector的正则约束是直接通过程序指定的:

BreadthCrawler crawler=new BreadthCrawler();
.....
.....
crawler.addRegex("+http://www\\.xinhuanet\\.com/.*");
crawler.addRegex("-http://www\\.xinhuanet\\.com/special/.*");
crawler.addRegex("-http://www\\.xinhuanet\\.com/info/.*");

WebCollector中正则有两种,正例正则,和反例正则。url要被接受,需要符合下面2个条件。

1.至少符合一条正例正则。

2.不能符合任意一条反例正则。


正例正则以+开头,反例正则以-开头(如果前面不加符号,默认是正例正则)。

上面代码中,http://www.xinhuanet.com/auto/index.html就可以被接受。因为它符合一条正例http://www.xinhuanet.com/.* ,不符合任意一条反例正则(http://www.xinhuanet.com/special/.*和http://www.xinhuanet.com/info/.*)。

必须给出至少一条正例正则,才可以进行爬取,如果没有正例正则,不能符合上面的条件一。

WebCollector中正则匹配采用的是Patterm.matches,要求正则与URL完全匹配。如果上面代码中你的正则写成+http://www.xinhuanet.com/,而不是+http://www.xinhuanet.com/.*,那么只有网页http://www.xinhuanet.com/可以被接受,网页http://www.xinhuanet.com/index.html就不能被接收。


下面给出一个例子,爬取新华网的news.xinhuanet.com子域名,过滤掉gif和jpg图像:

BreadthCrawler crawler=new BreadthCrawler();
.....
.....
crawler.addRegex("+http://news\\.xinhuanet\\.com/.*");
crawler.addRegex("-.*gif.*");
crawler.addRegex("-.*jpg.*");



作者:AJAXHu 发表于2014-8-28 13:08:55 原文链接
阅读:63 评论:0 查看评论

hive 的分隔符、orderby sort by distribute by的优化

$
0
0

一、Hive 分号字符

分号是SQL语句结束标记,在HiveQL中也是,但是在HiveQL中,对分号的识别没有那么智慧,例如:

select concat(cookie_id,concat(';',’zoo’)) fromc02_clickstat_fatdt1 limit 2;

FAILED: Parse Error: line 0:-1 cannot recognize input'<EOF>' in function specification

可以推断,Hive解析语句的时候,只要遇到分号就认为语句结束,而无论是否用引号包含起来。

解决的办法是,使用分号的八进制的ASCII码进行转义,那么上述语句应写成:

select concat(cookie_id,concat('\073','zoo')) fromc02_clickstat_fatdt1 limit 2;

为什么是八进制ASCII码?

我尝试用十六进制的ASCII码,但Hive会将其视为字符串处理并未转义,好像仅支持八进制,原因不详。这个规则也适用于其他非SELECT语句,如CREATE TABLE中需要定义分隔符,那么对不可见字符做分隔符就需要用八进制的ASCII码来转义。

二、insert 新增数据

根据语法Insert必须加“OVERWRITE”关键字,也就是说每一次插入都是一次重写。那如何实现表中新增数据呢?

假设Hive中有表manbu,

hive> DESCRIBE manbu;

id int

value int

hive> SELECT * FROM manbu;

3 4

1 2

2 3

现增加一条记录:

hive> INSERT OVERWRITE TABLE manbu

SELECT id, value FROM (

SELECT id, value FROM manbu

UNION ALL

SELECT 4 AS id, 5 AS value FROM manbu limit 1

) u;

结果是:

hive>SELECT * FROM p1;

3 4

4 5

2 3

1 2

其中的关键在于, 关键字UNION ALL的应用, 即将原有数据集和新增数据集进行结合, 然后重写表.

三、初始值

INSERT OVERWRITE TABLE在插入数据时, 后面的字段的初始值应注意与表定义中的一致性. 例如, 当为一个STRING类型字段初始为NULL时:

NULL AS field_name // 这可能会被提示定义类型为STRING, 但这里是void

CAST(NULL AS STRING) AS field_name // 这样是正确的

又如, 为一个BIGINT类型的字段初始为0时:

CAST(0 AS BIGINT) AS field_name

四、orderby  sort by  distribute by的优化

Hive的排序关键字是SORT BY,它有意区别于传统数据库的ORDER BY也是为了强调两者的区别–SORT BY只能在单机范围内排序。

例如:

 set mapred.reduce.tasks=2;(设置reduce的数量为2 )

原值:

1.selectcookie_id,page_id,id from c02_clickstat_fatdt1

where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')

1.193.148.164.1288609861509.2  113181412886099008861288609901078194082403      684000005

1.193.148.164.1288609861509.2  127001128860563972141288609859828580660473      684000015

1.193.148.164.1288609861509.2   113181412886099165721288609915890452725326      684000018

1.193.131.218.1288611279693.0  01c183da6e4bc50712881288611540109914561053      684000114

1.193.131.218.1288611279693.0  01c183da6e4bc22412881288611414343558274174      684000118

1.193.131.218.1288611279693.0  01c183da6e4bc50712881288611511781996667988      684000121

1.193.131.218.1288611279693.0  01c183da6e4bc22412881288611523640691739999      684000126

1.193.131.218.1288611279693.0  01c183da6e4bc50712881288611540109914561053      684000128 

2. selectcookie_id,page_id,id from c02_clickstat_fatdt1 where

cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')

SORT BYCOOKIE_ID,PAGE_ID;

SORT排序后的值

1.193.131.218.1288611279693.0           684000118       01c183da6e4bc22412881288611414343558274174      684000118

1.193.131.218.1288611279693.0           684000114      01c183da6e4bc50712881288611540109914561053      684000114

1.193.131.218.1288611279693.0           684000128      01c183da6e4bc50712881288611540109914561053      684000128

1.193.148.164.1288609861509.2           684000005      113181412886099008861288609901078194082403      684000005

1.193.148.164.1288609861509.2           684000018      113181412886099165721288609915890452725326      684000018

1.193.131.218.1288611279693.0           684000126      01c183da6e4bc22412881288611523640691739999      684000126

1.193.131.218.1288611279693.0           684000121      01c183da6e4bc50712881288611511781996667988      684000121

1.193.148.164.1288609861509.2           684000015       127001128860563972141288609859828580660473      684000015

selectcookie_id,page_id,id from c02_clickstat_fatdt1

where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')

ORDER BYPAGE_ID,COOKIE_ID;

1.193.131.218.1288611279693.0           684000118      01c183da6e4bc22412881288611414343558274174      684000118

1.193.131.218.1288611279693.0           684000126      01c183da6e4bc22412881288611523640691739999      684000126

1.193.131.218.1288611279693.0           684000121       01c183da6e4bc50712881288611511781996667988      684000121

1.193.131.218.1288611279693.0           684000114      01c183da6e4bc50712881288611540109914561053      684000114

1.193.131.218.1288611279693.0           684000128       01c183da6e4bc50712881288611540109914561053      684000128

1.193.148.164.1288609861509.2           684000005      113181412886099008861288609901078194082403      684000005

1.193.148.164.1288609861509.2           684000018      113181412886099165721288609915890452725326      684000018

1.193.148.164.1288609861509.2           684000015      127001128860563972141288609859828580660473      684000015

可以看到SORT和ORDER排序出来的值不一样。一开始我指定了2个reduce进行数据分发(各自进行排序)。结果不一样的主要原因是上述查询没有reduce key,hive会生成随机数作为reduce key。这样的话输入记录也随机地被分发到不同reducer机器上去了。为了保证reducer之间没有重复的cookie_id记录,可以使用DISTRIBUTE BY关键字指定分发key为cookie_id。

selectcookie_id,country,id,page_id,id from c02_clickstat_fatdt1 where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')  distribute by cookie_id SORT BY COOKIE_ID,page_id;

1.193.131.218.1288611279693.0           684000118      01c183da6e4bc22412881288611414343558274174      684000118

1.193.131.218.1288611279693.0           684000126      01c183da6e4bc22412881288611523640691739999      684000126

1.193.131.218.1288611279693.0           684000121      01c183da6e4bc50712881288611511781996667988      684000121

1.193.131.218.1288611279693.0           684000114      01c183da6e4bc50712881288611540109914561053      684000114

1.193.131.218.1288611279693.0           684000128      01c183da6e4bc50712881288611540109914561053      684000128

1.193.148.164.1288609861509.2           684000005      113181412886099008861288609901078194082403      684000005

1.193.148.164.1288609861509.2           684000018       113181412886099165721288609915890452725326      684000018

1.193.148.164.1288609861509.2           684000015      127001128860563972141288609859828580660473      684000015

例二:

CREATETABLE if not exists t_order(

id int,-- 编号

sale_idint, -- SID

customer_idint, -- CID

product_id int, -- PID

amountint -- 数量

)PARTITIONED BY (ds STRING);

在表中查询所有记录,并按照PID和数量排序:

setmapred.reduce.tasks=2;

Selectsale_id, amount from t_order

Sort bysale_id, amount;

这一查询可能得到非期望的排序。指定的2个reducer分发到的数据可能是(各自排序):

Reducer1:

Sale_id |amount

0 | 100

1 | 30

1 | 50

2 | 20

Reducer2:

Sale_id |amount

0 |110

0 | 120

3 | 50

4 | 20

使用DISTRIBUTE BY关键字指定分发key为sale_id。改造后的HQL如下:

setmapred.reduce.tasks=2;

Selectsale_id, amount from t_order

Distributeby sale_id

Sort bysale_id, amount;

这样能够保证查询的销售记录集合中,销售ID对应的数量是正确排序的,但是销售ID不能正确排序,原因是hive使用hadoop默认的HashPartitioner分发数据。

这就涉及到一个全排序的问题。解决的办法无外乎两种:

1.) 不分发数据,使用单个reducer:

setmapred.reduce.tasks=1;

这一方法的缺陷在于reduce端成为了性能瓶颈,而且在数据量大的情况下一般都无法得到结果。但是实践中这仍然是最常用的方法,原因是通常排序的查询是为了得到排名靠前的若干结果,因此可以用limit子句大大减少数据量。使用limit n后,传输到reduce端(单机)的数据记录数就减少到n* (map个数)。

2.) 修改Partitioner,这种方法可以做到全排序。这里可以使用Hadoop自带的TotalOrderPartitioner(来自于Yahoo!的TeraSort项目),这是一个为了支持跨reducer分发有序数据开发的Partitioner,它需要一个SequenceFile格式的文件指定分发的数据区间。如果我们已经生成了这一文件(存储在/tmp/range_key_list,分成100个reducer),可以将上述查询改写为

setmapred.reduce.tasks=100;

sethive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderPartitioner;

settotal.order.partitioner.path=/tmp/ range_key_list;

Selectsale_id, amount from t_order

Clusterby sale_id

Sort byamount;

有很多种方法生成这一区间文件(例如hadoop自带的o.a.h.mapreduce.lib.partition.InputSampler工具)。这里介绍用Hive生成的方法,例如有一个按id有序的t_sale表:

CREATETABLE if not exists t_sale (

id int,

namestring,

locstring

);

则生成按sale_id分发的区间文件的方法是:

createexternal table range_keys(sale_id int)

rowformat serde

'org.apache.hadoop.hive.serde2.binarysortable.BinarySortableSerDe'

stored as

inputformat

'org.apache.hadoop.mapred.TextInputFormat'

outputformat

'org.apache.hadoop.hive.ql.io.HiveNullValueSequenceFileOutputFormat'

location'/tmp/range_key_list'; 

insertoverwrite table range_keys

selectdistinct sale_id

fromsource t_sale sampletable(BUCKET 100 OUT OF 100 ON rand()) s

sort bysale_id;

生成的文件(/tmp/range_key_list目录下)可以让TotalOrderPartitioner按sale_id有序地分发reduce处理的数据。

区间文件需要考虑的主要问题是数据分发的均衡性,这有赖于对数据深入的理解。

作者:manburen01 发表于2014-8-28 13:06:38 原文链接
阅读:68 评论:0 查看评论

让你的Node.js应用跑得更快的10个技巧

$
0
0

Node.js 受益于它的事件驱动和异步的特征,所以已经很快了。但是,在现代网络中只是快是不行的。如果你打算用 Node.js 开发你的下一个Web应用的话,那么你就应该无所不用,让你的应用更快,异常的快。本文将介绍10条经过检验得知可大大提高Node速度的应用技巧。废话不多说,让我们逐条来看看。

 

1. 并行

创建 Web 应用的时候,你可能要多次调用内部 API 来获取各种数据。比如说,假设在 Dashboard 页面上,你要执行下面这几个调用:

•用户信息 -getUserProfile().
•当前活动 -getRecentActivity().
•订阅内容 -getSubscriptions().
•通知内容 -getNotifications().
为了拿到这些信息,你应该会为每个方法创建独立的中间件,然后将它们链接到 Dashboard 路由上。不过问题是,这些方法的执行是线性的,上一个没结束之前下一个不会开始。可行解决案是并行调用它们。

如你所知由于异步性,Node.js 非常擅长并行调用多个方法。我们不能暴殄天物。我上面提到的那些方法没有依赖性,所以我们可以并行执行它们。这样我们可以削减中间件数量,大幅提高速度。

我们可以用 async.js 来处理并行,它是一个专门用来调教 JavaScript 异步的 Node 模块。下面代码演示怎样用 async.js 并行调用多个方法的:

如果你想更深入了解 async.js ,请移步它的 GitHub 页面。

 

2. 异步

根据设计 Node.js 是单线程的。基于这点,同步代码会堵塞整个应用。比如说,多数的文件系统 API 都有它们的同步版本。下面代码演示了文件读取的同步和异步两种操作:

不过要是你执行那种长时间的阻塞操作,主线程就会被阻塞到这些操作完成为止。这大大降低你应用的性能。所以,最好确保你的代码里用的都是异步版本 API,最起码你应该在性能节点异步。而且,你在选用第三方模块的时候也要很小心。因为当你想方设法把同步操作从你代码中剔除之后,一个外部库的同步调用会让你前功尽弃,降低你的应用性能。

 

3. 缓存

如果你用到一些不经常变化的数据,你应该把它们缓存起来,改善性能。比如说,下面的代码是获取最新帖子并显示的例子:
如果你不经常发贴的话,你可以把帖子列表缓存起来,然后一段时间之后再把它们清理掉。比如,我们可以用 Redis 模块来达到这个目的。当然,你必须在你的服务器上装 Redis。然后你可以用叫做 node_redis 的客户端来保存键/值对。下面的例子演示我们怎么缓存帖子:

看到了吧,我们首先检查 Redis 缓存,看看是否有帖子。如果有,我们从缓存中拿这些帖子列表。否则我们就检索数据库内容,然后把结果缓存。此外,一定时间之后,我们可以清理 Redis 缓存,这样就可以更新内容了。

 

4. gzip 压缩

开启 gzip 压缩对你的 Web 应用会产生巨大影响。当一个 gzip 压缩浏览器请求某些资源的时候,服务器会在响应返回给浏览器之前进行压缩。如果你不用 gzip 压缩你的静态资源,浏览器拿到它们可能会花费更长时间。

在 Express 应用中,我们可以用内建 express.static() 中间件来处理静态内容。此外,还可以用 compression 中间件压缩和处理静态内容。下面是使用例:

5. 如果可以,在用客户端渲染

现在有超多功能强劲的客户端 MVC/MVVM 框架,比如说 AngularJS, Ember, Meteor, 等等,构建一个单页面应用变得非常简单。基本上,你只要公开一个 API,返回 JSON 响应给客户端就可以了,而不需要在服务端渲染页面。在客户端,你可以用框架来组织 JSON 然后把它们显示在 UI 上。服务端只发送 JSON 响应可以节省带宽,改善性能,因为你不需要在每个响应里面都返回布局标记了,对吧,你只需要返回纯 JSON,然后在客户端渲染它们。

看下我的这个教程,它是关于怎样用 Express 4 公开一个 RESTful APIs的。我还写了另一篇教程,演示了怎样把这些 APIs 和 AngularJS 结合起来。

 

6. 不要在 Sessions 存储太多数据

典型的 Express 页面应用, Session 数据默认是保存在内存中的。当你把太多数据保存在 Session 的时候,会导致服务器开销显著增大。所以,要么你切换到别的储存方式来保存 Session 数据,要么尽量减少存储在 Session 中的数据量。

比如说,当用户登录到你的应用的时候,你可以只在 Session 中保存他们的 ID 而不是整个用户数据对象。还有,对于那些你能够从 id 拿到对象的查询,你应该会喜欢用  MongoDB 或者 Redis 来存储 session 数据。

 

7. 优化查询

假设你有个博客,你要在主页上显示最新帖子。你可能会通过 Mongoose 这样取数据:
不过问题是 Mongoose 的 find() 方法会把对象的所有字段都查询出来,而许多字段在主页上并不要求。比如说,commentsis 保存的是特定帖子的回复。我们不需要显示文章回复,所以我们可以在查询的时候把它给剔除掉。这无疑会提高速度。可以像这样优化上面那条查询:

 

8. 用标准的 V8 方法

集合上的一些操作,比如 map,reduce,和 forEach 不一定支持所有浏览器。我们可以通过前台的库解决部分浏览器兼容性问题。但对于 Node.js,你要确切知道 Google 的 V8 JavaScript 引擎支持哪些操作。这样,你就可以在服务端直接用这些内建方法来操作集合了。

 

9. 在 Node 前面用 Nginx

Nginx 是个微小型轻量 Web 服务器,用它可以降低你的 Node.js 服务器的负载。你可以把静态资源配置到 nginx 上,而不是在 Node 上。你可以在 nginx 上用 gzip 压缩响应,让所有的响应都变得更小。所以,如果你有个正在营运的产品,我觉得你应该会想用 nginx 来改善运行速度的。

 

10. 打包 JavaScript

最后,你还可以大大提高页面应用速度,通过把多个 JS 文件打包。当浏览器在页面渲染中碰到 <script> 元素的时候会被堵塞,直到拿到这个脚本才继续运行(除非设置了异步属性)。比如,如果你的页面有五个 JavaScript 文件,浏览器会发出五个独立的 HTTP 请求来获取他们。如果把这五个文件压缩打包成一个,整体性能将可以大幅提升。CSS 文件也是一样。你可以用诸如 Grunt/Gulp 这样的编译工具来打包你的资源文件。

 

结论

上面 10 条技巧肯定可以提高你的 Web 应用的速度的。不过,我知道还有改善和优化的空间。如果你有任何改善性能的技巧的话,在回复里告诉我。



感谢 u012797015投递这篇资讯

资讯来源: 开源中国社区

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



[转]多线程情况下HttpClient的使用

$
0
0

本文转截自:http://www.thinkingquest.net/articles/210.html

 

3.x版本的httpclient属于apache的commons项目。 从4.x开始,httpclient被转移到了httpcomponent项目下。 api也发生了重大的变化。 http 3.x已经不推荐使用。使用3.x版本的地方,官方建议都升级到4.x版本。

本文的api也都基于4.x版本。下面是一个最simple的案例:

private String upload(String url, HttpEntity entity) {
    String result = null;
    HttpClient httpClient = new DefaultHttpClient();
    try {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(entity);
        HttpResponse response = httpClient.execute(httpPost);
        int status = response.getStatusLine().getStatusCode();
        if (status == HttpStatus.SC_OK) {
            HttpEntity resEntity = response.getEntity();
            result = EntityUtils.toString(resEntity, "UTF-8");
        } else {
            logger.error("upload:" + url + " error code:" + status);
        }
    } catch (Exception ex) {
        logger.error("Error with HttpClient ", ex);
    } finally {
        try {
            httpClient.getConnectionManager().shutdown();
        } catch (Exception ignore) {}
    }
    return result;
}

在这段代码中,每调用一次upload方法,都会new一次 BasicHttpClient对象。由此产生一个疑问,这个对象是否是线程安全的呢?查阅了文档,文档中说它是线程安全的。文档地 址:http://hc.apache.org/httpcomponents-client-ga/tutorial/html /httpagent.html

实测对一个BasicHttpClient对象,多个线程调用,只有一个线程运行正常,其他线程全部抛出异常。究其根源,是其中的ConnectionManager的问题。
在多线程的情况下,如果创建一个BasicHttpClient对象,代码应该如下:

PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
BasicHttpParams params = new BasicHttpParams();
params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 64 * 1024);
client = new DefaultHttpClient(cm, params);

 

每次执行client.execute(method)之后,需要调用method的releaseConnection()方法。

PoolingClientConnectionManager是其中的关键,替代了默认采用的BasicClientConnectionManager。这样就可以多线程。
setMaxTotal设置的是最大连接数。如果不设置,默认值为20。defaultMaxPerRoute的默认值是2。文档中说,这两个参数过于保守。对于频繁请求的应用来说,都太小了。
关于其它的参数可以参见文档:

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e399

 

本文转截自:http://www.thinkingquest.net/articles/210.html

----

PS:

可以使用method的abort方法 哎~~



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



前景目标检测1(总结)

$
0
0

运动前景对象检测一直是国内外视觉监控领域研究的难点和热点之一,其目的是从序列图像中将变化区域从背景图像中提取出来,运动前景对象的有效检测对于对象跟踪、目标分类、行为理解等后期处理至关重要,那么区分前景对象,非常关键的一个问题是确定一个非常合适的背景,背景从象素的角度来理解,每一个象素就是有可能是前景点,也有可能是背景点,那么我们就要防止背景中误进入原属于前景点的对象,目前有几种常用的方法,但分别有利弊。

主要可以分为:背景建模,帧差法,光流法

1: Single Gaussian(单高斯模型)

Real-time tracking of the human body

 

2:Mixture of Gaussian model(混合高斯模型)

An improved adaptive background mixture model for real-time tracking with shadow detection

基于混合高斯模型的自适应背景差分算法,类似于帧间差分法,使用混合高斯分布模型来表征图像帧中每一个像素点的特征,当获取新的图像帧时,适时更新混合高斯分布模型,某一时刻选取混合高斯模型中的一个子集表征当前背景,如果当前图像帧的某个像素点与混合高斯模型的背景子集匹配,则判定为背景,否则判定为前景点。总体来说是通过学习与训练计算出有没有运动对象时的背景

 

3:Running Gaussian average(滑动高斯平均)

Real-tine tracking of the human body

混合高斯在现有的背景建模算法中算是较好的,很多新的算法或者改进的算法都是基于它的原理变形的,但是混合高斯的缺点是计算量相对比较大,速度偏慢,对光照敏感。

 

4:CodeBook(码本)

Real-time foreground-background segmentation using codebook model

Real-time foreground-background segmentation using a modified codebook model

码本的效果还可以,之后有多中版本, 但是对光照也敏感;

 

5:SOBS-Self-organization background subtraction(自组织背景检测)

A self-Organizing approach to background subtraction for+visual surveillance

对于自组织背景建模算法即SOBS算法,该算法对光照有一定的鲁棒性,但MAP的模型比输入图片大,计算量比较大,但是可以通过并行处理来解决算法的速度问题,可以进行尝试;

 

6:SACON(样本一致性建模算法)

A consensus-based method for tracking

A consensus-based method for tracking-Modelling background scenario and foreground appearance

SACON-Background subtraction based on a robust consensus method

该方法是基于统计的知识,效果还不错;

 

7:ViBe算法

ViBe-A Universal Background Subtraction

作者网站:http://www2.ulg.ac.be/telecom/research/vibe/

ViBe算法是一个有别于传统方法的算法,作者已经申请了专利,可以做研究,用一帧图像就可以初始化背景模型,该方法计算量比较小,速度很快,可以嵌入到相机中,可以抗摄像头抖动,并且对噪声也有一定的鲁棒性,检测效果很不错;

 

 

8:Color(基于颜色信息的背景建模方法)

A statistical approach for real-time robust background subtraction and shadow detection

基于颜色信息的背景建模方法,简称Color算法,该算法将像素点的差异分解成Chromaticity差异和Brightness差异,对光照具有很强的鲁棒性,并有比较好的效果,计算速度也比较快,基本可以满足实时性的要求,做了许多视频序列的检测,效果比较理想;

 

9:统计平均法

 

10:Temporal Median filter( 中值滤波法)

Automatic congestion detection system for underground platform

Detecting moving objects,ghost,and shadows in video streams

统计平均法和中值滤波法,对于这两个算法,只对统计平均法做了实现,并进行了测试,算法的应用具有很大的局限性,只能算是理论上的一个补充;

 

11:W4方法

W4.pdf

W4算法应该是最早被用于实际应用的一个算法,这个大家可以去查看相关的资料,这里不再细说;

 

12:本征背景法

A Bayesian computer vision system for modeling human interactions

基于贝叶斯框架

 

13:核密度估计

Non-parametric model for background subtraction

最后就是核密度估计算法,该算法应该是一个比较鲁棒的算法,可以解决很多算法参数设置方面的问题,无需设置参数应该是算法的一大优势。

 

SOBS、Color、VIBE、SACON、PDF等可以进行深入的了解,特别是近年来出现的Block-based(块)或Region-Based(区域)、Features-Based(特征)、基于层次分类或层次训练器的算法可以进行深入的研究。

 

14:光流法(速度太慢,基本不用)

光流法概念源自光流场,当运动物体的影象在表面上的模式运动就是所谓的光流场,是一个二维速度场。而光流法根据连续多帧图像序列,计算各象素点运动的大小和方向,它反映了图像上每一像点灰度的变化趋势。优点:不需要背景建模,在无法预先获得场景的任何信息的情况下,也能够检测出独立的运动对象。缺点是计算复杂,往往需要特殊的硬件支持,很难满足实时性要求。

 

15: http://code.google.com/p/bgslibrary/ 这个网站的库包含了各种各样背景减除的方法,可以省很多时间。

 

16:Evaluation of Background Subtraction Techniques for Video Surveillance

综述性评估文章,可以看到各种算法的性能。

 

17:王先荣博客对前景提取的分析(含代码)

http://www.cnblogs.com/xrwang/archive/2010/02/21/ForegroundDetection.html

 

18:帧差法

|frame(i) - frame(i-1)| > Th,背景就是上一帧图像。每一帧与上一帧进行差分运算。提取效果显然与运动前景对象的速度和帧率有关(帧率指一秒钟有几张图片)。扩展下,建立在统计模型基础上的有选择的背景建模,实际上就是混合高斯法。优点:速度较快,稳定性较好。缺点是可能出现物体的“空洞现象”,空洞是由于某一大型运动物体,它的两帧之间存在象素十分接近的重合部分,所以导致这部分被差分剪去了。(帧差法主要有,二帧差,三帧差,累积帧差)

 

19:固定背景法

|frame(i) - background(i)| > Th,由于背景是预先设定的固定的一幅图像,这里必然引入了四个问题:光照变化,摄像机抖动,高频率振荡背景,运动转静止物体的干扰。优点:计算简单,易于实现。缺点是摄象头要绝对静止,而且不适应光照变化。

 

20:Pixel-Based Adaptive Segmenter

Background Segmentation with Feedback: The Pixel-Based Adaptive Segmenter

http://www.mmk.ei.tum.de/~hom/pbas  网站

(PBAS)检测算法是基于像素的无参数模型,该算法结合了SACON和VIBE两个算法的优势,并在这两个算法的基础上改进而来;

主要创新点:

(1)引入控制论的思想,使前景判断阈值和背景模型更新率自适应变化,随背景的复杂程度变化。

(2) 引入背景复杂程度的度量方法,根据背景复杂程度调整前景判断阈值和背景模型更新率。

 

 

本文转载自: Albert-Lxy

行人检测

$
0
0

最近一直在看行人检测的论文,对目前的行人检测做大概的介绍。

行人检测具有极其广泛的应用:智能辅助驾驶,智能监控,行人分析以及智能机器人等领域。从2005年以来行人检测进入了一个快速的发展阶段,但是也存在很多问题还有待解决,个人觉得主要还是在性能和速度方面还不能达到一个权衡。

1.行人检测的现状(大概可以分为两类)

(1).基于背景建模:利用背景建模方法,提取出前景运动的目标,在目标区域内进行特征提取,然后利用分类器进行分类,判断是否包含行人;

背景建模目前主要存在的问题:(背景建模的方法总结可以参考我的前一篇博文介绍) (前景目标检测总结)

  • 必须适应环境的变化(比如光照的变化造成图像色度的变化);
  • 相机抖动引起画面的抖动(比如手持相机拍照时候的移动);
  • 图像中密集出现的物体(比如树叶或树干等密集出现的物体,要正确的检测出来);
  • 必须能够正确的检测出背景物体的改变(比如新停下的车必须及时的归为背景物体,而有静止开始移动的物体也需要及时的检测出来)。
  • 物体检测中往往会出现Ghost区域,Ghost区域也就是指当一个原本静止的物体开始运动,背静差检测算法可能会将原来该物体所覆盖的区域错误的检测为运动的,这块区域就成为Ghost,当然原来运动的物体变为静止的也会引入Ghost区域,Ghost区域在检测中必须被尽快的消除。

(2).基于统计学习的方法:这也是目前行人检测最常用的方法,根据大量的样本构建行人检测分类器。提取的特征主要有目标的灰度、边缘、纹理、颜色、梯度直方图等信息。分类器主要包括神经网络、SVM、adaboost以及现在被计算机视觉视为宠儿的深度学习。

统计学习目前存在的难点:

(a)行人的姿态、服饰各不相同、复杂的背景、不同的行人尺度以及不同的关照环境。

(b)提取的特征在特征空间中的分布不够紧凑;

(c)分类器的性能受训练样本的影响较大;

(d)离线训练时的负样本无法涵盖所有真实应用场景的情况;

目前的行人检测基本上都是基于法国研究人员Dalal在2005的CVPR发表的HOG+SVM的行人检测算法 (Histograms of Oriented Gradients for Human Detection, Navneet Dalel,Bill Triggs, CVPR2005)。HOG+SVM作为经典算法也别集成到opencv里面去了,可以直接调用实现行人检测

为了解决速度问题可以采用背景差分法的统计学习行人检测,前提是背景建模的方法足够有效(即效果好速度快),目前获得比较好的检测效果的方法通常采用多特征融合的方法以及级联分类器。(常用的特征有Harry-like、Hog特征、LBP特征、Edgelet特征、CSS特征、COV特征、积分通道特征以及CENTRIST特征。

2.行人检测综述性文章  

[1] D. Geronimo, and A. M.Lopez. Vision-based Pedestrian Protection Systems for Intelligent Vehicles, BOOK, 2014.

[2] P.Dollar, C. Wojek,B. Schiele, et al. Pedestrian detection: an evaluation of the state of the art [J]. IEEE Transactions on PatternAnalysis andMachine Intelligence, 2012, 34(4): 743-761.

[3]苏松志, 李绍滋, 陈淑媛等.  行人检测技术综述[J].  电子学报, 2012, 40(4): 814-820.

[4]M. Enzweiler, and D.Gavrila. Monocular pedestrian detection: survey and experiments [J].  IEEE Transactions on Pattern Analysis andMachine Intelligence, 2009, 31(12): 2179-2195.

[5] D. Geronimo, A. M.Lopez and A. D. Sappa, et al. Survey of pedestrian detection for advanced driverassistance systems [J].  IEEE Transactionson Pattern Analysis and Machine Intelligence, 2010, 32(7): 1239-1258.

[6]贾慧星, 章毓晋.车辆辅助驾驶系统中基于计算机视觉的行人检测研究综述[J],  自动化学报, 2007, 33(1): 84-90.

[7] 许言午, 曹先彬,乔红. 行人检测系统研究新进展及关键技术展望[J],  电子学报, 2008, 36(5): 368-376.

[8] 杜友田; 陈峰;徐文立; 李永彬;基于视觉的人的运动识别综述,  电子学报, 2007. 35(1): 84-90.

[9]朱文佳. 基于机器学习的行人检测关键技术研究[D].  第一章硕士学位论文, 上海交通大学. 2008. 指导教师: 戚飞虎.

 最新论文

2014_ITS_Toward real-time pedestrian detection based on a deformable template model

2014_PAMI_Scene-specific pedestrian detection for static video surveillance

2014_CVPR_Pedestrian Detection in Low-resolution Imagery by Learning Multi-scale Intrinsic Motion Structures (MIMS)

2014_CVPR_Switchable Deep Network for Pedestrian Detection

2014_CVPR_Informed Haar-like Features Improve Pedestrian Detection

2014_CVPR_Word Channel Based Multiscale Pedestrian Detection Without Image Resizing and Using Only One Classifier

2013_BMVC_Surveillance camera autocalibration based on pedestrian height distribution

2013_Virtual and real world adaptation for pedestrian detection

2013_Search space reduction in pedestrian detection for driver assistance system based on projective geometry

2013_CVPR_Robust Multi-Resolution Pedestrian Detection in Traffic Scenes

2013_CVPR_Optimized Pedestrian Detection for Multiple and Occluded People
2013_CVPR_Pedestrian Detection with Unsupervised and Multi-Stage Feature Learning
2013_CVPR_Single-Pedestrian Detection aided by Multi-pedestrian Detection
2013_CVPR_Modeling Mutual Visibility Relationship in Pedestrian Detection
2013_CVPR_Local Fisher Discriminant Analysis for Pedestrian Re-identification

 3.行人检测source code

1. INRIA Object detection and Localization Toolkit, Dalal于2005年提出了 基于HOG特征的行人检测方法,行人检测领域中的经典文章之一。HOG特征目前也被用在其他的目标检测与识别、图像检索和跟踪等领域中。

2.  Real-time Pedestrian Detection. Jianxin Wu实现的快速行人检测方法。

3.  Hough Transfom for Pedestrian Detection. Olga Barinova, CVPR 2010 Paper: On detection of multiple object instances using Hough Transforms

4.  HIKSVM, HOG+LBP+HIKSVM, 行人检测的经典方法.

5.  GroundHOG, GPU-based Object Detection with Geometric Constraints, In: ICVS, 2011. CUDA版本的HOG+SVM,  video.

6.  100FPS_PDS, Pedestrian detection at 100 frames per second, R. Benenson. CVPR, 2012. 实时的(⊙o⊙)哦。 Real-time!!!

7.  POM: Probabilistic Occupancy Map. Multiple camera pedestrian detection.

8.  Pitor Dollar Detector. Integral Channel Feature + 多尺度特征近似+多特征融合. Real-Time!

4.行人检测DataSets

MIT数据库

该数据库为较早公开的行人数据库,共924张行人图片(ppm格式,宽高为64x128),肩到脚的距离约80象素。该数据库只含正面和背面两个视角,无负样本,未区分训练集和测试集。Dalal等采用“HOG+SVM”,在该数据库上的检测准确率接近100%。

INRIA数据库

该数据库是目前使用最多的静态行人检测数据库,提供原始图片及相应的标注文件。训练集有正样本614张(包含2416个行人),负样本1218张;测试集有正样本288张(包含1126个行人),负样本453张。图片中人体大部分为站立姿势且高度大于100个象素,部分标注可能不正确。图片主要来源于GRAZ-01、个人照片及google,因此图片的清晰度较高。在XP操作系统下部分训练或者测试图片无法看清楚,但可用OpenCV正常读取和显示。

Daimler行人数据库

该数据库采用车载摄像机获取,分为检测和分类两个数据集。检测数据集的训练样本集有正样本大小为18x36和48x96的图片各15560(3915x4)张,行人的最小高度为72个象素;负样本6744张(大小为640x480或360x288)。测试集为一段27分钟左右的视频(分辨率为640x480),共21790张图片,包含56492个行人。分类数据库有三个训练集和两个测试集,每个数据集有4800张行人图片,5000张非行人图片,大小均为18x36,另外还有3个辅助的非行人图片集,各1200张图片。

Caltech行人数据库

该数据库是目前规模较大的行人数据库,采用车载摄像头拍摄,约10个小时左右,视频的分辨率为640x480,30帧/秒。标注了约250,000帧(约137分钟),350000个矩形框,2300个行人,另外还对矩形框之间的时间对应关系及其遮挡的情况进行标注。数据集分为set00~set10,其中set00~set05为训练集,set06~set10为测试集(标注信息尚未公开)。性能评估方法有以下三种:(1)用外部数据进行训练,在set06~set10进行测试;(2)6-fold交叉验证,选择其中的5个做训练,另外一个做测试,调整参数,最后给出训练集上的性能;(3)用set00~set05训练,set06~set10做测试。由于测试集的标注信息没有公开,需要提交给 Pitor Dollar。结果提交方法为每30帧做一个测试,将结果保存在txt文档中(文件的命名方式为I00029.txt I00059.txt ……),每个txt文件中的每行表示检测到一个行人,格式为“[left, top,width, height, score]”。如果没有检测到任何行人,则txt文档为空。该数据库还提供了相应的Matlab工具包,包括视频标注信息的读取、画ROC(Receiver Operatingcharacteristic Curve)曲线图和非极大值抑制等工具。

TUD行人数据库

TUD行人数据库为评估运动信息在行人检测中的作用,提供图像对以便计算光流信息。训练集的正样本为1092对图像(图片大小为720x576,包含1776个行人);负样本为192对非行人图像(手持摄像机85对,车载摄像机107对);另外还提供26对车载摄像机拍摄的图像(包含183个行人)作为附加训练集。测试集有508对图像(图像对的时间间隔为1秒,分辨率为640x480),共有1326个行人。Andriluka等也构建了一个 数据库用于验证他们提出的检测与跟踪相结合的行人检测技术。该数据集的训练集提供了行人的矩形框信息、分割掩膜及其各部位(脚、小腿、大腿、躯干和头部)的大小和位置信息。测试集为250张图片(包含311个完全可见的行人)用于测试检测器的性能,2个视频序列(TUD-Campus和TUD-Crossing)用于评估跟踪器的性能。

NICTA行人数据库

该数据库是目前规模较大的静态图像行人数据库,25551张含单人的图片,5207张高分辨率非行人图片,数据库中已分好训练集和测试集,方便不同分类器的比较。Overett等用“RealBoost+Haar”评估训练样本的平移、旋转和宽高比等各种因素对分类性能的影响:(1)行人高度至少要大于40个象素;(2)在低分辨率下,对于Haar特征来说,增加样本宽度的性能好于增加样本高度的性能;(3)训练图片的大小要大于行人的实际大小,即背景信息有助于提高性能;(4)对训练样本进行平移提高检测性能,旋转对性能的提高影响不大。以上的结论对于构建行人数据库具有很好的指导意义。

ETH行人数据库

Ess等构建了基于双目视觉的行人数据库用于多人的行人检测与跟踪研究。该数据库采用一对车载的AVT Marlins F033C摄像头进行拍摄,分辨率为640x480,帧率13-14fps,给出标定信息和行人标注信息,深度信息采用置信度传播方法获取。

CVC行人数据库

该数据库目前包含三个数据集(CVC-01、CVC-02和CVC-Virtual),主要用于车辆辅助驾驶中的行人检测研究。CVC-01[Geronimo,2007]有1000个行人样本,6175个非行人样本(来自于图片中公路区域中的非行人图片,不像有的行人数据库非行人样本为天空、沙滩和树木等自然图像)。CVC-02包含三个子数据集(CVC-02-CG、CVC-02-Classification和CVC-02-System),分别针对行人检测的三个不同任务:感兴趣区域的产生、分类和系统性能评估。图像的采集采用Bumblebee2立体彩色视觉系统,分辨率640x480,焦距6mm,对距离摄像头0~50m的行人进行标注,最小的行人图片为12x24。CVC-02-CG主要针对候选区域的产生,有100张彩色图像,包含深度和3D点信息;CVC-02-Classification主要针对行人分类,训练集有1016张正样本,7650张负样本,测试集分为基于切割窗口的分类(570张行人,7500张非行人)和整张图片的检测(250张包含行人的图片,共587个行人);CVC-02-System主要用于系统的性能评估,包含15个视频序列(4364帧),7983个行人。CVC-Virtual是通过Half-Life 2图像引擎产生的虚拟行人数据集,共包含1678虚拟行人,2048个非行人图片用于测试。

USC行人数据库

该数据库包含三组数据集(USC-A、USC-B和USC-C),以XML格式提供标注信息。USC-A[Wu, 2005]的图片来自于网络,共205张图片,313个站立的行人,行人间不存在相互遮挡,拍摄角度为正面或者背面;USC-B的图片主要来自于 CAVIAR视频库,包括各种视角的行人,行人之间有的相互遮挡,共54张图片,271个行人;USC-C有100张图片来自网络的图片,232个行人(多角度),行人之间无相互遮挡。

5.Others

相关资料资料
1. Edgar Seemann维护的 行人检测网站,比较全,包括publications, code, datasets等。
2.  Pedestrian detection: state of the art. A video talk by Pitor Dollar. Pitor Dollar做了很多关于行人检测方法的研究,他们研究小组的Caltech Pedestrian Dataset也很出名。

6.人体行为识别(Human Action Recognition)

来源:http://hi.baidu.com/susongzhi/item/656d196a2dcd733cac3e83e3

 

1.  Statistical and Structural Recognition of Human Actions. ECCV, 2010 Tutorial, by Ivan Laptev and Greg Mori. (注:要用爬墙软件才能访问到)
2.  Human Action Recognition in realistic scenarios, 一份很好的硕士生毕业论文开题资料。

 

参考:http://hi.baidu.com/susongzhi/item/085983081b006311eafe38e7

数据库异常hang住解决

$
0
0
 下午内网 测试库同事反应查询更新数据很慢,有时甚至表都打不开,后来通过服务器【linux】的top命令查看了下,cpu和mem占用正常,但wait高达80%多(下面两图显示的就是问题前后观察EM对比的截图,版本是oracle10gR2,EM的效果比oracle11gR2逊色不少哈):
  -------------------------------------->>
  ---------------------------->>
  接着通过sqldevelpdev客户端查询有没有锁等待之类会话事件,果然有,而且是两个session持有TX锁,然后通过下面的sql查询从oracle和linux级别kill掉了相应session,以为风波就此平静,结果过了不到一分钟查询又出现,只不过这次只有一个session持有TX锁,于是就去查找对应的sql_txt,找到后发现是个同事写的存储过程,定时任务,当时正在运行,让其确认下是不是任务执行出问题了,结果一查,是程序问题,造成的死循环,它会批量发起会话,kill一个后接着又锁,循环反复,后来他改了下程序后重新运行,一切恢复通畅.
--查询死锁
select sess.sid, sess.serial#,  lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode
from v$locked_object lo, dba_objects ao,v$session sess
where ao.object_id = lo.object_id and lo.session_id = sess.sid;
--oracle级别kill session
alter system kill session '1627,1';
alter system kill session '1564,64740';
--查询当前连接会话
select s.value,s.sid,a.username,a.MACHINE from v$sesstat S,v$statname N,v$session A
where n.statistic#=s.statistic# and name='session pga memory' and s.sid=a.sid and a.sid=1626
order by s.value;
--查询造成死锁的sql语句
SELECT   a.SID, a.username, s.sql_text FROM v$session a, v$sqltext s
WHERE a.sql_address = s.address AND a.sql_hash_value = s.hash_value  and a.SID=1626
ORDER BY a.username, a.SID, s.piece;
--造成锁等待的操作内容
begin
flt_com.p_line_relation_change(:A0,:B0,:C0,:D0,:E0,:ret_errorcode,:ret_errorname);
end;
--通过sid查找pid,进而通过系统级别kill
select spid, osuser, s.program from v$session s,v$process p where s.paddr=p.addr and s.sid=1605;
--服务器级别kill
kill -9 spid
--------------------------------over game


顺其自然EVO 2014-08-28 10:19 发表评论

杀死你的APP的6个致命错误

$
0
0

20140827075650559

导读:没有开发者或者设计师会故意破坏应用的设计。所有的应用程序创建者都对自己的应用寄予美好的愿望,但是很多错误是在他们无意识的状态下破坏app的设计。以下是应用开发者和设计者经常犯的6个错误。

在app设计过程中,开发者和设计师犯过很多破坏设计的错误,不过以下是最明显的一部分,并且也很容易避免。深入理解设计规则和移动应用特性可以帮你打造更好的用户体验。

1、糟糕的app icon

通常情况下,用户对应用的第一印象来自于icon。当用户看到应用的icon时,他们经常会做这些猜想:它是安全的吗?我可以信任它吗?这款应用可靠吗?应用是否是由专业人士开发?它值得我投入时间吗?

对于不同的开发者和设计者来说,每个人似乎都有他们自己关于什么是好的icon的想法。在App Store的“Camera” 类别中,你会看到一些icon非常引人注目,而另一些icon则似乎被隐蔽了,默默无闻地藏在某个角落。很明显,让icon脱颖而出的是其视觉上的吸引力,但是哪些元素让icon更具视觉吸引力呢?

● 专注于一个独特的形状。是否有一个形状,你可以用在自己的icon中,从而提高icon的可辨认度;

●用色上精挑细选。确保你使用的颜色能满足某个目的,并保证它们彼此之前能相互协调;

●避免使用摄影作品。在一个小尺寸的icon上,用户很难看清摄影作品的细节;

●避免使用大量文本,保证其易读性。

确保你的应用已经遵守了上述几项,从而避免给用户带来不专业的感觉。

2、强迫用户注册

比如,朋友给你推荐了一款非常优秀的应用,而你也非常有兴趣使用它。下载应用,打开,而弹出的第一个屏幕却要求你先注册,很肯定的一点,这不是你期望的第一体验。用户下载应用后肯定希望能立刻体验它,如果你使用计算器应用都需要注册,那么这个设计是非常愚蠢的。不过,有些应用出于功能方面的要求需要首先进行注册,这种情况下,要确保有一个很好的指导过程,并且注册要求应该切合应用的实际需求。如果不是这种情况,那么你可以侥幸首先展示应用,如果用户希望解锁更多功能,比如邀请朋友和跟踪目标,那么再要求用户注册。

3、过小的控件

这一点就如同让一个手指粗大的人穿针引线一样,几乎是不可能实现的。对于儿童来说,我们需要简化元素并将之放大,对于应用来说也一样,大尺寸控件更易于用户与之进行交互。在此前的iOS版本中,计算器应用中控件尺寸已经比较合适了,不过iOS 7使用了更大一点尺寸的控件。

4、难以阅读的文本

对用户来说,滚动阅读要比眯着眼阅读容易的多。很多时候,你想从屏幕上获得尽可能多的信息,比如股票图表,但对于文本来说,滚动方式可以让你更快地进行阅读。不过,阅读速度依然依赖于文本阅读的难以程度。使用更大尺寸的文本没有什么不妥。就像上边提到的控件部分,更大一点的尺寸并不仅仅适用于儿童,当不在4英寸屏幕上进行阅读时,大一点的字体会让阅读变得更加容易。

如果你不确定应该使用哪个字号的文本,那可以使用 Dynamic Type 。这样用户可以决定哪个字体大小最适合他们,而你也无需为如何恰到好处地展示内容而担心。

5、承载过多品牌

思考一下,用户使用你的app所要付出的代价:

● 他们需要从App Store下载你的应用,它展示应用的名称和icon;

● 他们需要通过查看应用名称和icon在手机上打开应用;

● 他们需要观看展示app logo和名称的加载视图。

等到他们真正要使用应用时,你的品牌已经通过三次不同的机会曝光给他们。除此以外,真的没有更多的需求要你在应用中填塞商标或品牌。对于网站来说,给品牌更多曝光机会似乎无可厚非,因为你不知道用户是如何到达你的网站的。但是对于应用来说,用户到达应用只有一个方法,就是点击打开应用。

6、令人困惑的动画

动画可以让应用更加简单简洁,不过不适当的使用也会让应用变得难以理解或者令用户迷失。把动画用在设计当中非常尤其,不过问题在于很多时候它们并没有任何目的。在本文中,我们不深究纷繁难懂的动画。

本文作者:@樊晋朋  来自: i黑马


(关注更多人人都是产品经理观点,参与微信互动(微信搜索“人人都是产品经理”或“woshipm”)

SEO (搜索引擎优化)的时代要终结了吗?

$
0
0

seo-rip

Mashable是社交媒体最知名的网站之一。它对自己的定义是一个“面向互联一代的顶尖新闻、信息和资源来源”。在大多数情况下,该网站会向读者提供有关社交媒体和万维网的有价值信息。然而,一篇预测SEO过期的文章证明,即使如Mashable这样的知名媒体也可能犯错。可怕的错误。

一次又一次,专业人员宣布SEO的终结,我不得不承认,他们的论点听起来很靠谱。然而,那些真正了解、生活在网络营销世界中的人知道,搜索引擎优化(SEO)将继续存在下去。进化?√。变形?√。过时?×!绝不会过时!

对SEO的争论以及现实情况

正如前面提到的,Mashable的文章中提出的论点听起来很有说服力,但只是部分正确。但那些按照文章的建议行事的人会发现,如果网站的内容被认为是竞争力的一部分,他们的网站也不会获得排名提升。

比如,这篇文章的作者声称,谷歌决定停止公布关键字的流行度,这损害了搜索引擎优化,是有机网络推广终结的明确标志。谷歌的决定是一个众所周知的事实,但对它的意义的解读是错误的,因为网络推广专家并不需要这些信息就能带来了好的效果。

这篇文章误解的另一个例子是,谷歌决定停止搜索引擎优化,因为它损害了谷歌的目标。这是真的。谷歌改变并改进了用于评定现有网站排名的算法。然而,受这些变化影响的不是SEO专家,而只有那些用非法手段提高排名的网站。

关于页面优化

除了批评这篇文章外,这篇文章的作者还是提了一些真知灼见。具体而言,建议创建高质量网站,以便作为适当网络推广的可靠基础。

能给读者带来真正好处的高质量内容,能提供简单、直观的导航,准确的层次和细致的检查。这些网站不会有任何错误,如失效链接或错误页面。所有这些优质网站的方面都是搜索引擎优化过程中不可缺少的部分。因此,搜索引擎优化不会消亡。

我们不能放弃失去影响力的链接

与文章中的观点相反,经验表明,即使在如今,出于网站推广的目的建立链接也很重要。任何试图在拥有高度竞争媒介的类别中推广网站,却不建立超链接策略的行为,都是注定要失败的。即使在谷歌的算法多次更新后,链接在排名中依旧很重要。

创建链接时需要注意的几点(部分):

  • 提高同一类别链接的优先级。来自相同领域网站的直接或间接链接。
  • 创建有用链接的另一个重要特性是变化。网站主题和链接类型(文字、图片等)都是链接策略至关重要的组成部分。最重要的是,确保了链接每次都出现在不同的锚文本中。
  • 使用符合 Google Penguin更新标准的链接,Google Penguin是谷歌在2012年发布的最重要的更新。这次更新确保了在来源和链接它们的文字上不自然的链接不会获得排名提升,甚至还能起到相反的效果。

总之:SEO还将存在,且依旧很重要和必要!

的确,要提高一个网站的排名,高质量的网站内容、出现在社交媒体中以及其他网路营销手段都至关重要。然而,虽然这些很重要,但要在一个流行/竞争性强的领域中,光靠这些手段来提高网站排名还不够。高品质的SEO不会消失。相反,它会重塑自己,并且变得比以往任何时候都更重要!

本文来自动点合作媒体 GeekTime,作者为Exactive LTD网络部门负责人兼联合CEO On Yavin。Yavin是搜索引擎优化(SEO)方面的专家,拥有多年网络营销经验。

本文 SEO (搜索引擎优化)的时代要终结了吗?来自 动点科技.


hbase读写优化小记

$
0
0
客户端编程时我们可以注意的:
1、批量读
当我们使用scan顺序读的时候,默认是一个RPC请求返回一条数据,我们可以设置一次返回多条缓存在客户端缓存,比如sn.setCaching(1000);
2、批量写
数据在客户端累计到一定量再发次请求,批量写
table.setWriteBufferSize(1 * 1024 * 1024); 
table.setAutoFlush(false); 
    
3、使用filter
使用过滤器,在服务器端就做好过滤再返回数据到客户端,减少网络流量


服务端需要注意到的地方:
1、rowkey的设计尽量短小,尽量避免顺序递增
2、指定列族参数,比如大多是scan顺序读,可将block设大些,默认块大小是64K,可以设为128,使用bloomfilter提高随机读性能规避一些hfile的读
3、region热点
开始会不断往一个region写,可以预划分region
如果rowkey不可避免会造成热点,在rowkey加哈希前缀 对region server数量取余,这种情况scan读的时候会比较麻烦,需要客户端计算好各个子范围开启多个线程分别去范围读
4、memstore提高写性能,blockcache提高读性能,看需求调整,调大一方调小一方,一般加起来占60至70%
5、关闭major compact,手工弄
6、频繁split我们可以改为手工split
比如一开始都是只往一个region里写,只有当region到一定数量才可能负载比较均衡(写请求),这里又出现了个问题,假设各个region大小非常均匀,他们有可能在同一时间split,影响效率,我们可以关闭split,手工split某些region

作者:u011750989 发表于2014-8-28 16:32:56 原文链接
阅读:85 评论:0 查看评论

PC远程调试移动设备 - Barret Lee

$
0
0

我们在移动端进行前端开发时,会遇到一个让人头痛但不得不面对的问题——调试。

在 PC 机器上,我们有功能强大的 Chrome DevTools、Firebug,即便是老版本的 IE ,我们也可以安装微软提供的插件,对网页样式和请求信息轻松进行调试。但在手机、平板上,很多人就无招可施了,一个劲的 alert 查看调试信息。如果你已经厌倦了可爱又可恨的 alert 弹窗,请继续往下阅读。

一、先说说调试的原理

设备浏览器中输入一个 URL,它会向 URL 所在的 server 请求资源:

+-------------+ +---------------+
| client |--------→| Internet |
+-------------+ +---------------+

此时,数据是从 client 和 目标 server 之间的隐秘交互,除非 server 端的代码是由我们自己控制,否则很难了解他们之间都做了什么信息传递。如果 server 传过来的代码存在 bug,此时我们就相当纠结了。比较常见的情景是,该 server 就是我们的测试机器,我们在测试机器上开发,通过一个移动设备 client 来实施调试代码,常用的调试方式就是修改 server 代码,再实时查看 client 的响应。

但是,问题来了。某天,Barret 发现 client 端页面显示有 bug,由于 client 请求的目标 server 是线上,不像平时的测试机器,我们可以随意修改代码然后查看效果,并且线上的代码都是经过压缩和打包了的,很难阅读,怎么办?

于是,我想到了使用代理:

+-------------+ \ / +---------------+
| client |-----×---→| Internet |
+-------------+ / \ +---------------+
| ↑
| |
| +-------------+ |
+----→| proxy |-----+
+-------------+

我们在 client 端做相应配置,让他的请求强制指向 proxy,然后 proxy 转发请求到目标 server,proxy 上的请求和响应都是透明的,通过篡改 client 到 proxy 的请求,或者篡改 server 到 proxy 的响应,就可以实时查看这些人为修改在 client 端的效果了。本文目的就是说明 proxy 是如何操作的。

二、通过 Fiddler 代理

windows 下著名的 http(s) 代理软件 fiddler 使用比较广泛,mac 下可以使用 charles 代理,由于使用人群相对偏少,本文就不细说,感兴趣的可以 PM 我。charles 是一个跨平台的软件,windows 下也可以使用,不过个人偏好 fiddler。OK,我们来看看 fiddler 是如何一步一步完成网络代理的。

1. 配置客户端

这里说的客户端包括手机、平板甚至电脑。一般的 android / IOS 设备都可以设置代理:

step 1. 当连接好网络之后(相信你在一个 wifi 环境下进行开发),点击右侧的箭头按钮,我使用的是 android 手机,IOS 也比较好找,在 设置>Wi-Fi 中找到对应的网络,右侧有个圆圈包着的 i 图标,点击进入:

step 2. 一般代理方式有两种,手动和自动,将其设置为手动,然后填写,你电脑的 IP(为啥呢?因为 proxy 是你的电脑,client 的请求要全部转发到你的电脑上,然后使用 fiddler 软件去分析/替换请求),windows 下使用 ipconfig 可以看到本机 IP,linux/unix 下使用 ifconfig 查看:

step 3. 设置端口,端口可以随意设置,但最好大于 3000,数值比较小的端口可能被系统占用了。

这里需要注意一点,由于 client 相对我们电脑的 fiddler 来说是一个远程设备,所以要在 Allow Remote Computers to Connert 选项上打上勾勾。

step 4. 进入手机浏览器,输入网址:

step 5. 然后把你的眼睛挪到电脑屏幕上看看 fiddler:

到这里,我相信你已经看明白了整个 proxy 的原理。至于 fiddler 如何替换包,如何修改包,如果调试,不是本文叙述的重点,下面演示一个简单的替换。

2. 调试

请求百度的页面,我们把百度的 logo 换成博客园的:

step 1. 在 AutoResponder 中添加一项:

step 2. 进入你的浏览器(UC下清空缓存,如果缓存中有百度图片,他会使用缓存,并不发出这个请求),打开百度页面:

然后你就发现,貌似哪里有点不对~ 除此之外,你还可以将线上文件替换到本地,比如线上的 xyz-min.js 替换成本地的 xyz.js 然后修改 xyz.js 的内容,直接调试线上 bug,异常方便!

三、其他工具

有人会说,我没有实体机,那我建议你在电脑上安装虚拟机,android 和 IOS 的虚拟机都比较好安装。

有人会说,我电脑太卡,跑不动虚拟机,那我建议你就是用上述方式。

有人会说,.....,(如果没实体机也没虚拟机,那你开发个毛线呀)。

Fiddler 和 Charles 都是 HTTP(s) 层的抓包软件,如果你是 websocket 开发调试,建议使用 wireshark,网络七层协议,这个软件能抓除数据链路层之外的所有层信息,出于安全考虑,它抓到的包是不能篡改的。

还有一些比较好用的工具,如利用 pac 文件配置系统代理,weinre 调试等,这里简单介绍下 weinre:

1. 安装

npm install –g weinre

2. 打开

weinre -httpPort 7999 -boundHost -all-
  • httpPort 监听端口
  • boundHost –all- 绑定主机

3. 说明都写在图片里头,相信聪明的你可以悟到

四、小结

移动端开发不比 PC 轻松,调试只是需要注意的一个小点,还有很多很多未知的东西等着我们去探索,本文也算是抛砖引玉,如果您有更好的移动端调试方案,希望可以分享出来,一起交流。

 


本文链接: PC远程调试移动设备,转载请注明。

创新工场有哪些失败项目?我们能从中学到什么?

$
0
0
失败或碰到挑战的项目也不少。这里不点名,不谈细节,但是谈谈碰到什么挑战(有些已经失败,有些还在努力):
  1. 有一个项目由几个很牛的技术人员负责,策划一个很有技术深度的平台,但是初步搭建后,原来认为的潜在客户其实不愿意如此依靠一个第三方的技术平台。
  2. 有些项目出现创始人不和的问题,都是认识不久的共同创始人,创业前充满激情,甚至彼此互补加分,但是创业后发现彼此的远景或工作方式不符合。如果一位创始人离开,对士气打击较大。
  3. 有一个项目是一位很优秀的产品经理,但是这个项目成功关键之一是要建立很好的线下合作伙伴关系,而这个关键做不好,产品再好也没有用。
  4. 有一个项目有一位很聪明的创业者,总是想加新的功能,新的产品线,不够专一,产品推出迭代太慢,错失市场良机。
  5. 有一个项目过分相信美国的趋势,忽视了在某方面中国的互联网格局已经和美国不同,走了弯路才发现一个美国的良机在中国并不一定存在。


— 完 —
本文作者: 李开复

【知乎日报】 你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 10 个回答,查看全部。
延伸阅读:
TBBT第五季第15集里Sheldon和Leonard互相说的“Sup”是什么意思?
《生活大爆炸》第五季第 19 集里面那个可以发出鞭子声的 app 是什么?

Java实现的基于模板的网页结构化信息精准抽取组件:HtmlExtractor

$
0
0

HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取。

 

HtmlExtractor是为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效。

如何使用?

HtmlExtractor由2个子项目构成,html-extractor和html-extractor-web。
html-extractor实现了数据抽取逻辑,是从节点,html-extractor-web提供web界面来维护抽取规则,是主节点。
html-extractor是一个jar包,可通过maven引用:
<dependency><groupId>org.apdplat</groupId><artifactId>html-extractor</artifactId><version>1.0</version></dependency>
  html-extractor-web是一个war包,需要部署到Servlet/Jsp容器上。 

单机集中式使用方法:

//1、构造抽取规则

List<UrlPattern> urlPatterns = new ArrayList<>();
//1.1、构造URL模式
UrlPattern urlPattern = new UrlPattern();
urlPattern.setUrlPattern("http://money.163.com/\\d{2}/\\d{4}/\\d{2}/[0-9A-Z]{16}.html");
//1.2、构造HTML模板
HtmlTemplate htmlTemplate = new HtmlTemplate();
htmlTemplate.setTemplateName("网易财经频道");
htmlTemplate.setTableName("finance");
//1.3、将URL模式和HTML模板建立关联
urlPattern.addHtmlTemplate(htmlTemplate);
//1.4、构造CSS路径
CssPath cssPath = new CssPath();
cssPath.setCssPath("h1");
cssPath.setFieldName("title");
cssPath.setFieldDescription("标题");
//1.5、将CSS路径和模板建立关联
htmlTemplate.addCssPath(cssPath);
//1.6、构造CSS路径
cssPath = new CssPath();
cssPath.setCssPath("div#endText");
cssPath.setFieldName("content");
cssPath.setFieldDescription("正文");
//1.7、将CSS路径和模板建立关联
htmlTemplate.addCssPath(cssPath);
//可象上面那样构造多个URLURL模式
urlPatterns.add(urlPattern);

//2、获取抽取规则对象
ExtractRegular extractRegular = ExtractRegular.getInstance(urlPatterns);
//注意:可通过如下3个方法动态地改变抽取规则
//extractRegular.addUrlPatterns(urlPatterns);
//extractRegular.addUrlPattern(urlPattern);
//extractRegular.removeUrlPattern(urlPattern.getUrlPattern());

//3、获取HTML抽取工具
HtmlExtractor htmlExtractor = HtmlExtractor.getInstance(extractRegular);

//4、抽取网页
String url = "http://money.163.com/08/1219/16/4THR2TMP002533QK.html";
List<ExtractResult> extractResults = htmlExtractor.extract(url, "gb2312");

//5、输出结果
int i = 1;
for (ExtractResult extractResult : extractResults) {
    System.out.println((i++) + "、网页 " + extractResult.getUrl() + " 的抽取结果");
    for(ExtractResultItem extractResultItem : extractResult.getExtractResultItems()){
        System.out.print("\t"+extractResultItem.getField()+" = "+extractResultItem.getValue());              
    }
    System.out.println("\tdescription = "+extractResult.getDescription());
    System.out.println("\tkeywords = "+extractResult.getKeywords());
}
 

多机分布式使用方法:

1、运行主节点,负责维护抽取规则:
  将子项目html-extractor-web打成War包然后部署到Tomcat。
2、获取一个HtmlExtractor的实例(从节点),示例代码如下:
String allExtractRegularUrl = "http://localhost:8080/HtmlExtractorServer/api/all_extract_regular.jsp";
String redisHost = "localhost";
int redisPort = 6379;
HtmlExtractor htmlExtractor = HtmlExtractor.getInstance(allExtractRegularUrl, redisHost, redisPort);
3、抽取信息,示例代码如下:
String url = "http://money.163.com/08/1219/16/4THR2TMP002533QK.html";
List<ExtractResult> extractResults = htmlExtractor.extract(url, "gb2312");

int i = 1;
for (ExtractResult extractResult : extractResults) {
    System.out.println((i++) + "、网页 " + extractResult.getUrl() + " 的抽取结果");
    for(ExtractResultItem extractResultItem : extractResult.getExtractResultItems()){
        System.out.print("\t"+extractResultItem.getField()+" = "+extractResultItem.getValue());              
    }
    System.out.println("\tdescription = "+extractResult.getDescription());
    System.out.println("\tkeywords = "+extractResult.getKeywords());
}
 


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



利用JUnit和Spring-test对SpringJDBC组件DAO层测试

$
0
0

借着学习Druid连接池的机会,使用的Spring,将知识点联系起来,简单写了一个利用JUnit和Spring-test对SpringJDBC组件DAO层测试的Demo,分类归在Spring中吧。

 

SpringJDBC组件是Spring提供的一个对底层JDBC的封装,扩展了更多更方便的接口,方便我们对数据库的操作。

 

Demo利用Maven构建,pom.xml文件配置如下(Tomcat、Jetty等暂时不需要,懒得删...)

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zhangpl.demo</groupId><artifactId>druid</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>druid</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- 如果依赖的version,使用${druid-version},则需要定义properties属性 --><druid-version>1.0.2</druid-version></properties><dependencies><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid-version}</version><!-- <version>0.2.8</version> --></dependency><!-- Servlet、JSP --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.4</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency><!-- Junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.9</version></dependency><!-- Mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.9</version></dependency><!-- commons-logging --><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version><type>pom</type></dependency><!-- Spring-test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>3.2.5.RELEASE</version></dependency><!-- Spring相关 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>3.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>3.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>3.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>3.2.5.RELEASE</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.6</source><target>1.6</target></configuration></plugin><plugin><groupId>org.mortbay.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><version>8.1.15.v20140411</version><configuration><scanIntervalSeconds>10</scanIntervalSeconds></configuration></plugin><plugin><groupId>org.codehaus.cargo</groupId><artifactId>cargo-maven2-plugin</artifactId><version>1.4.8</version><configuration><container><containerId>tomcat7x</containerId><home>E:\SoftwareDevelopment\Software\apache-tomcat\apache-tomcat-7.0.47-windows-x64\apache-tomcat-7.0.47</home></container><configuration><type>standalone</type><home>${project.build.directory}/tomcat7x</home><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><cargo.servlet.URIEncoding>UTF-8</cargo.servlet.URIEncoding><cargo.jvmargs>-Dfile.encoding=UTF-8</cargo.jvmargs></properties></configuration></configuration></plugin></plugins></build></project>

 

 

然后,数据库中建表users,字段很简单,对应下面的实体类User.java

 

/**
 * @author zhangpl
 * E-mail:xingsan.zhang@gmail.com
 * 2014年8月24日  下午11:34:27
 */
public class User {
	private int id;
	private String username;
	private String password;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
}

 

 

下面是Spring的配置文件applicationContext.cml,注意:

1.连接池使用的是Druid,可不与理会;

2.使用Spring提供的注解;

3.扫描属性文件的配置;

 

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"><!-- 注解配置 --><context:component-scan base-package="com.zhangpl.demo" /><!-- 扫描属性文件 --><context:property-placeholder location="classpath*:db.properties" /><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		init-method="init" destroy-method="close"><!-- 基本属性 url、user、password --><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.user}" /><property name="password" value="${jdbc.password}" /><!-- 配置初始化大小、最小、最大 --><property name="initialSize" value="1" /><property name="minIdle" value="1" /><property name="maxActive" value="20" /><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="60000" /><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="60000" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="300000" /><property name="validationQuery" value="SELECT 'x'" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="false" /><property name="maxPoolPreparedStatementPerConnectionSize"
			value="20" /><!-- 配置监控统计拦截的filters --><property name="filters" value="stat" /></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource"><ref bean="dataSource" /></property></bean></beans>

 

 

UserDAO.java

 

/**
 * @author zhangpl
 * @E-mail xingsan.zhang@gmail.com
 * @Date   2014年8月24日  下午11:30:13
 */
@Repository
public class UserDAO {

	@Resource
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 查询
	 * Edited by zhangpl
	 * @return List<Map<String,Object>>
	 */
	public List<Map<String,Object>> getUser(){
		List<Map<String ,Object>> userList = this.jdbcTemplate.queryForList("select *from users");
		return userList;
	}
	/**
	 * 添加
	 * Edited by zhangpl
	 * @param user
	 * @return int
	 */
	public int saveUser(User user){
		int flag = this.jdbcTemplate.update("insert into users(username,password) values ('"+user.getUsername()+"','"+user.getPassword()+"') ");
		return flag;
	}
	/**
	 * 删除
	 * Edited by zhangpl
	 * @param id
	 * @return int
	 */
	public int deleteUser(int id){
		int flag = this.jdbcTemplate.update("delete from users where id = "+id);
		return flag;
	}
	/**
	 * 修改
	 * Edited by zhangpl
	 * @param user
	 * @return int
	 */
	public int updateUser(User user){
		int flag = this.jdbcTemplate.update("update users set username='"+user.getUsername()+"',password='"+user.getPassword()+"' where id="+user.getId());
		return flag;
	}

	
}

 

 

建立测试类UserDAOTest.java

 

/**
 * @author zhangpl
 * @E-mail xingsan.zhang@gmail.com
 * @Date   2014年8月28日  下午10:56:58
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext.xml"})
public class UserDAOTest {
	@Resource
	UserDAO userDAO;
	@Test
	public void testGetUser() throws Exception {
		List list = userDAO.getUser();
		System.out.println(list);
	}
	@Test
	public void testSaveUser() throws Exception {
		User user = new User();
		user.setUsername("zhangsan");
		user.setPassword("123456");
		int flag = userDAO.saveUser(user);
		if(flag>0){
			System.out.println("添加成功!");
		}else{
			System.out.println("添加失败");
		}
	}
	@Test
	public void testUpdateUser() throws Exception {
		User user = new User();
		user.setId(2);
		user.setUsername("zhangxingsan");
		user.setPassword("654321");
		int flag = userDAO.updateUser(user);
		if(flag>0){
			System.out.println("修改成功!");
		}else{
			System.out.println("修改失败!");
		}
	}
	@Test
	public void testDeleteUser() throws Exception {
		int flag = userDAO.deleteUser(2);
		if(flag>0){
			System.out.println("删除成功!");
		}else{
			System.out.println("删除失败!");
		}
	}
}

 

 

测试类中需要注意的地方:

@RunWith:指定单元测试执行类,这里就指定的是SpringJUnit4ClassRunner.class;

@ContextConfiguration:指定Spring的配置文件;

 

记下来是对知识点的一个小结,有不当的地方,欢迎批评指正。





已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Viewing all 15843 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>