随笔-46  评论-64  文章-2  trackbacks-0
  2006年2月21日
     摘要: 废话不多说,先看看我们最终达到的效果.  源码下载在文章最后。Style1:Style2:上面的tag cloud实现思想如下:1. Server端提供Tag的相关信息,包括TagName,Posts等,使用JSON格式传输数据    这个例子中,我使用Servlet,使用json-lib将Bean转成JSON字符串。当然Tag的相关信息这里只是演示,真实环境中可能就需要从数据库取出来再处理了。 ...  阅读全文
posted @ 2008-09-28 16:10 jht 阅读(3130) | 评论 (3)编辑 收藏
1. response.setHeader("Cache-Control","no-cache");

This is used to prevent the browser from caching your dynamic content generated by a JSP or Servlet.

You set this attribute in the HTTP header of the response object which would tell the browser not to cache this content. So everytime you request the page again, the browser would make a new request, instead of showing you a cached page.

2.使用服务器端控制AJAX页面缓存:
    response.setHeader( "Pragma", "no-cache" );
    response.addHeader( "Cache-Control", "must-revalidate" );
    response.addHeader( "Cache-Control", "no-cache" );
    response.addHeader( "Cache-Control", "no-store" );
    response.setDateHeader("Expires", 0);
单纯的使用 xmlhttp.setRequestHeader("Cache-Control","no-cache")无效。

3.Cache-Control头域
  Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如下:
  Public指示响应可被任何缓存区缓存。
  Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
  no-cache指示请求或响应消息不能缓存
  no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
  max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
  min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
  max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

Read more:
   http://www.jiehoo.com/browser-cache-problem.htm (作者: Cherami 原载: 浏览器缓存)
   再论怎么有效利用浏览器缓存之怎么避免浏览器缓存静态文件
   HTTP协议header头域- PetitPrince - 博客园
posted @ 2008-09-27 10:23 jht 阅读(16553) | 评论 (3)编辑 收藏
< link id = " css "  rel = StyleSheet type = " text/css "  href = " ./button.css "   />

< script type = " text/javascript " >
 
var  cssArray  =   new  Array( " button.css " , " button1.css " , " button2.css " , " button3.css " , " button4.css " , " button5.css " , " button6.css " );
 
var  index  =   0 ;
 
function  changeCssFile()
 
{
  
var  css  =  document.getElementById( " css " );
  index
++ ;
  
if (index < cssArray.length)
  
{
   css.href 
=  cssArray[index];
  }

  
else
  
{
   index 
= 0 ;
   css.href 
=  cssArray[index];
  }

 }

</ script >

  < class ="button"  href ="#"  onclick ="changeCssFile()" >
  
< span  id ="buttonText" > Change another style </ span >
 
</ a >
posted @ 2008-09-25 12:26 jht 阅读(744) | 评论 (0)编辑 收藏
A:浏览器问题,可能会把透明区域显示成有灰度的区域,解决办法,转成gif格式吧,支持比较好

see: GIF or PNG? - Quality Web Tips
posted @ 2008-09-24 23:02 jht 阅读(1164) | 评论 (1)编辑 收藏
比如说下面的这个header.jsp中有中文,那么包含这个文件的网页可能就会出现乱码
<jsp:include page="header.jsp"></jsp:include>

解决办法是在header.jsp里加上下面这段话:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
posted @ 2008-09-23 12:46 jht 阅读(434) | 评论 (0)编辑 收藏
     摘要: log4j 支持运行时修改日志的相关配置,看了一下他的source code, 用FileWatchdog这个类来做的,代码也很简单,通过循环在一定时间间隔读取配置文件,如果文件变更,调用一个doOnChange()方法。如果自己要做一个支持运行时修改配置的系统可参考上面的做法。下面是一段支持运行时修改配置的系统Prototype代码,和log4j的做法稍有不同,使用Observer模式,使其更加...  阅读全文
posted @ 2008-09-04 14:49 jht 阅读(1289) | 评论 (0)编辑 收藏

可以用下面这个方法来做到

import  org.apache.log4j.Logger;
import  org.apache.log4j.PropertyConfigurator;

public   class  DemoRunTimeChangeLog4J  {

 
private   static   final  Logger logger  =  Logger.getLogger(DemoRunTimeChangeLog4J. class );

 
public   static   void  main(String[] args)  {
  PropertyConfigurator.configureAndWatch(
" src/log4j.configureAndWatch " , 60000 );
  
  
while  ( true {
   
if  (logger.isDebugEnabled())  {
    logger.debug(
" DEBUG MESSAGE " );
   }


   logger.info(
" Info Message " );

   
try   {
    Thread.sleep(
5000 );
   }
  catch  (InterruptedException e)  {
   }

  }

 }

}


posted @ 2008-09-03 17:35 jht 阅读(609) | 评论 (0)编辑 收藏
自定义TagLib的时候碰到这个错误,原因是编辑tld文件的时候没有使用DTD或者Schema文件验证,拼写错误导致最终报这个错误消息

如果遇到同样问题的同学,不妨检查一下自己的tld文件对不对。

BTW: tld类的异常需要处理好
posted @ 2008-08-19 15:53 jht 阅读(7665) | 评论 (1)编辑 收藏
这个问题可能由两个地方导致

1. 你的POJO类不是一个JavaBean,最可能的原因是没有一个无参构造函数
2. 在dwr.xml里这个类的<convert>指定的不对,或者是没有指定
posted @ 2008-08-11 11:21 jht 阅读(4135) | 评论 (4)编辑 收藏
数独游戏小程序

数独的游戏规则很简单:在九个九宫格里,填入1到9的数字,让每个数字在每个行、列及九宫格里都 只出现一次就可以过关了! 虽然游戏的规则十分简单,但很多人在没有计算机辅助时,常常会不小心造成违规状况。

下面是我做的一个数独小程序 1.0 版本,目前功能如下:

选择外观;
数独自动出题;
数独自动解题;
游戏计时功能;
开启解答辅助功能,出错提示;
开启解答辅助功能,辅助线;

程序基于Java Swing,运行需要JRE1.6以上版本。
 
可双击执行的JAR包,点此下载。(Napkin的LookAndFeel蛮好玩,我就一起弄在里面了)
程序的源码,点此下载。(有兴趣修改源码的朋友可以DIY出自己喜欢的版本。)

或者也可以从 http://groups.google.com/group/afun 这个group的files里面找到上面的两个文件。

对数独有兴趣的朋友可以玩一下这个小工具,欢迎留下宝贵意见,让这个小程序更完善。 可能我会另开一篇日志说一下Source Code相关的东西。
 
Figure: 填值的出错提示
Figure: 填值的出错提示2
演示如何使用辅助线功能:
首先选中Enable help system选项, 然后选择按钮 1 ,这时候关于 1 的辅助线开启,把不能填1的单元格都画了线,画线规则是,1所在的行画桃红色横线,1所在的列画橙色竖线,1所在的九宫格画粉色X线,如下图,这时候我们发现,在第五行只有第二列这一单元格格没有被画上线,那么这一个肯定只能填上1。
这时候我们就可以把1填入到 第五行第二列,这时辅助线会自动更新。如下图,此时没有可以确定填入1的单元格了,我们可以换一个数看辅助线。
 OK,我们选择3,这时候辅助线如下,我们发现第五行第四格可以确定填入3这个值。
填入3之后的图如下:
解答成功之后,会弹出恭喜解答成功的对话框。
自动解答功能可能出现的异常情况
当题目比较复杂的时候,可能会弹出如下的提示异常的对话框,这是因为解答数独用了递归的解法,难度大时递归深度很深,导致栈溢出,可以通过运行JVM时指定线程栈大小的方法来解决这个问题。
posted @ 2008-08-02 17:32 jht 阅读(2686) | 评论 (4)编辑 收藏
new & valueof & 直接赋值的区别
首先来看下面这段代码
public static void main(String[] args) {
  String s1 = "s1";
  String s2 = new String("s2");
  String s3 = String.valueOf(12345);
}
 
编译成class文件之后,使用eclipse class file viewer查看
 
  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 3, Locals: 4
  public static void main(java.lang.String[] args);
     0  ldc <String "s1"> [16]
     2  astore_1 [s1]

