posts - 78,  comments - 48,  trackbacks - 0
     摘要: 下面的代码表现出使用set 带来的好处。  1public class TaskTemplate {  2    private String id;  3    private String title;  4    private String detail;  5      6    private Set<TaskTemplate> preconditions;  7    p...  阅读全文
posted @ 2006-12-01 10:25 黑咖啡 阅读(351) | 评论 (0)编辑 收藏
Coding 生涯已经有1年4个月了,虽然比较熟悉公司框架,用起来还比较熟练,但是回头想想,其实自己还是停留在新手阶段,与刚出学校的那些“大侠”们不相上下。特别是昨天看到我们的CTO-BridGu(相信去过javaeye的朋友没有不知道这个名字的吧)给我改写的一段程序以后,感觉自己的程序是那么的幼稚。丝毫没有professional的感觉,很是惭愧!
这个功能是一个解析String生成function的功能,当然格式要求非常严格的,而且格式验证也是一个不可缺少,而且是非常重要的环节。
不知道你看到这个功能脑子里面想到是什么样的解决方案呢?我没有多想,拿起来就当String来处理,split, substring etc.

看看程序吧:
下面是我的方法,暂且说是方法吧:
 1    public void addFunction(String prototype,Long comId)throws AlpineException{
 2        ModDao dao = (ModDao)this.getDao("modDao");
 3        Components com = this.findByPrimaryKey(Components.class, comId);
 4        Functions function = new Functions();
 5        function.setComponent(com);
 6        prototype = delDupSpace(prototype);
 7        String[] funTtemp = prototype.split("\n");
 8        String fun = funTtemp[0];
 9        if(fun.indexOf("(") == -1||fun.indexOf(")") == -1){
10            throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
11        }
12        String funHead = fun.substring(0,fun.indexOf("("));
13        String[] typeAndHead = funHead.split(" ");
14        if(typeAndHead.length < 1){
15            throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
16        }else{
17            if(typeAndHead.length >1){
18                function.setReturnType(typeAndHead[0]);
19                function.setFunctionName(typeAndHead[typeAndHead.length-1]);
20            }else{
21                function.setReturnType("void");
22                function.setFunctionName(typeAndHead[0]);
23            }
24            if(fun.indexOf("//") != -1){
25                String exp = fun.substring(fun.indexOf(";")+1);
26                exp = exp.replaceAll("&#13;", "");
27                function.setExplanation(exp);
28            }
29            this.insert(function);
30    
31            String paStr = fun.substring(fun.indexOf("(")+1, fun.indexOf(")"));
32            if(!StringHelper.isEmpty(paStr)){
33                String[] pas = paStr.split(",");
34                for (int i = 0; i < pas.length; i++) {
35                    Parameters parameter = new Parameters();
36                    String[] pars = pas[i].split(" ");
37                    if(pars.length < 2 || pars.length > 3){
38                        throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
39                    }else{
40                        if(pars.length == 2){
41                            Parameters paDup = dao.getParameterByPaName(pars[1], function.getId());
42                            if(paDup != null)
43                                throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
44                                
45                            parameter.setParameterName(pars[1]);
46                            parameter.setParameterType(pars[0]);
47                            parameter.setInOrOut("In");
48                        }
49                        if(pars.length == 3){
50                            Parameters paDup = dao.getParameterByPaName(pars[2], function.getId());
51                            if(paDup != null)
52                                throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
53                            
54                            parameter.setParameterName(pars[2]);
55                            parameter.setParameterType(pars[1]);
56                            if(pars[0].contains("In"))
57                                parameter.setInOrOut("In");
58                            if(pars[0].contains("Out"))
59                                parameter.setInOrOut("Out");
60                        }
61                        parameter.setFunction(function);
62                        this.insert(parameter);
63                        parameter.setOrderF(parameter.getId());
64                        this.update(parameter);
65                    }
66                }
67            }
68            
69            for (int i = 1; i < funTtemp.length; i++) {//start 1
70                String[] paTemp = funTtemp[i].split(":");
71                if(paTemp.length == 2){
72                    Parameters parameter = dao.getParameterByPaName(paTemp[0].trim(),function.getId());
73                    if(parameter != null){
74                        parameter.setExplanation(paTemp[1]);
75                        this.update(parameter);
76                    }
77                }
78            }
79        }
80    }
以下是BirdGu的方案:
  1public class FunctionParser {
  2    public static class Token {
  3        private TokenType type;
  4        private String content;
  5        public Token(TokenType type, String content) {
  6            super();
  7            this.type = type;
  8            this.content = content;
  9        }
 10        public String getContent() {
 11            return content;
 12        }
 13        public TokenType getType() {
 14            return type;
 15        }
 16        
 17        
 18    }
 19    
 20    private enum TokenType {symbol, leftParenthese, rightParenthese, inOutFlag, comment, comma};
 21    private enum TokenParseStatus {start, inSymbol, comment1, inOutFlag};
 22
 23    private interface ParseStatus {
 24        public ParseStatus process (Functions function, Token token, Stack<String> symbolStack)
 25        throws InvalidSyntaxException;
 26    }
 27    
 28    private static final ParseStatus START = new ParseStatus() {
 29        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack)
 30        throws InvalidSyntaxException {
 31            if (token.getType() == TokenType.symbol) {
 32                symbolStack.push(token.getContent());
 33                return GOT_FIRST_SYMBOL;
 34            } 
 35            throw new InvalidSyntaxException (token);
 36        }
 37    };
 38    
 39    private static final ParseStatus GOT_FIRST_SYMBOL = new ParseStatus () {
 40        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 41            if (token.getType() == TokenType.leftParenthese) {
 42                function.setReturnType("void");
 43                function.setFunctionName(symbolStack.pop());
 44                return WAITING_FIRST_ARG;
 45            } else if (token.getType() == TokenType.symbol) {
 46                function.setFunctionName(token.getContent());
 47                function.setReturnType(symbolStack.pop());
 48                return BEFORE_ARG_DEF;
 49            } 
 50            throw new InvalidSyntaxException (token);
 51        }
 52    };
 53    
 54    private static final ParseStatus BEFORE_ARG_DEF = new ParseStatus () {
 55        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 56            if (token.getType() == TokenType.leftParenthese) {
 57                return WAITING_FIRST_ARG;
 58            }
 59            throw new InvalidSyntaxException (token);
 60        }
 61    };
 62    
 63    private static final ParseStatus WAITING_FIRST_ARG = new ParseStatus () {
 64
 65        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 66            if (token.getType() == TokenType.rightParenthese) {
 67                return AFTER_ARG_DEF;
 68            } else if (token.getType() == TokenType.symbol) {
 69                symbolStack.push(token.getContent());
 70                return GOT_ARG_TYPE;
 71            } else if (token.getType() == TokenType.inOutFlag) {
 72                symbolStack.push (token.getContent());
 73                return GOT_IN_OUT_FLAG;
 74            }
 75            throw new InvalidSyntaxException (token);    
 76        }
 77    };
 78    
 79    private static final ParseStatus GOT_IN_OUT_FLAG = new ParseStatus () {
 80        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 81            if (token.getType() == TokenType.symbol) {
 82                symbolStack.push(token.getContent());
 83                return GOT_ARG_TYPE;
 84            }
 85            throw new InvalidSyntaxException (token);    
 86        }
 87    };
 88    
 89    private static final ParseStatus GOT_ARG_TYPE = new ParseStatus () {
 90        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 91            if (token.getType() == TokenType.symbol) {
 92                Parameters param = new Parameters ();
 93                param.setParameterName(token.getContent());
 94                param.setParameterType(symbolStack.pop());
 95                String inOutFlag = "In";
 96                if (!symbolStack.isEmpty()) {
 97                    inOutFlag = symbolStack.pop();
 98                }
 99                param.setInOrOut(inOutFlag);
100                function.adParameter(param);
101                return GOT_ARG_VALUE;
102            }
103            throw new InvalidSyntaxException (token);    
104        }
105    };
106    
107    private static final ParseStatus GOT_ARG_VALUE = new ParseStatus () {
108        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
109            if (token.getType() == TokenType.rightParenthese) {
110                return AFTER_ARG_DEF;
111            } else if (token.getType() == TokenType.comma) {
112                return WAITING_ARG;
113            }
114            throw new InvalidSyntaxException (token);    
115        }
116    };
117    
118    private static final ParseStatus WAITING_ARG = new ParseStatus () {
119        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
120            if (token.getType() == TokenType.symbol) {
121                symbolStack.push(token.getContent());
122                return GOT_ARG_TYPE;
123            } else if(token.getType() == TokenType.inOutFlag) {
124                symbolStack.push(token.getContent());
125                return GOT_IN_OUT_FLAG;
126            }
127            return null;
128        }
129    };
130    
131    private static final ParseStatus AFTER_ARG_DEF = new ParseStatus () {
132        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
133            if (token.getType() == TokenType.comment) {
134                function.setExplanation(token.getContent());
135                return END;
136            }
137            throw new InvalidSyntaxException (token);
138        }
139    };
140    
141    private static final ParseStatus END = new ParseStatus () {
142        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
143            throw new InvalidSyntaxException (token);
144        }
145    };
146    
147    private StringBuffer currentLine;
148    private int index;
149    private Functions function;
150    
151    public Functions parse(String content) throws InvalidSyntaxException {
152        if (StringHelper.isEmpty(content)) {
153            throw new IllegalArgumentException ("content is empty.");
154        }
155        StringTokenizer tokenizer = new StringTokenizer (content, "\n");
156        String line = tokenizer.nextToken();
157        parseFirstLine (line);
158        while (tokenizer.hasMoreTokens()) {
159            line = tokenizer.nextToken();
160            parseParamLine (line);
161        }
162        return function;
163    }
164    
165    private void parseFirstLine (String line) throws InvalidSyntaxException {
166        currentLine = new StringBuffer (line);
167        index = 0;
168        function = new Functions ();
169        Token token;
170        ParseStatus status = START;
171        Stack<String> stack = new Stack<String> ();
172        while ( (token = nextToken()) != null) {
173            status = status.process(function, token, stack);
174        }
175        if (status != AFTER_ARG_DEF && status != END) 
176            throw new InvalidSyntaxException ("Function hasn't finished properly.");
177    }
178
179    private void parseParamLine (String line) 
180    throws InvalidSyntaxException {
181        int idx = line.indexOf(':');
182        if (idx < 0) {
183            throw new InvalidSyntaxException ("Expected ':' from parameter line.");
184        }
185        String paramName = line.substring(0, idx);
186        String comment = line.substring(idx + 1);
187        Parameters param = function.getParameter (paramName);
188        if (paramName == null)
189            throw new InvalidSyntaxException ("Unknown parameter:'paramName'");
190        param.setExplanation(comment);
191    }
192    
193    private Token nextToken () throws InvalidSyntaxException {
194        if (index >= currentLine.length())
195            return null;
196        StringBuffer buf = new StringBuffer ();
197        TokenParseStatus status = TokenParseStatus.start;
198        while (index < currentLine.length ()) {
199            char ch = currentLine.charAt(index);
200            if (status == TokenParseStatus.start) {
201                if (isSymbolLetter(ch)) {
202                    status = TokenParseStatus.inSymbol;
203                    buf.append(ch);
204                    ++ index;
205                } else if (ch == '(') {
206                    ++ index;
207                    return new Token (TokenType.leftParenthese, "(");
208                } else if (ch == ')') {
209                    ++ index;
210                    return new Token (TokenType.rightParenthese, ")");
211                } else if (ch == ',') {
212                    ++ index;
213                    return new Token (TokenType.comma, ",");
214                } else if (ch == ' ' || ch == '\t') {
215                    ++ index;
216                } else if (ch == '[') {
217                    status = TokenParseStatus.inOutFlag;
218                    ++ index;
219                } else if (ch == ';') {
220                    ++ index;
221                    String str = currentLine.substring(index);
222                    index = currentLine.length();
223                    return new Token (TokenType.comment, str);
224                } else {
225                    throw new InvalidSyntaxException ("Enexpected character: " + ch);
226                }
227            } else if (status == TokenParseStatus.inSymbol) {
228                if (isSymbolLetter(ch)) {
229                    buf.append(ch);
230                    ++ index;
231                } else {
232                    return new Token (TokenType.symbol, buf.toString());
233                } 
234            } else if (status == TokenParseStatus.inOutFlag) {
235                if (isSymbolLetter(ch)) {
236                    buf.append (ch);
237                    ++ index;
238                } else if ( ch == ']') {
239                    ++ index;
240                    String str = buf.toString ();
241                    if (! ("In".equals(str) || "Out".equals(str))) {
242                        throw new InvalidSyntaxException ("Invalid in/out flag.");
243                    }
244                    return new Token (TokenType.inOutFlag, str);
245                }
246            }
247        }
248        if (status == TokenParseStatus.inSymbol) {
249            return new Token (TokenType.symbol, buf.toString());
250        }
251        return null;
252    }
253
254    private boolean isSymbolLetter(char ch) {
255        return Character.isLetter(ch) || Character.isDigit(ch);
256    }
257}

相比之下,第一种方法相形见绌。
想必这也是很多“大鸟”找不到合适人选的原因吧。
上面两种方法不用多说,大家一看就知道好在哪里,同时还是编程思想的截然不同。
posted @ 2006-12-01 10:13 黑咖啡 阅读(409) | 评论 (0)编辑 收藏
Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。

  写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?

  这需要你先插入一个empty的blob,这将创建一个blob的cursor,然后你再把这个empty的blob的cursor用select查询出来,这样通过两步操作,你就获得了blob的cursor,可以真正的写入blob数据了。

  看下面的JDBC的demo,把oraclejdbc.jar这个二进制文件写入数据库表javatest的content字段(这是一个blob型字段)

  import java.sql.*;
  import java.io.*;
  import oracle.sql.*;
  public class WriteBlob {

  public static void main(String[] args) {

  try {
  DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
  Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","fankai","fankai");
  conn.setAutoCommit(false);

  BLOB blob = null;

  PreparedStatement pstmt = conn.prepareStatement("insert into javatest(name,content) values(?,empty_blob())");
  pstmt.setString(1,"fankai");
  pstmt.executeUpdate();
  pstmt.close();

  pstmt = conn.prepareStatement("select content from javatest where
  }
posted @ 2006-11-10 11:45 黑咖啡 阅读(2258) | 评论 (1)编辑 收藏

我用过的2个:

1.xtreexloadtree,总体来说,实现还不错,提供了一次性构建树,和动态加载树(生成指定格式的XML才可以),改变Style,功能中等,用法中等.

2.yuitreeview,这也是不错的实现,是Yahoo提供的,支持一次性构建,动态构建,改变Style,Menu样式等等,功能很多,但用法比较复杂


没用过,只是听说的

3.dtree,比较中规中矩的一个实现,用法简单,不支持动态加载。



还有其他的好的js,大家可以补充。

posted @ 2006-11-09 16:13 黑咖啡 阅读(766) | 评论 (0)编辑 收藏
   

 
Oracle8i中使用Java语言来开发存储过程
本篇文章来源与时代朝阳数据库(原晓通数据库)培训部Oracle 资料库。
在Oracle8i之前,开发人员只能使用PL/SQL来开发存储过程。而在Oracle8i之中,不仅可以使用原有的PL/SQL开发存储过程,而且也可以使用Java语言来开发存储过程。本篇文章将简单介绍关于这方面的知识,包括以下内容:
 
l         存储过程简介;
l         Java存储过程
l         Java存储过程的开发步骤
l         使用Java开发过程;
l         使用Java开发函数;
l         使用Java开发包;
l         使用Java开发触发器;
l         使用Java开发对象方法;
l         使用JDeveloper开发JSP。 存储过程简介
存储过程是存储在数据库中的一段存储程序。当创建存储过程时,系统会对其进行编译,并将执行代码存储到数据库中。
 
1.         设计存储过程的方针
 
l         在定义存储过程时,要使用其完成单一、相对集中的任务。
l         在定义存储过程时,不要定义已经由其它特征所提供功能的过程。例如,不要定义强制数据完整性的过程(使用完整性约束)。
 
2.         存储过程的优点
1)        安全性
 
当创建了存储过程之后,可以将执行该过程的权限授予其它用户,从而使得他可以执行特定的数据库操作,而不能访问其它模式对象(例如表)。例如,你可以将执行过程(更新表)的权限授予其它用户,但不授予它们直接访问该表的权限。
 
2)        性能
 
l         存储过程只被发送到数据库一次,相对于SQL语句或PL/SQL块而言,其网络通信量更小。
l         当调用存储过程时,数据库会直接运行该存储过程,无需进行编译。相对于SQL语句或PL/SQL块而言,其执行速度更快。
 
3)        内存分配
 
存储过程充分利用了Oracle共享内存的能力。在将存储过程装载到内存中后,多个用户可以同时调用该存储过程,从而降低了应用对Oracle的实际内存需求。
 
4)        生产力
 
存储过程提高了开发生产力。通过将公共集合编写为存储过程,避免了冗余代码,从而提高了开发生产力。例如,我们可以编写用于插入、更新、删除AUTHS表的过程,此后应用可以直接调用这些过程,而无需重写SQL语句。当管理数据的方法发生变化时,只需要修改过程,而不需要对应用进行任何修改。 Java存储过程
在以前的Oracle版本中,开发存储过程是通过PL/SQL来完成的。而在Oracle8i版本中,我们不仅可以使用PL/SQL开发存储过程,而且还可以使用Java语言来开发存储过程。
 
