爪哇东南的自留地

学习探讨开源和web开发

导航

<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

统计

常用链接

留言簿(1)

随笔分类

随笔档案

相册

收藏夹

life

technique

搜索

最新评论

阅读排行榜

评论排行榜

#

java 基本试题

1.通过什么参数分配Java内存使用?
java -Xms128m -Xmx512m

2.Treemap和Hashmap区别是什么?
TreeMap对Key进行排序,而HashMap不排序。HashMap通过hashcode对其内容进行快速查找, 而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该 使用TreeMap(HashMap中元素的排列顺序是不固定的)。

3.为何加入:private static final long serialVersionUID?
可以利用JDK的bin目录下的serialver.exe工具产生。
序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持 对象的唯一性。在java中serialVersionUID是唯一控制着能否反序列化成功的标志, 只要这个值不一样,就无法反序列化成功。

4.JSP编译和执行原理?
JSP文件的Scriptlets在编译后将被包含于该JSP servlet的service()方法。当JSP引擎处理客户端请求时,JSP Scriptlets在被请求的时候被执行。如果scriptlet产生输出,输出将在out (JSPWriter)对象中进行缓存然后最终发送到客户端。

5.怎么解决JSP/Servlet web中中文乱码的问题

6.JDBC中,statement,prepared statement ,Callable statement的区别是什么?
Statement 接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法;而 CallableStatement 添加了处理 OUT 参数的方法。
PreparedStatement:对于同一条语句的多次执行,Statement每次都要把SQL语句发送给数据
库,这样做效率明显不高,而如果数据库支持预编译,PreparedStatement可以先把要执行的语句一次发给它,然后每次执行而不必发送相同的语句,效率当然提高,当然如果数据库不支持预编译,
PreparedStatement会象Statement一样工作,只是效率不高而不需要用户工手干预.
    另外PreparedStatement还支持接收参数.在预编译后只要传输不同的参数就可以执行,大大
提高了性能.
CallableStatement:是PreparedStatement的子类,它只是用来执行存储过程的.

7.什么情况下会抛出“打开游标超过最大数”的异常?

8.XML解析中:SAX和DOM的不同点有哪些?

9.抽象类和接口的区别?

10.什么是中间件

11.JSP的内置对象有那些?
Out, request, response, application, session, exception, config, page, pageContext.

12.有那些方法能防止、化解对web网站的攻击?
13.如何提高访问web网站的速度?
14.Java可采用的MVC框架技术有哪些?他们的特征和适用环境如何?
Struts, WebWork, Spring, JSF…

15.MVC的优缺点是什么,适用范围如何?
MVC开发模式分离数据访问层和数据表现层,并使开发人员开发一个可伸缩性的强、便于扩展的控制器,来维护整个流程。
16.TOMCAT配置中,有关安全的设置选项有哪些?
17.Apach与Tomcat配合使用,是为解决什么问题?怎么实现?运行过程如何?


18.Collection的四个接口
add();
addAll();
isEmpty();
iterator();
contains();

19.Cookie
20.多态
21.Web上参数的传输方式
22.HashTable和HashMap的区别
Hashtable和HashMap类有三个重要的不同之处。第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。
23.运行环境中的GC

24.final,finally,finalzie的区别
final:
final可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能,这些特点使final在Java中拥有了一个不可或缺的地位,也是学习Java时必须要知道和掌握的关键字之一。
final成员
当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,二是在构造函数中,两者只能选其一。
还有一种用法是定义方法中的参数为final,对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。
final方法
将方法声明为final那有两个原因,第一就是说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。第二就是允许编译器将所有对此方法的调用转化为inline(行内)调用的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。
final类
当你将final用于类身上时,你就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员,你可以定义其为final,也可以不是final。而对于方法,由于所属类为final的关系,自然也就成了final型的。你也可以明确的给final类中的方法加上一个final,但这显然没有意义。

finally:
finally 关键字是对 Java 异常处理模型的最佳补充。 finally 结构使代码总会执行,而不管有无异常发生。使用 finally 可以维护对象的内部状态,并可以清理非内存资源。如果没有 finally,您的代码就会很费解。例如,下面的代码说明,在不使用 finally 的情况下您如何编写代码来释放非内存资源:

