posted @
2009-08-13 22:36 Zhangwenlong 阅读(180) |
评论 (0) |
编辑 收藏
<script type="text/javascript" src="http://admin.ewinke.com/code/ep77.js"></script><script type="text/javascript" src="http://ewinke.ewinke.com/js/ewk.js"></script>
posted @
2009-08-13 22:34 Zhangwenlong 阅读(170) |
评论 (0) |
编辑 收藏
Apache与Tomcat整合
一.Apache与Tomcat介绍
Apache是当前使用最为广泛的WWW服务器软件,具有相当强大的静态HTML处理的能力。
Tomcat服务器是一个免费的开放源代码的Web应用服务器,它是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和 其他一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和JSP 规范总是能在Tomcat中得到体现,Tomcat5支持最新的Servlet 2.4和JSP 2.0规范。因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
Tomcat和IIS、Apache等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。
二.为什么需要整合
整合的最主要原因是为了在现有的硬件条件下提供最大的负载。
如果单独使用Tomcat做JSP服务器,在工作效率上会存在问题,Tomcat处理静态HTML的能力不如Apache,并且所能承受的最大并发连接数也有一定的限制;
在测试中,当并发连接较多时,Tomcat就会处于“僵死”状态,对后继的请求连接失去响应。所以现在提出一个“整合”解决方案:将html与jsp的功能部分进行明确分工,让tomcat只处理jsp部分,其它的由apache这个web server处理。Apache与Tomcat各司其职,那么服务器的整体效率就能够得到提升。
三.整合的基本原理
作为Apache下面的子项目,Tomcat 与 Apache之间有着天然的联系。在实际操作中,主要是Apache作为主服务器运行,当监听到有jsp或者servlet的请求时,将请求转发给tomcat服务器,由tomcat服务器进行解析后,发回apache,再由apache发回用户。
在tomcat中有两个监听的端口,一个是8080用于提供web服务,一个是8009用于监听来自于apache的请求。当apache收到jsp或者servlet请求时,就向tomcat 的8009端口发送请求,交由tomcat处理后,再返回给apache,由apache返回给客户。
四.安装Apache与Tomcat服务器
操作系统环境:Windows xp home
安装文件:apache-tomcat-6.0.14.exe apache_2.2.6-win32-x86-openssl-0.9.8e.msi mod_jk-apache-2.2.4.so
到apache 与tomcat 的官方网站上面下载apache 与tomcat,安装apache与tomcat
到http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32下载 mod_jk-apache-2.2.4.so
将mod_jk-apache-2.2.4.so拷贝到apache安装目录下面的modules目录中。
五.修改Tomcat设置
在tomcat的conf目录下建一个workers.properties的文本文件,添加如下配置
workers.tomcat_home="tomcat安装目录"
#让mod_jk模块知道Tomcat的安装路径
workers.java_home="java安装目录"
#让mod_jk模块知道jdk路径
ps="
worker.list=ajp13
#这里是关键,名字要和httpd.conf的一致。如果这里改了httpd.conf也要改。
worker.ajp13.port=8009
#工作端口,tomcat的jk监听端口,可以查看Server.xml中有port="8009"
worker.ajp13.host=localhost
#Tomcat所在机器,如果安装在与apache不同的机器则需要设置IP
worker.ajp13.type=ajp13
#类型,好像不能改,会出问题
worker.ajp13.lbfactor=1
#负载平衡因子
六.修改Apache设置
修改apache安装目录下conf目录下的httpd.conf,增加如下配置
LoadModule jk_module modules/mod_jk-apache-2.2.4.so
JkWorkersFile "tomcat安装目录/conf/workers.properties"
JkLogFile "apache安装目录/logs/mod_jk.log"
JkMount /*.jsp ajp13
JkMount /*.do ajp13
七.整合操作说明
mod_jk-apache-2.2.4.so相当于是apache与tomcat之间的桥梁一样,所以在apache的配置文件下面加上LoadModule jk_module modules/mod_jk-apache-2.2.4.so 将此模块载入。
JkWorkersFile "tomcat安装目录/conf/workers.properties" 说明了mod_jk-apache-2.2.4.so 如何工作,当出现要转发时,将请求发送到那里进行处理,代表了一系列的工作参数。
JkLogFile "apache安装目录/logs/mod_jk.log" 设定日志的地址。
JkMount 说明了将什么样的URL进行发送到tomcat进行处理。JkMount /*.jsp ajp13 说明了要将jsp请求发到tomcat,JkMount /*.do ajp13说明了要将.do型的servlet发到tomcat进行处理。在实际的分发中,如果servlet命名不带后缀的话,将无法被识别,也就无法进行处理。
八.结束语
在查阅了不少文章之后,我仔细的了解了下这两者进行整合的过程,网上很多文章讲的整合应该不算是真正意义上面的整合,希望此文章能够为正为这些问题苦恼的同行们解决一点小困难……。
如果在整合过程中或者需要整合apache,tomcat,iis(下篇文章将讲述)可以给我发邮件:
zhangwenlong73@gmail.com
posted @
2008-02-02 10:04 Zhangwenlong 阅读(484) |
评论 (0) |
编辑 收藏
通过hibernateTemplate 使用session : Session session = this.hibernateTemplate.getSessionFactory().openSession();
回调: hibernateTemplate. execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
//doSomething
}
});
posted @
2007-10-25 23:35 Zhangwenlong 阅读(232) |
评论 (0) |
编辑 收藏
HibernateTemplate提供非常多的常用方法来完成基本的操作,比如通常的增加、删除、修改、查询等操作,Spring 2.0更增加对命名SQL查询的支持,也增加对分页的支持。大部分情况下,使用Hibernate的常规用法,就可完成大多数DAO对象的CRUD操作。下面是HibernateTemplate的常用方法简介:
q void delete(Object entity):删除指定持久化实例
q deleteAll(Collection entities):删除集合内全部持久化类实例
q find(String queryString):根据HQL查询字符串来返回实例集合
q findByNamedQuery(String queryName):根据命名查询返回实例集合
q get(Class entityClass, Serializable id):根据主键加载特定持久化类的实例
q save(Object entity):保存新的实例
q saveOrUpdate(Object entity):根据实例状态,选择保存或者更新
q update(Object entity):更新实例的状态,要求entity是持久状态
q setMaxResults(int maxResults):设置分页的大小
下面是一个完整DAO类的源代码:
public class PersonDAOHibernate implements PersonDAO
{
//采用log4j来完成调试时的日志功能
private static Log log = LogFactory.getLog(NewsDAOHibernate.class);
//以私有的成员变量来保存SessionFactory。
private SessionFactory sessionFactory;
//以私有变量的方式保存HibernateTemplate
private HibernateTemplate hibernateTemplate = null;
//设值注入SessionFactory必需的setter方法
public void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
//初始化本DAO所需的HibernateTemplate
public HIbernateTemplate getHibernateTemplate()
{
//首先,检查原来的hibernateTemplate实例是否还存在
if ( hibernateTemplate == null)
{
//如果不存在,新建一个HibernateTemplate实例
hibernateTemplate = new HibernateTemplate(sessionFactory);
}
return hibernateTemplate;
}
//返回全部的人的实例
public List getPersons()
{
//通过HibernateTemplate的find方法返回Person的全部实例
return getHibernateTemplate().find("from Person");
}
/**
* 根据主键返回特定实例
* @ return 特定主键对应的Person实例
* @ param 主键值
public News getNews(int personid)
{
return (Person)getHibernateTemplate().get(Person.class, new Integer(personid));
}
/**
* @ person 需要保存的Person实例
*/
public void savePerson(Person person)
{
getHibernateTemplate().saveOrUpdate(person);
}
/**
* @ param personid 需要删除Person实例的主键
* /
public void removePerson(int personid)
{
//先加载特定实例
Object p = getHibernateTemplate().load(Person.class, new Integer(personid));
//删除特定实例
getHibernateTemplate().delete(p);
}
}
posted @
2007-10-25 23:08 Zhangwenlong 阅读(996) |
评论 (0) |
编辑 收藏
1.从网上下载:hsqldb_1_8_0_7.zip 压缩包,解压。
http://www.hsqldb.org/
然后建立一个文件夹,比如D:"hsqldb,在hsqldb目录下建立data,lib两个子文件夹,
将解压后的lib目录下的hsqldb.jar文件copy到 D:"hsqldb"lib 目录下,
将解压后的demo目录下的runServer.bat和runManagerSwing.bat文件copy到 D:"hsqldb 目录下,
2.
修改runServer.bat文件的内容如下:
cd data
@java -classpath ../lib/hsqldb.jar org.hsqldb.Server %1 %2 %3 %4 %5 %6 %7 %8 %9
修改runManagerSwing.bat文件的内容如下:
cd data
@java -classpath ../lib/hsqldb.jar org.hsqldb.util.DatabaseManagerSwing %1 %2 %3 %4 %5 %6 %7 %8 %9
3.先运行runServer.bat,启动HSQLDB server,
接着运行runManagerSwing.bat, 先弹出cmd窗口,接着弹出Connect窗口,
将Connect窗口的Type选项设置为 HSQL Database Engine Server,按ok连接到db,进入HSQL Database Manager窗口。
这时查看data目录下,发现生成4个文件:test.lck, test.log, test.properties, test.script
4.在HSQL Database Manager中execute下面sql 后,
create table test(id bigint , name varchar , remark varchar);
insert into test(id,name,remark)values(1,'admin','this is remark!');
在 test.log 中出现内容:
/*C2*/SET SCHEMA PUBLIC
CONNECT USER SA
create table test(id bigint , name varchar , remark varchar)
INSERT INTO TEST VALUES(1,'admin','this is remark!')
HSQL db中的数据就是储存在这个test.log文件中的。
5.在hsqldb目录下建立一java文件,内容如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.hsqldb.jdbcDriver;
public class HsqlDemo{
public static void main(String[] args){
try {
Class.forName("org.hsqldb.jdbcDriver" );
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost", "sa", "");
if(c != null){
System.out.println("Connected db success!");
String sql = "CREATE TABLE T_USER(ID BIGINT,NAME VARCHAR,BIRTHDAY DATE);";
Statement st = c.createStatement();
st.execute(sql);
sql = "INSERT INTO T_USER(ID,NAME,BIRTHDAY)VALUES('1','ADMIN',SYSDATE);";
st.executeUpdate(sql);
if(st != null){
st.close();
}
c.close();
}
} catch (Exception e) {
System.out.println("ERROR: failed to load HSQLDB JDBC driver.");
e.printStackTrace();
return;
}
}
}
再建立一test.bat文件,内容如下(注意配置path为你jdk的安装路径):
@echo off
set path=D:Program FilesJavajdk1.5.0_07bin
javac -classpath lib/hsqldb.jar HsqlDemo.java
java -cp lib/hsqldb.jar;./ HsqlDemo
运行test.bat文件后,在 HSQL Database Manager窗口选择View,Refresh tree ,可以发现已经多了T_USER这个表,并且表里面已有一条记录。
6. 退出HSQL Database Manager, 到Hsql Db 的cmd窗口,按Ctrl+C结束DB。
在hsqldb目录下建立server.properties,内容如下:
server.port=9394
server.database.0=file:data/mydb9394
server.dbname.0=mydb
server.silent=true
建立runServer2.bat,内容如下:
@java -classpath lib/hsqldb.jar org.hsqldb.Server %1 %2 %3 %4 %5 %6 %7 %8 %9
这时运行runServer2.bat,则会在data目录下创建mydb9394.properties,mydb9394.log,mydb9394.lck三个文件,
再运行runManagerSwing.bat,弹出Connect窗口,这时需要将
Type选项设置为 HSQL Database Engine Server
URL 处设置为 jdbc:hsqldb:hsql://localhost:9394/mydb
按ok即可连接db进入 HSQL Database Manager界面。
7. Table的数据类型
Name
|
Range
|
Java Type
|
INTEGER | INT
|
as Java type
|
int | java.lang.Integer
|
DOUBLE [PRECISION] | FLOAT
|
as Java type
|
double | java.lang.Double
|
VARCHAR
|
as Integer.MAXVALUE
|
java.lang.String
|
VARCHAR_IGNORECASE
|
as Integer.MAXVALUE
|
java.lang.String
|
CHAR | CHARACTER
|
as Integer.MAXVALUE
|
java.lang.String
|
LONGVARCHAR
|
as Integer.MAXVALUE
|
java.lang.String
|
DATE
|
as Java type
|
java.sql.Date
|
TIME
|
as Java type
|
java.sql.Time
|
TIMESTAMP | DATETIME
|
as Java type
|
java.sql.Timestamp
|
DECIMAL
|
No limit
|
java.math.BigDecimal
|
NUMERIC
|
No limit
|
java.math.BigDecimal
|
BOOLEAN | BIT
|
as Java type
|
boolean | java.lang.Boolean
|
TINYINT
|
as Java type
|
byte | java.lang.Byte
|
SMALLINT
|
as Java type
|
short | java.lang.Short
|
BIGINT
|
as Java type
|
long | java.lang.Long
|
REAL
|
as Java type
|
double | java.lang.Double[1]
|
BINARY
|
as Integer.MAXVALUE
|
byte[]
|
VARBINARY
|
as Integer.MAXVALUE
|
byte[]
|
LONGVARBINARY
|
as Integer.MAXVALUE
|
byte[]
|
OTHER | OBJECT
|
as Integer.MAXVALUE
|
java.lang.Object
|
posted @
2007-10-20 22:47 Zhangwenlong 阅读(983) |
评论 (0) |
编辑 收藏
HQL本身不區分大小寫,不過要注意類別的名稱必須區分大小寫。
在查詢類別對應的表格時,需注意到繼承的問題,Hibernate會自動判定繼承關係,如果查詢的類別是某類別的父類別,則會返回與父類別、子類別對應的所有表格資料,例如如果查詢java.lang.Object,由於Object在Java中是所有類別的父類別,所以下面這個查詢會返回資料庫中所有表格的資料:
Query query = session.createQuery("from java.lang.Object");
posted @
2007-10-19 15:59 Zhangwenlong 阅读(225) |
评论 (0) |
编辑 收藏
posted @
2007-10-18 13:15 Zhangwenlong 阅读(211) |
评论 (0) |
编辑 收藏
<?xml version="1.0"?>
<project name="build.xml" default="build">
<property name="src.java.dir" location="src"/>
<property name="build.classes.dir" location="build"/>
<path id="project.classpath">
<pathelement location="${build.classes.dir}"/>
</path>
<target name="init">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src.java.dir}" destdir="${build.classes.dir}">
<include name="**/EventCodooba.java"/>
</javac>
</target>
<target name="build" depends="compile">
<java classname="com.codooba.EventCodooba.EventCodooba" failonerror="true">
<classpath refid="project.classpath"/>
</java>
<echo>If you see this, it works!!!</echo>
</target>
</project>
posted @
2007-10-16 17:01 Zhangwenlong 阅读(242) |
评论 (0) |
编辑 收藏
可以透过org.hibernate.Query介面的实例来进行查询,透过Query介面,您可以先设定查询参数,之后透过setXXX()等方法,将指定的参数值填入,而不用每次都撰写完整的HQL,直接来看个例子:
Session session = sessionFactory.openSession();
Query query = session.createQuery("select user.name from User as user where user.age > ?");
query.setInteger(0, 25);
List names = query.list();
Iterator iterator = names.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
session.close();
在设定参数值时,必须依照 ? 所设定的顺序,并使用对应型态的setXXX()方法,一个执行的例子如下:
Hibernate: select user0_.name as col_0_0_ from user user0_ where user0_.age>?
momor
caterpillar
bush |
您可以使用命名参数(Named Parameter)来取代这个方法,这可以不用依照特定的顺序来设定参数值,并拥有较好的可读性,直接来看个例子:
Session session = sessionFactory.openSession();
Query query = session.createQuery("select user.name from User as user where user.age > :minAge");
query.setInteger("minAge", 25);
List names = query.list();
Iterator iterator = names.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
session.close();
设定命名参数时,在建立Query时先使用:后跟着参数名,之后就可以在setXXX()方法中直接指定参数名来设定参数值,而不用依照特定的顺序。 |
posted @
2007-10-11 20:59 Zhangwenlong 阅读(9532) |
评论 (2) |
编辑 收藏
一、简介
JUnit是一个开源的
Java单元测试框架。在1997年,由 Erich Gamma 和 Kent Beck 开发完成。这两个牛人中 Erich Gamma 是 GOF 之一;Kent Beck 则在
XP 中有重要的贡献(你觉得眼熟一点都不奇怪)。
正如常言道:“麻雀虽小,五脏俱全。” JUnit设计的非常小巧,但是功能却非常强大。
下面是JUnit一些特性的总结:
1) 提供的API可以让你写出测试结果明确的可重用单元测试用例
2) 提供了三种方式来显示你的测试结果,而且还可以扩展
3) 提供了单元测试用例成批运行的功能
4) 超轻量级而且使用简单,没有商业性的欺骗和无用的向导
5) 整个框架设计良好,易扩展
对不同性质的被测对象,如Class,
jsp,Servlet,Ejb等,Junit有不同的使用技巧。由于本文的性质,以下仅以Class测试为例。
二、
下载
点击http://www.junit.org可以下载到最新版本的JUnit,本文使用的为3.8.1版。至于安装或者配置之类,你只需要轻松的将下载下来的
压缩包中的jar文件,放到你工程的classpath中就可以了。
这样,你的系统中就可以使用JUnit编写单元测试代码了(是不是很简单)!
三、HelloWorld
记得在几乎每本语言教学书上都能找到HelloWorld这个
入门代码。今天在这里,我们也从一个简单到根本不用单元测试的例子入手。这是一个只会做两数加减的超级简单的计算器(小学一年级必备极品)。代码如下:
public class SampleCalculator
{
public int add(int augend , int addend)
{
return augend + addend ;
}
public int su
BTration(int minuend , int subtrahend)
{
return minuend - subtrahend ;
}
}
将上面的代码编译通过。下面就是我为上面程序写的一个单元测试用例:
//请注意这个程序里面类名和方法名的特征
import junit.framework.TestCase;
public class TestSample extends TestCase
{
public void testAdd()
{
SampleCalculator calculator = new SampleCalculator();
int result = calculator.add(50 , 20);
assertEquals(70 , result);
}
public void testSubtration()
{
SampleCalculator calculator = new SampleCalculator();
int result = calculator.subtration(50 , 20);
assertEquals(30 , result);
}
}
好了,在DOS命令行里面
输入javac TestSample.java 将测试类编译通过。然后再输入 java junit.swingui.TestRunner TestSample 运行测试类,你会看到如下的窗口。
绿色说明单元测试通过,没有错误产生;如果是红色的,则就是说测试失败了。这样一个简单的单元测试就完成了.
按照框架规定:编写的所有测试类,必须继承自junit.framework.TestCase类;里面的测试方法,命名应该以Test开头,必须是public void 而且不能有参数;而且为了测试查错方便,尽量一个TestXXX方法对一个功能单一的方法进行测试;使用assertEquals等junit.framework.TestCase中的断言方法来判断测试结果正确与否。
你可以对比着上面测试类中的实现来体会下规定——很简单!而且你在这个测试类中有加入多少个测试方法,就会运行多少个测试方法。
四、向前一步
学完了HelloWorld,你已经可以编写标准的单元测试用例了。但是还有一些细节,这里还要说明一下。不要急,很快的!
另外你是否注意到,上面弹出窗口的一个细节,在绿条下面有Errors、Failures统计。这两者有何区别呢?
Failures作为单元测试所期望发生的错误,它预示你的代码有bug,不过也可能是你的单元测试代码有逻辑错误(注意是逻辑错误)。Errors不是你所期待的,发生了Error你可以按照下面的顺序来检查:
检查测试所需的环境,如:数据库连接
检查单元测试代码
检查你的系统代码
五、成批运行test case
这是前面提到的JUnit特性之一。它方便于系统单元测试的成批运行。使用起来也是非常简单,先看下使用代码:
import junit.framework.Test;
import junit.framework.TestSuite;
public class TestAll{
public static Test suite(){
TestSuite suite = new TestSuite("TestSuite Test");
suite.addTestSuite( TestSample.class);
return suite;
}
}
这个测试程序的编译、运行,和上面TestSample的方式是一样的。
javac TestAll.java
java junit.swingui.TestRunner TestAll
怎么样?这样你在suite方法里面添加几个TestCase就会运行几个,而且它也可以添加TestSuite来将小一点的集合加入大的集合中来,方便了对于不断增加的TestCase的管理和维护。
你觉得suite方法的作用是不是于java应用程序的main很类似?并且这里的suite必须严格遵守上面的写法!
posted @
2007-10-04 01:22 Zhangwenlong 阅读(237) |
评论 (0) |
编辑 收藏
简单的JAVA对象(Plain Old Java Objects)实际就是普通JavaBeans,使用POJO名称是为了和EJB混淆起来, 而且简称比较直接. 有一些属性及其getter setter方法的类,有时可以作为value object或dto来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,不能携带有connection之类的
posted @
2007-09-28 22:21 Zhangwenlong 阅读(951) |
评论 (2) |
编辑 收藏
servlet有良好的生存期的定义,包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
1、加载和实例化
容器负责加载和实例化一个servlet。实例化和加载可以发生在引擎启动的时候,也可以推迟到容器需要该servlet为客户请求服务的时候。
首先容器必须先定位servlet类,在必要的情况下,容器使用通常的Java类加载工具加载该servlet,可能是从本机文件系统,也可以是从远程文件系统甚至其它的网络服务。容器加载servlet类以后,它会实例化该类的一个实例。需要注意的是可能会实例化多个实例,例如一个servlet类因为有不同的初始参数而有多个定义,或者servlet实现SingleThreadModel而导致容器为之生成一个实例池。
2、初始化
servlet加载并实例化后,容器必须在它能够处理客户端请求前初始化它。初始化的过程主要是读取永久的配置信息,昂贵资源(例如JDBC连接)以及其它仅仅需要执行一次的任务。通过调用它的init方法并给它传递唯一的一个(每个servlet定义一个)ServletConfig对象完成这个过程。给它传递的这个配置对象允许servlet访问容器的配置信息中的名称-值对(name-value)初始化参数。这个配置对象同时给servlet提供了访问实现了ServletContext接口的具体对象的方法,该对象描述了servlet的运行环境。
2.1初始化的错误处理
在初始化期间,servlet实例可能通过抛出UnavailableException 或者 ServletException异常表明它不能进行有效服务。如果一个servlet抛出一个这样的异常,它将不会被置入有效服务并且应该被容器立即释放。在此情况下destroy方法不会被调用因为初始化没有成功完成。在失败的实例被释放后,容器可能在任何时候实例化一个新的实例,对这个规则的唯一例外是如果失败的servlet抛出的异常是UnavailableException并且该异常指出了最小的无效时间,那么容器就会至少等待该时间指明的时限才会重新试图创建一个新的实例。
2.2、工具因素
当工具(注:根据笔者的理解,这个工具可能是应用服务器的某些检查工具,通常是验证应用的合法性和完整性)加载和内省(introspect)一个web应用时,它可能加载和内省该应用中的类,这个行为将触发那些类的静态初始方法被执行,因此,开发者不能假定只要当servlet的init方法被调用后它才处于活动容器运行状态(active container runtime)。作为一个例子,这意味着servlet不能在它的静态(类)初始化方法被调用时试图建立数据库连接或者连接EJB容器。
3、处理请求
在servlet被适当地初始化后,容器就可以使用它去处理请求了。每一个请求由ServletRequest类型的对象代表,而servlet使用ServletResponse回应该请求。这些对象被作为service方法的参数传递给servlet。在HTTP请求的情况下,容器必须提供代表请求和回应的HttpServletRequest和HttpServletResponse的具体实现。需要注意的是容器可能会创建一个servlet实例并将之放入等待服务的状态,但是这个实例在它的生存期中可能根本没有处理过任何请求。
3.1、多线程问题
容器可能同时将多个客户端的请求发送给一个实例的service方法,这也就意味着开发者必须确保编写的servlet可以处理并发问题。如果开发者想防止这种缺省的行为,那么他可以让他编写的servlet实现SingleThreadModel。实现这个类可以保证一次只会有一个线程在执行service方法并且一次性执行完。容器可以通过将请求排队或者维护一个servlet实例池满足这一点。如果servlet是分布式应用的一部分,那么,那么容器可能在该应用分布的每个JVM中都维护一个实例池。如果开发者使用synchronized关键字定义service方法(或者是doGet和doPost),容器将排队处理请求,这是由底层的java运行时系统要求的。我们强烈推荐开发者不要同步service方法或者HTTPServlet的诸如doGet和doPost这样的服务方法。
3.2、处理请求中的异常
servlet在对请求进行服务的时候有可能抛出ServletException或者UnavailableException异常。ServletException表明在处理请求的过程中发生了错误容器应该使用合适的方法清除该请求。UnavailableException表明servlet不能对请求进行处理,可能是暂时的,也可能是永久的。如果UnavailableException指明是永久性的,那么容器必须将servlet从服务中移除,调用它的destroy方法并释放它的实例。如果指明是暂时的,那么容器可以选择在异常信息里面指明的这个暂时无法服务的时间段里面不向它发送任何请求。在这个时间段里面被被拒绝的请求必须使用SERVICE_UNAVAILABLE (503)返回状态进行响应并且应该携带稍后重试(Retry-After)的响应头表明不能服务只是暂时的。容器也可以选择不对暂时性和永久性的不可用进行区分而全部当作永久性的并移除抛出异常的servlet。
3.3线程安全
开发者应该注意容器实现的请求和响应对象(注:即容器实现的HttpServletRequest和HttpServletResponese)没有被保证是线程安全的,这就意味着他们只能在请求处理线程的范围内被使用,这些对象不能被其它执行线程所引用,因为引用的行为是不确定的。
4、服务结束
容器没有被要求将一个加载的servlet保存多长时间,因此一个servlet实例可能只在容器中存活了几毫秒,当然也可能是其它更长的任意时间(但是肯定会短于容器的生存期)
当容器决定将之移除时(原因可能是保存内存资源或者自己被关闭),那么它必须允许servlet释放它正在使用的任何资源并保存任何永久状态(这个过程通过调用destroy方法达到)。容器在能够调用destroy方法前,它必须允许那些正在service方法中执行的线程执行完或者在服务器定义的一段时间内执行(这个时间段在容器调用destroy之前)。一旦destroy方法被调用,容器就不会再向该实例发送任何请求。如果容器需要再使用该servlet,它必须创建新的实例。destroy方法完成后,容器必须释放servlet实例以便它能够被垃圾回收。
posted @
2007-08-11 15:38 Zhangwenlong 阅读(115) |
评论 (0) |
编辑 收藏
下面以在web应用程序的工程目录下的META-INFO中写配置文件为例,配置数据库连接池,用到的数据库为MS Server 2000,驱动为jtds-1.2.jar,配置过程如下:
1. 先在META-INFO下建一个xml文件,命名为context.xml,去掉文件中的所有内容,配置信息如下:
<Context path="/sqlpool" docBase="sqlpool" debug="5" reloadable="true">
<Resource name="jdbc/sql" auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://localhost/test" username="sa"
password="sa" maxActive="4" maxIdle="2" maxWait="5000" />
</Context>
在上面的配置中sqlpool为你的工程名,jdbc/sql可以更改为你喜欢的名字,它即为你要引用的数据源的名字,其他的驱动和密码之类的,要视情况而定。
2. 在工程目录下的WEB-INF中,在web.xml中web-app子元素内配置如下信息,引用上面的数据源:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/sql</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
3. 接下在jsp页面中做个小测试。但要注意,不要在java类中做测试,这个我试过,会抛出javax.naming.NoInitialContextException异常,原因是DataSource是由容器(TOMCAT)提供的,在jsp页面中测试代码如下:
<%
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup ("java:/comp/env");
DataSource db = (DataSource)envContext.lookup("jdbc/sql");
Connection conn = db.getConnection( );
out.print("ok");
conn.close();
%>
当然还需要导入jar包:
<%@ page import="java.sql.*"%>
<%@ page import="javax.naming.*"%>
<%@ page import="javax.sql.*"%>
以上测试完全通过,表示数据库连接池创建成功,仅已此文献给那些初学者,快速上手!!
posted @
2007-07-28 22:50 Zhangwenlong 阅读(756) |
评论 (0) |
编辑 收藏
元素
一。语法
<!ELEMENT NAME CONTENT>
关键字 元素名称 元素类型
二。元素类型
EMPTY-该元素不能包含子元素和文本,但可以有属性-(空元素)
ANY-该元素可以包含任何在DTD中定义的元素内容
#PCDATA-可以包含任何字符数据,但是不能在其中包含任何子元素
纯元素类型--只包含子元素,并且这些子元素外没有文本
混合类型--包含子元素和文本数据的混合体
三。EMPTY示例--空元素
<!ELEMENT 人 EMPTY>
<家庭>
<人 名字="皮诺曹" 性别="男" 年龄="6"/>
</家庭> <家庭>
<人>皮诺曹</人>
<人><大人>皮诺曹爸爸</大人></人>
</家庭>
(错误)
四。ANY示例
<!ELEMENT 人 ANY>
<家庭>
<人>皮诺曹</人>
<人><大人>皮诺曹爸爸</大人></人>
</家庭>
将根元素设为ANY类型后,元素出现的次数和顺序不受限制。
五。#PCDATA示例
<!ELEMENT 人 (#PCDATA)>
<家庭>
<人 性别="男" 年龄="6">皮诺曹</人>
</家庭>
<家庭>
<人><大人>皮诺曹爸爸</大人></人>
</家庭>
(错误)
六。组合类型示例
<!ELEMENT 家庭 (人+, 家电*)>
<家庭>
<人 名字="郭大路" 性别="男" 年龄="25"/>
<人 名字="李寻欢" 性别="男" 年龄="38" 爱好="作个教育家和伟人"/>
<家电 名称="彩电" 数量="3"/>
</家庭>
posted @
2007-07-03 22:31 Zhangwenlong 阅读(125) |
评论 (0) |
编辑 收藏
商业规则和业务逻辑可以通过程序存储在oracle中,这个程序就是存储过程。
存储过程是SQL, PL/SQL, JAVA 语句的组合, 它使你能将执行商业规则的代码从从你的应用程序中移动到数据库。这样的结果就是,代码存储一次但是能够被多个程序使用。
要创建一个 过程对象(procedural object),必须有 CREATE PROCEDURE 系统权限。如果这个过程对象需要被其他的用户schema 使用,那么你必须有 CREATE ANY PROCEDURE 权限。
执行 procedure 的时候,可能需要excute权限。或者EXCUTE ANY PROCEDURE 权限。
如果单独赋予权限,如下例所示: grant execute on MY_PROCEDURE to Jelly
调用一个存储过程的例子: execute MY_PROCEDURE( 'ONE PARAMETER');
PROCEDURE 和 FUNCTION 的区别。 function有返回值,并且可以直接在Query中引用function和或者使用function的返回值。
PACKAGE 是function,procedure,variables 和sql 语句的组合。package允许多个procedure使用同一个变量和游标。
创建 procedure的语法:
CREATE [ OR REPLACE ] PROCEDURE [ schema.]procedure
[(argument [IN | OUT | IN OUT ] [NO COPY] datatype
[, argument [IN | OUT | IN OUT ] [NO COPY] datatype]...
)]
[ authid { current_user | definer }]
{ is | as } { pl/sql_subprogram_body |
language { java name 'String' | c [ name, name] library lib_name
}]
sql 代码
- CREATE PROCEDURE sam.credit (acc_no IN NUMBER, amount IN NUMBER) AS
- BEGIN
- UPDATE accounts
- SET balance = balance + amount
- WHERE account_id = acc_no;
- END;
可以使用 create or replace procedure 语句, 这个语句的用处在于,你之前赋予的excute权限都将被保留。
IN, OUT, IN OUT 用来修饰参数。IN 表示这个变量必须被调用者赋值然后传入到PROCEDURE进行处理。OUT 表示PRCEDURE 通过这个变量将值传回给调用者。IN OUT 则是这两种的组合。
authid代表两种权限: 定义者权限(difiner right 默认),执行者权限(invoker right)。定义者权限说明这个procedure中涉及的表,视图等对象所需要的权限只要定义者拥有权限的话就可以访问。执行者权限则需要调用这个procedure的用户拥有相关表和对象的权限。
posted @
2007-07-02 15:46 Zhangwenlong 阅读(800) |
评论 (1) |
编辑 收藏