Thinking

快乐编程,开心生活
posts - 21, comments - 27, trackbacks - 0, articles - -5
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2007年2月6日

CCP Review-Javascript
1、对于div中的input标签,如果div的style.display属性为'none',那么调用input标签的focus方法在IE6.0上会报错,首先应该让其display属性为''或者'block'再调用;
2、当HTML元素的name属性唯一时可以利用document.getElementById()调用获得这个元素;
3、如果异步提交耗时较长,可在异步提交之前显示等待提示,在回调函数中根据返回值更新提示;
4、在JS中function也是可以作为变量的,所以我们可以在自己封装的框架中预留回调函数供自定义使用,如下面的代码:
 1 //common.js
 2 var callback = null;
 3 function commonUse(){
 4   
 5   if(typeof(callback) == "function"){
 6     callback();
 7   }
 8   
 9 }
10 
11 //self.js
12 function selfUse(){
13   
14   callback = function(){
15     //do something before
16   }
17   commonUse();
18   
19 }

5、JS中可以使用正则表达式来校验数字域、日期域和EMail等。代码示例如下:
校验日期的例子:
 1     function isDate(date){
 2         //对日期格式进行验证 要求为2000-2099年  格式为 yyyy-mm-dd 并且可以正常转换成正确的日期
 3         var regex=/^(19|20)\d{2}-((0[1-9]{1})|(1[0-2]{1}))-((0[1-9]{1})|([1-2]{1}[0-9]{1})|(3[0-1]{1}))$/;
 4         
 5         if(!regex.test(date)){
 6             return false;
 7         }
 8         var arr_=date.split("-");
 9         var tmp = new Date(arr_[0], parseFloat(arr_[1])-1, parseFloat(arr_[2]));
10         if(tmp.getFullYear()!=parseFloat(arr_[0]) 
11             || tmp.getMonth()!=parseFloat(arr_[1])-1 
12             || tmp.getDate()!=parseFloat(arr_[2])){
13             return false;
14         }
15          
16          return true;
17     }
  这篇文章有详细的说明:http://www.blogjava.net/byterat/archive/2006/12/20/89143.html
  这本电子书是讲解正则表达式的:http://www.blogjava.net/Files/kawaii/RegularExpressions.zip 