finalize:
根据Java语言规范,JVM保证调用finalize函数之前,这个对象是不可达的,但是JVM不保证这个函数一定会被调用。另外,规范还保证finalize函数最多运行一次。
通常,finalize用于一些不容易控制、并且非常重要资源的释放,例如一些I/O的操作,数据的连接。这些资源的释放对整个应用程序是非常关键的。在这种情况下,程序员应该以通过程序本身管理(包括释放)这些资源为主,以finalize函数释放资源方式为辅,形成一种双保险的管理机制,而不应该仅仅依靠finalize来释放资源。

posted @ 2006-09-13 20:18 ericli 阅读(373) | 评论 (0)编辑 收藏

富客户端技术(之一)   FCKEditor   最流行的文本编辑器

     C/S体系结构采用了开放的模式在一定的程度上解决了人们对联机办公等的网络应用需求,导致了胖客户端应用(fat clients)流行。
    随着人们对网络应用需求的进一步深入,B/S结构的网络应用又随之诞生了,这种结构的网络应用又称为瘦客户端应用,只要通过Web浏览器,各种处理任务都可以调用系统资源来完成,这样大大简化了客户端,减轻了系统维护与升级的成本和工作量,降低了用户的总体拥有成本(TCO)。
    今天的网络应用需要从“什么都用Web浏览器”到“根据情况采用强化客户端技术”进行本质的转变。人们需要更为复杂而精美的应用交互界面,发布和表现多种复杂形式的多媒体和内容,对形式多样而丰富的信息内容进行更好的组织和表现,而这些正是目前广泛应用的B/S结构所不能达到的,于是富客户端技术应运而生。
   作为开源的j2ee技术中涉及到view层的富客户端是一种趋势,而今天要介绍就是其中的一个简单的开源技术FCKEditor,运用它,可以在你的的页面展示出类似word页面的效果,而且无须安装,只需要在你的项目中引入相关的jar文件,在需要控件的地方适当的调用就可以了。
   下面我做一个简单的演示给大家
   1.首先,我们先去了解一下FCKEditor   http://www.fckeditor.net/
   英文介绍简单明了:
   This HTML text editor brings to the web many of the powerful functionalities of desktop editors like MS Word.
It's lightweight and doesn't require any kind of installation on the client computer.  
   2.然后去下载相关的文件,这里我下载的是FCKeditor_2.3.1.zip文件
   3.解压文件,本人使用的jsp页面,还需要下载 FCKeditor.Java 的相关文件
   4.从sample01.jsp开始,使用中来体会学习
************************************jsp页面*********************************************
 
<%@ page language="java" import="com.fredck.FCKeditor.*" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
 <head>
  <title>FCKeditor - JSP Sample</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="robots" content="noindex, nofollow">
  <link href="../sample.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript">

function FCKeditor_OnComplete( editorInstance )
{
 window.status = editorInstance.Description ;
}

  </script>
 </head>
 <body>
  <h1>FCKeditor - JSP - Sample 1</h1>
  This sample displays a normal HTML form with an FCKeditor with full features
  enabled.
  <hr>
<!--  自己的 action 方式  -->
  <form action="sampleposteddata.jsp" method="get" target="_blank">
<%
//以下是修改的关键
FCKeditor oFCKeditor ;
oFCKeditor = new FCKeditor( request, "EditorDefault" ) ;//初始化的一些配置,第二个参数EditorDefault就是这个字段的名称
oFCKeditor.setBasePath( "/FCKeditor/" ) ;//为了寻找相应的frame页面:fckeditor.html;同时传递参数;这里设置为我们需要的路径!
//oFCKeditor.setBasePath( "/nhoa/FCKeditor/" ) ;//我的例子,就是指明你的文件放在哪个目录下
oFCKeditor.setValue( "ligang's example!" );//初始化页面显示的数据
out.println( oFCKeditor.create() ) ;//建立吧,看源码很简单!
%>
   <br>
   <input type="submit" value="Submit">
  </form>
 </body>
</html>
************************************jsp页面***********************************

