分享
 
 
 

Web Service学习笔记之----JAX-RPC

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Web Service学习笔记之----JAX-RPC

导读

本文是我对学习jwsdp-1.2时所做笔记的整理,其中主要是一些指导性的内容,并没有多少概念以及原理的介绍,读者可能觉得略显简单,如果想要学习基本概念可以参考网上有关Web Service的资料。本文例子所使用的开发环境是WindowXP+JWSDP-1.2。

一.Web Service简介

1.定义

由两部分组成

·SOAP--Web Service之间的基本通信协议。

·WSDL--Web Service描述语言,它定义了Web Service做什么,怎么做和查询的信息。

2.简单的Web Service实现

包含四个基本步骤

·创建Web Service的商业逻辑(通常是一些Java类)

·将这些Java类部署到一个SOAP服务器上

·生成客户访问代码

·部署客户应用

注意:WSDL等文件的生成通常是利用厂商提供的工具来完成

3.WSDL解析

WSDL描述语言一般包含三部分

·What部分--包括了type、message和portType元素

Type:定义了Web Service使用的数据结构(使用XML Schema定义)

Message:一个Message是SOAP的基本通信元素。每个Message可以有一个或多个Part,每个Part代表一个参数。

PortType:消息汇总为不同的操作并归入到一个被称为portType的实体中。一个portType代表一个接口(Web Service支 持的操作集合),每个Web Service可以有多个接口,它们都使用portType表示。每个操作又包含了input和 output部分。

·How部分--包含binding元素

binding元素将portType绑定到特定的通信协议上(如HTTP上的SOAP协议)

·Where部分--由service元素组成

它将portType,binding以及Web Service实际的位置(URI)放在一起描述

4.客户端

通常Web Service可以有三种类型的客户

·商业伙伴(Business Partner)--包括分发商,零售商以及大型消费者)

此类客户通过SOAP、WSDL、ebXML、UDDI等XML技术与Web Service连接

·瘦客户--包括Web浏览器、PDA以及无线设备

该类客户通常经由轻量协议(如HTTP)与Web Service连接

·肥客户--包括Applet、各类应用以及现存系统

通常使用重量级协议(如IIOP)连接Web Service

二.使用JAX-RPC开发Web Service

1.JAX-RPC支持的数据类型

JAX-RPC除了支持Java的基本数据类型外还支持一些自定义对象,但这些对象有一些条件限制

·有缺省构造函数的对象

·没有实现java.rmi.Remote接口

·字段必须是JAX-RPC支持的类型

·公有字段不能声明为final或transient

·非公有字段必须有对应的setter和getter方法

2.使用JAX-RPC创建Web Service

·基本步骤

A. 编写服务端接口并实现

一个服务的end-point有一些规定:必须实现java.rmi.Remot接口而且每个方法需要抛出RemoteException异常。

B. 编译、生成并且将所有服务需要的类和文件打包成WAR文件

C. 部署包含服务的WAR文件

·如何创建服务

A. 编译服务所需的类文件

B. 生成服务所需文件

可以使用wscompile工具生成model.gz文件,它包含了描述服务的内部数据结构命令如下

wscompile -define -d build -nd build -classpath build config.xml

-model build/model.gz

define标志告诉工具读取服务的 endpoint接口并且创建WSDL文件。-d和-nd标志告诉工具将输出文件写入指定的目录build。工具需要读以下的config.xml文件

<?xml version=”1.0” encoding=”UTF-8”?>

<configuration xmlns=”http://java.sun.com/xml/ns/jax-rpc/ri/config”>

<service

name=”HelloService”

targetNamespace=”urn:Star”

typeNamespace=”urn:Star”

packageName=”helloservice”>

<interface name=”helloservice.HelloIF”/>

</service>

</configuration>

该文件告诉wscompile创建model文件所需的信息

·服务名称:MyHelloService

·WSDL名字空间:urn:Star

·HelloService的所有类在包helloservice中

·服务的端点(endpoint)接口:helloservice.HelloIF

C. 将服务打包为WAR文件

WEB-INF/classes/hello/HelloIF.class

WEB-INF/classes/hello/HelloImpl.class

WEB-INF/jaxrpc-ri.xml

WEB-INF/model.gz

WEB-INF/web.xml

jaxrpc-ri.xml文件如下所述

<?xml version=”1.0” encoding=”UTF-8”?>

<webServices xmlns=”http://java.sun.com/xml/ns/jax-rpc/ri/dd

version=”1.0”

targetNamespaceBase=”urn:Star”