1.         PL/SQL与Java存储过程比较
 
与PL/SQL相比,使用Java语言开发存储过程有以下优点:
 
l         Java语言具有更强大的运算能力,提供了更多的运算方法。当要完成进行复杂运算的存储过程时,使用JSP将是你最好的选择。
l         PL/SQL只能用于Oracle数据库,而Java语言可以应用于更多的数据库系统(如Sybase、DB2、Informix等等),所以Java存储过程将具有更好的兼容性、可移植性。
 
2.         JSP分类
Java存储过程包括过程、函数、触发器以及对象方法四种类型。
 
3.         调用JSP的四种方法
 
l         CALL语法;
l         DML语句;
l         PL/SQL块、子程序、包;
l         由触发器隐含调用。 Java存储过程的开发步骤
1.         编写Java源代码
 
当开发Java存储过程时,首先应该编写Java源代码。如下图所示:
注意事项:
 
l          当以public方式声明类时,类名必须与其文件名完全一致。
l          只有public static方法可以作为Java存储过程。
 
2.         装载Java代码及类到Oracle8i数据库中
在编写了Java源代码之后,接下来应该将Java代码及相应的Java类装载到Oracle8i数据库中。如下图所示:
装载Java代码及类到RDBMS有以下两种方法:
 
l         使用loadjava工具,通过该工具可以快速装载Java源代码(.java)、Java二进制代码(.class)以及Java打包文件(.jar)。
l         使用CREATE Java、ALTER Java装载Java代码。
 
其中,前一种方法相对简单,并且我们推荐你使用这种方法。
 
3.         生成调用说明
 
在装载了Java类之后,接下来应该生成对public static方法的调用说明,最终完成Java存储过程的开发工作。如下图所示:
 
完成上述步骤之后,就完成了Java存储过程的开发工作,然后就可以调用并执行该Java存储过程了。 使用Java开发过程
过程用于执行某种操作。需要注意的是,过程所对应的Java方法返回值必须为空(void)。本节以创建用于插入、修改和删除AUTHS表的JSP为例,说明使用Java开发过程的方法。如下图所示:
下面讲述完成上述任务的方法及过程:
 
1.         编写Java源代码
 
程序清单如下(manipulate_auths.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
 
/* 主类 */
public class manipulate_auths {
 
  public static void insert_auths
    (String code,String name,int sex,String birthdate,String entry_date_time)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
String sql = "INSERT INTO auths
 (author_code,name,sex,birthdate,entry_date_time) " +
                 "VALUES (?,?,?,?,?)";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      pstmt.setString(2, name);
      pstmt.setInt(3, sex);
      pstmt.setString(4, birthdate);
      pstmt.setString(5, entry_date_time);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) { }
  }
 
  public static void delete_auths (String code)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "DELETE FROM auths  WHERE author_code = ?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) { }
  }
 
  public static void modify_salary (String code,float salary)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "UPDATE auths SET salary = ? WHERE author_code = ?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setFloat(1, salary);
      pstmt.setString(2, code);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) { }
  }
}
2.         装载Java代码及类到Oracle8i数据库中
 
在编写了Java源代码之后,就可以将Java对象装载到Oracle8i数据库中了。下面是完成这项任务的方法:
 

 
3.         发行Java,生成调用说明
 
在装载了Java类后,就可以发行该Java类,并生成调用其方法的过程说明了。下面是完成该项任务的方法:
 




 
4.         调用JSP
在生成了调用Java方法的过程说明之后,我们就可以调用JSP了。例如:
 

使用Java开发函数
函数用于返回特定数据。本节将通过创建用于返回作者的文章标题,以及某种类型的文章个数为例,说明使用Java开发函数的方法。如下图所示:
 
 
下面讲述完成上述任务的方法和过程。
 
1.         编写Java源代码
 
程序清单如下(query_article.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
 
/* 主类 */
public class query_article {
 
  public static String auths_article(String code)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql1 = "SELECT name FROM auths WHERE author_code=?";
    String sql2 = "SELECT title FROM article WHERE author_code=?";
    /* 声明并初始化auths_article变量 */
    String auths_article = new String();
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql1);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      /* 执行查询,并将结果保存到结果集中 */
      ResultSet rset = pstmt.executeQuery();
      /* 循环获取并处理结果集数据 */
      while(rset.next())
        auths_article =auths_article + rset.getString(1);
      /* 关闭结果集 */
      rset.close();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
    auths_article = auths_article + "所编写文章的标题如下:\n";
 
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql2);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      /* 执行查询,并将结果保存到结果集中 */
      ResultSet rset = pstmt.executeQuery();
      /* 循环获取并处理结果集数据 */
      while(rset.next()) {
        auths_article =auths_article + "    " + rset.getString(1) + "\n";
      }
      /* 关闭结果集 */
      rset.close();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
    return auths_article;
  }
 
  public static String query_type_article_number(String code)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "SELECT count(*) FROM article WHERE article_code IN "
       + "(SELECT article_code FROM article_type WHERE type_code=?)";
    String article_number = new String("类型为" + code + "的文章共有 ");
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      /* 执行查询,并将结果保存到结果集中 */
      ResultSet rset = pstmt.executeQuery();
      /* 循环获取并处理结果集数据 */
      while(rset.next())
        article_number = article_number + rset.getString(1) + "篇";
      /* 关闭结果集 */
      rset.close();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
    return article_number;
  }
}
 
2.         装载Java代码及类到Oracle8i数据库中
 
在编写了Java源代码之后,就可以将Java对象装载到Oracle8i数据库中了。下面是完成这项任务的方法:

 
3.         发行Java,生成调用说明
 
在装载了Java类后,就可以发行该Java类,并生成调用其方法的函数说明了。下面是完成该项任务的方法:
 


 
4.         调用JSP
 
在生成了调用Java方法的函数说明之后,就可以调用这些函数了。例如:
 
使用Java开发
Java类用于封装Java方法,与此类似,包用于封装过程和函数等。本节将通过创建用于管理表subject的包为例,说明使用Java开发包的方法。如下图所示:
 

 
下面讲述完成上述任务的方法和过程。
 
1.         编写Java源代码
 
程序清单如下(manage_subject.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
 
/* 主类 */
public class manage_subject {
 
  public static String query_subject()
  throws SQLException {
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造SQL语句 */
    String sql = "SELECT * FROM subject";
    /* 声明并初始化subject变量 */
    String subject = new String();
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 创建Statement对象 */
      Statement stmt = conn.createStatement();
      /* 执行SQL语句,并将查询结果赋给结果集 */
      ResultSet rset = stmt.executeQuery(sql);
      /* 循环获取并处理结果集变量 */
      while(rset.next())
        subject = subject + rset.getString(1) + "\n";
      /* 关闭结果集 */
      rset.close();
    } catch (SQLException e) {}
    return subject;
  }
 
  public static void insert_subject(String subject)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "INSERT INTO subject VALUES(?)";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, subject);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
 
  public static void delete_subject(String subject)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "DELETE FROM subject WHERE subject=?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, subject);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
 
  public static void update_subject(String old_subject,String new_subject)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "UPDATE subject SET subject=? WHERE subject=?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, new_subject);
      pstmt.setString(2, old_subject);
      /* 执行动态SQL语句 */
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
}
 
2.         装载Java代码及类到Oracle8i数据库中
 
在编写了Java源代码之后,就可以将Java对象装载到Oracle8i数据库中了。下面是完成这项任务的方法:
 


 
3.         发行Java,生成调用说明
 
在装载了Java类后,就可以发行该Java类,并生成调用其方法的包了。下面是完成该项任务的方法:



4.         调用JSP
 
在生成了调用Java方法的包后,就可以调用这些方法所对应的函数和过程了。例如:
 




使用Java开发触发器
触发器是一段存储程序,当执行特定修改操作时,会触发它,并执行其中的存储程序。下面以记载表AUTHS作者工资更新情况的触发器为例,说明使用Java开发触发器的方法。如下图所示:
 


 
下面讲述完成上述任务的方法和过程。
 
1.         编写Java源代码
 
程序清单如下(trigger.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
/* 主类 */
public class trigger {
 
  public static void log_salary(String name,float old_sal,float new_sal)
  throws SQLException {
 
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    String sql = "INSERT INTO salary_audit VALUES(?,?,?)";
 
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      PreparedStatement pstmt = conn.prepareStatement(sql);
      pstmt.setString(1, name);
      pstmt.setFloat(2, old_sal);
      pstmt.setFloat(3, new_sal);
      pstmt.executeUpdate();
      pstmt.close();
    } catch (SQLException e) {}
  }
}
 
2.         装载Java代码及类到Oracle8i数据库中
 
在编写了Java源代码之后,就可以将Java对象装载到Oracle8i数据库中了。下面是完成这项任务的方法:
 


3.         发行Java,生成调用说明
 
在装载了Java类后,就可以发行该Java类,并生成调用其方法的过程说明及触发器了。下面是完成该项任务的方法:




 
4.         调用JSP
 
在创建了触发器之后,当修改作者工资时会自动调用其中的存储程序。例如:
 

使用Java开发对象方法
对象类型是一种用户自定义的数据结构,它可以将数据类型、函数以及过程封装到该数据结构中。对象方法是指对象类型中的函数和过程,本节将以获取和增加对象工资信息为例,说明使用Java开发对象方法的方法。如下图所示:

 
下面讲述完成上述任务的方法及过程:
 
1.         编写Java源代码
 
程序清单如下(object_type.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;
import oracle.oracore.*;
import oracle.jdbc2.*;
import java.math.*;
 
/* 主类,实现了SQLData接口 */
public class object_type implements SQLData {
 
  /* 声明private变量,它们对应于对象类型的属性 */
  private String code;
  private String name;
  private BigDecimal sex;
  private BigDecimal salary;
 
  /* 方法get_name():对象类型的方法,用于获取对象姓名 */
  public String get_name() {
    return name;
  }
 
  /* 方法get_salary():对象类型的方法,用于获取对象工资 */
  public BigDecimal get_salary() {
    BigDecimal sal = salary;
    return sal;
  }
  /* 方法raise_salary():对象类型的方法,用于增加对象工资 */
  public void raise_salary(BigDecimal raise) {
    salary = salary.add(raise);
  }
 
  /* 以下程序段实现了接口SQLData */
  String sql_type;
  public String getSQLTypeName() throws SQLException {
    return sql_type;
  }
 
  public void readSQL(SQLInput stream, String typeName) throws SQLException {
    sql_type = typeName;
    code = stream.readString();
    name = stream.readString();
    sex = stream.readBigDecimal();
    salary = stream.readBigDecimal();
  }
 
  public void writeSQL(SQLOutput stream) throws SQLException {
    stream.writeString(code);
    stream.writeString(name);
    stream.writeBigDecimal(sex);
    stream.writeBigDecimal(salary);
  }
}
 
2.         装载Java代码及类到Oracle8i数据库中
 
在编写了Java源代码之后,就可以将Java对象装载到Oracle8i数据库中了。下面是完成这项任务的方法:
 


 
3.         发行Java,生成调用说明
 
在装载了Java类后,就可以发行该Java类,并生成调用其方法的相应对象方法了。下面是完成该项任务的方法:
 



 
4.         调用JSP
 
在创建了对象类型及对象方法之后,就可以调用这些对象方法了。例如:
 
使用JDeveloper开发JSP
本节以创建用于操纵ARTICLE表的JSP为例,说明使用JDeveloper 2.0开发JSP的方法。如下图所示:

这里只简单介绍使用JDeveloper开发JSP的过程和步骤,而关于如何使用JDeveloper请读者参见相关手册。
 
1.         准备工作
 
1)        选择“File—> New Workspace”,创建名称为jsp.jws的工作组。如下图所示:
 

 
2)        选择“File—>New Project”,此时会启动新项目创建向导,并显示如下对话框:
 

 
3)        选中“Create an <Empty Project>”,然后单击“Next”,此时会显示如下对话框:

 
4)        如上图所示,在“Project Name”框中键入“article”,项目路径框中键入“d:\jsp”,然后单击“Next”,此时会显示如下对话框:
 

 
5)        在上图的对话框中键入你所需要的信息,然后单击“Next”,此时会显示如下对话框:
 

 
6)        单击“Finish”,完成项目的创建过程,此时的图形界面如下:
 

 
2.         编写Java源代码
 
在完成了准备工作之后,我们就可以编写Java源代码了。步骤如下:
 
1)        选择“File—>New”,此时会弹出如下对话框:
 


 
2)        如上图所示,选中“Class”,然后单击“OK”,此时会弹出如下对话框:
 

 
3)        如上图所示,在“Class Name”框中键入“article”,选中“Style”中的“Public”,然后单击“OK”,此时会增加名称为“article.java”的节点。如下图所示:
 

 
4)        双击“article.java”节点,会显示编辑工作区。如下图所示:
 

 
5)        然后,在编辑工作区中编写如下的Java源代码(article.java):
 
/* 导入Java类 */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
 
/* 主类 */
public class article {
 
  public static String query_article(String code)
  throws SQLException {
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句*/
    String sql = "SELECT author_code,title FROM article " +
                  "WHERE article_code = ?";
    /* 声明String变量article_info,该变量将用于存储文章信息 */
    String article_info = new String();
 
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      ResultSet rset = pstmt.executeQuery();
      /* 循环获取并处理结果 */
      while(rset.next()) {
        article_info = "作者代码:  " + rset.getString(1) + "\n";
        article_info = article_info + "文章标题:  " +
                          rset.getString(2);
      }
      /* 关闭结果集 */
      rset.close();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
    return article_info;
  }
 
  public static void insert_article(String article_code,
      String author_code,String secrate_level,String pub_date)
  throws SQLException {
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "INSERT INTO article (article_code,author_code," +
                    "secrate_level,pub_date) VALUES (?,?,?,?)";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, article_code);
      pstmt.setString(2, author_code);
      pstmt.setString(3, secrate_level);
      pstmt.setString(4, pub_date);
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
 
  public static void delete_article (String code)
  throws SQLException {
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造SQL语句 */
    String sql = "DELETE FROM article  WHERE article_code = ?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, code);
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
 
  public static void update_article (String code,String secrate_level)
  throws SQLException {
    /* 建立到数据库的缺省连接 */
    Connection conn = new OracleDriver().defaultConnection();
    /* 构造动态SQL语句 */
    String sql = "UPDATE article SET secrate_level = ?" +
                  " WHERE article_code = ?";
    /* 使用try ... catch语句抓取并抛出例外 */
    try {
      /* 准备动态SQL语句 */
      PreparedStatement pstmt = conn.prepareStatement(sql);
      /* 设置动态SQL参数值 */
      pstmt.setString(1, secrate_level);
      pstmt.setString(2, code);
      pstmt.executeUpdate();
      /* 关闭动态SQL语句 */
      pstmt.close();
    } catch (SQLException e) {}
  }
}
 
3.         配置并发行JSP
 
步骤如下:
 
1)        选择“Project—>Deploy—>New Profile”,此时会弹出如下对话框:
 

 
2)        如上图所示,选中“Deploy Java Classes and Stored Procedure to Oracle8i”,然后单击“Next”,此时会弹出如下对话框:
 

 
3)        单击“Next”,此时会弹出如下对话框:
 

 
4)        单击“Next”,此时会显示如下对话框:
 

 
5)        单击“Next”,此时会显示如下对话框:
 

 
6)        清除“Default Database Package”框,然后单击“Next”,此时会显示如下对话框:
 

 
7)        单击“New”创建数据库连接,此时会弹出如下对话框:
 

 
该对话框用于配置数据库连接信息,按照你的数据库设置来配置相应参数。完成数据库连接的配置后,单击“Test Connection”测试配置是否正确。如果配置不正确,则修改配置参数。
 
8)        单击“OK”,此时会弹出如下对话框:
 

 
在该对话框中显示了相应的数据库连接信息。
 
9)        单击“Next”,此时会弹出如下对话框:
 

 
10)     单击“Finish”,此时会弹出如下对话框:
 

 
11)     单击“No”退出配置,然后在主窗口中选中配置文件“Profile1.prf”,单击鼠标右键,此时会显示如下弹出菜单:
 

 
12)     从弹出菜单中选择“Properties”,此时会显示如下对话框:
 

 
13)     选择“Methods”页,此时的对话框如下所示:
 

 
14)     如上图所示,选中Publish下的所有单选框,然后单击“Done”,此时会显示如下对话框:
 

 
15)     单击“Yes”,会开始配置和发行JSP,并最终显示如下界面:
 

 
16)     单击“Done”,此时会显示如下信息框:
 

 
17)     单击“OK”,这样我们就完成了配置和发行JSP的全部过程了。然后,我们就可以调用JSP完成相应任务了。
 
4.         调用JSP
 
在创建了基于Java的函数和过程之后,就可以调用这些函数和过程了。方法如下:
 





posted @ 2006-08-16 15:18 黑咖啡 阅读(304) | 评论 (0)编辑 收藏
Oracle开发人员 JAVA存储过程
利用Java存储过程简化数据库操作

作者:Kuassi Mensah

利用Java存储过程沟通SQL、XML、Java、J2EE和Web服务。

