( ! ) Deprecated: Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers. in /var/www/html/wp-includes/functions.php on line 6131
Call Stack
#TimeMemoryFunctionLocation
10.0000484224{main}( ).../index.php:0
20.0000484576require( '/var/www/html/wp-blog-header.php ).../index.php:17
30.08684416688require_once( '/var/www/html/wp-includes/template-loader.php ).../wp-blog-header.php:19
40.08744446008include( '/var/www/html/wp-content/themes/twentyfifteen/archive.php ).../template-loader.php:125
50.08744446008get_header( $name = ???, $args = ??? ).../archive.php:19
60.08744446224locate_template( $template_names = [0 => 'header.php'], $load = TRUE, $load_once = TRUE, $args = [] ).../general-template.php:48
70.08744446320load_template( $_template_file = '/var/www/html/wp-content/themes/twentyfifteen/header.php', $load_once = TRUE, $args = [] ).../template.php:749
80.08744446864require_once( '/var/www/html/wp-content/themes/twentyfifteen/header.php ).../template.php:814
90.08764454272wp_head( ).../header.php:18
100.08764454272do_action( $hook_name = 'wp_head' ).../general-template.php:3197
110.08764454488WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
120.08764454488WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
130.08784576256wp_enqueue_scripts( '' ).../class-wp-hook.php:341
140.08784576256do_action( $hook_name = 'wp_enqueue_scripts' ).../script-loader.php:2311
150.08784576472WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
160.08784576472WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
170.08794583992twentyfifteen_scripts( '' ).../class-wp-hook.php:341
180.08814585512wp_style_add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../functions.php:440
190.08814585512WP_Styles->add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../functions.wp-styles.php:245
200.08814585512WP_Dependencies->add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../class-wp-styles.php:385
210.08814585512_deprecated_argument( $function_name = 'WP_Dependencies->add_data()', $version = '6.9.0', $message = 'IE conditional comments are ignored by all supported browsers.' ).../class-wp-dependencies.php:317
220.08814585832wp_trigger_error( $function_name = '', $message = 'Function WP_Dependencies->add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:5925
230.08814586584trigger_error( $message = 'Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:6131

( ! ) Deprecated: Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers. in /var/www/html/wp-includes/functions.php on line 6131
Call Stack
#TimeMemoryFunctionLocation
10.0000484224{main}( ).../index.php:0
20.0000484576require( '/var/www/html/wp-blog-header.php ).../index.php:17
30.08684416688require_once( '/var/www/html/wp-includes/template-loader.php ).../wp-blog-header.php:19
40.08744446008include( '/var/www/html/wp-content/themes/twentyfifteen/archive.php ).../template-loader.php:125
50.08744446008get_header( $name = ???, $args = ??? ).../archive.php:19
60.08744446224locate_template( $template_names = [0 => 'header.php'], $load = TRUE, $load_once = TRUE, $args = [] ).../general-template.php:48
70.08744446320load_template( $_template_file = '/var/www/html/wp-content/themes/twentyfifteen/header.php', $load_once = TRUE, $args = [] ).../template.php:749
80.08744446864require_once( '/var/www/html/wp-content/themes/twentyfifteen/header.php ).../template.php:814
90.08764454272wp_head( ).../header.php:18
100.08764454272do_action( $hook_name = 'wp_head' ).../general-template.php:3197
110.08764454488WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
120.08764454488WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
130.08784576256wp_enqueue_scripts( '' ).../class-wp-hook.php:341
140.08784576256do_action( $hook_name = 'wp_enqueue_scripts' ).../script-loader.php:2311
150.08784576472WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
160.08784576472WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
170.08794583992twentyfifteen_scripts( '' ).../class-wp-hook.php:341
180.11844587688wp_style_add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../functions.php:444
190.11844587688WP_Styles->add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../functions.wp-styles.php:245
200.11844587688WP_Dependencies->add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../class-wp-styles.php:385
210.11844587688_deprecated_argument( $function_name = 'WP_Dependencies->add_data()', $version = '6.9.0', $message = 'IE conditional comments are ignored by all supported browsers.' ).../class-wp-dependencies.php:317
220.11844588008wp_trigger_error( $function_name = '', $message = 'Function WP_Dependencies->add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:5925
230.11854588232trigger_error( $message = 'Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:6131

Spring中基于aop命名空间的AOP


本文地址:http://www.blogjava.net/cmzy/archive/2008/08/23/223870.html
下篇地址:Spring中基于aop命名空间的AOP 二(声明一个切面、切入点和通知)


    在某些时候,我们工程中使用的JDK 不一定就是1.5 以上,也就是说可能不支持Annotation 注解,这时自然也就不能使用@AspectJ 注解驱动的AOP 了,那么如果我们仍然想使用AspectJ 灵活的切入点表达式,那么该如何呢?Spring 为我们提供了基于xml schematic 的aop 命名空间,它的使用方式和@AspectJ 注解类似,不同的是配置信息从注解中转移到了Spring 配置文件中。在这里,我们将详细介绍如何使用Spring 提供的<aop:config/> 标签来配置Spring AOP 。



1 、一点准备工作和一个例子


    使用<aop:config/> 标签,需要给Spring 配置文件中引入基于xml schema 的Spring AOP 命名空间。完成后的Spring 配置文件如下(在该节,所有例程的配置文件中添加了Spring AOP 命名空间,除非特殊情况外,为了节约空间,这部分将在给出的代码中省略),粗体内容即为我们需要添加的内容:






  1. <?xml version=“1.0” encoding=“UTF-8”?>  

  2. <beans xmlns=“http://www.springframework.org/schema/beans”  

  3.         xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”  

  4.         xmlns:aop=“http://www.springframework.org/schema/aop”  

  5.         xsi:schemaLocation=”http://www.springframework.org/schema/beans   

  6.               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    

  7.               http://www.springframework.org/schema/aop    

  8.               http://www.springframework.org/schema/aop/spring-aop-2.5.xsd >  

  9. ………… Spring配置信息   

  10. </beans>  


    关于aop命名空间的标签,我们前面使用过的有<aop:aspectj-autoproxy/>,在这一节,我们将以<aop:config/>标签作为重点。事实上,我们在这一节介绍的所有标签都是该标签的子标签。



   下面有一个例程来直观的展示如何使用<aop:config/>标签来配置Spring AOP(完整代码见例程4.15)。在例子中,我们使用<aop:config/>配置一个切面并拦截目标对象Peoples的SayHello()方法,在它执行前输出提示信息。
首先创建工程AOP_Test4.15,添加Spring IoC和Spring AOP库后,创建aop.test包,新建目标类People,代码如下:






  1. package aop.test;   

  2.   

  3. /**  

  4.  * 该类将作为目标对象对应的类。  

  5.  * @author zhangyong  

  6.  * */  

  7. public class People{   

  8.   

  9.         public String SayHello(String str){   

  10.                 System.out.println(this.getClass().getName()+ “说:”+str);   

  11.                 return str;   

  12.         }   

  13. }   


    修改Spring xml配置文件,将该类注册为一个受管Bean:






  1. <bean id=“TestBean” class=“aop.test.People” />  


    创建含有main()方法的测试类TestMain,从Spring IoC容器中获取Peoples对象,并调用其SayHello()方法,代码如下:






  1. package aop.test;   

  2.   

  3. // import省略   

  4. public class TestMain {   

  5.         public static void main(String[] args) {   

  6.                 // 实例化Spring IoC容器   

  7.                 ApplicationContext ac = new ClassPathXmlApplicationContext(   

  8.                                 “applicationContext.xml”);   

  9.                 // 获取受管Bean的实例   

  10.                 People p = (People) ac.getBean(“TestBean”);   

  11.                 p.SayHello(“传入的参数值”);   

  12.         }   

  13. }   


   创建MyAspect类,添加一个beforeAdvice()方法作为前置通知方法,代码如下:






  1. package aop.test;   

  2.   

  3. import org.aspectj.lang.JoinPoint;   

  4.   

  5. public class MyAspect {   

  6.            

  7.         public void beforeAdvice(JoinPoint point) {   

  8.             System.out.println(“前置通知被触发:” +    

  9.                                 point.getTarget().getClass().getName()+    

  10.                                 “将要” + point.getSignature().getName());   

  11.         }   

  12. }   


    修改xml配置文件,为其添加aop命名空间,并把MyAspect注册为一个受管Bean,作为我们下面定义切面的backing bean。代码如下:






  1. <?xml version=“1.0” encoding=“UTF-8”?>  

  2. <beans xmlns=“http://www.springframework.org/schema/beans”  

  3.         xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”  

  4.         xmlns:aop=“http://www.springframework.org/schema/aop”  

  5.         xsi:schemaLocation=”http://www.springframework.org/schema/beans   

  6. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    

  7.                http://www.springframework.org/schema/aop    

  8. http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”>  

  9.   

  10.         <bean id=“MyAspect” class=“aop.test.MyAspect” />  

  11.         <bean id=“TestBean” class=“aop.test.People” />  

  12.            

  13.         <aop:config proxy-target-class=“true”>  

  14.                 <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  15.                         <aop:pointcut id=“testPointcut”  

  16.                                 expression=“execution(* aop..*(..))” />  

  17.                         <aop:before pointcut-ref=“testPointcut”  

  18.                                 method=“beforeAdvice” />  

  19.                 </aop:aspect>  

  20.         </aop:config>  

  21. </beans>  


    运行主类,输出如下:


例程4.15输出结果


例程4.15输出结果


 


2、声明一个切面
      在基于AOP命名空间的Spring AOP中,要声明一个切面,需要使用<aop:config/>的子标签<aop:aspect>。<aop:aspect>标签有一个ref属性必须被赋值,它用于指定和该切面关联的受管Bean(backing bean,以后我们都将使用Backing Bean来称呼这样的Bean)。正如下例所示,该Bean对应的java类是一个普通的java类,在该类中定义了切面的通知方法。此外,<aop:aspect>标签还有两个可选的order属性和id属性,order属性用于指定该切面的加载顺序,id属性用于标识该切面。范例如下:





  1. <?xml version=“1.0” encoding=“UTF-8”?>  

  2. <beans ……>  

  3.         <bean id=“MyAspect” class=“aop.test.MyAspect” />  

  4.         <aop:config proxy-target-class=“true”>  

  5.                 <aop:aspect ref=“MyAspect” order=“1” id=“TestAspectName”>  

  6.                         ……切面其他配置   

  7.                 </aop:aspect>  

  8.         </aop:config>  

  9. ……其他配置   

  10. </beans>    

 



3、声明一个切入点
      要声明一个切入点,可以使用<aop:aspect>的子标签<aop:pointcut>,在Spring2.5中它有两个属性id和expression,分别用于标示该切入点和设定该切入点表达式。例如:






  1. <?xml version=“1.0” encoding=“UTF-8”?>  

  2. <beans ……>  

  3.     <bean id=“MyAspect” class=“aop.test.MyAspect”/>  

  4.     <aop:config proxy-target-class=“true”>  

  5.         <aop:aspect ref=“MyAspect” order=“1” id=”TestAspectName”>  

  6.               <aop:pointcut id=“test”  

  7.                 expression=“execution(* aop.test.TestBean.*(..))”/>  

  8.               <aop:before pointcut=“aop.test.MyAspect.Pointcut1()”    

  9.                                method=“beforeAdvice” />  

  10.         </aop:aspect>  

  11.     </aop:config>  

  12. ……其他配置   

  13. </beans>  

 




<aop:pointcut>标签的expression属性使用前面介绍的切入点表达式语言,也就是说支持AspectJ切入点表达式。但是由于xml对”&&”、”||”、”!”等逻辑运算符不友好,@AspectJ切入点表达式语言中使用的这些逻辑运算符在xml配置中需要分别用”and”、”or”和”not”来代替。
有时候,我们也需要在xml中使用@Pointcut注解声明的切入点,那么该如何呢?大家可能记得,我们可以在切入点表达式中可以引用另一个切入点。对了,就在这里,我们使用该特性可以完成这个任务,如下:






  1. <aop:pointcut id=“test”   expression=“aop.test.MyAspect.Pointcut1()” />  

 



注意:这里我们必须使用全路径来标示引用的切入点。


4、 声明一个通知
      和@AspectJ一样,基于AOP命名空间的配置也可以定义五种通知类型,并且使用方式和特性类似。与@AspectJ不同的是,配置信息从Annotation中转移到了xml配置文件。
    1)、前置通知
    声明一个前置通知可以使用<aop:aspect>的子标签<aop:before/>。该标签的属性说明如下表:

<aop:before/>标签属性说明





















属性


说明


pointcut


指定该通知的内置切入点


pointcut-ref


通过 id 引用已定义的切入点


method


指定通知对应的方法,该方法必须已在切面的 backing bean 中被声明


arg-names


通过方法的参数名字来匹配切入点参数


      对于一个通知来说,切入点和对应的通知方法是必须的。也就是说,在这些属性中,method属性是必须的,我们必须要给通知指定一个对应的方法;pointcut属性和pointcut-ref必须有一个被指定,以此确定该通知的切入点。范例如下:




  1. <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  2.     <aop:pointcut id=“testPointcut”  

  3.         expression=“execution(* aop.test.TestBean.*(..))”/>  

  4.     <aop:before pointcut-ref=“testPointcut” method=“beforeAdvice”/>  

  5. </aop:aspect>  

 



     2)、 后置通知
     声明一个后置通知使用<aop:after/>标签,它的属性等和<aop:before/>标签类似,下面是范例:




  1. <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  2.     <aop:pointcut id=“testPointcut”  

  3.         expression=“execution(* aop.test.TestBean.*(..))” />  

  4.     <aop:after  pointcut-ref=“testPointcut” method=“AfterAdvice”/>  

  5. </aop:aspect>  

 



     3)、 返回后通知
      <aop:after-returning/>标签可以声明一个返回后通知,该标签的属性和<aop:before/>相比它多了一个returning属性。该属性的意义类似于@AfterReturning注解的returning属性,用于将链接点的返回值传给通知方法。用法如下:




  1. <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  2.     <aop:pointcut id=“testPointcut”  

  3.         expression=“execution(* aop.test.TestBean.*(..))” />  

  4.     <aop:after-returning pointcut-ref=“testPointcut”  

  5.         method=“AfterReturnAdvice” returning=“reVlue” />  

  6. </aop:aspect>  

 



       4)、 异常通知
        声明一个异常通知使用<aop:after-throwing />标签,它有一个类似于throwing属性又来指定该通知匹配的异常类型。用法如下:




  1. <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  2.      <aop:pointcut id=“testPointcut”  

  3.         expression=“execution(* aop.test.TestBean.*(..))” />  

  4.      <aop:after-throwing pointcut-ref=“testPointcut”  

  5.         method=“afterThrowingAdvice” throwing=“throwable” />  

  6. </aop:aspect>  

 



      5)、 环绕通知
      环绕通知是所有通知中功能最强大的通知,用<aop:around/>标签来声明。用法如下:




  1. <aop:aspect ref=“MyAspect” order=“0” id=“Test”>  

  2.     <aop:pointcut id=“testPointcut”  

  3.         expression=“execution(* aop.test.TestBean.*(..))” />  

  4.         <aop:around pointcut-ref=“testPointcut” method=“aroundAdvice”/>  

  5. </aop:aspect>  




(完)


基于OO的可移动DIV窗口。

  项目需要一个可移动的DIV窗口,要求调用简单,可以重用。本人马上就考虑到使用OO了。代码如下:

 

 

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME=”Generator” CONTENT=”EditPlus”>
  <META NAME=”Author” CONTENT=””>
  <META NAME=”Keywords” CONTENT=””>
  <META NAME=”Description” CONTENT=””>
 </HEAD>

 <BODY>
<SCRIPT LANGUAGE=”JavaScript”>
  <!–
var ie=document.all;
var nn6=document.getElementById&&!document.all;
var isdrag=false;
var y,x;
var oDragObj;
var qtD = document;
function $(id){
 return getObj(id);
}
function getObj(id){
 return qtD.getElementById(id);
}
function cleanDiv(obj){
(typeof(obj)==”string”?$(obj):obj).innerHTML=”;
}

function msgWindow(msgContext){

 this.width=400;
 this.height=300;
 this.title = ”;
 this.content = ”;
 this.context = (typeof(msgContext)==”string”?$(msgContext):msgContext);

 this.popup = function(){
  var left = (screen.width – this.width) / 2;
  var top = (screen.height – this.height) / 2 -20;
  this.context.innerHTML ='<div id=”msgwin” style=”position:absolute;left:’+left+’px;top:’+top+’px;width:’+this.width+’px; height:’+this.height+’px; border:#999999 1pt solid; background-color:#F7F7F7″>’+
      ‘<div id=”title_0″ style=”width:100%; height:30px; background-image:url(http://www.1363.cn/images/btn_close.gif” onclick=”javascript:cleanDiv(\’context\’)” style=”cursor:hand; margin-top:6px;”/></div></div>’+
      ‘<div id=”txt”  style=”width:95%; height:90%; text-align:left;overflow: hidden; padding-left:10px;line-height:24px; color:#333333; font-size:12px; “>’+this.content+'</div></div>’;
  document.onmousedown=initDrag;
  document.onmouseup=new Function(“isdrag=false”);
 }
}

function moveMouse(e) {
 if (isdrag) {
  oDragObj.style.top  =  (nn6 ? nTY + e.clientY – y : nTY + event.clientY – y)+”px”;
  oDragObj.style.left  =  (nn6 ? nTX + e.clientX – x : nTX + event.clientX – x)+”px”;
  return false;
 }
}

function initDrag(e) {
 var oDragHandle = nn6 ? e.target : event.srcElement;
 if(oDragHandle.tagName!=’DIV’ || oDragHandle.id==’txt’)return;
 var topElement = “HTML”;
 while (oDragHandle.tagName != topElement && oDragHandle.id != “msgwin”) {
  oDragHandle = nn6 ? oDragHandle.parentNode : oDragHandle.parentElement;
 }
 if (oDragHandle.id==”msgwin”) {
  isdrag = true;
  oDragObj = oDragHandle;
  nTY = parseInt(oDragObj.style.top+0);
  y = nn6 ? e.clientY : event.clientY;
  nTX = parseInt(oDragObj.style.left+0);
  x = nn6 ? e.clientX : event.clientX;
  document.onmousemove=moveMouse;
  return false;
 }
}


function testNotes(member_id,truename){
 msg = new msgWindow(‘context’);
 msg.title=”提示窗口”;
 msg.content =’  欢迎光临本站。’;
 msg.popup();
}
  //–>
  </SCRIPT> 
  <div id=’context’></div>

  <SCRIPT LANGUAGE=”JavaScript”>
  <!–
 
testNotes(1,’aa’);
  //–>
  </SCRIPT>
 </BODY>
</HTML>

JavaRebel 1.2发布,充分支持Spring

JavaRebel是一个JVM插件(-javaagent),能够即时重载java class更改,因此不需要重新部署一个应用或者重启容器,节约开发者时间。它是一个Java EE和Java 独立应用的常用解决方案。最新的稳定版本JavaRebel代码加载包含一个Spring的插件,能重新加载Spring配置快速的促进生产力的发展,甚至更多。查看Screencast ,下载JavaRebel插件

这个稳定的JavaRebel主要致力于两个主题:稳定和可扩展性。下面是它与1.1版本的区别:

core:增强了core的JavaRebel现在可以处理任何复杂的代码或容器。
SDK:您可以对应用程序和库的任何部分进行增值,无论您身在何处或怎么设置。SDk 为开放源代码。
JavaRebel插件:现在支持自定义的classloaders更容易,容器和框架只需登记一个小插件即可。
Eauinox OSGi容器,现在支持IBM WebSphere 和 Atlassian 混合插件。

查看完整的更新列表 或现在就开始下载JavaRebel

我们已经准备了一个Screencast来说明Spring插件的功能。查看该插件的安装手册 ,了解更多的详情或现在就下载

另类加水印——根据明暗度分别加不同的水印


  1. package image;   

  2.   

  3. import java.awt.AlphaComposite;   

  4. import java.awt.Color;   

  5. import java.awt.Font;   

  6. import java.awt.Graphics;   

  7. import java.awt.Graphics2D;   

  8. import java.awt.Image;   

  9. import java.awt.image.BufferedImage;   

  10. import java.awt.image.ColorModel;   

  11. import java.awt.image.PixelGrabber;   

  12. import java.io.File;   

  13. import java.io.FileOutputStream;   

  14.   

  15. import javax.imageio.ImageIO;   

  16.   

  17. import com.sun.image.codec.jpeg.JPEGCodec;   

  18. import com.sun.image.codec.jpeg.JPEGImageEncoder;   

  19.   

  20. public class WaterMark {   

  21.   

  22.     /**  

  23.      * 获取指定矩形中的像素的矩阵  

  24.      *   

  25.      * @param imageSrc  

  26.      * @param startX  

  27.      * @param startY  

  28.      * @param w  

  29.      * @param h  

  30.      * @return  

  31.      */  

  32.     private int[] getPixArray(Image imageSrc, int startX, int startY,   

  33.             int w, int h) {   

  34.         int[] pix = new int[(w – startX) * (h – startY)];   

  35.            

  36.         /*下面是别人程序中的一段,我实在不明白为何要加这一段,因为我去掉也没有问题,加上还会报错*/  

  37.         PixelGrabber pg = null;   

  38.         try {   

  39.             pg = new PixelGrabber(imageSrc, startX, startY, w-startX, h-startY, pix, 0, w);   

  40.             if (pg.grabPixels() != true) {   

  41.                 try {   

  42.                     throw new java.awt.AWTException(“pg error” + pg.status());   

  43.                 } catch (Exception eq) {   

  44.                     eq.printStackTrace();   

  45.                 }   

  46.             }   

  47.         } catch (Exception ex) {   

  48.             ex.printStackTrace();   

  49.         }   

  50.         return pix;   

  51.     }   

  52.   

  53.     /**  

  54.      * 将1张图片和另1张图片的指定区域重合。可用于制作水印。图片的左上角坐标为0,0  

  55.      *   

  56.      * @param lightnessWaterImg  

  57.      *            颜色比较亮的水印图片,适合底色比较暗的情况  

  58.      * @param darknessWaterImg  

  59.      *            颜色比较暗的水印图片,适合底色比较亮的情况,如果不想区分,则输入null,平均灰度边界同时失效。  

  60.      * @param targetImg  

  61.      *            源图片  

  62.      * @param startX  

  63.      * @param startY  

  64.      * @param x  

  65.      * @param y  

  66.      * @param alpha  

  67.      *            透明度,0f为全透明,1f为完全不透明,0.5f为半透明  

  68.      * @param averageGray  

  69.      *            平均灰度边界(0-255),大于此值,则打暗的水印图片,小于此值则打亮的水印图片。  

  70.      *            默认值128。超过范围,按默认值进行。  

  71.      */  

  72.     private final void pressImage(String lightnessWaterImg,   

  73.             String darknessWaterImg, String targetImg, int startX, int startY,   

  74.             int x, int y, float alpha, float averageGray) {   

  75.         try {   

  76.             // 先判断亮水印和源文件的值是否为null,否则抛出异常   

  77.             if (lightnessWaterImg == null || lightnessWaterImg == “”  

  78.                     || targetImg == null || targetImg == “”) {   

  79.                 throw new Exception(“亮水印或者源图片的地址不能为空”);   

  80.             }    

  81.             // 再判断平均灰度边界是否越界   

  82.             if (averageGray>255||averageGray<0) {   

  83.                 averageGray = 128;   

  84.             }   

  85.                

  86.   

  87.             // 装载源图片   

  88.             File _file = new File(targetImg);   

  89.             // 图片装入内存   

  90.             BufferedImage src = ImageIO.read(_file);   

  91.             // 获取图片的尺寸   

  92.             int width = src.getWidth(null);   

  93.             int height = src.getHeight(null);   

  94.             // 根据源图片尺寸,设置预装载的一个图片,默认是RGB格式的   

  95.             BufferedImage image = new BufferedImage(width, height,   

  96.                     BufferedImage.TYPE_INT_RGB);   

  97.             Graphics2D graphics = image.createGraphics();   

  98.             // 绘制内存中的源图片至指定的矩形内   

  99.             graphics.drawImage(src, 00, width, height, null);   

  100.             // 在已经绘制的图片中加入透明度通道   

  101.             graphics.setComposite(AlphaComposite.getInstance(   

  102.                     AlphaComposite.SRC_ATOP, alpha));   

  103.                

  104.   

  105.             // 获取源图片中和设定的同样大小的区域内的像素集合   

  106.             int[] pixels = getPixArray(src, startX, startY, x, y);   

  107.   

  108.             //查询此集合的平均灰度   

  109.             float average = getAverageGrap(x-startX,y-startY,pixels);   

  110.   

  111.             // 如果平均灰度大于130,则说明此区域比较亮,否则则比较暗   

  112.             System.out.println(average);   

  113.   

  114.                

  115.             //装载水印图片所需参数   

  116.             File water;   

  117.             BufferedImage bufferwater;   

  118.                

  119.             // 根据设定的平均灰度边界来装载不同的水印   

  120.             if (darknessWaterImg == null||average>=averageGray) {   

  121.                 // 装载亮水印文件   

  122.                 water = new File(darknessWaterImg);   

  123.             }else{   

  124.                 // 装载暗水印文件   

  125.                 water = new File(lightnessWaterImg);   

  126.             }   

  127.             // 装入内存   

  128.             bufferwater = ImageIO.read(water);   

  129.                            

  130.             graphics.drawImage(bufferwater, startX, startY, x, y,   

  131.                     null);   

  132.             // 水印文件结束   

  133.             graphics.dispose();   

  134.             FileOutputStream out = new FileOutputStream(targetImg);   

  135.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);   

  136.             // 绘制新的文件   

  137.             encoder.encode(image);   

  138.             out.close();   

  139.                

  140.         } catch (Exception e) {   

  141.             e.printStackTrace();   

  142.         }   

  143.     }   

  144.            

  145.     /**  

  146.      * 查询某个区域的平均灰度  

  147.      * @param width  

  148.      * @param height  

  149.      * @param pixels  

  150.      * @return  

  151.      */  

  152.     private float getAverageGrap(int width,int height,int[] pixels){   

  153.         /* 下面是开始算这个区域的亮度了,灰度等同于亮度 */  

  154.         ColorModel colorModel = ColorModel.getRGBdefault();   

  155.         int i = 0;   

  156.         int j = 0;   

  157.         int k = 0;   

  158.         int r = 0;   

  159.         int g = 0;   

  160.         int b = 0;   

  161.         int gray = 0;   

  162.         float average = 0;// 平均灰度   

  163.         for (i = 0; i < height; i++) {   

  164.             for (j = 0; j < width; j++) {   

  165.                 // 定位像素点   

  166.                 k = i * width + j;   

  167.                 r = colorModel.getRed(pixels[k]);   

  168.                 g = colorModel.getGreen(pixels[k]);   

  169.                 b = colorModel.getBlue(pixels[k]);   

  170.   

  171.                 // 计算灰度值   

  172.                 gray = (r * 38 + g * 75 + b * 15) >> 7;   

  173.   

  174.                 average = average + gray;   

  175.             }   

  176.         }   

  177.         // 计算平均灰度   

  178.         average = average / ((i – 1) * (j – 1));   

  179.         return average;   

  180.     }   

  181.     public static void main(String[] args) {   

  182.         WaterMark waterMark = new WaterMark();   

  183.   

  184.         waterMark.pressImage(“F:\\Mine\\My Pictures\\素材\\w2.png”“F:\\Mine\\My Pictures\\素材\\w1.png”,   

  185.                 “F:\\Mine\\My Pictures\\素材\\2.jpg”5205009008000.5f, 50);   

  186.         System.out.print(“添加成功”);   

  187.     }   

  188.   

  189. }  

一个体现Java接口及工厂模式优点的例子

     随着模式概念的普及,了解模式和使用模式的程序员越来越多,很多人在学习模式的时候,都会有这样一种疑惑:“有必要搞得这么复杂吗?”。的确,因为教程的例子过于简单化(这样方便读者学习),或者是作者选例子的时候并没有很好体现所讲模式的优点,很多情况下如果仅就其例子的问题来说,用模式是太复杂了。因此才导致这样的误解:“模式就是把简单的问题复杂化吗?”。当然不是,随着你开发实践的不断丰富,你终会发现模式强大威力,而且模式也并非贵族化的编程方式,它就是一些经过提炼了的解决问题的方法技巧。

 

      通过学习模式,程序员开始告别过去准直线式的代码方式,模式开扩了我们的视野,强化了我们面向对象编程的思维方式。然而现在又出现了另一个普遍的问题,盲目应用模式。模式是问题的解决方案,先有问题才有模式,模式是依附于所要解决的问题的而生的。必须了解模式在很多情况下是以提高代码的复杂度为代价来增强灵活性、可复用性。如果在自已的代码中使用某一模式仅只提高了代码的复杂度,而其它方面收效甚微,或者某部份代码根本就不存在灵活性及高复用性的需求,那么我们就没有必要为使用模式而放弃更直观简单的代码写法。

 

      一流的高手90%精力关注问题的解决方案,因为找到了好的解决方案,再写起代码会很轻松代码也简洁流畅,看这样的代码是一种享受和提高;二流的熟手90%精力关注代码实现,因为问题的解决方案并非最佳,实现的代码也会比较复杂;三流菜鸟记流水帐,90%精力在敲键盘,常常做了大半才发现行不通,回过头来再用90%的时间敲键盘,根本不会用到任何模式,写出来的代码的只有他自已才能看懂。做出来的软件也是支离破碎,做一丁点改动都要大费周折,而且你还不知道改动后会产生什么问题,大有住危房里的感觉。

 

      在这里还是举一个滥用模式的例子吧。我曾参与过一个大集团公司OA系统的第二期开发,开发沿用原有代码架构并增加新的功能模块。文档很少我读原代码时就被它程序里的代码转来转去搞得头大如斗,最后读懂了:原代码架构总体采用工厂模式,而且是最复杂的抽象工厂模式。它把所有模块类都通过工厂生成还工厂套工厂,并且每一个模块类都有一个接口,每个接口也只有一个模块现实类,因为涉及权限控制还用了代理(proxy)模式。 读懂代码后我开始嵌入代码,发现每新增一个类,都要到六个Java文件中去增加相应代码,而在类中每增加一个方法,也要到它的接口等四个Java文件中去增加相应代码。天呀!!!记得当时我的小姆指常会不听使唤,就是因为频繁的使用Ctrl+C 、Ctrl+V,小姆指按着Ctrl键给累的。整个项目组苦不堪言,真烦透了。项目结束后我回顾发现:代理模式用得还对(现在针对权限这类横向控制有AOP编程这种新的解决办法了)但工厂模式在这里根本就是画蛇添足,不仅没有解决什么问题,反而增加代码复杂度和耦合性,降低了开发效率连维护难度都提高了。而且那种每个类简单的加一个接口的方式,更是没有道理,这让我很想说周星驰说过的一句话:“球~~~不是这么踢~~~~的,接口~~~不是这么用~~~的”。言归正传,我们先来看这样一个常见问题:某系统需要支持多种类型的数据库。用过Oracle、MSSQL等数据库的人都知道,它们的SQL编写方式都各有些不同。比如说Oracle的唯一标识自动+1字段用的是序列,MSSQL改一下字段属性就成了,还有各种各自特有的SQL用法。为了支持多数据库,难道我们要开发多套系统?当然NO。请看下面的解决方案。

 

      即然数据库存在多种,我们可以将系统中所有对数据库的操作抽象出来,写成一个个方法组合到一个类中,有几种数据库我们就写几个这样的类。具体设计类图如下:

20060910.gif

 

 

简要说明:


  • OracleDataOperate、SqlserverDataOperate、MysqlDataOperate,分别代表Oracle、Sqlserver、Mysql这三种数据库的操作类。继承自AbstractDataOperate
  • AbstractDataOperate是一个抽象类,包含了那些不同种类数据库都是一样代码的操作方法。继承自DataOperate
  • DataOperate是上面说的数据操作类的统一接口,只有两个方法:取得一条记录、插入一条记录。
  • DataOperateFactory是一个工厂方法,统一用它的方法来得到数据库操作类的实例。
  • SampleClass是我们系统的某个功能模块的类。
  • People是一个实体类,代表一条记录。三个字段 oid唯一标识符、name姓名、date生日。

 

详细说明:

1、所有系统功能模块类只认DataOperat这个接口还不必管具体的实现类是OracleDataOperate还SqlserverDataOperate。DataOperate源代码如下:

publicinterface DataOperate {

    //根据记录的唯一标识取出一条记录

    People getPeople(String oid);

    //插入一条记录

    boolean insertPeople(People people);

}

 

2、AbstractDataOperate、OracleDataOperate、SqlserverDataOperate、MysqlDataOperate都是继承DataOperate接口的,没什么好说的,省略。

 

3、DataOperateFactory。我们看看工厂方法怎么写的。

publicclass DataOperateFactory {

    publicstaticfinalint ORACLE = 0; //定义三个表示数据库类型的常量

    publicstaticfinalint MYSQL = 1;

    publicstaticfinalint SQLSERVER = 2;

 

    privatestatic DataOperate db;

    privatestaticint dataType = MYSQL;

    /**

     * 根据数据库类型(dataType)取得一个数据库操作类的实例,

     * 这里对DataOperate使用了单例模式,因为OracelDataOperate等都是无状态的工具类,

     * 所以整个系统只保留一个实例就行了。

     *

     * @return 返回的是接口,客户端不必关心具体是用那个实现类

     */

    publicstatic DataOperate getInstance() {

        if (db == null) {

            if (dataType == ORACLE) //根据dateType返回相应的实现类

                returnnew OracelDataOperate();

            if (dataType == MYSQL)

                returnnew MysqlDataOperate();

            if (dataType == SQLSERVER)

                returnnew SqlserverDataOperate();

        }

        return db;

    }

}

 

4、接下来就看看使用端是如何调用工厂方法和使用数据操作类的。

/**

 * 系统某个功能类

 */

publicclass SampleClass {

private DataOperate db; //声明一个数据库操作类,注意这里用的是接口噢

    /**某方法*/

    publicvoid sampleMethod() {

        db = DataOperateFactory.getInstance();//得到单一实例

        People p = db.getPeople(“123”); //取得一条记录

        db.insertPeople(p);//再插回去

    }

}

 

  我们发现SampleClass中根本没有出现OracelDataOperate、MysqlDataOperate等的影子,这就是接口的威力。客户端不必针对OracelDataOperate等写不同的代码,它只关心DataOperate即可,具体要取那个类的逻辑就由DataOperateFactory负责了。

 

总结:



  • 从例子中我们可以看到什么是面向接口的编程方式。SampleClass使用数据操作类可以不必关心具体是那个类,只要是符合接口的都行


  • 要实例?只须调用DataOperateFactory.getInstance()即可,其它的交于DataOperateFactory这个工厂来做吧,使用端什么都不用关心。


  • 我们要支持新的数据库类型,只须要象OracelDataOperate那样,再写一个继承AbstractDataOperate的类即可,比如SysbaseDataOperate。然后到DataOperateFactory中加入相应代码即可。


  • 如果我们想要可配置性更高,可以用privatestaticint dataType = MYSQL;中的值设置到一个文本文件中。

  对于开发支持多种数据库的系统,强烈建议使用hibernate,我现在做的系统就是用hibernate的,开发时用Mysql,到要给客户时将数据库换了DB2,程序不用做任何改动,真正的无逢移植。不过这样,本文所提到的方法就没什么用了.

使用JRockit Mission Control进行性能分析和调优


Mission ControlBEA JRockit JVM自带的一组以极低的开销来监控、管理和分析生产环境中的应用程序的工具。它包括三个独立的应用程序:内存泄漏监测器(Memory Leak Detector)、JVM运行时分析器(Runtime Analyzer)和管理控制台(Management Console)。BEAJRockit R26版本就开始捆绑这个工具套件,目前最新的版本是3.0。最近我们使用其中的Runtime Analyzer对国内某著名行业解决方案进行性分析和调优。


 


JRockit Runtime AnalyzerJRA)是一个JVM分析器,是一个随需应变的“动态记录器”。它记录了Java应用程序和JVM在一段预定的时间内的详细记录。然后通过JRA应用程序对记录下来的文件进行离线分析。所记录的数据包括对方法的调用跟踪、错误的同步、锁定的分析,还有垃圾收集统计信息,优化决策以及对象统计信息和其他重要的应用程序/JVM行为。它的目的是让JRockit开发人员能够找到良好的方法来基于现实应用程序优化JVM,对于帮助客户在生产和开发环境中解决问题十分有用。


 


2.性能数据分析和调优


 


在本次项目中,操作|A和操作B的百人并发脚本执行完成的时间接近两分钟,因此我们使用JRA进行了2分钟(120)的记录。在GC常规信息中,我们发现在短短两分钟时间内,垃圾收集的总数高达365次,而由此造成的暂停时间有42.5秒之多。也就是说35%的执行时间是在做垃圾收集。


 


因为最大堆尺寸已经设置成1024M,对于32位操作系统上的Java应用已经是足够大了(在IA32构架下,由于操作系统给每个进程的最大内存寻址空间为1.8G,因此最大堆尺寸不能超过1.8G),因此堆的大小并不是造成频繁垃圾收集的原因。那么在高并发度的场景下,可能的影响因素很可能是Nursery大小。


 


Nursery 也称为新代,是指运行分代式垃圾收集器时,在堆中分配 新对象 的可用块区域。 Nursery 变满时,会在新垃圾收集中单独对其进行垃圾收集。Nursery 大小决定了新收集的频率和持续时间。较大 Nursery 会降低收集的频率,但是会稍微增加每个新收集的持续时间。 Nursery 之所以具有价值,是因为 Java 应用程序中的大多数对象都是在新代中夭亡的。与收集整个堆相比,应首选从新空间中收集垃圾,因为该收集过程的开销更低,而且在触发收集时,新空间中的大多数对象均已死亡。在新收集过程中,JVM 首先确定 Nursery 中的哪些对象是活动的,此后将它们提升到旧空间,并释放 Nursery,供分配新的小对象使用


 


Nursery的默认缺省值是10M/CPU,对于我们Clovertown服务器来说,只有20M。由于出现频繁收集的情况,那么我们推断是由于Nursery的默认值太低的原因。一方面在高并发用户的场景下,肯定是有大量的新对象产生,那么Nursery的空闲空间很容易就被耗尽。因此Nursery发生垃圾收集频率就会比较高。另一方面更短的垃圾收集间隔会使得新对象在Nursery的存活率提高因为很多新对象可能还没来得及使用完毕就已经发生垃圾收集。这样更多的对象会被提升到旧代,使得旧代的对象也会急剧增加,从而使得旧代发生垃圾收集的频率也增加。


 


因为JRockit JVM可以使用-Xns:<size>来设置Nursery的尺寸,我们要在保证垃圾回收停顿时间(garbage collection-pause)尽可能短的同时,尽量加大Nursery的尺寸,这在创建了大量的临时对象时尤其重要。推荐值是最大堆尺寸的10%,因此我们在JRockit的运行时参数上添加了 –Xns100m。再次运行脚本后,JRA收集的信息显示GC暂停时间骤降到15.3s,次数也有所减少,降到296


 




















Nursery大小


20M(默认值)


100M


GC暂停时间


42.5s


15.3s


垃圾收集的总数


365


296


平均暂停时间


116ms


52ms


 


此外,我们从方法信息中可以看到调用次数最多耗时间最长的两个方法分别是jrockit.vm.Locks.monitorEnterSecondStagecom.ABC.StateManager.makeState两个方法。展开前置任务后发现调用这两个方法最多的方法是com.ABC.SqlQueryAction.query。而jrockit.vm.Locks.monitorEnterSecondStage显然是JRockit实现锁机制的特定的API。因此我们怀疑是对数据库的操作时有资源互斥的现象发现。


 


考虑到高并发用户的场景下,对数据库操作的并发度也很高,因此对数据库连接的争用比较激烈。我们察看了一下当时WebLogic JDBC的配置,发现connection pool的大小只是缺省值20,相对来说偏小了,对性能会有一定的影响。因此我们增大connection pool的大小到100。重新运行测试脚本后发现性能有较大提升。


 


 



















 


JDBC connection size 20  w/ default nursery


JDBC connection size 100 w/ 100M nursery


Increase %


 


操作A


22.125


12.079


83%


操作B


35.195


21.773


62%


 


 


在性能调优完成后,我们又进行了功能测试(回归测试),以验证上述改动没有影响系统的功能性正确。


四、小结


其实利用Mission ControlJava应用进行调优并不难,对吧?希望本次性能分析调优的过程可以给大家一些启发,今后可以应用到日常工作中。

resin clustering

本文主要讲述resin的clustering,简单明了。由于条件限制,只使用一台服务器,运行多个resin来实现clustering,如果多台服务器,只要修改相应的ip地下就可以了。

 

步骤1:

配置好resin.conf,至少可以把web应用运行起来。

 

步骤2:

执行:cp resin.conf resin-web.conf

 

resin.conf作为clustering的配置文件;

resin-web.conf为作web-tier的配置文件;

 

修改resin.conf

把app-tier中的<http address=”*” port=”80″/> 修改为       <!–http address=”*” port=”80″/–>

 

在<!– define the servers in the cluster –>下面增加servers(ip和端口可以自行修改)

 <server id=”a” address=”192.168.1.65″ port=”6800″/>
 <server id=”b” address=”192.168.1.64″ port=”6801″/>

 

修改resin-web.conf


在<!– define the servers in the cluster –>下面增加servers(ip和端口可以自行修改)

 <server id=”a” address=”192.168.1.65″ port=”6800″/>
 <server id=”b” address=”192.168.1.64″ port=”6801″/>

 

把web-tier中的 <http address=”*” port=”9080″/>修改为 <http address=”*” port=”80″/>

 

步骤3:

启动app-tier

java -jar lib/resin.jar -conf conf/resin.conf -server a &

java -jar lib/resin.jar -conf conf/resin.conf -server b &

 

启动web-tier

java -jar lib/resin.jar -conf conf/resin-web.conf -server web-a &

 

打开浏览器输入localhost

看看输出什么?

 

试着把a关闭,再打开locahost看看?

 

成功了吧?

使用JRockit作为Eclipse的Java VM


早些天写了一篇关于调整Eclipse启动的blog,目的还是希望提升Eclipse(包括启动时)的总体性能。 今天,尝试了一下使用BEA JRockit来作为Eclipse的JVM,同时使用JRockit来编译所有的项目。


安装JRockit:


1. 从BEA下载最新的JRockit。 JRockit据说是Wintel平台下最快的Java编译器(以前还有IBM的JDK和Jike,IBM JDK现在是WebSphere的一部分,而最先支持增量编译的Jike已经贡献给Eclipse了,BEA也将会把JRockit贡献给Eclipse。 天下归一啊)。 BEA的JRockit主页在这里,从这里下载最新的JRockit 5.0(我下载的是R26.4.0),大约75MB。


2. 安装JRockit非常容易,不停的”Next”即可。 安装完以后,可以把JAVA_HOME设置为JRockit(可选项)。


配置Eclipse:


1. Eclipse启动参数。 其实就是像前一篇所说的那样,在Eclipse启动参数里面修改-vm的值,使用JRockit来启动Eclipse。比如我修改为:


C:\Java\eclipse\eclipse.exe -vm C:\java\jrockit-R26.4.0-jdk1.5.0_06\ bin\javaw.exe -vmargs -Xms256m -Xmx512m -XXsetgc:singleparpar -XXcompactratio:1


2. 在Eclipse里面,安装JRockit,即在Installed JRE中添加JRockit,并设置为默认。 这样,就可以用JRockit来编译项目了。


至于性能:


Eclipse(我的Eclipse是v3.2 Callisto,含所有的插件,以及Crystal Report, SWT Designer, PowerDesigner,Mylar, FindBugs等插件)启动的时候,比使用Sun JDK 1.5要快一些(但不是快很多很多,毕竟Sun JDK 1.5的性能已经提升了),大约能有10-15%的改进吧。 我的工程一共有95个plug-in项目和1个Web项目。


之后,我可能会尝试一下把JRockit用到Glassfish的服务器上,看看效果如何。


【参考文章】Running BEA Workshop/Eclipse with JRockit 5.0


Technorati : ,
Del.icio.us : ,

linux下crontab时间的格式说明

cron 配置计划任务的书写格式


说明:

第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59
第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23
第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31
第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12
第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。
每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;
第七段应该定义的是:执行的命令和参数。

注:其中用户名可是省略,用户名定义的是程序用哪个用户来执行,比如mysql服务器,我们可以定义成以mysql用户来启动、停止、重新 启动,这时要写上用户名;不过对于cron来说意义不是太大,因为每个用户都有自己的cron配置文件。有些程序的启动必须用到root用户,这时我们就 可以修改root用户的cron配置文件就行了。在每个用户的配置文件中,不必指定用户名。


我们可以把计划任务写在全局性配置文件中,如果您想把一个计划放入全局性配置文件中,就得改发行版所对应的cron全局配置文件,比如Fedora 5的全局性配置文件是/etc/crontab文件;


每个用户也能定义自己的cron配置文件,用crontab -e 命令来定义;


举一例:让机器在每天8点30分重新启动;


关于时间格式中有7个字段。我们可以直接更改或者添加,当然这是系统任务调用。举个例子,比如我在每天的早上8点30分重新启动机器,就可以在
/etc/crontab中加入下面的两句,第一句就是注释了。以#号开始,后面写一个自己能知道这是什么任务的备注;


# reboot OS
30 8 * * * root /sbin/reboot

第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59
第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23
第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31
第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12
第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。
每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;
第七段应该定义的是:执行的命令和参数。


对比上面的例子就知道,30是不是分钟??8是不是小时?如果有*代表的地方,表示全部,也就是说,每个月,每天,每星期都要执行。root 表示用root用户执行,命令是/sbin/reboot ,也就是说,系统在每天 8点30分重新启动;


我们可以把每天8点30分重新启动的计划任务写入cron全局性配置文件中,也可以定义在root用户自己的cron配置文件中。如果定义在 root自己的配置文件,请用root身份来执行 crontab -e 来修改配置文件;crontab -e 进入修改配置文件的过程,其实和vi的用法一样.


Google Guice Example

最近在研究Google 的 Guice,感觉用起来挺简单的,入门应该比Spring要容易的多,这也许是因为Guice刚刚出世,很功能还没有完善吧,但据说Google内部已经在用了,我想再过一段时间取Spring而代之也不是没有可能,至少也能跟Spring平分天下吧。

下面是一个简单的小实例

1.业务逻辑接口

package com.hawkunion.guice;

/**

*

* @author 杜庆明

*/

public interface Work {

     public void sayHello(String userName);

}

2.实现接口的业务逻辑

package com.hawkunion.guice;

/**

*

* @author 杜庆明

*/

public class WorkImpl implements Work{

   

     public void sayHello(String userName) {

         System.out.println(“Hello! 欢迎你:”+userName);

     }

   

}

3.要用到业务逻辑的类

package com.hawkunion.guice;

import com.google.inject.Inject;

/**

*

* @author 杜庆明

*/

public class RunWorkClass {

   

     private Work work = null;

   

     @Inject

     public void setWork(Work workimpl){

         this.work = workimpl;

     }

   

     public void runWork(){

         work.sayHello(“阿杜”);

     }   

}

4.Module

package com.hawkunion.guice;

import com.google.inject.Binder;

import com.google.inject.Module;

/**

*

* @author 杜庆明

*/

public class MyModule implements Module {

     public void configure(Binder binder) {

         binder.bind(Work.class).to(WorkImpl.class);

     }

}

5.测试

package com.hawkunion.guice;

import com.google.inject.Guice;

import com.google.inject.Injector;

import com.google.inject.Module;

/**

*

* @author 杜庆明

*/

public class TestWork {

   

     public static void main(String args[]){

         RunWorkClass runWorkClass = new RunWorkClass();

         Module module = new MyModule();

       

         Injector in = Guice.createInjector(module);//把module给Guice

         in.injectMembers(runWorkClass);//让Guice把需要注入的业务逻辑注入给对象

         runWorkClass.runWork();//   运行work

     }

}