     3  new java.lang.String [18]
     6  dup
     7  ldc <String "s2"> [20]
     9  invokespecial java.lang.String(java.lang.String) [22]
    12  astore_2 [s2]
    13  sipush 12345
    16  invokestatic java.lang.String.valueOf(int) : java.lang.String [25]
    19  astore_3 [s3]

    20  return
      Line numbers:
        [pc: 0, line: 12]
        [pc: 3, line: 13]
        [pc: 13, line: 14]
        [pc: 20, line: 20]
      Local variable table:
        [pc: 0, pc: 21] local: args index: 0 type: java.lang.String[]
        [pc: 3, pc: 21] local: s1 index: 1 type: java.lang.String
        [pc: 13, pc: 21] local: s2 index: 2 type: java.lang.String
        [pc: 20, pc: 21] local: s3 index: 3 type: java.lang.String
}
 
对于第一行代码 String s1 = "s1"; 编译成字节码之后,对应两条指令,
  1. ldc指令从运行时常量池push一个值到Frame的操作数栈上面,这个值在这里就是"s1"字符串的引用,
  2. astore指令将objectref存储到局部变量,这里也就是存储到局部变量s1。
 
对于第二行代码   String s2 = new String("s2");编译成字节码之后,对于的指令也用高亮标注出来了,这里把操作数栈的情况画了出来,希望能帮助理解。橙色标注的为栈顶元素。
  1. new指令会在堆上创建对象,操作数栈里压入创建的objectref,
     
    objectref
    ...
  2. dup指令复制操作数栈顶的元素, 
    objectref
    objectref
    ...
  3. ldc指令依然是从常量池push一个值到Frame的操作数栈上,这个值是"s2"字符串的引用。 
    "s2"_ref
    objectref
    objectref
    ...
  4. invokespecial 指令调用一个方法,这里就是调用String的构造函数,调用完成之后栈上还有一个objectref 
    objectref
    ...
  5. astore指令将objectref存储到局部变量,这里也就是存储到局部变量s2。 
                
    ...
 
对于第三行代码  String s3 = String.valueOf(12345); 编译成字节码之后对应的指令,
  1. sipush 将 12345 压栈
  2. invokestatic 调用 String.valueof(int) 方法
  3. astore 将栈顶的对象引用存储到本地变量s3 (这里不再深究这个栈顶元素是怎么来的了)
 
PMD检查代码的时候,有这样的warning: Avoid instantiating String objects.Call String.valueOf() instead. PMD给出的原因是In JDK 1.5, calling new String() causes memory allocation. String.valueOf() is more memory friendly.
 
经过上面的分解,我们应该知道原因了,以后写代码的时候,初始化一个字符串,  String s1 = "s1"; 这样的代码肯定比  String s2 = new String("s2");代码强,将其他类型的值转换成String的时候,valueof方法比new方法效率也高。

 
备注:
A frame is used to store data and partial results(局部变量,操作数栈), as well as to perform dynamic linking , return values for methods, and dispatch exceptions.
 
ldc指令的操作数栈: ...->...,value (value是int,float 或者 string 类型的引用)
astore的操作数栈: ...,objectref->...
new指令的操作数栈: ...->...,objectref
dup指令的操作数栈: ...,value->...,value,value
invokespecial的操作数栈: ...,objectref, [agr1,[arg2...]]->...
invloestatic的操作数栈:..., [arg1, [arg2...]] -> ...

 
如果要理解的更透彻建议阅读以下参考资料:
posted @ 2008-07-28 14:27 jht 阅读(1691) | 评论 (1)编辑 收藏

java.awt.Component.requestFocusInWindow

posted @ 2008-07-22 14:34 jht 阅读(372) | 评论 (1)编辑 收藏
http://www.blogjava.net/Files/jht/MyScreenSnap_2.0.zip

截图程序,设计目标:简单易用

支持全屏截图和选择截图,运行需要JRE1.5以上版本

在1.0版http://www.blogjava.net/Files/jht/MyScreenSnap.zip的基础上,

   * 修改了一下主界面,增加图片保存为BMP,GIF,JPG,PNG格式的功能

   * 参考了千里冰封的代码,加上了调整选择区域的功能

Source Code已经包含在压缩包里面了,有兴趣的可以down下来改改。

下面是1.0版本和2.0版本的两个界面。

1.0vs2.0.png
posted @ 2008-07-02 09:17 jht 阅读(321) | 评论 (1)编辑 收藏
其实是个简单的小问题,仅在此做个记录。

遇到这个问题的不妨读一下这篇文章先:Access查询和过滤条件 http://www.fontstuff.com/access/acctut06.htm

我遇到的报错语句如下:

update monitor_table set logoffTime ='2008-04-06 16:58:54', keyClickCount ='17' where userName ='abcd' and logonTime ='2008-04-06 16:56:36' 

读了上面的文章,知道 MS Access的时间分隔符号为 # ,而 MS SQL Server的时间分隔符为 '

所以正确的语句应该是:

update monitor_table set logoffTime ='2008-04-06 16:58:54', keyClickCount ='17' where userName ='abcd' and logonTime =#2008-04-06 16:56:36

posted @ 2008-05-19 15:39 jht 阅读(1894) | 评论 (1)编辑 收藏
http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96616/arxml24.htm
posted @ 2008-05-19 15:38 jht 阅读(180) | 评论 (0)编辑 收藏
如题,有人真的遇到过这个问题,开始被问到的时候还真觉得奇怪,心想不会啊,从JDK5开始就支持这个枚举类型了啊,为什么呢?

开始还怀疑他的JDK版本太低导致的,但是一看是JDK1.6的,迷惑了几秒。。。

然后我打开了Eclipse的Java编译选项,发现原来遇到这个问题的人的Java编译级别设置的是1.4,如下图,当然就会出问题了。

compile_setting.png

呵呵,虽然,这是个小问题,但是如果遇到了还真够新手郁闷一阵的。
posted @ 2008-04-02 20:56 jht 阅读(875) | 评论 (2)编辑 收藏

作者简介

徐皓,北京航空航天大学计算机系本科生,你可以通过ertri@163.com与他联系。

正文

不灵敏的图形用户界面会降低应用程序的可用性。当以下现象出现的时候,我们通常说这个用户界面反应不灵敏。

  1. 不响应事件的现象;
  2. 没有更新的现象
[@more@]

这些现象在很大程度上与事件的处理方法相关,而在编写Swing应用程序的时候,我们几乎必然要编写方法去响应鼠标点击按钮,键盘回车等事件。在这些方法中我们要编写一些代码,在运行时去触发一些动作。常见动作包括查找,更新数据库等。在这篇文章中通过对一个实例的分析,介绍了一些基本概念,常见的错误以及提出了一个解决方案。

event-dispatching thread

我们一定要记住,事件响应方法的代码都是在event-dispatching thread中执行的,除非你启用另一个线程。

那么,什么是event-dispatching thread呢?在《Java Tutorial》[1]中,作者给出了一条单一线程规则:一旦一个Swing组件被实现(realized),所有的有可能影响或依赖于这个组件的状态的代码都应该在event-dispatching thread中被执行。而实现一个组件有两种方式:

  1. 对顶层组件调用show(), pack(), 或者setVisible(true);
  2. 将一个组件加到一个已经被实现的容器中。

单一线程规则的根源是由于Swing组件库的大部分方法是对多线程不安全的,尽管存在一些例外。这些例外的情况可以在《Java Tutorial》[1]的相关章节找到,这里不再展开。

为了支持单一线程模型,Swing组件库提供了一个专门来完成这些与Swing组件相关的操作的线程,而这一线程就是event-dispatching thread。我们的事件响应方法通常都是由这一线程调用的,除非你自己编写代码来调用这些事件响应方法。在这里初学者经常犯的一个错误就是在事件响应方法中完成过多的与修改组件没有直接联系的代码。其最有可能的效果就是导致组件反应缓慢。比如以下响应按钮事件的代码:

