??xml version="1.0" encoding="utf-8" standalone="yes"?>
2、用注意:(x)
.properties文g是放在class包中的,不是在源码src?br />
2: java org.apache.axis.wsdl.WSDL2Java -p com.hnisi.axis.client
http://192.168.3.42:8080/test/services/BookOrder?wsdl
前提QAXIS环境配好
在本文中Q我们下载的JBoss版本为:(x)4.2.1.GA?/span>
下蝲地址Q?/span>
在如上的下蝲中下蝲JBoss-4.2.1.GA.zip文g?/span>
下蝲完成后,其解压~后卛_完成安装Q解压羃后将其放|到一个不带空格的目录(若目录带有空|例如Q?/span>C:"Program FilesQ日后可能会(x)产生一些莫名的错误)Q?/span>egQ?/span>E:"JBoss4.2.1。同时在“环境变量设|”中讄名ؓ(f)JBOSS_HOME的环境变量,gؓ(f)JBoss的安装\径,如下图所C:(x)
在此Q?/span>JBoss的安装工作已l结束,可通过如下方式试安装是否成功Q?/span>
q行JBoss安装目录"bin"run.batQ如果窗口中没有出现异常Q且出现Q?/span>10:16:19,765 INFO [Server] JBoss (MX MicroKernel) [4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)] Started in 30s:828ms字样Q则表示安装成功?/span>
我们可以通过讉KQ?/span> http://localhost:8080/ q入JBoss的欢q界面,点击JBoss Management下的JMX Console可进?/span>JBoss的控制台?/span>
若启动失败,可能׃下原因引P(x)
1Q?span style="FONT: 7pt 'Times New Roman'"> JBoss所用的端口Q?/span>8080Q?/span>1099Q?/span>1098Q?/span>8083{)被占用。一般情况下?/span>8080端口被占用(例如Q?/span>Oracle占用?/span>8080端口Q,此时需要修?/span>JBoss的端口,Ҏ(gu)?/span>JBoss安装目录"server"default"deploy"jboss-web.deployer目录Q修改其下的server.xml目录Q在此文件中搜烦8080Q将其改成你惌的端口即可(例如8088Q;
2Q?span style="FONT: 7pt 'Times New Roman'"> JDK安装不正;
3Q?span style="FONT: 7pt 'Times New Roman'"> JBoss下蝲不完全?/span>
二. JBoss 的目录结构说?/span>
目录 |
描述 |
bin |
启动和关?/span> JBoss 的脚本( run.bat ?/span> windows pȝ下的启动脚本Q?/span> shutdown.bat ?/span> windows pȝ下的关闭脚本Q?/span> |
client |
客户端与 JBoss 通信所需?/span> Java 库( JARs Q?/span> |
docs |
配置的样本文Ӟ数据库配|等Q?/span> |
docs/dtd |
?/span> JBoss 中用的各种 XML 文g?/span> DTD ?/span> |
lib |
一?/span> JAR Q?/span> JBoss 启动时加载,且被所?/span> JBoss 配置׃n。(不要把你的库攑֜q里Q?/span> |
server |
各种 JBoss 配置。每个配|必L在不同的子目录。子目录的名字表C配|的名字?/span> JBoss 包含 3 个默认的配置Q?/span> minimial Q?/span> default ?/span> all Q在你安装时可以q行选择?/span> |
server/all |
JBoss 的完全配|,启动所有服务,包括集群?/span> IIOP ?/span> |
server/default |
JBoss 的默认配|。在没有?/span> JBoss 命o(h)行中指定配置名称时用?/span> ( 我们下蝲?/span> 4.2.1 版本默认采用此配|?/span> ) ?/span> |
server/default/conf |
JBoss 的配|文件?/span> |
server/default/data |
JBoss 的数据库文g。比如,嵌入的数据库Q或?/span> JBossMQ |
server/default /deploy |
JBoss 的热部v目录。放到这里的M文g或目录会(x)?/span> JBoss 自动部v?/span> EJB ?/span> WAR ?/span> EAR Q甚x务?/span> |
server/default /lib |
一?/span> JAR Q?/span> JBoss 在启动特定配|时加蝲他们?/span> (default ?/span> minimial 配置也包含这个和下面两个目录?/span> ) |
server/default/log |
JBoss 的日志文件?/span> |
server/default/tmp |
JBoss 的(f)时文件?/span> |
三. JBoss 的配|?/span>
1. 日志文g讄
若需要修?/span>JBoss默认?/span>log4j讄Q可修改JBoss安装目录"server"default"conf下的jboss-log4j.xml文gQ在该文件中可以看到Q?/span>log4j的日志输出在JBoss安装目录"server"default"log下的server.log文g中。对?/span>log4j的设|,读者可以在|上搜烦更加详细的信息?/span>
2. web 服务的端口号的修?/span>
q点在前文中有所提及(qing)Q即修改JBoss安装目录"server"default"deploy"jboss-web.deployer下的server.xml文gQ内容如下:(x)
<Connector port="8080" address="${jboss.bind.address}"
maxThreads="250" maxHttpHeaderSize="8192"
emptySessionPath="true" protocol="HTTP/1.1"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
上面的8080端口修改Z惌的端口即可。重新启?/span>JBoss后访问:(x)http://localhost/:新设|的端口Q可看到JBoss的欢q界面?/span>
3. JBoss 的安全设|?/span>
1Q?/strong> jmx-console d的用户名和密码设|?/span>
默认情况讉K http://localhost:8080/jmx-console 可以浏?/span>jboss的部|管理的一些信息,不需要输入用户名和密码,使用h有点安全隐?zhn)。下面我们针Ҏ(gu)问题?/span>jbossq行配置Q得访?/span>jmx-console也必要知道用户名和密码才可q去讉K。步骤如下:(x)
i) 扑ֈJBoss安装目录/server/default/deploy/jmx-console.war/WEB-INF/jboss-web.xml文gQ去?/span><security-domain>java:/jaas/jmx-console</security-domain>的注释。修改后的该文g内容为:(x)
<jboss-web>
<!-- Uncomment the security-domain to enable security. You will
need to edit the htmladaptor login configuration to setup the
login modules used to authentication users.-->
<security-domain>java:/jaas/jmx-console</security-domain>
</jboss-web>
iiQ修改与iQ中?/span>jboss-web.xml同目录下的web.xml文gQ查扑ֈ<security-constraint/>节点Q去掉它的注释,修改后该部分内容为:(x)
<!-- A security constraint that restricts access to the HTML JMX console
to users with the role JBossAdmin. Edit the roles to what you want and
uncomment the WEB-INF/jboss-web.xml/security-domain element to enable
secured access to the HTML JMX console.-->
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role JBossAdmin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>
在此处可以看出,为登录配|了角色JBossAdmin?/span>
iiiQ?/span> 在第一步中?/span>jmx-console安全域和W二步中的运行角?/span>JBossAdmin都是?/span>login-config.xml中配|,我们?/span>JBoss安装目录/server/default/config下找到它。查扑字ؓ(f)Q?/span>jmx-console?/span>application-policyQ?/span>
<application-policy name = "jmx-console">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
<module-option name="usersProperties">props/jmx-console-users.properties</module-option>
<module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
</login-module>
</authentication>
</application-policy>
在此处可以看出,d的角艌Ӏ用L(fng)的信息分别在props目录下的jmx-console-roles.properties?/span>jmx-console-users.properties文g中设|,分别打开q两个文件?/span>
其中jmx-console-users.properties文g的内容如下:(x)
# A sample users.properties file for use with the UsersRolesLoginModule
admin=admin
该文件定义的格式为:(x)用户?/span>=密码Q在该文件中Q默认定义了一个用户名?/span>adminQ密码也?/span>admin的用P读者可其Ҏ(gu)所需的用户名和密码?/span>
jmx-console-roles.properties的内容如下:(x)
# A sample roles.properties file for use with the UsersRolesLoginModule
admin=JBossAdmin, HttpInvoker
该文件定义的格式为:(x)用户?/span>=角色Q多个角色以?/span>,”隔开Q该文g默认?/span>admin用户定义?/span>JBossAdmin?/span>HttpInvokerq两个角艌Ӏ?/span>
配置完成后读者可以通过讉KQ?/span> http://localhost:8088/jmx-console/ Q输?/span>jmx-console-roles.properties文g中定义的用户名和密码Q访?/span>jmx-console的页面?/span>
2Q?/strong> web-console d的用户名和密码设|?/span>
默认情况下,用户讉KJBoss?/span>web-consoleӞ不需要输入用户名和密码,Z安全赯Q我们通过修改配置来ؓ(f)其加上用户名和密码。步骤如下:(x)
iQ找?/span>JBoss安装目录"server"default"deploy"management"console-mgr.sar"web-console.war"WEB-INF"jboss-web.xml文gQ去?/span><security-domain>java:/jaas/web-console</security-domain>的注释,修改后的文g内容为:(x)
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE jboss-web
PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>
<!-- Uncomment the security-domain to enable security. You will
need to edit the htmladaptor login configuration to setup the
login modules used to authentication users.-->
<security-domain>java:/jaas/web-console</security-domain>
<!-- The war depends on the -->
<depends>jboss.admin:service=PluginManager</depends>
</jboss-web>
iiQ打开iQ中jboss-web.xml同目录下?/span>web.xml文gQ去?/span><security-constraint>部分的注释,修改后的该部分内容ؓ(f)Q?/span>
<!-- A security constraint that restricts access to the HTML JMX console
to users with the role JBossAdmin. Edit the roles to what you want and
uncomment the WEB-INF/jboss-web.xml/security-domain element to enable
secured access to the HTML JMX console.-->
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role JBossAdmin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>
iiiQ打开JBoss安装目录"server"default"conf下的login-config.xml文gQ搜?/span>web-consoleQ可扑ֈ如下内容Q?/span>
<application-policy name = "web-console">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
<module-option name="usersProperties">web-console-users.properties</module-option>
<module-option name="rolesProperties">web-console-roles.properties</module-option>
</login-module>
</authentication>
</application-policy>
在文件中可以看到Q设|登?/span>web-console的用户名和角色等信息分别?/span>login-config.xml文g所在目录下?/span>web-console-users.properties?/span>web-console-roles.properties文g中,但因目录下无q两个文Ӟ我们?/span>JBoss安装目录"server"default"conf"props目录下徏立这两个文gQ文件内容可参考在?/span>jmx-consoled的用户名和密码设|?/span>中的两个相应的配|文件的内容Q?/span>web-console-users.properties文g的内容如下:(x)
# A sample users.properties file for use with the UsersRolesLoginModule
admin=admin
web-console-roles.properties文g的内容如下:(x)
# A sample roles.properties file for use with the UsersRolesLoginModule
admin=JBossAdmin,HttpInvoker
因ؓ(f)此时q两个文件不?/span>login-config.xml同目录,所?/span>login-config.xml文g需q行许修改Q修改后?/span><application-policy name = "web-console">元素的内容ؓ(f)Q?/span>
<application-policy name = "web-console">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
<module-option name="usersProperties">props/web-console-users.properties</module-option>
<module-option name="rolesProperties">props/web-console-roles.properties</module-option>
</login-module>
</authentication>
</application-policy>
四. ?/span>MyEclipse 中配|?/span>JBoss
W者的MyEclipse版本Q?/span>5.1.1 GA
JBoss版本Q?/span>4.2.1 GA
JDK版本Q?/span>1.5
q入Window-> Preferences-> MyEclipse -> Application Servers -> JBoss4Q进行如下设|:(x)
选择JBoss 4下的JDK讄所用的JDK.
讄完成后,部vE序Ӟ?x)发现多?/span>JBoss 4部v的选择Q如下图所C:(x)
同时?img height="25" alt="" src="http://www.aygfsteel.com/images/blogjava_net/amigoxie/21128/r_clip_image305.jpg" width="31" border="0" /> 中展开Q可看到JBoss 4的启动图标?/span>
Ҏ(gu)有很多种Q?/p>
比如Q在getRequestDispatcher("/jsp/jsptoserv/hello.jsp").forward(request, response);之前修改
request的编码,那么在jsp/jsptoserv/hello.jsp中得到的参数值就是制定的~码的字W?/p>
本文我们使用Filter来修改request的编?br />
1)首先~写filterc:(x)
package myFilter;
import java.io.IOException;
import javax.servlet.*;
public class ChangeCharsetFilter implements Filter {
protected String encoding = null;/////要制定的~码Q在web.xml中配|?br />protected FilterConfig filterConfig = null;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request.getCharacterEncoding() == null){
String encoding = getEncoding();////得到指定的编码名?br /> if (encoding != null)
request.setCharacterEncoding(encoding);////讄request的编?br /> }
chain.doFilter(request, response);///有机?x)执行下一个filter
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");///得到在web.xml中配|的~码
}
protected String getEncoding() {
return (this.encoding);///得到指定的编?br />}
}
2。编辑web.xml文g
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
? PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
? "<web-app>
<filter>
<filter-name>SetCharacterEncoding</filter-name>
<filter-class>myFilter.ChangeCharsetFilter </filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>//////指定~码为GB2312
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>////////对于所有的request改变其编?br /></filter-mapping>
</web-app>
///
3。写一个a.jsp
<%@ page contentType="text/html; charset=GB2312" %>
<html>
<head></head>
<body>
<%
String name=request.getParameter("name");///本来q里得到字符是iso-8859-1~码的,不能直接
在Console中输出的Q但是现在改变了request的编码方式,此时的name的编码是GB2312,所以能正确在Console中显C的?/p>
System.out.println(name);
%>
<form action="a.jsp" method="post">
<input type="text" name="name">
<input type="submit">
</form>
<%=name%>
</body>
</html>
完!
关于中文处理的问题就写这些了Q?/p>
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class DataStore {
DataSource dataSource = null;
private static Connection conn = null;
private Statement stmt = null;
private boolean hadErrors = false;
//construct
public DataStore(DataSource dataSource) throws Exception{
this.dataSource = dataSource;
conn = dataSource.getConnection();
stmt = conn.createStatement();
}
//invoke transaction
public void beginTransaction() throws SQLException{
conn.setAutoCommit(false);
}
//perform transaction
public void commitTransaction() throws SQLException{
//hadErrors = false
if(!hadErrors){
conn.commit();
}
else{ //hadErrors = true
conn.rollback();
hadErrors = false;
}
hadErrors = false;
conn.setAutoCommit(true);
}
//mark error
public void ErrorOccur(){
hadErrors = true;
}
//execute insert,delete,update
synchronized public void execute(String sql) throws SQLException{
if(stmt != null)
stmt.executeUpdate(sql);
else{
Log log = LogFactory.getLog("mylog");
log.error("fail to execute sql");
}
}
//execute select
synchronized public ResultSet read(String sql) throws SQLException{
if(stmt != null){
ResultSet tmp = null;
tmp = stmt.executeQuery(sql);
return tmp;
}else{
return null;
}
}
// count of result
synchronized public int readCount(String sql) throws SQLException{
int nCount = 0;
try{
if(stmt != null){
ResultSet tmp = null;
tmp = stmt.executeQuery(sql);
if(tmp != null && tmp.next()){
nCount = tmp.getInt(1);
}else{
nCount = 0;
}
}
}catch(SQLException e){
nCount = 0;
}
return nCount;
}
// close db
synchronized public void stop(){
try{
if(conn != null){
conn.close();
stmt.close();
}
}catch(Exception e){
Log log = LogFactory.getLog("mylog");
log.error("fail to close db- DataStore.java");
}finally{
conn = null;
}
}
}
q在研究Q貌似DCL的问题还存在?/p>
?/span>
1?/span>
首先E序代码获取初始化的
JNDI
环境q且调用
Context.lookup()
Ҏ(gu)?/span>
JNDI
服务提供者那里获一?/span>
DataSource
对象
?/span>
2?/span>
中间?/span>
JNDI
服务提供者返回一?/span>
DataSource
对象l当前的
Java
应用E序q个
DataSource
对象代表了中间层服务上现存的~冲数据?span lang="EN-US">
??/span>
应用E序调用
DataSource
对象?/span>
getConnection()
Ҏ(gu)
?/span>
4?/span>
?/span>
DataSource
对象?/span>
getConnection()
Ҏ(gu)被调用时Q中间层服务器将查询数据?/span>
q接~冲池中有没?/span>
PooledConnection
接口的实例对象。这?/span>
PooledConnection
对象被用于与数据库建立物理上的数据库连?span lang="EN-US">
?/span>
5?/span>
如果在缓冲池中命中了一?/span>
PooledCoonection
对象那么q接~冲池将单地?/span>
新内部的~冲q接队列q将?/span>
PooledConnection
对象q回。如果在~冲池内?/span>
有找到现成的
PooledConnection
对象Q那?/span>
ConnectionPoolDataSource
接口会(x)?/span>
用来产生一个新?/span>
PooledConnection
对象q将它返回以便应用程序?span lang="EN-US">
?/span>
6?/span>
中间层服务器调用
PooledConnection
对象?/span>
getConnection()
Ҏ(gu)以便q还一?/span>
java.sql.Connection
对象l当前的
Java
应用E序
?/span>
7?/span>
当中间层服务器调?/span>
PooledConnection
对象?/span>
getConnection()
Ҏ(gu)Ӟ
JDBC
数据
库驱动程序将?x)创Z?/span>
Connection
对象q且把它q回中间层服务器
?/span>
8?/span>
中间层服务器?/span>
Connection
对象q回l应用程?/span>
Java
应用E序Q可以认?/span>
Connection
对象是一个普通的
JDBC Connection
对象使用它可以和数据库徏立。事
实上的连接与数据库引擎生交互操?span lang="EN-US">
?/span>
9?/span>
当应用程序不需要?/span>
Connection
对象Ӟ可以调用
Connection
接口?/span>
close()
?/span>
法?font color="#ff3300">h意这U情况下
close()
Ҏ(gu)q没有关闭事实上的数据库q接Q仅仅是?/span>
放了被应用程序占用的数据库连接,q将它还l数据库q接~冲池,数据库连?/span>
~冲池会(x)自动这个数据库q接交给h队列中下一个的应用E序使用?/span>
]]>
配置tomcat
q一步的目的是告诉tomcat如何q接数据?br />可以分ؓ(f)两种大的cdQ每U类型又有很多种配置方式
配置cd一Q?br />(直接配置的类型,q种方式最?
Ҏ(gu)一Q?br />直接在tomcat_home/conf/localhost/下徏立一个xml文gQ文件名?lt;yourAppName>.xml
例如我的工程名叫jndiQ对应的名字叫jdni.xml
内容如下:
说明Q这U配|需要告诉tomcat resource的内容,resource应用于什么地?br />W一U方法通过文g名知道了app的name
W二U方式本w就在app内部Q所以name肯定知道
两种方式都要攑֜context?/p>
配置cd二:(x)
(配置全局resourceQ然后通过resourcelink来映?
步骤一Q配|全局resourceQ这一步对于所有的配置都是一L(fng)Q?br />打开tomcat_home/conf/server.xml加入
步骤二:(x)映射
(映射可以配置在多个地方,也就有多个配|方法:(x))
Ҏ(gu)一Q(Ҏ(gu)cd一的配|理解)
直接在tomcat_home/conf/localhost/下徏立一个xml文gQ文件名?lt;yourAppName>.xml
例如我的工程名叫jndiQ对应的名字叫jdni.xml加入如下内容
Ҏ(gu)三:(x)(上边两种Ҏ(gu)都是把全局的resource 映射ljndiq个web应用Q第三种Ҏ(gu)是把这?br />全局的resource直接公开l所有的应用)
在tomcat_home/conf/context.xml?lt;Context></context>之间加入
<ResourceLink global="jdbc/test" name="jdbc/test" type="javax.sql.DataSource"/>
q行试Q?br />打开ieQ输?a href="http://localhost:8080/jndi/index.jsp">http://localhost:8080/jndi/index.jsp
常见错误Q?br />1QName jdbc is not bound in this Context
2QCannot create JDBC driver of class '' for connect URL 'null' conf localhost
原因Q?br />大多数是因ؓ(f)配置了全局的resourceQ但没有link造成的?br />解决Q?br />加入linkp了,link的方式见cd二的三种Ҏ(gu)?/p>
分析Q?br />看到上边q么多方法,是否感觉D~ؕQ其实不要死记配|,按照原理分析一下就好了?br />你需要的是告诉tomcat哪个应用如何q接数据库?/p>
cd一的方式对应一个应用单独用这个配|的情况
是直接告诉tomcat"应用? "q接数据库需要的参数"
cd二的方式对应多个应用׃n一个配|的情况
q样先配|server.xml告诉tomcat全局范围?q接数据库需要的参数"
然后映射Q映的时?br />1,如果不知?app name(应用?"只需要通过文g名来传递这个信?br />2,如果"app name"都知道就只需要加入映的内容
3,如果要配|成全局公用的,׃需?app name"Q本w放在tomcat的context.xml?/p>
最后再ơ提醒一下:(x)所有的配置必须攑֜<context></context>之间
也许你听说过Hibernate的大名,但可能一直不了解它,也许你一直(f)望用它q行开发,那么本文正是你所需要的Q在本文中,我向大家重点介绍Hibernate的核心API调用库,q讲解一下它的基本配|?
看完本文后,我相信你对什么是ORMQ对?关系映射Q以?qing)它的优点?x)有一个深ȝ认识Q我们先通过一个简单的例子开始来展现它的威力?
正如一些传l的l典计算机文章大都会(x)通过一个“hello,world”的例子开始讲解一P我们也不例外Q我们也从一个相对简单的例子来阐qHibernate的开发方法,但如果要真正阐述Hibernate的一些重要思想Q仅仅靠在屏q上打印一些字W是q远不够的,在我们的CZE序中,我们创Z些对象,q将其保存在数据库中Q然后对它们q行更新和查询?
阅读D
“Hello World”“Hello world”示例程序让(zhn)对Hibernate有一个简单的认识?
理解Hibernate的架构介lHibernate接口的主要功能?
核心接口Hibernate?个核心接口,通过q几个接口开发h员可以存储和获得持久对象Qƈ且能够进行事务控?
一个重要的术语QTypeType是Hibernate发明者发明的一个术语,它在整个构架中是一个非常基、有着强大功能的元素,一个Type对象能将一个Javacd映射到数据库中一个表的字D中厅R?
{略接口Hibernate与某些其它开源Y件不同的q有一点――高度的可扩展性,q通过它的内置{略机制来实现?
基础配置Hibernate可以配置成可在Q何Java环境中运行,一般说来,它通常被用?Q?层的C/S模式的项目中Qƈ被部|在服务端?
创徏一个SessionFactory对象要创Z个SessionFactory对象Q必dHibernate初始化时创徏一个Configurationcȝ实例Qƈ已写好的映文件交由它处理?
“Hello World?
Hibernate应用E序定义了一些持久类Qƈ且定义了q些cM数据库表格的映射关系。在我们q个“Hello world”示例程序中包含了一个类和一个映文件。让我们看看q个单的持久cd含有一些什么?映射文g是怎样定义的?另外Q我们该怎样用Hibernate来操作这个持久类?
我们q个单示例程序的目的是将一些持久类存储在数据库中,然后从数据库取出来,q将其信息正文显C给用户。其中Message正是一个简单的持久c:(x)Q它包含我们要显C的信息Q其源代码如下:(x)
列表1 Message.Java 一个简单的持久c?
package hello;
public class Message {
private Long id;
private String text;
private Message nextMessage;
private Message() {}
public Message(String text) {
this.text = text;
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Message getNextMessage() {
return nextMessage;
}
public void setNextMessage(Message nextMessage) {
this.nextMessage = nextMessage;
}
}
MessagecL三个属性:(x)Message的id 、消息正文、以?qing)一个指向下一条消息的指针。其中id属性让我们的应用程序能够唯一的识别这条消息,通常它等同于数据库中的主键,如果多个Messagecȝ实例对象拥有相同的idQ那它们代表数据库某个表的同一个记录。在q里我们选择了长整型作ؓ(f)我们的id|但这不是必需的。Hibernate允许我们使用L的类型来作ؓ(f)对象的id|在后面我们会(x)Ҏ(gu)作详l描q?
你可能注意到Messagecȝ代码cM于JavaBean的代码风|q且它有一个没有参数的构造函敎ͼ在我们以后的代码中我l用这U风格来~写持久cȝ代码?
Hibernate?x)自动管理Messagecȝ实例Qƈ通过内部机制使其持久化,但实际上Message对象q没有实CQ何关于Hibernate的类或接口,因此我们也可以将它作Z个普通的JavacL使用Q?
Message message = new Message("Hello World");
System.out.println( message.getText() );
以上q段代码正是我们所期望的结果:(x)它打印“hello world”到屏幕上。但qƈ不是我们的最l目标;实际上Hibernate与诸如EJB容器q样的环境在持久层实现的方式上有很大的不同。我们的持久c?Messagec?可以用在与容器无关的环境中,不像EJB必须要有EJB容器才能执行。ؓ(f)了能更清楚地表现q点Q以下代码将我们的一个新消息保存到数据库中去Q?
Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Message message = new Message("Hello World");
session.save(message);
tx.commit();
session.close();
以上q段代码调用了Hibernate的Session和Transaction接口Q关于getSessionFactory()Ҏ(gu)我们会(x)马上提到Q。它相当于我们执行了以下SQL语句Q?
insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
values (1, 'Hello World', null)
在以上的SQL语句中,MESSAGE_ID字段到底被初始化成了什么值呢Q由于我们ƈ没有在先前的代码中ؓ(f)message对象的id属性赋与初始|那它是否为null呢?实际上Hibernate对id属性作了特D处理:(x)׃它是一个对象的唯一标识Q因此当我们q行save()调用ӞHibernate?x)?f)它自动赋予一个唯一的|我们在后面内容中讲q它是如何生成这个值的Q?
我们假设你已l在数据库中创徏了一个名为MESSAGE的表Q那么既然前面这D代码让我们Message对象存入了数据库中,那么现在我们p它们一一取出来。下面这D代码将按照字母序Q将数据库中的所有Message对象取出来,q将它们的消息正文打印到屏幕上:(x)
Session newSession = getSessionFactory().openSession();
Transaction newTransaction = newSession.beginTransaction();
List messages =newSession.find("from Message as m order by m.text asc");
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Message message = (Message) iter.next();
System.out.println( message.getText() );
}
newTransaction.commit();
newSession.close();
在以上这D代码中Q你可能被find()Ҏ(gu)的这个参数困扰着Q?from Message as m order by m.text asc"Q其实它是Hibernate自己定义的查询语aQ全U叫Hibernate Query Language(HQL)。通俗地讲HQL与SQL的关pd不多是方言与普通话之间的关p,咋一看,你会(x)觉得它有点类gSQL语句。其实在find()调用ӞHibernate?x)将q段HQL语言译成如下的SQL语句Q?
select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
from MESSAGES m
order by m.MESSAGE_TEXT asc
以下是q行l果Q?
1 message(s) found:
Hello World
如果你以前没有ORMQ对象-关系映射Q的开发经验,那你可能惛_代码的某个地方去Lq段SQL语句Q但在Hibernate中你可能?x)失望?x)它根本不存在Q所有就SQL语句都是Hibernate动态生成的?
也许你会(x)觉得q缺点什么,对!仅凭以上代码Hibernate是无法将我们的MessagecL久化的。我们还需要一些更多的信息Q这是映射定义表!q个表在Hibernate中是以XML格式来体现的Q它定义了Messagecȝ属性是怎样与数据库中的MESSAGES表的字段q行一一对应的,列表2是这个示例程序的映射配置文g清单Q?
列表2Q示例程序的对象Q关pL表
Q?xml version="1.0"?Q?
Q?DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"Q?
Qhibernate-mappingQ?
Qclass name="hello.Message" table="MESSAGES"Q?
Qid name="id" column="MESSAGE_ID"Q?
Qgenerator class="increment"/Q?
Q?idQ?
Qproperty name="text" column="MESSAGE_TEXT"/Q?
Qmany-to-one name="nextMessage" cascade="all" column="NEXT_MESSAGE_ID"/Q?
Q?classQ?
Q?hibernate-mappingQ?
以上q个文档告诉Hibernate怎样MessagecL到MESSAGES表中Q其中Messagecȝid属性与表的MESSAGE_ID字段对应Qtext属性与表的MESSAGE_TEXT字段对应QnextMessage属性是一个多对一的关p,它与表中的NEXT_MESSAGE_ID相对应?
相对于有些开源项目来_(d)Hibernate的配|文件其实是很容易理解的。你可以LC改与l护它。只要你定义好了持久cM数据库中表字D늚对应关系p了,Hibernate?x)自动帮你生成SQL语句来对Message对象q行插入、更新、删除、查扑ַ作,你可以不写一句SQL语句Q甚至不需要懂得SQL语言Q?
现在让我们做一个新的试验,我们先取出第一个Message对象Q然后修改它的消息正文,最后我们再生成一个新的Message对象Qƈ它作ؓ(f)W一个Message对象的下一条消息,其代码如下:(x)
列表3 更新一条消?
Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
// 1 is the generated id of the first message
Message message =(Message) session.load( Message.class, new Long(1) );
message.setText("Greetings Earthling");
Message nextMessage = new Message("Take me to your leader (please)");
message.setNextMessage( nextMessage );
tx.commit();
session.close();
以上q段代码在调用时QHibernate内部自动生成如下的SQL语句Q?
select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
from MESSAGES m
where m.MESSAGE_ID = 1
insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
values (2, 'Take me to your leader (please)', null)
update MESSAGES
set MESSAGE_TEXT = 'Greetings Earthling', NEXT_MESSAGE_ID = 2
where MESSAGE_ID = 1
当第一个Message对象的text属性和nextMessage被程序修Ҏ(gu)Q请注意Hibernate是如何检到q种变化Qƈ如何在数据库中自动对它更新的。这实际上是Hibernate的一个很有h(hun)值的特色Q我们把它称为“自动脏数据”,Hibernate的这个特色得当我们修改一个持久对象的属性后Q不必显式地通知Hibernated它在数据库中q行更新。同L(fng)Q当W一个Message对象调用setNextMessage()Ҏ(gu)第二个Message对象作ؓ(f)它的下一条消息的引用ӞW二条消息会(x)无需调用save()Ҏ(gu)Q便可以自动C存在数据库中。这U特色被UCؓ(f)“联保存”,它也免去了我们显式地对第二个Message对象调用save()Ҏ(gu)之苦?
如果我们再运行先前的那段数据库中所有的Message对象都打印出来的代码Q那它的q行l果如下Q?
2 message(s) found:
Greetings Earthling
Take me to your leader (please)
“Hello world”示例程序现在介l完毕。我们ȝ对Hibernate有了一个简单的认识Q下面我们将回过头来Q对Hibernate的主要API调用作一下简要的介绍Q?
理解Hibernate的架?/strong>
当你想用Hibernate开发自qZ持久层的应用ӞW一件事情应当是熟?zhn)它的~程接口。Hibernate的API接口设计得尽量简z明了,以方便开发h员。然而实际上׃ORM的复杂性,它的API一般都不可能设计得很简单。但是别担心Q你没有必要一下子了解所有的Hibernate的API接口?br />
我们应用层攑֜了持久层的上部,实际上在传统的项目中Q应用层充当着持久层的一个客L(fng)角色。但对于一些简单的目来说Q应用层和持久层q没有区分得那么清楚Q这也没什么,在这U情况下你可以将应用层和持久层合q成了一层?
Hibernate的接口大致可以分Z下几U类型:(x)
· 一些被用户的应用程序调用的Q用来完成基本的创徏、读取、更新、删除操作以?qing)查询操作的接口。这些接口是Hibernate实现用户E序的商业逻辑的主要接口,它们包括Session、Transaction和Query?
· Hibernate用来d诸如映射表这c配|文件的接口Q典型的代表有ConfigurationcR?
· 回调(Callback)接口。它允许应用E序能对一些事件的发生作出相应的操作,例如Interceptor、Lifecycle和Validatable都是q一cL口?
· 一些可以用来扩展Hibernate的映机制的接口Q例如UserType、CompositeUserType和IdentifierGenerator。这些接口可qL(fng)序来实现Q如果有必要Q?
Hibernate使用了J2EE架构中的如下技术:(x)JDBC、JTA、JNDI。其中JDBC是一个支持关pL据库操作的一个基层;它与JNDI和JTA一L(fng)合,使得Hibernate可以方便地集成到J2EE应用服务器中厅R?
在这里,我们不会(x)详细地去讨论Hibernate API接口中的所有方法,我们只简要讲一下每个主要接口的功能Q如果你想了解得更多的话Q你可以在Hibernate的源码包中的net.sf.hibernate子包中去查看q些接口的源代码。下面我们依ơ讲一下所有的主要接口Q?
核心接口
以下5个核心接口几乎在M实际开发中都会(x)用到。通过q些接口Q你不仅可以存储和获得持久对象,q且能够q行事务控制?
Session接口
Session接口对于Hibernate 开发h员来说是一个最重要的接口。然而在Hibernate中,实例化的Session是一个轻量的类Q创建和销毁它都不?x)占用很多资源。这在实际项目中实很重要,因ؓ(f)在客L(fng)序中Q可能会(x)不断地创Z?qing)销毁Session对象Q如果Session的开销太大Q会(x)l系l带来不良媄响。但值得注意的是Session对象是非U程安全的,因此在你的设计中Q最好是一个线E只创徏一个Session对象?
在Hibernate的设计者的头脑中,他们session看作介于数据q接与事务管理一U中间接口。我们可以将session惌成一个持久对象的~冲区,Hibernate能检到q些持久对象的改变,q及(qing)时刷新数据库。我们有时也USession是一个持久层理器,因ؓ(f)它包含这一些持久层相关的操作,诸如存储持久对象x据库Q以?qing)从数据库从获得它们。请注意QHibernate 的session不同于JSP应用中的HttpSession。当我们使用sessionq个术语Ӟ我们指的是Hibernate中的sessionQ而我们以后会(x)HttpSesion对象UCؓ(f)用户session?
SessionFactory 接口
q里用到了一个设计模式――工厂模式,用户E序从工厂类SessionFactory中取得Session的实例?
令你感到奇怪的是SessionFactoryq不是轻量的!实际上它的设计者的意图是让它能在整个应用中׃n。典型地来说Q一个项目通常只需要一个SessionFactory够了,但是当你的项目要操作多个数据库时Q那你必Mؓ(f)每个数据库指定一个SessionFactory?
SessionFactory在Hibernate中实际vC一个缓冲区的作用,它缓冲了Hibernate自动生成的SQL语句和一些其它的映射数据Q还~冲了一些将来有可能重复利用的数据?
Configuration 接口
Configuration接口的作用是对Hibernateq行配置Q以?qing)对它进行启动。在Hibernate的启动过E中QConfigurationcȝ实例首先定位映射文档的位|,dq些配置Q然后创Z个SessionFactory对象?
虽然Configuration接口在整个Hibernate目中只扮演着一个很的角色Q但它是启动hibernate时你所遇到的每一个对象?
Transaction 接口
Transaction接口是一个可选的APIQ你可以选择不用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码?Transaction接口是对实际事务实现的一个抽象,q些实现包括JDBC的事务、JTA中的UserTransaction、甚臛_以是CORBA事务。之所以这栯计是能让开发者能够用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移倹{?
Query和Criteria接口
Query接口让你方便地对数据库及(qing)持久对象q行查询Q它可以有两U表达方式:(x)HQL语言或本地数据库的SQL语句。Queryl常被用来绑定查询参数、限制查询记录数量,q最l执行查询操作?
Criteria接口与Query接口非常cMQ它允许你创建ƈ执行面向对象的标准化查询?
值得注意的是Query接口也是轻量U的Q它不能在Session之外使用?
Callback 接口
当一些有用的事g发生时――例如持久对象的载入、存储、删除时QCallback接口?x)通知HibernateL收一个通知消息。一般而言QCallback接口在用L(fng)序中q不是必ȝQ但你要在你的项目中创徏审计日志Ӟ你可能会(x)用到它?
一个重要的术语QType
Hibernate的设计者们发明了一个术语:(x)TypeQ它在整个构架中是一个非常基、有着强大功能的元素。一个Type对象能将一个Javacd映射到数据库中一个表的字D中去(实际上,它可以映到表的多个字段中去Q。持久类的所有属性都对应一个type。这U设计思想使用Hibernate有着高度的灵zL和扩展性?
Hibernate内置很多typecdQ几乎包括所有的Java基本cdQ例如Java.util.Currency、Java.util.calendar、byte[]和Java.io.Serializable?
不仅如此QHibernateq支持用戯定义的typeQ通过实现接口UserType和接口CompositeUserTypeQ你可以加入自己的type。你可以利用q种特色让你的项目中使用自定义的诸如Address、Nameq样的typeQ这样你可以获得更大的便利Q让你的代码更优雅。自定义type在Hibernate中是一Ҏ(gu)心特Ԍ它的设计者鼓׃多多使用它来创徏一个灵zR优雅的目Q?
{略接口
Hibernate与某些其它开源Y件不同的q有一点――高度的可扩展性,q通过它的内置{略机制来实现。当你感觉到Hibernate的某些功能不I或者有某些~陷Ӟ你可以开发一个自q{略来替换它Q而你所要做的仅仅只是承它的某个策略接口,然后实现你的新策略就可以了,以下是它的策略接口:(x)
· 主键的生?(IdentifierGenerator 接口)
· 本地SQL语言支持 (Dialect 抽象c?
· ~冲机制 (Cache 和CacheProvider 接口)
· JDBC q接理 (ConnectionProvider接口)
· 事务理 (TransactionFactory, Transaction, ?TransactionManagerLookup 接口)
· ORM {略 (ClassPersister 接口)
· 属性访问策?(PropertyAccessor 接口)
· 代理对象的创?(ProxyFactory接口)
HibernateZ上所列的机制分别创徏了一个缺省的实现Q因此如果你只是要增强它的某个策略的功能的话Q只需单地l承q个cd可以了,没有必要从头开始写代码?
以上是Hibernate的一些核心接口,但当我们真正开始用它进行开发时Q你的脑里可能M(x)有一个疑问:(x)我是通过什么方式,q从哪里取得Session的呢Q以下我们就解答q个问题?
基础配置
现在回顾一下我们先前的内容Q我们写Z一个示例程序,q简要地讲解了Hibernate的一些核心类。但要真正你的目q行hQ还有一件事必须要做Q配|。Hibernate可以配置成可在Q何Java环境中运行,一般说来,它通常被用?Q?层的C/S模式的项目中Qƈ被部|在服务端。在q种目中,W(xu)eb览器、或Java GUIE序充当者客L(fng)。尽我们的焦点主要是集中在多层web应用Q但实际上在一些基于命令行的应用中也可以用Hibernate。ƈ且,对Hibernate的配|在不同的环境下都会(x)不同QHibernateq行在两U环境下Q可理环境和不可管理环?
· 可管理环境――这U环境可理如下资源Q池资源理Q诸如数据库q接池和Q还有事务管理、安全定义。一些典型的J2EE服务器(JBoss、Weblogic、WebSphereQ已l实Cq些?
· 不可理环境――只是提供了一些基本的功能Q诸如像Jetty或Tomcatq样的servlet容器环境。一个普通的Java桌面应用或命令行E序也可以认为是处于q种环境下。这U环境不能提供自动事务处理、资源管理或安全理Q这些都必须由应用程序自己来定义?
Hibernate的设计者们这两种环境设计了一个统一的抽象界面,因此对于开发者来说只有一U环境:(x)可管理环境。如果实际项目是建立在诸如Tomcatq类不可理的环境中Ӟ那Hibernate会(x)使用它自q事务处理代码和JDBCq接池,使其变ؓ(f)一个可理环境?
对于可管理的环境而言QHibernate?x)将自己集成在这U环境中。对于开发者而言Q你所要做的工作非常简单:(x)只需从一个ConfigurationcM创徏一个SessionFactorycd可以了?
创徏一个SessionFactory对象
Z能创Z个SessionFactory对象Q你必须在Hibernate初始化时创徏一个Configurationcȝ实例Qƈ已写好的映文件交由它处理。这PConfiguration对象可以创Z个SessionFactory对象Q当SessionFactory对象创徏成功后,Configuration对象没有用了,你可以简单地抛弃它。如下是CZ代码Q?
Configuration cfg = new Configuration();
cfg.addResource("hello/Message.hbm.xml");
cfg.setProperties( System.getProperties() );
SessionFactory sessions = cfg.buildSessionFactory();
在以上代码中QMessage.hb.xmlq个映射文g的位|比较特D,它与当前的classpath相关。例如classpath包含当前目录Q那在上qC码中的Message.hbm.xml映射文g可以保存在当前目录下的hello目录中?
作ؓ(f)一U约定,Hibernate的映文仉认以.htm.xml作ؓ(f)其扩展名。另一个约定是坚持为每一个持久类写一个配|文Ӟ想一惛_果你所有持久类的映写入一个单独的配置文g中的话,那这个配|文件肯定非常庞大,不易l护。但q里又出C一个新问题Q如果ؓ(f)每个cd一个配|文件的话,q么多的配置文g应该存放在哪里呢Q?
Hibernate推荐你将每个映射文g保存在与持久cȝ同的目录下,q且与持久类同名。例如我们第一个示例程序中的Message持久cL在hello目录下,那你必须在这个目录下存放名ؓ(f)Message.hbm.xml的映文件。这样一个持久类都有自己的一个映文Ӟ避免了出现像struts目中的“struts-config.xml地狱”的情况。如果你不遵循这U规定,那你必须手动地用addResource()Ҏ(gu)一个个的映文件蝲入;但你如果遵@q种规定Q那你可以方便地用addClass()Ҏ(gu)同时持久类和它的映文件蝲入,以下是体现这U便利性的CZ代码Q?
SessionFactory sessions = new Configuration()
.addClass(org.hibernate.auction.model.Item.class)
.addClass(org.hibernate.auction.model.Category.class)
.addClass(org.hibernate.auction.model.Bid.class)
.setProperties( System.getProperties() )
.buildSessionFactory();
当然QHibernate的映文件还有很多其它的配置选项Q比如数据库q接的设定,或是能够改变Hibernateq行时行为的一些设定。所有的讄可能是非常庞杂的Q以让你喘不过气来Q但是不必担心,因ؓ(f)Hibernate为绝大多数值都讑֮了一个合理缺省|你只需要修改这些配|文件中的极一部分倹{?
你可以通过以下几种方式来修改Hibernate的系l配|参敎ͼ(x)
· 一个Java.util.Properties实例作ؓ(f)参数传给C(j)onfigurationcȝsetProperties()Ҏ(gu)?
· 在Hibernate启动时用Java –Dproperty=value的方式设|倹{?
· 在classpath可以扑ֈ的\径下创徏一个名为hibernate.properties的配|文件?
· 在classpath可以扑ֈ的\径下创徏一个名为hibernate.cfg.xml的文Ӟq在ӞpropertyQ标{中定义属性倹{?
以上是对Hibernate的一个大致介l,如果你想知道得更多,那本文还是远q不够的Q我陆l推出更多关于Hibernate的资料。但有一Ҏ(gu)毫无疑问的:(x)它的是一个非怼U的持久层解决Ҏ(gu)Q?/p>
Java的内核和class文g是基于unicode的,qJavaE序h良好的跨q_性,但也带来了一些中文ؕ码问题的ȝ。原因主要有两方面,Java和JSP文g本n~译时生的q问题和JavaE序于其他媒介交互生的q问题?/p>
首先JavaQ包括JSPQ源文g中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP~译成class文gq程中,使用的编码方式与源文件的~码不一_(d)׃(x)出现q。基于这Uؕ码,在Java文g中尽量不要写中文Q注释部分不参与~译Q写中文没关p)Q如果必d的话Q尽量手动带参数Qecoding GBK或-ecoding gb2312~译Q对于JSPQ在文g头加?lt;%@ page contentType="text/html;charset=GBK"%>?lt;%@ page contentType="text/html;charset=gb2312"%>基本上就能解册cMؕ码问题?/p>
本文要重点讨论的是第二类qQ即JavaE序与其他存储媒介交互时产生的ؕ码。很多存储媒介,如数据库Q文Ӟ等的存储方式都是基于字节流的,JavaE序与这些媒介交互时׃(x)发生字符(char)与字?byte)之间的{换,例如从页面提交表单中提交的数据在JavaE序里显CZؕ码等情况?/p>
如果在以上{换过E中使用的编码方式与字节原有的编码不一_(d)很可能就?x)出Cؕ码?/p>
二、解x?/p>
对于行的Tomcat来说Q有以下两种解决Ҏ(gu)Q?/p>
1) 更改 D:\Tomcat\conf\server.xmlQ指定浏览器的编码格式ؓ(f)“简体中文”:(x)
Ҏ(gu)是找?server.xml 中的
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" URIEncoding='GBK' />
标记Q粗体字是我d的?/p>
可以q样验证你的更改是否成功Q在更改前,在你出现q的页面的IE览器,点击菜单“查看|~码”,?x)发现“西?ISO)”处于选中状态。而更改后Q点击菜单“查看|~码”,?x)发现“简体中?GB2312)”处于选中状态?/p>
b)更该 Java E序Q我的程序是q样的:(x)
public class ThreeParams extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=GBK");
...
}
}
_体字是必需要有的,它的作用是让览器把Unicode字符转换为GBK字符。这样页面的内容和浏览器的显C模式都设成了GBKQ就不会(x)q了?/p>
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import javax.activation.DataHandler;
import org.apache.axis.attachments.ManagedMemoryDataSource;
import org.apache.axis.types.URI;
import org.apache.struts.upload.FormFile;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference;
import cn.com.chinatelecom.www.schema.ctcc.multimedia_messaging.v2_2.MessagePriority;
import cn.com.chinatelecom.www.wsdl.ctcc.multimedia_messaging.send.v2_2._interface.SendMessage;
import cn.com.chinatelecom.www.wsdl.ctcc.multimedia_messaging.send.v2_2.service.SendMessageServiceLocator;
import com.telecom.dao.DBLinker;
import com.telecom.util.AttachPart;
import com.telecom.util.Sequence;
public class MMS_send {
public MMS_send() {
}
private AttachPart attachmentParts[];
private static SimpleReference _receipt_request;
public void saveMmsMessage(String filepath, AttachPart[] ap,String mmsRoad) {
for (int i = 0; i < ap.length; i++) {
AttachPart part = ap[i];
try {
String s=saveAttachmentMessage(part.getContent().getInputStream(), part
.getContentType(), mmsRoad, filepath);
System.out.println("last s:"+s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String saveAttachmentMessage(InputStream in, String contentType,
String fileName, String folderPath) throws Exception {
System.out.println("FileName: "+fileName);
// 打开多媒体库
File file = new File(folderPath + "/mmsImage");
// 如果媒体库不存在则徏讑֤媒体?br /> if (!file.exists()) {
file.mkdirs();
}
// 图片存攑ֈ多媒体库,q保存其信息到数据库
String filePath = file.getAbsolutePath();
BufferedInputStream bin = null;
OutputStream os = null;
try {
bin = new BufferedInputStream(in);
file = new File(filePath + "/" + fileName);
if (!file.exists()) {
file.createNewFile();
}
os = new FileOutputStream(file);
byte[] bytes = new byte[1];
int beginIndex = 0;
int endIndex = beginIndex + 1;
while (true) {
int _read = bin.read(bytes, beginIndex, endIndex);
if (_read == -1) {
break;
}
os.write(bytes);
}
String contextPathFileName = "mmsImage/" + fileName;
bin.close();
in.close();
os.close();
return contextPathFileName;
} catch (IOException e) {
e.printStackTrace();
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
throw new Exception();
} finally {
try {
bin.close();
in.close();
os.close();
} catch (IOException e) {
throw new Exception();
}
}
}
public AttachPart buildEMAttachmentPartFromFile(FormFile mmsFile) {
AttachPart attchmentPart = new AttachPart();
try {
InputStream in = mmsFile.getInputStream();
String contentType = mmsFile.getContentType();
if ("image/pjpeg".equals(contentType))
contentType = "image/jpeg";
ManagedMemoryDataSource source = new ManagedMemoryDataSource(
mmsFile.getInputStream(), 16384, contentType, true);
attchmentPart.setContent(source);
attchmentPart.setContentType(mmsFile.getContentType());
String fileName = mmsFile.getFileName();
String suffix = fileName.substring(fileName.indexOf('.'));
attchmentPart.setFileName(Sequence.getID("") + suffix);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return attchmentPart;
}
public static void main(String[] args) {
Sag_sms s = new Sag_sms();
try {
s.sendSmsBySAG("13977770119", "法律", "1004");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
}
}
}
<%
EnterpriseNumForm enf = new EnterpriseNumForm();
Connection conn = null;
ResultSet rs = null;
ResultSet rs2 = null;
Statement sta = null;
Statement sta2 = null;
try {
conn = (Connection) DBLinker.linkDB();
String sql1 = "select distinct(strEnID) eid from tbEnterpriseNum";
rs = null;
sta = conn.createStatement();
rs = sta.executeQuery(sql1);
if (rs.next()) {
enf.setEnID(rs.getString("eid"));
}else{
enf.setEnID("0000");
}
String sql2 = "select distinct(strPresentNum) pn from tbEnterpriseNum ";
rs2 = null;
sta2 = conn.createStatement();
rs2 = sta2.executeQuery(sql2);
Vector v = new Vector();
while (rs2.next()) {
v.add(rs2.getString("PN"));
}
String[] s=new String[v.size()];
for(int i=0;i<v.size();i++){
s[i]=v.elementAt(i).toString();
}
enf.setNums(s);
System.out.println(v.size());
//session.setAttribute("enf",enf);
} catch (Exception e) {
} finally {
rs2.close();
rs.close();
sta.close();
sta2.close();
conn.close();
}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<link rel="stylesheet" type="text/css" href="../include/style.css">
<title>详细信息</title>
<script language="javascript">
function checkNum(){
selectAllMember(form1.nums);
form1.submit();
}
function selectAllMember(selection)
{
var ops=selection.options;
for(var i=0;i<ops.length;i++)
{
ops[i].selected=true;
}
}
function deleteSelectedMember(selection)
{
var ops=selection.options;
for(var i=0;i<ops.length;i++)
{
if(ops[i].selected==true)
{
selection.remove(i);
i--;
}
}
}
function other_add(){
if(form1.otherNum.value==""){
alert("不能为空");
}else{
additemNoRepeat(form1.otherNum.value,form1.otherNum.value,form1.nums);
}
}
function additemNoRepeat(Otext,Ovalue,selectElement){//不重复的d
for(j=0;j<selectElement.options.length;j++){
if(selectElement.options[j].value==Ovalue){
var flag=1;
alert(Otext+"已添?);
break;
}
}
if(flag!=1){
selectElement.options[selectElement.options.length]=new Option(Otext,Ovalue);
}
}
</script>
<style type="text/css">
<!--
.style3 {FONT-WEIGHT: bold; FONT-SIZE: 14px; COLOR: #246bad; LINE-HEIGHT: 2 }
body {
background-color: #E7F0FA;
}
-->
</style>
<meta http-equiv="pragma" content="no-cache">
<%response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.addHeader("Expires","Thu, 01 Jan 1970 00:00:01 GMT");
response.flushBuffer();%>
</head>
<body opener.location.reload()">
<table width="100%">
<tr>
<td bgcolor="#ffffff">
<table width="530" border="0" cellpadding="0" cellspacing="0"
style="word-break:break-all; ">
<tr>
<td width="60" background="../linkman/images/s22.jpg">
</td>
<td width="447" background="../linkman/images/s23.jpg">
<span class="style3">修改企业L(fng)和主叫绑定号?lt;/span>
</td>
<td width="6">
<img src="../linkman/images/s24.jpg" width="6" height="58">
</td>
<td width="17"></td>
</tr>
<tr>
<td colspan="4">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="17">
</td>
<td bgcolor="#e7f0fa">
<table width="94%" border="0" align="center" cellpadding="0"
cellspacing="0">
<form name="form1" method="post"
action="../companyadmin/EditENF.do?method=SaveENF" >
<tr>
<td width="17%" height="25">
企业L(fng)Q?br /> </td>
<td width="100%" height="25">
<input name="enID" type="text" id="enID"
value="<%=enf.getEnID()%>">
</td>
</tr>
<tr>
<td width="17%" height="25">
dl定L(fng)Q?br /> </td>
<td>
<select name="nums" size="20" multiple id="nums"
style="width:64%">
<%
String[] v = enf.getNums();
System.out.println(v.length);
if (v.length != 0) {
for (int k = 0; k < v.length; k++) {
String oldpn = new String();
oldpn = v[k];
System.out.println(oldpn);
%>
<option value="<%=oldpn%>">
<%=oldpn%>
</option>
<%
}
}
%>
</select>
<input type="button" name="Submit" value="删除L(fng)"
onClick="deleteSelectedMember(document.all.nums)">
</td>
</tr>
<tr>
<td height="30" scope="col">
误入号?
</td>
<td>
<input type="text" id="otherNum">
<input type="button" name="Submit" value="d"
onClick="other_add()">
</td>
</tr>
</form>
</table>
</td>
<td width="17">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="30" colspan="4">
<div align="center">
<a href="javascript:checkNum();">保存讄</a>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
1Q?span style="FONT: 7pt 'Times New Roman'"> 安装 axis Q将 axis 发布包( webapps\axis Q复制到服务器部|的目录?/span> D:\Tomcat 5.0\webapps Q启?/span> tomcat Q访?/span> http://192.168.0.51:7070/axis/ Q?/span> axis 安装完成
2 . d必要的类包:(x)生?/span> webservice 所需?/span> jar 包拷贝至Q?/span> D:\Tomcat 5.0\webapps\axis\WEB-INF\lib Q目录下Qƈ类和配|文件等拯?/span> D:\Tomcat 5.0\webapps\axis\WEB-INF\classes ?/span>
3. 讄部v环境变量 someclasspath Q?/span> someclasspath 中设|的是部|?/span> webservice q程中所需用到?/span> jar 包,它包含了 axis 下所有的cd?/span> tomcat 下的Q具体ؓ(f)
D:\Tomcat5.0\webapps\axis\WEB-INF\lib\axis.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\axis-ant.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\commons-discovery.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\commons-logging.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\jaxrpc.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\log4j-1.2.8.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\saaj.jar;D:\Tomcat 5.0\webapps\axis\WEB-INF\lib\wsdl4j.jar;
4 Q设|部|?/span> webservice 的部|文?/span> ( deploy.wsdd ) Q具体设|如下。将 deploy.wsdd文g攑֜c:\目录?/span>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="SMS" provider="java:RPC">
<!-- 指出要发布成web service的类 -->
<parameter name="className" value="com.beyondbit.sms.port.SMSPort "/>
<!-- 允许所有publicҎ(gu)可被调用 -->
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
?span lang="EN-US">dos环境下运行部|命令,部vwebservice
命o(h)Q?span lang="EN-US">
java -cp "%someclasspath%" org.apache.axis.client.AdminClient –p 7070 deploy.wsdd
发布成功Q此时可通过 http://192.168.0.51:7070/axis/servlet/AxisServlet地址看到名字为sms的webservice已部|成?o:p> (或者不用通过wsdd文g,直接dserver-config.wsdd.在相应区域添加例如下面的内容:
<service name="TestWS" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.telecom.notify.DefaultSmsNotify"/>
</service>
)
可通过点击webservice名字旁的描述文g链接Q察看webservice的描q文?o:p>
5Q在客户端生成调用webservice的java文g,命o(h)如下java -cp "%someclasspath%" org.apache.axis.wsdl.WSDL2Java -p <试用例?gt; -t<url地址>
?span lang="EN-US">dos环境下输入命?o:p>
java -cp "%someclasspath%" org.apache.axis.wsdl.WSDL2Java -p com.smsCase -t http://192.168.0.51:7070/axis/services/sms?wsdl
pȝ执行该命令后?x)?span lang="EN-US">c:\目录下生成com\smsCase文g夹,其中包含生成的类。利用ant{工L(fng)译这些文Ӟ~译q程中需要用到someclasspath中的jar包)。可通过以下例程调用webservice,
public String parseXml()
{
String xmlString = "";
try
{
SMSPortServiceLocator service = new SMSPortServiceLocator();
SMSServiceSoapBindingStub binding = (SMSServiceSoapBindingStub)new SMSPortServiceLocator().getSMSService();
binding = (SMSServiceSoapBindingStub)service.getSMSService();
xmlString = binding.toReceiveMsg("000","1234");
}
catch(Exception e)
{
e.printStackTrace();
}
return xmlString;
}
此中调用webservice中的sms中的toReceiveMsgҎ(gu)?o:p>
6Q卸载weserviceQ设|卸载部|文?undeploy.wsddQ?/span> ?/span> undeploy.wsdd文g攑֜c:\目录?/span>
<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
<service name="sms"/>
</undeployment>
?span lang="EN-US">dos环境下运行卸载webservice命o(h)Q卸载webservice
命o(h)Q?span lang="EN-US">
java -cp "%someclasspath%" org.apache.axis.client.AdminClient –p 7070 undeploy.wsdd
Pass.error.a=\u65e7\u5bc6\u7801\u4e0d\u5bf9
Pass.error.b=\u5bc6\u7801\u4e0d\u5339\u914d
2.b攑ֈsrc?后缀为properties.在config文g配置?lt;message-resources parameter="b" null="false"/>
3.使用
if (oldpass.equals("") || newpass.equals("")|| conpass.equals("")) {
errors.add("fail_1", new ActionError("All.error.a"));
saveErrors(request, errors);
return mapping.findForward("fail");
4.打完收工QEasy~
旉Q?006-07-26 作者:(x)axman 览ơ数Q? 2070 本文关键字:(x)java, equal, 基础 |
|
equalsҎ(gu)的重要性毋da,只要你想比较的两个对象不愿是同一对象,你就应该实现equalsҎ(gu),让对象用你认为相{的条g来进行比较?/p>
下面的内容只是API的规?没有什么太高深的意?但我之所以最先把它列在这?是因些规范在事实中ƈ不是真正能保证得到实现?/p>
以上几条规则q不是最完整的表q?详细的请参见API文档?/p>
对于Objectc?它提供了一个最最严密的实?那就是只有是同一对象?equalsҎ(gu)才返回true,也就是h们常说的引用比较而不是值比较。这个实C密得已经没有什么实际的意义,所以在具体子类(相对于Object来说)?如果我们要进行对象的值比?必d现自qequalsҎ(gu)?
先来看一下以下这D늨?
public boolean equals(Object obj) { if (obj == null) return false; if (!(obj instanceof FieldPosition)) return false; FieldPosition other = (FieldPosition) obj; if (attribute == null) { if (other.attribute != null) { return false; } } else if (!attribute.equals(other.attribute)) { return false; } return (beginIndex == other.beginIndex && endIndex == other.endIndex && field == other.field); }
q是JDK中java.text.FieldPosition的标准实?g没有什么可说的. 我相信大多数或绝大多数程序员认ؓ(f),q是正确的合法的equals实现.毕竟它是JDK的API实现? q是让我们以事实来说话吧:
package debug; import java.text.*; public class Test { public static void main(String[] args) { FieldPosition fp = new FieldPosition(10); FieldPosition fp1 = new MyTest(10); System.out.println(fp.equals(fp1)); System.out.println(fp1.equals(fp)); } } class MyTest extends FieldPosition{ int x = 10; public MyTest(int x){ super(x); this.x = x; } public boolean equals(Object o){ if(o==null) return false; if(!(o instanceof MyTest )) return false; return ((MyTest)o).x == this.x; } }
q行一下看看会(x)打印Z?
System.out.println(fp.equals(fp1));打印true System.out.println(fp1.equals(fp));打印flase
两个对象,出现了不对称的equals法.问题出在哪里(脑筋急{弯:(x)当然出在JDK实现的BUG)?
我相信有太多的程序员(除了那些Ҏ(gu)不知道实现equalsҎ(gu)的程序员?在实现equalsҎ(gu)旉用过instanceofq行W来q行短\优化的,实事求是地说很长一D|间我也这么用q。太多的教程Q文档都l了我们q样的误对{而有些稍有了解的E序员可能知道这L(fng)优化可能有些不对但找不出问题的关键。另外一U极端是知道q个技术缺L(fng)骨灰U专家就提议不要q样应用?/p>
我们知道Q?通常"要对两个对象q行比较Q那么它?应该"是同一cd。所以首先利用nstanceofq行W进行短路优化,如果被比较的对象不和当前对象是同一cd则不用比较返回false,但事实上Q?子类是父cȝ一个实?Q所以如?子类 o instanceof 父类Q始l返回true,q时肯定不会(x)发生短\优化Q下面的比较有可能出现多U情况,一U是不能造型成子c而抛出异常,另一U是父类的private 成员没有被子cȝ承而不能进行比较,q有是形成上面q种不对U比较。可能会(x)出现太多的情c?/p>
那么Q是不是׃能用 instanceofq行W来q行优化Q答案是否定的,JDK中仍然有很多实现是正的Q如果一个class是final的,明知它不可能有子c,Z么不?instanceof来优化呢Q?/p>
Zl护SUN的开发小l的声誉Q我不说明哪个类中,但有一个小l成员在用这个方法优化时在后加加上了加上了这L(fng)注释Q?/p>
if (this == obj) // quick check return true; if (!(obj instanceof XXXXClass)) // (1) same object? return false;
可能是有些疑问,但不知道如何做(不知道ؓ(f)什么没有打?sh)话l我......Q?/p>
那么对于非finalc,如何q行cd的quick check呢?
用被比较对象的class对象和当前对象的class比较Q看h是没有问题,但是Q如果这个类的子cL有重新实现equalsҎ(gu)Q那么子cd比较的时候,obj.getClass() 肯定不等于XXXCalss.class,也就是子cȝequals无效,所以if(obj.getClass() != this.getClass()) return false;才是正确的比较?
另外一个quick check是if(this==obj) return true;
是否equalsҎ(gu)一定比较的两个对象׃定是要同一cdQ上面我用了"通常"Q这也是l大多数E序员的愿望Q但是有些特D的情况Q我们可以进行不同类型的比较Q这q不q反规范。但q种Ҏ(gu)情况是非常罕见的Q一个不恰当的例子是QIntegercȝequals可以和Sort做比较,比较它们的value是不是同一数学倹{(事实上JDK的API中ƈ没有q样做,所以我才说是不恰当的例子)。在完成quick check以后Q我们就要真正实C认ؓ(f)的“相{”。对于如果实现对象相{,没有太高的要求,比如你自己实现的“h”类Q你可以认ؓ(f)只要name相同卌为它们是相等的,其它的sex,ago都可以不考虑。这是不完全实现Q但是如果是完全实现Q即要求所有的属性都是相同的Q那么如何实现equalsҎ(gu)Q?/p>
class Human{ private String name; private int ago; private String sex; .................... public boolean equals(Object obj){ quick check....... Human other = (Human)ojb; return this.name.equals(other.name) && this.ago == ohter.ago && this.sex.equals(other.sex); } }
q是一个完全实玎ͼ但是Q有时equals实现是在父类中实玎ͼ而要求被子类l承后equals能正的工作Q这时你q不事实知道子类到底扩展了哪些属性,所以用上面的方法无法equals得到完全实现?/p>
一个好的方法是利用反射来对equalsq行完全实现Q?/p>
public boolean equals(Object obj){ quick check....... Class c = this.getClass(); Filed[] fds = c.getDeclaredFields(); for(Filed f:fds){ if(!f.get(this).equals(f.get(obj))) return false; } return true; }
Z说明的方便,上明的实现省略了异常Q这L(fng)实现攑֜父类中,可以保证你的子类的equals可以按你的愿望正地工作?/p>
关于equalsҎ(gu)的最后一Ҏ(gu)Q如果你要是自己重写Q正说应该是盖)了equalsҎ(gu)Q那同时׃定要重写hashCode().为是规范Q否?............
我们q是看一下这个例子:(x)
public final class PhoneNumber { private final int areaCode; private final int exchange; private final int extension; public PhoneNumber(int areaCode, int exchange, int extension) { rangeCheck(areaCode, 999, "area code"); rangeCheck(exchange, 99999999, "exchange"); rangeCheck(extension, 9999, "extension"); this.areaCode = areaCode; this.exchange = exchange; this.extension = extension; } private static void rangeCheck(int arg, int max, String name) { if(arg < 0 || arg > max) throw new IllegalArgumentException(name + ": " + arg); } public boolean equals(Object o) { if(o == this) return true; if(!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.extension == extension && pn.exchange == exchange && pn.areaCode == areaCode; } }
注意q个cLfinal的,所以这个equals实现没有什么问题?
我们来测试一?
public static void main(String[] args) { Map hm = new HashMap(); PhoneNumber pn = new PhoneNumber(123, 38942, 230); hm.put(pn, "I love you"); PhoneNumber pn1 = new PhoneNumber(123, 38942, 230); System.out.println(pn); System.out.println("pn.equals(pn1) is " + pn.equals(pn1)); System.out.println(hm.get(pn1)); System.out.println(hm.get(pn)); }
既然pn.equals(pn1),那么我put(pn,"I love you");后,get(pn1)q什么是null呢?
{案是因为它们的hashCode不一P而hashMap是以hashCodeZ键的?/p>
所以规范要求,如果两个对象q行equals比较时如果返回true,那么它们的hashcode要求q回相等的倹{?
好了Q休息,休息一下。。。。。。。。。。。。。。。?
转蝲自dev2dev|友axman?a target="_blank">go deep into java专栏?/strong>
一个男?
一个写E序的男?
一个写E序q正在从E序中寻扑ֿ乐的男h.
一个写E序q正在从E序中寻扑ֿ乐ƈ把快乐传递给大家的男?
一个书?
一个寂寞的书生.
一个寂寞的梅香竹媄下敲声写늚书生.
一个寂寞的梅香竹媄下敲声写韉|钟暮鼓中逸气扬剑的书?
那个男h是位书生。没有h知道他的姓名Q居无定所Q行无定t,亦耕变读,或渔或樵?br />所以有人叫他樵?Axman)Q有人叫他渔?fisher)?/p>
SWT 在外观和性能上都过?/span> awt/swing Qؓ(f)什么这栯呢?下面单的试E序?x)让你一目了然。废话也不多_(d)让我们看E序?/span>
下面让我们写一个简单的E序来测试一下,E序只做一件事Q就是用
Label
昄
”Hello World!?/span>
Q我的测试环境是
JDK
AWT_CODE:
import java.awt.Frame;
import java.awt.Label;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class awtTest {
public static void main(String[] args) {
long memory =
long time =
memory = Runtime.getRuntime().freeMemory();
time = System.currentTimeMillis();
Frame frame = new Frame();
Label label = new Label();
label.setText("Hello World!");
frame.add(label);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.pack();
System.out.println(System.currentTimeMillis() - time);
System.out.println(memory - Runtime.getRuntime().freeMemory());
}
}
q行效果?qing)所用的旉和内存|(x)
SWING_CODE:
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class swingTest {
public static void main(String[] args) {
long memory =
long time =
memory = Runtime.getRuntime().freeMemory();
time = System.currentTimeMillis();
JFrame frame = new JFrame();
JLabel label = new JLabel();
label.setText("Hello World!");
frame.add(label);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.pack();
System.out.print("Time:");
System.out.println(System.currentTimeMillis() - time);
System.out.print("Memory:");
System.out.println(memory - Runtime.getRuntime().freeMemory());
}
}
q行效果?qing)所用的旉和内存|(x)
SWT_CODE:
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
public class swtTest {
public static void main(String[] args) {
long memory =
long time =
memory = Runtime.getRuntime().freeMemory();
time = System.currentTimeMillis();
Display display = new Display();
Shell shell = new Shell(display);
Label label = new Label(shell, SWT.NONE);
label.setText("Hello World!");
shell.pack();
label.pack();
shell.open();
System.out.print("Time:");
System.out.println(System.currentTimeMillis() - time);
System.out.print("Memory:");
System.out.println(Runtime.getRuntime().freeMemory() - memory);
while(!shell.isDisposed()) {
if(!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
label.dispose();
}
}
q行效果?qing)所用的旉和内存|(x)
如果你仔l看代码Q你?x)发现?/span> SWT 的代码中Q我注解?/span> ?**?/span> 代码处,与前两者有所不同Q这也我疑惑的地方,在整个程序运行中Q运行后的剩余内存居然比q行前的剩余内存值大。接着Q我在调试该E序的时候,我发现在 Shell shell = new Shell(display) 语句执行后,内存值有明显的增加,如果你知?/span> SWT 底层是如何操作的Q知道这是什么原因引L(fng)Q请?/span> 联系?/font> q告诉我q是Z么,我好做出修正?/span>
如果你是初学者,不知道怎么q行
SWT
E序Q其实很单的Q只需要在你的工程?/span>
Libraries
d一个名?/span>
org.eclipse.swt.win32.win32.x86_
"D:\\Program Files\\Microsoft Office\\Office10\\powerpnt.exe /s 1.pps");
// "C:\\WINDOWS\\system32\\rundll32.exe jpg.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
}
W?1 步,安装 ADF q行时库
此步骤与运行时库安装到 OC4J 的步骤类伹{在q行安装E序时请保服务器处于停止状态?/span>
W?2 步,创徏与应用服务器的连?/span>
按照前面所q创Z个新q接。?zhn)无法试此连接?/span>
W?3 步,创徏部v描述文g
(zhn)唯一需要的描述文g是 web.xmlQ它?JDeveloper10g 在创?web 面时生成?/span>
W?4 步,为每一层创建部|配|文?/span>
~辑 web 客户端的部v配置文g。确保将目标q接讄为?zhn)在?2 步中创徏?tomcat q接。输入正的 war 文g名。在 Tomcat 中,上下文根Z web 应用E序的文件夹名称?/span>
W?5 步,创徏一个全局部v配置文gQ仅限三层应用程序)
跌此步骤?/span>
W?6 步,部v应用E序
右键单击“webapp.deploy?/span>?
选择“deploy to tomcat?/span>
W?7 步,试应用E序
通过在浏览器中键?http://localhost:8080/[warfilename]/departments.jspQ测试应用程序的部v?/span>
javac –d . *.java
2Q在%APP_HOME%/webapp/WEB-INF目录下创建server-config.wsddQAXIS配置文gQ所有web服务都要在该文g中注册)文g。Ş如:(x)
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns=" <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendMultiRefs" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="axis.sendMinimizedElements" value="true"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="session"/>
</handler>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="request"/>
<parameter name="extension" value=".jwr"/>
</handler>
</requestFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<service name="login" provider="java:RPC">
<!-- 服务cd -->
<parameter name="className" value="com.test.service.loginService"/>
<!-- 允许讉K所有方?-->
<parameter name="allowedMethods" value="*"/>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
</deployment>
注:(x)server-config.wsdd文g也可以通过~写deploy.wsdd文g生成Q具体方法ؓ(f)Q在%APP_HOME%/webapp/WEB-INF目录下创建deploy.wsdd文gQSOAP发布描述文gQ,形如Q?/p>
<deployment xmlns=" <parameter name="className" value="LoginService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
然后相应服务器端class~译后在命o(h)行输入:(x)
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd
在当前目录下生成server-config.wsdd文g?/p>
完成以上操作后,可在览器中通过http://localhost:8080/axis/services/login?wsdl 讉K该服务?br />
3QJAVA客户端实玎ͼ(x)
可以通过AXIS中的org.apache.axis.wsdl.WSDL2Javacd已发布的web服务q行客户端实例化Q具体命令ؓ(f)Q在%APP_HOME%/webapp/WEB-INF目录下命令行输入Q?/p>
Java -Djava.ext.dirs=lib org.apache.axis.wsdl.WSDL2Java url[YiWang1]
命o(h)执行后会(x)在本地当前目录下生成以url为模版的package目录层次l构(如:(x)local.axis.service.*),该目录中针对每个服务器端接口?x)自动生?个本地类?/p>
其中Q?/p>
inferface LoginService在客L(fng)本地定义服务器接口的映射?/p>
interface LoginServiceService定义了用于获得web服务的getterҎ(gu)?/p>
class LoginServiceServiceLocator具体实现LoginServiceService接口Q保存了服务器的url{相关信息?/p>
class LoginSoapBindingStub 具体实现LoginServiceQ负责服务器交互?/p>
Q部|了web服务之后Q如果接口不变而url发生改变Q可以直接在客户端更新LoginServiceServiceLocator中有x务器地址的相关信息,或者用配置文g的Ş式修改)
~译以上几个cL需要axis.jarQjaxrpc.jar两个包,命o(h)为:(x)
javac -classpath lib\axis.jar;lib\jaxrpc.jar –d . *.java
~译成class后可以通过jar命o(h)打包作ؓ(f)接口部v在客L(fng)?/p>
客户端测试例E:(x)
如果通过java应用E序形式q行试Q命令ؓ(f)Q?/p>
java -Djava.ext.dirs=lib -cp . package.class
--------------------------------------------------------------------------------
[YiWang1]服务器通过Wsdl形式发布的web服务的完整url地址?br />