使用步骤:
(1)项目中import 这个包包:fckEditor.jar(将src的java代码打包),需要看源码也可以!
(2)修改你的jsp页面,在需要添加该效果的地方模仿以上jsp页面进行修改
(3)想想,好象没有什么事了!
(4)试试吧!
5.分析实现原理
主要就是oFCKeditor.create() ,通过这个方法建立控件,在源代码中可以看见
public String create() {
  StringBuffer strEditor=new StringBuffer();
  
  strEditor.append("<div>");
  String encodedValue=HTMLEncode(value);

   if(isCompatible()) { //浏览器版本符合要求产生我们的控件
   strEditor.append("<input type=\"hidden\" id=\"" + instanceName + "\" name=\"" + instanceName + "\" value=\"" + encodedValue + "\">");
  
   strEditor.append(createConfigHTML());
   strEditor.append(createIFrameHTML());
  
  }
  else{//浏览器版本不符合要求,产生一个textarea,呵呵,也不失是一种弥补的方式
   strEditor.append("<TEXTAREA name=\"" + instanceName + "\" rows=\"4\" cols=\"40\" style=\"WIDTH: " + width + "; HEIGHT: " + height + "\" wrap=\"virtual\">"+encodedValue+"</TEXTAREA>");
  }
  strEditor.append("</div>");
  return strEditor.toString();
 }
   其实就是一个servelt向浏览器写一些html语句,其中的createConfigHTML()就是通过配置文件config.js向控件传递一些参数,在页面是通过hidden域来传递的,但是自己没有找到这个文件的位置,希望明白的朋友可以告诉我......
createIFrameHTML()就是建立控件的方法,其中最重要的一个参数就是sLink,
String sLink=basePath + "editor/fckeditor.html?InstanceName=" + instanceName;它指明了控件数据的名称就是instanceName,它有时在那里被用户初始化的呢,呵呵,是在构造方法里面,FCKeditor 类有一个构造方法
 public FCKeditor(HttpServletRequest req, String parInstanceName){
  request=req;
  basePath = request.getContextPath() + "/FCKeditor/";
  instanceName=parInstanceName;
  oConfig = new FCKeditorConfigurations() ;
 }
我们在jsp页面上,看到
oFCKeditor = new FCKeditor( request, "EditorDefault" ) ;//初始化的一些配置,第二个参数EditorDefault就是这个
变量
6.到这里,需要我们试用者了解的部分就这些了,剩下的工作就是控件自己实现了,呵呵,真的很简单啊
总结:
使用就要做两件事情:import fckEditor.jar,这个jar包是我自己通过开源的代码自己编译后打的
还有就是在需要的地方添加代码,注意两个地方,一个是选取合适的构造函数和构造函数参数,还有就是
设定好自己项目摆放FCKeditor文件的目录,基本没有什么问题,今天在工作的项目上使用了一下没有什么问题.

posted @ 2006-09-13 20:14 ericli 阅读(3752) | 评论 (4)编辑 收藏

tomcat 4.1.30启动过程的源码分析

前几天为了解决sinpool兄的《多线程的问题。》一帖,专门看了一下tomcat 4.1.30的源码,
其中重点研究了tomcat的启动这一部分,个人感觉tomcat的源码还是写的很清楚易懂,值得一看。
(以前看过struts的部分代码,感觉也比较经典)    
然后我看后的代码整理了一下,附在下面,希望对其他人有用,也希望感兴趣的兄弟可以多看看好的代码,
肯定对自己的程序设计和代码质量颇有益处。

一. 启动类(包含main()方法的类):
org.apache.catalina.startup.Bootstrap
这个类是tomcat的启动类,主要按照如下步骤,进行主要的启动工作:
1. 创建3个ClassLoader:common,catalina和share,它们对应tomcat的3个Classloader,我想对tomcat
的classloader有研究的兄弟对这个肯定不陌生,其中common classloader是紧跟在系统的classloader(也就是
系统环境变量中设置的CLASSPATH所对应的classloader),而catalina classloader是common的子classloader,是tomcat
运行所需要的类的classloader,而shared classloader也是common的子classloader,是和catalina平级的classloader,
之所以说是shared classloader,是因为它是所有tomcat下面发布的webapp classloader(每一个web app都有一个自己的classloader)
的父classloader。它们这3个classloader分别读取tomcat home下面的common, server和shared三个目录里面的classes和lib目录,
用于初始化自己所控制的类库和资源。