存储过程(stored procedure)允许将运行于数据库层中的持久性逻辑与运行于中间层中的商务逻辑有效地分离开来。这种分离可以降低整个应用程序的复杂性,并提供其重用性、安全性、性能和可伸缩性。

但是,妨碍存储过程广泛采用的一个主要障碍是不同数据库厂商使用各种专有的、且依赖于数据库的实现语言。使用基于Java的存储过程可以解决这一问题。Oracle已经实现了ANSI标准,这些标准规定了从SQL中将静态Java方法作为过程或函数进行调用的能力。这种实现被简单地称作"Java存储过程"。

在本文中,你将了解基于Java的存储过程如何帮助简化商务逻辑、提高其性能,并扩展数据库的功能。本文将介绍Oracle如何在数据库内启用基于Java的存储过程。还会介绍Java存储过程如何访问数据,以及如何创建基本Java存储过程。

选择PL/SQL还是Java

在考虑Oracle存储过程时,你可能会想到PL/SQL。不过,从Oracle8i开始,Oracle已经在数据库中支持Java,从而为存储过程提供了不同于PL/SQL的开放式和可移植的方法。我可以听到"$64 000问题":"我如何在PL/SQL和Java之间做出选择?我是否应当忘记已经学习的所有PL/SQL相关知识,而变为一个Java天地的新手?"

两种语言都适用于数据库编程,都有自己的优点和弱点。在决定选择哪一种语言时,可以参考下面根据经验得出的通用规则:


对于要求与SQL进行无缝集成的数据库中心来说则逻辑使用PL/SQL,从而完成对数据库对象、类型和特性的访问。


出于与数据库的无关性考虑时,可以选择Java作为开放式的语言来取代PL/SQL,同时也为了集成和沟通SQL、XML、J2EE和Web服务等各个领域。
OralceJVM使得Java可以运行在数据库中

从Oracle8i版本1(Oralce8.1.5)开始,Oracle便提供紧密集成的Java虚拟机(JVM),JVM支持Oralce的数据库会话期结构。任何数据库对话期都可以在第一Java代码调用时启动一个虚拟上专用的JVM,后续的用户可以使用这一已经存在的支持Java的会话期。事实上,所有会话共享同一JVM代码并保持"仅静态"的私有状态,而垃圾则收集在单个对话期空间内,从而为各个Java对话期提供了和SQL操作相同的对话期隔离和数据完整性能力。这里,不需要为了数据完整性而进行单独的Java支持的过程。这一基于对话期的结构提供了较小的内存占用率,并使OracleJVM具有与Oracle数据库一样的线性SMP可伸缩性。

创建Java存储过程

要将Java方法转换为Java存储过程需要几个步骤,包括:用loadjava实用程序将Java类加载到数据库中,利用调用规范(Call Spec)发布Java方法,将Java方法、参数类型和返回类型映射到其SQL的对应部分。下面部分说明如何完成这些步骤。

我将使用一个简单的Hello类,它有一个方法Hello.world(),返回字符串"Hello world":


public class Hello { public static String world () { return "Hello world"; } }
Loadjava 实用程序

Loadjava是加载Java源文件、Java类文件和Java资源文件的实用程序,它可以用来验证字节码,并将Java类和JAR文件布置到数据库中。它既可以通过命令行调用,也可以通过包含于DBMS_JAVA类中的loadjava()方法调用。为了加载我们的Hello.class示例,输入:


loadjava -user scott/tiger Hello.class

从Oracle9i版本2开始,loadjava允许通过为包含在被处理的类中的方法创建相应的Call Specs来自动将Java类发布为存储过程。Oracle为开发、测试、调试和布置Java存储过程提供了Oracle9i JDeveloper。

The Resolver Spec

基于JDK的JVM在列于CLASSPATH中的目录中查找类引用,并对其进行解析。因为Oracle数据库类存在于数据库模式中,所以OracleJVM利用数据库解析器(resolver)通过列于Resolver Spec中的模式查找并解析类引用。与CLASSPATH不同(CLASSPATH可以应用于所有的类),Resover Spec根据每类的情况进行应用。缺省解析器首先在加载类的模式中搜寻类,然后在公共同义词(public synonyms)中搜索。


 loadjava -resolve <myclass>
你可能需要指定不同的解析器,也可以在使用loadjava时强制进行解析,从而在布置时确定可能在以后运行时发生的任何问题。


loadjava -resolve -resolver "((* SCOTT) (foo/bar/* OTHERS) (* PUBLIC))"
Call Spec和存储过程调用

为了从SQL中调用Java方法(以及从PL/SQl和JDBC中调用),必须首先通过Call Spec发布公共静态方法,它为SQL定义方法采用的参数以及返回的SQL类型。

在我们的例子中,我们将利用SQL*Plus连接到数据库,并为Hello.world()定义一个顶级Call Spec:


SQL> connect scott/tiger SQL> create or replace function helloworld return VARCHAR2 as language java name 'Hello.world () return java.lang.String'; / Function created.
可以像下面这样调用Java存储过程:


SQL> variable myString varchar2[20]; SQL> call helloworld() into :myString; Call completed. SQL> print myString; MYSTRING --------------------- Hello world
Java存储过程可以通过其Call Spec从以下各项中进行调用:SQL DML语句(INSERT, UPDATE、DELETE、SELECT、CALL、EXPLAIN PLAN、LOCK TABLE和MERGE)、PL/SQL块、子程序、程序包以及数据库触发器。Call Spec的美妙之处在于存储过程实现可以从PL/SQL转换为Java,反之亦可,这一点对于请求者是透明的。

Call Spec从实现语言中(PL/SQL或Java)中抽象出调用界面,因而使之能够在原有应用程序和新的基于Java/J2EE的应用程序之间共享商务逻辑。但是,在从Java客户程序调用在数据库驻留的Java类时,你可能不希望通过PL/SQL包装器(wrapper)。在以后的版本中,Oracle计划提供一种机制,它可以使开发人员略过Call Spec。

高级数据访问控制

Java存储过程可用于控制和限制对Oracle数据的访问,其方法是只允许用户通过存储过程管理数据,而存储过程在其调用者的权限内执行,而不能对表本身进行访问。例如,你可以在特定时间内禁止更新数据,或者使管理者只具有查询工资数据的权利,而不能进行更新,或者记录所有的访问并通知某一安全机构。

原有应用程序与J2EE应用程序之间的数据逻辑共享

因为原有应用程序与J2EE应用程序都通过Call Spec调用存储过程,所以J2EE和非J2EE应用程序可以共享相同的数据逻辑。由于有了Call Spec,所以不用考虑所用的是何种实现语言(无论是PL/SQL还是Java),该数据逻辑都可以共享。

为BMP实体Bean自动生成主关键字

在对EJB实体bean应用BMP时,一个bean实例可以由自动生成的与新插入的数据相关联的主关键字惟一确定,它是ejbCreate()的返回值。可以利用一个插入相应数据的存储过程在一个数据库操作中检索ejbCeater()中的该值,并检索或计算主关键字。作为另一种方法,也可以利用JDBC3.0的RETURN_GENERATED_KEYS特性,以一个SQL语句插入该数据并检索相应的关键字(或ROWID)。但是,存储过程方法在各个JDBC驱动器版本和数据库之间更具可移植性。

可以用以下三个步骤实现这一模式:
>
创建一个Java存储过程,在公共GenPk类中定义一个公共静态Java方法insertAccount()。此方法将插入数据、计算惟一的关键字(通过发出一个序列号),并返回计算出的关键字作为主关键字。


定义Call Spec


CREATE OR REPLACE PROCEDURE insertAccount(owner IN varchar, bal IN number, newid OUT number) AS LANGUAGE JAVA NAME 'GenPK.insertAccount( java.lang.String [])'; /


在ejbCreate()内调用存储过程


Public AccountPK ejbCreate(String ownerName, int balance) throws CreateException { try { CallableStatement call = conn.prepareCall{ "{call insertAccount(?, ?, ?)}"}; return new AccountPK(accountID); } }
为CMP实体Bean定制主关键字查找器

查找器方法(Finder methods)用于检索已存在的EJB实体bean实例。主关键字查找器使你能够检索惟一标识的EJB实例。对于CMP实体bean,EJB容器根据声明描述,自动生成主关键字查找器findByPrimaryKey()方法。但是,在某些情况下,可能需要更多的控制,例如可能需要专门的查找器,如findByStoredProcKey()。在这些情况下,你可以结合使用Java存储过程和对象关系框架(如Oracle9i应用服务器[Oracle9iAS] TopLink)来实现定制的主关键字查找器方法。在将EJB查找器定义为REDIRECT或NAMED查找器后,TopLink将生成一个SQL查询用于检索bean实例。

数据驱动的EJB调用

在数据驱动体系结构中,商务逻辑调用可以作为数据库操作(如插入、更新或删除)的结果来触发。实现该数据逻辑的Java存储过程可以被声明为数据库触发器,用以调用运行于中间层J2EE应用服务器的EJB。EJB的调用既可以采用J2EE1.3兼容的服务器通过Interoperable Inter-ORB Protocol(IIOP)标准远程方法调用(remote method invocation,RMI)实现,也可以通过销售商特定的传输协议(如Oracle9iAS/Oc4J的ORMI,或者通过BEA WebLogic的T3)用RMI来实现。每个应用服务器提供商在提供基于IIOP的RMI,以提供互操作性的同时,都有其自己优化的协议。Oracle9iAS同时支持基于IIOP的RMI调用和基于ORMI协议的RMI调用。

数据驱动的消息传送

Oracle9i数据库嵌入了Advanced Queuing(AQ,高级排队),它是一种集成的、稳定、可靠、安全、可扩展和事务处理式的消息排队框架。Oracle通过标准的Java消息传送系统(Java Messaging System,JMS)API为Java开发人员提供AQ功能。Java存储过程可以通过JMS接口调用AQ操作,从而能够实现快速、在会话期内、可扩展的、数据驱动的消息传送。

Java存储过程可以利用JMS调用AQ操作。可以用以下4个步骤实现这一模式:


创建并启动JMS Queue(为此,可以将以下一些操作嵌入SQL脚本内):


execute dbms_aqadm.create_queue_table(queue_table => 'queue1', queue_payload_type => 'SYS.AQ$_JMS_TEXT_MESSAGE', comment => 'a test queue', multiple_consumers => false, compatible => '8.1.0'); execute dbms_aqadm.create_queue( queue_name => 'queue1', queue_table => 'queue1' ); execute dbms_aqadm.start_queue(queue_name => 'queue1');


创建Java存储过程(代码摘录如下):