typeNamespaceBase=”urn:Star”

urlPatternBase=”webservice”>

<endpoint name=”Hello”

displayName=”HelloWorld Service”

description=”A simple web service”

interface=”helloservice.HelloIF”

model=”/WEB-INF/model.gz”

implementation=”helloservice.HelloImpl”/>

<endpointMapping endpointName=”Hello” urlPattern=”/hello”/>

</webServices>

D. 处理WAR文件

使用命令行

wsdeploy -o hello-jaxrpc.war hello-jaxrpc-original.war

wsdeploy工具完成以下几个任务

·读 hello-jaxrpc-original.war作为输入

·从jaxrpc-ri.xml文件中获得信息

·为服务生成tie classes

·生成名为HelloService.wsdl的WSDL文件

·将tie classes和HelloService.wsdl文件打包到新的war文件中

E. 在服务器上部署服务

如果你使用的是TOMCAT,你可以将WAR文件拷贝到webapps目录下,然后可以在

<http://localhost:8080/[context]/[servicename>上看是否配置成功

·如何使用JAX-RPC创建Web Service客户端

通常有三种类型的客户:Static Stub、Dynamic Proxy和Dynamic Invocation Interface(DII)

Static Stub客户

·生成Stub

通过使用config-wsdl.xml和wscompile工具,可以生成stub

wscompile -gen:client -d build -classpath build config-wsdl.xml

config-wsdl.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>

<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">

<wsdl location="http://localhost:8080/helloWS/hello?WSDL"

packageName="staticstub"/>

</configuration>

wscompile工具读取服务器上的WSDL文件并生成stub

·编写静态客户代码

Stub stub=(Stub)(new HelloService_Impl().getHelloIFPort());

HelloIF hello=(HelloIF)stub;

Hello.sayHello(“starchu”);

注意:HelloService_Impl类由wscompile生成

·编译代码

·运行客户端(需要包含saaj API和JAX-RPC API运行)

Dynamic Proxy客户

·生成接口

通过使用config-wsdl.xml文件和wscompile工具,可以生成客户所需的接口

wscompile -import -d build -classpath build config-wsdl.xml

config-wsdl.xml和前面列出的文件内容相同。

·编写动态客户代码

ServiceFactory factory=ServiceFactory.newInstance();

URL wsdlUrl=new URL(“<your web service wsdl url>”);

Service service=factory.createService(wsdlUrl,

new QName(“urn:Star”,”HelloService”));

HelloIF hello=(HelloIF)service.getPort(

new QName(“urn:Star”,”HelloIFPort”),HelloIF.class);

Hello.sayHello(“starchu”);

注意:这里不再需要静态客户代码的HelloService_Impl类

·编译代码

·运行客户端(需要包含saaj API和JAX-RPC API运行)

Dynamic Invocation Interface客户

这个方法为我们提供了更有弹性的客户调用方式,客户代码不在需要由wscompile工具生成的运行时类,当然这种代码更加复杂。具体步骤如下:

·创建ServiceFactory实例

ServiceFactory factory=ServiceFactory.newInstance();

·创建Service(利用服务名的Qname)

Service service=factory.createService(new QName(“HelloService”));

·创建Call对象(使用端点接口的Qname)

Call call=service.createCall(new QName(“HelloIF”));

·设置端点的地址和一些Call对象属性

call.setTargetEndpointAddress(args[0]);

call.setProperty(Call.SOAPACTION_USE_PROPERTY,new Boolean(true));

call.setProperty(Call.SOAPACTION_URI_PROPERTY,””);