String str = null;
this.textArea.setText("Please wait...");
try {
//do something that is really time consuming
str = "Hello, world!";
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.textArea.setText(str);    

执行之后的效果就是按钮似乎定住了一段时间,直到Done.出现之后才弹起来。原因就是Swing组件的更新和事件的响应都是在event-dispatching thread中完成的,而事件响应的时候,event-dispatching thread被事件响应方法占据,所以组件不会被更新。而直到事件响应方法退出时才有可能去更新Swing组件。

为了解决这个问题,有人也许会试图通过调用repaint()方法来更新组件:

final String[] str = new String[1];
this.jTextArea1.setText("Please wait...");
this.repaint();

try {
Thread.sleep(1000L);
}catch(InterruptedException e) {
e.printStackTrace();
}
str[0] = "Done.";

jTextArea1.setText(str[0]);

但是这一个方法没有起到预期的作用,按钮仍然定住一段时间,在察看了repaint()方法的源代码之后就知道原因了。

PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
new Rectangle(x, y, width, height));
Toolkit.getEventQueue().postEvent(e);        

repaint()方法实际上是在事件队列里加了一个UPDATE的事件,而没有直接去重画组件,而且这一个事件只能等待当前的事件响应方法结束之后才能被分配。因此只有绕过分配机制直接调用paint方法才能达到目的。

final String[] str = new String[1];
this.jTextArea1.setText("Please wait...");
this.paint(this.getGraphics());

try {
Thread.sleep(1000L);
}catch(InterruptedException e) {
e.printStackTrace();
}
str[0] = "Done.";

jTextArea1.setText(str[0]);

这样却是实现了更新,但是还存在着以下的问题。虽然从感觉上,按钮已经弹起来了,但是在Done.出现之前,我们却无法按下这个按钮。可以说按钮还是定住了,只不过定在了弹起的状态。调用重绘方法无法从根本上解决问题,因此我们需要寻求其他的方法。

使用多线程

有效的解决方法是使用多线程。首先看一看一个更好的解决方案,这一方案是在参考《Rethinking Swing Threading》[3]的一个程序片段完成的:

final String[] str = new String[1];
this.jTextArea1.setText("Please wait...");
this.repaint();

new Thread() {
public void run() {
try {
Thread.sleep(1000L);
}catch(InterruptedException e) {
e.printStackTrace();
}
str[0] = "Done.";
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
jTextArea1.setText(str[0]);
}
});
}
}.start();

在这个程序中,要花费大量时间的操作被放到另一个线程当中,从而使事件响应方法能快速返回,event-dispatching thread就可以更新UI和响应其它事件了。注意到这个程序使用了invokeLater()方法。invokeLater()方法的作用是让event-dispatching thread去运行制定的代码。当然也可以不使用invokeLater()方法,但是这样就违背了单一线程原则,同时带来了一定程度的相对多线程的不安全性。到现在,解决方案似乎是完美的了,但是我们看一看在原来的程序添加下面的代码,尽管我们通常不这样做。

public void paint(java.awt.Graphics g) {
super.paint(g);
g.drawRect(1, 1, 100, 100);
}

我们会发现以前画的矩形被覆盖了一部分,原因是由于我们没用重画这一个矩形,因此在结尾加上对repaint()方法的调用。

final String[] str = new String[1];
this.jTextArea1.setText("Please wait...");
this.repaint();

new Thread() {
public void run() {
try {
Thread.sleep(1000L);
}catch(InterruptedException e) {
e.printStackTrace();
}
str[0] = "Done.";
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
jTextArea1.setText(str[0]);
repaint();
}
});
}
}.start();

如果你认为这段代码过于缺乏可读性,通过在《Java Tutorial》[1]里面介绍的SwingWorker来简化编程的方法。可以通过实现一个construct()方法来实现花费大量时间的操作和重写finished()方法来完成组件更新的工作。

this.jTextArea1.setText("Please wait...");

final SwingWorker worker = new SwingWorker() {
public Object construct() {
try {
Thread.sleep(1000L);
}catch(InterruptedException e) {
e.printStackTrace();
}
return "Done.";
}
public void finished() {
jTextArea1.setText(getValue().toString());
repaint();
}
};
worker.start();

在《Rethinking Swing Threading》[3],作者将以上的编程方式称为同步方式。另外作者提出了一个通过消息机制来实现相同功能的更清晰,但是需要编写更多代码的"异步"的方法。

结论

总之,我们在编写使用Swing组件的程序是要记住以下几点:

1、不要过多地占用event-dispatching thread;

2、与更新组件相关的代码要使用event-dispatching thread去执行;

3、要更新组件。

编写反应灵敏的图形用户界面还需要考虑很多问题,以上只是最基本的一部分。欢迎有兴趣的读者来信进行讨论。

posted @ 2008-03-13 17:53 jht 阅读(555) | 评论 (0)编辑 收藏

打开注册表编辑器,进入主键[HKEY_CURRENT_USER\Software\Microsoft\Command Processor],将“CompletionChar”键值设置为9。  

posted @ 2008-01-30 16:40 jht 阅读(699) | 评论 (0)编辑 收藏
在Struts中我们用html:errors标签在JSP页面上输出验证过程中产生的错误信息,错误信息一般来自于消息资源文件(xxx.properties文件,一般位于classes目录下,文本文件),当然错误信息也可以是不是资源文件中的文本消息,而是自定义的文本。接下来将详细讲述。

  先来看一个简单例子

1、资源文件错误信息来源(其格式为 key = value )
   
   error.test = this is a test error.

2、JSP页面中用于显示错误信息标签
  
   <html:errors property="testerror"/>

3、ActionFormBean的validate()方法中产生错误信息

   ActionErrors error = new ActionErrors();

   error.add("testerror",new ActionMessage("error.test"))
  
   return error;

 

  这个例子的功能就是在ActionForm Bean的validate()方法中产生一条名为:testerror的错误信息,错误信息息是资源文件中key为error.test的值。然后在页面上用html:errors标签输出testerror这条错误信息。

  这是最常用的一种功能,所有的错误信息都在资源文件里面。

  有人会问,错误信息只能存放在资源文件中吗,其实不是这样。不需要资源文件也可以产生错误信息

  我们再来看一下ActionMessage的另一种构造方法:

  ActionMessage(String key,boolean isresource)

  如果isresource值为true,则表示key是资源文件中的key,产生的消息就是与key相对应的消息
  如果isresource值为false,则表示key为一条普通的消息。

  如果上面的error.add改为error.add("testerror",new ActonMessage("这是一条自定义消息",false",));那么页面上显示的将是:这是一条自定义消息.


  另外还可以用ActionMessage产生复合消息,比如我们要输出:xxx不能用作用户名,其中xxx是一个变量。

  首先我们在资源文件中加一个条复合消息

  testmsg = {0}不能用作用户名。这里{0}是要被替换的参数。

  我们再来看一下ActionMessage的另一中构造方法
  ActionMessage(String key,Object value0);

  也就是说用value0的值来替换{0}

  我们修改error.add为error.add("testerror",new ActonMessage("testmsg","毛泽东"))

  那么JSP页面上将显示:毛泽东不能用作用户名。


  当然在一条复合消息中也可带多个参数,参数依次为{0},{1},{2}或更多
  例如:loginUser = 用户名:{0} 姓名:{1} 登录次数:{2}.....
  那么在产生错误消息时就用new ActionMessage(String key,Object value0,Object value1,Object  value2.....)或者使用对象数组new ActionMessage(String key,Object[] values)
  

  String[] detail = {"Admin","王晶","12"};
  error.add("testerror",new ActionMessage("loginUser",detail))


Note:

Cannot find message resources under key org.apache.struts.action.MESSAGE  错误的原因是没有配置资源文件

解决办法: 在struts-config.xml 中加入如下的一段

<message-resources parameter="application" null="false"></message-resources>


posted @ 2008-01-14 22:20 jht 阅读(1126) | 评论 (1)编辑 收藏

备忘:

> sqlplus ( < username > [/ < password > ][@ < connect_identifier > ] | /) [AS SYSDBA | AS SYSOPER] | /NOLOG
 SQL  >     desc   user_source;
 Name                                       
Null  ?    Type
  
--  --------------------------------------- -------- ---------------------------- 
  NAME                                                 VARCHAR2  (  30  )
 TYPE                                                
VARCHAR2  (  12  )
 LINE                                                
NUMBER  
  
TEXT                                                   VARCHAR2  (  4000  )

SQL 
>     select     TEXT     from   user_source   where   TYPE  =   '  PROCEDURE  '     and   NAME  =   '  Your_Procedure_name  '  ;

no rows selected

SQL 
>    var  out_var  number
exec  Your_Procedure_name ( '' , '' , '' ,:out_var)
print  out_var

posted @ 2007-11-28 14:00 jht 阅读(2715) | 评论 (0)编辑 收藏
ct protect -r -chmod 775 directory-or-file-name #Set directory/file/element protection.
posted @ 2007-11-06 12:07 jht 阅读(551) | 评论 (0)编辑 收藏

问题,向脚步传递参数的时候如何取得一个一个的option

办法一: 就是一个一个读 用$#取得变量个数,然后读$1 $2 $3,不是很方便

查了一下命令手册:发现用getopts命令更方便,man page不是很好懂

直接看 Example.sh:

# !/ bin / sh

while  getopts 'a:b:c' myoption
    
do
    
case  $myoption  in
        a) ls 
- al
        ;;    
        b) ls 
