??xml version="1.0" encoding="utf-8" standalone="yes"?> 补充Q?br />
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"
%> OUT: IF / CHOOSE: 1、EL表达式用${}表示,可用在所有的HTML和JSP标签?作用是代替JSP面中复杂的JAVA代码. 2、EL表达式可操作帔R 变量 和隐式对? 最常用?隐式对象?{param}?{paramValues}.
${param}表示q回h参数中单个字W串的?
${paramValues}表示q回h参数的一l?pageScope表示面范围的变?requestScope表示h对象的变?
sessionScope表示会话范围内的变量.applicationScope表示应用范围的变? 3?lt;%@ page isELIgnored="true"%>
表示是否用EL语言,TRUE表示止.FALSE表示不禁?JSP2.0中默认的启用EL语言. 4、EL语言可显C?逻辑表达式如${true and false}l果是false 关系表达式如${5>6} l果是false
术表达式如 ${5+5} l果?0 5、EL中的变量搜烦范围?page request session application 点运符(.)?[ ]"都是表示获取变量的?区别是[
]可以昄非词cȝ变量 Java NIO出现不只是一个技术性能的提高,你会发现|络上到处在介绍它,因ؓ它具有里E碑意义Q从JDK1.4开始,Java开始提高性能相关的功能,从而得Java在底层或者ƈ行分布式计算{操作上已经可以和C或Perl{语aq齐驱?/p>
?
果你至今q是在怀疑Java的性能Q说明你的思想和观念已l完全落伍了QJava一两年应该用新的名词来定义。从JDK1.5开始又要提供关于线E、ƈ
发等新性能的支持,Java应用在游戏等适时领域斚w的机会已l成熟,Java在稳定自׃间gC后,开始蚕食传lC的领域?/p>
本文主要单介lNIO的基本原理,在下一文章中Q将l合Reactor模式和著名线E大?a >Doug
Lea的一文章深入讨论?/p>
NIO主要原理和适用?/p>
NIO
有一个主要的cSelector,q个cM一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有
事g发生Ӟ他会通知我们Q传回一lSelectionKey,我们dq些Key,׃获得我们刚刚注册q的socketchannel,然后Q我们从
q个Channel中读取数据,攑ֿQ包准能够读刎ͼ接着我们可以处理q些数据?/p>
Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮?目前p一个算?Q一旦轮询到一个channel有所注册的事情发生,比如数据来了Q他׃站v来报告,交出一把钥匙,让我们通过q把钥匙来读取这个channel的内宏V?/p>
了解了这个基本原理,我们l合代码看看使用Q在使用上,也在分两个方向,一个是U程处理Q一个是用非U程Q后者比较简单,看下面代码: q是一个守候在端口9000的noblock server例子Q如果我们编制一个客LE序Q就可以对它q行互动操作Q或者用telnet
L?9000 可以链接上?/p>
${expression}
2.[]?q算W?br />
EL 提供.和[]两种q算W来存取数据?br />
当要存取的属性名UC包含一些特D字W,??{ƈ非字母或数字的符P׃定要使用 []。例如:
${user.My-Name}应当改ؓ${user["My-Name"] }
如果要动态取值时Q就可以用[]来做Q?无法做到动态取倹{例如:
${sessionScope.user[data]}中data 是一个变?br />
3.变量
EL存取变量数据的方法很单,例如Q?{username}。它的意思是取出某一范围中名UCؓusername的变量?br />
因ؓ我们q没有指定哪一个范围的usernameQ所以它会依序从Page、Request、Session、Application范围查找?br />
假如途中扑ֈusernameQ就直接回传Q不再l找下去Q但是假如全部的范围都没有找到时Q就回传null?br />
属性范围在EL中的名称
Page PageScope
Request RequestScope
Session SessionScope
Application ApplicationScope
二、EL隐含对象
1.与范围有关的隐含对象
与范围有关的EL 隐含对象包含以下四个QpageScope、requestScope、sessionScope 和applicationScopeQ?br />
它们基本上就和JSP的pageContext、request、session和application一P
在EL中,q四个隐含对象只能用来取得范围属性|即getAttribute(String name)Q却不能取得其他相关信息?br />
例如Q我们要取得session中储存一个属性username的|可以利用下列ҎQ?br />
session.getAttribute("username") 取得username的|
在EL中则使用下列Ҏ
${sessionScope.username}
2.与输入有关的隐含对象
与输入有关的隐含对象有两个:param和paramValuesQ它们是EL中比较特别的隐含对象?br />
例如我们要取得用Lh参数Ӟ可以利用下列ҎQ?br />
request.getParameter(String name)
request.getParameterValues(String name)
在EL中则可以使用param和paramValues两者来取得数据?br />
${param.name}
${paramValues.name}
3.其他隐含对象
cookie
JSTLq没有提供设定cookie的动作,
例:要取得cookie中有一个设定名UCؓuserCountry的|可以使用${cookie.userCountry}来取得它?br />
header和headerValues
header 储存用户览器和服务端用来沟通的数据
例:要取得用h览器的版本,可以使用${header["User-Agent"]}?br />
另外在鲜机会下Q有可能同一标头名称拥有不同的|此时必须改ؓ使用headerValues 来取得这些倹{?br />
initParam
initParam取得讑֮web站点的环境参?Context)
例:一般的ҎString userid = (String)application.getInitParameter("userid");
可以使用 ${initParam.userid}来取得名UCؓuserid
pageContext
pageContext取得其他有关用户要求或页面的详细信息?br />
${pageContext.request.queryString} 取得h的参数字W串
${pageContext.request.requestURL} 取得h的URLQ但不包括请求之参数字符?br />
${pageContext.request.contextPath} 服务的web application 的名U?br />
${pageContext.request.method} 取得HTTP 的方?GET、POST)
${pageContext.request.protocol} 取得使用的协?HTTP/1.1、HTTP/1.0)
${pageContext.request.remoteUser} 取得用户名称
${pageContext.request.remoteAddr } 取得用户的IP 地址
${pageContext.session.new} 判断session 是否为新?br />
${pageContext.session.id} 取得session 的ID
${pageContext.servletContext.serverInfo} 取得L端的服务信息
三、ELq算W?br />
1.术q算W有五个Q?????或div?或mod
2.关系q算W有六个Q?=或eq?=或ne?lt;或lt?gt;或gt?lt;=或le?gt;=或ge
3.逻辑q算W有三个Q?amp;&或and、||或or?或not
4.其它q算W有三个QEmptyq算W、条件运符?)q算W?br />
例:${empty param.name}?{A?B:C}?{A*(B+C)}
四、EL函数(functions)?br />
语法Qns:function( arg1, arg2, arg3 …. argN)
其中ns为前|名U?prefix)Q它必须和taglib 指o的前|名UC|?br />
FOREACH:
<c:forEach
items="${messages}"
var="item"
begin="0"
end="9"
step="1"
varStatus="var">
……
</c:forEach>
<c:out value="/${logininfo.username}"/>
<c:out>value
中的内容输出到当前位|,q里也就是把logininfo 对象?br />
username属性D出到面当前位置?br />
${……}是JSP2.0
中的Expression
LanguageQELQ的语法。它定义了一个表辑ּQ?br />
其中的表辑ּ可以是一个常量(如上Q,也可以是一个具体的表达语句Q如forEach循环体中
的情况)。典型案例如下:
Ø
${logininfo.username}
q表明引用logininfo 对象的username
属性。我们可以通过“.”操作W引
用对象的属性,也可以用“[]”引用对象属性,?{logininfo[username]}
?{logininfo.username}辑ֈ了同L效果?br />
“[]”引用方式的意义在于,如果属性名中出CҎ字符Q如“.”或?#8220;-”Q?br />
此时必M?#8220;[]”获取属性g避免语法上的冲突Q系l开发时应尽量避?br />
q一现象的出玎ͼ?br />
与之{同的JSP
Script大致如下Q?br />
LoginInfo logininfo
=
(LoginInfo)session.getAttribute(“logininfo”);
String username =
logininfo.getUsername();
可以看到QEL大大节省了编码量?br />
q里引出的另外一个问题就是,EL 从哪里扑ֈlogininfo
对象Q对?br />
${logininfo.username}q样的表辑ּ而言Q首先会从当前页面中L之前?br />
否定义了变量logininfoQ如果没有找到则依次到Request、Session?br />
Application
范围内寻找,直到扑ֈ为止。如果直到最后依然没有找到匹配的
变量Q则q回null.
如果我们需要指定变量的L范围Q可以在EL表达式中指定搜寻范围Q?br />
${pageScope.logininfo.username}
${requestScope.logininfo.username}
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
在Spring
中,所有逻辑处理单元q回的结果数据,都将作ؓAttribute 被放
|到HttpServletRequest 对象中返回(具体实现可参见Spring
源码?br />
org.springframework.web.servlet.view.InternalResourceView.
exposeModelAsRequestAttributesҎ的实C码)Q也是说Spring
MVC
中,l果数据对象默认都是requestScope。因此,在Spring MVC
中,
以下dҎ应慎用:
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
Ø
${1Q?}
l果辑ּ计算l果Q即整数??br />
Ø
${i>1}
如果变量值i>1的话Q将q回boolcdtrue。与上例比较Q可以发现EL会自
动根据表辑ּ计算l果q回不同的数据类型?br />
表达式的写法与java代码中的表达式编写方式大致相同?/p>
<c:if test="${var.index % 2 ==
0}">
*
</c:if>
判定条g一般ؓ一个EL表达式?br />
<c:if>q没有提供else子句Q用的时候可能有些不便,此时我们可以通过<c:choose>
tag来达到类似的目的Q?br />
<c:choose>
<c:when
test="${var.index % 2 ==
0}">
*
</c:when>
<c:otherwise>
!
</c:otherwise>
</c:choose>
cMJava
中的switch
语句Q?lt;c:choose>提供了复杂判定条件下的简化处理手法。其
?lt;c:when>子句cMcase子句Q可以出现多ơ。上面的代码Q在奇数行时输出“*”P
而偶数行时输?#8220;!”?/p>
]]>
]]>
]]>
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;
/**
* @author Administrator
* @version
*/
public class NBTest {
/** Creates new NBTest */
public NBTest() {
}
public void startServer() throws Exception {
int channels = 0;
int nKeys = 0;
int currentSelector = 0;
// 使用Selector
Selector selector = Selector.open();
// 建立Channel q绑定到9000端口
ServerSocketChannel ssc = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(InetAddress
.getLocalHost(), 9000);
ssc.socket().bind(address);
// 使设定non-blocking的方式?/span>
ssc.configureBlocking(false);
// 向Selector注册Channel及我们有兴趣的事?/span>
SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
printKeyInfo(s);
while (true) // 不断的轮?/span>
{
debug("NBTest: Starting select");
// Selector通过selectҎ通知我们我们感兴的事g发生了?/span>
nKeys = selector.select();
// 如果有我们注册的事情发生了,它的传回值就会大?
if (nKeys > 0) {
debug("NBTest: Number of keys after select operation: " + nKeys);
// Selector传回一lSelectionKeys
// 我们从这些key中的channel()Ҏ中取得我们刚刚注册的channel?/span>
Set selectedKeys = selector.selectedKeys();
Iterator i = selectedKeys.iterator();
while (i.hasNext()) {
s = (SelectionKey) i.next();
printKeyInfo(s);
debug("NBTest: Nr Keys in selector: "
+ selector.keys().size());
// 一个key被处理完成后Q就都被从就l关键字Qready keysQ列表中除去
i.remove();
if (s.isAcceptable()) {
// 从channel()中取得我们刚刚注册的channel?/span>
Socket socket = ((ServerSocketChannel) s.channel())
.accept().socket();
SocketChannel sc = socket.getChannel();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ
| SelectionKey.OP_WRITE);
System.out.println(++channels);
} else {
debug("NBTest: Channel not acceptable");
}
}
} else {
debug("NBTest: Select finished without any keys.");
}
}
}
private static void debug(String s) {
System.out.println(s);
}
private static void printKeyInfo(SelectionKey sk) {
String s = new String();
s = "Att: " + (sk.attachment() == null ? "no" : "yes");
s += ", Read: " + sk.isReadable();
s += ", Acpt: " + sk.isAcceptable();
s += ", Cnct: " + sk.isConnectable();
s += ", Wrt: " + sk.isWritable();
s += ", Valid: " + sk.isValid();
s += ", Ops: " + sk.interestOps();
debug(s);
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
NBTest nbTest = new NBTest();
try {
nbTest.startServer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
DigesterZ规则的XML文档解析,主要用于XML到Java对象的映?br />
commons-beanutils.jar
提供对Java 反射和自省API的包?br />
aspectjweaver.jar
用于在Spring 2.0中集成AspectJ AspectJ LTWl入?br />
ognl.jar
OGNL是Object-Graph Navigation Language的羃写,它是一U功能强大的表达式语aQExpression
LanguageQ简UCؓELQ,通过它简单一致的表达式语法,可以存取对象的Q意属性,调用对象的方法,遍历整个对象的结构图Q实现字D늱型{化等?
能。它使用相同的表辑ּd取对象的属?br />
hibernate2依赖的一些包
hibernate2.jar
Hibernate的库Q没有什么可说的Q必M用的jar?br />
cglib-asm.jar
CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库Q必M用的jar?br />
dom4j.jar
dom4j是一个Java的XML APIQ类gjdomQ用来读写XML文g的。dom4j是一个非帔R怼U的Java XML
APIQ具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的YӞ可以在SourceForge上找到它。在IBM
developerWorks上面可以扑ֈ一文章,对主的Java XML
APIq行的性能、功能和易用性的评测Qdom4j无论在那个方面都是非常出色的。我早在近两年之前开始用dom4jQ直到现在。如今你可以看到?
来越多的Java软g都在使用dom4j来读写XMLQ特别值得一提的是连Sun的JAXM也在用dom4j。这是必M用的jar
包,Hibernate用它来读写配|文件?br />
odmg.jar
ODMG是一个ORM的规范,Hibernate实现了ODMG规范Q这是一个核心的库,必须使用的jar?br />
commons-collections.jar
Apache Commons包中的一个,包含了一些Apache开发的集合c,功能比java.util.*强大。必M用的jar?br />
commons-beanutils.jar
Apache Commons包中的一个,包含了一些Bean工具cȝ。必M用的jar?br />
commons-lang.jar
Apache Commons包中的一个,包含了一些数据类型工LQ是java.lang.*的扩展。必M用的jar?br />
commons-logging.jar
Apache Commons包中的一个,包含了日志功能,必须使用的jar包。这个包本n包含了一个Simple
LoggerQ但是功能很弱。在q行的时候它会先在CLASSPATH找log4jQ如果有Q就使用log4jQ如果没有,找JDK1.4带的
java.util.loggingQ如果也找不到就用Simple
Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾Q当初Apache极力游说Sun把log4j加入JDK1.4Q?
然而JDK1.4目组已经接近发布JDK1.4产品的时间了Q因此拒l了Apache的要求,使用自己的java.util.loggingQ这个包
的功能比log4j差的很远Q性能也一般?br />
后来Apache开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的
logE序Q底层的Logger是可以切换的Q你可以选择log4jQjava.util.logging或者它自带的Simple
Logger。不q我仍然强烈使用log4jQ因为log4j性能很高Qlog输出信息旉几乎{于System.outQ而处理一条logq_只需
?us。你可以在Hibernate的src目录下找到Hibernate已经Z准备好了的log4j的配|文Ӟ你只需要到Apache
|站M载log4j可以了。commons-logging.jar也是必须的jar包?br />
使用Hibernate必须的jar包就是以上的q几个,剩下的都是可选的
ant.jar
Ant~译工具的jar包,用来~译Hibernate源代码的。如果你不准备修改和~译Hibernate源代码,那么没有什么用Q可选的jar?br />
optional.jar
Ant的一个辅助包
c3p0.jar
C3PO是一个数据库q接池,Hibernate可以配置Z用C3POq接池。如果你准备用这个连接池Q就需要这个jar包?br />
proxool.jar
也是一个连接池Q同?br />
commons-pool.jar,commons-dbcp.jar
DBCP数据库连接池QApache的Jakartal织开发的QTomcat4的连接池也是DBCP?
实际上Hibernate自己也实C一个非帔R常简单的数据库连接池Q加上上?个,你实际上可以在Hibernate上选择4U不同的数据库连接池Q?
选择哪一个看个h的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中用HibernateQ一定要用App
Server的连接池Q不要用以上4U连接池Q否则容器管理事务不起作?br />
connector.jar
JCA 规范Q如果你在App Server上把Hibernate配置为Connector的话Q就需要这个jar。不q实际上一般App Server肯定会带上这个包Q所以实际上是多余的?br />
jaas.jar
JAAS是用来进行权限验证的Q已l包含在JDK1.4里面了。所以实际上是多余的包?br />
jcs.jar
如果你准备在Hibernate中用JCS的话Q那么必d括它Q否则就不用?br />
jdbc2_0-stdext.jar
JDBC2.0的扩展包Q一般来说数据库q接池会用上它。不qApp Server都会带上Q所以也是多余的?br />
jta.jar
JTA规范Q当Hibernate使用JTA的时候需要,不过App Server都会带上Q所以也是多余的?br />
junit.jar
Junit包,当你q行Hibernate自带的测试代码的时候需要,否则׃用?br />
xalan.jar, xerces.jar, xml-apis.jar
Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App
Server都会带上QJDK1.4也包含了解析器,不过不是XercesQ是CrimsonQ效率比较差Q不qHibernate用XML只不q是d
配置文gQ性能没什么紧要的Q所以也是多余的
antlr.jar
语法生成工具
spring 相关jar包作用:
除了spring.jar文gQSpringq包括有其它13个独立的jar包,各自包含着对应的SpringlgQ用户可以根据自q需要来选择l合自己的jar包,而不必引入整个spring.jar的所有类文g?br />
(1) spring-core.jar
q个jar文g包含Spring框架基本的核心工LQSpring其它lg要都要用到q个包里的类Q是其它lg的基本核心,当然你也可以在自q应用pȝ中用这些工L?br />
(2) spring-beans.jar
q个jar文g是所有应用都要用到的Q它包含讉K配置文g、创建和理bean以及q行Inversion of Control /
Dependency
InjectionQIoC/DIQ操作相关的所有类。如果应用只需基本的IoC/DI支持Q引入spring-core.jar及spring-
beans.jar文g可以了?br />
(3) spring-aop.jar
q个jar文g包含在应用中使用Spring的AOPҎ时所需的类。用基于AOP的SpringҎ,如声明型事务理QDeclarative Transaction ManagementQ,也要在应用里包含q个jar包?br />
(4) spring-context.jar
q个jar文g为Spring核心提供了大量扩展。可以找C用Spring
ApplicationContextҎ时所需的全部类QJDNI所需的全部类QUI斚w的用来与模板QTemplatingQ引擎如
Velocity、FreeMarker、JasperReports集成的类Q以及校验Validation斚w的相关类?br />
(5) spring-dao.jar
q个jar文g包含Spring DAO、Spring Transactionq行数据讉K的所有类。ؓ了用声明型事务支持Q还需在自q应用里包含spring-aop.jar?br />
(6) spring-hibernate.jar
q个jar文g包含Spring对Hibernate 2及Hibernate 3q行装的所有类?br />
(7) spring-jdbc.jar
q个jar文g包含对Spring对JDBC数据讉Kq行装的所有类?br />
(8) spring-orm.jar
q个jar文g包含Spring对DAOҎ集q行了扩展,使其支持
iBATIS、JDO、OJB、TopLinkQ因为Hibernate已经独立成包了,现在不包含在q个包里了。这个jar文g里大部分的类都要依赖
spring-dao.jar里的c,用这个包时你需要同时包含spring-dao.jar包?br />
(9) spring-remoting.jar
q个jar文g包含支持EJB、JMS、远E调用RemotingQRMI、Hessian、Burlap、Http Invoker、JAX-RPCQ方面的cR?br />
(10) spring-support.jar
q个jar文g包含支持~存CacheQehcacheQ、JCA、JMX、邮件服务(Java Mail、COS MailQ、Q务计划SchedulingQTimer、QuartzQ方面的cR?br />
(11) spring-web.jar
q个jar文g包含Web应用开发时Q用到Spring框架时所需的核心类Q包括自动蝲入WebApplicationContextҎ的cRStruts与JSF集成cR文件上传的支持cRFiltercd大量工具辅助cR?br />
(12) spring-webmvc.jar
q个jar文g包含Spring
MVC框架相关的所有类。包含国际化、标{、Theme、视囑ֱ现的FreeMarker、JasperReports、Tiles、Velocity?
XSLT相关cR当Ӟ如果你的应用使用了独立的MVC框架Q则无需q个JAR文g里的McR?br />
(13) spring-mock.jar
q个jar文g包含Spring一整套mockcL辅助应用的测试。Spring试套g使用了其中大量mockc,q样试更加简单。模拟HttpServletRequest和HttpServletResponsecdWeb应用单元试是很方便的?br />
jstl相关jar包简?br />
׃要搭SSH框架Q面寚w么多包,都不知道q嘛的,于是把每个包的作用都查q去Q有Ҏ聊,呵呵?br />
mail.jar
java发送电子邮?,里面包含了activation.jar和mail.jar两个?通过里面的类的调用便可以辑ֈ发送电子邮件的目的.里面.......
dom.jar
文对象模型”(DOM)允许开发者在 XML l构内引用、检索和更改 XML l构中的各项元素?br />
jaxen-full.jar
jaxen是一个用Java开发的XPath 引擎,支持JDOM, dom4j?br />
jaxp-api.jar
JAXP是Java API for XML Processing的英文字头羃?中文含义?用于XML文档处理的用Java语言~写的编E接?br />
jadb2_0-stdxt.jar
javax.sql包,可以查下java API?br />
jstl.jar
sax.jar
SAX是一个用于处理XML事g驱动?#8220;?#8221;模型Q虽然它不是W3C标准Q但它却是一个得Cq泛认可的API
saxpath.jar
SAXPath is an event-based API for XPath parsers, that is, for parsers
which parse XPath expressions. SAXPath is intended to be for XPath what
SAX is for XML
standard.jar
标准标签库包。jstl核心的两个包之一?br />
xalan.jar
Xalan是将可扩展标记语a(XML)转换文本链接标识语言(HTML)或其它类型XML文的规?br />
xercesImpl.jar
实现解析XML文g的功能很方便,我们可以通过下蝲W三方的一些工具包如xml-apis.jar,xercesImpl.jar
Xerces是一个与可扩展标记语a(XML)兼容的语法分析器。Xerces分析器可处理Java和C++,它采用互联网联盟XML、文件对?..Xerces-C是用可移植的C++子集~写的XML分析器。Xerces-C允许对XML数据q行d操作
如果要用JSTL,则必djstl.jar和standard.jar文g攑ֈclasspath?如果你还需要用XML
processing及Database access
(SQL)标签,q要相关JAR文g攑ֈclasspath?q些JAR文g全部存在于下载回来的zip文g中?
]]>
Spring2 针对q程讉K服务Q提供的一个remote包。其的的是提供一套统一的远E服务发布功能?br />
先来看一下Spring2支持那些q程服务功能:
1. RMI服务
2. Hessian或者Burlap通过HTTPq程调用服务
3. HTTP调用器暴露服?br />
下面用一个例子,来看一下Spring2 是怎样对这些服务进行统一的封装和理?br />
先看一下服务器端的源代?br />
Book getById(String id);
}
public class Book {
public String name;
public String id;
public String author;
}
public class BookService implements IBookService {
public Book getById(String id) {
return BookStore.getById(id);
}
}
客户端源代码
private IBookService bookService;
public void setAccountService(IBookService bookService) {
this.bookService = bookService;
}
public Book getBookById(String id) {
return bookService.getById(id);
}
}
//客户端调用示?/span>
public static void main(String[] args) {
ClassPathXmlApplicationContext context;
context = new ClassPathXmlApplicationContext("applicationContext.xml");
BookQueryService bookQueryService = (BookQueryService) context.getBean("bookQueryService");
Book book = bookQueryService.getBookById("1");
}
使用Spring2 发布 RMI服务CZ
<bean id="bookService" class="com.xmatthew.spring.remote.BookService">
</bean>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName" value="bookService"/>
<property name="service" ref="bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
<property name="registryPort" value="1800"/>
</bean>
客户端配|?
<bean class="com.xmatthew.spring.remote.client.BookQueryService">
<property name="bookService" ref="bookService"/>
</bean>
<bean id="bookService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1800/bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
</bean>
使用Spring2 发布 ZHttp的Hessian服务CZ
注: Hessian提供一U基于HTTP的二q制q程协议。它是由Caucho创徏的,可以?http://www.caucho.com 扑ֈ更多有关Hessian的信息?br />
首ؓ使用HessianQ需要ؓ光|Spring ?DispatcherServlet
把下面的配置加入到web.xml?br />
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
<bean id="bookService" class="com.xmatthew.spring.remote.BookService">
</bean>
<bean name="/bookService" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
</bean>
客户端配|?
<bean class="com.xmatthew.spring.remote.client.BookQueryService">
<property name="bookService" ref="bookService"/>
</bean>
<bean id="bookService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
</bean>
使用Spring2 发布 ZHttp的Burlap服务CZ
BurlapQ它是一个基于XML的Hessian替代Ҏ。它的配|方法和上述Hessian的一栗只要把 Hessian 换成 Burlap p了?br />
服务器端使用:
org.springframework.remoting.caucho.BurlapServiceExporter 发布服务
客户端?
org.springframework.remoting.caucho.BurlapProxyFactoryBean
使用Spring2 发布 ZHTTP调用器暴露服?br />
和用自w序列化机制的轻量协议Burlap和Hessian相反QSpring HTTP调用器用标准Java序列化机制来通过HTTP暴露业务.
但其配置与Burlap和Hessian很相q?br />
<bean id="bookService" class="com.xmatthew.spring.remote.BookService">
</bean>
<bean name="/bookService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
</bean>
客户端配|?
<bean class="com.xmatthew.spring.remote.client.BookQueryService">
<property name="bookService" ref="bookService"/>
</bean>
<bean id="bookService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/bookService"/>
<property name="serviceInterface" value="com.xmatthew.spring.remote.IBookService"/>
</bean>
]]>
首先q是配置好web.xml文gQ主要添加的代码有:
2. <listener-class>
3. org.springframework.web.util.Log4jConfigListener
4. </listener-class>
5. </listener>
6.
7. <listener>
8. <listener-class>
9. org.springframework.web.context.ContextLoaderListener
10. </listener-class>
11. </listener>
12.
13. <welcome-file-list>
14. <welcome-file>index.jsp</welcome-file>
15. </welcome-file-list>
16.
17. <servlet>
18. <servlet-name>sim</servlet-name>
19. <servlet-class>
20. org.springframework.web.servlet.DispatcherServlet
21. </servlet-class>
22. </servlet>
23.
24. <servlet-mapping>
25. <servlet-name>sim</servlet-name>
26. <url-pattern>*.html</url-pattern>
27. </servlet-mapping>
以上的配|和以前是一LQ所以没什么好说的?
然后接着我们建立一个applicationContext.xmlQ作?span class="hilite1">SPRING的配|文件。以往版本里面SPRING?
q个配置文g往往随着E序的增加而越来越臃肿Q就我本人来说就十分不喜Ƣ这U方式。因为程序员需要花费大量的旉ȝ理和l护自己的XML文gQ大大的?
了E序员的生效率。ƈ且由于大量的XML文gQ得新加入团队的h员学习成本的增加Q往往造成了很多工时上的浪贏V终于,2.5版本开始支持了annotationQ得这个问题可以得C定的解决。那么好Q下面我们来看看现在的配|文件?
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns:context="http://www.springframework.org/schema/context"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans
6. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7. http://www.springframework.org/schema/context
8. http://www.springframework.org/schema/context/spring-context-2.5.xsd">
9. <context:annotation-config />
10. </beans>
很好Q很强大Q简单一句话搞定?
搞定了IOC的配|文Ӟ那么我们需要一个MVC的配|XMLQ如果没有annotationQ那么这个文件一样会来臃ѝ然后现在呢Q?
sim-servlet.xml
2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3. xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
5. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
6.
7. <!--
8. - The controllers are autodetected POJOs labeled with the @Controller annotation.
9. -->
10. <context:component-scan base-package="com.sofmit.sim.wr.web"/>
11.
12. <!--
13. - This bean configures the 'prefix' and 'suffix' properties of
14. - InternalResourceViewResolver, which resolves logical view names
15. - returned by Controllers. For example, a logical view name of "vets"
16. - will be mapped to "/WEB-INF/jsp/vets.jsp".
17. -->
18. <bean
19. class="org.springframework.web.servlet.view.InternalResourceViewResolver"
20. p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
21. </beans>
同样十分单,在这里只需要指定好CONTROLLER的包可以了?
现在配置已经全部OK了,是不是感觉很LQ哈哈,原来annotation真是如此妙Qؓ我们节约了大量的配置XML的时间?
下面只需要一个controller和一个JSP面可以完成我们这儿APPLICATION了,那么我们l箋?
首先是controller的定义?
2. * com.sofmit.sim.wr.web
3. * Hello.java
4. */
5. package com.sofmit.sim.wr.web;
6.
7. import org.springframework.stereotype.Controller;
8. import org.springframework.ui.Model;
9. import org.springframework.web.bind.annotation.RequestMapping;
10. import org.springframework.web.bind.annotation.RequestMethod;
11.
12. /**
13. * @author TianYe
14. * 2008-2-14
15. */
16. @Controller
17. @RequestMapping("/hello.html")
18. public class Hello {
19.
20. @RequestMapping(method = RequestMethod.GET)
21. public String sayHello(Model model){
22. model.addAttribute("say","hello");
23. return "test";
24. }
25. }
在这里面Q用@Controller定义此类是一?span class="hilite1">Spring MVC的controller。然后定义好讉K的\?/hello.html"。在Ҏ上面定义好通过GET方式讉K时调用我们的sayHelloҎQ在Ҏ中定义好要传lJSP面的变?say"以及内容"hello"Q然后定位到面"test"?
一个简单的controller实C?
剩下的就没有什么技术含量了Q就是一个简单的JSP面?
2. <h2>Test Page say:${say}</h2>
]]>
一U是面hqhӞ服务器端控制一个超时时间比?0分钟Q到了时间之后用h有动作就被踢出。这U方法的优点是,如果用户忘了退出,可以防止
别h恶意操作。缺ҎQ如果你在做一件很耗时间的事情Q超q了q个旉限制Qsubmit的时候可能要再次面登陆。如果原来的叉又是强制失效的话Q就
有可能丢׃做的工作。在实现的角度来看,q是最单的QServer端默认实现的是q样的模式?br />
另一U方式是Q站炚w用框架结
构,有一个Frame或者隐藏的iframe在不断刷斎ͼq样你永q不会被t出Q但是服务器端ؓ了判断你是否在线Q需要定一个发呆时_如果过q个发呆
旉你除了这个自动刷新的面外没有刷新其他页面的话,pZ已经不在U了。采取这U方式的典型是xici.net?
他的优点是可以可以利用不断的h实现一些类似server-push的功能,比如|友之间发送消息?br />
不管哪一U模式,Z实现览当前所有的在线用户Q还需要做一些额外的工作。servlet API中没有得到Session列表的API?br />
可以利用的是Listener. Servlet
2.2?.3规范在这里略微有一些不一栗?.2中HttpSessionBindingListener可以实现当一个HTTPSession中的
Attribute变化的时候通知你的cR?.3中还引入了HttpSessionAttributeListener.鉴于我用的环境?
Visual age for java 4和JRun server 3.1,他们q不直接支持Servlet
2.3的编E,q里我用的是HttpSessionBindingListener.
需要做的事情包括做一个新的类来实现HttpSessionBindingListener接口。这个接口有两个ҎQ?br />
public void valueBound(HttpSessionBindingEvent event)
public void valueUnbound(HttpSessionBindingEvent event)
当你执行Session.addAttribute(String,Object)的时候,如果你已l把一个实C
HttpSessionBindingListener接口的类加入为Attribute,Session会通知你的c,调用你的valueBound?
法。相反,Session.removeAttributeҎ对应的是valueUndoundҎ?br />
public class HttpSessionBinding implements javax.servlet.http.HttpSessionBindingListener
{
ServletContext application = null;
public HttpSessionBinding(ServletContext application)
{
super();
if (application ==null)
throw new IllegalArgumentException("Null application is not accept.");
this.application = application;
}
public void valueBound(javax.servlet.http.HttpSessionBindingEvent e)
{
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions == null)
{
activeSessions = new Vector();
}
JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
if (sessionUser != null)
{
activeSessions.add(e.getSession());
}
application.setAttribute("activeSessions",activeSessions);
}
public void valueUnbound(javax.servlet.http.HttpSessionBindingEvent e)
{
JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
if (sessionUser == null)
{
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions != null)
{
activeSessions.remove(e.getSession().getId());
application.setAttribute("activeSessions",activeSessions);
}
}
}
}
假设其中的JDBCUsercL一个Q意UsercR在执行用户dӞ把UsercdHttpSessionBindingc都加入到Session中去?br />
q样Q每ơ用L录后Q在application中的attribute "activeSessions"q个vector中都会增加一条记录。每当session时QvalueUnbound被触发,在这个vector中删d要被时的session.
public void login()
throws ACLException,SQLException,IOException
{
/* get JDBC User Class */
if (user != null)
{
logout();
}
{
// if session time out, or user didn't login, save the target url temporary.
JDBCUserFactory uf = new JDBCUserFactory();
if ( (this.request.getParameter("userID")==null) || (this.request.getParameter("password")==null) )
{
throw new ACLException("Please input a valid userName and password.");
}
JDBCUser user = (JDBCUser) uf.UserLogin(
this.request.getParameter("userID"),
this.request.getParameter("password") );
user.touchLoginTime();
this.session.setAttribute("user",user);
this.session.setAttribute("BindingNotify",new HttpSessionBinding(application));
}
}
Login的时候,把User和这个BindingNotofy目的的类都加入到session中去。logout的时候,pd在activeSessionsq个vector中删去这个session.
public void logout()
throws SQLException,ACLException
{
if (this.user == null && this.session.getAttribute("user")==null)
{
return;
}
Vector activeSessions = (Vector) this.application.getAttribute("activeSessions");
if (activeSessions != null)
{
activeSessions.remove(this.session);
application.setAttribute("activeSessions",activeSessions);
}
java.util.Enumeration e = this.session.getAttributeNames();
while (e.hasMoreElements())
{
String s = (String)e.nextElement();
this.session.removeAttribute(s);
}
this.user.touchLogoutTime();
this.user = null;
}
q两个函C于一个HttpSessionManagercM.q个cd用了jsp里面的application全局对象。这个类的其他代码和本文无关且相当长Q我׃贴出来了?br />
下面来看看jsp里面怎么用?br />
假设一个登录用的表单被提交到doLogin.jsp, 表单中包含UserName和password域。节选部分片D:
Q?
HttpSessionManager hsm = new HttpSessionManager(application,request,response);
try
{
hsm.login();
}
catch ( UserNotFoundException e)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=User%20does%20not%20exist.");
return;
}
catch ( InvalidPasswordException e2)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=Invalid%20Password");
return;
}
catch ( Exception e3)
{
%Q?Error:Q?=e3.toString() %Q<brQ?br />
Press Qa href="login.jsp"QHereQ?aQ?to relogin.
Q? return;
}
response.sendRedirect("index.jsp");
%Q?/td>
再来看看现在我们怎么得到一个当前在U的用户列表?br />
Qbody bgcolor="#FFFFFF"Q?br />
Qtable cellspacing="0" cellpadding="0" width="100%"Q?br />
Qtr Q?br />
Qtd style="width:24px"QSessionId
Q?tdQ?br />
Qtd style="width:80px" QUser
Q?tdQ?br />
Qtd style="width:80px" QLogin Time
Q?tdQ?br />
Qtd style="width:80px" QLast access Time
Q?tdQ?br />
Q?trQ?br />
Q?
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions == null)
{
activeSessions = new Vector();
application.setAttribute("activeSessions",activeSessions);
}
Iterator it = activeSessions.iterator();
while (it.hasNext())
{
HttpSession sess = (HttpSession)it.next();
JDBCUser sessionUser = (JDBCUser)sess.getAttribute("user");
String userId = (sessionUser!=null)?sessionUser.getUserID():"None";
%Q?br />
QtrQ?br />
Qtd nowrap=''Q<%= sess.getId() %Q</tdQ?br />
Qtd nowrap=''Q<%= userId %Q</tdQ?br />
Qtd nowrap=''Q?br />
Q?= BeaconDate.getInstance( new java.util.Date(sess.getCreationTime())).getDateTimeString()%Q</tdQ?br />
Qtd class="Q?= stl %Q?" nowrap=''Q?br />
Q?= BeaconDate.getInstance( new java.util.Date(sess.getLastAccessedTime())).getDateTimeString()%Q</tdQ?br />
Q?trQ?br />
Q?
}
%Q?br />
Q?tableQ?br />
Q?bodyQ?/td>
以上的代码从application中取出activeSessionsQƈ且显C出具体的时间。其中BeaconDatecd设ؓ格式化时间的cR?br />
q样Q我们得C一个察看在U用L列表的框架。至于在U用户列表分늭功能Q与本文无关Q不予讨论?br />
q是一个非h模型的例子,依赖于session的超时机制。我的同事sonymusic指出很多时候由于各个厂商思想的不同,q有可能是不可信赖的?
考虑到这U需求,需要在每个叉h的时候都判断当前用户距离上次使用的时间是否超q某一个预定时间倹{这实质上就是自己实现session时。如果需
要实现刷新模型,必M用这U每个叶面进行刷新判断的Ҏ?
]]>
目名称
目描述
ASM
Java bytecode manipulation framework
AspectWerkz
AspectWerkz - Dynamic AOP for Java
Axis
Axis - an implementation of the SOAP (Simple Object
Access Protocol) submission to W3C
Batik
Batik SVG Toolkit - Toolkit using images in the
Scalable Vector Graphics (SVG) format
BCEL
Byte Code Engineering Library - Analyze, create and
manipulate Java class files
BeanUtils
BeanUtils - Utilities for working with
JavaBeans
Catalina
Catalina - Servlet and JSP based web server
Cayenne
Professional Object Relational Mapping
CGLIB
CGLIB - Dynamic byte code generatorhttp://andyluo.blogjava.net
Chain
Chain - Implementation of the GoF "Chain of
Responsibility" pattern
Checkstyle
Checkstyle - Development tool to help writing Java
code that adheres to a coding standard
CLI
Command Line Library - Simple API for working with
the command line arguments and options
Codec
Commons Codec - Encoders and decoders like Base64,
Hex, phonetic encodings and URLs
Collections
Collections - Filling the holes left in Sun's
Collections API
Configuration
Commons Configuration - Generic API enabling
configuration from a variety of sources
DBCP
DBCP - Connection pooling implementations
DBUtils
DbUtils - Set of classes designed to make working
with JDBC easier
Digester
Struts Digester - Configure an XML/Java mapping with
actions when patterns are recognized
Discovery
Discovery - Discovering, or finding, implementations
for pluggable interfaces
DNSJava
DNS in Java - Supporting common record types,
queries, zone transfers and dynamic updates
doclet
JavaDoc Doclet - Custom output from the types methods
and fields in a source tree.
Dom4j
DOM4J - XML, XPath and XSLT library
DTDParser
DTDParse DTD Library - You can use this library to
parse a DTD
EL
EL - The JSP 2.0 Expression Language Interpreter from
Apache
fastutil
FastUtil - Type-specific maps sets and lists with a
small memory footprint and fast access
FileUpload
HTTP File Upload Library - Add robust, fast file
upload capability to your web applications
FreeMarker
HTML Template Enginehttp://andyluo.blogjava.net
GJT
Giant Java Tree - Java library consisting entirely of
open source components
gnu-regex
GNU Regular Expressions - Implementation of a
traditional (non-POSIX) NFA regex engine
Groovy
Groovy - Scripting Language
Hibernate
Hibernate - Relational Persistence For Idiomatic
Java
HiveMind
HiveMind - A services and configuration
microkernel
HSQLDB
HSQLDB - The Java SQL relational database
HTMLParser
HTML Parser - Java library used to parse
HTML
HTTPClient
HTTP Client - Fills holes left by the java.net
package, including most recent HTTP standards
Informa
Informa - News aggregation library
IO
Commons-IO - Utility classes, stream implementations,
file filters and endian classes for IO
iText
iText - Generates PDF on the fly
J2EE
Java 2 Platform, Enterprise Edition
J2SE
Java2 Standard Edition v5
JAI
Java Advanced Imaging - Network-enabled, scalable,
platform-independent image processing
Jalopy
Jalopy Source Formatter - Formats Java source code
according to widely configurable rules
Jasper
Jasper - Tomcat JSP enginehttp://andyluo.blogjava.net
JasperReports
JasperReports - Free Java reporting library
Java3d
Java3D - Object-oriented interfaces that support a
simple, high-level programming mode
JavaComm
Java Communications - API for technologies such as
voice mail, fax and smartcards
JavaGroups
JavaGroups - Reliable multicast communication enable
processes to send messages to each other
Jaxen
Jaxen XPath Processor - Object model walker; evaluate
XPath expressions in dom4j and JDOM
JAXME
JaxMe 2 - Open source implementation of
JAXB
JClassLib
JClassLib - Library for reading, modifing and writing
Java class files and bytecode
JCommon
JCommon - Collection of useful classes used by
JFreeChart, JFreeReport and other projects
JCrontab
JCronTab - Scheduler written in Java, provide a fully
functional schedules for Java projects
JDIC
JDIC - JDesktop Integration Components
JDNC
JDNC - JDesktop Network Components
JDO
Java Data Objects - Direct storage of Java domain
model instances into a database
JDOM
JDOM XML Library - For accessing, manipulating and
outputting XML data from Java code.
JetSpeed
JetSpeed - Java Portal Server
JEXL
Java Expression Language - is an embedable expression
language engine
JFreeChart
JFreeChart - Free library for generating charts,
including pie, bar, line and areas charts
JGroups
JGroups - Multicast communication toolkit
JMeter
JMeter - Load testing applcation
JMF
Java Media Framework - Library for audio, video and
other time-based media
JMock
JMock - Testing library
JSF
JavaServer Faces - Web Framework
JSword
JSword - Bible software in Java, compatible with the
Sword project for C/C++
JTidy
JTidy - HTML syntax checker
JUnit
JUnit - Regression testing framework used by the
developer who implements unit tests in Java
JXPath
JXPath Library - Simple interpreter of an expression
language called XPath
Lang
Lang - Utilities including Enums, String
manipulation, reflection, serialization and more
Log4J
Log4J - Fast logging API that lets you configure
logging at runtime
Logging
Commons Logging - Simple wrapper API around multiple
logging APIs
Lucene
Lucene - high-performance, full-featured text search
engine written entirely in Java
Math
Math - Library of lightweight, self-contained
mathematics and statistics components
Net
Network Library - Support for Finger, Whois, TFTP,
Telnet, FTP, NNTP, etc developed by ORO
OJB
OJB - O/R tool that allows transparent
persistence
OpenJMS
Open source JMS server
ORO
ORO - Text processing library
OSCache
OSCache - A high performance J2EE caching
framework
PJA
Pure Java AWT - Toolkit for drawing graphics without
any native graphics resources
PMD
PMD - Scans Java source code for potential
problems
POI
POI - Java OLE 2 Manipulator
Pool
Commons Pooling - provides an generic, configurable
Object-pooling API
Primitives
Primitives - Collection of types and utilities
optimized for working with Java primitives
Proxool
Java connection pool
Quartz
Quartz - J2EE open source job scheduler
Regexp
Jakarta Regular Expressions - Java RegEx library
under BSD style license
Rhino
Mozilla JavaScript - open-source implementation of
JavaScript written entirely in Java
Seraph
Seraph - Atlassian Security Framework
SiteMesh
A web-page layout and decoration framework
Slide
Slide - Content repository, can serve as a basis for
CMS
SOAP
Apache Soap - implementation of the SOAP submission
to W3C
Speedo
OSS JDO implementationhttp://andyluo.blogjava.net
Spring
Server Side alternative to J2EE APIs
Struts
Jakarta Struts - open source framework for building
web applications
Tapestry
Tapestry - Web Framework
Turbine
Turbine - Servlet based framework allowing developers
to quickly build secure web applications
UDDI4J
UDDI4J - Library that provides an API to interact
with a UDDI registry
Validator
Validtator - Validate data from user input
Velocity
Velocity - Support for clean, quick MVC web
development and support for the Struts framework
Village
Village - API that sits on top of the JDBC to make
it easier to interact with a JDBC
WebWork 2
Next generation of WebWork
Xalan
Xalan - XSLT processor for transforming XML documents
into HTML, text, or XML
XDoclet
XDoclet - Code generation engine
Xerces
Xerces2 - The next generation of high performance,
XML parsers in the Apache Xerces family
XMLBeans
XMLBeans - XML-Java binding toolhttp://andyluo.blogjava.net
XMLPull
XMLPull - Defines a simple pull parsing API that does
pull XML parsing from J2ME to J2EE
XMLRPC
XML-RPC - Implementation of XML-RPC, using XML over
HTTP to implement remote procedure calls
XNI
Xerces Native Interface - Framework for streaming a
document and constructing generic parsers
XOM
XML Object Model - Tree-based API for processing XML
that strives for correctness and simplicity.
XStream
XML serialization
]]>
ThreadLocal是什?
ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ而是thread
local
variableQ线E局部变量)。也许把它命名ؓThreadLocalVar更加合适。线E局部变量(ThreadLocalQ其实的功用非常单,是为每一个用该变量的线E都提供一个变量值的副本Q是每一个线E都可以独立地改变自q副本Q而不会和其它U程的副本冲H。从U程的角度看Q就好像每一个线E都完全拥有该变量。线E局部变量ƈ不是Java的新发明Q在其它的一些语a~译器实玎ͼ如IBM
XL
FORTRANQ中Q它在语a的层ơ提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线E局部变量的代码相对比较W拙Q这也许是线E局部变量没有在Java中得到很好的普及的一个原因吧?
ThreadLocal的设?
首先看看ThreadLocal的接口:
Object get() ;
// q回当前U程的线E局部变量副?protected Object initialValue(); //
q回该线E局部变量的当前U程的初始?
void set(Object value);
// 讄当前U程的线E局部变量副本的?
ThreadLocal?个方法,其中值得注意的是initialValue()Q该Ҏ是一个protected的方法,昄是ؓ了子c重写而特意实现的。该Ҏq回当前U程在该U程局部变量的初始|q个Ҏ是一个gq调用方法,在一个线E第1ơ调用get()或者set(Object)时才执行Qƈ且仅执行1ơ。ThreadLocal中的实实现直接q回一个nullQ?
protected Object initialValue() { return null; }
ThreadLocal是如何做Cؓ每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ用于存储每一个线E的变量的副本。比如下面的CZ实现Q?
public class ThreadLocal
{
private Map values =
Collections.synchronizedMap(new HashMap());
public Object
get()
{
Thread curThread = Thread.currentThread();
Object o
= values.get(curThread);
if (o == null &&
!values.containsKey(curThread))
{
o =
initialValue();
values.put(curThread, o);
}
return
o;
}
public void set(Object
newValue)
{
values.put(Thread.currentThread(),
newValue);
}
public Object
initialValue()
{
return
null;
}
}
当然Q这q不是一个工业强度的实现Q但JDK中的ThreadLocal的实现M思\也类g此?
ThreadLocal的?
如果希望U程局部变量初始化其它|那么需要自己实现ThreadLocal的子cdƈ重写该方法,通常使用一个内部匿名类对ThreadLocalq行子类化,比如下面的例子,SerialNumcMؓ每一个类分配一个序?
public class SerialNum
{
// The next serial number to
be assigned
private static int nextSerialNum = 0;
private
static ThreadLocal serialNum = new ThreadLocal()
{
protected
synchronized Object initialValue()
{
return new
Integer(nextSerialNum++);
}
};
public static int
get()
{
return ((Integer)
(serialNum.get())).intValue();
}
}
SerialNumcȝ使用非常地单,因ؓget()Ҏ是static的,所以在需要获取当前线E的序号Ӟ单地调用Q?
int serial = SerialNum.get();
卛_?
在线E是zd的ƈ且ThreadLocal对象是可讉K的时Q该U程持有一个到该线E局部变量副本的隐含引用Q当该线E运行结束后Q该U程拥有的所以线E局部变量的副本都将失效Qƈ{待垃圾攉器收集?
ThreadLocal与其它同步机制的比较
ThreadLocal和其它同步机制相比有什么优势呢QThreadLocal和其它所有的同步机制都是Z解决多线E中的对同一变量的访问冲H,在普通的同步机制中,是通过对象加锁来实现多个线E对同一变量的安全访问的。这时该变量是多个线E共享的Q用这U同步机刉要很l致地分析在什么时候对变量q行dQ什么时候需要锁定某个对象,什么时候释放该对象的锁{等很多。所有这些都是因为多个线E共享了资源造成的。ThreadLocal׃另一个角度来解决多线E的q发讉KQThreadLocal会ؓ每一个线E维护一个和该线E绑定的变量的副本,从而隔M多个U程的数据,每一个线E都拥有自己的变量副本,从而也没有必要对该变量进行同步了。ThreadLocal提供了线E安全的׃n对象Q在~写多线E代码时Q可以把不安全的整个变量装qThreadLocalQ或者把该对象的特定于线E的状态封装进ThreadLocal?
׃ThreadLocal中可以持有Q何类型的对象Q所以用ThreadLocal
get当前U程的值是需要进行强制类型{换。但随着新的Java版本Q?.5Q将模版的引入,新的支持模版参数的ThreadLocalcd从中受益。也可以减少强制cd转换Qƈ一些错误检查提前到了编译期Q将一定程度地化ThreadLocal的用?
ȝ
当然ThreadLocalq不能替代同步机Ӟ两者面向的问题领域不同。同步机制是Z同步多个U程对相同资源的q发讉KQ是Z多个U程之间q行通信的有效方式;而ThreadLocal是隔d个线E的数据׃nQ从Ҏ上就不在多个U程之间׃n资源Q变量)Q这样当然不需要对多个U程q行同步了。所以,如果你需要进行多个线E之间进行通信Q则使用同步机制Q如果需要隔d个线E之间的׃n冲突Q可以用ThreadLocalQ这极大地化你的程序,使程序更加易诅R简z?/div>
]]>
在o/r映射的时候出现的概念Q如果没有o/r映射Q没有这个概念存在了。通常?
应数据模?数据?,本nq有部分业务逻辑的处理。可以看成是与数据库中的表相映射的java对象。最单的PO是对应数据库中某个表中的一条记录,
多个记录可以用PO的集合。PO中应该不包含MҎ据库的操作?
VO(value object) 值对?
通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,q根据业务的需?个h觉得同DTO(数据传输对象),在web上传递?nbsp;
TO(Transfer Object)Q数据传输对?br />
在应用程序不同tie(关系)之间传输的对?nbsp;
BO(business object) 业务对象
从业务模型的角度?见UML元g领域模型中的领域对象。封装业务逻辑的java对象,通过调用DAOҎ,l合PO,VOq行业务操作?nbsp;
POJO(plain ordinary java object) 单无规则java对象
U?
的传l意义的java对象。就是说在一些Object/Relation Mapping工具中,能够做到l护数据库表记录?
persisent object完全是一个符合Java Bean规范的纯Java对象Q没有增加别的属性和Ҏ。我的理解就是最基本?
Java BeanQ只有属性字D及setter和getterҎQ?
DAO(data access object) 数据讉K对象
?
一个sun的一个标准j2ee设计模式Q这个模式中有个接口是DAOQ它负持久层的操作。ؓ业务层提供接口。此对象用于讉K数据库。通常和POl合?
用,DAO中包含了各种数据库的操作Ҏ。通过它的Ҏ,l合POҎ据库q行相关的操作。夹在业务逻辑与数据库资源中间。配合VO,
提供数据库的CRUD操作...
O/R Mapper 对象/关系 映射
定义好所有的mapping之后Q这个O/R Mapper可以帮我们做很多的工作。通过q些mappings,q个O/R Mapper可以生成所有的关于对象保存Q删除,d的SQL语句Q我们不再需要写那么多行的DAL代码了?nbsp;
实体Model(实体模式)
DAL(数据讉K?
IDAL(接口?
DALFactory(cd?
BLL(业务逻辑?
BOF Business Object Framework 业务对象框架
SOA Service Orient Architecture 面向服务的设?
EMF Eclipse Model Framework Eclipse建模框架
服务器环境变?/font> | 功能q?/font> |
localhost | 服务器的域名 |
192.168.0.5 | 服务器的IP地址 |
Windows XP | 服务器操作系l?/td> |
1.6.0 | 服务?Java 虚拟机版?/td> |
2.5 | 服务器支持的 Servlet API 版本 |
2.1 | 服务器支持的 JSP API 版本 |
Apache Tomcat/6.0.16 | 服务器Y件的名称及版? Tomcat 6.0) |
8080 | 服务器正在运行的端口 |
pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 | 服务?CPU cd |
D:"Java"Tomcat6.0.16"webapps"ROOT"env.jsp | h的物理\?/td> |
null | 在域名根目录外的到被h面的\?/td> |
GET | 发出request的方?/td> |
null | 通过使用GETҎ提交的Q何数?/td> |
/env.jsp | E序被调用的路径 |
127.0.0.1 | 发出requesth的远端机器的名称 |
127.0.0.1 | 发出requesth的远端机器的IP名称 |
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322) | 客户h的浏览器cd |
面源代码:
env.jsp
<%--
env.jsp
服务器信息
@version: 1.00
Note:
TODO:
Date: 2005-10-10
@author: BeanSoft
--%>
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%><html>
<style>
a:hover{color:orange}
</style>
<title>服务器环境变?lt;/title>
<body><p>
<table width=90% border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#99CCFF" style="border-collapse: collapse">
<tr>
<td width="50%" align="center" bgcolor="#99CCFF"><font color="#FFFFFF">服务器环境变?lt;/font></td>
<td height="16" align="center" bgcolor="#99CCFF"><font color="#FFFFFF">功能q?lt;/font></td>
</tr>
<tr>
<td width="50%"><%= request.getServerName()%> </td>
<td height="4">服务器的域名</td>
</tr>
<tr>
<td width="50%"><%= java.net.InetAddress.getLocalHost().getHostAddress() %> </td>
<td height="4">服务器的IP地址</td>
</tr>
<tr>
<td width="50%"><%=System.getProperty("os.name")%> </td>
<td height="4">服务器操作系l?lt;/td>
</tr>
<tr>
<td width="50%"><%=System.getProperty("java.version")%> </td>
<td height="4">服务?Java 虚拟机版?lt;/td>
</tr>
<tr>
<td width="50%"><%=application.getMajorVersion() + "." + application.getMinorVersion()%> </td>
<td height="4">服务器支持的 Servlet API 版本</td>
</tr>
<tr>
<td width="50%"><%=JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion()%> </td>
<td height="4">服务器支持的 JSP API 版本</td>
</tr>
<tr>
<td width="50%"><%=application.getServerInfo()%> </td>
<td height="4">服务器Y件的名称及版?
Tomcat 6.0)</td>
</tr>
<tr>
<td width="50%"><%=request.getServerPort()%> </td>
<td height="5">服务器正在运行的端口</td>
</tr>
<tr>
<td width="50%"><%=System.getProperty("sun.cpu.isalist")%></td>
<td height="5">服务?CPU cd</td>
</tr>
<tr>
<td width="50%"><%=request.getRealPath(request.getServletPath())%> </td>
<td height="4">h的物理\?lt;/td>
</tr>
<tr>
<td width="50%"><%=request.getPathInfo()%> </td>
<td height="4">在域名根目录外的到被h面的\?lt;/td>
</tr>
<tr>
<td width="50%"><%=request.getMethod()%> </td>
<td height="4">发出request的方?lt;/td>
</tr>
<tr>
<td width="50%"><%=request.getQueryString()%> </td>
<td height="4">通过使用GETҎ提交的Q何数?lt;/td>
</tr>
<tr>
<td width="50%"><%=request.getServletPath()%> </td>
<td height="4">E序被调用的路径</td>
</tr>
<tr>
<td width="50%"><%=request.getRemoteHost()%> </td>
<td height="4">发出requesth的远端机器的名称</td>
</tr>
<tr>
<td width="50%"><%=request.getRemoteAddr()%> </td>
<td height="5">发出requesth的远端机器的IP名称</td>
</tr>
<tr>
<td width="50%"><%=request.getHeader("User-Agent")%> </td>
<td height="4">客户h的浏览器cd</td>
</tr>
</table>
</body>
</html>
下面是序列化和外部化在代码的关联方式:
public interface Serializable {}
public interface Externalizable
extends Serializable {
void readExternal(ObjectInput
in);
void writeExternal(ObjectOutput
out);
}
序列化和外部化的主要区别
外部化和序列化是实现同一目标的两U不同方法。下面让我们分析一下序列化和外部化之间的主要区别?/p>
通过Serializable接口对对象序列化的支持是内徏于核?API 的,但是java.io.Externalizable的所有实现者必L供读取和写出的实现。Java 已经h了对序列化的内徏支持Q也是说只要制作自qcjava.io.SerializableQJava ׃试图存储和重l你的对象。如果用外部化Q你可以选择完全p己完成读取和写出的工作,Java 对外部化所提供的唯一支持是接口:
voidreadExternal(ObjectInput in)
void writeExternal(ObjectOutput
out)
现在如何实现readExternal() 和writeExternal() 完全看你自׃?/p>
序列化会自动存储必要的信息,用以反序列化被存储的实例Q而外部化则只保存被存储的cȝ标识。当你通过 java.io.Serializable接口序列化一个对象时Q有关类的信息,比如它的属性和q些属性的cdQ都与实例数据一赯存储h。在选择? Externalizableq条路时QJava 只存储有x个被存储cd的非常少的信息?/p>
每个接口的优点和~点
Serializable接口
· 优点Q?/strong>内徏支持
· 优点Q?/strong>易于实现
· ~点Q?/strong>占用I间q大
· ~点Q?/strong>׃额外的开销D速度变比较慢
Externalizable接口
· 优点Q?/strong>开销较少Q程序员军_存储什么)
· 优点Q?/strong>可能的速度提升
·
~点Q?/strong>虚拟Z提供M帮助Q也是说所有的工作都落C开发h员的肩上?/p>
在两者之间如何选择要根据应用程序的需求来定。Serializable通常是最单的解决ҎQ但是它可能会导致出C可接受的性能问题或空间问题;在出现这些问题的情况下,Externalizable可能是一条可行之路?/p>
要记住一点,如果一个类是可外部化的QExternalizableQ,那么ExternalizableҎ被用于序列化类的实例,即ɘq个cd提供了SerializableҎQ?/p>
private void writeObject() 本文作者:David Petersheim是Genscape公司的应用程序开发部MQ。他设计和开发用于获取和处理实时能源数据的服务器端应用程序?/p>
private void readObject()
]]>
一、概q?/font>
ProcesscL一个抽象类Q所有的Ҏ均是抽象的)Q封装了一个进E(即一个执行程序)?br />
Process cL供了执行从进E输入、执行输出到q程、等待进E完成、检查进E的退出状态以及销毁(杀掉)q程的方法?br />
ProcessBuilder.start() ?Runtime.exec Ҏ创徏一个本E,q返?Process 子类的一个实例,该实例可用来控制q程q获取相关信息?
创徏q程的方法可能无法针Ҏ些本机^C的特定进E很好地工作Q比如,本机H口q程Q守护进E,Microsoft Windows 上的 Win16/DOS q程Q或?shell 脚本。创建的子进E没有自ql端或控制台。它的所有标?ioQ即 stdinQstdoutQstderrQ操作都通过三个? (getOutputStream()QgetInputStream()QgetErrorStream()) 重定向到父进E。父q程使用q些来提供到子q程的输入和获得从子q程的输出。因为有些本机^C针对标准输入和输出流提供有限的缓冲区大小Q如果读写子 q程的输出流或输入流q速出现失败,则可能导致子q程dQ甚至生死锁?
当没?Process 对象的更多引用时Q不是删掉子q程Q而是l箋异步执行子进E?
二、API预览
destroy()
杀掉子q程?
exitValue()
q回子进E的出口倹{?
InputStream getErrorStream()
获得子进E的错误?
InputStream getInputStream()
获得子进E的输入?
OutputStream getOutputStream()
获得子进E的输出?
waitFor()
D当前U程{待Q如果必要,一直要{到p Process 对象表示的进E已l终止?
三、如何创建Process对象Q一般有一下两U方法:
1、每?ProcessBuilder 实例理一个进E属性集。start() Ҏ利用q些属性创Z个新?Process 实例。start() Ҏ可以从同一实例重复调用Q以利用相同的或相关的属性创建新的子q程。(ProcessBuilderq个是JDK5中新d的finalc,详细请参 ?#8220;深入研究java.lang.ProcessBuilderc?#8221;一文?
2、Runtime.exec() Ҏ创徏一个本E,q返?Process 子类的一个实例。详l请参看“深入研究java.lang.Runtimec?#8221;一文?
四、官方API文?/strong>
java.lang.Object
java.lang.Process
public abstract class Process
Process
子类的一个实例,该实例可用来控制q程q获取相关信息?code>Process
对象的更多引用时Q不是删掉子q程Q而是l箋异步执行子进E?
对于带有 Process
对象表示的进E?
构造方法摘?/strong>
()
Ҏ摘要
abstract void
()
杀掉子q程?/td>
abstract int
()
q回子进E的出口倹{?/td>
()
获得子进E的错误?/td>
()
获得子进E的输入?/td>
()
获得子进E的输出?/td>
abstract int
()
D当前U程{待Q如果必要,一直要{到p
从类 java.lang.Object l承的方?/strong>
, , , , , , , , , ,
构造方法详l信?/strong>
Process
public Process()
Ҏ详细信息
getOutputStream
public abstract OutputStream getOutputStream()
- 获得子进E的输出。输出流被传送给p
getInputStream
public abstract InputStream getInputStream()
- 获得子进E的输入。输入流获得p
getErrorStream
public abstract InputStream getErrorStream()
- 获得子进E的错误。错误流获得p
waitFor
public abstract int waitFor()
throws InterruptedException
- D当前U程{待Q如果必要,一直要{到p
0
表示正常l止?
- 抛出Q?/strong>
exitValue
public abstract int exitValue()
- q回子进E的出口倹{?
-
- q回Q?/strong>
- ?
0
表示正常l止?
- 抛出Q?/strong>
Process
对象表示的子q程未l止?/dd>
destroy
public abstract void destroy()