FROM: http://blog.csdn.net/yuvmen/archive/2009/11/09/4790805.aspx
Mainly refer to the http://cxf.apache.org related content:
1. The basic method for creating a service using CXF (UseCXFBuilt-in jettyContainer)
Reference: http://cxf.apache.org/docs/a-simple-jax-ws-service.html
In four steps:
① Set the build Environment
② Write Service
③ Publish a service
④ Access Service
1) set the build Environment
Create a new project and add the following files in the lib directory of apache-cxf-2.2.4.zip to Build Path:
Commons-logging-1.1.1.jar
Geronimo-activation_1.1_spec-1.0.2.jar (or Sun's Activation jar)
Geronimo-annotation_1.0_spec-1.1.1.jar (jsr250)
Geronimo-javamail_1.4_spec-1.6.jar (or Sun's JavaMail jar)
Geronimo-servlet_2.5_spec-1.2.jar (or Sun's Servlet jar)
Geronimo-ws-metadata_2.0_spec-1.1.2.jar (jsr181)
Geronimo-jaxws_2.1_spec-1.0.jar (or Sun's jaxws-api-2.1.jar)
Geronimo-stax-api_1.0_spec-1.0.1.jar (or other stax-api jar)
Jaxb-api-2.1.jar
Jaxb-impl-2.1.12.jar
Jetty-6.1.21.jar
Jetty-util-6.1.21.jar
Neethi-2.0.4.jar
Saaj-api-1.3.jar
Saaj-impl-1.3.2.jar
Wsdl4j-1.6.2.jar
Wstx-asl-3.2.8.jar
XmlSchema-1.4.5.jar
Xml-resolver-1.2.jar
Cxf-2.2.4.jar
Optional. Add Spring jars to add Spring support for XML Configuration. The added jars are as follows:
Aopalliance-1.0.jar
Spring-core-2.5.5.jar
Spring-beans-2.5.5.jar
Spring-context-2.5.5.jar
Spring-web-2.5.5.jar
2) Write Service
A) Write Interface
@ WebService
Public interface HelloWorld {
String sayHi (String text );
// JAX-WS/JAXB cannot directly support advanced use cases to handle the special XmlAdapter they need to write
String sayHiToUser (User user );
/* Map Transmission
* JAXB does not support Maps. It can handle Lists well, but Maps cannot support them directly.
* They also need to use an XmlAdapter to map maps to beans that can be used by JAXB.
*/
@ XmlJavaTypeAdapter (IntegerUserMapAdapter. class)
Map <Integer, User> getUsers ();
}
Note:: Wsdl will rename the parameter name. If you do not want this, you should write it as follows:
@ WebService
Public interface HelloWorld {
String sayHi (@ WebParam(Name = "text") String text );
}
B) Write implementation:
Package demo. hw. server;
Import java. util. LinkedHashMap;
Import java. util. Map;
Import javax. jws. WebService;
@ WebService (endpointInterface = "demo. hw. server. HelloWorld ",
ServiceName = "HelloWorld") // tells CXF which interface is used to create the WSDL
Public class HelloWorldImpl implements HelloWorld {
Map <Integer, User> users = new LinkedHashMap <Integer, User> ();
Public String sayHi (String text ){
System. out. println ("sayHi called ");
Return "Hello" + text;
}
Public String sayHiToUser (User user ){
System. out. println ("sayHiToUser called ");
Users. put (users. size () + 1, user );
Return "Hello" + user. getName ();
}
Public Map <Integer, User> getUsers (){
System. out. println ("getUsers called ");
Return users;
}
}
3) Release Service (CXF comes with Jetty server, so it can be released without Tomcat)
A) use the jws high-level encapsulation:
System. out. println ("Starting Server ");
HelloWorldImpl implementor = new HelloWorldImpl ();
String address = "http: // localhost: 9000/helloWorld ";
Endpoint. publish (address, implementor );
B) use the following code to precisely control service behavior:
HelloWorldImpl implementor = new HelloWorldImpl ();
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean ();
SvrFactory. setServiceClass (HelloWorld. class); // save, but it is not recommended because it may cause minor problems.
SvrFactory. setAddress ("http: // localhost: 9000/helloWorld ");
SvrFactory. setServiceBean (implementor );
SvrFactory. getInInterceptors (). add (new LoggingInInterceptor ());
SvrFactory. getOutInterceptors (). add (new LoggingOutInterceptor ());
SvrFactory. create ();
Since then, you can use http: // localhost: 9000/helloWorld? To display the wsdl of the service.
LoggingInInterceptor and LoggingOutInterceptor are log interceptors used to display logs during input and output.
4) Access Services
A) use the jws high-level encapsulation:
// The first parameter is the unfix of class package name implemented by the interface
Private static final QName SERVICE_NAME = new QName ("http://server.hw.demo/", "HelloWorld ");
Private static final QName PORT_NAME = new QName ("http://server.hw.demo/", "HelloWorldPort ");
......
Service service = Service. create (SERVICE_NAME );
// Endpoint Address
String endpointAddress = "http: // localhost: 9000/helloWorld ";
// Add a port to the Service
Service. addPort (PORT_NAME, SOAPBinding. SOAP11HTTP_BINDING, endpointAddress );
HelloWorld hw = service. getPort (HelloWorld. class );
System. out. println (hw. sayHi ("World "));
B) or use the following code to control the service more accurately:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean ();
Factory. getInInterceptors (). add (new LoggingInInterceptor ());
Factory. getOutInterceptors (). add (new LoggingOutInterceptor ());
Factory. setServiceClass (HelloWorld. class );
Factory. setAddress ("http: // localhost: 9000/helloWorld ");
HelloWorld client = (HelloWorld) factory. create ();
String reply = client. sayHi ("HI ");
System. out. println ("Server said:" + reply );
System. exit (0 );
2. wsdl2java: generate a java class from the wsdl document for the client to use
Set the environment variable CXF_HOME = D: \ Program Files \ apache-cxf-2.2.4, add "; % CXF_HOME % \ bin" after PATH (optional), and then run the wsdl2java batch processing Program, which is used as follows:
Wsdl2java-p package name-d directory name wsdl path
For example, wsdl2java-p demo. service. client-d e: \ src htt: // localhost: 8080/helloWorld? Wsdl
-P specifies the namespace of the wsdl, that is, the package name of the Code to be generated.
-D specifies the directory where the code to be generated is located
-The client generates the code for the client to test the web service.
-The server generates the code for the server to start the web service.
-Impl: generate the web service implementation code
-Ant generate the build. xml file
-All: generate all the starting endpoint code: types, service proxy, service interface, server mainline, client mainline, implementation object, and an Ant build. xml file.
See http://cwiki.apache.org/CXF20DOC/wsdl-to-java.html for detailed usage
3. Define complex types (basic types such as int, String, no need to define additional), references: http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.html
For example:
Package com. example. customerservice;
@ XmlAccessorType (XmlAccessType. FIELD)
Public class Customer {// custom class
String name;
String \ [\] address;
Int numOrders;
Double revenue;
BigDecimal test;
Date birthDate;
CustomerTypeType; // custom Enumeration type
}
Public enumCustomerType{
PRIVATE, BUSINESS
}
// Define Exception
@ WebFault (name = "NoSuchCustomer ")
@ XmlAccessorType (XmlAccessType. FIELD)
Public class NoSuchCustomerException extends RuntimeException {
/**
* We only define the fault details here. Additionally each fault has a message
* That shoshould not be defined separately
*/
String customerName;
} // The default action for defining Exceptions is to create Exception_Exception when the Java code is generated later. Therefore, you must use the @ WebFault mark to get a name for the Bean, which is different from the Exception name.
@ WebService // mark this interface as a service
Public interface CustomerService {
Public Customer [] getCustomersByName (@ WebParam (name = "name") String name) throws NoSuchCustomerException; // @ WebParam marks the parameter name in the wsdl. If omitted, wsdl will be replaced by arg0
}
// @ WebService can also be used to customize the Interface Name and service name, which correspond to endpointInterface and serviceName, for example:
@ WebService (endpointInterface = "com. example. customerservice", serviceName = "HelloWorld ")
Generated WSDL:
<Xs: complexTypeCOLOR: green "> customer"> // complex type
<Xs: sequence>
<Xs: element minOccurs = "0" COLOR: green "> name" type = "xs: string"/>
<Xs: element maxOccurs = "unbounded" minOccurs = "0" COLOR: green "> address" nillable = "true" COLOR: green "> xs: string"/>
<Xs: elementCOLOR: green "> numOrders" COLOR: green "> xs: int"/>
<Xs: elementCOLOR: green "> revenue" COLOR: green "> xs: double"/>
<Xs: element minOccurs = "0" COLOR: green "> test" COLOR: green "> xs: decimal"/>
<Xs: element minOccurs = "0" COLOR: green "> birthDate" COLOR: green "> xs: dateTime"/>
<Xs: element minOccurs = "0" COLOR: green "> type" COLOR: green "> tns: customerType"/>
</Xs: sequence>
</Xs: complexType>
MinOccurs = "0" is optional, so that new elements can be added at any time to maintain compatibility. If you do not want this option, you can mark @ XmlElement (required = true)
MaxOccurs = "unbounded" is used to facilitate the subsequent xml to repeat this element to form an array.
<Xs: simpleTypeCOLOR: green "> customerType"> // Enumeration type
<Xs: restriction base = "xs: string">
<Xs: enumeration value = "PRIVATE"/>
<Xs: enumeration value = "BUSINESS"/>
</Xs: restriction>
</Xs: simpleType>
<Xs: elementCOLOR: green "> NoSuchCustomer" COLOR: green "> tns: NoSuchCustomer"/> // exception class
<Xs: complexTypeCOLOR: green "> NoSuchCustomer">
<Xs: sequence>
<Xs: elementCOLOR: green "> customerName" nillable = "true" COLOR: green "> xs: string"/>
</Xs: sequence>
</Xs: complexType>
<Wsdl: messageCOLOR: green "> NoSuchCustomerException">
<Wsdl: partCOLOR: green "> NoSuchCustomerException" element = "tns: NoSuchCustomer">
</Wsdl: part>
</Wsdl: message>
//Note:: The names of Element and Message are different. This is achieved by marking @ Webfault. They can also have the same name, but in that case, the generated Exception name will be ugly: NoSuchCustomerException_Exception