Spring boot publishes Web Service Services
SpringBoot publishing Webservice is actually exposing JAVA Class classes as Webservice services through Webservice annotations.
Dependencies required for publishing services
// Dependencies required for web service publishing <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.5</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.1.5</version> </dependency>
Only these two dependencies are needed to publish web service. JDK uses 1.8. After dependency is introduced, start looking at the code!
Write service classes to be exposed
Before writing the code, you need to know about the use of web service related annotations [understand by yourself]. There is no explanation here. Go directly to the code!
import org.apache.cxf.annotations.WSDLDocumentation; import org.apache.cxf.annotations.WSDLDocumentationCollection; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.xml.ws.Endpoint; /** * @Author: zp * @Description: TODO * @Date: 2021/6/24 14:17 * @Version: 1.0 */ @WebService(serviceName="EWebService",targetNamespace="http://com.zpg.fun") @SOAPBinding(style = SOAPBinding.Style.RPC) //wsdl xml document description @WSDLDocumentation(value = "This service is SpringBoot take JAVA Class Annotated as WebService service,Services can be consumed according to JSON and XML Different data formats for different service choices. This service is only used as an example of a service, and there is no specific implementation of the service.", placement = WSDLDocumentation.Placement.TOP) public class EWebService { @WebMethod(operationName="RequestDataByJson") @WebResult(name="jsonReturn") @WSDLDocumentationCollection( { @WSDLDocumentation("RequestDataByJson receive json Format input for service consumption"), @WSDLDocumentation(value = "Participants must follow json Data format for service consumption", placement = WSDLDocumentation.Placement.INPUT_MESSAGE), @WSDLDocumentation(value = "RequestDataByJson Service response content", placement = WSDLDocumentation.Placement.OUTPUT_MESSAGE) } ) public Object RequestDataByJson(@WebParam(name="jsonReqParam")String jsonReqParam){ System.out.println("===========RequestDataByJson============="); return RequestOther(jsonReqParam); } @WebMethod(operationName="RequestDataByXml") @WebResult(name="xmlReturn") @WSDLDocumentationCollection( { @WSDLDocumentation("RequestDataByXml receive xml Format input for service consumption"), @WSDLDocumentation(value = "Participants must follow xml Data format for service consumption", placement = WSDLDocumentation.Placement.INPUT_MESSAGE), @WSDLDocumentation(value = "RequestDataByXml Service response content", placement = WSDLDocumentation.Placement.OUTPUT_MESSAGE) } ) public Object RequestDataByXml(@WebParam(name="xmlReqParam")String xmlReqParam){ System.out.println("===========RequestDataByXml============="); return RequestOther(xmlReqParam); } @WebMethod(exclude=true)//The current method is not published public Object RequestOther(String object){ // Perform other service logic processing // SayHello sayHello = new SayHello(); // sayHello.say("service call succeeded"); return "RequestOther Service response succeeded! Input parameters are:"+object; } public static void main(String[] args) { String url = "http://youIP:youPort/ESBWebservice"; Endpoint publish = Endpoint.publish(url,new EWebService()); if(publish.isPublished()) { System.out.println("=============server is running=============="); }else { System.out.println("=============server is error================"); } } }
The Webservice service class is ready. Run the main method in this class directly to publish the Webservice service.
Publishing services
Run the main method in this class and pay attention to modifying your own ip and port. The effect after operation is shown in the figure:
Access in browser http://youIP:youPort/ESBWebservice?wsdl Check whether the service is published successfully! As shown in the figure:
Seeing such an interface means that the service is published successfully! Here is how to call the service.
General invocation of Webservice service
The general calling method is as follows:
import org.apache.cxf.endpoint.Client; import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory; public static void main(String[] args) { try { String url ="http://youIP:youPort/ESBWebservice?wsdl"; //Generate client instance JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient(url); //Service parameters String paramString = "Parameter content"; //Automatic proxy initiation request Object[] obj = client.invoke("RequestDataByJson",paramString); System.out.println("The return value of the call is:"+obj[0]); } catch (Exception e) { e.printStackTrace(); } } }
The call result is shown in the figure below:
The service responded successfully. However, this kind of calling method may cause some Webservice services to call normally on the SOAPUI, but various exceptions occur when using this method to access, resulting in the problem that the service call is impossible.
Frequently asked questions about Webservice service invocation
1,No operation was found with the name
2. Unmarshalling Error: unexpected element (uri: "return: HL7 org: V3", local: "return"). The required element is < {urn: HL7 org: V3} hipmessageserverresult >
3. The return value is an object and must be parsed
It is recommended to use the calling method of web service
This method combines the calling method in hutool with the wsdl parsing provided by jdk to encapsulate the calling method.
Call required dependencies
// Dependencies required for custom calls <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency>
Call tool class
import cn.hutool.http.webservice.SoapClient; import com.ibm.wsdl.PortImpl; import com.ibm.wsdl.extensions.soap.SOAPAddressImpl; import com.ibm.wsdl.extensions.soap12.SOAP12AddressImpl; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import javax.wsdl.Definition; import javax.wsdl.Service; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.factory.WSDLFactory; import javax.wsdl.xml.WSDLReader; import javax.xml.namespace.QName; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPMessage; import java.io.ByteArrayInputStream; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @Author: zp * @Description: webservice Service request tool * @Date: 2021/8/24 10:57 * @Version: 1.0 */ public class WebserviceUtils { public static void main(String[] args) { // Map<String,Object> params = new HashMap<>(); // params.put("theIpAddress","218.21.240.106"); // String url = "http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx?wsdl"; // String methodName = "getCountryCityByIp"; // System.out.println("the service response value is:" + requestwsdl (URL, methodname, parameters)); Map<String,Object> params = new HashMap<>(); params.put("jsonReqParam","Service parameters"); String url = "http://youIP:youPort/ESBWebservice?wsdl"; String methodName = "RequestDataByJson"; System.out.println("The service response value is:"+requestWsdl(url,methodName,params)); } /** * wsdl analysis * @param url wsdl address * @param methodName Requested method name * @param parameter Parameter value * @return */ public static String requestWsdl(String url, String methodName, Map<String, Object> parameter) { try { WSDLFactory factory = WSDLFactory.newInstance(); WSDLReader reader = factory.newWSDLReader(); reader.setFeature("javax.wsdl.verbose", true); reader.setFeature("javax.wsdl.importDocuments", true); //Resolve wsdl address Definition def = reader.readWSDL(url); // Namespace to which the element belongs String namespaceURI = def.getTargetNamespace(); String wsdlService = null; String soapVersion = SOAPConstants.SOAP_1_1_PROTOCOL; //Get the service and the binding name where the service is located according to the wsdl address and namespace Map<QName, Object> map1 = def.getServices(); for (Map.Entry<QName, Object> vo : map1.entrySet()) { wsdlService = vo.getKey().getLocalPart(); } QName sname = new QName(namespaceURI, wsdlService); //Get the service information in the specified space Service service = def.getService(sname); Map<String, Object> ports = service.getPorts(); Iterator<?> itor = ports.entrySet().iterator(); while (itor.hasNext()) { Map.Entry<String, Object> map = (Map.Entry<String, Object>) itor.next(); //If the wsdl address of the service is not consistent with the binding address of the service method name, you need to obtain the address where the service name is located PortImpl valueMap = (PortImpl) map.getValue(); @SuppressWarnings("rawtypes") List extensList = valueMap.getExtensibilityElements(); if (extensList != null) { for (int i = 0; i < extensList.size(); i++) { //Get the binding address of the service ExtensibilityElement extElement = (ExtensibilityElement) extensList.get(i); //After obtaining the locationURI, directly access the changed address for service consumption, and no longer use the wsdl address if (extElement instanceof SOAPAddressImpl) { SOAPAddressImpl soapAddress = (SOAPAddressImpl) extElement; url = soapAddress.getLocationURI(); soapVersion = SOAPConstants.SOAP_1_1_PROTOCOL; } if (extElement instanceof SOAP12AddressImpl) { SOAP12AddressImpl soapAddress = (SOAP12AddressImpl) extElement; url = soapAddress.getLocationURI(); soapVersion = SOAPConstants.SOAP_1_2_PROTOCOL; } } } //Avoid that some service providers provide a service in multiple ways and report errors. After obtaining it here, it will not be obtained again [e.g. weather query soap1.1 soap1.2 httpPost httpGet are provided] break; } return sendMessage(url, namespaceURI, methodName, parameter, soapVersion).trim(); } catch (Exception e) { return "Network error, please contact the administrator"+e.getMessage(); } } /** * <p>Title: sendMessage</p> * <p>Description:Send a soap request to get the return value of the original service</p> * @param wsdlUrl The service address or the binding address where the service is located * @param namespaceURI Namespace * @param methodName service name * @param params Parameter map * @param soapVersion soap edition * @return * @throws Exception */ private static String sendMessage(String wsdlUrl, String namespaceURI,String methodName,Map<String, Object> params, String soapVersion) { String returnStr=""; try { SoapClient client = SoapClient.create(wsdlUrl) // Set the method to be requested. The method prefix of this interface is web. Pass in the corresponding namespace .setMethod(methodName,namespaceURI) // Set parameters, where the prefix of the method is automatically added: .setParams(params); returnStr = client.send(true); if(StringUtils.isNotBlank(returnStr)) { // Different service definitions have different return information nodes and different namespaces, which makes it impossible to locate the value location -- "and convert it to the soap message body for value taking SOAPMessage soap = formatSoapString(returnStr,soapVersion); if(null!=soap) { try { Document doc = soap.getSOAPPart().getEnvelope().getBody().extractContentAsDocument(); //Return information node in soapBody Node node = doc.getFirstChild(); if(node != null) { returnStr = node.getTextContent().trim(); }else { returnStr="Failed to get the return value"; } } catch (Exception e) { returnStr="Failed to get the return value"; } } }else { returnStr = "Failed to get value"; } } catch (Exception e1) { e1.printStackTrace(); returnStr = "Service call failed!"+e1.getMessage(); } return returnStr; } /** * <p>Title: formatSoapString</p> * <p>Description: Convert the string to the soapMessage body according to the message body string returned by soap and the soap version</p> * @param soapString * @param soapVersion * @return */ public static SOAPMessage formatSoapString(String soapString,String soapVersion) { MessageFactory msgFactory = null; try { if("SOAP 1.1 Protocol".equals(soapVersion)) { msgFactory = MessageFactory.newInstance(); } if("SOAP 1.2 Protocol".equals(soapVersion)) { msgFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); } SOAPMessage reqMsg = msgFactory.createMessage(new MimeHeaders(), new ByteArrayInputStream(soapString.getBytes(Charset.forName("UTF-8")))); reqMsg.saveChanges(); return reqMsg; } catch (Exception e) { return null; } } }
After verification, calling in this way can perfectly avoid these problems mentioned above!