public static void runTest(String msgBody) { try { // get database connection ora_drv = new OracleDriver(); db_conn = ora_drv.defaultConnection(); // setup sender (cf online code sample) .. // create message s_msg = s_session.createTextMessage(msgBody); // send message sender.send(s_msg); s_session.commit(); // receive message r_msg = (TextMessage) receiver.receive(); r_session.commit(); // output message text String body = r_msg.getText(); System.out.println("message was '"+body+"'"); ..} }


创建Call Spec:


create or replace procedure jmsproc (t1 IN VARCHAR) as language java name 'jmsSample.main (java.lang.String[])'; /


调用存储过程:


call jmsproc('hello');
数据库辅助的Web发布(缓冲失效)

各应用程序结构必须面对的一个共同问题是如果可靠地将数据库信息进行缓存,以提高整个系统的性能。JCACHE是一种即将公布的标准规范(JSR 107),它可以解决这一问题。它说明了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等。它可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)。

为了跟踪原始数据的所有变化,并刷新已缓存的数据,Java存储过程会作为一个触发器被附加在一个表上。这个表的任何变化都会自动调用该存储过程,后者再调出一个已定义的JSP使JCACHE对象失效,该对象将其状态映射到该数据库表。在失效时,紧跟其后的查询将强制缓存器根据数据库的数据进行更新。 下面的步骤
阅读关于Java存储过程的更多信息
本文摘自白皮书"释放Java存储过程的能量(Unleash the Power of Java Stored Procedures)",可以在以下位置找到该白皮书:
otn.oracle.com/tech/java/java_db/pdf/
OW_30820_JAVA_STORED_PROC_paper.PDF

Oracle9i数据库第2版中的新PL/SQL特性
otn.oracle.com/tech/pl_sql/pdf/
Paper_30720_Doc.pdf

Resolver Spec
otn.oracle.com/docs/products/oracle9i/
doc_library/release2/java.920/a96659.pdf

OracleJVM and Java 2 Security
otn.oracle.com/docs/products/oracle9i/
doc_library/release2/java.920/a96656.pdf

下载代码
练习本文中的代码示例:
otn.oracle.com/sample_code/tech/
java/jsp/Oracle9iJSPSamples.html

了解作为Web服务的存储过程
otn.oracle.com/tech/webservices
 


扩展数据库的功能

在数据库中直接运行Java代码的一个妙处就在于要实现新的功能,只需要简单地加载代码或库,并利用Call Spec制作可用于SQL、PL/SQL、Java、J2EE和非Java API的进入点(公共静态方法)。Oracle9i数据库用户可以很容易地扩展数据库

功能。Oracle自己利用这种能力来获得新的应用程序和工具包,如XML Developer Kits(XDKs)。

沟通SQL、PL/SQL、Java、J2EE、.NET和XML

Oracle XDK是用Java编写的,并将其公共方法可用作Java存储过程,从而扩展了数据库的XML可编程能力。SQL、PL/SQL、Java、J2EE和非Java(.NET)商务逻辑都能够访问XML分析器、XSLT处理器、XPath引擎和XML SQL Utility(XSU)。

XML分析器可以通过xmlparser和xmldom包进行访问。XSU是一种Java实用程序,它可以由SQL查询结果或JDBC ResultSet生成XML文档,并将XML文档中的数据写入数据库表或视图中。利用XSU,XML输出可以输出为文本、Dom树或DTS。通过dbms_xmlquery和dbms_xmlsave包,XSU即可用于PL/SQL。

结论

Oracle数据库与Java VM的集成可以创建可移植、功能强大和与数据库无关的数据逻辑和持续性逻辑(persistence logic)。运行于中间层的商务逻辑和运行于数据库层的数据逻辑之间的分离提高了应用程序的可扩展性、灵活性和可维护性。

posted @ 2006-08-16 11:55 黑咖啡 阅读(252) | 评论 (0)编辑 收藏

什么是存储过程呢?

定义:

      将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来, 那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。

讲到这里,可能有人要问:这么说存储过程就是一堆SQL语句而已啊?

Microsoft公司为什么还要添加这个技术呢?

那么存储过程与一般的SQL语句有什么区别呢?

存储过程的优点:

1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次  就编译一次,所以使用存储过程可提高数据库执行速度。

2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。

3.存储过程可以重复使用,可减少数据库开发人员的工作量

4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权

存储过程的种类:

     1.系统存储过程:以sp_开头,用来进行系统的各项设定.取得信息.相关管理工作,

                               如 sp_help就是取得指定对象的相关信息
  2.扩展存储过程   以XP_开头,用来调用操作系统提供的功能

                              exec master..xp_cmdshell 'ping 10.8.16.1'

   3.用户自定义的存储过程,这是我们所指的存储过程

   常用格式

   Create procedure procedue_name

   [@parameter data_type][output]

   [with]{recompile|encryption}

   as

        sql_statement

解释: 

output:表示此参数是可传回的

with {recompile|encryption}

recompile:表示每次执行此存储过程时都重新编译一次

encryption:所创建的存储过程的内容会被加密

如:

   表book的内容如下

   编号    书名                           价格

   001      C语言入门                   $30

   002      PowerBuilder报表开发  $52

 实例1:查询表Book的内容的存储过程

   create proc query_book

      as

      select * from book

   go

   exec query_book

 实例2:加入一笔记录到表book,并查询此表中所有书籍的总金额

   Create proc insert_book

   @param1 char(10),@param2 varchar(20),@param3 money,@param4 money output

   with encryption  ---------加密

   as

   insert book(编号,书名,价格) Values(@param1,@param2,@param3)
   select @param4=sum(价格) from book
  go

  执行例子:
  declare @total_price money
  exec insert_book '003','Delphi 控件开发指南',$100,@total_price
  print '总金额为'+convert(varchar,@total_price)
  go
存储过程的3种传回值:
   1.以Return传回整数
   2.以output格式传回参数
   3.Recordset
传回值的区别:
       output和return都可在批次程式中用变量接收,而recordset则传回到执行批次的客户端中 

实例3:设有两个表为Product,Order,其表内容如下:
      Product
           产品编号       产品名称    客户订数    
            001             钢笔         30        
            002             毛笔         50        
            003             铅笔         100       
      Order 
           产品编号         客户名     客户订金
            001              南山区      $30
            002              罗湖区      $50
            003              宝安区      $4
请实现按编号为连接条件,将两个表连接成一个临时表,该表只含编号.产品名.客户名.订金.总金额,
总金额=订金*订数,临时表放在存储过程中

代码如下:
     Create proc temp_sale
     as
       select a.产品编号,a.产品名称,b.客户名,b.客户订金,a.客户订数* b.客户订金 as总金额
       into #temptable from Product a inner join Order b on a.产品编号=b.产品编号
    if  @@error=0
       print 'Good'
    else
       print 'Fail'
     go

posted @ 2006-08-16 11:53 黑咖啡 阅读(220) | 评论 (0)编辑 收藏
1、线程 新建线程运行机制。

2、File IO  文件建立,读写,删除。 
posted @ 2006-07-31 17:44 黑咖啡 阅读(235) | 评论 (0)编辑 收藏
     摘要: 1 /**/ /*   2  * Made In GamVan.com   3  * Created on 2005年3月18日, 下午8:37   4 ...  阅读全文
posted @ 2006-07-27 13:03 黑咖啡 阅读(316) | 评论 (0)编辑 收藏
文件的建立/检查与删除

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>文件的建立、检查与删除</title>
</head>
<body>
<%
String path=request.getRealPath("");
//out.println(path);
File f=new File(path,"File.txt");
//out.println(f);
//out.println(f.exists());

if(f.exists()){//检查File.txt是否存在
f.delete();//删除File.txt文件
out.println(path + "\\File.txt 存在,已删除。");
}else{
f.createNewFile();//在当前目录下建立一个名为File.txt的文件
out.println(path + "\\File.txt 不存在,已建立。");//输出目前所在的目录路径
}
%>

  目录的建立/检查与删除

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>目录的建立/检查与删除</title>
</head>
<body>
<%
String path=request.getRealPath("");
path=path + "\\Sub";//将要建立的目录路径
File d=new File(path);//建立代表Sub目录的File对象,并得到它的一个引用
if(d.exists()){//检查Sub目录是否存在
d.delete();
out.println("Sub目录存在,已删除");
}else{
d.mkdir();//建立Sub目录
out.println("Sub目录不存在,已建立");
}
%>
</body>
</html>

  如何在JSP中处理虚拟目录

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>JSP中如何处理虚拟目录</title>
</head>
<body>
取得虚拟目录对应的磁盘路径<br>
Web站点主目录的位置为<font color=#ff0000><%=request.getRealPath("/")%></font><br>
JSP网页所在的目录位置<font color=#ff0000><%=request.getRealPath("./")%></font><br>
JSP网页所在目录上一层目录的位置<font color=#ff0000><%=request.getRealPath("../")%></font><br>
</body>
</html>

文件属性的取得

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.Date,java.io.*"%>
<html>
<head>
<title>文件属性的取得</title>
</head>
<body>
<%
String path=request.getRealPath("/");
File f=new File(path,"ReadData.txt");
if(f.exists()){
%>
<%=f.getName()%>的属性如下:<br><br>
文件长度为:<%=f.length()%>
<%=f.isFile()?"是文件":"不是文件"%><br>
<%=f.isDirectory()?"是目录":"不是目录"%><br>
<%=f.canRead()?"可读取":"不可读取"%><br>
<%=f.canWrite()?"可写入":"不可写入"%><br>
<%=f.isHidden()?"是隐藏文件":"不是隐藏文件"%><br>
文件的最后修改日期为:<%=new Date(f.lastModified())%><br>
<%
}else{
f.createNewFile();//在当前目录下建立一个名为ReaData.txt的文件
%>
<%=f.getName()%>的属性如下:<br><br>
文件长度为:<%=f.length()%>
<%=f.isFile()?"是文件":"不是文件"%><br>
<%=f.isDirectory()?"是目录":"不是目录"%><br>
<%=f.canRead()?"可读取":"不可读取"%><br>
<%=f.canWrite()?"可写入":"不可写入"%><br>
<%=f.isHidden()?"是隐藏文件":"不是隐藏文件"%><br>
文件的最后修改日期为:<%=new Date(f.lastModified())%><br>
<%
}
%>
</body>
</html>

  取出目录中文件的方法

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>取出目录中文件的方法--列出目录中的文件</title>
</head>
<body>
<%
String path=request.getRealPath("/");
File d=new File(path);//建立当前目录中文件的File对象
File list[]=d.listFiles();//取得代表目录中所有文件的File对象数组
out.println("<font color=#ff0000>" + path + "目录下的文件:</font><br>");
for(int i=0;i<list.length;i++){
if(list<I>.isFile()){
out.println(list<I>.getName() + "<br>");
}
}
out.println("<br><font color=#ff0000>" + path + "目录下的目录:</font><br>");
for(int i=0;i<list.length;i++){
if(list<I>.isDirectory()){
out.println(list<I>.getName() + "<br>");
}
}
%>
</body>
</html>

判断是否为空白文件

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>判断是否为空白文件</title>
</head>
<body>
<%
String path=request.getRealPath("/");
out.println(path);
FileReader fr=new FileReader(path + "\\AtEnd.txt");//建立FileReader对象,并实例化为fr
//对FileReader类生成的对象使用read()方法,可以从字符流中读取下一个字符。
if(fr.read()==-1)//判断是否已读到文件的结尾
{
out.print("AtEnd.txt文件中没有数据<br>");
}else{
out.println("AtEnd.txt文件中有数据");
}
fr.close();
%>
</body>
</html>
    <B>读取所有的文件数据</B>
<ccid_nobr>
<table width="400" border="1" cellspacing="0" cellpadding="2"
bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">
<tr>
<td bgcolor="e6e6e6" class="code" style="font-size:9pt">
<pre><ccid_code> <%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*,java.lang.*"%>
<html>
<head>
<title>读取所有的文件数据</title>
</head>
<body>
<%
String path=request.getRealPath(".");
FileReader fr=new FileReader(path + "\\ReadData.txt");
//关键在于读取过程中,要判断所读取的字符是否已经到了文件的末尾,
并且这个字符是不是文件中的断行符,即判断该字符值是否为13。
int c=fr.read();//从文件中读取一个字符
//判断是否已读到文件结尾
while(c!=-1){
out.print((char)c);//输出读到的数据
c=fr.read();//从文件中继续读取数据
if(c==13){//判断是否为断行字符
out.print("<br>");//输出分行标签
fr.skip(1);//略过一个字符
//c=fr.read();//读取一个字符
}
}
fr.close();
%>
</body>
</html>

  一行一行读取数据

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>文件读取</title>
</head>
<body>
<%
String path=request.getRealPath("");//取得当前目录的路径
FileReader fr=new FileReader(path + "\\file\\inc\\t.txt");//建立FileReader对象,并实例化为fr
BufferedReader br=new BufferedReader(fr);//建立BufferedReader对象,并实例化为br
String Line=br.readLine();//从文件读取一行字符串
//判断读取到的字符串是否不为空
while(Line!=null){
out.println(Line + "<br>");//输出从文件中读取的数据
Line=br.readLine();//从文件中继续读取一行数据
}
br.close();//关闭BufferedReader对象
fr.close();//关闭文件
%>
</body>
</html>
略过文件中的字符不读取

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>略过字节不读取</title>
</head>
<body>
<%
String path=request.getRealPath(".");
FileReader fr=new FileReader(path + "\\ReadData.txt");
fr.skip(2);//跳过2个字节
int c=fr.read();//读取一个字节
while(c!=-1){
out.print((char)c);
c=fr.read();
}
fr.close();
%>
</body>
</html>

  将数据写入文件

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>将数据写入文件</title>
</head>
<body>
<%
String path=request.getRealPath(".");
FileWriter fw=new FileWriter(path + "\\WriteData.txt");//建立FileWriter对象,并实例化fw
//将字符串写入文件
fw.write("大家好!");
fw.write("本书是《JSP编程技巧》");
fw.write("请多多指教!");
fw.write("email:stride@sina.com");
fw.close();

FileReader fr=new FileReader(path + "\\WriteData.txt");
BufferedReader br=new BufferedReader(fr);//建立BufferedReader对象,并实例化为br
String Line=br.readLine();
//读取一行数据
out.println(Line + "<br>");
br.close();//关闭BufferedReader对象
fr.close();
%>
</body>
</html>

  将写入文件的数据分行

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>将写入文件的数据分行</title>
</head>
<body>
<%
String path=request.getRealPath(".");
FileWriter fw=new FileWriter(path + "\\WriteData.txt");
BufferedWriter bw=new BufferedWriter(fw);
bw.write("大家好!");
bw.write("本书是《JSP编程技巧》。");
bw.newLine();//断行
bw.write("请多多指教!");
bw.newLine();//断行
bw.write("email: stride@sina.com");
bw.flush();//将数据更新至文件
fw.close();//关闭文件流
out.println("写入文件内容为:<br>");
FileReader fr=new FileReader(path + "\\WriteData.txt");
BufferedReader br=new BufferedReader(fr);
String Line=br.readLine();//读取一行数据
while(Line!=null){
out.println(Line + "<br>");
Line=br.readLine();
}
fr.close();
%>
</body>
</html>

  如何将数据追加写入到文件

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*"%>
<html>
<head>
<title>将写入文件的数据分行</title>
</head>
<body>
<%
String path=request.getRealPath(".");
RandomAccessFile rf=new RandomAccessFile(path + "\\WriteData.txt","rw");
//定义一个类RandomAccessFile的对象,并实例化
rf.seek(rf.length());//将指针移动到文件末尾
rf.writeBytes("\nAppend a line to the file!");
rf.close();//关闭文件流
out.println("写入文件内容为:<br>");
FileReader fr=new FileReader(path + "\\WriteData.txt");
BufferedReader br=new BufferedReader(fr);//读取文件的BufferedRead对象
String Line=br.readLine();
while(Line!=null){
out.println(Line + "<br>");
Line=br.readLine();
}
fr.close();//关闭文件
%>
</body>
</html></I></I></I></I>

posted @ 2006-07-27 13:00 黑咖啡 阅读(368) | 评论 (0)编辑 收藏
取得虚拟目录对应的磁盘路径:

Web站点主目录的位置为<%=request.getRealPath("/")%
JSP网页所在的目录位置<%=request.getRealPath("./")%>
JSP网页所在目录上一层目录的位置<%=request.getRealPath("../")%>
posted @ 2006-07-27 12:58 黑咖啡 阅读(418) | 评论 (0)编辑 收藏
(Bloger注)自我感觉一个初学者,在经历了一段时间的编程实践以后,应该花时间整体了解一下我们开发中所用到的技术和相关领域的发展情况。开阔视野是进步的一个必不可少的功课。

J2EE学习者越来越多,J2EE本身技术不断在发展,涌现出各种概念,本文章试图从一种容易理解的角度对这些概念向初学者进行解释,以便掌握学习J2EE学习方向。

  首先我们需要知道Java和J2EE是两个不同概念,Java不只是指一种语言,已经代表与微软不同的另外一个巨大阵营,所以Java有时是指一种软件系统的流派,当然目前主要是.NET和Java两大主流体系。

  J2EE可以说指Java在数据库信息系统上实现,数据库信息系统从早期的dBase、到Delphi/VB等C/S结构,发展到B/S(Browser浏览器/Server服务器)结构,而J2EE主要是指B/S结构的实现。

  J2EE又是一种框架和标准,框架类似API、库的概念,但是要超出它们。如果需要详细了解框架,可先从设计模式开始学习。

  J2EE是一个虚的大的概念,J2EE标准主要有三种子技术标准:WEB技术、EJB技术和JMS,谈到J2EE应该说最终要落实到这三个子概念上。

  这三种技术的每个技术在应用时都涉及两个部分:容器部分和应用部分,Web容器也是指Jsp/Servlet容器,你如果要开发一个Web应用,无论是编译或运行,都必须要有Jsp/Servlet库或API支持(除了JDK/J2SE以外)。

  Web技术中除了Jsp/Servlet技术外,还需要JavaBeans或Java Class实现一些功能或者包装携带数据,所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。

  谈到JavaBeans技术,就涉及到组件构件技术(component),这是Java的核心基础部分,很多软件设计概念(设计模式)都是通过JavaBeans实现的。

  JavaBeans不属于J2EE概念范畴中,如果一个JavaBeans对象被Web技术(也就是Jsp/Servlet)调用,那么JavaBeans就运行在J2EE的Web容器中;如果它被EJB调用,它就运行在EJB容器中。

  EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务、安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系统。

  至此,JavaBeans组件发展到EJB后,并不是说以前的那种JavaBeans形式就消失了,这就自然形成了两种JavaBeans技术:EJB和POJO,POJO完全不同于EJB概念,指的是普通JavaBeans,而且这个JavaBeans不依附某种框架,或者干脆可以说:这个JavaBeans是你为这个应用程序单独开发创建的。

  J2EE应用系统开发工具有很多:如JBuilder、Eclipse等,这些IDE首先是Java开发工具,也就是说,它们首要基本功能是可以开发出JavaBeans或Java class,但是如果要开发出J2EE系统,就要落实到要么是Web技术或EJB技术,那么就有可能要一些专门模块功能(如eclipse需要lomboz插件),最重要的是,因为J2EE系统区分为容器和应用两个部分,所以,在任何开发工具中开发J2EE都需要指定J2EE容器。

  J2EE容器分为WEB容器和EJB容器,Tomcat/Resin是Web容器;JBoss是EJB容器+Web容器等,其中Web容器直接使用Tomcat实现的。所以你开发的Web应用程序可以在上面两种容器运行,而你开发的Web+EJB应用则只可以在JBoss服务器上运行,商业产品Websphere/Weblogic等和JBoss属于同一种性质。

  J2EE容器也称为J2EE服务器,大部分时它们概念是一致的。

  如果你的J2EE应用系统的数据库连接是通过JNDI获得,也就是说是从容器中获得,那么你的J2EE应用系统基本与数据库无关,如果你在你的J2EE应用系统耦合了数据库JDBC驱动的配置,那么你的J2EE应用系统就有数据库概念色彩,作为一个成熟需要推广的J2EE应用系统,不推荐和具体数据库耦合,当然这其中如何保证J2EE应用系统运行性能又是体现你的设计水平了。

  衡量J2EE应用系统设计开发水平高低的标准就是:解耦性;你的应用系统各个功能是否能够彻底脱离?是否不相互依赖,也只有这样,才能体现可维护性、可拓展性的软件设计目标。

  为了达到这个目的,诞生各种框架概念,J2EE框架标准将一个系统划分为WEB和EJB主要部分,当然我们有时不是以这个具体技术区分,而是从设计上抽象为表现层、服务层和持久层,这三个层次从一个高度将J2EE分离开来,实现解耦目的。

  因此,我们实际编程中,也要将自己的功能向这三个层次上靠,做到大方向清楚,泾渭分明,但是没有技术上约束限制要做到这点是很不容易的,因此我们还是必须借助J2EE具体技术来实现,这时,你可以使用EJB规范实现服务层和持久层,Web技术实现表现层;

  EJB为什么能将服务层从Jsp/Servlet手中分离出来,因为它对JavaBeans编码有强制的约束,现在有一种对JavaBeans弱约束,使用Ioc模式实现的(当然EJB 3.0也采取这种方式),在Ioc模式诞生前,一般都是通过工厂模式来对JavaBeans约束,形成一个服务层,这也是是Jive这样开源论坛设计原理之一。

  由此,将服务层从表现层中分离出来目前有两种可选架构选择:管理普通JavaBeans(POJO)框架(如Spring、JdonFramework)以及管理EJB的EJB框架,因为EJB不只是框架,还是标准,而标准可以扩展发展,所以,这两种区别将来是可能模糊,被纳入同一个标准了。 但是,个人认为:标准制定是为某个目的服务的,总要牺牲一些换取另外一些,所以,这两种架构会长时间并存。

  这两种架构分歧也曾经诞生一个新名词:完全POJO的系统也称为轻量级系统(lightweight),其实这个名词本身就没有一个严格定义,更多是一个吸引人的招牌,轻量是指容易学习容易使用吗?按照这个定义,其实轻量Spring等系统并不容易学习;而且EJB 3.0(依然叫EJB)以后的系统是否可称为轻量级了呢?

  前面谈了服务层框架,使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来,而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离,这部分JavaBeans主要负责显示相关,一般是通过标签库(taglib)实现,不同框架有不同自己的标签库,Struts是应用比较广泛的一种表现层框架。

  这样,表现层和服务层的分离是通过两种框架达到目的,剩余的就是持久层框架了,通过持久层的框架将数据库存储从服务层中分离出来是其目的,持久层框架有两种方向:直接自己编写JDBC等SQL语句(如iBatis);使用O/R Mapping技术实现的Hibernate和JDO技术;当然还有EJB中的实体Bean技术。

  持久层框架目前呈现百花齐放,各有优缺点的现状,所以正如表现层框架一样,目前没有一个框架被指定为标准框架,当然,表现层框架现在又出来了一个JSF,它代表的页面组件概念是一个新的发展方向,但是复杂的实现让人有些忘而却步。

  在所有这些J2EE技术中,虽然SUN公司发挥了很大的作用,不过总体来说:网络上有这样一个评价:SUN的理论天下无敌;SUN的产品用起来撞墙;对于初学者,特别是那些试图通过或已经通过SUN认证的初学者,赶快摆脱SUN的阴影,立即开溜,使用开源领域的产品来实现自己的应用系统。

  最后,你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现,基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。

  还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解,那么域建模提供了一种比较切实可行的正确理解业务需求的方法,相关详细知识可从UML角度结合理解。

  当然,如果你想设计自己的行业框架,那么第一步从设计模式开始吧,因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法,当你学会了系统基本单元JavaBean或类之间解耦时,那么系统模块之间的解耦你就可能掌握,进而你就可以实现行业框架的提炼了,这又是另外一个发展方向了。

  以上理念可以总结为一句话:
J2EE开发三件宝: Domain Model(域建模)、patterns(模式)和framework(框架)。

  推荐一套高质量的J2EE开源系统: JPestore
  
  如果初学者没有理解,欢迎继续讨论,大胆提出你心中的疑问。

posted @ 2006-07-20 17:23 黑咖啡 阅读(207) | 评论 (0)编辑 收藏
     摘要: 你所需要做的就是:按照你的需求配置Tomcat,只要你正确配置,Tomcat一般都能适合你的要求。下面是一系列关于Tomcat的配置技巧,这些技巧源自于我的书:《Tomcat权威指南》,希望对你有所帮助。 Jason Brittain   1. 配置系统管理(Admin Web Application)  大多数商业化的J2EE服务器都提供一个功能强大的管理界面,且大都采用易于理解的Web应用界面...  阅读全文
posted @ 2006-07-20 16:09 黑咖啡 阅读(266) | 评论 (0)编辑 收藏

连续几天安装配置和连接Mysql数据库,今天终于成功了,回想这几天,
真的是甜酸苦辣都有,单mysql就重装了不下10次,而在eclipse上编写的连接数据库的程序总是报错.我都已经down了oracal准备放弃mysql了,不过...
就象电视剧演的那样,转机总是在这个时候出现,先是看到了saulzy关于mysql4.1.11版本的安装介绍,接着又找到了一款不错的mysql 界面插件,
最后在网友的帮助下把mysql的JDBC驱动配好并连通了.一连5天,日子真不好过阿,不过这个过程中,
我也觉得自己学到不少东西,呵呵,反正都撑过来了,就要继续往前走.现在,就这几天弄的总结一下,希望对同是正在学习JAVA技术的同道中人能有帮助.

我曾写过一篇叫<<配置Eclpise+tomcat并实现JSP的编写与部署>>,现在写的这些算是它的后续.

一.    软件下载
Mysql
下载版本:4.1.11
http://dev.mysql.com/downloads/mysql/4.1.html

JDBC驱动
下载版本:3.1.8
http://dev.mysql.com/downloads/connector/j/3.1.html

Mysql界面插件:mysql-front
下载版本镜像:HongKong(我下回来安装就是中文版了)
http://www.mysqlfront.de/download.html

二.    软件安装
1.安装mysql
    就如我上面所说的,我是参考了saulzy的文章,现在给出saulzy这篇文章的连接:
http://blog.csdn.net/saulzy/archive/2005/04/23/359648.aspx
里面图文并茂,说得非常清楚
(在这里再一次感谢saulzy)

2.JDBC驱动:mysql-connector-java-3.1.8
这只是一个压缩包,并不需要安装,只要将其解压,我么使用的是文件夹mysql-connector-java-3.1.8里的文件:mysql-connector-java-3.1.8-bin.jar.

3. Mysql界面插件:mysql-front
这是一个安装程序,按照提示安装就可以了.

三.    环境配置
 首先,我要说明的是我现在
tomcat的安装路径是: D:\Program Files\Java\Tomcat
  JDK的安装路径是:D:\Program Files\Java\j2sdk

在这里,需要配置环境变量的是JDBC驱动.在配置前先要把刚才说到的mysql-connector-java-3.1.8-bin.jar本地硬盘某处(我放的地方:D:\Program Files\Java\mysqlforjdbc),然后根据你放的地方,配置classpath,我的配置是这样的:
.;D:\Program files\Java\j2sdk\lib\tools.jar;D:\Program Files\Java\j2sdk\lib\mysql-connector-java-3.1.8-bin-g.jar;D:\Program Files\Java\mysqlforjdbc\mysql-connector-java-3.1.8-bin.jar
配置这个的目的是让你的java应用程序找到连接mysql的驱动.

配置完环境变量后还有很重要一步就是为JSP连接数据库配置驱动,这个其实很简单,就是把mysql-connector-java-3.1.8-bin.jar拷到某些文件夹里就行了,我在网上看了很多资料问了很多人,各种说法都有,我综合了一下,为了保险,我都全做了,呵呵,反正就是拷一个400K的文件而已,现列出要把mysql-connector-java-3.1.8-bin.jar拷进去的文件夹,如下:
D:\Program Files\Java\Tomcat\common\lib
D:\Program Files\Java\Tomcat\shared\lib

四.    数据库的使用

Mysql安装完毕以后,还有一些要注意的地方,这里saulzy也写了篇文章,大家看看就清楚了,连接如下:http://blog.csdn.net/saulzy/archive/2005/04/23/359811.aspx
就象在saulzy的文章力提到的,mysql安装好后最重要一样就是要看数据库有没有作为系统服务启动了,所以在大家进行数据库操作前,应要看看,在操作系统的
开始->运行->输入services.msc,确定你在安装时你设置的关于mysql的那个服务已经启动,这样你在操作数据库时不会报连接不上的错误.
上面提到了一个较方便的mysql界面插件,但是这个界面是我在已经开始使用mysql后才找到的,刚开始我是在dos下用命令行进行操作的.虽然那个界面也可以进行建库啊,设定权限等操作,但是,我觉得懂得在使用命令行也是一个很重要的技能,所以我先从命令行开始说,怎样简单使用mysql.到后面会谈及mysql-front的使用.

现在我想在mysql里建一个数据库shujuku,以及在数据库里建一个表biao.具体的命令如下(假设mysql我是刚安装好的)

 

 


1.    进入dos状态(记住命令行的要运行在mysql的安装目录下的bin目录的)如下图一:
 
2.    连接mysql
输入:mysql ?h localhost ?u root ?p
出现要求输入密码的界面(如图二)
 

 


输入在安装时已设好的密码,就近入了mysql的命令编辑界面了,如图三:
 
3.    使用mysql的基本命令(在mysql命令行编辑每输入完命令后最后一定要有分号,不然会报错)
显示数据库:show databases;
使用数据库:use 数据库名;
例子如图四:
 


4.建库
命令:create database shujuku;
5.为数据库设置权限(用户和密码)
命令:grant all privileges on shujuku.* to test@localhost identified by  “123456”;
当你执行完这个命令以后,只要你再以用户名:test,密码:123456登录时你就只可以对shujuku这个数据库操作,这样避开使用root,对数据库的安全有很大帮助.如图五
 

6.建表
命令:create table biao(id int(8) primary key,name varchar(10));
如图六

剩下来的与标准sqsl命令基本上是一样的,具体操作略
值得一提的是,你在命令行上输入"?",就会有mysql命令的简单帮助,如图八:
 

呵呵,那样,我们还可以知道退出,就是"exit",呵呵!

五.    关于mysql-front的使用
我找了好几个mysql的界面工具,觉得最简洁方便还是mysql-front,可惜的是要收费,不过还好有试用期,呵呵,可以先感受感受一下,最重要一点是mysql-front有简体中文版的,英文不好的我用起来就舒服多了.下面简单说说使用吧.
首先,安装就不用说了,有向导,而且很简单.安装好后第一次运行时会跳出来一个要求添加对话的框,在这里你可以添加例如上面已经设定好的shujuku,过程如图九,十,十一:
 

 

 

当你在注册的复选框里填上你在上面mysql设定好的用户名和密码后,在选择数据库框里就有shujuku 的数据库了,选上,按确定.进入mysql-fron后,你就会看到下面的界面,这是你就可以进行操作了.如图十二
 
 
要说明的是,你还可以把root用户也加进去,这要你在mysql-fron的界面上选
设置->对话->新建,再按上面进行就可以,出了root你还可以加入更多的用户,方法还是一样的,设置不同的用户,是方便对不同数据库进行管理,呵呵,root是权限最高的,可不要随便让别人使用你的root用户,保正你数据库的安全.

六.    JSP连接mysql
现在就是尝试用jsp连接mysql了
我在eclipse里建了个test_mysql.jsp页面,代码如下:

<%@ page contentType="text/html; charset=gb2312" %>
<%@ page language="java" %>
<%@ page import="com.mysql.jdbc.Driver" %>
<%@ page import="java.sql.*" %>
<%
  //驱动程序名
  String driverName="com.mysql.jdbc.Driver";
  //数据库用户名
  String userName="cl41";
  //密码
  String userPasswd="123456";
  //数据库名
  String dbName="db";
  //表名
  String tableName="dbtest";
  //联结字符串
  String url="jdbc:mysql://localhost/"+dbName+"?user="+userName+"&password="+userPasswd;
  Class.forName("com.mysql.jdbc.Driver").newInstance();
  Connection connection=DriverManager.getConnection(url);
  Statement statement = connection.createStatement();
  String sql="SELECT * FROM "+tableName;
  ResultSet rs = statement.executeQuery(sql);
  //获得数据结果集合
   ResultSetMetaData rmeta = rs.getMetaData();
  //确定数据集的列数,亦字段数
   int numColumns=rmeta.getColumnCount();
  // 输出每一个数据值
 out.print("id");
 out.print("|");
 out.print("num");
 out.print("<br>");
while(rs.next()) {
out.print(rs.getString(1)+" ");  
out.print("|");
out.print(rs.getString(2));
out.print("<br>"); 
}  
out.print("<br>");
out.print("数据库操作成功,恭喜你");
rs.close();  
statement.close();  
connection.close();  
%>  

然后把test¬_mysql.jsp部署到tomcat处,如何部署可参考我的另一篇文章<<配置Eclpise+tomcat并实现JSP的编写与部署>>

在浏览器,你就可以看到如图十三的:
 

呵呵,文章终于写完了,原来写篇简洁清晰,图文并茂的文章真的不容易.还是那句话,希望对度这篇文章的你有帮助吧!Good luck!
由于这里不能贴图片,我把我文章里面的图片都打包了,在附件处!
(如有转载,请注明原作者是cl41,谢谢合作!)

 

posted @ 2006-07-20 14:55 黑咖啡 阅读(266) | 评论 (0)编辑 收藏
     摘要: 有很多朋友虽然安装好了 mysql 但却不知如何使用它。在这篇文章中我们就从连接 mysql 、 修改密码、增加用户等方面来学习一些 mysql 的常用命令。 ...  阅读全文
posted @ 2006-07-20 14:02 黑咖啡 阅读(413) | 评论 (0)编辑 收藏

Java中关于时间的操作主要是:
1、获取当前时间,和某个时间进行比较。此时主要拿long型的时间值。
 方法如下:

要使用
java.util.Date 。获取当前时间的代码如下

Date date = new Date();

date.getTime() ;

还有一种方式,使用 System.currentTimeMillis() ;
都是得到一个当前的时间的long型的时间的毫秒值,这个值实际上是当前时间值与1970年一月一号零时零分零秒相差的毫秒数

2、获取某种格式的日期。
方法:

获取时间的格式,需要用到一个专门用于时间格式的类 java.text.SimpleDateFormat

首先,定义一个 SimpleDateFormat 变量

SimpleDateFormat sdf = new SimpleDateFormat("",Locale.SIMPLIFIED_CHINESE);

这个构造函数的定义如下:

SimpleDateFormat(String   pattern, Locale   locale)

第一个参数 pattern ,我们后面再解释,这里我们使用一个 "", 第二个参数,是用来设置时区的,这里用到了 java.util.Locale 这个类,这个类了面定义了很多静态变量,直接拿过来用就 OK ,我们把时区设置为 Locale.SIMPLIFIED_CHINESE ,只看名字,这个静态变量的意义已经很清楚了。

 

接下来我们使用这个 SimpleDateFormat 把当前时间格式化为一个如下格式的时间字符串“ XXXX XX XX _XX XX XX 秒”,代码:

sdf.applyPattern("yyyy年MM月dd日_HH时mm分ss秒");

String timeStr = sdf.format(new Date());

 

获取时间格式的函数是 format ,这个函数的参数是 java.util.Date 对象,这个没有什么花头。

要说明一下的是这个 pattern ,所谓的模式。这里, yyyy,MM,dd 等,这就是模式。

我们可以在 SimpleDateFormat 的构造函数中指定模式,比如

SimpleDateFormat sdf = new SimpleDateFormat(" yyyy-MM-dd ",Locale.SIMPLIFIED_CHINESE);

也可以获取时间格式的时候使用applyPattern函数临时指定,上面的例子就是这样。

什么字符代表什么,这是 j2se 约定好的,设置模式的时候,我们可以使用约定好的字符加上任何我们想要的字符串。

j2se 对字符所代表的模式的约定列表如下:

 

 

Letter Date or Time Component Presentation
G Era designator Text
y Year Year
M Month in year Month
w Week in year Number
W Week in month Number
D Day in year Number
d Day in month Number
F Day of week in month Number
E Day in week Text
a Am/pm marker Text 
H Hour in day (0-23) Number
k Hour in day (1-24) Number
K Hour in am/pm (0-11)  Number
h   Hour in am/pm (1-12)  Number
m   Minute in hour  Number
s   Second in minute  Number
S   Millisecond  Number  
z   Time zone   General time zone 
Z   Time zone  RFC 822 time zone 

posted @ 2006-07-18 13:53 黑咖啡 阅读(18845) | 评论 (1)编辑 收藏
SAP R/3 是一个基于客户/服务机结构和开放系统的、集成的企业资源计划系统。其功能覆盖企业的财务、后勤(工程设计、采购、库存、生产销售和质量等)和人力资源管理、SAP业务工作流系统以及因特网应用链接功能等各个方面。

R/3
应用软体采模组化结构。它们既可以单独使用,也可以和其它解决方案相结合。从流程导向的角度而言,各应用软体间的整合程度越高,它们带来的好处就越多。

FI 财务会计 集中公司有关会计的所有资料,提供完整的文献和全面的资讯,同时作为企业实行控制和规划的最新基础。

TR 财务管理 是一个高效率财务管理完整解决方案,确保公司在世界范围的周转,对财务资产结构实行盈利化组合,并限制风险。

CO 管理会计 是公司管理系统中规划与控制工具的完整体系,具有统一的报表系统,协调公司内部处理业务的内容和过程。

EC 企业控制 根据特制的管理资讯,连续监控公司的成功因素和业绩指标。

IM投资管理 提供投资手段和专案,从规划到结算的综合性管理和处理,包括投资前分析和折旧模拟。

PP 生产计划 提供各种制造类型的全面处理:从重覆性生产、订制生产、订装生产,加工制造、批量及订存生产直至过程生产,具有扩展MPRⅡ的功能。另外还可以选择连接PDC、制程控制系统,CADPDM

MM 物料管理 以工作流程为导向的处理功能对所有采购处理最佳化,可自动评估供应商,透过精确的库存和仓储管理降低采购和仓储成本,并与发票核查相整合。

PM 工厂维护 提供对定期维护、检查、耗损维护与服务管理的规划、控制和处理,以确保各操作性系统的可用性。

QM 品质管理 监控、输入和管理整个供应链与品质保证相关的各类处理、协调检查处理、启动校正措施、以及与实验室资讯系统整合。

PS 专案管理 协调和控制专案的各个阶段,直接与采购及控制合作,从报价、设计到批准以及资源管理与结算。

SD 销售与分销 积极支援销售和分销活动,具有出色的定价、订单快速处理、按时交货,交互式多层次可变配置功能,并直接与盈利分析和生产计划模组连接。

HR 人力资源管理 采用涵盖所有人员管理任务和帮助简化与加速处理的整合式应用程式,为公司提供人力资源规划和管理解决方案。

开放式资讯仓储 包括智能资讯系统,该系统把来自R/3应用程式和外部来源的数据归纳成为主管人员资讯,不仅支援使用者部门决策和控制,同时也支援对成功具有关键作用的高阶控制和监控。

R/3-定制化策略资讯管理

保持竞争领先地位端赖于公司建立有效并尽可能以客户为导向的企业流程结构的能力。这就需要具备可最有效支援今后企业流程的资讯处理系统。

R/3系统并非只是软件,它是一种策略性解决方案。

R/3系统-企业流程的思维与行动。

公司必须运用动态战略对瞬息万变的挑战作出反应。迅速适应客户新需求和市场新商机的能力,是赢得竞争胜利的决定性因素。此种适应力需要一个功能强大、开放式的基础结构,它可针对目前的企业流程提供最佳化支援,并能灵活适应变化与发展。R/3系统就是应付这些挑战的最佳解答,它是主从式架构上最普遍的标准商业应用软件。

SAP R/3系统具备以下功能和主要特点:

功能性:R/3以模块化的形式提供了一整套业务措施,其中的模块囊括了全部所需要的业务功能并把用户与技术性应用软件相联而形成一个总括的系统,用于公司或企业战略上和运用上的管理。

集成化: R/3把逻辑上联的部分连接在一起。重复工作和多余数据被完全取消,规程被优化,集成化的业务处理取代了传统的人工操作。

灵活性:R/3系统中方便的裁剪方法使之具有灵活的适应性,从而能满足各种用户的需要和特定行业的要求。R/3还配备有适当的界面来集成用户自己的软件或外来的软件。

开放性:R/3的体系结构符合国际公认的标准,使客户得以突破专用硬件平台及专用系统技术的局限。同时,SAP提供的开放性接口,可以方便地将第三方软件产品有效地集成到R/3系统中来。

用户友好:图标与图形符号简化了人机交互时的操作。统一设计的用户界面确保了工作人员能够运用同样的熟悉的技术从事不通的工作。

模块化:R/3的模块结构使用户既可以一个一个的选用新的实用程序,也可以完全转入一个新的组织结构体系。

可靠:作为用户的商业伙伴SAP始终不断地为集成化软件的质量设立越来越多的国际标准。

低成本高效益:信息处理是取得竞争优势的要点之一。当竞争加剧时,企业必须更加努力地获取其市场占有量。这就要使用高度集成化的数据处理软件,而R/3正是这种软件的优秀典范。

国际适用:R/3支持多种语言,而且是为跨国界操作而设计的。R/3可以灵活地适应各国的货币及税物要求。

服务:R/3系统实施过程中,用户将得到SAP技术专家的全面支持与服务,包括组织结构方面与技术方面的咨询,项目计划与实施方面的协助,以及培训课程。
posted @ 2006-07-10 19:02 黑咖啡 阅读(441) | 评论 (0)编辑 收藏
据美国哥伦比亚大学心理学教授STANLEY COREN结合208位各地驯狗专家,63名小型动物兽医师,及14名研究警戒犬与护卫狗的专家对各著名犬种进行深入访谈观察,并在Vancouver Dog Obedience Club提供的大量相当有价值的资料下,填写了一份非常复杂庞大的问卷,对犬只的工作服从性和智商进行了排名,现排行名次公布如下:

1.边境牧羊犬
2.贵宾犬
3.德国牧羊犬
4.金毛猎犬
5.杜宾犬
6.喜乐蒂犬(谢德兰牧羊犬)
7.拉布拉多猎犬
8.蝴蝶犬
9.洛威拿
10.澳洲牧牛犬
排名1-10的狗,大部分听到新指令5次,就会了解其涵义并轻易记住,主人下达时,它们遵守的几率高于95%,此外,即使主人位于远处,它们也会在听到指令后几秒种内就有反应。即使训练它们的人经验不足,它们也可以学习得很好。
11.威尔斯科基犬
12. 迷你型雪纳瑞
13.英国跳猎犬
14.比利时特弗伦犬
15.史其派克犬/比利史牧羊犬
16.苏格兰牧羊犬
17.德国短毛指示犬
18.英国可卡/标准型雪纳瑞
19.布列塔尼猎犬
20.美国可卡
21.威玛猎犬
22.伯恩山犬
23.松鼠犬
24.爱尔兰水猎犬
25.维兹拉犬
26.卡狄肯威尔斯科基犬

排名11-26的狗,似乎要学习5-15次才能学会简单指令,它们遵守第一次指令的几率是85%,对于稍微复杂的指令有时候反应会稍微迟缓一些,但只要勤加练习就能消除这种延缓状况。当主人离它们较远时,它们的反应有可能也稍微迟缓一些,不过,即使训练人员经验稍微不足,还是有办法将这些狗调教得很优秀。

27.切萨皮克湾拾列犬/波利犬/约克夏埂
28.巨型雪纳瑞
29.万能埂
30.伯瑞犬
31.威尔斯跳猎犬
32.曼彻斯特埂
33.萨莫耶犬
34.纽芬兰狗/澳洲埂/美国斯塔福郡埂/戈登蹲猎犬/长须牧羊犬
35.凯恩埂/凯利蓝埂/爱尔兰埂
36.挪威猎糜犬
37.猴面埂/丝毛埂/迷你品犬/法老王猎犬/克伦伯长毛垂耳猎犬
38.洛威埂
39.斑点狗
排名27-39是属于中上程度的狗,重复了15次指令后才会表现出似懂非懂的反应,需要很多额外练习,尤其在初级阶段。它们对第一次指令作出的回应几率是90%,表现的优劣取决于练习时间的多寡。整体来说,表现与排名较前的狗一样好,只是动作没那么平顺连贯,而且反应时间也稍微慢半拍,如果主人站得稍远,它们可能不会回应主人的指令,如果训练者缺乏经验,或过于严厉或没耐心,这些狗的表现就会很差。

40.贝林顿埂
41.爱尔兰猎狼犬
42.库瓦兹犬
43.萨路基猎犬
44.骑士查里王猎犬/德国刚毛指示犬
45.西伯利亚雪撬犬/比熊犬
46.藏獒/灵堤/英国猎狐犬/美国猎狐犬/格里芬犬
47.西高地白埂
48.拳师狗/大丹狗
49.腊肠狗
50.阿拉斯加雪撬犬
51.沙皮狗
52.罗德西亚背脊犬
53.爱尔兰埂
54.波斯顿埂/秋田狗


排名40-54的狗是智商与服从中等程度的狗,在学习过程中,会在。练习15-20次之后才对任务基本了解,若想得到令人满意的表现,可能需要25-40次的练习,如果没有练习,可能会忘记曾经学过的动作。它们回应第一次指令的几率是50%,但先决条件是必须先重复训练。如果主人站得很近,它们的表现回较好,如果与主人距离增加一样好,但经验不足的人,或缺乏耐心者,可能拿这些狗没办法
55.斯凯埂
56.西里罕埂
57.巴哥犬
58.法国斗牛犬
59.马尔济斯犬
60.意大利灵堤
61.中国冠毛犬
62.丹地丁蒙埂/西藏埂
63.英国老式牧羊犬
64.比利牛斯山犬
65.苏格兰埂/圣伯纳犬
66.牛头埂
67.吉娃娃
68.拉萨犬
69.斗牛獒犬

排名55-69的狗,要使指令达到完美表现,可能需要40-80次的练习。即使经过这么多练习,还是无法成为永久习惯,如果练习中断了一阵子,它们表现出来的就像是从来没有学过这些动作,经过练习后,狗的回应第一次指令的几率是30%。大部分时候,这些狗都很容易分心,而且只在它觉得高兴的时候才会执行主人的指令,如果主人站得离狗稍远,就必须花很多时间对它们大叫,因为它们很可能相应不理。通常这些狗被评价为“独立,冷漠”等等。有经验的驯狗者,只要肯花很多时间,对狗投注坚定而慈祥的关注,就可以使这些狗对指令产生立即反应,不过它们的表现充其量也只不过是差强人意而已。
70.西施犬
71.巴吉度猎犬
72.獒犬/比高犬
73.北京犬
74.血堤
75.苏俄牧羊犬
76.松狮犬
77.老虎狗
78.见生吉犬
79.阿富汗猎犬

排名70-79的狗,要让它们记住指令,通常要练习上百次学会后必须多加练习,否则它们会忘得像没学过这个动作一样,即使习惯养成了,它们还是没办法每次都回应主人的指令,第一次回应的几率是25%,有时候它们会把头偏离主人,像是故意不理会主人,或是故意挑战主人的权威。当它们回应指令时,行动通常缓慢不确定,或心不甘情不愿。有些狗必须戴上项圈才听话,一脱下项圈就无法无天了。普通训练人员可能控制不了这些狗的表现。
posted @ 2006-07-10 10:55 黑咖啡 阅读(232) | 评论 (0)编辑 收藏
完全oop的语言(ruby,smalltalk,...)中,smalltalk暂时是最优雅的了,看了它之后,才明白C#/vb/java的语法确实不能带来太多的效率。看看java和smalltalk的语言对比,就知道java可能采用了smalltalk的思想+c的外观了:
http://www.chimu.com/publications/J...talkSyntax.html
它很small,而且像talk一样接近人的语言。



---------------------以下是转载:
smalltalk
可是面向对象的程序设计语言的鼻祖阿,并且正在蓬勃的发展,没有过时。它是纯面向对象的语言,就连整数也是对象。开放环境也非常集成,如果感兴趣可以到一下网站下载,绝对有耳目一新的感觉。举个例子,

循环语句在smalltalk中是向一个整数对象发送消息:

10 timesRepeat: [ teresa moveRight: 10 ].

其中timesRepeat:为消息名称,10为接受消息的整数对象,
[ teresa moveRight: 10 ].是消息的参数,


这又是smalltalk强大的地方,它可以把一段程序作为参数传递给某个对象!!!
Squeak Smalltalk
http://www.squeak.org/ 这是一个非常有趣的smalltalk版本,看上去就像在你的电脑上模拟了另外一套完成的窗口系统,这里面的窗口更加利害,你甚至可以旋转它,不看不知道,看了才发现还有这么奇妙的语言,这么奇妙的开发环境。10M左右

Cincom Smalltalk
http://www.cincom.com/scripts/smalltalk.dll/home.ssp 这个版本比较实用,有详细的帮助,可以开发真正的windows程序。30M左右

Dolphin Smalltalk
http://www.object-arts.com/ 这里提供的免费smalltalk版本只有3M不到,如果你想先尝试一下这种语言的话,可以下载这个。

这是一个支持unicode的smalltalk版本:
http://www.objectconnect.com/
可以下载 限时版
posted @ 2006-07-06 16:28 黑咖啡 阅读(999) | 评论 (0)编辑 收藏
C#会前途黯淡,只因大胡子惹的祸?!有点耸人听闻吧。可是色列软件工程师 Tamir Khason自有一套理论(也许他曾学过中国的面相术)得出这样的结论。不信,咱就瞧瞧他发在自己Blog上的一篇文章,看看他有什么样的奇思妙想。


Fortran.jpg 
John Backus,Fortran之父

Prolog.jpg 
Alain Colmerauer, Prolog之父

ada.jpg 
Jean Ichbiah, Ada之父

  以上三人分别发明了Fortran、 Prolog和 Ada语言。这些语言都有着过人的优点,每一种在当时都可以称得上是创意不凡。很可惜,三个当中没有一个广泛流传。与之相对,下面的Brain Kernighan、Dennis Ritchie和Ken Thompson所“炮制” 出的C和Unix,已经使用了三十年了,也许再用100年也没问题!

C_BK.jpg 
C语言宗师Brain Kernighan

C_KT_DR.jpg 
UNIX/C创造者Ken Thompson 和 Dennis Ritchie

  Round 2

  以下两位分别是Alan Kay和Kristen Nygaard。是他们发明了第一批面向对象语言 Smalltalk和Simula 67。不过,这些语言都行之不远。

smalltalk.gif 
Smalltalk之父Alan Kay

simula.png 
Simula 67之父Kristen Nygaard

  Brad Cox,曾尝试把OO加入到C中,于是Objective-C诞生。然而,Objective-C 也是命运不济,目前只有在Mac操作系统中还能看到它的踪影。 与之相对,另一位所做的相同尝试却大红大紫,这就是Bjarne Stroustrup所写的C++。其实,看看 Stroustrup的脸就不难明白为什么这两种语言的命运会如此不同。

objective-c.gif 
Objective-C之父Brad Cox

c++.jpg 
C++之父Bjarne Stroustrup

  到这里,你能猜出点规律来吗?

  答案揭晓:有大胡子——有旺运;没胡子——只有干瞪眼!

  由此,看看下面两位的胡子,C#和Java究竟鹿死谁手,不就是不言自明的吗?

csharp.jpg 
C#之父Anders Hejlsberg

java.jpg 
Java之父James Gosling

  Round 3

  当然,你也可以不信。不过,还有一个例证可以很好地说明。下面两位分别是Basic的作者Thomas Kurtz 与Perl的作者Larri Wall。两人虽然没有令人咋舌的大胡子,但两撇小胡子倒也浓密有致。自然,这两种语言红得发紫。

basic.gif 
Thomas Kurtz, Basic之父

perl.jpg 
Larry Wall, Perl之父

  但是同为动态语言,Python和Ruby的作者Guido van Rossum和松本行弘都没有胡子,哪怕是两撇小胡子,所以尽管它们都比Perl语言好,但都没有Perl使用广泛。不过,凡事都有转机。Rossum看样子极有希望很快长出大胡子,而日本人松本,看样子够呛。

python.jpg 
Guido van Rossum, Python之父

ruby1.jpg 
松本行弘, Ruby语言之父

  更有意思的事情还在后面,松本正巧看到了这个帖子,很不服气,于是便在自己的blog上贴出这幅照片:

ruby2.jpg 
  松本行弘:谁说俺长不出大胡子?

  看来, Ruby还是大有希望的!

  后记:从2005年发展的情况来看,Ruby的火爆再次证明的胡子定律的正确性。
posted @ 2006-07-06 16:09 黑咖啡 阅读(240) | 评论 (0)编辑 收藏
*********************JAVA资源收藏***********************

A.书名:《Thinking in Java》2e中文版 侯捷 / 王建兴 合译
URL: http://jjhou.csdn.net/thinking-in-java-20010919.pdf
B.书名:JBuilder5中文帮助文件
URL: http://www.code-labs.com/manual/Jb5cn_help1.rar
http://www.code-labs.com/manual/Jb5cn_help2.rar
C.书名:Think in Java(中文版)---chm格式
URL: http://www.code-labs.com/manual/Think%20In%20Java.chm
D.书名:Jbuilder开发人员指南(完整版)
URL: http://www.java-cn.net/book/books-zip/JbuilderGuide.zip
E.书名:Java2编程详解(Special_Edition_Using_Java)
URL: http://www.java-cn.net/book/books-zip/Java2Xiangjie.zip
F.书名:Java2 轻松进阶
URL: http://www.java-cn.net/book/books-zip/java11.zip
G.书名: JavaBeans开发使用手册
URL: http://www.java-cn.net/book/books-zip/JavaBeansDevelop.zip
H.书名:Java1.3API手册
URL: http://www.java-cn.net/book/books-zip/api.zip

java 教程与实例
http://download.pchome.net/php/download2.php?sid=10837&url=/development/reference/Javateach0307.zip&svr=3

I.书名:SCJP认证笔记
URL: http://vanstone.myetang.com/scjp/scjpnotes.rar
J.书名:Sun培训教材中文稿
URL: http://vanstone.myetang.com/scjp/javabook/sl275cn.pdf
K.书名:SCJP认证Bible
URL: http://vanstone.myetang.com/scjp/scjpbible.rar
L.书名:java开发规范(html)
URL: http://www.cn-java.com/target/download.php?id=790&downurl=../download/book/javaformat.zip
M.书名:EJB2.0 Entity bean(PDF)
URL: http://www.cn-java.com/target/download.php?id=708&downurl=../download/book/EJB2.0.zip
N.书名:J2ME用户使用手册(PDF)
URL: http://www.cn-java.com/target/download.php?id=667&downurl=../download/book/UserGuide.pdf
O.书名:JavaServerPages基础
URL: http://www.java-cn.net/book/books-zip/JSPIntro.zip
P.书名:RMI Enhancements
URL: http://www.cn-java.com/target/download.php?id=297&downurl=/download/tools/rmispecjdk12.zip
Q.书名:无废话XML
URL: http://www.cn-java.com/target/download.php?id=222&downurl=../download/tools/wfhxml_gb.zip

R.书名:Design Pattens
注释:号称软件工程师的床头必备书籍,非常经典,对面向对象思想在实践应用中的模式做了经典性的总结
URL: http://automation.seu.edu.cn/auto/content/Design.zip

S.书名:设计模式 可复用面向对象软件的基础
注释:南京大学翻译的Design Patterns的中译本,机械工业出版社出版,翻译质量较好
URL: http://automation.seu.edu.cn/auto/content/DesignCh.zip

T.书名:Thinking in Java with Patten
注释:与Thinking in Java为同一作者所著,设计模式与Java的结合
URL: http://automation.seu.edu.cn/auto/content/TIPatterns[Thinking%20in%20Pattern%20with%20java].zi
p

U.书名:The Design Pattens Java Companion
注释:另一本Design patten 与Java相结合的书 James w.Cooper著
URL: http://automation.seu.edu.cn/auto/content/DesignJava.zip

V.书名:Java 2 平台安全技术-结构,API设计和实现
注释:来自china pub,PDF文档,中译本
URL: http://automation.seu.edu.cn/auto/content/Java2Safe.zip

W.书名:Mastering Enterprise JavaBeans
注释:Ed Roman著,EJB的优秀书籍
URL: http://automation.seu.edu.cn/auto/content/EJB-book.zip

X.书名:Pure JSP
注释:James Goodwill著 Sams, Macmillan Computer Publishing 2000.6.8出版
URL: http://automation.seu.edu.cn/auto/content/Pure%20jsp.zip

Y.书名:Sun Tutorial 2001.5
注释:Sun公司的经典教程,入门必读
URL: http://automation.seu.edu.cn/auto/content/tutorial_2001.zip

Z.书名:JDK1.3.1 document Winhelp 格式
注释:Winhelp格式的JDK文档,更易阅读和查找,很棒
URL: http://automation.seu.edu.cn/auto/content/jdk13doc_help.zip


1A.书名:The Java Virtual Machine Specification Second Edition
注释:Java 虚拟机规范,有助于理解Java的实现原理,Sun出版
URL:http://automation.seu.edu.cn/auto/content/vmspec.2nded.html.zip

1B.书名:The Java Language Sepcification Second Edition
注释:Java 语言规范,Java编程语言的详细说明,Sun出版
URL: http://automation.seu.edu.cn/auto/content/langspec-2.0.zip

1C.书名:Java programmer's FAQ
注释:Sun公司的FAQ,内容丰富,覆盖面广
URL: http://automation.seu.edu.cn/auto/content/faq.zip

1D.书名:Cocoon 2 简介
注释:Cocoon 是一种 Java 服务器框架,它允许使用 XSLT转换动态发布 XML 内容。通过依靠 XML 描述内容,使用 XSLT 将内容转换成多种格式,Cocoon 提供了用于构建内容、
逻辑和表示在很大程度上彼此分离的应用程序的平台。 本教程将介绍 Cocoon 2,一个比原始 Cocoon 应用程序更有效和更可伸缩的平台。
URL: http://www-900.ibm.com/developerWorks/cn/education/xml/x-cocoon/tutorial/x-cocoon.zip

1E.书名:java事件传递技术
注释:Java 2 平台使程序员可以从事件的角度来思考系统,而不从是传统的调用-返回(call-return)体系结构风格的角度。在该平台本身内部,就有对多种事件通知模式的直接支持。思考事件的一种方
式是通过事件的粒度和所有权。一些事件模式适合在对象实例状态变化的粒度上表示事件。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-delivery/tutorial/j-delivery.zip

1F.书名:使用 JDBC 构建基于 Web 的应用程序
注释:如果您对构建使用 JDBC 访问数据库的 Web 应用程序的各种方法感兴趣,那么本教程适合于您。在这一实践指南中,您将通过使用三项独立的技术来学习这一过程的基础知识,这三项技术是:servle
t 方法、JavaServer Pages(JSP)页面方法以及 JSP、JavaBeans 与 servlet 相结合的方法(也称为 Model Two)。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-jdbcweb/tutorial/j-jdbcweb.zip

1G.书名:Java 3D 探奇
注释:本教程是为没有任何 3D 编程经验的 Java 程序员而编写的。我们将从一些基本的 3D 概念入手,探索如何构建一副场景图 — 用于描述我们想要渲染的场景的基本对象。然后,我们将接触 Java
3D 的一些更强大的功能。我们的重点将放在使用一些 Java 3D 实用类来开始您的编程。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-java3d/tutorial/j-java3d.zip
1Q.书名:Java 调试
注释:即使是最高级的开发人员所开发的最简单的应用程序也可能包含错误。如果要成为好的调试人员,不必象大侦探那样调查蛛丝马迹。您只需了解概念并熟悉正确的工具。在本教程中,我们提供了关于基本 Java 调
试概念和更高级调试类型的详细信息。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-debug/j-debug.zip

1R.书名:构建定制的树型视图
注释:在这篇免费的 dW 专有的独家教程中,讲述了关于 Swing 树型视图的概念、它们所显示的内容、如何设置它们以及如何定制它们。它还讲述了使用线程来执行长时间运行任务的概念,这样用户界面就可以保
持迅速反应。研究 Java Swing 树的相关类,演示了如何定制基本数据模型和树节点的绘制。为说明这些概念,我们将生成一个增强型 JTree,JMagnitudeTree。这个增强型 JTree 可
以显示树节点的相对数量,以及标准节点名称和整个树型结构。例如,如果树显示的是文件目录结构,那么它可以指出所有文件和目录的相对大小。本教程并不试图充当编程参考,因此合适的 Swing 参考资料或在线文档
也许会有帮助。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-magnitudetree/MagnitudeTree.zip

1S.书名:构建 Java 聊天服务器
注释:在这篇免费的 dW 专有的独家教程中,我们将构建一个简单聊天系统的服务器和客户机方。您将在这个过程中学到创建这样一个服务器时可以用到的基本框架,该框架使用在很多情况下都能很好工作的传统技术。我
们还将讨论框架的一些限制,并找到克服这些限制的方法。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-chat/tutorial/j-chat.zip

1T.书名:构建带会话跟踪的 Servlet
注释:本教程讲授使用 Servlet 和 JSP 技术构建因特网应用的技巧。其关键是启用会话处理,那么 Servlet 就可以知道哪个用户在干什么。本教程显示了一个 URL 书签系统,在这个系统中,
多个用户访问一个系统以添加、除去和更新 HTML 书签列表。Servlet 使用 JSP 技术来处理用户交互。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-servlets2/tutorial/j-servlets2.zip


1H.书名:使用 JDBC 的高级数据库操作
注释:本教程旨在向您介绍几种高级数据库操作,包括存储过程和高级数据类型,它们可以通过使用 JDBC 的 Java 应用程序执行。教程中的示例代码是为 DB2 通用数据库 7.2 编写的,但因为使用了
DataSource 对象,修改这些代码以适用于其它数据库是不成问题的。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-jdbcadv/tutorial/j-jdbcadv.zip

1I.书名:用 JDBC 管理数据库连接
注释:本教程介绍了使用“Java 数据库连接”(Java Database Connection(JDBC))从 Java 应用程序内部建立和管理数据库连接所涉及的不同概念。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-jdbc/tutorial/j-jdbc.zip
1J.书名:Java 集合框架
注释:本教程将带您漫游 “Java 集合框架”(Java Collection Framework)。为了尽快开始学习“集合框架”,教程从一些面向初学者和专家等读者的简单编程示例入手。接着,教程继续
讨论集(set)和映射(map),它们的属性以及它们数学上的定义与“集合框架”中的 Set、 Map 和 Collection 定义有何不同。“Java 集合框架”的历史那一节澄清了集和映射相关类的一
些混淆。本教程彻底介绍了“集合框架”中所有的接口和实现这些接口的类。本教程不仅谈到了用线程安全和只读方式处理集合,还探讨了集合的算法支持。此外,教程还讨论了在 JDK 1.1 中使用“集合框架”的一个
子集。最后,教程以先于“Java 集合框架”的 ObjectSpace 中一种广泛使用的算法和数据结构库 JGL 的介绍作为结束。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-collections/tutorial/j-collections.z
ip

1K.书名:Java 套接字(socket)101
注释:本教程将告诉您什么是套接字(socket)并教您如何在 Java 程序中使用它。通过实际分析几个示例,从单个客户机/服务器通讯到池中的一组客户机访问服务器,您将学到如何用套接字处理现实世界中碰
到的典型情形。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-sockets/tutorial/j-sockets.zip

1L.书名:Java Message Service 基础教程
注释:本教程向您介绍了 Java 消息服务(Java Message Service,JMS)概述,并提供了使用它开发程序的基本知识。Sun Microsystems 开发 JMS 是为 Java
程序访问企业消息传递系统、也称面向消息的中间件(MOM)提供一种途径。通过中介这种间接方式来支持应用程序间数据的异步传递,MOM 提供了一种以松散组织的、灵活的风格来集成应用程序的机制。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-jms/tutorial/j-jms.zip

1M.书名:JavaMail API 基础教程
注释:想将邮件工具结合到您独立于平台的 Java 解决方案中吗?再没有比 JavaMail API 更合适的了,它提供了个独立于协议的模块,能用于 IMAP、POP、SMTP、MIME 和其它涉及因
特网的消息传递协议。现在,有了 JavaBeans Activation Framework (JAF)的支持,您的应用程序经由 JavaMail API 就能启用邮件功能啦。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-javamail/tutorial/j-javamail.zip

1N.书名:J2ME 循序渐进
注释:本教程详细审查了袖珍版 Java 2 平台 (J2ME),它主要面向在 Java 编程及面向对象设计与开发方面有深厚背景的中级开发者。 您可以首先了解 J2ME 的背景并研究 J2ME 的配置
和简表。随后,逐步建立您的开发环境,用于开发 J2ME 应用程序。
本教程将向您介绍一些课题如 K 虚拟机 (KVM),和 KJava API -- 用于关联连接有限设备配置 (CLDC) 和使用 CLDC 的移动信息设备简表。之后您将构造一个简单的应用程序来看看您能
用 J2ME 做些什么。您将使用 CLDC 和 KJava 开发一个基本绘图应用程序以及一个小型 MIDP 应用程序。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j2me/tutorial.zip

1O.书名:构建自己的 Java 库
注释:此篇教程主要教您怎样使用 Java 语言来构建自己的可重用的类库。内容包括设计良好类库的一些关键事项以及有效方法,为了更好的说明内容,教程还给出了一个简单的类库设计的例子。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-library/j-library.zip

1P.书名:了解 Java ClassLoader
注释:Java ClassLoader 是一个重要的、但又常常被人忽略的 Java 运行时系统组件。它是负责在运行时查找和装入类文件的类。创建自己的 ClassLoader 可以以实用且有趣的方式定
制 JVM,这样可以让您彻底重新定义如何将类文件引入系统。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-classloader/j-classloader.zip

1Q.书名:Java 调试
注释:即使是最高级的开发人员所开发的最简单的应用程序也可能包含错误。如果要成为好的调试人员,不必象大侦探那样调查蛛丝马迹。您只需了解概念并熟悉正确的工具。在本教程中,我们提供了关于基本 Java 调
试概念和更高级调试类型的详细信息。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-debug/j-debug.zip


1R.书名:构建定制的树型视图
注释:在这篇免费的 dW 专有的独家教程中,讲述了关于 Swing 树型视图的概念、它们所显示的内容、如何设置它们以及如何定制它们。它还讲述了使用线程来执行长时间运行任务的概念,这样用户界面就可以保
持迅速反应。研究 Java Swing 树的相关类,演示了如何定制基本数据模型和树节点的绘制。为说明这些概念,我们将生成一个增强型 JTree,JMagnitudeTree。这个增强型 JTree 可
以显示树节点的相对数量,以及标准节点名称和整个树型结构。例如,如果树显示的是文件目录结构,那么它可以指出所有文件和目录的相对大小。本教程并不试图充当编程参考,因此合适的 Swing 参考资料或在线文档
也许会有帮助。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-magnitudetree/MagnitudeTree.zip

1S.书名:构建 Java 聊天服务器
注释:在这篇免费的 dW 专有的独家教程中,我们将构建一个简单聊天系统的服务器和客户机方。您将在这个过程中学到创建这样一个服务器时可以用到的基本框架,该框架使用在很多情况下都能很好工作的传统技术。我
们还将讨论框架的一些限制,并找到克服这些限制的方法。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-chat/tutorial/j-chat.zip

1T.书名:构建带会话跟踪的 Servlet
注释:本教程讲授使用 Servlet 和 JSP 技术构建因特网应用的技巧。其关键是启用会话处理,那么 Servlet 就可以知道哪个用户在干什么。本教程显示了一个 URL 书签系统,在这个系统中,
多个用户访问一个系统以添加、除去和更新 HTML 书签列表。Servlet 使用 JSP 技术来处理用户交互。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/j-servlets2/tutorial/j-servlets2.zip

1U.书名:Java 语言基础
注释:本教程介绍了 Java 编程语言,包括一些用来说明面向对象架构语言的语法的示例, 以及一些标准编程的练习,如定义实例方法,使用内嵌(built-in)类型,创建用户自定义类型, 使用引用变量(
reference variables)等。
URL: http://www-900.ibm.com/developerWorks/cn/education/java/javaintro/tutorial/javaintro.zip


1V.书名:JavaRMI入门实战(实在找不到页面下载,这是ftp下载的)
URL:ftp://218.242.4.185/pub/work/JAVA_JSP_J2EE/Articles/RMI/JavaRMI%C8%EB%C3%C5%CA%B5%D5%BD.pdf

1W.书名:Java Xml 编程指南书籍源码
URL:ftp://202.115.39.65/--==Incoming==--/Documents/Tech/Java/J2EE/Java%20Xml%20编程指南书籍源码.rar

1X.书名:XML解决方案开发实务
URL:
http://www.guxiang.com/epubcn/readings/diannaotushu/100/download/xmlsolution.zip
posted @ 2006-07-06 10:34 黑咖啡 阅读(318) | 评论 (0)编辑 收藏

近段时间项目任务相对比较少,是一个很好补习java基础的机会,列一些需要着重注意的地方:

1、基础。一切活动的根基,重点在语法和api的理解,应用。
2、数据库。oracle 9i
3、struts
4、hibernate
5、sql语法

需要啃掉的书:
1、thinking in java
2、以前的课本有必要再看一下。

posted @ 2006-07-04 15:32 黑咖啡 阅读(206) | 评论 (0)编辑 收藏

try {
     new Thread(new Runnable() {
      public void run() {
       TaskService taskService = (TaskService)context.getBean(TaskService.SERVICE_NAME);
       List<Task> taskSharedList = taskService.getAllSharedTaskList();
       for (Task task : taskSharedList) {
        task.setOwner(mainFrame.getUserName());
       }
       try {
        ((LoginServiceProxyImpl) context.getBean(LoginServiceProxyImpl.SERVICE_NAME))
          .shareTask(taskSharedList);
       } catch (RemoteException e) {
        e.printStackTrace();
       } catch (ServiceException e) {
        e.printStackTrace();
       }
      }
     }).run();

    } catch (Exception e) {
    }

posted @ 2006-06-22 16:54 黑咖啡 阅读(173) | 评论 (0)编辑 收藏
无意见发现了这篇文章
关于《80前的前辈,你们都做了什么?!》一文对EasyJF团队造成恶劣影响的声明  
http://www.blogjava.net/daxia/archive/2006/06/01/49391.html

于是顺着线索看到了2篇文章,也是80前的一代人何80后的一代人的对话,也许带着些抱怨,也许带着些抨击,但是我并不能把这个定义为争吵,或者是争论。定义为对话,是因为我觉得主导自己人生的还是自己,自己的认识,自己的经历。如果一概的把自己的成长依赖于前辈的影响社会的塑造,那创新一词就该封存了。

贴出2篇文章的链接:
《80年代的兄弟,你会什么?!》http://blog.sina.com.cn/u/1490567244
80前的前辈,你们都做了些什么?! http://www.blogjava.net/daxia/archive/2006/05/29/48664.html
posted @ 2006-06-01 11:28 黑咖啡 阅读(172) | 评论 (0)编辑 收藏

时间真的是飞逝,转眼工作快一年了。

posted @ 2006-05-30 09:34 黑咖啡 阅读(136) | 评论 (0)编辑 收藏

通用惟一标识符(UUID)是128位比特的数字,用来惟一地标识因特网上的某些对象或者实体。根据使用的特定机制,通用惟一标识符不仅需要保证是彼此不相同的,或者最少也是与公元3400年之前其他任何生成的通用惟一标识符有非常大的区别。通用惟一标识符依靠保证惟一性的部分的组合。有保证的通用惟一标识符包括一个指向生成通用惟一标识符的主机的网络地址,时间戳(用来记录事务的精确时间的记录),以及一个随机生成的组件。因为网络地址标识了惟一的一台计算机 ,并且时间戳对于某台主机上的生成的每个通用惟一标识符也是惟一的,那么这两个部分就完全可以保证惟一性了。然而,随机生成的通用惟一标识符的元素也可以作为保护措施来防止所有的不可预见的问题。  

通用惟一标识符是作为tModel 数据结构中的一部分,这种数据结构标识通用描述、发现,和整合(UDDI)注册中的一种服务的类型(注册服务的通用表示法)。这种机制可用来发现网络服务。  

通用惟一标识符还可以用来指向大多数的可能的物体。微软和其他一些软件公司都倾向使用全球惟一标识符(GUID),这也是通用惟一标识符的一种类型,可用来指向组建对象模块对象和其他的软件组件。第一个通用惟一标识符是在网罗计算机系统(NCS)中创建,并且随后成为开放软件基金会(OSF)的分布式计算环境(DCE)的组件。

UUID,是128位整数(16字节)的全局唯一标识符(Universally Unique Identifier)。

UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成UUID的API。UUID按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。
在ColdFusion中可以用CreateUUID()函数很简单的生成UUID,其格式为:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。而标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
,可以从cflib 下载CreateGUID() UDF进行转换。
使用UUID的好处在分布式的软件系统中(比如:DCE/RPC, COM+,CORBA)就能体现出来,它能保证每个节点所生成的标识都不会重复,并且随着WEB服务等整合技术的发展,UUID的优势将更加明显。

PS:在MMColdFusion技术支持中心找到一篇文章,其中提到使用CreateUUID()会将WIN平台下的系统时间加快10毫秒,原因是JVM1.3.x 和1.4.x的bug,文章提到了解决方法。
posted @ 2006-05-26 17:13 黑咖啡 阅读(515) | 评论 (0)编辑 收藏
<span title="第一行&#13;&#10;第二行">haha haha haha</span>
posted @ 2006-05-19 12:07 黑咖啡 阅读(365) | 评论 (0)编辑 收藏
正在踌躇的时候发现下面的这段代码,终于得意解决。苦于对js没有足够的熟悉,代码中的具体方法参数还得继续学习,感谢提供代码的朋友。
function SetCwinHeight()
{
var cwin=document.getElementById("cwin");
if (document.getElementById)
{
if (cwin && !window.opera)
{
if (cwin.contentDocument && cwin.contentDocument.body.offsetHeight)
cwin.height = cwin.contentDocument.body.offsetHeight;
else if(cwin.Document && cwin.Document.body.scrollHeight)
cwin.height = cwin.Document.body.scrollHeight;
}
}
}

<iframe width="778" align="center" height="200" id="cwin" name="cwin" onload="Javascript:SetCwinHeight(this)" frameborder="0" scrolling="no"></iframe>


function SetCwinHeight(obj)
{
  var cwin=obj;
  if (document.getElementById)
  {
    if (cwin && !window.opera)
    {
      if (cwin.contentDocument && cwin.contentDocument.body.offsetHeight)
        cwin.height = cwin.contentDocument.body.offsetHeight;
      else if(cwin.Document && cwin.Document.body.scrollHeight)
        cwin.height = cwin.Document.body.scrollHeight;
    }
  }
}

引用时
onload="javascript:SetCwinHeight(this)"
posted @ 2006-04-27 15:50 黑咖啡 阅读(39268) | 评论 (13)编辑 收藏
RSS为Really Simple Syndication(简易供稿)的缩写,是某一站点用来和其它站点之间共享内容的一种简易方式,也叫聚合内容。网络用户可以在客户端借助于支持RSS的新闻聚合工具软件(例如SharpReader NewzCrawler、FeedDemon RSSReader),在不打开网站内容页面的情况下阅读支持RSS输出的网站内容。可见,网站提供RSS输出,有利于让用户发现网站内容的更新。在高速高质高效成为主流呼声的互联网时代,RSS无疑推动了网上信息的传播,提出了另一种看世界的方式。

    RSS,原意是把网站内容如标题、链接、部分内文甚至全文转换为可延伸标示语言(XML:eXtensible Markup Language)的格式,以向其它网站供稿,使用者可以用一般的浏览器观看,也可以用特殊的“阅读器”软件来阅读。
posted @ 2006-04-27 15:19 黑咖啡 阅读(186) | 评论 (0)编辑 收藏

WikiWiki一词来源于夏威夷语的 "wee kee wee kee" ,原本是“快点”的意思。在这里WikiWiki指一种超文本系统。这种超文本系统支持面向社群的协作式写作,同时也包括一组支持这种写作的辅助工具。我们可以在Web的基础上对Wiki文本进行浏览、创建、更改,而且创建、更改、发布的代价远比HTML文本为小;同时Wiki系统还支持面向社群的协作式写作,为协作式写作提供必要帮助;最后,Wiki的写作者自然构成了一个社群,Wiki系统为这个社群提供简单的交流工具。与其它超文本系统相比,wiki有使用方便及开放的特点,所以wiki系统可以帮助我们在一个社群内共享某领域的知识。

1995年Ward Cunningham为了方便模式社群的交流建立了一个工具-波特兰模式知识库(Portland Pattern Repository)。在建立这个系统的过程中,Ward Cunningham创造了Wiki的概念和名称,并且实现了支持这些概念的服务系统。这个系统是最早的Wiki系统。从1996年至2000年间,波特兰模式知识库围绕着面向社群的协作式写作,不断发展出一些支持这种写作的辅助工具,从而使Wiki的概念不断得到丰富。同时Wiki的概念也得到了传播,出现了许多类似的网站和软件系统。

您现在所访问的Wikipedia是目前世界上最大的Wiki系统,它是一个基于Wiki和GNU FDL的百科全书网站系统。该系统于2001年1月投入运行,2001年2月超过1,000条条目,2001年7月超过10,000条条目,目前(2003年1月)已经接近100,000条条目。Wikipedia条目的迅速增长说明了Wikipedia系统的健壮,也说明了Wiki的概念是经得起验证的。

Wiki的历史还不长,无论是Wiki概念自身,还是相关软件系统的特性,还都在热烈的讨论中;所以怎样的一个站点才能称得上是一个Wiki系统还是有争议的。与Wiki相关最近出现的技术还有Weblog,它们都降低了超文本写作和发布的难度。这两者都与内容管理系统关系紧密。

Wiki的特点

使用方便

维护快捷:快速创建、存取、更改超文本页面(这也是为什么叫作 "wiki wiki" 的原因)。

格式简单:用简单的格式标记来取代 HTML 的复杂格式标记。(类似所见即所得的风格)

链接方便:通过简单标记,直接以关键字名来建立链接(页面、外部连接、图像等)。

命名平易:关键字名就是页面名称,并且被置于一个单层、平直的名空间中。

有组织

自组织的:同页面的内容一样,整个超文本的组织结构也是可以修改、演化的。

可汇聚的:系统内多个内容重复的页面可以被汇聚于其中的某个,相应的链接结构也随之改变。

可增长

可增长:页面的链接目标可以尚未存在,通过点击链接,我们可以创建这些页面,从而使系统得到增长。

修订历史:记录页面的修订历史,页面的各个版本都可以被获取。

开放性

开放的:社群的成员可以任意创建、修改、删除页面。

可观察:系统内页面的变动可以被访问者观察到。

相关条目

Wiki引擎

Web log

内容管理系统

群件

posted @ 2006-04-27 15:19 黑咖啡 阅读(182) | 评论 (0)编辑 收藏
总看到别人的Blog那么漂亮,一直不知道怎么才能让自己的Blog漂亮起来,当然我是知道blogjava里面肯定是可以选模板的。但是一直没找到(可能是没找,哈哈!)

今天终于看到了,选了一个稍微满意的css ,不是我的最爱,其实是我不知道自己的最爱是什么样子的。希望有一天能有自己的个人网站。
posted @ 2006-04-26 14:06 黑咖啡 阅读(147) | 评论 (0)编辑 收藏
  • Level 0 —— “CSS? Isn’t that a multiplayer game?”
曾经风靡一时的 CS 游戏吗?
  • Level 1 —— “Yeah, I use it to remove underlines on links sometimes”
懂一点HTML和基础的CSS,知道如何用CSS去掉链接默认有的下划线,但仅仅是在HTML标签本身不能做到的时候才会考虑用用CSS。
  • Level 2 —— “No, I don’t like divs; tables are much easier to work with”
HTML 很熟练了,有过不少网站的经验,甚至可能已经是Webmaster了。听说过现在流行用div布局,不过还是table 用起来顺手。
  • Level 3 —— “Yes I’ve heard it’s good, but I can’t use it because of…”
体会到了CSS的好处,并且尝试用CSS做一些简单的布局,但苦于没有一个应用的项目或机会。
  • Level 4 —— “CSS? Oh! Yes, I use divs for all my layouts”
已经开始应用CSS布局,但缺乏经验,甚至过度应用,HTML页面如果没有CSS,结构将乱成一糟。
  • Level 5 —— “I use CSS for design, it’s better than tables because of…”
已经积累了丰富的CSS使用经验,也有了相当的理论基础。开始自觉的宣传结构与表现分离的原则。
  • Level 6 —— “What version of CSS? Yes, I do. Did you read my book about…”
牛人! 熟读W3C的CSS规范;深谙各个浏览器对CSS支持的细微区别;说不定就是 >>Web Standards Project 组织成员;常常发表优秀的文章并吸引大量拥蹙。
posted @ 2006-04-26 13:36 黑咖啡 阅读(184) | 评论 (0)编辑 收藏

从了解日本,到瓦解日本,最后达到占领日本的目的。于是我开始学日语了,哈哈!!!!

时间安排不好一直是自己的一个大毛病。。。。。怎么改正呢???????很晕。。。。。。

甩甩头。。。。。。还是得学啊。从现在坐起,合理安排时间,看来还是要把以前定计划的习惯拣起来了(尽管以前定的计划也没几个按照上面来的。。。晕)


论成败人生豪迈,大不了从头再来。 --彪子

posted @ 2006-04-02 13:12 黑咖啡 阅读(184) | 评论 (0)编辑 收藏
最近发现自己很多基础问题都不明白。导出搜集。于是有这一贴:
题目:
1.java程序在保存文件时,后缀名是?
2.java程序经过编译过后,后缀名是?
3.java程序文件保存时,主文件名是?
4.如何用浏览器观看输出至命令行模式的结果?
5.如何把一个java applet放到网页上?
6.public class  cjc extends java.applet.Applet{
public static void main(String args[])
{
cjc mf=new cjc();
mf.init();
}
public void init(){
累加 累加数字 = new 累加(10);
System.out.println(累加数字.总和());
}
}
class 累加{
int in=;
public 累加(int in){
this.in=in;
}
public int 总和(){
int i,sum;
sum=0;for(i=1;i<=in;i++)  sum+=i;
return sum;
}
}
如果你想要计算a加到b的总和,如何修改?
题目:
1. 下面哪个是对的?
A.IloveJava     B.$20   C.piggy@msl    D.Hello_worle   E.2two     F.sum+of+money
2.下面可能产生什么结果?如果有错如何改正?
int i=5;
int j=2;
k=i*j;
3.下面可能产生什么结果?如果有错如何改正?
float f=2.5;
f=f*2;
4.answer变量的数据类型应该是?
byte b=1;     char c=2;    short s=3;    int i=4;     float f=5.0f;
answer=b*c*s*i*f;
5.如果我想要把[2*2.5]的结果用一个float变量存放的话,程序应该如何编写?
题目:
1.请问最后a,b变量的数值是?
int x,a=5,b3;      x=a++ + b--;
A.x=8,a=5,b=3;    B.x=8,a=6,b=2;     C.x=7,a=5,b=2;     D.x=9,a=6,b=3;
2.下列表达式,哪几个是正确的?
A.int x=6;x=!x;     B.int x=6;x=~x;   C.boolean b=true; b=!b;    D. boolean b=true; b=!b;
3.下列表达式,哪几个x变量的值最后会是正数?
A.int x=-1;x=x>>>5;    B.int x=-1;x=x>>>32;     C.byte x=-1;x=x>>>5;  
D.int x=-1;x=x>>5;
4.下列的变量x,y,哪几个运算完,结果使true?
A.int i=100;float f=500.0f;i==f?     B.int i=40;float f=500.0f;i>f?
C.int i=20;float f=30.0f;i<f?           D.int i=55;float f=33.3f;i!=f?
5.下列的结果是?
int i=100;     i=((i++>>35) << 32)%10;
A.0     B.1     C.2      D.3

题目:
1.if(score >=90 && score <=100)
finalScore="甲";
else if (score >=80 && score <=90)
finalScore="乙 ";
else if (score >=70 && score <=80)
finalScore="丙 ";
else if (score >=60 && score <=70)
finalScore="丁 ";
else
finalScore="戊 ";
用更简单的方法写出来(不能用逻辑表达式)
2.写一个程序,它能够计算a加到b的总和,其中a不一定比b小。
3.写一个程序,它能够把1到100中的质数显示出来。
4.写一个程序,能够从五个数字中跳出最大值。
5.那些循环语句的写法是正确的?
A.while (int i<5){ i++; System.out.println(i);}
B.int i=5; while(i)  System.out.println(i);
C.int j=1; for (int k=1;j+k != 10;j++,k++)    System.out.println("j="+j+"k="+k);
D.int j=1;  do { System.out.println(j++);   if(j==5) contine loop1;}   while (j<20);

题目:
1.哪些是合法的重载?
public class Q1{      public void method(int i){ };     }
A.private void method(int i){ }           B.public void method(int k){ }
C.public int method(int i){ }               D.private float method(float f){ }
E.public String method(int i,int j){ }
2. 在Q2_2类中,哪些是合法的覆盖?
public class Q2_1{
public void method(int i){ };
}
class Q2_2 extends Q2_1{
}
A.public void method(int i){ }              B.private void method(int j){ }
C.public int method(int i){ }                D.public float method(float f){ }
E.private String method(String s){ }
3.Q4_2类运行的结果是什么?为什么?若把Q4_2类的第9行改成 Q4_1 q2=new Q4_2();  结果是多少?为什么?若把第11行改成 ((Q4_2) q2).method(); 结果是多少?为什么?
01:        public class Q4_1{
02:        public void method(int i){
03:        System.out.println(10);
04:}
05:}
06:        public class Q4_2 extends Q4_1{
07:        public static void main(String args{}){
08:        Q4_1 q1=new Q4_1();      
09:        Q4_2 q2=new Q4_2();
010:      q1.method(1);    
011:   q2.method(2);
012:}
013:      public void method(int k){
014:      System.out.println(20);
015:}

4.在Q9_1类中应该有哪些构造函数?
public class Q9_2 extends Q9_1{
public Q9_2(int i){ }
public Q9_2(int i,float f){ super(i,f)}
}
A.public Q9_1(){ }                                      B.public Q9_1(int k){ }
C.public Q9_1(int i,float f){ }                      D.public Q9_1(float f){ }

题目:
1.错在哪里?
public class text{
public static void main(String args[]){
A a=new A();
B b=(B) a;
C c=new A();
D d=(D) c;
}
}
class A{}
class B extends A {}
class C extends B {}
class D extends A {}
2.若一个抽象类种所有的方法都是抽象方法时,是不是可以改为接口?

1.两个对象作比较运算时,使用==运算符和equals方法有什么差别?
2.如果让一个类有复制能力,应该用那个接口?
3.如何把一个对象用字符串表示出来?
4.设计一个三角形和矩形类,修改它们的equals方法,如果两个对象面积相同,则equals方法返回true

1.如果有个int[0]型的数组x,你觉得A、B两种循环写法,哪一种比较好?为什么?
A.for(int i=1;i<10;i++)            B.for(int i=0;i<x.length;i++)
2.对象内存回收的顺序和什么有关?
3.可不可以控制何时启动GC?

try{
FileInputStream f=FileInputStream("test.txt");
System.out.println("Open file successed!");
}
catch(FileNotException fe){
System.out.println("File not found!");
}
catch(IOException ie){
System.out.println("IO  exception!");
}
catch(Exception e){
System.out.println("General  Exception!");
}
finally{
System.out.println("Do finally block!");
}
System.out.println("out of try block!");
1.如果第2行代码在运行时出现异常,程序会输出什么结果?
A.Open file successed!                                    B.File not found!
C.IO  exception!                                              D.General  Exception!
E.Do finally block!                                            F.out of try block!
2.接第一题,.如果第2行代码在运行时没有出现异常,程序会输出什么结果?
3.接第一题,.如果代码在运行时出现OutOfMemoryError异常,程序会输出什么结果?
4.f是个File类对象,它有个方法exists,用来检查文件是否存在。下面那一段代码最合适?
A.Exception e=new IOException("File not found!");
if(!exists)
throw e;
B.if(!exists)
throw new IOException("File"+f.getName()+" not found!");
C.if(!exists)
throw new IOException;
D..if(!exists)
throw "File not found!";
E.if(!exists)
throw new IOException();

1.说明Frame使用pack何setSize这两个方法的差别。
2.使用GridBagLayout时,需要设置那几种属性。
3.用GridBagLayout来模拟BorderLayout.
4.用java程学设计出如下的GUI界面。(组建可以设用Button类)
posted @ 2006-03-27 16:49 黑咖啡 阅读(441) | 评论 (0)编辑 收藏
系统国际化最重要的一个方面就是支持多语言。
将中文GB2312转换成UTF-8的方法:

new String(file.getFileName().getBytes(System.getProperty("file.encoding")), "UTF-8")

这里的System.getProperty("file.encoding")是获取系统默认的编码。测试在日文系统下也是可行的。

补充一个UTF-8的转换方法
 1public static String toUtf8String(String s) {
 2  StringBuffer sb = new StringBuffer();
 3  for (int i = 0; i < s.length(); i++{
 4   char c = s.charAt(i);
 5   if (c >= 0 && c <= 255{
 6    sb.append(c);
 7   }
 else {
 8    byte[] b;
 9    try {
10     b = Character.toString(c).getBytes("utf-8");
11    }
 catch (Exception ex) {
12     System.out.println(ex);
13     b = new byte[0];
14    }

15    for (int j = 0; j < b.length; j++{
16     int k = b[j];
17     if (k < 0)
18      k += 256;
19     sb.append("%" + Integer.toHexString(k).toUpperCase());
20    }

21   }

22  }

23  return sb.toString();
24 }
posted @ 2006-03-27 15:46 黑咖啡 阅读(323) | 评论 (0)编辑 收藏
最近工作中发现自己java底子还很差,决定巩固一下.打算就手边的一本《java2 编程指南》展开对java更深入的学习。

不知道是否有更好的学习资料呢?

posted @ 2006-03-27 09:44 黑咖啡 阅读(217) | 评论 (0)编辑 收藏

竟然不知道ERP的全称

记录于下,以备后忘  哈哈!
MRP、MRPⅡ和ERP简介
 
 
MRP、MRPⅡ和ERP,是企业管理信息系统发展的不同阶段。MPR主要对制造环节中的物流进行管理,使企业达到“既要保证生产又要控制库存”的目的;而MRPⅡ则集成了物流和资金流,将人、财、物,时间等各种资源进行周密计划,合理利用,以提高企业的竞争力;ERP的概念则由Garter Group率先提出,它将供应链、企业业务流程和信息流程都囊括其中。由于ERP的概念流传最广,现在已经成为企业管理信息系统的代名词。


现将有关信息化管理术语介绍如下:


MRP(material requirement planning)物料需求计划


MRPⅡ(manufacturing resource planning)制造企业资源计划


ERP(enterprise resource planning)企业资源计划


MIS(management information system)管理信息系统


OA(office automation)办公自动化


BRP(business process reengineering)业务流程优化


CRM(customer relationship management)客房关系管理


EIP(enterprise information portal)企业信息门户


EDI(electronic data interchange)电子数据交换


HRM(human resource management)人力资源管理


KM(knowledge management)知识管理


SCM(supply chain management)供应链管理


EAI(enterprise application integration)企业应用集成

 


 

posted @ 2006-03-22 10:39 黑咖啡 阅读(138) | 评论 (0)编辑 收藏
祝自己狗年,进步大大!
posted @ 2006-02-05 10:29 黑咖啡 阅读(120) | 评论 (0)编辑 收藏
仅列出标题
共2页: 上一页 1 2 

<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

留言簿(2)

随笔分类(67)

文章分类(43)

Good Article

Good Blogs

Open Source

最新随笔

最新评论

阅读排行榜

评论排行榜