2. 创建启动一个的org.apache.catalina.startup.Catalina类的实例,并调用它的process方法,这里使用的是java的reflection技术。
然后调用这个实例的process方法,并把Bootstrap接受到的命令行参数传递进去了,这里Bootstrap类并没有解析传给它的命令行参数。
当然在调用process之前还使用setParentClassLoader方法设置了一下父classloader。这里简单介绍一下有关classloader的一个重要
特性,就是如果classloader要load一个类时,不是自己先找,而是先把这个任务委派给自己的父classloader,然后自己的父classloader
也不找,在把这个任务委派给自己的父classloader,直到找到最顶层的classloader,然后再自顶向下的找对应的这个要load的类的定义,
如果那个classloader先找到,就返回。所以接合上面第一点介绍的tomcat中3个classloader,大家就可以明白tomca的classloader找类
的顺序了,这个对程序开发人员来说特别重要。我想使用过tomcat或者其他app server的兄弟肯定碰到过一个类明明存在可就是找不到,
或者总是找到一个老的版本,我想主要是在多个地方放置的原因,或者哪里有重名的类:-)

二.org.apache.catalina.startup.Catalina类
现在程序转到org.apache.catalina.startup.Catalina类里面的process方法。
这个方法首先设置一下catalina的home和base目录,然后通过arguments方法解析命令行参数,
最后调用execute()方法启动server。而execute方法很简单,就是根据arguments解析的命令行参数,
决定是启动server,还是stop server,如果是start server,就调用start方法,而下面重点讲一下这个start()方法,
因为才算是一个真正开始的启动tomcat的地方:-)
1. start方法首先使用Digester(这个东东是jakarta commons里面的一个用于解析xml文件的工具包,一开始是专门用于解析struts配置文件的,
后来被抽象成现在的一个通用工具,主要还是用来解析xml配置文件,根据一些定义的rule自动生成对应的类的实例,具体信息可以参考
apache网站上的文档)来设置tomcat配置文件,也就是/conf/server.xml这个文件的解析规则
然后通过如下代码来将配置文件中的数据转化成内存中的实例:

代码:
        File file = configFile();

        try {

            InputSource is =

                new InputSource("file://" + file.getAbsolutePath());

            FileInputStream fis = new FileInputStream(file);

            is.setByteStream(fis);

            digester.push(this);

            digester.parse(is);

            fis.close();

        } catch (Exception e) {

            System.out.println("Catalina.start: " + e);

            e.printStackTrace(System.out);

            System.exit(1);

        }   
    
 


转换的规则如下(我只作一些简单的介绍),例如配置文件中的
a. Server对应可以产成一个org.apache.catalina.core.StandardServer类(这个类很重要,是tomcat server的实现)
b. Server/GlobalNamingResources对应生成org.apache.catalina.deploy.NamingResources类
而大家比较熟悉的监听8080端口的类配置如下:
c. Server/Service/Connector:org.apache.catalina.connector.http.HttpConnector
d. Server/Service/Engine/Host/Context/:org.apache.catalina.core.StandardContext
有兴趣的兄弟可以参考jakarta commons里面的Digester文档和org.apache.catalina.startup.Catalina
这个类里面的createStartDigester方法.
在这段代码之后,一个叫server的变量已经通过Digester工具生成了,它将会用于启动tomcat。
2. 然后程序进行了一些server启动前的设置工作,例如重定向log输出流等等。而server启动的代码如下:

代码:
        // Start the new server

        if (server instanceof Lifecycle) {

            try {

                server.initialize();

                ((Lifecycle) server).start();

                try {

                    // Register shutdown hook

                    Runtime.getRuntime().addShutdownHook(shutdownHook);

                } catch (Throwable t) {

                    // This will fail on JDK 1.2. Ignoring, as Tomcat can run

                    // fine without the shutdown hook.

                }

                // Wait for the server to be told to shut down

                server.await();

            } catch (LifecycleException e) {

                System.out.println("Catalina.start: " + e);

                e.printStackTrace(System.out);

                if (e.getThrowable() != null) {

                    System.out.println("----- Root Cause -----");

                    e.getThrowable().printStackTrace(System.out);

                }

            }

        }

    
 