6、在JS编码中,如果代码量较大,要注意防止function名称重复,包括直接在页面上编写的和引用外部JS文件的,不然会出现一些莫名奇妙的问题;
7、注意JS代码中的函数返回语句return的使用;
8、尽量把JS代码写在外部公共的文件中,而在页面中引入,好处有:a.函数复用;b.JS文件缓存;c.提供页面解析速度。基于b,我们在修改JS代码后,要看IE的设置是否将原先的JS文件缓存造成问题;
9、对于同一个页面的多个表单提交,我们可以在第一个表单中设置相应的隐藏域,在表单提交之前利用JS脚本把其他表单的数据设置到第一个表单的隐藏域中;
10、对于异步校验的文本框,我们一般设置触发事件为onblur而不是onchange或者onpropertychange,以减少客户端和服务器的交互次数,但应该注意如果这个文本框最初没有获得焦点,那么onblur就不会触发,可以先调用以下onfocus,再调用onblur手动触发;
11、JS中不存在trim()函数,自定义如下:
 1 //JS去除首尾空格(同VBS的Trim)
 2     function trim(inputString) {   
 3         if (typeof inputString != "string") {
 4             return inputString; 
 5         }
 6         var retValue = inputString;
 7         var ch = retValue.substring(01);
 8         while (ch == " ") {
 9                //检查字符串开始部分的空格
10             retValue = retValue.substring(1, retValue.length);
11             ch = retValue.substring(01);
12         }
13         ch = retValue.substring(retValue.length-1, retValue.length);
14         while (ch == " ") {
15             //检查字符串结束部分的空格
16             retValue = retValue.substring(0, retValue.length-1);
17             ch = retValue.substring(retValue.length-1, retValue.length);
18         }
19         while (retValue.indexOf("  "!= -1) {
20             //将文字中间多个相连的空格变为一个空格
21             retValue = retValue.substring(0, retValue.indexOf("  ")) 
22                 + retValue.substring(retValue.indexOf("  ")+1, retValue.length);
23         }
24         return retValue;
25     }
12、JS中显示模式窗口,代码如下:
 1 function showMyDialog(){
 2   var dialogProperty = 'dialogWidth:800px;dialogHeight:600px;status:no';
 3   var windowProperty = "height=800,width=800,status=no,toolbar=no,menubar=yes,location=yes,resizable=yes,scrollbars=yes";
 4 
 5   var url = "SomeAction.do?id="+id+"&flag=true";
 6   var returnVal = window.showModalDialog(url,"", dialogProperty);
 7   if(typeof(returnVal) == "undefined"){
 8     return;
 9   }
10   if(returnVal !=  ""){
11     //do something   
12   }
13 }
14 
在新打开的模式窗口中,我们通过window.returnValue设置返回值,然后在父页面中我们通过returnVal可以拿到返回值。

posted @ 2007-11-27 23:41 lixw 阅读(269) | 评论 (0)编辑 收藏

  1. 启动数据库   
  db2start   
  2. 停止数据库   
  db2stop   
  3. 连接数据库   
  db2   connect   to   o_yd   user   db2   using   pwd   
  4. 读数据库管理程序配置   
  db2   get   dbm   cfg   
  5. 写数据库管理程序配置   
  db2   update   dbm   cfg   using   参数名   参数值   
  6. 读数据库的配置   
  db2   connect   to   o_yd   user   db2   using   pwd   
  db2   get   db   cfg   for   o_yd   
  7. 写数据库的配置   
  db2   connect   to   o_yd   user   db2   using   pwd   
  db2   update   db   cfg   for   o_yd   using   参数名   参数值   
  8. 关闭所有应用连接   
  db2   force   application   all   
  db2   force   application   ID1,ID2,,,Idn   MODE   ASYNC   
  (db2   list   application   for   db   o_yd   show   detail)   
  9. 备份数据库   
  db2   force   application   all   
  db2   backup   db   o_yd   to   d:   
  (db2   initialize   tape   on   \\.\tape0)   
  (db2   rewind   tape   on   \\.\tape0)   
  db2   backup   db   o_yd   to   \\.\tape0   
  10. 恢复数据库   
  db2   restore   db   o_yd   from   d:   to   d:     
  db2   restore   db   o_yd   from   \\.\tape0   to   d:   
  11. 绑定存储过程   
  db2   connect   to   o_yd   user   db2   using   pwd   
  db2   bind   c:\dfplus.bnd   
  拷贝存储过程到服务器上的C:\sqllib\function目录中   
  12. 整理表   
  db2   connect   to   o_yd   user   db2   using   pwd   
  db2   reorg   table   ydd   
  db2   runstats   on   table   ydd   with   distribution   and   indexes   all     
  13. 导出表数据  
  db2   export   to   c:\sw.txt   of   del   select   *   from   dftz  
  db2   export   to   c:\sw.ixf   of   ixf   select   *   from   dftz  
  14. 导入表数据  
  db2   import   from   c:\sw.txt   of   del   insert   into   ylbx.czyxx  
  db2   import   to   c:\sw.txt   of   del   commitcount   5000   messages       c:\dftz.msg   insert   into   dftz  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   messages   c:\dftz.msg   insert   into   dftz  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   insert   into   dftz  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   insert_update   into   dftz  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   replace   into   dftz  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   create   into   dftz       (仅IXF)  
  db2   import   to   c:\dftz.ixf   of   ixf   commitcount   5000   replace_create   into   dftz     (仅IXF)  
  15. 执行一个批处理文件  
  db2   –tf   批处理文件名  
  (文件中每一条命令用   ;结束)  
  16. 自动生成批处理文件  
  建文本文件:temp.sql  
  select   'runstats   on   table   DB2.'   ||   tabname   ||   '   with   distribution   and   detailed   indexes   all;'   from   syscat.tables   where   tabschema='DB2'   and   type='T';
  db2   –tf   temp.sql>runstats.sql  
  17. 自动生成建表(视图)语句  
  在服务器上:C:\sqllib\misc目录中  
  db2   connect   to   o_yd   user   db2   using   pwd  
  db2look   –d   o_yd   –u   db2   –e   –p   –c   c:\o_yd.txt     
  db2look   -d   lys   -e   -a   -x   -i   db2admin   -o   c:\aa.txt  
  18. 其他命令  
  grant   dbadm   on   database   to   user   bb   
  19.    select   *   from   czyxx   fetch   first   1   rows   only  
  20.    db2look   –d   lys   –u   db2admin   –w   –asd   –a   –e   –o   c:\mytable.txt   

posted @ 2007-04-27 08:54 lixw 阅读(255) | 评论 (0)编辑 收藏

1.在应用程序中使用日志的三个目的:
应用程序中添加日志的三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;
跟踪代码运行时轨迹,作为日后审计的依据;
担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。

2.log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。
使用Java特性文件做为配置文件的方法:
2.1. 配置根Logger,其语法为:
log4j.rootLogger = [ level ] , appenderName, appenderName, ...
其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。
Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。
比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。
2.2. 配置日志信息输出目的地Appender,其语法为
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
...
log4j.appender.appenderName.option = valueN

其中,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

2.3. 配置日志信息的格式(布局),其语法为:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
...
log4j.appender.appenderName.layout.option = valueN

其中,Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

3.在代码中使用Log4j,下面将讲述在程序代码中怎样使用Log4j。

3.1.得到记录器
使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:
public static Logger getLogger( String name),
通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;

3.2.读取配置文件
当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:
BasicConfigurator.configure (): 自动快速地使用缺省Log4j环境。
PropertyConfigurator.configure ( String configFilename) :读取使用Java的特性文件编写的配置文件。
DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。

3.3.插入记录信息(格式化日志信息)
当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:
Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;

一个配置的例子:
log4j.rootLogger=INFO, stdout ,R
log4j.appender.stdout.Threshold=ERROR
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n log4j.appender.R.Threshold=INFO
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=c:/log.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

posted @ 2007-04-25 17:34 lixw 阅读(270) | 评论 (0)编辑 收藏


1、在Javascript中操作Cookie:
 1 <script>
 2 //设置Cookie
 3   function setCookie(va){
 4        var expires = new Date();
 5       expires.setTime(expires.getTime() + 12 * 30 * 24 * 60 * 60 * 1000);
 6       /*   一年 x 一个月当作 30 天 x 一天 24 小时
 7       x 一小时 60 分 x 一分 60 秒 x 一秒 1000 毫秒 */
 8        document.cookie=va+';expires='+expires.toGMTString();
 9   }
10   //读取Cookie
11   function readCookie(name){
12   var cookieValue = "";
13   var search = name + "=";
14   if(document.cookie.length > 0)  {
15     offset = document.cookie.indexOf(search);
16     if (offset != -1)    {
17       offset += search.length;
18       end = document.cookie.indexOf(";", offset);
19       if (end == -1) end = document.cookie.length;
20       cookieValue = unescape(document.cookie.substring(offset, end))
21     }
22   }
23   return cookieValue;
24 }
25 
26 setCookie("user=123");
27 alert(readCookie('user'));
28 </script>
2、在Servlet中操作Cookie:
   a.要把Cookie发送到客户端,Servlet先要调用new Cookie(name,value)用合适的名字和值创建一个或多个Cookie,通过cookie.setXXX设置各种属性,通过response.addCookie(cookie)把cookie加入 应答头。
   b.要从客户端读入Cookie,Servlet应该调用request.getCookies (),getCookies()方法返回一个Cookie对象的数组。在大多数情况下,你只需要用循环访问该数组的各个元素寻找指定名字的Cookie, 然后对该Cookie调用getValue方法取得与指定名字关联的值。 
   c.创建Cookie 
   调用Cookie对象的构造函数可以创建Cookie。Cookie对象的构造函数有两个字符串参数:Cookie名字和Cookie值。名字和值都不能包含空白字符以及下列字符: 
   [ ] ( ) = , " / ? @ : ;   
   d.读取和设置Cookie属性 
   把Cookie加入待发送的应答头之前,你可以查看或设置Cookie的各种属性。下面摘要介绍这些方法: 
   getComment/setComment 
   获取/设置Cookie的注释。 
   getDomain/setDomain 
   获取/设置Cookie适用的域。一般地,Cookie只返回给与发送它的服务器名字完全相同的服务器。使用这里的方法可以指示浏览器把Cookie返回 给同一域内的其他服务器。注意域必须以点开始(例如.sitename.com),非国家类的域(如.com,.edu,.gov)必须包含两个点,国家 类的域(如.com.cn,.edu.uk)必须包含三个点。 
   getMaxAge/setMaxAge 
   获取/设置Cookie过期之前的时间,以秒计。如果不设置该值,则Cookie只在当前会话内有效,即在用户关闭浏览器之前有效,而且这些Cookie不会保存到磁盘上。参见下面有关LongLivedCookie的说明。 
   getName/setName 
   获取/设置Cookie的名字。本质上,名字和值是我们始终关心的两个部分。由于HttpServletRequest的getCookies方法返回的 是一个Cookie对象的数组,因此通常要用循环来访问这个数组查找特定名字,然后用getValue检查它的值。 
   getPath/setPath 
   获取/设置Cookie适用的路径。如果不指定路径,Cookie将返回给当前页面所在目录及其子目录下的所有页面。这里的方法可以用来设定一些更一般的 条件。例如,someCookie.setPath("/"),此时服务器上的所有页面都可以接收到该Cookie。 
   getSecure/setSecure 
   获取/设置一个boolean值,该值表示是否Cookie只能通过加密的连接(即SSL)发送。 
   getValue/setValue 
   获取/设置Cookie的值。如前所述,名字和值实际上是我们始终关心的两个方面。不过也有一些例外情况,比如把名字作为逻辑标记(也就是说,如果名字存在,则表示true)。 
   getVersion/setVersion 
   获取/设置Cookie所遵从的协议版本。默认版本0(遵从原先的Netscape规范);版本1遵从RFC 2109 , 但尚未得到广泛的支持。 
   e.在应答头中设置Cookie 
   Cookie可以通过HttpServletResponse的addCookie方法加入到Set-Cookie应答头。下面是一个例子: 
1    Cookie userCookie = new Cookie("user""uid1234"); 
2    response.addCookie(userCookie); 

   f.读取保存到客户端的Cookie 
   要把Cookie发送到客户端,先要创建Cookie,然后用addCookie发送一个Set-Cookie HTTP应答头。这些内容已经在上 面的2.1节介绍。从客户端读取Cookie时调用的是HttpServletRequest的getCookies方法。该方法返回一个与HTTP请求 头中的内容对应的Cookie对象数组。得到这个数组之后,一般是用循环访问其中的各个元素,调用getName检查各个Cookie的名字,直至找到目 标Cookie。然后对这个目标Cookie调用getValue,根据获得的结果进行其他处理。 
   上述处理过程经常会 遇到,为方便计下面我们提供一个getCookieValue方法。只要给出Cookie对象数组、Cookie名字和默认值, getCookieValue方法就会返回匹配指定名字的Cookie值,如果找不到指定Cookie,则返回默认值。 

   获取指定名字的Cookie值 
1 public static String getCookieValue(Cookie[] cookies, 
2        String cookieName,String defaultValue) { 
3        for(int i=0; i<cookies.length; i++) { 
4            Cookie cookie = cookies[i]; 
5            if (cookieName.equals(cookie.getName())) {
6                return(cookie.getValue()); 
7            } 
8        return(defaultValue); 
9    } 


posted @ 2007-02-27 08:57 lixw 阅读(179) | 评论 (0)编辑 收藏

1、在Action中获得Servlet API中的对象:
1 com.opensymphony.xwork2.ActionContext context = ActionContext.getContext();
2 HttpServletRequest request = org.apache.struts2.ServletActionContext.getRequest();
3 HttpServletResponse response = org.apache.struts2.ServletActionContext.getResponse();
4 HttpSession session = request.getSession();

    获取与Servlet运行环境无关的Session集合:
Map sessionMap = ActionContext.getContext().getSession();
    IOC方式访问,可以通过实现ServletRequestAware、ServletResponseAware和SessionAware。
参考WebWork API
2、自定义Action调用方法:
  • 在struts.xml的action配置中,增加属性method="aliasMethod";
  • 在访问Action的URL中增加!aliasMethod.action,形如 http://localhost:8080/app/ActionName!aliasMethod.action。
3、自己布局form:
    给<s:form />增加属性theme="simple"。

4、WebWork中的特殊命名对象:
    #prameters['foo'] or #parameters.foo                request.getParameter("foo");
    #request['foo'] or #request.foo                     request.getAttribute("foo");
    #session['foo'] or #session.foo                     session.getAttribute("foo");
    #application['foo'] or #application.foo             application.getAttribute("foo");
    #attr['foo'] or #attr.foo                           pageContext.getAttribute("foo");
  

posted @ 2007-02-26 10:23 lixw 阅读(585) | 评论 (2)编辑 收藏

一种比较简陋的方法:

 1 ActionListener taskPerformer = new ActionListener() {
 2             public void actionPerformed(ActionEvent evt) {
 3                 log.info("monitor is running at " + new java.util.Date());
 4                 String configfile = (String)getServletContext().getAttribute("configfile");
 5                 if(configfile != null && configfile.length()!=0){
 6                     try{
 7                         File file = new File(configfile);
 8                         if(file.lastModified() > lastModifyTime){
 9                             lastModifyTime = file.lastModified();
10                             loadProp();
11                         }
12                     }catch(Exception e){
13                         log.error("construct file:" + configfile + " exception");
14                         e.printStackTrace();
15                     }
16                 }
17             }
18  };
19         
20  //启动监听线程
21 new Timer(delay, taskPerformer).start();


来自geosoft.no的解决方法:
 1 import java.io.File;
 2 
 3 /**
 4  * Interface for listening to disk file changes.
 5  * @see FileMonitor
 6  * 
 7  * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a>
 8  */   
 9 public interface FileListener
10 {
11   /**
12    * Called when one of the monitored files are created, deleted
13    * or modified.
14    * 
15    * @param file  File which has been changed.
16    */
17   void fileChanged (File file);
18 }

  1 import java.util.*;
  2 import java.io.File;
  3 import java.lang.ref.WeakReference;
  4 
  5 /**
  6  * Class for monitoring changes in disk files.
  7  * Usage:
  8  *
  9  *    1. Implement the FileListener interface.
 10  *    2. Create a FileMonitor instance.
 11  *    3. Add the file(s)/directory(ies) to listen for.
 12  *
 13  * fileChanged() will be called when a monitored file is created,
 14  * deleted or its modified time changes.
 15  *
 16  * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a>
 17  */   
 18 public class FileMonitor
 19 {
 20   private Timer       timer_;
 21   private HashMap     files_;       // File -> Long
 22   private Collection  listeners_;   // of WeakReference(FileListener)
 23    
 24 
 25   /**
 26    * Create a file monitor instance with specified polling interval.
 27    * 
 28    * @param pollingInterval  Polling interval in milli seconds.
 29    */
 30   public FileMonitor (long pollingInterval)
 31   {
 32     files_     = new HashMap();
 33     listeners_ = new ArrayList();
 34 
 35     timer_ = new Timer (true);
 36     timer_.schedule (new FileMonitorNotifier(), 0, pollingInterval);
 37   }
 38 
 39 
 40   
 41   /**
 42    * Stop the file monitor polling.
 43    */
 44   public void stop()
 45   {
 46     timer_.cancel();
 47   }
 48   
 49 
 50   /**
 51    * Add file to listen for. File may be any java.io.File (including a
 52    * directory) and may well be a non-existing file in the case where the
 53    * creating of the file is to be trepped.
 54    * <p>
 55    * More than one file can be listened for. When the specified file is
 56    * created, modified or deleted, listeners are notified.
 57    * 
 58    * @param file  File to listen for.
 59    */
 60   public void addFile (File file)
 61   {
 62     if (!files_.containsKey (file)) {
 63       long modifiedTime = file.exists() ? file.lastModified() : -1;
 64       files_.put (file, new Long (modifiedTime));
 65     }
 66   }
 67 
 68   
 69 
 70   /**
 71    * Remove specified file for listening.
 72    * 
 73    * @param file  File to remove.
 74    */
 75   public void removeFile (File file)
 76   {
 77     files_.remove (file);
 78   }
 79 
 80 
 81   
 82   /**
 83    * Add listener to this file monitor.
 84    * 
 85    * @param fileListener  Listener to add.
 86    */
 87   public void addListener (FileListener fileListener)
 88   {
 89     // Don't add if its already there
 90     for (Iterator i = listeners_.iterator(); i.hasNext(); ) {
 91       WeakReference reference = (WeakReference) i.next();
 92       FileListener listener = (FileListener) reference.get();
 93       if (listener == fileListener)
 94         return;
 95     }
 96 
 97     // Use WeakReference to avoid memory leak if this becomes the
 98     // sole reference to the object.
 99     listeners_.add (new WeakReference (fileListener));
100   }
101 
102 
103   
104   /**
105    * Remove listener from this file monitor.
106    * 
107    * @param fileListener  Listener to remove.
108    */
109   public void removeListener (FileListener fileListener)
110   {
111     for (Iterator i = listeners_.iterator(); i.hasNext(); ) {
112       WeakReference reference = (WeakReference) i.next();
113       FileListener listener = (FileListener) reference.get();
114       if (listener == fileListener) {
115         i.remove();
116         break;
117       }
118     }
119   }
120 
121 
122   
123   /**
124    * This is the timer thread which is executed every n milliseconds
125    * according to the setting of the file monitor. It investigates the
126    * file in question and notify listeners if changed.
127    */
128   private class FileMonitorNotifier extends TimerTask
129   {
130     public void run()
131     {
132       // Loop over the registered files and see which have changed.
133       // Use a copy of the list in case listener wants to alter the
134       // list within its fileChanged method.
135       Collection files = new ArrayList (files_.keySet());
136       
137       for (Iterator i = files.iterator(); i.hasNext(); ) {
138         File file = (File) i.next();
139         long lastModifiedTime = ((Long) files_.get (file)).longValue();
140         long newModifiedTime  = file.exists() ? file.lastModified() : -1;
141 
142         // Chek if file has changed
143         if (newModifiedTime != lastModifiedTime) {
144 
145           // Register new modified time
146           files_.put (file, new Long (newModifiedTime));
147 
148           // Notify listeners
149           for (Iterator j = listeners_.iterator(); j.hasNext(); ) {
150             WeakReference reference = (WeakReference) j.next();
151             FileListener listener = (FileListener) reference.get();
152 
153             // Remove from list if the back-end object has been GC'd
154             if (listener == null)
155               j.remove();
156             else
157               listener.fileChanged (file);
158           }
159         }
160       }
161     }
162   }
163 
164 
165   /**
166    * Test this class.
167    * 
168    * @param args  Not used.
169    */
170   public static void main (String args[])
171   {
172     // Create the monitor
173     FileMonitor monitor = new FileMonitor (1000);
174 
175     // Add some files to listen for
176     monitor.addFile (new File ("D:\\myjava\\JCreatorWorkspace\\FileMonitor\\test.txt"));
177 
178     // Add a dummy listener
179     monitor.addListener (monitor.new TestListener());
180 
181     // Avoid program exit
182     while (!false) ;
183   }
184 
185   
186   private class TestListener
187     implements FileListener
188   {
189     public void fileChanged (File file)
190     {
191       System.out.println ("File [" + file.getName() + "] changed At:" + new java.util.Date());
192     }
193   }
194 }
195 
196 
197 

posted @ 2007-02-08 10:07 lixw 阅读(1423) | 评论 (2)编辑 收藏


1 //file may be named basename_locale.properties
2 ResourceBundle bundle = ResourceBundle.getBundle("basename");
3 // Enumerate contents of resource bundle
4 //The next two lines should be in one line.
5 for (Enumeration props = bundle.getKeys();props.hasMoreElements(); ) {
6     String key = (String)props.nextElement();
7     process(key, bundle.getObject(key));
8 }

posted @ 2007-02-08 09:43 lixw 阅读(394) | 评论 (0)编辑 收藏


1 String aString = "word1 word2 word3";
2 StringTokenizer parser = new StringTokenizer(aString);
3 while (parser.hasMoreTokens()) {
4     processWord(parser.nextToken());
5 }

posted @ 2007-02-08 09:43 lixw 阅读(150) | 评论 (0)编辑 收藏


 1 public static long checksum(byte[] buf) {
 2     try {
 3         CheckedInputStream cis = new CheckedInputStream(
 4        new ByteArrayInputStream(buf),new Adler32());
 5         byte[] tempBuf = new byte[128];
 6         while (cis.read(tempBuf) >= 0);        return cis.getChecksum().getValue();
 7     } catch (IOException e) {
 8         return -1;
 9     }
10 }

posted @ 2007-02-08 09:41 lixw 阅读(1464) | 评论 (0)编辑 收藏

 1 try {
 2      String inFilename = "infile";
 3      String outFilename = "outfile.zip";
 4      FileInputStream in = new FileInputStream(inFilename);
 5      ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));
 6           // Add ZIP entry to output stream.
 7      out.putNextEntry(new ZipEntry(inFilename));
 8      byte[] buf = new byte[1024];
 9      int len;
10      while ((len = in.read(buf)) > 0) {
11          out.write(buf, 0, len);
12     }
13         out.closeEntry();
14     out.close();
15     in.close();
16 }catch (IOException e) {}



 1 try {
 2      String inFilename = "infile.zip";
 3      String outFilename = "outfile";
 4      ZipInputStream in = new ZipInputStream(new FileInputStream(inFilename));
 5      OutputStream out = new FileOutputStream(outFilename);
 6      ZipEntry entry;
 7      byte[] buf = new byte[1024];
 8      int len;
 9      if ((entry = in.getNextEntry()) != null) {
10          while ((len = in.read(buf)) > 0) {
11               out.write(buf, 0, len);
12          }
13      }
14      out.close();
15      in.close();
16  } catch (IOException e) {
17  }

