??xml version="1.0" encoding="utf-8" standalone="yes"?> + ?/p>
- ?/p>
* ?/p>
/ ?div ?/p>
% ?mod 模(求余Q?/p>
== ?= {于 != ?!= 不等?/p>
< ?lt 于 内容 applicationScope 应用E序范围内的scoped变量l成的集?/p>
cookie 所有cookiel成的集?/p>
header HTTPh头部Q字W串 headerValues HTTPh头部Q字W串集合 initParam 全部应用E序参数名组成的集合 pageContext 当前面的javax.servlet.jsp.PageContext对象 pageScope 面范围内所有对象的集合 param 所有请求参数字W串l成的集?/p>
paramValues 所有作为字W串集合的请求参?/p>
requestScope 所有请求范围的对象的集?/p>
sessionScope 所有会话范围的对象的集?/p>
eg: ${empty(requestScope.backpath)?'admin_TcAction.do?method=findFinish':requestScope.backpath} <?xml version="1.0"?> <property </class> * 延迟加蝲 emylinkUlinks集合中只能存放EmylinkUlink对象Q从集合中获取对象无需再类型{?br />
它的原理是Q打开面的时候打开sessionQ一直到面装蝲完毕才关闭sessionQ这样就解决了lazy="true"时session is closed的问题?br />
关于OpenSessionInViewFilter 延迟加蝲失效问题 http://www.javaeye.com/topic/15057 一 CVS服务?/a>的安装: 如果没有安装你可以在Redhat W?张光盘上扑ֈ #> groupadd cvs 3。徏立cvsl的cvsroot用户和所属的目录Q? #> useradd -g cvs -G cvs –d /cvsroot cvsroot 4。ؓcvsroot用户d密码Q? #> passwd cvsroot 5。改?/cvsroot/ 的目录属性: #> chmod –R 770 /cvsroot 6。改变用L陆n份: #> su cvsroot 7。开始创建单个项目: #> cd /cvsroot #> cvs –d /cvsroot/project1 init 9。徏立CVS服务启动文gQ我们用xinetd方式Q? #> [Crtl]+[d] 切换到root用户w䆾 注:׃xinetd的server_args长度限制,当你惌行很多的单个仓库的时?可以q么做: #> vi cvspserver ~写cvs.run脚本 #> vi /cvsroot/cvs.run #>chmod +x /cvsroot/cvs.run 10。加入cvs服务Q? #>vi /etc/services cvspserver 2401/tcp #pserver cvs service #> /etc/init.d/xinetd restart 12。检查cvspserver服务是否已经启动Q? #> netstat -l |grep cvspserver tcp 0 0 *:cvspserver *:* LISTEN 二。CVS服务的用L理: 上面我们已经建立了project1和project2两个CVS仓库Q下面我们分别给两个仓库建立cvs用户? 13。创建可以登陆cvs服务?/a>的用户名和密码: #> su cvsroot trotter:*****:cvsroot #>vi /cvsroot/project2/CVSROOT/passwd trotter:*****:cvsroot q两个文件的意思是有trotterQmimiQgary三个cvs用户Qmimi拥有project1的用权限,gary拥有project2的用权限,trotter拥有project1和project2的用权限。登陆后的权限是cvsroot权限?br />
注意Q这里的cvs用户和系l用h不同的? 14?****为密码,׃下文件生成: #> vi /cvsroot/passwd.pl #>chmod a+x /cvsroot/passwd.pl 15。如果你想生成一个密码是“123456”Q则Q? #> /cvsroot/passwd.pl “123456” 回R卛_得到加密密码,用其替换passwd文g中的***** 16。OkQcvs现在已经全部安装完成了,如果你想让一个用h有project1的权限,你就?cvsroot/project1/CVSROOT/passwd中给他加入一个用P如果你想让一个用户同时具有project1和project2的权限,你就l?cvsroot/project1/CVSROOT/passwd?cvsroot/project2/CVSROOT/passwd里给他加一个用户名和密码相同的用户卛_。最后,我们试用一下: #> cvs -d :pserver:trotter@192.168.1.200:/cvsroot/project1 login 敲入命o回R后提C入trotter的密?你按照自p|的密码输入,如果没有什么错误信息出现就是成功了 一个cron表达式有臛_6个(也可?个)有空格分隔的旉元素?br />
按顺序依ơؓ 其中每个元素可以是一个??),一个连l区?9-12),一个间隔时?8-18/4)(/表示每隔4时),一个列?1,3,5),通配W?br />
׃"月䆾中的日期"?星期中的日期"q两个元素互斥的,必须要对其中一个设|?. 0 0 10,14,16 * * ? 每天上午10点,下午2点,4?br />
0 0/30 9-17 * * ??? 朝九晚五工作旉内每半小?br />
0 0 12 ? * WED 表示每个星期三中?2? 有些子表辑ּ能包含一些范围或列表 “*”字符代表所有可能的? “/”字符用来指定数值的增量
“L” 字符仅被用于天(月)和天Q星期)两个子表辑ּQ它是单?#8220;last”的羃? 但是它在两个子表辑ּ里的含义是不同的? 在天Q月Q子表达式中Q?#8220;L”表示一个月的最后一?, 如果?#8220;L”前有具体的内容,它就h其他的含义了 例如Q?#8220;6L”表示q个月的倒数W6天,“QRQL”表示q个月的最后一个星期五 注意Q在使用“L”参数Ӟ不要指定列表或范_因ؓq会D问题
所需文gQ?、jar?Q?commons-logging.jar 、log4j-1.2.8.jar 、taglibs-log.jar
2、配|文Ӟcommons-logging.properties 、log4j.properties
3、标{文Ӟtaglibs-log.tag
commons-logging.properties文g内容Q?/p>
##set Log as Log4J
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog
## set Log as SimpleLog
#org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
log4j.properties文g内容Q?/p>
#ConversionPattern参数的格式含?br />
#格式?nbsp;含义
#%c 输出日志信息所属的cȝ全名
#%d 输出日志旉点的日期或时_默认格式为ISO8601Q也可以在其后指定格式,比如Q?/span>%d{yyy-MM-dd HH:mm:ss }Q输出类|2002-10-18- 22Q?/span>10Q?/span>28
#%f 输出日志信息所属的cȝcd
#%l 输出日志事g的发生位|,卌出日志信息的语句处于它所在的cȝW几?br />
#%m 输出代码中指定的信息Q如log(message)中的message
#%n 输出一个回车换行符QWindowsq_?#8220;\r\n”QUnixq_?#8220;\n”
#%p 输出优先U,即DEBUGQINFOQWARNQERRORQFATAL。如果是调用debug()输出的,则ؓDEBUGQ依此类?br />
#%r 输出自应用启动到输出该日志信息所耗费的毫U数
#%t 输出产生该日志事件的U程?br />
## LOGGERS ##
#define a logger named helloAppLogger
log4j.rootLogger=info,console,file
## APPENDERS ##
# define an appender named console, which is set to be a ConsoleAppender
log4j.appender.console=org.apache.log4j.ConsoleAppender
# define an appender named file, which is set to be a RollingFileAppender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=dada.txt
## LAYOUTS ##
# assign a SimpleLayout to console appender
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
# assign a PatternLayout to file appender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} [%c]:%p -%c- %m%n
新徏log4j配置文g载入servletc?
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import org.apache.log4j.PropertyConfigurator;
public class Log4j extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";
//Initialize global variables
public void init() throws ServletException {
String prefix = this.getServletContext().getRealPath("/");
String file = this.getInitParameter("log4j");
System.out.println("载入log4j配置文g"+prefix+file);
if(file!=null){
PropertyConfigurator.configure(prefix+file);
}
}
//Clean up resources
public void destroy() {
}
}
<servlet-name>log4j</servlet-name>
<servlet-class>derek.log4j.Log4j</servlet-class>
<init-param>
<param-name>log4j</param-name>
<param-value>WEB-INF\classes\log4j.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>log4j</servlet-name>
<url-pattern>/log4j</url-pattern>
</servlet-mapping>
public class Log4jTest {
public Log4jTest() {
Logger log = Logger.getLogger(this.getClass().getName());
log.info("log4jDemo");
}
public static void main(String[] args) {
Log4jTest log4jtest = new Log4jTest();
}
}
]]>
<! DOCTYPE hibernate - configuration PUBLIC
" -//Hibernate/Hibernate Configuration DTD 3.0//EN "
" http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd " >
<!-- Generated by MyEclipse Hibernate Tools. -->
< hibernate - configuration >
< session - factory >
< property name = " myeclipse.connection.profile " > MSSQL </ property >
< property name = " connection.url " > jdbc:jtds:sqlserver: // 192.168.56.32:1433/itdb</property>
< property name = " connection.username " >dada </ property >
< property name = " connection.password " > dada </ property >
< property name = " connection.driver_class " > net.sourceforge.jtds.jdbc.Driver </ property >
< property name = " dialect " > org.hibernate.dialect.SQLServerDialect </ property >
< property name = " session_factory_name " > DerekSessionFactory </ property >
< property name = " show_sql " > false </ property >
< property name = " hibernate.jdbc.fetch_size " > 50 </ property >
< property name = " hibernate.jdbc.batch_size " > 20 </ property >
< mapping resource = " hbm/OvertimeAdmin.hbm.xml " />
< mapping resource = " hbm/OvertimeAgent.hbm.xml " />
< mapping resource = " hbm/OvertimePermit.hbm.xml " />
< mapping resource = " hbm/OvertimeRecord.hbm.xml " />
</ session - factory >
</ hibernate - configuration >
使用q接池的配置
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="myeclipse.connection.profile">MSSQL</property>
<property name="connection.datasource">java:comp/env/jdbc/itdb</property>
<property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<property name="session_factory_name">DerekSessionFactory</property>
<property name="show_sql">false</property>
<property name="hibernate.jdbc.fetch_size">50</property>
<property name="hibernate.jdbc.batch_size">20</property>
<mapping resource="hbm/OvertimeAdmin.hbm.xml" />
<mapping resource="hbm/OvertimeAgent.hbm.xml" />
<mapping resource="hbm/OvertimePermit.hbm.xml" />
<mapping resource="hbm/OvertimeRecord.hbm.xml" />
</session-factory>
</hibernate-configuration>
]]>
对于一个单个JSP面Q你可以使用定义page指o来设|jsp面是否支持EL。默认是支持EL(如果要页面不支持ELQ请讄?span class="myp11">isELIgnored=true;
<description> For config the ICW sample application </description>
<display-name>JSPConfiguration</display-name>
<url-pattern>/jsp/datareset.jsp</url-pattern>
<el-ignored>true< /
<page-encoding>ISO-8859-1</page-encoding>
<scripting-invalid>true</scripting-invalid>
<include-prelude>/jsp/prelude.jspf</include-prelude>
<include-coda>/jsp/coda.jspf</include-coda>
</jsp-property-group>
说明
q算W?/strong>
说明
> ?gt
大于
<= ?le
于{于
>= ?ge
大于{于
&& ?and
逻辑?/td>
|| ?or
逻辑?/td>
! ?not
逻辑?/td>
empty
查是否ؓI?/td>
a ? b : c
条gq算W?/td>
q算l果
EL 关系q算表达?/strong>
q算l果
${1}
1
${1 < 2}
true
${1 + 2}
3
${1 lt 2}
true
${1.2 + 2.3}
3.5
${1 > (4/2)}
false
${-4 - 2}
-6
${4.0 >= 3}
true
${21 * 2}
42
${4.0 ge 3}
true
${10%4}
2
${100.0 eq 100}
true
${10 mod 4}
2
${(10*10) != 100}
false
${(1==2) ? 3 : 4}
4
${(10*10) ne 100}
false
]]>
1.hbm.xml描述
EmylinkUpcode.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"
<hibernate-mapping package="hbm">
<class name="EmylinkUpcode" table="emylink_upcode">
<id
name="id" type="integer" column="plink_code"
>
<generator class="org.hibernate.id.IncrementGenerator"/>
</id>
name="account"
column="account"
type="string"
not-null="true"
length="20"
/>
<property
name="plinkName"
column="plink_name"
type="string"
not-null="true"
length="50"
/>
<property
name="plinkExplain"
column="plink_explain"
type="string"
not-null="false"
length="100"
/>
<property
name="typeCode"
column="type_code"
type="string"
not-null="false"
length="8"
/>
<set name="emylinkUlinks" inverse="true" lazy="true" cascade="all">
<key column="plink_code"/>
<one-to-many class="EmylinkUlink"/>
</set>
</hibernate-mapping>
操作U联Q?font color="#800080">cascadeQ关pR?br />
可选|
all : 所有情况下均进行联操作?br />
noneQ所有情况下均不q行U联操作?br />
save-update:在执行save-update?br />
q行U联操作?br />
deleteQ在执行delete时进行联操作?/span>
EmylinkUlink.hbm.xml
2.POJO对象
EmylinkUpcode.java
//?br />
// primary key
private java.lang.Integer id;
// fields
private java.lang.String account;
private java.lang.String plinkName;
private java.lang.String plinkExplain;
private java.lang.String typeCode;
// collections
private java.util.Set<hbm.EmylinkUlink> emylinkUlinks;
//?/span>
EmylinkUlink.java
//?/span>
private int hashCode = Integer.MIN_VALUE;
// primary key
private java.lang.Integer id;
// fields
private java.lang.String account;
private java.lang.String link;
private java.lang.String linkName;
private java.lang.String explain;
private java.util.Date indate;
private java.lang.String sort;
private java.lang.String m_private;
// many to one
private hbm.EmylinkUpcode plinkCode;
//?/span>
通过EmylinkUpcode加蝲EmylinkUlink(注意EmylinkUpcode.hbm.xml中声明了延迟加蝲)
Query q = session.createQuery("from EmylinkUpcode where account='derek'");
List l = q.list();
EmylinkUpcode eu = (EmylinkUpcode)l.get(0);
System.out.println(eu.getPlinkName());
//Hibernate.initialize(eu.getEmylinkUlinks());//当gq加载lazy=trueӞ强制加蝲及联对象
Set ul = eu.getEmylinkUlinks();
Iterator<EmylinkUlink> it = ul.iterator();//lazy=trueq且不用强制加载,则此时才真真及联加蝲
while(it.hasNext()){
System.out.println(it.next().getLinkName());
}
EmylinkSessionFactory.closeSession();
如果lazy=true(延迟加蝲), 加蝲EmylinkUpcode?hibernate不会立即加蝲EmylinkUlink,只有?Iterator<EmylinkUlink> it = ul.iterator();)执行?hibernate才加载EmylinkUlink实例; 如果在加载前关闭session,则报异常LazyInitializationException ; 可以使用Hibernate.initialize(Object o)强制及联加蝲
*J2SE5.0的泛?
this.emylinkUlinks = emylinkUlinks;
}
while(it.hasNext()){
EmylinkUlink el = it.next();//无需q行强制cd转换
System.out.println(el.getLinkName());
}
struts+spring+hibernate关于hibernate中lazy="true"的问题。web.xml中用
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
OpenSessionInView的效率问?nbsp; http://www.javaeye.com/topic/17501
]]>
1。查看你的操作系l上是否安装了CVSQ?br />
#> rpm -qa|grep cvs
2。徏立cvs用户l:
#> mkdir project1
#>mkdir project2
8。开始徏立仓库:
#> cvs –d /cvsroot/project2 init
#> chmod –R 770 ./project1/ ./project2/
#> cd /etc/xinetd.d
#> vi cvspserver
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
server = / usr / bin / cvs
server_args = - f -- allow - root =/ home2 / cvsroot / project1 -- allow - root =/ home2 / cvsroot / project2 pserver
log_on_failure += USERID
}
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
server = / cvsroot / cvs.run
log_on_failure += USERID
}
# !/ bin / bash
/ usr / bin / cvs - f
-- allow - root =/ cvsroot / project1
-- allow - root =/ cvsroot / project2
pserver
cvspserver 2401/udp #pserver cvs service
11。启动cvs服务Q?
应该有如下结果:
#> vi /cvsroot/project1/CVSROOT/passwd
mimi:*****:cvsroot
gary:*****:cvsroot
srand (time());
my $randletter = " (int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97)) " ;
my $salt = sprintf ( " %c%c " , eval $randletter, eval $randletter);
my $plaintext = shift;
my $crypttext = crypt ($plaintext, $salt);
print " ${crypttext} " ;
]]>
< bean id = " myTask " class = " usish.po.pub.MyTask " > <!--自己定义的Q务extends TimerTask -->
< property name = " generatPo " >
< ref local = " generatPO " />
</ property >
< property name = " importData " >
< ref local = " importData " />
</ property >
</ bean >
< bean id = " timer " class = " org.springframework.scheduling.timer.TimerFactoryBean " >
< property name = " scheduledTimerTasks " >
< list >
< ref local = " scheduledTimerTask_1 " /> <!--定时器的d?->
</ list >
</ property >
</ bean >
< bean id = " scheduledTimerTask_1 " class = " org.springframework.scheduling.timer.ScheduledTimerTask " > <!--d铑动Q?->
< property name = " timerTask " >
< ref local = " myTask " />
</ property >
< property name = " delay " >
< value > 1000 </ value >
</ property >
< property name = " period " >
< value > 50000 </ value >
</ property >
</ bean >
<!--2.使用Quartz定时-->
<!-- scheduler -->
<bean id="cacheClearStar" class="com.ztgame.memcached.CacheClearStar" />
<bean id="cacheClearStarJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref local="cacheClearStar" />
</property>
<property name="targetMethod">
<value>clear</value>
</property>
</bean>
<bean id="cacheClearStarTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref local="cacheClearStarJob" />
</property>
<property name="cronExpression">
<value>0 0 0 * * ?</value>
</property>
</bean>
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
<property name="triggers">
<ref local="cacheClearStarTrigger" />
</property>
</bean>
<!-- scheduler end -->
1.U(0~59Q?
2.分钟Q?~59Q?
3.时Q?~23Q?
4.天(月)Q?~31Q但是你需要考虑你月的天敎ͼ
5.月(0~11Q?
6.天(星期Q(1~7 1=SUN ?SUNQMONQTUEQWEDQTHUQFRIQSATQ?
7.q䆾Q?970Q?099Q?/span>
例如Q子表达式(天(星期Q)可以?“MON-FRI”Q?#8220;MONQWEDQFRI”Q?#8220;MON-WED,SAT”
因此Q?#8220;*”在子表达式(月)里表C每个月的含义,“*”在子表达式(天(星期Q)表示星期的每一?
例如Q在子表辑ּQ分钟)里的“0/15”表示从第0分钟开始,?5分钟 ;
在子表达式(分钟Q里?#8220;3/20”表示从第3分钟开始,?0分钟Q它?#8220;3Q?3Q?3”Q的含义一?
“Q?#8221;字符仅被用于天(月)和天Q星期)两个子表辑ּQ表CZ指定?
?个子表达式其中之一被指定了g后,Z避免冲突Q需要将另一个子表达式的D?#8220;Q?#8221;
在天Q星期)自表辑ּ中,“L”表示一个星期的最后一天,也就是SAT
]]>
* TOP查询
* @param sql String
* @param top int
* @return List
*/
public List findTop(String sql, int top) {
HibernateTemplate ht = this .getHibernateTemplate();
ht.setMaxResults(top);
return ht.find(sql);
}
/**
* 分页查询
* @param sql String
* @param firstRow int
* @param maxRow int
* @return List
*/
public List findPage( final String sql, final int firstRow, final int maxRow) {
return this .getHibernateTemplate().executeFind( new HibernateCallback(){
public Object doInHibernate(Session session) throws SQLException,
HibernateException {
Query q = session.createQuery(sql);
q.setFirstResult(firstRow);
q.setMaxResults(maxRow);
return q.list();
}
});
}
]]>
]]>
但是Q就像本文中“J2EE~Z对编E的支持”提到的一PJ2EEq个q_没有能够提供一个o人满意的应用E序~程模型Qapplication programming modelQ。Sun公司和一些大的应?a >服务?/a>供应商都想用开发工h降低J2EE开发的复杂性,但是q些工具没有其他的JAVA 开发工具优UQ后者有先进的重构工P?NETq_相比Q?a >J2EE的工h持显得很逊色?
很多J2EE开发工兯动生的代码像这些工hw同样复杂。在开?/a>C很多型J2EE开发者选择了另外一U开发方式—?一些可以降?a >J2EE开发难度的开?a >框架,较ؓ行的比如: struts, hibernate, ?spring frameworkQ他们当今很?a >J2EE目U扮演着重要角色?br />
Z么要采用框架Q?/strong>
框架是一׃些类l成Q正式这些类为应用程序提供了一个可重用?a >设计――或者我们经常提到的——应用程序种的一层。应用程序代码访问类库从?a >执行dQ而框架是调用应用E序代码Q从而管理程序的程。这是l常说道的好莱坞原则Q?#8220;不要试图联系我们Q我们到时候自会通知你?#8221;开发者写的程序在q行时由框架调用?br />
设计一个在各种未知背景下都可以使用的框架是很有挑战性的。框架很适合在复杂的J2EE开发中使用Q它可以为开发者提供一个简单易用的模型。采用一个经q良好设计的开源框架有很多好处Q?
·在好的框架下Q开发者只需要写一些必ȝ代码Q他们不需要直接接触底层的api?q一点很重要?br />
·l过良好设计的框架可以ؓE序提供清晰的结构ƈ且提高程序的内聚性。好清晰的结构得其他h可以更容易加入项目?br />
·一个容易用的框架可以通过一些例子和文档?a >用户提供最佛_c?br />
·采用成功的框架的代码比自q代码Ҏ试
·框架只有提供了一些值得使用的功能才会变得流行?a >J2EE工程只有真正需要框架的时候才会用它,而自q框架q不是这P后者是处于l治C的?br />
J2EE本n也提供了一些框架。比如, Enterprise Java-Beans (EJB) container或?servlet engineQ二者都q用?#8220; 采用了好莱坞原则”q个思想Qƈ采用q行时调用来理对象。像Strutsq些开?a >web应用框架正式建立在这两个框架的基上的Q本文讨论的重点也是像Strutsq样建立?a >J2EE上的框架Q他们ؓ开发者提供了更ؓ单的模型Q和其他的一些好处?
开源框架的出现
很多大型?a >J2EE目都用自己的内部框架来隐藏q_的复杂性,直到最qh们才逐渐发现一些在很多目中都存在的共有的NQ这些难题都可以׃个较为统一的解x案来解决。而有的框架正好可以充当这些问题的解决Ҏ。现在有U很明显的趋势:与从前的内部框架相比Q这些框架将成ؓq些N的更?#8220;标准?”的解x案?
J2EEq_的日益成熟是q些框架行的一个原因。开发者知道有些地ҎJ2EE的标准API无能为力的,倚他们的l验来看Q要弥补q个~陷是很困难的。于此同Ӟ一些优U的开源框架可供用,它们提供了极Z富的技术文档,在它们背后还有一个专业的团队做支持,q且一切都是免费的?
StrutsQ在web应用E序产生时就有的开源框架。在1999Q?000q_开发者们意识?a >JSP“Model1”的缺PJSP中充斥着h处理代码和静态数据模板,q意味着你不得不把业务逻辑和复杂的HTML以及其他的标{C赗那个时候还没有标准的框架和J2EE的标准支持,要解册个问题开发者就得自己实现前端控制器Q这样可以把业务逻辑分离到javacMQ从而可以减dJSP的维护难度。前端控制器模式l常q用在MVC架构中,MVC模式在OO语言的GUI开发中l常使用Q这个名字L让h误解QWEB MVC中的视图是从模型?#8220;?#8221;数据Q而在l典MVC中,模型把事?#8220;推向”视图Q?br />
最初的前端控制器实现质量参差不齐?001?002q间Q?a >apache开源组l发布的Struts改变了这个状况,虽然它ƈ非一个完的框架Q但已经_使其成ؓ该领域事实上的标准?br />
Struts向h们展CZ开源框架的一些优点,比如Q新手可以很Ҏ地熟悉它的结构?002q末Q它成立很多J2EE目很自然的选择Q每一个认真的J2EE开发者都会对它很熟悉?br />
Struts几乎用才每一?a >J2EE目中,q得它成ؓJ2EE架构的一个重要组成部分。甚臛_多保守的l织也将其作?a >软g底层的一部分Qƈ同意接受Apache的开?a >协议条款?br />
Hibernate。下一个倒下的多骨诺c牌是持久化?a >J2EE提供了两个持久化的手D:JdbCQ它是J2SE中访问关pL据库pȝ的标准APIQ另一个是实体Beans ,它是EJB中专门模型化持久化实体的lg?br />
JDBC以一U错误的~程模型来强制开发者用Java代码来处理关pL想。而实体beansQ先不说Sun和其他主要的J2EE供应商的吹嘘Q给人很W重的感觉:起初q门技术的应用范围很窄Q连持久对象间的关系都不能处理。它使得应用E序难于试Qƈ且用了一个很p糕的查询语a。直?a >2003q_即EJB2.0?.0做了很多改进Q开发者们却很用它?/p>
早期的尝?/strong>
持久化问题的解决Ҏ是由关系-对象映射QORMQ来解决的,它可以透明地持久化普通java对象QPOJOQ。该思想在注释中有解释。虽然这U方案ƈ不是专属java的。但相对与其他的C而言比如.NETQORM在javaC更加行(.NET开发者L对之抱有怀疑的态度)?br />
早在1990q_一些商业的ORM工具出CQ比如TopLink。但׃其h格昂c结构复杂ƈ且与Sun的实体bean标准相左Q所以很h会用。不怎样Q在持久化POJO斚wQ这些工具与JDBC和实体Bean相比实有了很大的进?br />
Java Data object?001q在Java Community Progress(www.jcp.org)的规范中出现。它Z般的POJO提供了大多数的持久化实现(管很多实现都是对关pL据库?。但Sun公司以及其他?a >J2EE技术提供商对该技术表现的很冷淡。所以JDO也没有能够流行?br />
Hibernate的出现。ORM领域?002q发生了大变化,原因有两个。首先,实体Beans在实践中p|Q开发者们其?a >J2EE中忽视掉了。它向开发者们说明了一个规范是如何开发拉入惔潭的?br />
另外的一个原因是Hibernate的发布,它是W一个功能健全的解决关系对象影射解决Ҏ。虽然在功能上,它没有TopLink多样。但在那些最常用的功能上QHibernate实现的更加健壮,q且有一个非怸业的团队提供全职的开发。Hibernateq不是全新的Q它的ORM思想在这个领域很普遍Q但它提供的~程模型比其他Q何竞争者都Ҏ使用、都来的直接Q它为ORM的用提供了更加易用、廉L途径?br />
于此同时Q新一代的商业产品针对关系数据库提供了极其高效的JDO规范的实现。这样开发者的选择更丰富了;q有QTopLink也朝着开发者友好的方向前进Q它的liscense来开放了?br />
ORM大获全胜
所的这些因素是的ORM比以往更加规范。虽然很多项目仍然用自q持久层框Ӟ但HibernateQTopLink以及一些高端的JDO实现Q得用自己持久层框架的难度相对变大、可l护性降低,自然Q也没有什么理由去使用自己的框架了?br />
虽然q些框架的功能覆盖范围已l很大了Q但仍有很多地方不在其中。比如,一个基于strutsQhibernate的项目,业务逻辑很难搞定。尽对于这U问题,J2EE规范提出了解x案(EJBQ,但仍旧没有一个合适的~程模型?br />
Spring
J2EE框架被大规模地运用到目中,而项目总要负责q些框架以及自己业务代码的连接,使之真正融合C赗Spring是专注于这个问题的Q它和Hibernate融合的很好?br />
本质上讲QSpring是IOC(Inversion of Control)和面向切面编E?AOP)的组合体。它是一个非侵入式的框架Q增ZPOJO的功能。从服务上讲(With a service abstraction)Q它程序代码从J2EE环境解耦到普通的java对象Q自Ӟq些代码可以qJ2EE而在多种环境中运行)。它q在很多功能上提供了除EJB之外的选择――比如ؓ所有的POJO提供声明式事务。Spring被广泛运用到很多目中,从小的webE序到大的企业应用程序?br />
在这个领域还有其他的产品Q比如HiveMind和NamoContainer。前者和Spring的思想大致相同Q只不过在IOC上有较大差异Q后者将很多服务融合在PicoContainer的IOC容器中。这些品的实现方式?a >J2EE的不同在于,它们都很M?br />
在有J2EE API下做试是非常困隄Q这些容器将POJO?a >J2EE API中脱d来,从而大大降低了试的难度。测试一个普通的java对象Q不用象试J2EEE序那样Q得先将应用E序部v到服务器上,要不得自己动手模拟J2EE环境。提供日益流行的试驱动的开发环境(对于开发者来说这是应得的Q,是这些轻量容器流行的关键因素?br />
下一个将会是谁?
Z日益对开源框架的重视Q得很多项目的成本大大降低Qƈ且投放用以及维护速度都增加了。现在的开源框枉有很高的质量Q都提供了很好的文档Q一些书c让开发者做参考。即便如此,两大因素是的J2EE领域充满了不定性:开源领域和J2EE“标准”的冲H和AOP的日益重要?br />
开源和标准之间的冲H表现在两个地方。一个是表现层,JSF的n后有Sun公司和其他的一些大公司Q而在q个领域有Struts{开源品与之竞争。在中间层,EJB 3.0采用J2SE5.0的annotations实现了依赖注?dependency injection)的功能,但这个功能只是Spring的一个子?br />
在这两个领域Q开源品都更加革新。JSP借鉴?a >ASP.netQ而Tapestry则采用了WebObjects的思想?br />
同样的,不知道EJB3.0Z要尝试着标准化依赖注入,即ɘq样会之不可避免地丧失很多功能?EJB 3.0好像也要q入E序~写领域Q?a >J2EE规范在这斚wq没有涉?br />
于此同时QAOP的重要性在J2EEC猛增Q在使用上,AOP也越来越受到开发者的青睐。像Spring、dynaop{被UC“带着双拐的AOP”实现提升了AOP的知名度。而纯_的AOP技术比如AspectJQ在来的几q也会流行v来?br />
其次Q?a >jboss通过JCP和EJB3.0保持一_它极大地推动了AOP技术。但即如此QJCP q没有{向AOPq象?br />
下一代的J2EE规范拥抱更单的POJO~程模型Q就像Spring和Hibernate做的一栗?a >J2EE开发者也注定要从“客户”转到以自q~程l验开发上来。这ơ改变将受到大多Ch的欢q,不像以前那样每一个新规范发布后,最l都没有能很好的实现?
]]>
你可以编辑config/default.properties 文g控制事务发生和超时设|。distributed.transaction.recovery 属性这个属性控制分布事物是否发生。这些事物可以发生的话,下面的条件必LI
跨库操作时的事物范围?br />
J2EEE序通过jdbc2.0 JTA驱动讉K数据?br />
当故障发生的时候,事物的各个的l成部分可以按照W合两段提交协议的方式提交或回滚?br />
事物发生的时候,server重新启动后事物可以提交或回滚?br />
distributed.transaction.recovery的gؓtrue或者false?a >J2EE安装后默认ؓfalse?br />
distributed.transaction.recovery=false
transaction.time属?br />
在应用container-managed 事物的ejb中,你可以控制事物超时的间隔通过讄transaction.timeout的倹{例如:
transaction.timeout=5
在设|以后,如果事物?U内没有完成Q?a >J2EE事物理器将回滚它。当J2EEW一ơ安装的时候,timeout的值时0代表没有时?br />
只有使用container-managed 理事物的ejb受到timeout的媄响。至于在bean-managed和JTA transactions 中你可以引用 UserTransaction ?setTransactionTimeoutҎ。同时你也可以在其他l徏中引用setTransactionTimeoutҎQ比如servlets和jsp?br />
8、端?br />
J2EE需要tcp/ip端口。修改config目录下的相应文g可以修改端口受下表是端口号和相应?a >文g?br />
EJB 9191 ejb.properties http.port=9191
HTTP 8000 web.properties port=8000
HTTPS 7000 web.properties https.port=7000
Naming and Directory 1050 orb.properties port=1050
9191 端口用于提供client下蝲需要的stubc?br />
8000 提供http服务
7000 提供https服务
1050 Zorb的jndi名字服务使用的端?br />
9、日?a >文g
J2EE server有几个日?a >文g。默认这?a >文g在logs目录下。编辑config/default.properties 文g中的 log.directory 属性可以更攚w认目录?br />
log.directory=logs
同时你也可以~辑default.properties 文g更改日志文g的名字。例如:你可以修改log.output 属性的值来修改the output.log 文g的名字?br />
一般来_日志文g军_于启?a >J2EE的模式。(singleq是multiple VM (virtual machine) 模式Q?Single VM 日志文g默认的情冉|Single VM 模式。在q种情况下,日志文g位于
$J2EE_HOME///ejb
logs是在default.properties 文g中log.directory 属性指定的。host元素是计机名称。生成下?a >文g?br />
system.out
system.err
event.log
output.log
error.log
system.out 和system.err文g包括ejb?System.out ?System.err的输出。如果你q行J2EE -verbose敎ͼ输出被写到stdoutQ标准输出) 和stderrQ标准错误。输出)。system.out ?system.err日志文g不徏。只有config/auth.properties 文g中audit属性gؓtrue时audit.lo才创建?br />
Multiple VM 日志
如果你用J2EE -mutiVM启动serverQejb和http服务在自q虚拟Z单独的服务启动。每一个depploy的应用程序也在自q虚拟Zq行。日?a >文g和上q的一P但是存放的目录不同。目录如下:
EJB $J2EE_HOME//ejb/ejbd
HTTP $J2EE_HOME//ejb/httpd
deployed application $J2EE_HOME//ejb/
web server日志
~辑web.properties文g中的内容Q可以改变由web server创徏的日?a >文g的名字?br />
10、安?br />
未授权用?br />
对于J2EE来说Q当有未授权的用戯图调用ejb container的时候,J2EE必须存在一般意义上的未授权用户存在。在J2EE中这个用户名字是guestQ密码是guest123。你可以在auth.properties 文g中修改用户名和密码?
default.principal.name=guest
default.principal.password=guest123
Keystore密码
如果用户使用公钥讉KhttpsQ认证信息放?.keystore 文g。默认的密码是changeit。可以在web.properties 文g中修改keystore.password 属性的值来改变密码?br />
ANYONE 角色
在application deployment工具的security面板中,默认的情况下Ҏ分配lANYONE 角色。这Ll果 是所有的用户和组都可以调用它。如果你没有影射C个特定的角色Q每一个用户和用户都可以调用它。可以在auth.properties 文g中设|anyone.role.name 的值来改变默认anyone角色?br />
钝化发生的条Ӟ内存限制
当ejb container开始钝化一个ejb的时候,它把ejb保存在附属存储中q且试图重新分配内存。默认的情况下,如果内存使用过128m的时候钝化开始发生。可以编辑config/default.properties 文g中passivation.threshold.memory 属性的值来修改默认倹{?br />
passivation.threshold.memory=128000000
值必L一个正的整数。当你减这个值的时候钝化现象回l常发生?br />
jndi name server host
如果jndi name server?a >J2EE server不在同一个机器上Q你必须改变config/orb.properties 文g中host属性的倹{?br />
host=localhost
HTTP 文档?br />
默认的情况下Qhttp和https服务的文档是public_html。你可以~辑web.properties 文g中documentroot属性的值来改变它?br />
documentroot=public_html/
]]>
都是文本文gQ你可以有Q
|,所有涉及的文g都在J2EE?br />
意的文本~辑器来~辑它们?br />
装目录下的oncfig目录Q这?a >文g
通常情况下,你没有改
的时候,你需要遵循本章的
变这?a >文g的必要。但是如果你
内容q行配置?br />
使用的数据库驱动不是cloudscape
2、JDBC驱动
默认的J2EE安装后支?br />
ejb使用的jdbc不是q接clo
不能定本版本的J2EE支持
cloudscape数据库(一个sun?br />
udscape数据库,那么你需要按
你用的jdbc驱动Q请?11111
司提供的演示数据库)Q如果你?br />
照下面的知道q行配置。(如果?br />
看相关信息。)
3、驱动的位置
你必L驱动文gQ?jar文gQcopy
包含在J2EE_CLASSPATH 的环境变量中?br />
?$J2EE_HOME/lib/system目录下。ƈ且保证该文g
4、J2EE_CLASSPATH 环境变量
J2EE server通过JDBC驱动q接数据
Ӟ.jar文gQ的位置。你可以在启动J2
中设|J2EE_CLASSPATH 变量。编辑用?br />
用户配置文g?/bin/userconfig.shQw
库。通通过J2EE_CLASSPATH 的环境变量定位驱动文
EE前在命o行设|这个变量。但是我们推荐你在脚?br />
配置文g在安装的q程中是必须的一步。在unix中,
indows nt中是bin/userconfig.bat
注意Q你应该同时在CLASSPATH环境变量中去掉驱?a >文gQ?jar文gQ?
5、JDBC 1.0 驱动
Z配置jdbc1.0驱动
jdbc.datasources两个属?br />
中?br />
Q编辑config/default.propert
倹{再ơ要注意的是驱动文g?br />
ies 文g的jdbc.drivers ?
d含在J2EE_CLASSPATH环境变量
jdbc.drivers 属?
jdbc.drivers 属性的值是有一pd
的冒号分割的jdbc驱动的类名。格式如下:
jdbc.drivers=:: . . .
例如Q jdbc.drive
rs=oracle.jdbc.driver.Oracle
Driver:testutil.MyDriver
jdbc.datasources 属性?
jdbc.datasources ?br />
库的url。典型的情况是:j
字和url都是在ejb~码的过
性值由两部分组成,一个是data
ndi名字是数据库的逻辑名字Qr
E中指定的。rul的格式,请参
source的jndi的名字,一个是数据
ul指定数据库的实际位置。jndi?br />
照jdbc驱动提供商的文档?br />
jdbc.datasources 的语法如下:
jdbc.datasources=|||. . .
W号有两个作用。第一Q它隔开几个jndi_datasourceQ第二,它隔开每一个jndi_datasource中的jndi_datasource> ?元素.
jndi_datasource元素的语法如下:
jdbc/
由jdbc关键字开_jn
di_name是在jndi目录中指定的d
atasouce名字?br />
例如Q jdbc.datasources=jdbc/Or
c:1521:acct|jdbc/MyDB|jdbc:test
acle|jdbc:oracle:thin@rt
6、支持JTA的JDBC2.0驱动
配置JTA的JDBC2.0的驱动,你需要设|以下属性的|
jdbc20.datasources
xadatasource..jndiname xadataso
urce..classname
xadatasource..dbuser
xadatasource..dbpassword
xadatasource..prop.
同时你也必须在J2EE_CLASSPATH 环境变量中包括jdbc驱动文g?
jdbc20.datasources 属?
jdbc20.datasources
lookupҎ的参敎ͼ?br />
属性的值和jndi名字q接Q用?br />
定位datasouce的位|(它就?br />
jdbc20.datasources 的语法如下:
jdbc20.datasources=||||的作用有两个Q第一Q隔开jndi_datasource 和ƈl成一对,W二Q隔开每一对的jndi_datasource> 、元素?
?jndi_XA_datasource有相同的语法Q?
jdbc/
jdbc关键字开头。jndi
_name是datasource名字Q这?br />
名字指向jndi目录?br />
例如Q jdbc20.datasources=jdb
c/Merant|jdbc/XAMerant|jdbc/Finch|jdbc/XAFinch
xadatasource属?
xadatasource..jndina
me 属性指定XA DataSource的jn
di名字。语法如下:
xadatasource..jndiname=jdbc/
n代表每一lxadatasou
jndi_XA_datasource元素?br />
source..dbuser ?xadata
有管理员的权限(更多的信
rce。第一个jdbc2.0驱动n?Q?br />
jdbc20.datasources 指定的?br />
source..dbpassword 属性指?br />
息请?2222 The distributed.
下一个是1Q?{等?br />
对应。The xadata
数据库用户和密码。通常该用户具
transaction.recovery Q?br />
xadatasource..prop. 指定和特定的
属性值关联的倹{实际的值可能是jdbc驱动?br />
例如Q xadatasour
ce.0.jndiname=jdbc/XAMerant
xadatasource.0.classname=com.mer
source.SequeLinkDataSource
ant.sequelink.jdbcx.data
xadatasource.0.prop.
url=jdbc:sequelink://mypc:50
00/[Oracle]
7、事?
你可以编辑config/def
distributed.transaction.
生的话,下面的条件必L
ault.properties 文g控制事务
recovery 属性这个属性控制分
I
发生和超时设|?br />
布事物是否发生。这些事物可以发
跨库操作时的事物范围?
J2EEE序通过jdbc2.0 JTA驱动讉K数据?
当故障发生的时候,事物的各个的l?br />
?br />
成部分可以按照符合两D|交协议的方式提交或回?br />
事物发生的时候,server重新启动后事物可以提交或回滚?
distributed.transact
ion.recovery的gؓtrue或者fa
lse。J2EE安装后默认ؓfalse?br />
distributed.transaction.recovery=false
transaction.time属?
在应用container-managed 事物的ej
transaction.timeout的倹{例如:
b中,你可以控制事物超时的间隔通过讄
transaction.timeout=5
在设|以后,如果事物?U内没有
的时候,timeout的值时0代表没有时?br />
完成QJ2EE事物理器将回滚它。当J2EEW一ơ安?br />
只有使用container-ma
JTA transactions 中你?br />
你也可以在其他组Z引用
naged 理事物的ejb受到timeo
以引?UserTransaction ?se
setTransactionTimeoutҎQ?br />
ut的媄响。至于在bean-managed?br />
tTransactionTimeoutҎ。同?br />
比如servlets和jsp?br />
8、端?
J2EE需要tcp/ip端口?br />
应的文g?br />
修改config目录下的相应文g?br />
以修改端口号。下表是端口号和?br />
EJB 9191 ejb.properties http.port=9191
HTTP 8000 web.properties port=8000
HTTPS 7000 web.properties ht
tps.port=7000
Naming and Directory 1050 or
b.properties port=1050
9191 端口用于提供client下蝲需要的stubc?
8000 提供http服务
7000 提供https服务
1050 Zorb的jndi名字服务使用的端?
9、日?a >文g
J2EE server有几个日
/default.properties 文g
?a >文g。默认这?a >文g在logs?br />
中的 log.directory 属性可?br />
录下。编辑config
更改默认目录?br />
log.directory=logs
同时你也可以~辑defa
log.output 属性的值来?br />
ult.properties 文g更改日志
改the output.log 文g的名?br />
文g的名字。例如:你可以修?br />
?br />
一般来_日志文g?br />
machine) 模式Q?Single V
件位?br />
定于启动J2EE的模式。(single
M 日志文g默认的情冉|Single
q是multiple VM (virtual
VM 模式。在q种情况下,日志?br />
$J2EE_HOME///ejb
logs是在default.prop
U。生成下?a >文g?br />
erties 文g中log.directory
属性指定的。host元素是计机?br />
system.out
system.err
event.log
output.log
error.log
system.out 和sys
你运行J2EE -verbose敎ͼ
system.out ?system.err
为true时audit.lo才创建?br />
tem.err文g包括ejb?System.
输出被写到stdoutQ标准输出)
日志文g不徏。只有config/aut
out ?System.err的输出。如?br />
和stderrQ标准错误。输出)?br />
h.properties 文g中audit属性?br />
Multiple VM 日志
如果你用J2EE -mutiVM启动serverQ?br />
每一个depploy的应用程序也在自q?br />
录不同。目录如下:
ejb和http服务在自q虚拟Z单独的服务启动?br />
拟机中运行。日?a >文g和上q的一P但是存放的目
EJB $J2EE_HOME//ejb/ejbd
HTTP $J2EE_HOME//ejb/httpd
deployed application $J2EE_HOME//ejb/
web server日志
~辑web.properties?br />
件中的内容,可以改变由web se
rver创徏的日?a >文g的名字?br />
10、安?
未授权用?
对于J2EE来说Q当有未
义上的未授权用户存在。在
auth.properties 文g中修
授权的用戯图调用ejb contai
J2EE中这个用户名字是guestQ?br />
改用户名和密码?
ner的时候,J2EE必须存在一般意
密码是guest123。你可以?br />
default.principal.name=guest
default.principal.password=guest123
Keystore密码
如果用户使用公钥讉KhttpsQ认?br />
System.getProperty("user.home")的返
是changeit。可以在web.properties ?br />
信息攑֜/.keystore 文g中。同时user-home?br />
回倹{keystore是一个典型的密码文g。默认的密码
件中修改keystore.password 属性的值来改变密码?br />
ANYONE 角色
在application deploy
艌Ӏ这Ll果 是所有的
个用户和用户都可以调用它
改变默认anyone角色?br />
ment工具的security面板中,?br />
用户和组都可以调用它。如果你
。可以在auth.properties 文g
认的情况下方法分配给ANYONE ?br />
没有影射C个特定的角色Q每一
中设|anyone.role.name 的值来
钝化发生的条Ӟ内存限制
当ejb container开始钝化一个ejb?br />
内存。默认的情况下,如果内存使用过
config/default.properties 文g中pass
?br />
时候,它把ejb保存在附属存储中q且试图重新分配
128m的时候钝化开始发生。可以编?br />
ivation.threshold.memory 属性的值来修改默认?br />
passivation.threshold.memory=128000000
值必L一个正的整数。当你减这个值的时候钝化现象回l常发生?
jndi name server host
如果jndi name server
nfig/orb.properties 文g
和J2EE server不在同一个机?br />
中host属性的倹{?br />
上,你必L变co
host=localhost
HTTP 文档?
默认的情况下Qhttp?br />
件中documentroot属性的?br />
https服务的文档是public_html
来改变它?br />
。你可以~辑web.properties ?br />
documentroot=public_html/
]]>
q个很重要,非常重要。J2EE늛的内容大而全Q但很多不一定就是具体实际项目需要的。象EJBU的权限控制Q如果你的表现层Q大部分目是Web serverQ和应用服务器不存在信Q问题Q那么基本上׃用考虑。又比如伸羃性,如果同时在线最多不过100个,没什么用处。针寚w目的实际情况选择效费比最合适的解决ҎQ而不要ؓ了应用先q技术而应用先q技术?nbsp;
2、选择合适的分布模型
提v分布Q很多h可能都会有这L设想Qserver A处理认证Qserver B处理订单Qserver C处理仓储Q如果B的负载太大,那么再细分一下:录入、修攚w分的EJB部v在server DQ统计、分析部分的部v在server EQ等{。其实没有必要,我的体会是:除非业务必须Q如分支机构l一通过总部的app server来进行权限验证)Q否则最好将所有的应用全部攑֜一个app server中,能在一个进E空间内更好Q用home interfaceQ,然后q行q的分?D?D即集中的所有app server功能上都是等L。相比前一U垂_或者网Ӟ分布Q^行分布的可靠性、容错能力、~能力都要更好,同时减少了部|Ӏ管理负担。最重要的是Q减了因ؓ业务逻辑层内部跨q程调用引v的开销Q提高了整体性能。然而,如果a、一些业务逻辑必须怺独立部v、管理,b、负载较为集中地分布在若q个EJB中,那么Q垂直分布还是必不可的?nbsp;
3、ؓEntity bean选择合适的数据存储Ҏ
首先量使用CMP理数据存储Q尤其是单的Q大部分业务操作都是插入删除修改的实体,不然光insert update够你忙的了Q更不用说数据库UL问题。其ơ对于简单的一对一、一对多关系Q如果你的app server没有实现EJB2.0规范Q可以考虑使用O/R映射工具帮助开发,象Cocobase, EJB creator{等Q可以提高不效率。对于复杂的对象存储Q没办法Q老老实实写代码?#8230;…
4、慎重考虑EJBHome.findByXXX()QlistXXX()的实?nbsp;
设想对一个百万记录的表q行索,l果集很可能是上万条、十万条Q这本n是一个耗费资源的过E;同时对于索到的每一个记录还要做一ơfindByPrimarykeyQ这么多ơ跨q程调用Q开销可想而知。ؓ什么有的h觉得用J2EE实现的程序奇慢无比,~Z仔细的设计就是主要原因之一?nbsp;
5、用抽象数据结构传递数?nbsp;
例如QlistOrder()q回Collection而不是VectorQinsertItems()也是以Collection为参数而不是LinkedList。当然这个实际上与J2EE本n关系不是很大?nbsp;
6、对Entity bean量使用Map来存储、传递属?nbsp;
对业务流E没有很大媄响的属性,象n高体重出生年月之c,最好用一个HashMap来存放,而不要直接用成员变量+getXXX/setXXX。对于ejbCreate也是一P十几个参数的createҎQ实现、维护都是代价高昂的。需知实际应用中q些字段的增减、属性变化是家常侉KQ光l护get/setҎ可能׃让你吐血了。但是,对于对业务流E有兛_意义的字D,例如员工的入职日期决定其休假天数的计,那么q是作ؓ成员变量的好?nbsp;
7、分清Entity bean和session bean的职?nbsp;
Entity bean是实体的对象形式Q它的职责应限于自n的存储,以及对外部提供访问内部数据的接口Q所以我认ؓ它本质上应该属于数据存储层)。Entity bean应该量避免自己实现有其他Entity bean参与的业务逻辑。例如,订单的货ƾ收C后,订单的状态由“提交”变ؓ“生效”Q同时将订单的金额按照某U规则折成该客LU分。这个业务流E有三个对象参与Q客P订单和积分折策略。那么,实现程的方法应该在哪个对象中呢Q是客户q是订单Q都不合适,如果在订单中Q那么订单对象需要了解客L分属性的接口及积分折的接口Q如果在客户对象中也是一栗耦合度增强就意味着l护隑ֺ增大Q如果用户对象的U分接口或者折策略的接口改变了,那么改变׃蔓g到订单对象中。合适的方式是用一个OrderProcessor来管理订单处理流E,以stateless session bean来实现。OrderProcessor了解所有参与订单处理的对象的接口,它集中管理对订单的处理流E,如果程发生变化Q订单生效之前要通过审批Q这U变化不会媄响到参与程的实体对象;同样Q参与流E的某个对象接口发生了变化,也不会媄响到其他对象?nbsp;
8、重视表现层的复?nbsp;
企业软g的界面,大部分都可以用一些基本元素如grid, tree, page control, form{组合而来。如果能合理采用一些技术对q些元素q行复用Q不但有利于降低开发成本,而且也便于统一l护界面风格。对J2EE的表现层Q也是JSP/servletQ可以采用的复用技术不多,基本上就是文件包含、创建类库、Tag ligQ本质上q是创徏cdQ用v来我觉得q不一定有直接Ҏ调用来的方便Q等{。还有一些不同于JSP/servlet的表现层框架Q如Apache Velocity、Enhydra、WebMacro{等Q也可以参考。虽然Javaq没有一个规范的、统一的HTML界面元素cdQ但自己目内部l一使用某种Ҏq是可能的?nbsp;
另外QXML+XSLT也是一U方案。将数据直接用XML形式表现出来Q绕qEntity beanQ然后再用XSLT模版转化成最l界面。XML与XSLT之间属于模式匚w式的松散耦合Q可以避免强cd语言Ҏ调用带来的参数类型、个数、顺序限Ӟ做到d地数据与界面分离Q同时XML形式的数据集在app server中可以按照合适的Ҏq行~冲Q避免频J访问数据库Q抵销XSLT转换引入的性能负担。同时XML和XSLT是业界广泛采U的标准Q如果今后采用不同的体系l构Q如从J2EEUL?Net或者相反)Q表现层的XSLT形式的界面可以重用。JSP或ASP没有这U可能。问题在于首先要理关系型数据到层次型XML数据的映,其次如果没有一个好的工P创徏、维护XSLT也是很费时费力的事情。我现在的项目正在朝q个方向努力Q希望能做一个象Delphi那样好用的,ZXSLT的HTML界面控g开发、管理、用环境?nbsp;
9、充分估计开发的艰辛E度
q个Q一a隑ְ。M实际需求的变化往往是超乎我们想象的Q要在需求分析结束的时候就清晰划分模块接口几乎做不刎ͼ计划不如变化。而J2EE体系架构是重量的框Ӟ虽然app server实现了很多功能,但同时也要求你开发的时候付出额外的代h。对于J2EE目的资金、时间、h手等资源估计Q宁可多不可,千万不要单认为用了一个weblogic׃事大吉了?nbsp;
]]>
在痛苦的抉择后,我选择J2EE..分nJ2EEl我带来的快乐。学到现在,最大的感觉Q就? 单就是美Q美是Java.不会有学MFC的痛苦,也不会有d析STL的艰辛,|\应用上一点也不逊色于C++。开始进入我?a >J2EE之旅?br />
q是下蝲了一?a >J2EE规范Q一?a >J2EE SDK。开始研I?a >J2EE,l合http://java.sun.com/j2ee/tutorial/index.html 提供?a >J2EE Tutorial开始研I了。大概过?个月Q开始有感觉了,也就在这个时候,需要我d成一?a >J2EE构架斚w的项目。差不多边学~写完成了,很多概念在写完后都不是很清晰Q因Z西太多了Q主要是ZJSP(Servlet)+Session Bean+EIS构架开发系l。当然也学到很多东西Q至对SB EJB的编写不成问题。懂得了JSP如何调用EJB……..
完成目后,我开始研I?a >Java Pet Store了,很是q瘾。开始知道了Servletqo器,XML斚w较ؓ全面的知识,知道?a >J2EE整个框架中各U技术的实际应用。慢慢的Q开始研IWebLogic配置好的Pet StoreQ也是Sun公司的)。慢慢的分析两者的不同之处。开始对J2EE Specification有了很好的感觉。因?a >J2EE Specification本n是很严肃的,但Pet Storel出了活力。在反复的学习中Q我明白?a >J2EE构架?0?D80%。新的问题又出来了,实际企业中会如何建构一?a >J2EEpȝ呢?带着q个问题Q我开始分析Core J2EE Patterns,q本书。同Ӟ也有EJB Design Patterns。慢慢的Q开始知道了J2EE的魅力所在,知道?a >J2EEZ么会在企业中得到较ؓ好的认可。大安知道Q设计模式一词,在公怸班,你们的老板会看你的代码吗?会赞赏你的DP很好吗,我想很少。在完成你的工作q度之余Q加班,加班Q再加班Q我想你没有更多的时间去分析研究DP.但,J2EE框架不一P她内|了很多优秀的设计模式,我们在设计开发、构架一?a >J2EEpȝ中用C很多设计模式。比如,MVC,EJB中封装的DAO设计模式。构架J2Epȝ用Session Façade,Message Façade设计模式也不会太困难。这也是后来J2EE吸引我的地方。慢慢的我知道了Q作Z?a >J2EE开发者,我们要掌握其中的核心内容。我个h认ؓQ?斚w很重要。实施EJBpȝ常用的架构、设计模式,比如session façade、message façade、DTO{?a >J2EEpȝ构架中常用的模式。UML-> EJB,EJB->UML怺映射。现在也一样在研究?br />
善于享受孤独Q幸好还?a >J2EEQ?/p>
]]>
一、什么是JDKQ?/strong>
学JAVA的h都应该知道SUN公司的JAVA 技术^台按其应用环境的不同有三个非常著名的版本Q他们是J2SEQ用于普通桌面应用程序的开发)QJ2EEQ用于企业应用E序的开发)和J2MEQ用于移动设备及其他消费cȝ子品的应用E序开发)QSUN公司三个版本分别提供了相应的开发工具包QSDKQSoftWare Development KitsQ?下蝲的网址在http://www.sun.com/downloadsQ不q可能因为全世界太多人登录的原故Q网늻常出现打不开的现象,其实大家在国内一些常用的资料下蝲|站同样可以DOWN到这些工具包的。在此不一一列D了。顺便提一下J2SE和J2EE目前最新的SDK版本是:
?J2SE 5.0 JDK
?J2EE 1.4 SDK
值得一提的是我们通常所说的JDK工具包指的是J2SE的SDK。目前一般学习者用得最多的也就是这个工具包了。大家还要注意一点,SUN公司Z同的操作pȝ提供了不同的JDK文gQ而且q些文g又有脱机版(OFFLINEQ与在线安装版(ONLINEQ之分,所以在下蝲的时候要注意选择正确?a >文g?br />
那么JDKq个工具包里到底有些什么东东呢Q其实这里面包括了JAVAE序的开发工PJAVAC命o{)、运行环境(JAVA命o{)和核心类包。可惌知要想q行JAVAE序。就必须安装好JDK工具包?br />
二、如何安装JDKQ?/strong>
当我们从|络上DOWN下J2SE 5.0 JDK以后Q是一个可执行文gQ?a >文g名叫做jdk-1_5_0-windows-i586.exeQ当然这个名字会因ؓ对应操作pȝ的不同而有所区别的,我用的操作pȝ是WINDOWSQ大家发C吗?Q,双击他就开始安装了。需要注意的是选择安装路径的问题,通常我们它安装在C盘根目录下(q也是安装程序默认的路径Q,其他的工作就是一个接一个地按NEXT啦?br />
三、搭行和开发环?/strong>
是不是当我们装完JDK以后可以编写代码,准备~译q行了呢Q别忙。大家还是跟着我一h查一下吧Q?br />
1、点L作系l桌面上左下角的‘开?#8217;菜单Q选择‘q行’Q然后在打开对话框里输入CMDQ看C吧,我们q入了命令提C符H口Q我们爱叫他DOS界面?br />
2、现在大家在H口里应该看到提C符了吧Q通常会是q样QC:\Documents and Settings\Administrator>
3、下面让我们在提C符后面敲上q样一个命令:JAVAQ出Cq样的提CZ吗?
Usage: java [-options] class [args...]
(to execute a class)
or java [-options] -jar jarfile [args...]
(to execute a jar file)
……
q是JAVA命o的帮助信息,如果有,那么成功一半了?br />
4、接下来Ql试一下:在命令提C符处敲QJAVAC。同样也出现了JAVAC的命令帮助提CZ吗?我想应该没有吧。你看到的也怼是这P ‘javac’不是内部或外部命令,也不是可q行的程序或批处?a >文g?br />
Z么出现这L情况呢?
q是因ؓ我们的操作系l在执行一个命令时Q首先会到当前目录下L找这个命?a >文g。如果在当前目录下找不到Q他׃按照pȝ变量PATH所指示的多条\径里L索,直到扑ֈ为止。如果在q两个地斚w找不C׃报上面大家看到的错误?br />
在C:\Documents and Settings\Administratorq个路径下我们当然找不到JAVAC命o啦。我们的JDK不是安装在C盘根目录下吗Q而我们的JAVAC、JAVA命o则在JDK目录下的BIN文g多wQ这个夹子里q有许多其他宝贝命o。如下图所C:
怎样才能让操作系l找到JAVAC命o呢?很简单!我们需要修改一下系l变量PATHQ这样就不用每次要运行这个命令时都得跑到C:\j2sdk1.4.2_02\binq个路径下面M。怎样修改PATHQ我们在W四个专题里来介l?br />
5、当我们在PATH变量里加了一条\径:C:\j2sdk1.4.2_02\bin以后Q再到命令提
C符状态下输入JAVACQ就会出现帮助提CZ。这p明我们可以开始写JAVAE序了?br />
6、让我们写一个Hello.java试一下吧Q我在E:\LESSON1q个文g夹下创徏
了一个文?a >文gQ输入如下一D代码,q且之保存为Hello.java?br />
public class Hello
{
public static void main(String args[])
{
System.out.println("Hello World!");
}
}
7、好现在我们又回到命令提C符状态下。在提示W处输入QJAVAC Hello.java,?br />
令又出错了。ؓ什么?因ؓ文g是徏在E:\LESSON1下面Q而我们的当前目录却不是它。在提示W处敲入Q?#8216;EQ?#8217;Q然后再Ԍ‘cd lesson1’Q进入JAVA文g所在的那个目录后,现在再敲JAVAC Hello.javaQ?a >文g成功~译。注意成功编译后会在当前目录下生Z个名叫:Hello.class的字节码文g。但是屏q上没有M提示?br />
8、再试着q行一?#8216;java Hello‘q个命oQ可以运行吗Q当然不行。ؓ什么,
因ؓ我们的字节码文g是在JAVA虚拟机里q行的,所有关于虚拟机要用的字节?a >文g的\径必d一个叫做CLASSPATH的操作系l变量里扑־到。否则我们的虚拟机就无法扑ֈq个字节?a >文gQ从而也无从执行了?br />
9、怎么办?先运行如下命令:set classpath=%classpath%;E:\lesson1Q然后再q?br />
?java Hello q个命o。屏q上l于出现了亲切的问候:Hello world!
不过奇怪的事情又发生了。当我们重新启动一个命令提C符H口再运行这个JAVA文gӞ又无法执行了Q屏q提C:Exception in thread "main" java.lang.NoClassDefFoundError: Hello。还是老问题,虚拟机又找不到字节码文g了。WHY?其实我们在DOSH口中设|的pȝ变量只对当前H口有效。要惌我们的变量设|对M一个DOSH口都有效,q得到桌面上d。我们仍然将在第四个专题里讲qCLASSPATHq个JAVA环境变量的设|?br />
四、PATHpȝ变量与CLASSPATH环境变量的设|?/strong>
Z么需要设|PATH和CLASSPATH变量我们在前面的专题已经介绍q了。下面我们讲一下具体如何设|:
1、右键单L的电脑,?#8216;属?#8217;菜单Q在弹出的对话框里选择‘高‘选项卡。然后在高选项卡页按下‘环境变量’按钮?br />
2、在弹出的环境变量窗口里我们会看到它分Z个部分。一部分是谁谁用L变量Q如QAdministrator的用户变量。一部分是系l变量。通常情况下我们在命o提示W下能够使用的变量数目是用户变量Q系l变量数目之和。那我们不管用户变量。直接到pȝ变量格里d找PATH变量吧。通常情况下系l装好后PATH变量在这里是早就存在了的。但是CLASSPATH变量则没有?br />
环境变量H口见图C:
3、找到PATH变量后,双击q个变量名称后,会弹出~辑pȝ变量H口。将光标停到变量值对话框的最后,然后加上‘QC:\j2sdk1.4.2_02\bin ’。注意分号后的\径就是JAVA和JAVAC命o所在的路径。见囄Q?br />
4、找不到CLASSPATH变量该怎么办呢Q很单。按下系l变量框下的新徏按钮。然后在弹出的新建系l变量对话框里输入你要加的变量名UͼCLASSPATHQ在变量值对话框里输入你要运行的字节?a >文g所在的路径。如囄Q?br />
大家在以后的学习中会发现Q只要是虚拟行所需的字节码文gQ即c?a >文gQ,包括SUN公司提供l我们的cR都需要将q些文g所在的路径攑ֈCLASSPATH下。否则,E序在编译过E中会经常找不着所需要的cd。那可是很头疼的事。比如说QJDK安装目录下的LIB目录下就有许?.jar文g。当我们的程序要使用到这些压~?a >文g里的cLQ就需要把q些文g所在的路径加到CLASSPATH里,比如_C:\j2sdk1.4.2_02\lib\dt.jar?br />
注意d*.jar包和直接d*.class文g的\径是有一点小区别的Q前者要包含JAR包的名字。而后者只需文g路径?br />
五、J2EEq行环境的搭?/strong>
开发企业的应用程序需要搭建好J2EE的运行环境。其实也是到SUN公司的网站上去DOWN下J2EE 1.4 SDK开发工具包。然后双d?a >文gQ如果你下蝲的版本与我的一栗那么这个安?a >文g׃是这个名字:j2eesdk-1_4-dr-windows-eval.exe。同L我们也将J2EE SDK安装在C盘根目录下?br />
需要特别提醒大家的是:J2EEq行环境的搭建是以J2SEq行环境的搭Zؓ基础的。其实想也想得到Z么。如果没有JDKQ哪里来的编译和q行命o呢(JAVA和javacQ。安装完J2EE 1.4 SDK包后Q具体的讄与测试步骤如下:
1、首先右往PATH变量里添加J2EE SDK的BIN目录。如QC:\j2sdkee1.3.1\bin。如何往里面dQ前面已l讲q?br />
2、然后新Z个变量:一个是JAVA_HOMEQ变量gؓQJDK的安装目录。另一个是J2EE_HOMEQ变量gؓJ2EE SDK的安装目录。如囄Q?br />
3、最后往CLASSPATH变量里添加一个关键的JAR包。它是J2EE.JAR包。比如我d的就是:C:\j2sdkee1.3.1\lib\j2ee.jar?br />
4、所有的工作做完以后。大家可以通过以下方式验证一下我们的J2EE环境是否已经搭徏成功。在命o提示W状态下输入命oQJ2EE QVerbose。如果屏q的最下面看到了这样一句话J2EE server startup complete.那就表示J2EE服务器成功启动了。在我们的J2EEE序要布|和q行的过E中。服务器一直启动着?/font>
]]>
目前QJava2q_?个版本,它们是适用于小型设备和卡的Java2q_Micro版(Java2PlatformMicroEditionQJ2MEQ、适用于桌面系l的Java2q_标准版(Java2PlatformStandardEditionQJ2SEQ、适用于创建服务器应用E序和服务的Java2q_企业版(Java2PlatformEnterpriseEditionQ?a >J2EEQ?br />
J2EE是一U利用Java2q_来简化企业解x案的开发、部|和理相关的复杂问题的体系l构?a >J2EE技术的基础是核心Javaq_或Java2q_的标准版Q?a >J2EE不仅巩固了标准版中的许多优点Q例?~写一ơ、随处运?的特性、方便存取数据库的JDBCAPI、CORBA技术以及能够在Internet应用中保护数据的安全模式{等Q同时还提供了对EJBQEnterpriseJavaBeansQ、JavaServletsAPI、JSPQJavaServerPagesQ以及XML技术的全面支持。其最l目的就是成Z个能够企业开发者大q羃短投攑ָ场时间的体系l构?br />
J2EE体系l构提供中间层集成框架用来满x需太多费用而又需要高可用性、高可靠性以及可扩展性的应用的需求。通过提供l一的开发^収ͼJ2EE降低了开发多层应用的费用和复杂性,同时提供对现有应用程序集成强有力支持Q完全支持EnterpriseJavaBeansQ有良好的向导支持打包和部v应用Q添加目录支持,增强了安全机Ӟ提高了性能?br />
?J2EE的优?/strong>
J2EE为搭建具有可伸羃性、灵zL、易l护性的商务pȝ提供了良好的机制:
保留现存的IT资:׃企业必须适应新的商业需求,利用已有的企业信息系l方面的投资Q而不是重新制定全盘方案就变得很重要。这P一个以渐进的(而不是激q的Q全盘否定的Q方式徏立在已有pȝ之上的服务器端^台机制是公司所需求的?a >J2EE架构可以充分利用用户原有的投资,如一些公怋用的BEATuxedo、IBMCICS,IBMEncina,、InpriseVisiBroker以及NetscapeApplicationServer。这之所以成为可能是因ؓJ2EE领域的升U途径。由于基?a >J2EEq_的品几乎能够在M操作pȝ和硬仉|上q行Q现有的操作pȝ和硬件也能被保留使用?br />
高效的开?J2EE允许公司把一些通用的、很J琐的服务端d交给中间件供应商d成。这样开发h员可以集中精力在如何创徏商业逻辑上,相应地羃短了开发时间。高U中间g供应商提供以下这些复杂的中间件服?
状态管理服?-让开发h员写更少的代码,不用兛_如何理状态,q样能够更快地完成程序开发?br />
持箋性服?-让开发h员不用对数据讉K逻辑q行~码p~写应用E序Q能生成更轻巧,与数据库无关的应用程序,q种应用E序更易于开发与l护?/p>
分布式共享数据对象CACHE服务--让开发h员编刉性能的系l,极大提高整体部v的~性?br />
支持异构环境:J2EE能够开发部|在异构环境中的可移植程序。基?a >J2EE的应用程序不依赖M特定操作pȝ、中间g、硬件。因此设计合理的ZJ2EE的程序只需开发一ơ就可部|到各种q_。这在典型的异构企业计算环境中是十分关键的?a >J2EE标准也允许客戯购与J2EE兼容的第三方的现成的lgQ把他们部v到异构环境中Q节省了p己制订整个方案所需的费用?br />
可~?企业必须要选择一U服务器端^収ͼq种q_应能提供极佳的可伸羃性去满那些在他们系l上q行商业q作的大Ҏ客户。基?a >J2EEq_的应用程序可被部|到各种操作pȝ上。例如可被部|到高端UNIX与大型机pȝQ这U系l单机可支持64?56个处理器。(q是NT服务器所望尘莫及的)J2EE领域的供应商提供了更为广泛的负蝲q{略。能消除pȝ中的瓉Q允许多台服务器集成部v。这U部|可达数千个处理器,实现可高度~的pȝQ满x来商业应用的需要?br />
E_的可用?一个服务器端^台必能全天候运转以满公司客户、合作伙伴的需要。因为INTERNET是全球化的、无处不在的Q即使在夜间按计划停Z可能造成严重损失。若是意外停机,那会有灾难性后果?a >J2EE部v到可靠的操作环境中,他们支持长期的可用性。一?a >J2EE部v在WINDOWS环境中,客户也可选择健壮性能更好的操作系l如SunSolaris、IBMOS/390。最健壮的操作系l可辑ֈ99.999%的可用性或每年只需5分钟停机旉。这是实时性很强商业系l理想的选择?br />
?J2EE的四层模?/strong>
J2EE使用多层的分布式应用模型Q应用逻辑按功能划分ؓlgQ各个应用组件根据他们所在的层分布在不同的机器上。事实上Qsun设计J2EE的初h是ؓ了解决两层模?client/server)的弊端,在传l模式中Q客L担当了过多的角色而显得臃肿,在这U模式中Q第一ơ部|的时候比较容易,但难于升U或改进Q可伸展性也不理惻I而且l常Z某种专有的协??通常是某U数据库协议。它使得重用业务逻辑和界面逻辑非常困难。现?a >J2EE的多层企业应用模型两层化模型中的不同层面切分成许多层。一个多层化应用能够Z同的每种服务提供一个独立的层,以下?a >J2EE典型的四层结?
q行在客L机器上的客户层组?br />
q行?a >J2EE服务器上的Web层组?br />
q行?a >J2EE服务器上的业务逻辑层组?br />
q行在EIS服务器上的企业信息系l?Enterpriseinformationsystem)层Y?/p>
J2EE应用E序lg
J2EE应用E序是由lg构成?J2EElg是具有独立功能的软g单元Q它们通过相关的类和文件组装成J2EE应用E序Qƈ与其他组件交互?/p>
2EE说明书中定义了以下的J2EElg:应用客户端程序和applets是客户层lg.JavaServlet和JavaServerPages(JSP)是web层组?EnterpriseJavaBeans(EJB)是业务层lg.
客户层组ӞJ2EE应用E序可以是基于web方式?也可以是Z传统方式?
web层组ӞJ2EEweb层组件可以是JSP面或Servlets.按照J2EE规范Q静态的HTML面和Applets不算是web层组件。web层可能包含某些JavaBean对象来处理用戯入,q把输入发送给q行在业务层上的enterprisebean来进行处理?br />
业务层组Ӟ业务层代码的逻辑用来满银行Q零售,金融{特D商务领域的需?p行在业务层上的enterprisebeanq行处理.下图表明了一个enterprisebean是如何从客户端程序接收数据,q行处理(如果必要的话),q发送到EIS层储存的Q这个过E也可以逆向q行?br />
有三U企业的bean:会话(session)beans,实体(entity)beans,和消息驱?message-driven)beans.会话bean表示与客LE序的时交?当客LE序执行完后,会话bean和相x据就会消?相反,实体bean表示数据库的表中一行永久的记录.当客LE序中止或服务器关闭?׃有潜在的服务保证实体bean的数据得以保?消息驱动beanl合了会话bean和JMS的消息监听器的特?允许一个业务层lg异步接收JMS消息.
企业信息pȝ?br />
企业信息pȝ层处理企业信息系lY件包括企业基pȝ例如企业资源计划(ERP),大型Z务处?数据库系l?和其它的遗留信息pȝ.例如Q?a >J2EE应用lg可能Z数据库连接需要访问企业信息系l?/p>
一.J2EE的概?/strong>
目前QJava2q_?个版本,它们是适用于小型设备和卡的Java2q_Micro版(Java2PlatformMicroEditionQJ2MEQ、适用于桌面系l的Java2q_标准版(Java2PlatformStandardEditionQJ2SEQ、适用于创建服务器应用E序和服务的Java2q_企业版(Java2PlatformEnterpriseEditionQ?a >J2EEQ?br />
J2EE是一U利用Java2q_来简化企业解x案的开发、部|和理相关的复杂问题的体系l构?a >J2EE技术的基础是核心Javaq_或Java2q_的标准版Q?a >J2EE不仅巩固了标准版中的许多优点Q例?~写一ơ、随处运?的特性、方便存取数据库的JDBCAPI、CORBA技术以及能够在Internet应用中保
护数据的安全模式{等Q同时还提供了对EJBQEnterpriseJavaBeansQ、JavaServletsAPI、JSPQJavaServerPagesQ以及XML技术的全面支持。其最l目的就是成Z个能够企业开发者大q羃短投攑ָ场时间的体系l构?br />
J2EE体系l构提供中间层集成框架用来满x需太多费用而又需要高可用性、高可靠性以及可扩展性的应用的需求。通过提供l一的开发^収ͼJ2EE降低了开发多层应用的费用和复杂性,同时提供对现有应用程序集成强有力支持Q完全支持EnterpriseJavaBeansQ有良好的向导支持打包和部v应用Q添加目录支持,增强了安全机Ӟ提高了性能?br />
?J2EE的优?/strong>
J2EE为搭建具有可伸羃性、灵zL、易l护性的商务pȝ提供了良好的机制:
保留现存的IT资:׃企业必须适应新的商业需求,利用已有的企业信息系l方面的投资Q而不是重新制定全盘方案就变得很重要。这P一个以渐进的(而不是激q的Q全盘否定的Q方式徏立在已有pȝ之上的服务器端^台机制是公司所需求的?a >J2EE架构可以充分利用用户原有的投资,如一些公怋用的BEATuxedo、IBMCICS,IBMEncina,、InpriseVisiBroker以及NetscapeApplicationServer。这之所以成为可能是因ؓJ2EE领域的升U途径。由于基?a >J2EEq_的品几乎能够在M操作pȝ和硬仉|上q行Q现有的操作pȝ和硬件也能被保留使用?br />
高效的开?J2EE允许公司把一些通用的、很J琐的服务端d交给中间件供应商d成。这样开发h员可以集中精力在如何创徏商业逻辑上,相应地羃短了开发时间。高U中间g供应商提供以下这些复杂的中间件服?
状态管理服?-让开发h员写更少的代码,不用兛_如何理状态,q样能够更快地完成程序开发?br />
持箋性服?-让开发h员不用对数据讉K逻辑q行~码p~写应用E序Q能生成更轻巧,与数据库无关的应用程序,q种应用E序更易于开发与l护?/p>
分布式共享数据对象CACHE服务--让开发h员编刉性能的系l,极大提高整体部v的~性?br />
支持异构环境:J2EE能够开发部|在异构环境中的可移植程序。基?a >J2EE的应用程序不依赖M特定操作pȝ、中间g、硬件。因此设计合理的ZJ2EE的程序只需开发一ơ就可部|到各种q_。这在典型的异构企业计算环境中是十分关键的?a >J2EE标准也允许客戯购与J2EE兼容的第三方的现成的lgQ把他们部v到异构环境中Q节省了p己制订整个方案所需的费用?br />
可~?企业必须要选择一U服务器端^収ͼq种q_应能提供极佳的可伸羃性去满那些在他们系l上q行商业q作的大Ҏ客户。基?a >J2EEq_的应用程序可被部|到各种操作pȝ上。例如可被部|到高端UNIX与大型机pȝQ这U系l单机可支持64?56个处理器。(q是NT服务器所望尘莫及的)J2EE领域的供应商提供了更为广泛的负蝲q{略。能消除pȝ中的瓉Q允许多台服务器集成部v。这U部|可达数千个处理器,实现可高度~的pȝQ满x来商业应用的需要?br />
E_的可用?一个服务器端^台必能全天候运转以满公司客户、合作伙伴的需要。因为INTERNET是全球化的、无处不在的Q即使在夜间按计划停Z可能造成严重损失。若是意外停机,那会有灾难性后果?a >J2EE部v到可靠的操作环境中,他们支持长期的可用性。一?a >J2EE部v在WINDOWS环境中,客户也可选择健壮性能更好的操作系l如SunSolaris、IBMOS/390。最健壮的操作系l可辑ֈ99.999%的可用性或每年只需5分钟停机旉。这是实时性很强商业系l理想的选择?br />
?J2EE的四层模?/strong>
J2EE使用多层的分布式应用模型Q应用逻辑按功能划分ؓlgQ各个应用组件根据他们所在的层分布在不同的机器上。事实上Qsun设计J2EE的初h是ؓ了解决两层模?client/server)的弊端,在传l模式中Q客L担当了过多的角色而显得臃肿,在这U模式中Q第一ơ部|的时候比较容易,但难于升U或改进Q可伸展性也不理惻I而且l常Z某种专有的协??通常是某U数据库协议。它使得重用业务逻辑和界面逻辑非常困难。现?a >J2EE的多层企业应用模型两层化模型中的不同层面切分成许多层。一个多层化应用能够Z同的每种服务提供一个独立的层,以下?a >J2EE典型的四层结?
q行在客L机器上的客户层组?br />
q行?a >J2EE服务器上的Web层组?br />
q行?a >J2EE服务器上的业务逻辑层组?br />
q行在EIS服务器上的企业信息系l?Enterpriseinformationsystem)层Y?/p>
J2EE应用E序lg
J2EE应用E序是由lg构成?J2EElg是具有独立功能的软g单元Q它们通过相关的类和文件组装成J2EE应用E序Qƈ与其他组件交互?/p>
2EE说明书中定义了以下的J2EElg:应用客户端程序和applets是客户层lg.JavaServlet和JavaServerPages(JSP)是web层组?EnterpriseJavaBeans(EJB)是业务层lg.
客户层组ӞJ2EE应用E序可以是基于web方式?也可以是Z传统方式?
web层组ӞJ2EEweb层组件可以是JSP面或Servlets.按照J2EE规范Q静态的HTML面和Applets不算是web层组件。web层可能包含某些JavaBean对象来处理用戯入,q把输入发送给q行在业务层上的enterprisebean来进行处理?br />
业务层组Ӟ业务层代码的逻辑用来满银行Q零售,金融{特D商务领域的需?p行在业务层上的enterprisebeanq行处理.下图表明了一个enterprisebean是如何从客户端程序接收数据,q行处理(如果必要的话),q发送到EIS层储存的Q这个过E也可以逆向q行?br />
有三U企业的bean:会话(session)beans,实体(entity)beans,和消息驱?message-driven)beans.会话bean表示与客LE序的时交?当客LE序执行完后,会话bean和相x据就会消?相反,实体bean表示数据库的表中一行永久的记录.当客LE序中止或服务器关闭?׃有潜在的服务保证实体bean的数据得以保?消息驱动beanl合了会话bean和JMS的消息监听器的特?允许一个业务层lg异步接收JMS消息.
企业信息pȝ?br />
企业信息pȝ层处理企业信息系lY件包括企业基pȝ例如企业资源计划(ERP),大型Z务处?数据库系l?和其它的遗留信息pȝ.例如Q?a >J2EE应用lg可能Z数据库连接需要访问企业信息系l?/p>