其中server这个变量就是在刚才Digester解析时创建好的。
(当时这个地方我看了很长时间,后来才发现是这样的,因为以前不太了解Digester这个东东)。
然后大家可以看到server启动主要是分3步:
1. initialize方法进行server启动的初始化操作
2. start方法启动server,主要是server中的的service和service中的connector
3. await方法等待server shutdown
其中我重点给大家介绍一下initialize方法和start方法
initialize方法:
这里面只有一个主要任务,就是逐次调用server中所有定义的service的initialize方法,
而每个service的initialize方法中调用这个service中定义的所有connector的initialize方法,
而connector的initialize方法则是创建一个serversocket用于接受客户端的请求就结束了。
如果大家看一下tomcat下面conf/server.xml,就可以发现,tomcat默认只定义了一个service叫做Tomcat-Standalone,
而下面只有默认定义了3个connector:
1. 8080端口的http connector
2. 8443端口的http ssl connector
3. 8009端口的Coyote/JK2 AJP 1.3 Connector
我想大家对这3个端口一定不陌生吧。
start方法:
这个方法里面有一个tomcat很重要,也是我认为tomcat设计对一个亮点,就是Lifecycle这个东东,它很象一个bus(总线)。
我想大家进行过程序设计的一定知道,开始设计的时候总要根据一个原则分出几个模块来,是为了代码分块,或者将
一部分功能相似的代码组织成一个模块,这样比较清楚,例如一个进销存系统会有采购,销售,库存和财务等模块,但是
我想很多人也碰到过这样的情况就是虽然分了模块但是如果在开发完毕以后,另外一个客户说只想要其中的销售模块,我想
大部分的开发人员肯定傻眼,因为虽然当时设计的时候分了模块,但是这些模块编写的时候却是交织在一起,互相的接口定义
很模糊,基本上都是直接调用另一个模块的方法,这样肯定分不开。而tomcat的这个Lifecycle的设计理念就可以解决这个问题的
一部分,它的原理就象是一个bus(总线),例如一个模块做完一个动作以后,例如销售模块创建好一个订单后,本来要直接调用
库存模块的api锁住一部分库存(我只是随便举个例子,实际业务不一定是这样),这样销售模块就需要依赖库存模块了。但是使用了
bus方式。我们就可以在订单创建后,向bus上发送一个订单创建的消息,而总线有一个事件注册机制,有点象swing的event,listener,
例如库存模块有一个listener专门用于监听订单创建的消息,进行处理,这样2个模块就互不依赖了。有兴趣的兄喜可以看看jcp上面
的一个叫做infobus的专题。
当然这个方式只是解决有效降低模块偶合度的一个方面(因为有的时候必须要直接调用另外一个模块的接口,
例如库存模块一定要直接缺德一个销售订单的信息,那么就需要定义一个接口类来描述订单的详细信息啦,这里就不具体解释了,
有空可以专门发个帖子跟大家探讨这个问题:-) ),就是不要显式触发另一个模块的某个动作,而是通过bus机制来发送消息,
而每个模块都有一个自己的handler,会监听bus,对自感兴趣的事件进行处理。tomcat的Lifecycle就是这个东西。
下面再回到start方法:
1. 它首先向总线发送了2个事件:BEFORE_START_EVENT和START_EVENT
2. 然后调用每个service的start方法,最后发送AFTER_START_EVENT消息通知其他程序
而service的start方法主要进行的动作如下:
1. 发送BEFORE_START_EVENT消息
2. 调用container的start方法
3. 然后调用connector的start方法
4. 最后发送AFTER_START_EVENT消息.
而connector的start方法就是大家最熟悉的socket编程了,大家可以参看org.apache.catalina.connector.http.HttpConnector这个类,
主要是使用java里面的多线程操作,初始化一个HttpProcessor的线程池,然后通过wait方法阻塞住每个HttpProcessor线程,只有
当接受到一个http请求时,在通过notify方法激活HttpProcessor线程,让其处理用户的http请求。

到此为止主要简单介绍了一下tomcat 4.1.30的启动过程,下次有机会的话,可以再看看它的webapp的deploy的管理部分的代码,然后和大家分享。如果大家对我写的帖子有什么意见的话,也欢迎批评指正,希望感兴趣的兄弟可以一起探讨:-) 废话不说了,很晚了该睡觉了,祝大家周一工作愉快

posted @ 2006-09-13 20:12 ericli 阅读(224) | 评论 (0)编辑 收藏

仅列出标题
共2页: 上一页 1 2