posted @ 2007-02-08 09:35 lixw 阅读(212) | 评论 (0)编辑 收藏

 1 public   void  doDownLoad(HttpServletRequest request, HttpServletResponse response, 
 2             String absolutePath)  {
 3         
 4          // 设置响应头信息
 5         response.setContentType( " application/octet-stream;charset=UTF-8 " ); 
 6         log.debug( " GET:  "   +  absolutePath);
 7         
 8         String str  =  FilePathParseUtil.getFileNameByPath(absolutePath);
 9          // 调用自定义的编码函数,解决不同浏览器上对汉字编码的处理
10         str  =   this .encodeFileName(request, str) == null ? str: this .encodeFileName(request, str);
11          // 设置response头信息,从而显示正确的文件名,并弹出另存对话框
12         response.setHeader( " Content-Disposition " " attachment; filename= "  
13                  +  str);
14         OutputStream out  =   null ;
15          try {
16              // 从response得到输出流,从而向客户端写出文件
17             out  =  response.getOutputStream();
18         }
catch (IOException e) {
19             log.error( " output stream is null " );
20             e.printStackTrace();
21         }

22          this .doDownLoad(out, absolutePath);
23     }

24     
25      /**
26      * 根据不同浏览器对文件名进行编码
27      *  @param  request 客户端请求
28      *  @param  fileName 文件名
29      *  @return  编码后的文件名
30       */