call.setProperty(“javax.xml.rpc.encodingstyle.namespace.uri”,

http://schemas.xmlsoap.org/soap/encoding/”);

·设置远程调用的返回类型、操作名和参数

QName stringType=new Qname(“http://www.w3.org/2001/XMLSchema”,”string”)

call.setReturnType(stringType);

call.setOperationName(new Qname(“urn:Star”,”sayHello”));

call.addParameter(“String_1”,stringType,ParameterMode.IN);

·调用call的invoke方法

String [] param={ “ starchu “ };

String retValue=call.invoke(param);

·编译代码并对Main方法设置<http://localhost:8080/helloWS/hello参数(服务器需有效>)

3.SOAP Message Handler的例子

通常使用JAX-RPC建立的Web Service并不需要开发人员自己处理SOAP消息,但是JAX-RPC提供了一种机制可以使程序员获得这种处理能力,这就是所谓的消息处理器。总的来说,像日志和加解密功能可以通过SOAP消息处理器实现,除此之外,你根本不需要处理SOAP消息。

·基本Handler处理过程

SOAP请求

·客户端处理器在请求消息发送到服务器前被调用

·服务端处理器在请求消息分发到端点前被调用

SOAP应答

·服务端处理器在应答消息发送回客户前被调用

·客户端处理器在应答消息转换成Java方法返回前被调用

SOAP错误

处理过程与SOAP应答的方式一样

注意:处理器可以在任意端组成处理器链

A.Handler基本编程模型

服务端

·编写服务端点接口代码、实现服务并且实现服务端处理器类

·创建jaxrpc-ri.xml文件,以便wscompile使用,其中包含了Handler的信息

·创建web.xml文件

·编译所有代码

·将文件打包为WAR文件

·用wsdeploy工具将原始war文件替换为完整可部署的war文件

·在服务器上部署war文件

客户端

·编写客户程序以及客户端处理器代码

·创建config.xml文件以便wscompile使用,它包含了客户端处理器的信息

·编译代码

·运行wscompile生成服务端点接口和客户类

·编译所有代码,并运行客户应用

B.建立客户端处理器

处理器必须扩展javax.xml.rpc.handler.GenericHandler类并且提供至少两个方法的实现init和getHandlers。此外,你可以利用handleXXX方法处理请求、应答和错误SOAP消息。基本步骤如下

·编写客户端处理器代码

Public class ClientHandler extends GenericHandler{

Public void init(HandlerInfo info){

This.info=info;

}

public QName[] getHeaders(){

return info.getHeaders();

}

public boolean handleRequest(MessageContext context){

SOAPMessageContext smc=(SOAPMessageContext)context;

SOAPMessage message=smc.getMessage();

file://You can use SOAP API to implement your own logic

file://such as logging and encrypt

……

file://Set a logger element in the SOAPHeader

SOAPHeaderElement loggerElement=

header.addHeaderElement(envelope.createName(“loginfo”,

“ns1”,”urn:Star:headprops”));

loggerElement.setMustUnderstand(true);

loggerElement.setValue(“10”);

file://Set a name element in the SOAP Header

SOAPHeaderElement nameElement=

Header.addHeaderElement(envelope.createName(“client”,

“ns1”,”urn:Star:headprops”));

nameElement.addTextNode(“Star chu”);

}

}

·编辑config.xml文件

<?xml version=”1.0” encoding=”UTF-8”?>

<configuration xmlns=”http://java.sun.com/xml/ns/jax-rpc/ri/config”?>

<wsdl location=”http://localhost:8080/handlerWS/handler?WSDL

packageName=”client”>

<handlerChains>

<chain runAt=”client”>

<handler className=”client.ClientHandler”>

<property name=”name” value=”client handler”/>

</handler>

</chain>

</handlerChains></wsdl></configuration>

·编写静态客户

C.建立服务端处理器

·编写服务端处理器(与客户端结构类似)

Public boolean handleRequest(MessageContext context){

SOAPMessageContext smc=(SOAPMessageContext)context;

……

Iterator it=header.examineAllHeaderElements();

While(it.hasNext()){

SOAPElement element=(SOAPElement)it.next();

If(element name is loginfo and must understand it){

element.getValue();

element.detach();

file://Invoke only when the setMustUnderstand(true)

}

}

}

detach方法用来移除元素,这个需求仅当一个元素设置了mustUnderstand属性在必要。

·编辑jaxrpc-ri.xml文件

<?xml version=”1.0” encoding=”UTF-8”?>

<webServices xmlns=”http://java.sun.com/jax-rpc/config/ri/dd

version=”1.0”

targetNamespaceBase=”urn:Star:wsdl”

typeNamespaceBase=”urn:Star:types”

urlPatternBase=”/handler”>

<endpoint name=”HandlerTest”

displayName=”Handler Test”

description=” … …”

interface=”service.HandlerTest”

model=”/WEB-INF/model.gz”

implementation=”service.HandlerTestImpl”>

<handlerChains>

<chain runAt=”server”>

<handler className=”service.LoggerHandler”

headers=”ns1:loginfo”

xmlns:ns1=”urn:Star:headerprops”>

<property name=”name” value=”Logger”/>

</handler>

<handler className=”service.NameHandler”>

<propery name=”name” value=”Name”/>

</handler>

</chain>

</handlerChains>

</endpoint>

<endpointMapping endpointName=”HandlerTest”

urlPattern=”/handler”/>

</webServices>

在第一个处理器中,XML使用了属性 headers描述头信息。这是因为客户代码告诉服务端,logger头必须被理解,否则客户将收到SOAP错误消息

·生成WAR文件并部署到服务器上

4.源代码

·HelloIF.java(endpoint接口)

package helloservice;

import java.rmi.RemoteException;

import java.rmi.Remote;

public interface HelloIF extends Remote{

public String sayHello(String target) throws RemoteException;

}

·HelloImpl.java

package helloservice;

public class HelloImpl implements HelloIF{

private String message="Hello";

public String sayHello(String target){

return message+target;

}

}

·StaticClient.java

package staticstub;

import javax.xml.rpc.Stub;

public class StaticClient{

private static String endpointAddress;

public static void main(String [] args){

if(args.length!=1){

System.err.println("Usage : java HelloClient [endpoint address]");

System.exit(-1);

}

endpointAddress=args[0];

System.out.println("Connect to :"+endpointAddress);

try{

Stub stub=createStub();

stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,

endpointAddress);

HelloIF hello=(HelloIF)stub;

System.out.println(hello.sayHello(" Starchu!"));

}catch(Exception e){System.err.println(e.toString());}

}

private static Stub createStub(){

return (Stub)(new HelloService_Impl().getHelloIFPort());

}

}

·DynamicClient.java

package dynamicproxy;

import java.net.URL;

import javax.xml.namespace.QName;

import javax.xml.rpc.Service;

import javax.xml.rpc.ServiceFactory;

import javax.xml.rpc.JAXRPCException;

import staticstub.HelloIF;

public class DynamicClient{

private static String wsdl;

private static String namespaceUri="urn:Star:wsdl";

private static String serviceName="HandlerService";

private static String portName="HandlerTestPort";

public static void main(String [] args){

if(args.length!=1){

System.err.println("Usage : java DynamicClient [server Url]");

System.exit(-1);

}

System.out.println("Connect to :"+args[0]);

helloWsdl=args[0]+"?WSDL";

try{

URL wsdlUrl=new URL(wsdl);

ServiceFactory serviceFactory=ServiceFactory.newInstance();

Service service=

serviceFactory.createService(wsdlUrl,

new QName(namespaceUri,serviceName));

HandlerTest proxy=(HandlerTest)service.getPort(

new QName(namespaceUri,portName),HandlerTest.class);

proxy.test();

}catch(Exception e){

System.err.println(e.toString());

}

}

}

·DIIClient.java

package dii;

import javax.xml.rpc.*;

import javax.xml.namespace.*;

public class DIIClient{

private static String qnameService = "HelloService";

private static String qnamePort = "HelloIF";

private static String BODY_NAMESPACE_VALUE ="urn:Star";

private static String ENCODING_STYLE_PROPERTY ="javax.xml.rpc.encodingstyle.namespace.uri";

private static String NS_XSD ="http://www.w3.org/2001/XMLSchema";

private static String URI_ENCODING ="http://schemas.xmlsoap.org/soap/encoding/";

public static void main(String [] args){

try{

ServiceFactory factory=ServiceFactory.newInstance();

Service service=factory.createService(new QName(qnameService));

QName port=new QName(qnamePort);

Call call=service.createCall(port);

call.setTargetEndpointAddress(args[0]);

call.setProperty(Call.SOAPACTION_USE_PROPERTY,new Boolean(true));

call.setProperty(Call.SOAPACTION_URI_PROPERTY,"");

call.setProperty(ENCODING_STYLE_PROPERTY,URI_ENCODING);

QName qnameTypeString=new QName(NS_XSD,"string");

call.setReturnType(qnameTypeString);

call.setOperationName(new QName(BODY_NAMESPACE_VALUE,"sayHello"));

call.addParameter("String_1",qnameTypeString,ParameterMode.IN);

String [] params = { "Starchu" };

System.out.println((String)call.invoke(params));

}catch(Exception e){

System.err.println(e.toString());

}

}

}

·Ant文件build.xml

<project name="helloWS" basedir="." default="deploy">

<property file="build.properties"/>

<property name="build" value="build"/>

<property name="dist" value="${build}\classes"/>

<property name="lib" value="${build}\lib"/>

<property name="src" value="src"/>

<property name="etc" value="${src}\etc"/>

<target name="clean">

<delete dir="${build}"/>

</target>

<target name="init">

<mkdir dir="${build}"/>

<mkdir dir="${dist}"/>

<mkdir dir="${lib}"/>

</target>

<path id="classpath">

<fileset dir="${tomcat.home}">

<include name="jaxrpc/**/*.jar"/>

<include name="jaxb/**/*.jar"/>

<include name="jaxp/**/*.jar"/>

<include name="saaj/**/*.jar"/>

<include name="jwsdp-shared/lib/**/*.jar"/>

</fileset>

<pathelement path="${dist}"/>

<pathelement location="${lib}"/>

</path>

<target name="compile-service" depends="init">

<javac srcdir="${src}" destdir="${dist}" includes="HelloService/**/*.java"/>

</target>

<target name="generate-sei-service" depends="compile-service">

<exec executable="wscompile.bat">

<arg line="-define -d ${build} -nd ${build} -classpath ${dist} ${etc}\config-interface.xml -model ${build}\model.gz"/>

</exec>

<copy todir="${build}">

<fileset dir="${etc}" includes="*.xml"/>

</copy>

</target>

<target name="package-service" depends="generate-sei-service">

<war warfile="${build}\${ant.project.name}-portable.war"

webxml="${build}\web.xml">

<webinf dir="${build}" includes="*.xml,*.gz,*.wsdl" excludes="web.xml"/>

<classes dir="${dist}" includes="**/*.class" defaultexcludes="no"/>

</war>

</target>

<target name="process-war" depends="package-service">

<exec executable="wsdeploy.bat">

<arg line="-o ${ant.project.name}.war ${build}\${ant.project.name}-portable.war"/>

</exec>

</target>

<target name="deploy">

<copy file="${ant.project.name}.war" todir="${server}"/>

</target>

<target name="undeploy">

<delete file="${server}\${ant.project.name}.war"/>

</target>

<!-- Generating Static Client -->

<target name="generate-stubs" depends="init">

<exec executable="wscompile.bat">

<arg line="-gen:client -d ${dist} -classpath ${dist} ${etc}\config-wsdl.xml"/>

</exec>

</target>

<target name="compile-client" depends="generate-stubs">

<javac srcdir="${src}" destdir="${dist}" includes="StaticStub/**/*.java">

<classpath refid="classpath"/>

</javac>

</target>

<target name="package-client" depends="compile-client">

<jar destfile="${lib}\client.jar" basedir="${dist}" excludes="HelloService/**/*.class"/>

</target>

<target name="run-client" depends="package-client">

<java classname="staticstub.HelloClient"

classpathref="classpath"

fork="true">

<sysproperty key="endpoint" value="${endpoint}"/>

<arg value="${server.port.url}"/>

</java>

</target>

<!-- Generating Dynamic Client -->

<target name="generate-interface" depends="init">

<exec executable="wscompile.bat">

<arg line="-import -d ${dist} -classpath ${dist} ${etc}\config-wsdl.xml"/>

</exec>

</target>

<target name="compile-dynamic-client" depends="generate-interface">

<javac srcdir="${src}" destdir="${dist}" includes="DynamicProxy/**/*.java">

<classpath refid="classpath"/>

</javac>

</target>

<target name="package-dynamic-client" depends="compile-dynamic-client">

<jar destfile="${lib}\client.jar" basedir="${dist}" includes="**/HelloIF.class,**/DynamicClient.class"/>

</target>

<target name="run-dynamic-client" depends="package-dynamic-client">

<java classname="dynamicproxy.DynamicClient"

classpathref="classpath"

fork="true">

<sysproperty key="endpoint" value="${endpoint}"/>

<arg value="${server.port.url}"/>

</java>

</target>

<!-- Generating Dynamic Invocation Interface -->

<target name="compile-dii">

<javac srcdir="${src}" destdir="${dist}" includes="DII/**/*.java">

<classpath refid="classpath"/>

</javac>

</target>

<target name="run-dii" depends="compile-dii">

<java classname="dii.DIIClient"

classpathref="classpath"

fork="true">

<sysproperty key="endpoint" value="${endpoint}"/>

<arg value="${server.port.url}"/>

</java>

</target>

</project>

·属性文件(build.xml文件使用)

server=C:/Java/jwsdp-1.2/webapps

tomcat.home=C:/Java/jwsdp-1.2

endpoint=http://localhost:8080/helloWS/hello

server.port.url=http://localhost:8080/helloWS/hello

参考资料

1. Developing Web Service Series <http://www.theserverside.com/resources/article.jsp?l=Systinet-web-services-part-1> www.theserverside.com

2. JWSDP-1.2 Tutorial java.sun.com

声明:如需转帖,请标明出处

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有