1、1、调整数据结构的设计。这一部分在开发信息系统之前完成,程序员需要考虑是否使用ORACLE数据库的分区功能,对于经常访问的数据库表是否需要建立索引等。
2、2、调整应用程序结构设计。这一部分也是在开发信息系统之前完成,程序员在这一步需要考虑应用程序使用什么样的体系结构,是使用传统的Client/Server两层体系结构,还是使用Browser/Web/Database的三层体系结构。不同的应用程序体系结构要求的数据库资源是不同的。
3、3、调整数据库SQL语句。应用程序的执行最终将归结为数据库中的SQL语句执行,因此SQL语句的执行效率最终决定了ORACLE数据库的性能。ORACLE公司推荐使用ORACLE语句优化器(Oracle Optimizer)和行锁管理器(row-level manager)来调整优化SQL语句。
4、4、调整服务器内存分配。内存分配是在信息系统运行过程中优化配置的,数据库管理员可以根据数据库运行状况调整数据库系统全局区(SGA区)的数据缓冲区、日志缓冲区和共享池的大小;还可以调整程序全局区(PGA区)的大小。需要注意的是,SGA区不是越大越好,SGA区过大会占用操作系统使用的内存而引起虚拟内存的页面交换,这样反而会降低系统。
5、5、调整硬盘I/O,这一步是在信息系统开发之前完成的。数据库管理员可以将组成同一个表空间的数据文件放在不同的硬盘上,做到硬盘之间I/O负载均衡。
6、6、调整操作系统参数,例如:运行在UNIX操作系统上的ORACLE数据库,可以调整UNIX数据缓冲池的大小,每个进程所能使用的内存大小等参数。
实际上,上述数据库优化措施之间是相互联系的。ORACLE数据库性能恶化表现基本上都是用户响应时间比较长,需要用户长时间的等待。但性能恶化的原因却是多种多样的,有时是多个因素共同造成了性能恶化的结果,这就需要数据库管理员有比较全面的计算机知识,能够敏感地察觉到影响数据库性能的主要原因所在。另外,良好的数据库管理工具对于优化数据库性能也是很重要的。
ORACLE数据库性能优化工具
常用的数据库性能优化工具有:
1、1、ORACLE数据库在线数据字典,ORACLE在线数据字典能够反映出ORACLE动态运行情况,对于调整数据库性能是很有帮助的。
2、2、操作系统工具,例如UNIX操作系统的vmstat,iostat等命令可以查看到系统系统级内存和硬盘I/O的使用情况,这些工具对于管理员弄清出系统瓶颈出现在什么地方有时候很有用。
3、3、SQL语言跟踪工具(SQL TRACE FACILITY),SQL语言跟踪工具可以记录SQL语句的执行情况,管理员可以使用虚拟表来调整实例,使用SQL语句跟踪文件调整应用程序性能。SQL语言跟踪工具将结果输出成一个操作系统的文件,管理员可以使用TKPROF工具查看这些文件。
4、4、ORACLE Enterprise Manager(OEM),这是一个图形的用户管理界面,用户可以使用它方便地进行数据库管理而不必记住复杂的ORACLE数据库管理的命令。
5、5、EXPLAIN PLAN——SQL语言优化命令,使用这个命令可以帮助程序员写出高效的SQL语言。
ORACLE数据库的系统性能评估
信息系统的类型不同,需要关注的数据库参数也是不同的。数据库管理员需要根据自己的信息系统的类型着重考虑不同的数据库参数。
1、1、在线事务处理信息系统(OLTP),这种类型的信息系统一般需要有大量的Insert、Update操作,典型的系统包括民航机票发售系统、银行储蓄系统等。OLTP系统需要保证数据库的并发性、可靠性和最终用户的速度,这类系统使用的ORACLE数据库需要主要考虑下述参数:
l l 数据库回滚段是否足够?
l l 是否需要建立ORACLE数据库索引、聚集、散列?
l l 系统全局区(SGA)大小是否足够?
l l SQL语句是否高效?
2、2、数据仓库系统(Data Warehousing),这种信息系统的主要任务是从ORACLE的海量数据中进行查询,得到数据之间的某些规律。数据库管理员需要为这种类型的ORACLE数据库着重考虑下述参数:
l l 是否采用B*-索引或者bitmap索引?
l l 是否采用并行SQL查询以提高查询效率?
l l 是否采用PL/SQL函数编写存储过程?
l l 有必要的话,需要建立并行数据库提高数据库的查询效率
SQL语句的调整原则
SQL语言是一种灵活的语言,相同的功能可以使用不同的语句来实现,但是语句的执行效率是很不相同的。程序员可以使用EXPLAIN PLAN语句来比较各种实现方案,并选出最优的实现方案。总得来讲,程序员写SQL语句需要满足考虑如下规则:
1、1、尽量使用索引。试比较下面两条SQL语句:
语句A:SELECT dname, deptno FROM dept WHERE deptno NOT IN
(SELECT deptno FROM emp);
语句B:SELECT dname, deptno FROM dept WHERE NOT EXISTS
(SELECT deptno FROM emp WHERE dept.deptno = emp.deptno);
这两条查询语句实现的结果是相同的,但是执行语句A的时候,ORACLE会对整个emp表进行扫描,没有使用建立在emp表上的deptno索引,执行语句B的时候,由于在子查询中使用了联合查询,ORACLE只是对emp表进行的部分数据扫描,并利用了deptno列的索引,所以语句B的效率要比语句A的效率高一些。
2、2、选择联合查询的联合次序。考虑下面的例子:
SELECT stuff FROM taba a, tabb b, tabc c
WHERE a.acol between :alow and :ahigh
AND b.bcol between :blow and :bhigh
AND c.ccol between :clow and :chigh
AND a.key1 = b.key1
AMD a.key2 = c.key2;
这个SQL例子中,程序员首先需要选择要查询的主表,因为主表要进行整个表数据的扫描,所以主表应该数据量最小,所以例子中表A的acol列的范围应该比表B和表C相应列的范围小。
3、3、在子查询中慎重使用IN或者NOT IN语句,使用where (NOT) exists的效果要好的多。
4、4、慎重使用视图的联合查询,尤其是比较复杂的视图之间的联合查询。一般对视图的查询最好都分解为对数据表的直接查询效果要好一些。
5、5、可以在参数文件中设置SHARED_POOL_RESERVED_SIZE参数,这个参数在SGA共享池中保留一个连续的内存空间,连续的内存空间有益于存放大的SQL程序包。
6、6、ORACLE公司提供的DBMS_SHARED_POOL程序可以帮助程序员将某些经常使用的存储过程“钉”在SQL区中而不被换出内存,程序员对于经常使用并且占用内存很多的存储过程“钉”到内存中有利于提高最终用户的响应时间。
CPU参数的调整
CPU是服务器的一项重要资源,服务器良好的工作状态是在工作高峰时CPU的使用率在90%以上。如果空闲时间CPU使用率就在90%以上,说明服务器缺乏CPU资源,如果工作高峰时CPU使用率仍然很低,说明服务器CPU资源还比较富余。
使用操作相同命令可以看到CPU的使用情况,一般UNIX操作系统的服务器,可以使用sar –u命令查看CPU的使用率,NT操作系统的服务器,可以使用NT的性能管理器来查看CPU的使用率。
数据库管理员可以通过查看v$sysstat数据字典中“CPU used by this session”统计项得知ORACLE数据库使用的CPU时间,查看“OS User level CPU time”统计项得知操作系统用户态下的CPU时间,查看“OS System call CPU time”统计项得知操作系统系统态下的CPU时间,操作系统总的CPU时间就是用户态和系统态时间之和,如果ORACLE数据库使用的CPU时间占操作系统总的CPU时间90%以上,说明服务器CPU基本上被ORACLE数据库使用着,这是合理,反之,说明服务器CPU被其它程序占用过多,ORACLE数据库无法得到更多的CPU时间。
数据库管理员还可以通过查看v$sesstat数据字典来获得当前连接ORACLE数据库各个会话占用的CPU时间,从而得知什么会话耗用服务器CPU比较多。
出现CPU资源不足的情况是很多的:SQL语句的重解析、低效率的SQL语句、锁冲突都会引起CPU资源不足。
1、数据库管理员可以执行下述语句来查看SQL语句的解析情况:
SELECT * FROM V$SYSSTAT
WHERE NAME IN
('parse time cpu', 'parse time elapsed', 'parse count (hard)');
这里parse time cpu是系统服务时间,parse time elapsed是响应时间,用户等待时间
waite time = parse time elapsed – parse time cpu
由此可以得到用户SQL语句平均解析等待时间=waite time / parse count。这个平均等待时间应该接近于0,如果平均解析等待时间过长,数据库管理员可以通过下述语句
SELECT SQL_TEXT, PARSE_CALLS, EXECUTIONS FROM V$SQLAREA
ORDER BY PARSE_CALLS;
来发现是什么SQL语句解析效率比较低。程序员可以优化这些语句,或者增加ORACLE参数SESSION_CACHED_CURSORS的值。
2、数据库管理员还可以通过下述语句:
SELECT BUFFER_GETS, EXECUTIONS, SQL_TEXT FROM V$SQLAREA;
查看低效率的SQL语句,优化这些语句也有助于提高CPU的利用率。
3、3、数据库管理员可以通过v$system_event数据字典中的“latch free”统计项查看ORACLE数据库的冲突情况,如果没有冲突的话,latch free查询出来没有结果。如果冲突太大的话,数据库管理员可以降低spin_count参数值,来消除高的CPU使用率。
内存参数的调整
内存参数的调整主要是指ORACLE数据库的系统全局区(SGA)的调整。SGA主要由三部分构成:共享池、数据缓冲区、日志缓冲区。
1、 1、 共享池由两部分构成:共享SQL区和数据字典缓冲区,共享SQL区是存放用户SQL命令的区域,数据字典缓冲区存放数据库运行的动态信息。数据库管理员通过执行下述语句:
select (sum(pins - reloads)) / sum(pins) "Lib Cache" from v$librarycache;
来查看共享SQL区的使用率。这个使用率应该在90%以上,否则需要增加共享池的大小。数据库管理员还可以执行下述语句:
select (sum(gets - getmisses - usage - fixed)) / sum(gets) "Row Cache" from v$rowcache;
查看数据字典缓冲区的使用率,这个使用率也应该在90%以上,否则需要增加共享池的大小。
2、 2、 数据缓冲区。数据库管理员可以通过下述语句:
SELECT name, value FROM v$sysstat WHERE name IN ('db block gets', 'consistent gets','physical reads');
来查看数据库数据缓冲区的使用情况。查询出来的结果可以计算出来数据缓冲区的使用命中率=1 - ( physical reads / (db block gets + consistent gets) )。
这个命中率应该在90%以上,否则需要增加数据缓冲区的大小。
3、 3、 日志缓冲区。数据库管理员可以通过执行下述语句:
select name,value from v$sysstat where name in ('redo entries','redo log space requests');查看日志缓冲区的使用情况。查询出的结果可以计算出日志缓冲区的申请失败率:
申请失败率=requests/entries,申请失败率应该接近于0,否则说明日志缓冲区开设太小,需要增加ORACLE数据库的日志缓冲区。
做了一大半年的业务数据库优化了,有一点感想,写出来自励一下。
公司开发的产品基本上都使用ORACLE数据库,而且业务系统中存储和使用的数据量很大,使用业务系统的用户也很多。在系统忙时,大约会有一千个用户同事访问数据库系统,因此经常会有用户抱怨系统慢,点击查询后,系统出现假死机现象,后台运行ORACLE系统的小型机的IDLE值偏低(甚至出现IDLE为0的情况,这时用户会惊呼数据库系统会瘫掉,虽然小型型机在IDLE值为0的情况下也不一定会瘫机,但这无疑会增加用户的担忧),系统运行在一个不安全的状态等等。
对于我现在所做的ORACLE优化,其实还停留在SQL优化的层次(以前我的前辈曾给我说关于数据库优化的三个层次:一是针对SQL的优化,如使用正确是索引,使用ORACLE提示等;二是针对数据库对象的优化,如增加索引,微调表结构等;三针对业务的优化,需要更改业务逻辑或者表结果,此类优化一般代价比较大,一般很少针对正在运行的系统做类似的操作)。
公司的客户很多,大多数情况会在公司远程处理客户的数据库问题。作为问题的定位者,一定要搞清楚实际运行的数据库系统到底出现了什么问题。现场的维护人员和用户最喜欢使用的形容词是:系统很慢;数据库锁表了等等。用户向外面传达的信心往往是非常模糊的,在开始接触这个问题时候起,我们就要引导用户去帮外面了解系统真实的情况。有几个东西是一定要看看的,一个是ORACLE系统的警告日志文件,在系统运行的有问题或者是忙时的几份STATSPACK报告(一般间隔时间10到15分钟),UNIX下SAR命令的输入结果(该命令可以按既定的时间间隔收集小型机系统CPU的使用情况)。通过这三个从现场收集的结果,我们基本可以了解现场数据库的运行情况。
其中ORACLE系统的警告日志文件能让我们了解ORACLE系统运行有没有一些重大的问题。
STATSPACK报告中概括了数据库系统的运行基本情况,其中关于如何解读报告可以写一本书了,不过我们首先要关注的是报告中有一段“Top 5 Timed Events”,这一段描述了当前ORACLE主要的等待事件是什么(关于ORACLE等待事件的概念可以参考相关的资料)。
SAR命令的输入我们要关注三个输出的分布情况USR、WIO、IDLE。其中SYS+USR+WIO+IDLE应该等于100%,USR占的比例高,一般说明SQL语句执行效率有问题,这种问题一般是由于索引选择性不高、表连接顺序和方式不对等等;WIO高一般说明SQL语句频繁进行I/O操作。对于具体的问题,则需要对具体的SQL语句进行分析,在分析过程中,阅读执行计划是我们的一个重要的工具。
在对ORACLE系统的整体情况有了一定的了解之后,下一步需要分析的就是系统运行过程效率不高的SQL,这是对业务优化的一个起点。如果这时不能够在实际系统中操作,了解SQL的运行过程是一个比较费时的过程的。不管怎么样,对于我们怀疑有问题的SQL,首先要阅读的就是该SQL的在实际系统中的执行计划,语句涉及到的表的数据量,访问表使用索引的选择性如何,表连接的顺序,多表之间的关联关系等等。
对于ORACLE应用系统的优化,大方向上有一个顺序,首先考虑优化业务系统、再考虑优化ORACLE系统本身的参数(如内存分配等),再考虑操作系统本身的优化;在优化业务系统中,首先是首先相关的SQL,以SQL入手分析表是否缺少索引,表连接顺序是否正确,使用的索引是否正确等,然后再考虑调整表结构,调整业务逻辑等等。因此,SQL语句是我们对一个ORACLE业务系统进行优化的敲门砖。
对于SQL优化,前面提到了,ORACLE的执行计划是我们必须使用的工具。本来按ORACLE系统本身提供的方法获取执行计划是一件非常麻烦的事情,不过现在的可视化工具比如PL/SQL DEVELOP或者TOAD等都给我们提供了非常方便的手段来获取SQL语句的执行计划,不过我认为ORACLE本身提供的方法还是有必要会的,特别是在远程处理问题的时候(我也不会,一定要学习一下)。
获取有性能问题的SQL语句,我们主要有两个途径,一个是通过STATSPACK报告。报告中有两节是我们需要重点关注的:《SQL ordered by Gets for》和《SQL ordered by Reads for DB》,这两节中分别按语句读取内存数据库块和读取的物理数据库块(数据库块是指ORACLE的块大小,一般是操作系统最小块的整数倍)的数量倒序排列,如果其中的语句不全(太长),可通过HASH_VALUE值到ORACLE的动态视图V$SQLTEXT中获取该SQL的全部语句。第二个是通过ORACLE系统的动态视图,V$SQL,该视图记录了每个SQL语句的执行次数,物理读和内存读、执行时间等等很多SQL语句的执行信息,可以通过如下语句选择一下物理读和内存读较高的语句:
SELECT
t.HASH_VALUE,
t.EXECUTIONS,
t.DISK_READS,
round(t.DISK_READS/t.EXECUTIONS) AS perDiskReads,
t.BUFFER_GETS,
round(t.BUFFER_GETS/t.EXECUTIONS) AS perBufferReads,
t.ELAPSED_TIME,
round(t.ELAPSED_TIME/t.EXECUTIONS) AS perElayTime,
t.CPU_TIME,
round(t.CPU_TIME/t.EXECUTIONS) AS perCpuTime,
t.FIRST_LOAD_TIME,
t.SQL_TEXT
FROM v$sql t
WHERE (t.DISK_READS/t.EXECUTIONS > 500 OR t.BUFFER_GETS/t.EXECUTIONS > 20000)
AND t.EXECUTIONS > 0
ORDER BY 6 DESC;
这个语句查询出来的SQL可能也不全,也可以通过HASH_VALUE在V$SQLTEXT中找到其全部的SQL。
对于找到的SQL语句我们可以逐一分析其执行计划,结合涉及到的表的数据量,我们可以估算或者测试该语句的执行效率,分析表WHERE条件中涉及的字段(术语叫做谓词),该字段数据分布如何,选择性是否好,是否有索引。这是一个非常繁杂和琐碎的工作,但从这些琐碎的工作中,我们能发现那些SQL执行时选择的索引不对,哪些表缺少相应的索引导致了全表扫描,哪些语句条件不够导致对分区表进行了全表扫描。总之,对于一个给定的SQL,我们结合其表数据量的大小和分布,SQL中使用的查询条件,能够找到一个性能最优的执行方式,通过调整索引、使用ORACLE提示,使ORACLE系统按照最优的方式来执行SQL。如何去分析和确定ORACLE的执行方式,一个最普遍的原则就是尽量根据其谓词(查询条件),使用选择性最好的索引(当然,对于一些小表,可以考虑使用全表扫描的方式性能会更好)。对于SQL的执行方式,需要在工作中不断积累经验,比如曾经在一次优化中发现对一个表安三个字段查询的非常多,因此决定建立该三个字段的复合索引,但结果其语句执行效率却更差。
呵呵,今天先写这么多了,希望大家多多指教
java 调用webservice的各种方法总结
现在webservice加xml技术已经逐渐成熟,但要真正要用起来还需时日!!
由于毕业设计缘故,我看了很多关于webservice方面的知识,今天和大家一起来研究研究webservice的各种使用方法。
一、利用jdk web服务api实现,这里使用基于 SOAP message 的 Web 服务
1.首先建立一个Web services EndPoint:
package Hello;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;
@WebService
public class Hello {
@WebMethod
public String hello(String name) {
return "Hello, " + name + "\n";
}
public static void main(String[] args) {
// create and publish an endpoint
Hello hello = new Hello();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/hello", hello);
}
}
2.使用 apt 编译 Hello.java(例:apt -d [存放编译后的文件目录] Hello.java ) ,会生成 jaws目录
3.使用java Hello.Hello运行,然后将浏览器指向http://localhost:8080/hello?wsdl就会出现下列显示
4.使用wsimport 生成客户端
使用如下:wsimport -p . -keep http://localhost:8080/hello?wsdl
这时,会在当前目录中生成如下文件:
5.客户端程序:
1class HelloClient{
2public static void main(String args[]) {
3 HelloService service = new HelloService();
4 Hello helloProxy = service.getHelloPort();
5 String hello = helloProxy.hello("你好");
6 System.out.println(hello);
7 }
8}
9
以上方法还稍显繁琐,还有更加简单的方法
二、使用xfire,我这里使用的是myeclipse集成的xfire进行测试的
利用xfire开发WebService,可以有三种方法:
1一种是从javabean 中生成;
2 一种是从wsdl文件中生成;
3 还有一种是自己建立webservice
步骤如下:
用myeclipse建立webservice工程,目录结构如下:
首先建立webservice接口,
代码如下:
1package com.myeclipse.wsExample;
2//Generated by MyEclipse
3
4public interface IHelloWorldService {
5
6 public String example(String message);
7
8}
接着实现这个借口:
1package com.myeclipse.wsExample;
2//Generated by MyEclipse
3
4public class HelloWorldServiceImpl implements IHelloWorldService {
5
6 public String example(String message) {
7 return message;
8 }
9
10}
修改service.xml 文件,加入以下代码:
1<service>
2 <name>HelloWorldService</name>
3 <serviceClass>
4 com.myeclipse.wsExample.IHelloWorldService
5 </serviceClass>
6 <implementationClass>
7 com.myeclipse.wsExample.HelloWorldServiceImpl
8 </implementationClass>
9 <style>wrapped</style>
10 <use>literal</use>
11 <scope>application</scope>
12 </service>
把整个项目部署到tomcat服务器中 ,打开浏览器,输入http://localhost:8989/HelloWorld/services/HelloWorldService?wsdl,可以看到如下:
然后再展开HelloWorldService后面的wsdl可以看到:
客户端实现如下:
1package com.myeclipse.wsExample.client;
2
3import java.net.MalformedURLException;
4import java.net.URL;
5
6import org.codehaus.xfire.XFireFactory;
7import org.codehaus.xfire.client.Client;
8import org.codehaus.xfire.client.XFireProxyFactory;
9import org.codehaus.xfire.service.Service;
10import org.codehaus.xfire.service.binding.ObjectServiceFactory;
11
12import com.myeclipse.wsExample.IHelloWorldService;
13
14public class HelloWorldClient {
15public static void main(String[] args) throws MalformedURLException, Exception {
16// TODO Auto-generated method stub
17Service s=new ObjectServiceFactory().create(IHelloWorldService.class);
18XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire());
19String url="http://localhost:8989/HelloWorld/services/HelloWorldService";
20
21 try
22 {
23
24 IHelloWorldService hs=(IHelloWorldService) xf.create(s,url);
25 String st=hs.example("zhangjin");
26 System.out.print(st);
27 }
28 catch(Exception e)
29 {
30 e.printStackTrace();
31 }
32 }
33
34}
35
这里再说点题外话,有时候我们知道一个wsdl地址,比如想用java客户端引用.net 做得webservice,使用myeclipse引用,但是却出现无法通过验证的错误,这时我们可以直接在类中引用,步骤如下:
1public static void main(String[] args) throws MalformedURLException, Exception {
2 // TODO Auto-generated method stub
3 Service s=new ObjectServiceFactory().create(IHelloWorldService.class);
4 XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire());
5
6
7//远程调用.net开发的webservice
8Client c=new Client(new URL("http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl"));
9 Object[] o=c.invoke("qqCheckOnline", new String[]{"531086641","591284436"});
10
11//调用.net本机开发的webservice
12Client c1=new Client(new URL("http://localhost/zj/Service.asmx?wsdl"));
13Object[] o1=c1.invoke("HelloWorld",new String[]{});
14
15}
三、使用axis1.4调用webservice方法
前提条件:下载axis1.4包和tomcat服务器 ,并将axis文件夹复制到tomcat服务器的webapp文件夹中
这里我就说一下最简单的方法:
首先建立一个任意的java类(例如:HelloWorld.java),复制到axis文件夹下,将其扩展名改为jws,然后重新启动tomcat,在浏览器中输入http://localhost:8989/axis/HelloWorld.jws?wsdl,就会得到一个wsdl文件,其客户端调用方法如下:
1import javax.xml.rpc.Service;
2import javax.xml.rpc.ServiceException;
3import javax.xml.rpc.ServiceFactory;
4
5import java.net.MalformedURLException;
6import java.net.URL;
7import java.rmi.RemoteException;
8
9import javax.xml.namespace.QName;
10
11public class TestHelloWorld {
12
13
14 public static void main(String[] args) throws MalformedURLException, ServiceException, RemoteException {
15 // TODO Auto-generated method stub
16
17 String wsdlUrl ="http://localhost:8989/axis/HelloWorld.jws?wsdl";
18 String nameSpaceUri ="http://localhost:8989/axis/HelloWorld.jws";
19 String serviceName = "HelloWorldService";
20 String portName = "HelloWorld";
21
22 ServiceFactory serviceFactory = ServiceFactory.newInstance();
23 Service afService =serviceFactory.createService(new URL(wsdlUrl),new QName(nameSpaceUri, serviceName));
24 HelloWorldInterface proxy = (HelloWorldInterface)afService.getPort(new QName(nameSpaceUri, portName),HelloWorldInterface.class);
25 System.out.println("return value is "+proxy.getName("john") ) ;
26
27 }
28
29}
30
四、使用axis2开发webservice(这里首先感谢李宁老师)
使用axis2 需要先下载
axis2-1.4.1-bin.zip
axis2-1.4.1-war.zip
http://ws.apache.org/axis2/
同理,也需要将axis2复制到webapp目录中
在axis2中部署webservice有两种方法,
第一种是pojo方式,这种方式比较简单,但是有一些限制,例如部署的类不能加上包名
第二种方式是利用xml发布webservice,这种方法比较灵活,不需要限制类的声明
下面分别说明使用方法:
1.pojo方式:在Axis2中不需要进行任何的配置,就可以直接将一个简单的POJO发布成WebService。其中POJO中所有的public方法将被发布成WebService方法。先实现一个pojo类:
1public class HelloWorld{
2 public String getName(String name)
3 {
4 return "你好 " + name;
5 }
6 public int add(int a,int b)
7 {
8 return a+b;
9 }
10}
11
由于这两个方法都是public类型,所以都会发布成webservice。编译HelloWorld类后,将HelloWorld.class文件放到%tomcat%\webapps\axis2\WEB-INF\pojo目录中(如果没有pojo目录,则建立该目录),然后打开浏览器进行测试:
输入一下url:
http://localhost:8080/axis2/services/listServices
会列出所有webservice
这是其中的两个webservice列表,接着,在客户端进行测试:
首先可以写一个封装类,减少编码,代码如下:
1package MZ.GetWebService;
2import javax.xml.namespace.QName;
3
4import org.apache.axis2.AxisFault;
5import org.apache.axis2.addressing.EndpointReference;
6import org.apache.axis2.client.Options;
7import org.apache.axis2.rpc.client.RPCServiceClient;
8
9
10public class GetWSByAxis2 {
11 private static String EndPointUrl;
12 private static String QUrl="http://ws.apache.org/axis2";
13 private QName opAddEntry;
14 public String WSUrl;
15 public RPCServiceClient setOption() throws AxisFault
16 {
17 RPCServiceClient serviceClient = new RPCServiceClient();
18 Options options = serviceClient.getOptions();
19 EndpointReference targetEPR = new EndpointReference(WSUrl);
20 options.setTo(targetEPR);
21 return serviceClient;
22 }
23
24 public QName getQname(String Option){
25
26 return new QName (QUrl,Option);
27 }
28 //返回String
29 public String getStr(String Option) throws AxisFault
30 {
31 RPCServiceClient serviceClient =this.setOption();
32
33 opAddEntry =this.getQname(Option);
34
35 String str = (String) serviceClient.invokeBlocking(opAddEntry,
36 new Object[]{}, new Class[]{String.class })[0];
37 return str;
38 }
39// 返回一维String数组
40 public String[] getArray(String Option) throws AxisFault
41 {
42 RPCServiceClient serviceClient =this.setOption();
43
44 opAddEntry =this.getQname(Option);
45
46 String[] strArray = (String[]) serviceClient.invokeBlocking(opAddEntry,
47 new Object[]{}, new Class[]{String[].class })[0];
48 return strArray;
49 }
50 //从WebService中返回一个对象的实例
51 public Object getObject(String Option,Object o) throws AxisFault
52 {
53 RPCServiceClient serviceClient =this.setOption();
54 QName qname=this.getQname(Option);
55 Object object = serviceClient.invokeBlocking(qname, new Object[]{},new Class[]{o.getClass()})[0];
56 return object;
57 }
58
59/ 读者可以自己封装数据类型,如int,byte,float等数据类型
60}
61
客户端调用方法:
MZ.GetWebService.GetWSByAxis2 ws=new MZ.GetWebService.GetWSByAxis2();
ws.WSUrl="http://localhost:8989/axis2/services/HelloWorld";
HelloWorld hello= (HelloWorld)ws.getObject("getName", HelloWorld.class);
System.out.println(hello.getName("zhangjin"));
2.使用service.xml发布webservice,这种方式和直接放在pojo目录中的POJO类不同。要想将MyService类发布成Web Service,需要一个services.xml文件,这个文件需要放在META-INF目录中,该文件的内容如下:
<service name="HelloWorld">
<description>
HelloWorld webservice
</description>
<parameter name="ServiceClass">
service.HelloWorld
</parameter>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</messageReceivers>
</service>
其中<service>元素用于发布Web Service,一个<service>元素只能发布一个WebService类,name属性表示WebService名,如下面的URL可以获得这个WebService的WSDL内容:
http://localhost:8080/axis2/services/myService?wsdl
除此之外,还有直接可以在其中制定webservice操作方法:可以这样些service.xml文件
1<service name="HelloWorld">
2 <description>
3 HelloWorld service
4 </description>
5 <parameter name="ServiceClass">
6 service.HelloWorld
7 </parameter>
8 <operation name="getName">
9 <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
10 </operation>
11 <operation name="add">
12 <messageReceiver
13 class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
14 </operation>
15</service>
16
如果要发布多个webservice,可以在文件两段加上<serviceGroup><service></service>...<service></service></serviceGroup>发布
2、2、调整应用程序结构设计。这一部分也是在开发信息系统之前完成,程序员在这一步需要考虑应用程序使用什么样的体系结构,是使用传统的Client/Server两层体系结构,还是使用Browser/Web/Database的三层体系结构。不同的应用程序体系结构要求的数据库资源是不同的。
3、3、调整数据库SQL语句。应用程序的执行最终将归结为数据库中的SQL语句执行,因此SQL语句的执行效率最终决定了ORACLE数据库的性能。ORACLE公司推荐使用ORACLE语句优化器(Oracle Optimizer)和行锁管理器(row-level manager)来调整优化SQL语句。
4、4、调整服务器内存分配。内存分配是在信息系统运行过程中优化配置的,数据库管理员可以根据数据库运行状况调整数据库系统全局区(SGA区)的数据缓冲区、日志缓冲区和共享池的大小;还可以调整程序全局区(PGA区)的大小。需要注意的是,SGA区不是越大越好,SGA区过大会占用操作系统使用的内存而引起虚拟内存的页面交换,这样反而会降低系统。
5、5、调整硬盘I/O,这一步是在信息系统开发之前完成的。数据库管理员可以将组成同一个表空间的数据文件放在不同的硬盘上,做到硬盘之间I/O负载均衡。
6、6、调整操作系统参数,例如:运行在UNIX操作系统上的ORACLE数据库,可以调整UNIX数据缓冲池的大小,每个进程所能使用的内存大小等参数。
实际上,上述数据库优化措施之间是相互联系的。ORACLE数据库性能恶化表现基本上都是用户响应时间比较长,需要用户长时间的等待。但性能恶化的原因却是多种多样的,有时是多个因素共同造成了性能恶化的结果,这就需要数据库管理员有比较全面的计算机知识,能够敏感地察觉到影响数据库性能的主要原因所在。另外,良好的数据库管理工具对于优化数据库性能也是很重要的。
ORACLE数据库性能优化工具
常用的数据库性能优化工具有:
1、1、ORACLE数据库在线数据字典,ORACLE在线数据字典能够反映出ORACLE动态运行情况,对于调整数据库性能是很有帮助的。
2、2、操作系统工具,例如UNIX操作系统的vmstat,iostat等命令可以查看到系统系统级内存和硬盘I/O的使用情况,这些工具对于管理员弄清出系统瓶颈出现在什么地方有时候很有用。
3、3、SQL语言跟踪工具(SQL TRACE FACILITY),SQL语言跟踪工具可以记录SQL语句的执行情况,管理员可以使用虚拟表来调整实例,使用SQL语句跟踪文件调整应用程序性能。SQL语言跟踪工具将结果输出成一个操作系统的文件,管理员可以使用TKPROF工具查看这些文件。
4、4、ORACLE Enterprise Manager(OEM),这是一个图形的用户管理界面,用户可以使用它方便地进行数据库管理而不必记住复杂的ORACLE数据库管理的命令。
5、5、EXPLAIN PLAN——SQL语言优化命令,使用这个命令可以帮助程序员写出高效的SQL语言。
ORACLE数据库的系统性能评估
信息系统的类型不同,需要关注的数据库参数也是不同的。数据库管理员需要根据自己的信息系统的类型着重考虑不同的数据库参数。
1、1、在线事务处理信息系统(OLTP),这种类型的信息系统一般需要有大量的Insert、Update操作,典型的系统包括民航机票发售系统、银行储蓄系统等。OLTP系统需要保证数据库的并发性、可靠性和最终用户的速度,这类系统使用的ORACLE数据库需要主要考虑下述参数:
l l 数据库回滚段是否足够?
l l 是否需要建立ORACLE数据库索引、聚集、散列?
l l 系统全局区(SGA)大小是否足够?
l l SQL语句是否高效?
2、2、数据仓库系统(Data Warehousing),这种信息系统的主要任务是从ORACLE的海量数据中进行查询,得到数据之间的某些规律。数据库管理员需要为这种类型的ORACLE数据库着重考虑下述参数:
l l 是否采用B*-索引或者bitmap索引?
l l 是否采用并行SQL查询以提高查询效率?
l l 是否采用PL/SQL函数编写存储过程?
l l 有必要的话,需要建立并行数据库提高数据库的查询效率
SQL语句的调整原则
SQL语言是一种灵活的语言,相同的功能可以使用不同的语句来实现,但是语句的执行效率是很不相同的。程序员可以使用EXPLAIN PLAN语句来比较各种实现方案,并选出最优的实现方案。总得来讲,程序员写SQL语句需要满足考虑如下规则:
1、1、尽量使用索引。试比较下面两条SQL语句:
语句A:SELECT dname, deptno FROM dept WHERE deptno NOT IN
(SELECT deptno FROM emp);
语句B:SELECT dname, deptno FROM dept WHERE NOT EXISTS
(SELECT deptno FROM emp WHERE dept.deptno = emp.deptno);
这两条查询语句实现的结果是相同的,但是执行语句A的时候,ORACLE会对整个emp表进行扫描,没有使用建立在emp表上的deptno索引,执行语句B的时候,由于在子查询中使用了联合查询,ORACLE只是对emp表进行的部分数据扫描,并利用了deptno列的索引,所以语句B的效率要比语句A的效率高一些。
2、2、选择联合查询的联合次序。考虑下面的例子:
SELECT stuff FROM taba a, tabb b, tabc c
WHERE a.acol between :alow and :ahigh
AND b.bcol between :blow and :bhigh
AND c.ccol between :clow and :chigh
AND a.key1 = b.key1
AMD a.key2 = c.key2;
这个SQL例子中,程序员首先需要选择要查询的主表,因为主表要进行整个表数据的扫描,所以主表应该数据量最小,所以例子中表A的acol列的范围应该比表B和表C相应列的范围小。
3、3、在子查询中慎重使用IN或者NOT IN语句,使用where (NOT) exists的效果要好的多。
4、4、慎重使用视图的联合查询,尤其是比较复杂的视图之间的联合查询。一般对视图的查询最好都分解为对数据表的直接查询效果要好一些。
5、5、可以在参数文件中设置SHARED_POOL_RESERVED_SIZE参数,这个参数在SGA共享池中保留一个连续的内存空间,连续的内存空间有益于存放大的SQL程序包。
6、6、ORACLE公司提供的DBMS_SHARED_POOL程序可以帮助程序员将某些经常使用的存储过程“钉”在SQL区中而不被换出内存,程序员对于经常使用并且占用内存很多的存储过程“钉”到内存中有利于提高最终用户的响应时间。
CPU参数的调整
CPU是服务器的一项重要资源,服务器良好的工作状态是在工作高峰时CPU的使用率在90%以上。如果空闲时间CPU使用率就在90%以上,说明服务器缺乏CPU资源,如果工作高峰时CPU使用率仍然很低,说明服务器CPU资源还比较富余。
使用操作相同命令可以看到CPU的使用情况,一般UNIX操作系统的服务器,可以使用sar –u命令查看CPU的使用率,NT操作系统的服务器,可以使用NT的性能管理器来查看CPU的使用率。
数据库管理员可以通过查看v$sysstat数据字典中“CPU used by this session”统计项得知ORACLE数据库使用的CPU时间,查看“OS User level CPU time”统计项得知操作系统用户态下的CPU时间,查看“OS System call CPU time”统计项得知操作系统系统态下的CPU时间,操作系统总的CPU时间就是用户态和系统态时间之和,如果ORACLE数据库使用的CPU时间占操作系统总的CPU时间90%以上,说明服务器CPU基本上被ORACLE数据库使用着,这是合理,反之,说明服务器CPU被其它程序占用过多,ORACLE数据库无法得到更多的CPU时间。
数据库管理员还可以通过查看v$sesstat数据字典来获得当前连接ORACLE数据库各个会话占用的CPU时间,从而得知什么会话耗用服务器CPU比较多。
出现CPU资源不足的情况是很多的:SQL语句的重解析、低效率的SQL语句、锁冲突都会引起CPU资源不足。
1、数据库管理员可以执行下述语句来查看SQL语句的解析情况:
SELECT * FROM V$SYSSTAT
WHERE NAME IN
('parse time cpu', 'parse time elapsed', 'parse count (hard)');
这里parse time cpu是系统服务时间,parse time elapsed是响应时间,用户等待时间
waite time = parse time elapsed – parse time cpu
由此可以得到用户SQL语句平均解析等待时间=waite time / parse count。这个平均等待时间应该接近于0,如果平均解析等待时间过长,数据库管理员可以通过下述语句
SELECT SQL_TEXT, PARSE_CALLS, EXECUTIONS FROM V$SQLAREA
ORDER BY PARSE_CALLS;
来发现是什么SQL语句解析效率比较低。程序员可以优化这些语句,或者增加ORACLE参数SESSION_CACHED_CURSORS的值。
2、数据库管理员还可以通过下述语句:
SELECT BUFFER_GETS, EXECUTIONS, SQL_TEXT FROM V$SQLAREA;
查看低效率的SQL语句,优化这些语句也有助于提高CPU的利用率。
3、3、数据库管理员可以通过v$system_event数据字典中的“latch free”统计项查看ORACLE数据库的冲突情况,如果没有冲突的话,latch free查询出来没有结果。如果冲突太大的话,数据库管理员可以降低spin_count参数值,来消除高的CPU使用率。
内存参数的调整
内存参数的调整主要是指ORACLE数据库的系统全局区(SGA)的调整。SGA主要由三部分构成:共享池、数据缓冲区、日志缓冲区。
1、 1、 共享池由两部分构成:共享SQL区和数据字典缓冲区,共享SQL区是存放用户SQL命令的区域,数据字典缓冲区存放数据库运行的动态信息。数据库管理员通过执行下述语句:
select (sum(pins - reloads)) / sum(pins) "Lib Cache" from v$librarycache;
来查看共享SQL区的使用率。这个使用率应该在90%以上,否则需要增加共享池的大小。数据库管理员还可以执行下述语句:
select (sum(gets - getmisses - usage - fixed)) / sum(gets) "Row Cache" from v$rowcache;
查看数据字典缓冲区的使用率,这个使用率也应该在90%以上,否则需要增加共享池的大小。
2、 2、 数据缓冲区。数据库管理员可以通过下述语句:
SELECT name, value FROM v$sysstat WHERE name IN ('db block gets', 'consistent gets','physical reads');
来查看数据库数据缓冲区的使用情况。查询出来的结果可以计算出来数据缓冲区的使用命中率=1 - ( physical reads / (db block gets + consistent gets) )。
这个命中率应该在90%以上,否则需要增加数据缓冲区的大小。
3、 3、 日志缓冲区。数据库管理员可以通过执行下述语句:
select name,value from v$sysstat where name in ('redo entries','redo log space requests');查看日志缓冲区的使用情况。查询出的结果可以计算出日志缓冲区的申请失败率:
申请失败率=requests/entries,申请失败率应该接近于0,否则说明日志缓冲区开设太小,需要增加ORACLE数据库的日志缓冲区。
做了一大半年的业务数据库优化了,有一点感想,写出来自励一下。
公司开发的产品基本上都使用ORACLE数据库,而且业务系统中存储和使用的数据量很大,使用业务系统的用户也很多。在系统忙时,大约会有一千个用户同事访问数据库系统,因此经常会有用户抱怨系统慢,点击查询后,系统出现假死机现象,后台运行ORACLE系统的小型机的IDLE值偏低(甚至出现IDLE为0的情况,这时用户会惊呼数据库系统会瘫掉,虽然小型型机在IDLE值为0的情况下也不一定会瘫机,但这无疑会增加用户的担忧),系统运行在一个不安全的状态等等。
对于我现在所做的ORACLE优化,其实还停留在SQL优化的层次(以前我的前辈曾给我说关于数据库优化的三个层次:一是针对SQL的优化,如使用正确是索引,使用ORACLE提示等;二是针对数据库对象的优化,如增加索引,微调表结构等;三针对业务的优化,需要更改业务逻辑或者表结果,此类优化一般代价比较大,一般很少针对正在运行的系统做类似的操作)。
公司的客户很多,大多数情况会在公司远程处理客户的数据库问题。作为问题的定位者,一定要搞清楚实际运行的数据库系统到底出现了什么问题。现场的维护人员和用户最喜欢使用的形容词是:系统很慢;数据库锁表了等等。用户向外面传达的信心往往是非常模糊的,在开始接触这个问题时候起,我们就要引导用户去帮外面了解系统真实的情况。有几个东西是一定要看看的,一个是ORACLE系统的警告日志文件,在系统运行的有问题或者是忙时的几份STATSPACK报告(一般间隔时间10到15分钟),UNIX下SAR命令的输入结果(该命令可以按既定的时间间隔收集小型机系统CPU的使用情况)。通过这三个从现场收集的结果,我们基本可以了解现场数据库的运行情况。
其中ORACLE系统的警告日志文件能让我们了解ORACLE系统运行有没有一些重大的问题。
STATSPACK报告中概括了数据库系统的运行基本情况,其中关于如何解读报告可以写一本书了,不过我们首先要关注的是报告中有一段“Top 5 Timed Events”,这一段描述了当前ORACLE主要的等待事件是什么(关于ORACLE等待事件的概念可以参考相关的资料)。
SAR命令的输入我们要关注三个输出的分布情况USR、WIO、IDLE。其中SYS+USR+WIO+IDLE应该等于100%,USR占的比例高,一般说明SQL语句执行效率有问题,这种问题一般是由于索引选择性不高、表连接顺序和方式不对等等;WIO高一般说明SQL语句频繁进行I/O操作。对于具体的问题,则需要对具体的SQL语句进行分析,在分析过程中,阅读执行计划是我们的一个重要的工具。
在对ORACLE系统的整体情况有了一定的了解之后,下一步需要分析的就是系统运行过程效率不高的SQL,这是对业务优化的一个起点。如果这时不能够在实际系统中操作,了解SQL的运行过程是一个比较费时的过程的。不管怎么样,对于我们怀疑有问题的SQL,首先要阅读的就是该SQL的在实际系统中的执行计划,语句涉及到的表的数据量,访问表使用索引的选择性如何,表连接的顺序,多表之间的关联关系等等。
对于ORACLE应用系统的优化,大方向上有一个顺序,首先考虑优化业务系统、再考虑优化ORACLE系统本身的参数(如内存分配等),再考虑操作系统本身的优化;在优化业务系统中,首先是首先相关的SQL,以SQL入手分析表是否缺少索引,表连接顺序是否正确,使用的索引是否正确等,然后再考虑调整表结构,调整业务逻辑等等。因此,SQL语句是我们对一个ORACLE业务系统进行优化的敲门砖。
对于SQL优化,前面提到了,ORACLE的执行计划是我们必须使用的工具。本来按ORACLE系统本身提供的方法获取执行计划是一件非常麻烦的事情,不过现在的可视化工具比如PL/SQL DEVELOP或者TOAD等都给我们提供了非常方便的手段来获取SQL语句的执行计划,不过我认为ORACLE本身提供的方法还是有必要会的,特别是在远程处理问题的时候(我也不会,一定要学习一下)。
获取有性能问题的SQL语句,我们主要有两个途径,一个是通过STATSPACK报告。报告中有两节是我们需要重点关注的:《SQL ordered by Gets for》和《SQL ordered by Reads for DB》,这两节中分别按语句读取内存数据库块和读取的物理数据库块(数据库块是指ORACLE的块大小,一般是操作系统最小块的整数倍)的数量倒序排列,如果其中的语句不全(太长),可通过HASH_VALUE值到ORACLE的动态视图V$SQLTEXT中获取该SQL的全部语句。第二个是通过ORACLE系统的动态视图,V$SQL,该视图记录了每个SQL语句的执行次数,物理读和内存读、执行时间等等很多SQL语句的执行信息,可以通过如下语句选择一下物理读和内存读较高的语句:
SELECT
t.HASH_VALUE,
t.EXECUTIONS,
t.DISK_READS,
round(t.DISK_READS/t.EXECUTIONS) AS perDiskReads,
t.BUFFER_GETS,
round(t.BUFFER_GETS/t.EXECUTIONS) AS perBufferReads,
t.ELAPSED_TIME,
round(t.ELAPSED_TIME/t.EXECUTIONS) AS perElayTime,
t.CPU_TIME,
round(t.CPU_TIME/t.EXECUTIONS) AS perCpuTime,
t.FIRST_LOAD_TIME,
t.SQL_TEXT
FROM v$sql t
WHERE (t.DISK_READS/t.EXECUTIONS > 500 OR t.BUFFER_GETS/t.EXECUTIONS > 20000)
AND t.EXECUTIONS > 0
ORDER BY 6 DESC;
这个语句查询出来的SQL可能也不全,也可以通过HASH_VALUE在V$SQLTEXT中找到其全部的SQL。
对于找到的SQL语句我们可以逐一分析其执行计划,结合涉及到的表的数据量,我们可以估算或者测试该语句的执行效率,分析表WHERE条件中涉及的字段(术语叫做谓词),该字段数据分布如何,选择性是否好,是否有索引。这是一个非常繁杂和琐碎的工作,但从这些琐碎的工作中,我们能发现那些SQL执行时选择的索引不对,哪些表缺少相应的索引导致了全表扫描,哪些语句条件不够导致对分区表进行了全表扫描。总之,对于一个给定的SQL,我们结合其表数据量的大小和分布,SQL中使用的查询条件,能够找到一个性能最优的执行方式,通过调整索引、使用ORACLE提示,使ORACLE系统按照最优的方式来执行SQL。如何去分析和确定ORACLE的执行方式,一个最普遍的原则就是尽量根据其谓词(查询条件),使用选择性最好的索引(当然,对于一些小表,可以考虑使用全表扫描的方式性能会更好)。对于SQL的执行方式,需要在工作中不断积累经验,比如曾经在一次优化中发现对一个表安三个字段查询的非常多,因此决定建立该三个字段的复合索引,但结果其语句执行效率却更差。
呵呵,今天先写这么多了,希望大家多多指教
java 调用webservice的各种方法总结
现在webservice加xml技术已经逐渐成熟,但要真正要用起来还需时日!!
由于毕业设计缘故,我看了很多关于webservice方面的知识,今天和大家一起来研究研究webservice的各种使用方法。
一、利用jdk web服务api实现,这里使用基于 SOAP message 的 Web 服务
1.首先建立一个Web services EndPoint:
package Hello;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;
@WebService
public class Hello {
@WebMethod
public String hello(String name) {
return "Hello, " + name + "\n";
}
public static void main(String[] args) {
// create and publish an endpoint
Hello hello = new Hello();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/hello", hello);
}
}
2.使用 apt 编译 Hello.java(例:apt -d [存放编译后的文件目录] Hello.java ) ,会生成 jaws目录
3.使用java Hello.Hello运行,然后将浏览器指向http://localhost:8080/hello?wsdl就会出现下列显示
4.使用wsimport 生成客户端
使用如下:wsimport -p . -keep http://localhost:8080/hello?wsdl
这时,会在当前目录中生成如下文件:
5.客户端程序:
1class HelloClient{
2public static void main(String args[]) {
3 HelloService service = new HelloService();
4 Hello helloProxy = service.getHelloPort();
5 String hello = helloProxy.hello("你好");
6 System.out.println(hello);
7 }
8}
9
以上方法还稍显繁琐,还有更加简单的方法
二、使用xfire,我这里使用的是myeclipse集成的xfire进行测试的
利用xfire开发WebService,可以有三种方法:
1一种是从javabean 中生成;
2 一种是从wsdl文件中生成;
3 还有一种是自己建立webservice
步骤如下:
用myeclipse建立webservice工程,目录结构如下:
首先建立webservice接口,
代码如下:
1package com.myeclipse.wsExample;
2//Generated by MyEclipse
3
4public interface IHelloWorldService {
5
6 public String example(String message);
7
8}
接着实现这个借口:
1package com.myeclipse.wsExample;
2//Generated by MyEclipse
3
4public class HelloWorldServiceImpl implements IHelloWorldService {
5
6 public String example(String message) {
7 return message;
8 }
9
10}
修改service.xml 文件,加入以下代码:
1<service>
2 <name>HelloWorldService</name>
3 <serviceClass>
4 com.myeclipse.wsExample.IHelloWorldService
5 </serviceClass>
6 <implementationClass>
7 com.myeclipse.wsExample.HelloWorldServiceImpl
8 </implementationClass>
9 <style>wrapped</style>
10 <use>literal</use>
11 <scope>application</scope>
12 </service>
把整个项目部署到tomcat服务器中 ,打开浏览器,输入http://localhost:8989/HelloWorld/services/HelloWorldService?wsdl,可以看到如下:
然后再展开HelloWorldService后面的wsdl可以看到:
客户端实现如下:
1package com.myeclipse.wsExample.client;
2
3import java.net.MalformedURLException;
4import java.net.URL;
5
6import org.codehaus.xfire.XFireFactory;
7import org.codehaus.xfire.client.Client;
8import org.codehaus.xfire.client.XFireProxyFactory;
9import org.codehaus.xfire.service.Service;
10import org.codehaus.xfire.service.binding.ObjectServiceFactory;
11
12import com.myeclipse.wsExample.IHelloWorldService;
13
14public class HelloWorldClient {
15public static void main(String[] args) throws MalformedURLException, Exception {
16// TODO Auto-generated method stub
17Service s=new ObjectServiceFactory().create(IHelloWorldService.class);
18XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire());
19String url="http://localhost:8989/HelloWorld/services/HelloWorldService";
20
21 try
22 {
23
24 IHelloWorldService hs=(IHelloWorldService) xf.create(s,url);
25 String st=hs.example("zhangjin");
26 System.out.print(st);
27 }
28 catch(Exception e)
29 {
30 e.printStackTrace();
31 }
32 }
33
34}
35
这里再说点题外话,有时候我们知道一个wsdl地址,比如想用java客户端引用.net 做得webservice,使用myeclipse引用,但是却出现无法通过验证的错误,这时我们可以直接在类中引用,步骤如下:
1public static void main(String[] args) throws MalformedURLException, Exception {
2 // TODO Auto-generated method stub
3 Service s=new ObjectServiceFactory().create(IHelloWorldService.class);
4 XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire());
5
6
7//远程调用.net开发的webservice
8Client c=new Client(new URL("http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl"));
9 Object[] o=c.invoke("qqCheckOnline", new String[]{"531086641","591284436"});
10
11//调用.net本机开发的webservice
12Client c1=new Client(new URL("http://localhost/zj/Service.asmx?wsdl"));
13Object[] o1=c1.invoke("HelloWorld",new String[]{});
14
15}
三、使用axis1.4调用webservice方法
前提条件:下载axis1.4包和tomcat服务器 ,并将axis文件夹复制到tomcat服务器的webapp文件夹中
这里我就说一下最简单的方法:
首先建立一个任意的java类(例如:HelloWorld.java),复制到axis文件夹下,将其扩展名改为jws,然后重新启动tomcat,在浏览器中输入http://localhost:8989/axis/HelloWorld.jws?wsdl,就会得到一个wsdl文件,其客户端调用方法如下:
1import javax.xml.rpc.Service;
2import javax.xml.rpc.ServiceException;
3import javax.xml.rpc.ServiceFactory;
4
5import java.net.MalformedURLException;
6import java.net.URL;
7import java.rmi.RemoteException;
8
9import javax.xml.namespace.QName;
10
11public class TestHelloWorld {
12
13
14 public static void main(String[] args) throws MalformedURLException, ServiceException, RemoteException {
15 // TODO Auto-generated method stub
16
17 String wsdlUrl ="http://localhost:8989/axis/HelloWorld.jws?wsdl";
18 String nameSpaceUri ="http://localhost:8989/axis/HelloWorld.jws";
19 String serviceName = "HelloWorldService";
20 String portName = "HelloWorld";
21
22 ServiceFactory serviceFactory = ServiceFactory.newInstance();
23 Service afService =serviceFactory.createService(new URL(wsdlUrl),new QName(nameSpaceUri, serviceName));
24 HelloWorldInterface proxy = (HelloWorldInterface)afService.getPort(new QName(nameSpaceUri, portName),HelloWorldInterface.class);
25 System.out.println("return value is "+proxy.getName("john") ) ;
26
27 }
28
29}
30
四、使用axis2开发webservice(这里首先感谢李宁老师)
使用axis2 需要先下载
axis2-1.4.1-bin.zip
axis2-1.4.1-war.zip
http://ws.apache.org/axis2/
同理,也需要将axis2复制到webapp目录中
在axis2中部署webservice有两种方法,
第一种是pojo方式,这种方式比较简单,但是有一些限制,例如部署的类不能加上包名
第二种方式是利用xml发布webservice,这种方法比较灵活,不需要限制类的声明
下面分别说明使用方法:
1.pojo方式:在Axis2中不需要进行任何的配置,就可以直接将一个简单的POJO发布成WebService。其中POJO中所有的public方法将被发布成WebService方法。先实现一个pojo类:
1public class HelloWorld{
2 public String getName(String name)
3 {
4 return "你好 " + name;
5 }
6 public int add(int a,int b)
7 {
8 return a+b;
9 }
10}
11
由于这两个方法都是public类型,所以都会发布成webservice。编译HelloWorld类后,将HelloWorld.class文件放到%tomcat%\webapps\axis2\WEB-INF\pojo目录中(如果没有pojo目录,则建立该目录),然后打开浏览器进行测试:
输入一下url:
http://localhost:8080/axis2/services/listServices
会列出所有webservice
这是其中的两个webservice列表,接着,在客户端进行测试:
首先可以写一个封装类,减少编码,代码如下:
1package MZ.GetWebService;
2import javax.xml.namespace.QName;
3
4import org.apache.axis2.AxisFault;
5import org.apache.axis2.addressing.EndpointReference;
6import org.apache.axis2.client.Options;
7import org.apache.axis2.rpc.client.RPCServiceClient;
8
9
10public class GetWSByAxis2 {
11 private static String EndPointUrl;
12 private static String QUrl="http://ws.apache.org/axis2";
13 private QName opAddEntry;
14 public String WSUrl;
15 public RPCServiceClient setOption() throws AxisFault
16 {
17 RPCServiceClient serviceClient = new RPCServiceClient();
18 Options options = serviceClient.getOptions();
19 EndpointReference targetEPR = new EndpointReference(WSUrl);
20 options.setTo(targetEPR);
21 return serviceClient;
22 }
23
24 public QName getQname(String Option){
25
26 return new QName (QUrl,Option);
27 }
28 //返回String
29 public String getStr(String Option) throws AxisFault
30 {
31 RPCServiceClient serviceClient =this.setOption();
32
33 opAddEntry =this.getQname(Option);
34
35 String str = (String) serviceClient.invokeBlocking(opAddEntry,
36 new Object[]{}, new Class[]{String.class })[0];
37 return str;
38 }
39// 返回一维String数组
40 public String[] getArray(String Option) throws AxisFault
41 {
42 RPCServiceClient serviceClient =this.setOption();
43
44 opAddEntry =this.getQname(Option);
45
46 String[] strArray = (String[]) serviceClient.invokeBlocking(opAddEntry,
47 new Object[]{}, new Class[]{String[].class })[0];
48 return strArray;
49 }
50 //从WebService中返回一个对象的实例
51 public Object getObject(String Option,Object o) throws AxisFault
52 {
53 RPCServiceClient serviceClient =this.setOption();
54 QName qname=this.getQname(Option);
55 Object object = serviceClient.invokeBlocking(qname, new Object[]{},new Class[]{o.getClass()})[0];
56 return object;
57 }
58
59/ 读者可以自己封装数据类型,如int,byte,float等数据类型
60}
61
客户端调用方法:
MZ.GetWebService.GetWSByAxis2 ws=new MZ.GetWebService.GetWSByAxis2();
ws.WSUrl="http://localhost:8989/axis2/services/HelloWorld";
HelloWorld hello= (HelloWorld)ws.getObject("getName", HelloWorld.class);
System.out.println(hello.getName("zhangjin"));
2.使用service.xml发布webservice,这种方式和直接放在pojo目录中的POJO类不同。要想将MyService类发布成Web Service,需要一个services.xml文件,这个文件需要放在META-INF目录中,该文件的内容如下:
<service name="HelloWorld">
<description>
HelloWorld webservice
</description>
<parameter name="ServiceClass">
service.HelloWorld
</parameter>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</messageReceivers>
</service>
其中<service>元素用于发布Web Service,一个<service>元素只能发布一个WebService类,name属性表示WebService名,如下面的URL可以获得这个WebService的WSDL内容:
http://localhost:8080/axis2/services/myService?wsdl
除此之外,还有直接可以在其中制定webservice操作方法:可以这样些service.xml文件
1<service name="HelloWorld">
2 <description>
3 HelloWorld service
4 </description>
5 <parameter name="ServiceClass">
6 service.HelloWorld
7 </parameter>
8 <operation name="getName">
9 <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
10 </operation>
11 <operation name="add">
12 <messageReceiver
13 class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
14 </operation>
15</service>
16
如果要发布多个webservice,可以在文件两段加上<serviceGroup><service></service>...<service></service></serviceGroup>发布