31      public  String encodeFileName(HttpServletRequest request, String fileName) {   
32         String agent  =  request.getHeader( " USER-AGENT " );
33          try {
34              if  ( null   !=  agent  &&   - 1   !=  agent.indexOf( " MSIE " ))  {   
35                  return  URLEncoder.encode(fileName,  " UTF-8 " );   
36             }
else   if  ( null   !=  agent  &&   - 1   !=  agent.indexOf( " Mozilla " ))  {   
37                  return   " =?UTF-8?B? " +
38                          new  String(
39                                 Base64.encodeBase64(
40                                     fileName.getBytes( " UTF-8 " )
41                                 )
42                         )  +   " ?= " ;   
43             }
  else   {   
44                  return  fileName;   
45             }

46         }
catch (UnsupportedEncodingException e) {
47              return   null ;
48         }

49     }
  

posted @ 2007-02-07 14:32 lixw 阅读(245) | 评论 (0)编辑 收藏

来自telio.be的JS:

 1/* Licence:
 2*   Use this however/wherever you like, just don't blame me if it breaks anything.
 3*
 4* Credit:
 5*   If you're nice, you'll leave this bit:
 6*
 7*   Class by Pierre-Alexandre Losson -- http://www.telio.be/blog
 8*   email : plosson@users.sourceforge.net
 9*/