- l $OPTARG    
        ;;
        c) ls 
- l    
    esac
    done


用法和效果:
Example.sh -a stringa
就会执行 ls -al 这个命令, stringa 其实不起左右,但是这个参数还是要的

Example.sh -b -lrt
那就会执行 ls -l -lrt 传进去的参数起作用了

当然也可以这样
Example.sh -a 123 -b -lrt z, 这个作用就是两个命令都执行了


可以用变量保存这些OPTARG参数,在while循环外面接着使用

posted @ 2007-10-30 14:46 jht 阅读(2186) | 评论 (0)编辑 收藏
Hibernate 提供了一个hibernate.properties的模板,稍加修改就能得到自己想要的配置效果

下面这一段XML配置文件中关于数据库连接方式的配置,可以在hibernate.properties中完成
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>
<hibernate-configuration>
    
<session-factory name="sf">
    
<!-- 
        <property name="hibernate.connection.driver_class">
            org.hsqldb.jdbcDriver
        </property>
        <property name="hibernate.connection.url">
            jdbc:hsqldb:hsql://localhost/HibernateMapping
        </property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.dialect">
            org.hibernate.dialect.HSQLDialect
        </property>
     
-->
        
<mapping package="cn.heapstack.models" />
        
<mapping class="cn.heapstack.models.User" />
        
<mapping class="cn.heapstack.models.UserInfo" />
    
</session-factory>

    
</hibernate-configuration>
## HypersonicSQL
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
hibernate.dialect org.hibernate.dialect.HSQLDialect
hibernate.connection.driver_class org.hsqldb.jdbcDriver
hibernate.connection.username sa
hibernate.connection.password
hibernate.connection.url jdbc:hsqldb:hsql://localhost/HibernateMapping
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$



代码示例:
Configuration cfg = new AnnotationConfiguration().configure("./hibernate.cfg.xml");
SessionFactory sf 
= cfg.buildSessionFactory();
Session session 
= sf.openSession();
org.hibernate.Transaction tx
= session.beginTransaction();
tx.commit();
session.close();
posted @ 2007-10-26 14:40 jht 阅读(277) | 评论 (1)编辑 收藏

AnyEdit  是一个挺好用的工具,在eclipse工具栏上加了几个常用的工具按钮,比如全部保存。
Work Set导入导出的功能也挺有用。

AnyEdit还有自动删除行末空格的功能,支持tab和空格的相互转换,支持在文本编辑状态下高亮显示空格。

除此之外打开光标下所在类定义或者是文件的功能也非常实用。

顺便说一下,这个插件的作者还开发了不少有用的插件,可以从下面的链接里找到更详细的信息

地址: http://andrei.gmxhome.de/eclipse.html

posted @ 2007-09-29 10:20 jht 阅读(2166) | 评论 (1)编辑 收藏
首先看这一段简单的log4j配置
log4j.logger.cn=debug,stdout
log4j.logger.cn.heapstack
=debug,stdout
log4j.appender.stdout
=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout
=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern
=%d [%t] %-5p %c line.%L: %m%n
这个配置导致日志文件中输出两行相同的结果

原因是这样的,第二行的logger继承自第一行的logger,两个logger的apperder都是指向stdout
Appender的输出是独立的,所以导致了我们使用如下代码获得logger的时候会输出两行

public static Logger logger = Logger.getLogger(cn.heapstack.demopkg.Main.class);


知道这个原因之后解决办法也就简单了,即我们不需要定义重复的appder,
可以把第二行最后的stdout去掉,或者注释掉第二行,如果输出级别相同的话
posted @ 2007-09-28 09:57 jht 阅读(1288) | 评论 (0)编辑 收藏

Download and some env configure
 1. download gwt version gwt-windows-1.4.60 from http://code.google.com/webtoolkit
 2. unzip gwt-windows-1.4.60.zip file
 3. set system env variable GWT_HOME to the path where you hold your gwt files
 4. add %GWT_HOME% to your env path

Google Code Home > Google Web Toolkit > Getting Started Guide , it's a good place to get start.
You could follow this guide and get a first impression of what GWT can do and how convenient it is.

Usage
projectCreator -eclipse MyProject
ApplicationCreator [-eclipse projectName] [-out dir] [-overwrite] [-ignore] className

 

Eclipse plugin