10function refreshProgress()
11{
12    UploadMonitor.getUploadInfo(updateProgress);
13}

14
15function updateProgress(uploadInfo)
16{
17    if (uploadInfo.inProgress)
18    {
19        document.getElementById('uploadbutton').disabled = true;
20        document.getElementById('file1').disabled = true;
21
22        var fileIndex = uploadInfo.fileIndex;
23
24        var progressPercent = Math.ceil((uploadInfo.bytesRead / uploadInfo.totalSize) * 100);
25
26        document.getElementById('progressBarText').innerHTML = 'upload in progress: ' + progressPercent + '%';
27
28        document.getElementById('progressBarBoxContent').style.width = parseInt(progressPercent * 3.5+ 'px';
29
30        window.setTimeout('refreshProgress()', 1000);
31    }

32    else
33    {
34        document.getElementById('uploadbutton').disabled = false;
35        document.getElementById('file1').disabled = false;
36    }

37
38    return true;
39}

40
41function startProgress()
42{
43    document.getElementById('progressBar').style.display = 'block';
44    document.getElementById('progressBarText').innerHTML = 'upload in progress: 0%';
45    document.getElementById('uploadbutton').disabled = true;
46
47    // wait a little while to make sure the upload has started ..
48    window.setTimeout("refreshProgress()"1500);
49    return true;
50}

51

一个可以有其他页面引用的进度条页面:
 1<%
 2    String path = request.getContextPath();
 3    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 4%>
 5<script src="<%=basePath%>common/js/upload.js"> </script>
 6<script src="<%=basePath%>dwr/interface/UploadMonitor.js"> </script>
 7<script src="<%=basePath%>dwr/engine.js"> </script>
 8<script src="<%=basePath%>dwr/util.js"> </script>
 9<style type="text/css">
10    body { font: 11px Lucida Grande, Verdana, Arial, Helvetica, sans serif; }
11    #progressBar { padding-top: 5px; }
12    #progressBarBox { width: 350px; height: 20px; border: 1px inset; background: #eee;}
13    #progressBarBoxContent { width: 0; height: 20px; border-right: 1px solid #444; background: #9ACB34; }
14</style>
15
16<div id="progressBar" style="display: none;">
17    <div id="theMeter">
18        <div id="progressBarText"></div>
19        <div id="progressBarBox">
20            <div id="progressBarBoxContent"></div>
21        </div>
22    </div>
23</div>

在dwr.xml 中的配置:

 1<?xml version="1.0" encoding="UTF-8"?>
 2<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" 
 3"http://getahead.ltd.uk/dwr/dwr20.dtd">
 4<dwr>
 5    <allow>
 6        <create creator="new" javascript="UploadMonitor" scope="script">
 7            <param name="class" value="be.telio.mediastore.ui.upload.UploadMonitor"/>
 8        </create>
 9        <convert converter="bean" match="be.telio.mediastore.ui.upload.UploadInfo"/>
10    </allow>
11</dwr>

在web.xml中增加如下对DwrServlet的配置:

 1<servlet>
 2    <servlet-name>dwr-invoker</servlet-name>
 3    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
 4    <init-param>
 5      <param-name>debug</param-name>
 6      <param-value>false</param-value>
 7    </init-param>
 8    <init-param>
 9      <param-name>pollAndCometEnabled</param-name>
10      <param-value>true</param-value>
11    </init-param>
12    <init-param>
13      <param-name>allowGetForSafariButMakeForgeryEasier</param-name>
14      <param-value>true</param-value>
15    </init-param>
16    <load-on-startup>2</load-on-startup>
17  </servlet>
18
19  <servlet-mapping>
20    <servlet-name>dwr-invoker</servlet-name>
21    <url-pattern>/dwr/*</url-pattern>
22  </servlet-mapping>

posted @ 2007-02-07 14:28 lixw 阅读(3603) | 评论 (1)编辑 收藏

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout

#hibernate log level
log4j.logger.org.hibernate=error

#struts log level
#log4j.logger.org.apache.struts=error

#spring log level
#log4j.logger.org.springframework=error

#oscache log level
log4j.logger.com.opensymphony.oscache=error

 

posted @ 2007-02-07 14:19 lixw 阅读(756) | 评论 (0)编辑 收藏

利用spring在同一页面提交多个Form,填充多个FormBean。

http://opensource.atlassian.com/confluence/spring/display/COOK/Forms+-+Multiple+forms+on+the+same+page

posted @ 2007-02-07 09:37 lixw 阅读(495) | 评论 (0)编辑 收藏

昨天看了一天的EJB,才刚刚对EJB的流程有了一点了解,现在总结出来,请大家多多指教:

1、创建自己的Bean(现在我只学习了一个会话Bean的例子),其中包含商务方法的实现;

(2--5的操作可由容器自动完成,如WebLogic中的Build EJB,如果在MyEclipse中,可以在生成Bean的时候选择是用XDoclet自动生成以下接口)

2、创建远程接口(继承自EJBObject),其中包括商务方法的空实现(必须抛出远程异常),客户端通过该接口与EJB对象交互,

    它的具体实现由EJB容器供应商实现,实现的对象就是EJB对象,它拥有对实际Bean的引用;

3、创建Home接口(继承自EJBHome),其中至少包含一个create()方法,这个方法返回EJB对象,并抛出远程异常,

    它的作用相当于EJB对象的生成库;

(4和5是可选的操作,本地用户可以通过这些接口而不是远程接口来调用Bean)

4、创建本地接口(继承自EJBLocalObject),方法跟远程接口中的相当,只是不需要抛出远程异常;

5、创建本地Home接口(继承自EJBLocalHome),方法跟Home接口相当,同样不需要抛出远程异常;

6、如果采用自动生成接口的话,同时会在META-INF生成下生成多个XML配置文件:

  ejb-jar.xml:它是EJB规范中要求的配置,是容器无关的。下面是一个实际配置的例子

 1 < ejb-jar >
 2    < enterprise-beans >
 3
 4 <! -配置会话Bean- >
 5      < session >
 6        < ejb-name > HelloBean </ ejb-name >
 7        < home > bean.HelloHome </ home >
 8        < remote > bean.HelloObject </ remote >
 9        < ejb-class > bean.HelloBean </ ejb-class >
10        < session-type > Stateless </ session-type >
11        < transaction-type > Container </ transaction-type >
12      </ session >
13
14      < entity >
15 <! -配置实体Bean- >
16      </ entity >
17    </ enterprise-beans >
18 </ ejb-jar >
19

 还有一个与特定容器相关的配置文件:

如WebLogic中配置文件为weblogic-ejb-jar.xml,下面是一个实际配置的例子:

1 < weblogic-ejb-jar >
2    < weblogic-enterprise-bean >
3      < ejb-name > HelloBean </ ejb-name >
4      < stateless-session-descriptor >
5      </ stateless-session-descriptor >
6        < jndi-name > ejb.helloJNDI </ jndi-name >
7    </ weblogic-enterprise-bean >
8   < weblogic-ejb-jar >

在Jboss则会有相应的配置文件。

7、现在我们看到我们的Bean、Home接口、EJBObject接口已经与特定的命名绑定;

8、现在客户端要调用Bean中的某个商务方法:

  • 通过JNDI查找到Home对象,获得它的引用;
  • Home对象是EJB对象的生成库,由它创建生成新的EJB对象;
  • 客户端调用EJB对象的商务方法;
  • EJB对象将请求委托给实际的Bean;
  • Bean实现商务方法。

 

posted @ 2007-02-06 17:33 lixw 阅读(634) | 评论 (0)编辑 收藏

1、查询缓存

  首先需要配置hibernate.cache.use_query_cache=true

如果用ehcache,配置ehcache.xml,注意hibernate3.0以后不是net.sf的包名了

 1 <cache name="net.sf.hibernate.cache.StandardQueryCache"
 2 
 3 maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
 4 
 5 timeToLiveSeconds="7200" overflowToDisk="true"/>
 6 
 7 <cache name="net.sf.hibernate.cache.UpdateTimestampsCache"
 8 
 9 maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
10 
11 

  然后

query.setCacheable(true);//激活查询缓存

query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可选

第二行指定要使用的cacheRegion是myCacheRegion,即你可以给每个查询缓存做一个单独的配置,

使用setCacheRegion来做这个指定,需要在ehcache.xml里面配置它:

1 < cache  name ="myCacheRegion"  maxElementsInMemory ="10"  eternal ="false"
2
3 timeToIdleSeconds ="3600"  timeToLiveSeconds ="7200"  overflowToDisk ="true"   />
4
5


如果省略第二行,不设置cacheRegion的话,那么会使用上面提到的标准查询缓存的配置,也就是

net.sf.hibernate.cache.StandardQueryCache

  问题:当hibernate更新数据库的时候,它怎么知道更新哪些查询缓存呢?

    hibernate在一个地方维护每个表的最后更新时间,其实也就是放在上面

net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。

当通过hibernate更新的时候,hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表,当hibernate查询一个缓存是否存在的时候,如果缓存存在,它还要取出缓存的生成时间和这个缓存所查询的表,然后去查找这些表的最后更新时间,如果有一个表在生成时间后更新过了,那么这个缓存是无效的。可以看出,只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。

  注意:

    放入缓存中的key是查询的语句,value是查询之后得到的结果集的id列表。

表面看来这样的方案似乎能解决hql利用缓存的问题,但是需要注意的是,构成key的是:

hql生成的sql、sql的参数、排序、分页信息等。也就是说如果你的hql有小小的差异,

比如第一条hql取1-50条数据,第二条hql取20-60条数据,那么hibernate会认为这是两个

完全不同的key,无法重复利用缓存。因此利用率也不高。

   查询缓存必须配合二级缓存一起使用,否则极易出现1+N的情况

   如果不设置"查询缓存",那么hibernate只会缓存使用load()方法获得的单个持久化对象,

如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法

获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行,如果需要"查询缓存",需要在使用Query或Criteria()时设置其setCacheable(true);属性。 
2、Collection缓存

  需要在hbm的collection里面设置

< cache  usage ="read-write" />

假如class是Cat,collection叫children,那么ehcache里面配置

1 < cache  name ="com.xxx.pojo.Cat.children"
2
3 maxElementsInMemory ="20"  eternal ="false"  timeToIdleSeconds ="3600"
4
5 timeToLiveSeconds ="7200"
6
7 overflowToDisk ="true"   />
8

Collection的缓存和前面查询缓存的list一样,也是只保持一串id,但它不会因为这个表更新过就

失效,一个collection缓存仅在这个collection里面的元素有增删时才失效。

这样有一个问题,如果你的collection是根据某个字段排序的,当其中一个元素更新了该字段时,

导致顺序改变时,collection缓存里面的顺序没有做更新 
3、Class缓存(也称二级缓存)

   可由Hibernate提供的二级缓存实现,它存在于SessionFactory级别,

缓存结构可以看作是一个hash table,key是数据库记录的id,value是id对应的pojo对象。

当用户根据id查询对象的时候(load、iterator方法),会首先在缓存中查找,

如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query方法)

则不会利用二级缓存,而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写不读的。 
在hibernate.cfg.xml配置:

< property  name ="hibernate.cache.provider_class" >

       org.hibernate.cache.EhCacheProvider

</ property >

hibernate3支持

Hashtable Cache(org.hibernate.cache.HashtableCacheProvider)

EhCache(org.hibernate.cache.EhCacheProvider)

OSCache(org.hibernate.cache.OSCacheProvider)

SwarmCache(org.hibernate.cache.SwarmCacheProvider)

JBossCache(org.hibernate.cache.TreeCacheProvider)

在相应的POJO配置文件中增加:

<!--

指定缓存同步策略:

read-write                           读写型

nonstrict-read-write             非严格读写型

read-only                            只读型

transactional                        事务型

-->

<cache usage="read-write"/> 

Cache read-only nonstrict-read-write read-write transactional
EhCache Yes Yes Yes No
OSCache Yes Yes Yes No
SwarmCache Yes Yes No No
TreeCache Yes No No Yes

     对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论

list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate

会先取数据库select id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有

的话就去数据库load。

   当某个ID通过hibernate修改时,hibernate会知道,于是移除缓存。

这样大家可能会想,同样的查询条件,第一次先list,第二次再iterate,就可以使用到缓存了。

实际上这是很难的,因为你无法判断什么时候是第一次,而且每次查询的条件通常是不一样的,假

如数据库里面有100条记录,id从1到100,第一次list的时候出了前50个id,第二次iterate的时候

却查询到30至70号id,那么30-50是从缓存里面取的,51到70是从数据库取的,共发送1+20条sql。

所以我一直认为iterate没有什么用,总是会有1+N的问题。 如果想要对list或者iterate查询的结

果缓存,就要用到查询缓存了。 
  注意:

   对于one-to-many的关联关系,如果对one应用缓存,则应同时对many应用。

   二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做

缓存失效操作。基于此机制,如果数据表不是被hibernate独占,那么二级缓存无法得到有效控制

   hibernate 3.0在做批量修改、批量更新的时候,是不会同步更新二级缓存的

   查询缓存和二级缓存是有关联关系的,他们不是完全独立的两套东西。假如一个查询条件hql_1

,第一次被执行的时候,它会从数据库取得数据,然后把查询条件作为key,把返回数据的所有id

列表作为value(请注意仅仅是id)放到查询缓存中,同时整个结果集放到二级缓存,key是id,

value是pojo对象。当你再次执行hql_1,它会从缓存中得到id列表,然后根据这些列表一个一个的

到二级缓存里面去找pojo对象,如果找不到就向数据库发起查询。也就是说,如果二级缓存配置了

超时时间,就有可能出现查询缓存命中了,获得了id列表,但是class里面相应的pojo已经因为超

时被失效,hibernate就会根据id清单,一个一个的去向数据库查询,有多少个id,就执行多少个

sql。该情况将导致性能下降严重。

   查询缓存的失效机制也由hibernate控制,数据进入缓存时会有一个timestamp,它和数据表的

timestamp对应。当hibernate环境内发生save、update等操作时,会更新被操作数据表的

timestamp。用户在获取缓存的时候,一旦命中就会检查它的timestamp是否和数据表的timestamp

匹配,如果不,缓存会被失效。因此查询缓存的失效控制是以数据表为粒度的,只要数据表中任何

一条记录发生一点修改,整个表相关的所有查询缓存就都无效了。因此查询缓存的命中率可能会很

低。 
4、对方法的缓存

  对于调用频率较高的查询类方法,我们希望缓存方法结果

在spring中可利用拦截器(Interceptor)实现,可能如下面的配置:

 1 < beans >
 2
 3      < bean  id ="cacheInterceptor"
 4
 5 class ="org.springframework.aop.interceptor.cache.OSCacheInterceptor" >
 6
 7         <! - 默认刷新时间(秒)- >
 8
 9         < property  name ="defaultRefreshPeriod" >
10
11             < value > 60 </ value >
12
13         </ property >
14
15         < property  name ="identifiers" >
16
17             < props >
18
19                < prop  key ="java.util.Map" > toString </ prop >
20
21             </ props >
22
23         </ property >
24
25      </ bean >
26
27      <! - 正则表达式匹配 - >
28
29      < bean  id ="searcherAdvisor"
30
31 class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
32
33         < property  name ="advice" >
34
35             < ref  local ="cacheInterceptor"   />
36
37         </ property >
38
39         < property  name ="patterns" >
40
41             < list >
42
43                < value > .get. </ value >
44
45             </ list >
46
47         </ property >
48
49      </ bean >
50
51      <! - 自动代理 - >
52
53      < bean  id ="proxyCreator1"
54
55 class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
56
57         < property  name ="beanNames" >
58
59            <!--  需截获方法的bean列表  -->
60
61             < list >
62
63                < value > commonSelect </ value >
64
65             </ list >
66
67         </ property >
68
69         < property  name ="interceptorNames" >
70
71            <!--  截获器列表  -->
72
73             < list >
74
75                < value > searcherAdvisor </ value >
76
77             </ list >
78
79         </ property >
80
81      </ bean >
82
83 < beans >
84
85

 这里通过自动代理创建bean,并指定作用其上的interceptor列表,在commonSelect存在searchAdvisor,

而searchAdvisor对匹配*get*模式的方法调用将通过cacheInterceptor进行处理。

posted @ 2007-02-06 17:31 lixw 阅读(630) | 评论 (0)编辑 收藏

缓存---基础理论篇   
          
1.   缓存
      缓存介于应用程序和永久性数据存储源之间,它的作用是降低应用程序直接读写永久数据存储源的频率,从而提高应用的运行性能。
      缓存中的数据是数据存储源中数据的拷贝,应用程序在运行时直接读写缓存中的数据,只在某些特定时刻按照缓存中的数据来同步更新数据存储源。
      缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。  

2.   各类CACHE简介

2.1.   Java Caching System
       JSC(Java Caching System)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。动态内容和报表系统能够获得更好的性能。如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。  
官方网站 http://jakarta.apache.org/turbine/jcs/

2.2   EHCache
      EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
官方网站 http://ehcache.sourceforge.net/;

2.3.   OSCache
       OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。
       OSCache有以下特点:
       缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
       拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。
      永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。
      支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。
      缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
官方网站 http://www.opensymphony.com/oscache/

2.4.   JCache
       JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。
官方网站 http://jcache.sourceforge.net/

 2.5.   ShiftOne
        ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。
官方网站 http://jocache.sourceforge.net/

  2.6.   SwarmCache
        SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。
官方网站 http://swarmcache.sourceforge.net

 2.7.   TreeCache / JBossCache 
        JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。JBossCache包括两个模块:TreeCache和TreeCacheAOP。TreeCache --是一个树形结构复制的事务处理缓存。TreeCacheAOP --是一个"面向对象"缓存,它使用AOP来动态管理POJO(Plain Old Java Objects)
官方网站 http://www.jboss.org/products/jbosscache;

 2.8.   WhirlyCache
        Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。
官方网站 https://whirlycache.dev.java.net/

posted @ 2007-02-06 17:27 lixw 阅读(289) | 评论 (0)编辑 收藏

一、最简单的方式:
设置表单form 的 method=”post” ENCTYPE="multipart/form-data"
通过
InputStream in =servletRequest.getInputStream();
以流的方式处理,它的缺点就不言而喻了

二、commons-fileupload:
官方网站:[http://jakarta.apache.org/commons/fileupload/]
它提供基于Servlet的上传,可上传到内存、文件,且文件的上传位置,最大上传文件字节数可以在程序中设置,
特别是对于多文件上传支持较好,List items = upload.parseRequest(request)就可以处理多文件,其他都不用考虑,
提供了item.isFormField()判断是否为标准表单值的方法,简洁实用,但是可配置仍然不好,对API的依赖性很大

使用步骤:
1、首先判断一个HttpServletRequest是否是一个上传文件的请求:
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
2、处理请求:
2.1、创建基于硬盘存储的工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
/* 或者
DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);
*/
2.2、设置工厂属性,从而生成个性化ServletFileUpload
//设置最多只允许在内存中存储的数据,单位:字节
factory.setSizeThreshold(yourMaxMemorySize);
// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
factory.setRepository(yourTempDirectory);
2、处理上传文件:
Iterator iter = items.iterator();
while (iter.hasNext()) {
   FileItem item = (FileItem) iter.next();
   //判断是否为标准表单域
   if (item.isFormField()) {
        String name = item.getFieldName();
 String value = item.getString();
   …
     } else {
  String fieldname = item.getFieldName();
  String filename = item.getName();
  String contentType = item.getContentType();
  boolean isInMemory = item.isInMemory();
  long sizeInBytes = item.getSize();
  …
 //直接从内存访问上传数据
 byte[] data = item.get();
   
 //采用流方式读取上传文件
 InputStream stream = item.openStream();

 // 保存到文件
 if (writeToFile) {
 File uploadedFile = new File(storeFilePath);
 item.write(uploadedFile);
    } else {
 //转换为输出流
 InputStream uploadedStream = item.getInputStream();
 ...
 uploadedStream.close();
 }
}
...

三、javazoom的UploadBean:
官方网站:[http://www.javazoom.net/jzservlets/uploadbean/uploadbean.html]

功能强大,支持上传到文件系统,数据库,同时它还有一些高级功能,如对上传的监听,overwrite过滤器、自定义解析器、
overwrite策略、黑名单、白名单等,特别是它采用了JavaBean方式,所以在JSP页面可以轻松的采用

从而实现上传到硬盘目录但是它的源代码是需要Money的,我们只能得到它的jar包和API Doc,
同时它对多文件上传处理的不是很好(我觉得)。

官方网站上有详细的说明供参考。

四、Jspsmartupload
官方网站:[http://www.jspsmart.com/] 可惜一直打不开
这里有一篇文章说明:[http://java.ccidnet.com/art/3737/20060717/638255_1.html]

posted @ 2007-02-06 17:19 lixw 阅读(517) | 评论 (0)编辑 收藏

 1 < script language = " javascript " >  
 2 // 行追加 
 3 function  lineAdd() 
 4
 5 var  count  =   1
 6 var  newLine_1  =   " <tr> "  
 7 newLine_1  +=   " <td><input type='file' size='30' name='uploadfile "   +  count  +   " '></td> "
 8 count ++
 9 newLine_1  +=   " <td><input type='button' value='删除' style='cursor:hand' onClick='lineDel(this)'></td> "
10 newLine_1  +=   " </tr> "
11
12 var  tmp  =   ""
13 tmp  =   " <table id='D1'> "
14 tmp  +=  D1.innerHTML; 
15 tmp  +=  newLine_1; 
16 tmp  +=   " </table> "
17 D1.outerHTML  =  tmp; 
18 }
 
19
20 // 行删除 
21 function  lineDel(btn) 
22
23 D1.deleteRow(btn.parentNode.parentNode.rowIndex); 
24 }
 
25
26 </ script >

posted @ 2007-02-06 17:17 lixw 阅读(430) | 评论 (0)编辑 收藏

 1 import  java.security. * ;     
 2    
 3 public   class  MD5 {     
 4    
 5   public   final   static  String getMD5(String s) {     
 6    char  hexDigits[]  =   {     
 7      ' 0 ' ' 1 ' ' 2 ' ' 3 ' ,     
 8      ' 4 ' ' 5 ' ' 6 ' ' 7 ' ,     
 9      ' 8 ' ' 9 ' ' a ' ' b ' ,     
10      ' c ' ' d ' ' e ' ' f ' }
;     
11    try   {     
12     byte [] strTemp  =  s.getBytes();     
13    MessageDigest mdTemp  =  MessageDigest.getInstance( " MD5 " );     
14    mdTemp.update(strTemp);     
15     byte [] md  =  mdTemp.digest();     
16     int  j  =  md.length;     
17     char  str[]  =   new   char [j  *   2 ];     
18     int  k  =   0 ;     
19     for  ( int  i  =   0 ; i  <  j; i ++ {     
20      byte  byte0  =  md[i];     
21     str[k ++ =  hexDigits[byte0  >>>   4   &   0xf ];     
22     str[k ++ =  hexDigits[byte0  &   0xf ];     
23    }
     
24     return   new  String(str);     
25   }
catch  (Exception e) {     
26     return   null ;     
27   }
     
28  }
     
29      
30   public   static   void  main(String[] args) {     
31    
32   System.out.print(MD5.getMD5( " abcd " ));     
33  }
    
34 }
    
35

posted @ 2007-02-06 17:15 lixw 阅读(150) | 评论 (0)编辑 收藏