cypal.studio.for.gwt
 1. download from http://code.google.com/p/cypal-studio/ version: cypal.studio.for.gwt-RC2.zip
 2. install this eclipse plugin (install it by new local site or just copy files, it's up on you )
 
GWT Designer 

 1. download from http://www.instantiations.com/gwtdesigner/index.html
 2. during install you need to choose Eclipse base location and GWT_HOME location
 
 Study how to use this plugin,
Webdemos
http://www.instantiations.com/gwtdesigner/demos.html

GWT desinger document homePage
http://downloads.instantiations.com/DesignerDoc/integration/latest/docs/html/gwt/index.html

Tutorial: Creating a Login application
http://downloads.instantiations.com/DesignerDoc/integration/latest/docs/html/gwt/tutorial/tutorial_login.html
 

posted @ 2007-09-25 15:09 jht 阅读(442) | 评论 (1)编辑 收藏
Groovy Eclipse Plugin 允许你编辑编译允许groovy脚本和类。

注意该插件正在不断开发中,你可以查看该插件开发的最近进展: issues and bugs

Eclipse 版本兼容性

Eclipse 3.0 : 不能工作,因为和3.1Eclipse有依赖关系

Eclipse 3.1 : 该插件的 1.0.1 与之不兼容,但是插件的1.0.0.20070118 版本可以正常工作

Eclipse 3.2 : 兼容

Eclipse 3.3 : 兼容(根据最小化的初始测试)


通过UpdateSite安装

包含最近发布的站点: http://dist.codehaus.org/groovy/distributions/update/

  • 在Eclipse菜单里选择: Help -> Software Updates -> Find and Install -> Search For New Features
  • 点击 New Remote Site
  • 在 Name 字段里填名称 (例如: Groovy)
  • 将上面的URL拷贝到 URL 字段里,然后点击 OK
  • 选中新建Groovy站点然后确定
  • 在 Select the Features to Install 下选中Groovy 的选项(确保你选择了最新的版本)点击 Next
  • 接受,点击 Next
  • 如何默认安装位置可以的话,点击 Finish (然后eclipse开始下载Plugin)
  • 如果你看到plugin为签名的对话框弹出来了,点击 Install or Install All

这将下载并安装Eclipse的Groovy插件.  它需要重启Eclipse来保证插件加载完成。

如果你想尝试最近的开发中的版本,  可以用这个站点: http://dist.codehaus.org/groovy/distributions/updateDev/

创建一个 Groovy 工程

按照如下步骤创建一个基本的Groovy工程:

  • 打开: File -> New -> Project
  • 选择 Java Project 然后点 Next
  • Project Name 字段填上你工程的名字
  • Project Layout 下选择 Create separate source and output folders 然后点击 Finish
  • 在 Package Explorer 下找到刚刚新建的工程,右击, 选择 Groovy -> Add Groovy Nature

到目前为止你有了一个src目录,一个bin-groovy目录,还有几个库文件。还有一个由Eclipse创建的bin目录,但是因为过滤隐藏了。下面的几步是为了让bin-groovy目录成为默认的输出文件夹,并且将它和src文件夹关联,使得调试工具知道从哪找关联的源代码和类。

  • Package Explorer, 右击 "GroovyJava" 工程, 选择: Build Path -> Configure Build Path
  • 使用 Browse 按钮,将 Default Output Folderbin 改为 bin-groovy
  • 点击 OK, OK
posted @ 2007-09-23 11:19 jht 阅读(4055) | 评论 (2)编辑 收藏
     摘要: 使用DWR做一个demo的时候,总是报出 JS Alert: Max depth exceeded when dereferencing ... function  update()  {  // ...  阅读全文
posted @ 2007-08-12 17:54 jht 阅读(4176) | 评论 (5)编辑 收藏

这个问题出现发生的代码如下:

    public String execute() throws Exception {
        
// String path = getText("struts.multipart.saveDir");
        try {
            
int i = getMyDoc().length;

            
for (int j = 0; j < i; j++{
                File save 
= new File("C:/upload/" + getMyDocFileName()[j]);
                FileUtils.copyFile(getMyDoc()[j], save);
            }

        }
 catch (Exception e) {
            
return ActionSupport.ERROR;
        }

        
return ActionSupport.SUCCESS;

    }


这是用Struts2上传多个文件时候的一段代码,错误处理是遇到异常时return 一个ERROR,结果调用这个这个UploadAction报错 No result defined for action .....

应该修改成这样,捕获到异常时return ActionSupport.INPUT ,这样当页面第一次被载入时就不会报错了

posted @ 2007-07-26 17:29 jht 阅读(3542) | 评论 (1)编辑 收藏
这个问题是在使用Struts2想做一个上传文件的页面时候Tomcat报出来的错误,详细信息如下:
2007-7-19 21:34:09 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet jsp threw exception
java.lang.RuntimeException: Unable to load bean org.apache.struts2.dispatcher.multipart.MultiPartRequest (jakarta) - [unknown location]
    at com.opensymphony.xwork2.inject.ContainerBuilder$4.create(ContainerBuilder.java:136)
    at com.opensymphony.xwork2.inject.ContainerImpl.getInstance(ContainerImpl.java:476)
    at com.opensymphony.xwork2.inject.ContainerImpl.getInstance(ContainerImpl.java:486)
    at com.opensymphony.xwork2.inject.ContainerImpl$9.call(ContainerImpl.java:517)
    at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:542)
    at com.opensymphony.xwork2.inject.ContainerImpl.getInstance(ContainerImpl.java:515)
    at org.apache.struts2.dispatcher.Dispatcher.wrapRequest(Dispatcher.java:697)
    at org.apache.struts2.dispatcher.FilterDispatcher.prepareDispatcherAndWrapRequest(FilterDispatcher.java:330)
    at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:390)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
    at java.lang.Thread.run(Thread.java:595)
Caused by: Unable to load bean org.apache.struts2.dispatcher.multipart.MultiPartRequest (jakarta) - [unknown location]
    at org.apache.struts2.config.BeanSelectionProvider$ObjectFactoryDelegateFactory.create(BeanSelectionProvider.java:246)
    at com.opensymphony.xwork2.inject.ContainerBuilder$4.create(ContainerBuilder.java:134)
    ... 22 more

最后Google了不少文章,找到了原因:(缺少了必要的jar包)

Struts2使用开源项目Apache Jakarta Commons FileUpload和内建的FileUploadInterceptor拦截器实现文件上传,所需的jar包如下:

commons-logging-1.1.jar
freemarker-2.3.8.jar
ognl-2.6.11.jar
struts2-core-2.0.6.jar
xwork-2.0.1.jar
commons-io-1.3.1.jar
commons-fileupload-1.2.jar


参考资料:

在Struts 2中实现文件上传

Struts2文件上传



posted @ 2007-07-19 21:57 jht 阅读(17118) | 评论 (11)编辑 收藏
     摘要: 原文地址:  http://java.sun.com/docs/books/tutorial/rmi/index.html 译者:jht 欢迎大家对翻译中存在的问题批判指正,谢谢大家!从Word粘帖过来之后格式有点问题,所以把word文档传上来了,点击下载 RMI   ...  阅读全文
posted @ 2007-05-09 16:59 jht 阅读(2034) | 评论 (0)编辑 收藏
     摘要: 一、一些概念     WebService技术现在几乎无处不在,以前玩.NET的时候最开始接触这个概念,C#语言对WebService近似原生性的支持使我们用C#可以非常迅速的开发出一个WebService,没有任何复杂烦扰的步骤。    后来没有机会再在.Net Framework上面开发,转投了Java的怀抱,想要开发出一个WebService感觉比较,搞一堆命令生成一堆...  阅读全文
posted @ 2007-03-31 21:27 jht 阅读(3658) | 评论 (3)编辑 收藏
     摘要: 今天稍微花了点时间实现了一个java的屏幕截图程序,功能简单,支持全屏截图和选择截图用JSmooth做了个.exe程序,直接运行就可以了,附:程序下载 http://www.blogjava.net/Files/jht/MyScreenSnap.zipJRE1.4版本的可执行程序 http://www.blogjava.net/Files/jht/MyScreenSnap_jre1.4.zip关键...  阅读全文
posted @ 2007-03-29 19:19 jht 阅读(1649) | 评论 (5)编辑 收藏
这个技巧比较Cool也比较基础常用,关键技术是使用图像重新绘制组件
看下面demo的代码
import java.awt.Insets;
import javax.swing.ImageIcon;
import javax.swing.JButton;

public class ImageButton extends JButton {

    
private static final long serialVersionUID = 7760427126786950870L;

    
public ImageButton(ImageIcon icon) {
        setSize(icon.getImage().getWidth(
null),icon.getImage().getHeight(null));
        setIcon(icon);
        setMargin(
new Insets(0,0,0,0));
        setIconTextGap(
0);
        setBorderPainted(
false);
        setBorder(
null);
        setText(
null);

    }

}


稍微要解释一下的是讲button的边框都设置成为0,还有边框的重绘设置false,我们可以用不同的贴图表示按钮被选中等的状态

使用这个组件的demoCode

        ImageButton button = new ImageButton("images/*.png");
        button.setPressedIcon(
new ImageIcon("images/*.png"));
        button.setRolloverIcon(
new ImageIcon("images/*.png"));
        button.setSelectedIcon(
new ImageIcon("images/*.png"));
        button.setRolloverSelectedIcon(
new ImageIcon("images/*.png"));
        button.setDisabledIcon(
new ImageIcon("images/*.png"));
        button.setDisabledSelectedIcon(
new ImageIcon("images/*.png"));

这个Hack要显示效果好,关键就在于贴图了,可见美工很重要。

我准备每天Hack一篇

更多内容,可以看Swing Hacks


参考资料:
 "Swing Hacks by Joshua Marinacci and Chris Adamson. Copyright 2005 O'Reilly Media, Inc., 0-596-00907-0."
posted @ 2007-03-28 23:57 jht 阅读(492) | 评论 (0)编辑 收藏
It's easy to create a frame without title bar.Just use this method setUndecorated(true)

JFrame frame = new JFrame();
frame.setUndecorated(
true);
frame.setSize(
500200);
frame.show();
posted @ 2007-03-28 13:24 jht 阅读(385) | 评论 (0)编辑 收藏

Step1:创建带有Native方法描述的ProcessHandler.java文件

Step2javac 编译该文件,生成ProcessHandler.class文件

Step3javah ProcessHandler.class 生成pkg_ProcessHandler.h Native方法头文件,注意包名字为pkg,所以生成的方法以pkg_开头

Step4:使用Eclipse建立Managed Make C++ Project,在第二步选择Shared Library,然后把刚刚生成和的pkg_ProcessHandler.h 加入工程

Step5:实现Native方法,从头文件里面Copy出这个方法,完成具体实现,编译工程,生成dll

Step6:完成后Jni调用,注意dll库需要在系统Path里,否则会出现java.lang.UnsatisfiedLinkError: no *** in java.library.path

 

 

除了上面的路径问题,还有可能不能成功调用该 dll ,原因上 g++/gcc 编译出来的东西和 java 预期的不匹配,详细描述参考 http://www.blogjava.net/lixf/archive/2005/12/23/25177.html win32 下使用 gcc 编译供 java 调用的 dll 须知 (jni) 我也是遇到问题 Google 到这篇文章的, Solution 当然也在该文章里面

 

参考资料:

例解 VC++ 6.0 实现 JNI (非烂文)

posted @ 2007-01-16 15:33 jht 阅读(320) | 评论 (0)编辑 收藏
     摘要: 国内Nokia手机主要参数列表 型号   所属系列 最大Jar SizeMIDP版本 CLDC版本屏幕尺寸3105S40164KB11128x1283200S40164KB11128x1283300S40164KB11128x1283510S40164KB11128x1283530S40164KB11128x1283650S601动态分配11176x2086220S40164KB11128x128...  阅读全文
posted @ 2007-01-01 17:10 jht 阅读(453) | 评论 (0)编辑 收藏
Sun Microsystems 将 J2ME 定义为“一种以广泛的消费性产品为目标的的高度优化的 Java 运行时环境,包括寻呼机、移动电话、可视电话、数字机顶盒和汽车导航系统。”

J2ME最早在1999 年 6 月的JavaOne大会上被正式提出之后,J2ME 为小型设备带来了 Java 语言的跨平台功能,允许移动无线设备共享应用程序。有了 J2ME,Sun 已经使 Java 平台能够适应集成了或基于小型计算设备的用户产品。

J2ME实际上是一系列规范的集合,由JCP(Java Community Process)制定并发布相关的JSR(Java Specification Request),各个厂商按照规范在自己的产品上进行实现,但是必须要通过TCK(Technical Compatible Kit,兼容性测试)测试来保证兼容性。

J2ME定义了一种灵活的层次规范结构来规范众多的移动设备,不同层次的规范互相协作提供一个完整的移动Java平台。
20059610835921.jpg 

J2ME体系结构和配置
  (1)J2ME体系结构

  J2ME体系结构基于设备的系列和类别,一个类别定义了一个特定种类的设备。移动电话、寻呼机和个人电脑记事本都是单独的类别。对存储器和处理能力有相近需求的若干类别的设备构成设备的一个系列。移动电话、寻呼机和个人电脑记事本一起就是占用资源很小的设备的一个系列。

  Java 虚拟机层(Java Virtual Machine Layer):是Java虚拟机的一个实现,它是为特定设备的主机操作系统定制的,而且支持特定的J2ME配置(Configuration)。

  配置层(Configuration Layer):配置层定义了Java虚拟机功能上和特定类别设备上可用的Java类库的最小集。从某种程度上说,一个配置定义了Java平台功能部分和库的共同性,开发者可以假设这些功能部件和库在属于某一特定类别的所有设备上都是可用的。

  框架层(Profile Layer):框架层定义了特定系列设备上可用的应用程序编程接口(API)的最小集。框架在一个特定的配置上实现。应用程序是针对特定框架编写的,因此可以移植到支持该框架的任何设备上。一个设备可以支持多个框架。用户和应用程序供应商看到最多的就是这一层。

  MIDP(Mobile Information Device Profile)层:移动信息设备框架。是Java API集合,它处理诸如用户界面、持久存储和联网等问题。

  (2)J2ME配置Configuration

  由上可知,J2ME组件都围绕一个中心,这些中心被称为“配置”(Configuration)。它们用于消费电子和嵌入设备的特别的类。目前J2ME定义2个“配置”,这2种“配置”由于其处理运算的能力不同而支持不同的设备对象。

  Connected Limited Device Configuration(CLDC,有限连接设备配置):该“配置”定义Java应用程序接口以及支持手持设备的技术。如手机、掌上电脑等。

  Connected Device Configuration(CDC,连接设备配置):该“配置”支持“插入墙”式设备的应用程序接口,如机顶盒等。

  上述两种“配置”,其区别在于它们应用于的设备的能力:

  CLDC设备的处理器能力有限(与台式机比较),且存储器大小一般只在128KB到512KB之间,而CDC系统则不同,它可能有32位或64位处理器,以及有限的存储容量,不过它的下限也超过512KB。它们共同所遵循的原则是,每个不同功能的硬件设备都将被不同的虚拟机支持。

  3.J2ME的简表Profile
  虽然,“配置”为一组通用设备提供了最小的Java平台,但是开发者感兴趣的是为个别设备设计应用程序,当他们只使用“配置”进行开发,那么所编写的应用程序肯定会有所欠缺。“配置”必须满足所有设备的最小要求,而用户界面、输入机制和数据持久性都具有高度的设备具体性,每一种设备都有自己的方法,这些往往不在“配置”所能满足的最小要求范围之内。

  现在,5个已知简表已经有了规范。而每个简表的责任都是为了完善配置的不足。

  (1)MIDP简表

  MIDP(Mobile Information Device Profile,移动信息设备简表)是第一个实现的简表,它补充了CLDC配置,并且提供应用程序语义和控件、用户界面、持久存储器、网络和用于移动电话的计时器、双通道呼叫器和其他无线电设备。

  (2)PDA简表

  Palm公司是开发PDA简表规范的领头人,该简表完善了CLDC配置,在相当长的时间内,它都将是KJava类程序包的替代品。Java规范建议该简表至少应当提供2个核心功能片段,即用户界面显示工具包,适合于“有限的尺寸和深度显示”,另一个则是持久数据存储器机制。显示工具包应该是抽象窗口工具包的一个子集,而持久机制将为应用程序、数据、配置/环境信息提供简单的数据存储。

  (3)Foundation简表

  Foundation简表的任务是担任一个基础简表,便于以后开发出来的提供图形用户接口、 网络等功能的简表附着在它之上。除了用于基础简表,Foundation简表还提供完整网络的支持,不管有没有使用图形用户接口。

  (4)Personal简表

  在当前规范的需求下, Personal简表提供下一代Personal Java环境。该简表允诺,提供互联网连接性和Web保真度以及一个能够运行Java Applets的GUI。

  (5)RMI简表

  我们知道CDC配置为共享的、固定网络连接信息设备提供最小的Java环境。该简表将通过提供Java到Java的RMI来协助提供更好的网络连接性。


参考资料:
J2ME无线通信编程入门 
http://www.vchelp.net/wyy/j2me/j2me_arc.asp

名词:
Configuration
Profile
CDC
CLDC
MDIP

posted @ 2007-01-01 15:22 jht 阅读(505) | 评论 (0)编辑 收藏
使用OSGI还是J2ME还没有定下来

        针对SmartPhone 的 OSGI framework有一个来自ProSyst的Commercial版本的实现,可以通过注册获得试用版的软件,已经注册了,但是还没有通过审批获得下载权限。所以暂时OSGI的方案搁浅,下手不是那么方便,资料也少,虽然很想搞出这个玩意。

        于是想着建个J2ME的环境试试看,发现Nokia Developer Suite 3.0 已经不是新的版本,虽然网上搜到很多文章都是介绍3.0套件的,现在Nokia推荐的是Carbide.j 1.5,明天搭环境吧准备Eclipse 3.2 + EclipseMe + Carbide.j 1.5 + Sun WTK 2.2
posted @ 2007-01-01 00:32 jht 阅读(545) | 评论 (1)编辑 收藏
     摘要: 用各种网络下载工具下文件的时候,大多数下载软件支持添加批量下载任务的功能,闲暇之余coding了一个简单的程序,实现批量下载.分了三个类RegFiles.java主要实现通配符文件地址的构造,提供了一些辅助方法,方便的添加需要下载的URLURLFileSaver.java 实现将URL指向的文件保存到本地的功能FileDownLoader.java 创建多个线程下载大家看code,欢迎提出重构意见...  阅读全文
posted @ 2006-12-31 15:58 jht 阅读(1159) | 评论 (0)编辑 收藏

         最近准备毕业设计的开题报告,原来设想手机控制端使用J2ME,但是mentor给我思路说可以考虑使用OSGI,一番开导,完全打乱了我原来的想法,思路当然也开阔不少,我决定研究一下OSGI的可行性。

         先介绍一下OSGI,如很多人一样,对OSGI这个名词的了解关注适于Eclipse,常见的解释“OSGi 联盟建立于 1999 年,是一个非赢利机构,旨在建立一个开放的服务规范。OSGi 规范为网络服务定义了一个标准的、面向组件的计算环境,它最初的目的就是为各种嵌入式设备提供通用的软件运行平台,屏蔽设备操作系统与硬件区别的中间件平台,通过这个平台,可以对不同软件商提供的应用(OSGi 中称为 Bundle)进行组件的生命周期管理的能力,如应用组件可以从运行中被安装、升级或者移除而不需要中断设备的操作,应用组件可以动态的发现和使用其他库或者应用程序。由于 OSGi 技术具有服务组件模块化、动态加载应用等优点,正被越来越多的领域关注,如嵌入设备制造业、汽车制造业、企业应用等。目前,OSGi 联盟发布的最新的 OSGi 服务规范为 4.0。

           看了OSGI的WhitePaper说OSGI应用于多种领域,见下图osgi areas.PNG
        我就想在我的Nokia6670手机里使用OSGI,照理来讲肯定是可以搞定的,因为WhitePaper说了不少嘛,但是目前对OSGI的了解仅限于使用Eclipse开发几个Bundle的简单协作,自己想想直接把这个部署到手机里貌似不太可能,然后又Google的N多资料,终于发现一个CLDC设备上OSGI的实现,来自ProSystmBedded Server CLDC Edition,貌似有个评估版可以下载,我发现可以在我的Nokia机器上使用OSGI framework的希望了。还有Google到的信息是Knopflerfish的一个OSGI platform实现貌似是可以在SonyEricsson P900机器上跑起来了的。
        郁闷的台湾南海的地震把什么海底光缆搞挂了,这几天国外网站都上不了,osgi,Knopflerfish,ProSyst都上不去,所以不能获取进一步深入学习资料,网页都打不开非常郁闷啊!

        不知道有没有人部署过这样的OSGI在手机里的应用,总觉得这个OSGI的WhitePaper说的都是抽象层面上的,我想学习的是怎么样把这个用起来。说OSGI规范化***,但是不知道如何用起来啊。。。希望有研究OSGI的人和我交流交流。

       osgi architecture.PNG


         J2ME + WebService是个简单的架构,J2ME开发手机上的Application,WebService提供手机和Server的信息交互。考虑过用.NET实现WebService,J2ME调用。这个系统结构相对容易被更多人了解且容易实现。

         两种实现,相对来说更想尝试OSGI,但是OSGI却相对来说陌生一点,现在很多关于OSGI的资料也访问不了,矛盾啊。。。

posted @ 2006-12-29 22:47 jht 阅读(1000) | 评论 (3)编辑 收藏

         到公司实习近五个月了,主要从事C++开发,困扰于复杂的专家系统的陈旧代码,不能说代码写的不好,肯定比我写出来的C++代码好,但是却很难让人读懂,逻辑复杂,而且又缺乏Code的维护,文档也没有,所有系统特性完全由前人口传声授,搞得很头大。。。
         
         当然也学习到不少东西,比如如何分析复杂的代码,经历种种挫败打击之后,我总结出如下规律,面对一个复杂的系统,你完全不知道它是干什么的,首先从大的角度把握系统的业务特性,主要完成后哪些操作,企业级别应用不外乎数据库的CRUD,非要区分出不同之处个人认为就是各种应用如何把着简单的四种操作弄得更复杂啦!具体方法无非转圈再转圈!

         然后拆解出系统层次架构的模型,在纸上画出层次实现框图有助于快速把握系统的层次模型。

         分解出层次模型之后的下一步就是关注BusinessLogic层东西,如何系统层析模型不好,例如BL和DAO混杂,首先要做的是想办法如何重构这样的模型,因为不重构这样的系统很快你就会感觉这个项目没有尽头了,在痛苦中煎熬啊。在写Code之前,一定要理解BL的东西,Code谁都会写,但是要高效完成Coding工作,理解你要写什么是前提,我自己在这个方面吃亏不少,写出来Code,自己也不知道是干什么的,项目结束了,现在强烈鄙视自己了

         
         重新开始BLOG生涯了,原因:巩固自己学习到的知识,并且将自己学习的体会于大家分享,也许我的些许经验能给迷茫当中的人带来帮助,不吝啬自己的只言片语,哪怕是不够成熟的。另一方面,表达出自己的理解和思想,或许会获得大家不同的评价,你有一个思想我有一个思想,交换,我们就有两个思想了!当然,自己错误的理解马上能得到大家的纠正,这对自己知识的构建是非常好有帮助的!

         下一阶段学习计划 Spring,Hibernate,有空也玩玩AJAX

         

posted @ 2006-12-16 20:34 jht 阅读(247) | 评论 (0)编辑 收藏
      这篇文章在网上已经被转了无数次了,转贴负责的有图,不负责的图也丢了……  
      再转一次吧,我想也不为多,全当成自己的学习资料收集了
     
      以下内容转贴,因为转烂了,所以作者已经不详了……

最近我作了数据库JSP的频繁连接,在此给出数据库连接池的必要性,对于JSP来说一个很好的J2EE服务器是很必要的,JBOOS,WebLogic都是很好的解决方案。


一般情况下,在使用开发基于数据库的WEB程序时,传统的模式基本是按以下步骤:
  1. 在主程序(如Servlet、Beans)中建立数据库连接。
  2. 进行SQL操作,取出数据。
  3. 断开数据库连接。
  使用这种模式开发,存在很多问题。首先,我们要为每一次WEB请求(例如察看某一篇文章的内容)建立一次数据库连接,对于一次或几次操作来讲,或许你觉察不到系统的开销,但是,对于WEB程序来讲,即使在某一较短的时间段内,其操作请求数也远远不是一两次,而是数十上百次(想想全世界的网友都有可能在您的网页上查找资料),在这种情况下,系统开销是相当大的。事实上,在一个基于数据库的WEB系统中,建立数据库连接的操作将是系统中代价最大的操作之一。很多时候,可能您的网站速度瓶颈就在于此。
  其次,使用传统的模式,你必须去管理每一个连接,确保他们能被正确关闭,如果出现程序异常而导致某些连接未能关闭,将导致数据库系统中的内存泄露,最终我们将不得不重启数据库。
  针对以上问题,我们首先想到可以采用一个全局的Connection对象,创建后就不关闭,以后程序一直使用它,这样就不存在每次创建、关闭连接的问题了。但是,同一个连接使用次数过多,将会导致连接的不稳定,进而会导致WEB SERVER的频频重启。故而,这种方法也不可取。实际上,我们可以使用连接池技术来解决上述问题。首先,介绍一下连接池技术的基本原理。顾名思义,连接池最基本的思想就是预先建立一些连接放置于内存对象中以备使用:
    
如图所示,当程序中需要建立数据库连接时,只须从内存中取一个来用而不用新建。同样,使用完毕后,只需放回内存即可。而连接的建立、断开都有连接池自身来管理。同时,我们还可以通过设置连接池的参数来控制连接池中的连接数、每个连接的最大使用次数等等。通过使用连接池,将大大提高程序效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。下面我们以一个名为ConnectionPool的连接池为例来看看连接池的实现。先看看ConnectionPool的基本属性:
  m_ConnectionPoolSize:连接池中连接数量下限
  m_ConnectionPoolMax:连接池中连接数量上限
  m_ConnectionUseCount:一个连接的最大使用次数
  m_ConnectionTimeout:一个连接的最长空闲时间
  m_MaxConnections = -1:同一时间的最大连接数
  m_timer:定时器
  这些属性定义了连接池与其中的每个连接的有效状态值。连接池的自我管理,实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。其管理流程如下:

通过上图,我们可以定义出ConnectionPool要完成管理所需要的基本接口:
public class ConnectionPool implements TimerListener{
  public boolean initialize() //连接池初始化
  public void destroy() //连接池的销毁
  public synchronized java.sql.Connection getConnection() //取一个连接
  public synchronized void close() //关闭一个连接
  private synchronized void removeFromPool() //把一个连接从连接池中删除
  private synchronized void fillPool() //维护连接池大小
  public synchronized void TimerEvent() //定时器事件处理函数
}
  通过这几个接口,已经可以完成连接池的基本管理。在TimeEvent()函数中完成连接池的状态检验工作,fillPool()时连接池至少保持最小连接数。因为我们要保存每一个连接的状态,所以还需要一个数据库连接对象:
class ConnectionObject{
  public java.sql.Connection con; public boolean inUse; //是否被使用标志
  public long lastAccess; //最近一次开始使用时间
  public int useCount; //被使用次数
}
加入了ConnectionObject对象后,在ConnectionPool中操作的应该只是ConnectionObject,而其他进程需要的只是ConnectionObject的con属性,因此我们再加入一个类,作为其他进程获得与返回连接的接口: CLASS Conn{
  GetConnection(); //从连接池中取出一个有效连接
  CloseConnection(); //返回连接,此时并没有关闭连接,只是放回了连接池
  DestroyPool(); //销毁连接池
}
  最后我们的整个系统总的架构如下:
     
通过上面的介绍,我们可以看出,连接池技术的关键就是其自身的管理机制,以上的管理流程只是本人一点见解,关键是想向大家介绍一种思路,在此基础上,您可以进一步完善连接池技术为您所用。


posted @ 2006-03-14 14:36 jht 阅读(286) | 评论 (0)编辑 收藏
Adapter模式
使用Adapter模式的目的:把一个类的接口转换成客户端需要的接口。
适用场合:
   当你想使用一个现有类的功能,但是它的接口不能满足你的需要
   当你想创建一个循环使用的类,用于使一些没有相互联系的类,或者是未知的将来会引进的类之间协调合作完成某些功能。也就是说,这些类不必要具备一致的接口
   当你要使用数个现有的的子类,但是要对每一个子类进行接口的改写变得很不切实际。
 
具体的例子
   变压器(Adapter),变压器把一种电压变换成另一种电压。美国的生活用电电压是110V,而中国的电压是220V。如果要在中国使用美国电器,就必须有一个能把220V电压转换成110V电压的变压器。这个变压器就是一个Adapter。
 
客户买回了美国的电器Machine,工作电压110V,电器插头为3相(阴、阳、地级),所以需要一个电压和相级的转换器或者说是适配器来使这个Machine能在中国使用。
一、类的Adapter模式
package Adapter;

interface 电器需要使用
{
    
public void 两相插口();
    
public void 电压_110V();
}


class 中国_供电
{
    
protected int v;
    
public 中国_供电()
    
{
        v
=220;
        System.out.println(
"中国供电提供的电压是:" +v+"V");
    }

    
//返回中国电压的值
    public int voltage()
    
{
        
return v;
    }

}

class 变压器_相位转换器 extends 中国_供电 implements 电器需要使用 
{

    
public void 两相插口() {
        System.out.println(
"变压器_相位转换器——提供三相到两相转换操作,返回两相插口");
        
    }


    
public void 电压_110V() {
        v 
= this.voltage()/2;
        System.out.println(
"变压器_相位转换器——转换后提供电压为:"+v+"V");
    }

    
}


public class ClassAdapter {

    
public static void main(String[] args) {
        变压器_相位转换器 device 
= new 变压器_相位转换器();
        
        device.电压_110V();
        device.两相插口();
        
        System.out.println(
"经过变压器_相位转换器的包装(Warpper),在美国买来的电器能够使用啦!^0^");

    }


}


二、对象的Adapter模式
package Adapter;

interface 电器需要使用_a
{
    
public void 两相插口();
    
public void 电压_110V();
}


class 中国_供电_a
{
    
protected int v;
    
public 中国_供电_a()
    
{
        v
=220;
        System.out.println(
"中国供电提供的电压是:" +v+"V");
    }

    
//返回中国电压的值
    public int voltage()
    
{
        
return v;
    }

}

class 变压器_相位转换器_a implements 电器需要使用_a 
{
    中国_供电_a supply 
= new 中国_供电_a();

    
public void 两相插口() {
        System.out.println(
"变压器_相位转换器——提供三相到两相转换操作,返回两相插口");
        
    }


    
public void 电压_110V() {
        supply.v 
= supply.voltage()/2;
        System.out.println(
"变压器_相位转换器——转换后提供电压为:"+supply.v+"V");
    }

    
}


public class ObjectAdapter {

    
    
public static void main(String[] args) {
        变压器_相位转换器_a device 
= new 变压器_相位转换器_a();
        
        device.电压_110V();
        device.两相插口();
        
        System.out.println(
"经过变压器_相位转换器的包装(Warpper),在美国买来的电器能够使用啦!^0^");

    }


}


posted @ 2006-02-24 21:13 jht 阅读(998) | 评论 (0)编辑 收藏

设计模式学习(一) 工厂模式之简单工厂

Creational Pattern:

*creates objects for you rather than having you instantiate objects directly

*gives your program more flexibility in deciding which objects need to be created for a given case

 

工厂模式有以下三种形态:

简单工厂(Simple Factory)模式:又称静态工厂方法(Static Factory Method)模式

工厂方法(Factory Method)模式:又称多态性工厂(Polymorphic Factory)模式

抽象工厂(Abstract Factory)模式:又称工具箱(Kit Toolkit)模式

 

简单工厂模式其实是普通工厂模式的一个特例,今天就从这里开始吧。

其结构可以简单地表示如下:


SimpleFactory.jpg没用
Visio画,大家见谅呀


    我们从一个实际的例子来看这个简单工厂模式

假设一个农场,专门向市场销售各种水果,假设只提供良种的水果,苹果和葡萄,我们为水果设计一个抽象类Fruit,所有水果都必须实现这个接口

package simple_Factory;
//水果抽象出来的接口
public interface Fruit {
    
void grow();
    
void harvest();
}


public class Apple implements Fruit {

    
private int treeAge;

    
public void grow() {
        log(
"Apple is glowing");
        
    }


    
private void log(String string) {
        System.out.println(string);        
    }


    
public void harvest() {
        log(
"Apple has been harvested.");
    }

    
    
public int getTreeAge() {
        
return treeAge;
    }


    
public void setTreeAge(int treeAge) {
        
this.treeAge = treeAge;
    }


}


public class Grape implements Fruit {

    
private boolean seedless;
    
public void grow() {
        log(
"Grape is growing------");
    }


    
    
public void harvest() {
        log(
"Grape has been harvested.");
    }

    
private void log(String string) {
        System.out.println(string);        
    }


    
public boolean isSeedless() {
        
return seedless;
    }


    
public void setSeedless(boolean seedless) {
        
this.seedless = seedless;
    }


}


public class OtherFruits implements Fruit {

    
public void grow() {        
    }


    
public void harvest() {        
    }


}

 

FruitFactory类,水果加工厂,根据需要(不同参数代表不同的水果需求)给市场供给水果。

 

package simple_Factory;

//水果加工厂,根据需要给市场供给水果
public class FruitFactory {
    
public static Fruit supplyFruit(String need)
    
{
        
if(need.equalsIgnoreCase("apple"))
            
return new Apple();
        
else if(need.equalsIgnoreCase("grape"))
            
return new Grape();
        
else
            
return new OtherFruits();        
    }

}

测试方法:
package simple_Factory;

public class Test {

    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        Fruit a 
= FruitFactory.supplyFruit("apple");
        Fruit b 
= FruitFactory.supplyFruit("Grape");
        Fruit c 
= FruitFactory.supplyFruit("others");
        
        a.grow();a.harvest();
        b.grow();b.harvest();
        c.grow();c.harvest();
    }

}


    自己弄懂和讲给别人懂还是有很大差距的,第一篇文章虽然写好了,但是感觉不够好,不知道能不能给初学者一点点帮助呢……

    自强不息,继续努力!
posted @ 2006-02-21 22:03 jht 阅读(2168) | 评论 (7)编辑 收藏