【问题标题】:Java CXF restful webservicesJava CXF 宁静的网络服务
【发布时间】:2012-01-08 13:42:44
【问题描述】:

我的网络服务类如下:

package com.siemens.rest;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.BindingType;
import javax.xml.ws.Provider;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.http.HTTPException;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

@WebServiceProvider
@BindingType(value = HTTPBinding.HTTP_BINDING)
public class ConverterService implements Provider<Source> {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Resource
    protected WebServiceContext wsContext;

    private BigDecimal rupeeRate = new BigDecimal("40.58");
    private BigDecimal euroRate = new BigDecimal("0.018368");

    public Source invoke(Source source) {
        try {
            String amount = null;

            if (source == null) {
                System.out.println("Getting input from query string");
                MessageContext mc = wsContext.getMessageContext();
                String query = (String) mc.get(MessageContext.QUERY_STRING);
                System.out.println("Query String = " + query);
                ServletRequest req = (ServletRequest) mc
                        .get(MessageContext.SERVLET_REQUEST);
                amount = req.getParameter("amount");
            } else {
                System.out.println("Getting input from input message");
                Node n = null;
                if (source instanceof DOMSource) {
                    n = ((DOMSource) source).getNode();
                } else if (source instanceof StreamSource) {
                    StreamSource streamSource = (StreamSource) source;
                    DocumentBuilderFactory dbf = DocumentBuilderFactory
                            .newInstance();
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    InputSource inputSource = null;
                    if (streamSource.getInputStream() != null) {
                        inputSource = new InputSource(
                                streamSource.getInputStream());
                    } else if (streamSource.getReader() != null) {
                        inputSource = new InputSource(streamSource.getReader());
                    }
                    n = db.parse(inputSource);
                } else {
                    throw new RuntimeException("Unsupported source: " + source);
                }
                NodeList children = n.getChildNodes();
                for (int i = 0; i < children.getLength(); i++) {
                    Node child = children.item(i);
                    if (child.getNodeName().equals("dollars")) {
                        amount = child.getAttributes().getNamedItem("amount")
                                .getNodeValue();
                        break;
                    }
                }
            }
            BigDecimal dollars = new BigDecimal(amount);
            BigDecimal rupees = dollarToRupees(dollars);
            BigDecimal euros = rupeesToEuro(rupees);
            return createResultSource(rupees, euros);
        } catch (Exception e) {
            e.printStackTrace();
            throw new HTTPException(500);
        }
    }

    public BigDecimal dollarToRupees(BigDecimal dollars) {
        BigDecimal result = dollars.multiply(rupeeRate);
        return result.setScale(2, BigDecimal.ROUND_UP);
    }

    public BigDecimal rupeesToEuro(BigDecimal rupees) {
        BigDecimal result = rupees.multiply(euroRate);
        return result.setScale(2, BigDecimal.ROUND_UP);
    }

    private Source createResultSource(BigDecimal rupees, BigDecimal euros) {
        String body = "<ns:return xmlns:ns=\"http://rest.jaxws.samples.geronimo.apache.org\">"
                + "<ns:dollarToRupeesResponse>"
                + rupees
                + "</ns:dollarToRupeesResponse><ns:rupeesToEurosResponse>"
                + euros + "</ns:rupeesToEurosResponse></ns:return>";
        Source source = new StreamSource(new ByteArrayInputStream(
                body.getBytes()));
        return source;
    }
}

和web.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <display-name>jaxws-rest-converter</display-name>
  <servlet>
    <servlet-name>ConverterService</servlet-name>
    <servlet-class> com.siemens.rest.ConverterService </servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ConverterService</servlet-name>
    <url-pattern>/converter</url-pattern>
  </servlet-mapping>
</web-app>

在 tomcat 6.0 中部署时,出现以下异常:

严重:Servlet /jaxws-rest-converter 抛出 load() 异常 java.lang.ClassCastException:com.siemens.rest.ConverterService 不能 被强制转换为 javax.servlet.Servlet 在 org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1116) 在 org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993) 在 org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420) 在 org.apache.catalina.core.StandardContext.start(StandardContext.java:4733) 在 org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) 在 org.apache.catalina.core.StandardHost.start(StandardHost.java:840) 在 org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) 在 org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463) 在 org.apache.catalina.core.StandardService.start(StandardService.java:525) 在 org.apache.catalina.core.StandardServer.start(StandardServer.java:754) 在 org.apache.catalina.startup.Catalina.start(Catalina.java:595) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 java.lang.reflect.Method.invoke(未知来源)在 org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) 在 org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

我认为web.xml 是错误的,任何人都可以帮助我。我正在尝试在CXF 中实现宁静的网络服务。

【问题讨论】:

  • 你用maven吗?你如何引入依赖关系?

标签: java web-services rest cxf


【解决方案1】:

我认为您的实施中有几处错误。

首先,您的web.xml 确实是错误的。该文件旨在声明 servlet、过滤器等,但绝不是 web 服务提供者。你得到ClassCastException 是因为你告诉你ConverterService 是一个servlet。

所以,你需要做的是在你的 web.xml 中声明 Apache CXF servlet 让他回答一些请求。检查这个例子:

   <!-- 
       Web service Front Controller. It will receive all the web service request and then it 
       delegates the request to the web services configured in the CXF config file
    -->
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 
       Every request that start with this will be handled by the CXF servlet 
    -->
    <servlet-mapping>
      <servlet-name>CXFServlet</servlet-name>
      <url-pattern>/ctx/authbasic/ws/*</url-pattern>
    </servlet-mapping>

在此之后,您需要正确声明您的每一项网络服务。我使用 Spring 来配置我的 Apache CXF 服务,所以在这里你可以查看一个示例。

    <jaxws:endpoint id="dataService"
        implementor="some.package.DataSIB"
        address="/DataService" wsdlLocation="classpath:wsdls/DataService.wsdl">
        <jaxws:properties>
            <!-- jaxws properties binding config -->
        </jaxws:properties>
        <jaxws:dataBinding>
          <!-- data binding config -->
        </jaxws:dataBinding>
    </jaxws:endpoint>

使用此配置,您对/ctx/authbasic/ws/DataService 的任何请求都将由 Web 服务实现处理。这里是 Web 服务声明 (SEI) 及其实现 (SIB) 的示例:

@WebService(name = "dataService", targetNamespace = "http://some-domain/dataservice/definition")
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL, parameterStyle = ParameterStyle.WRAPPED)
public interface DataSEI {
    // You methods here
}

@WebService(endpointInterface = "some.package.DataSEI",
serviceName = "dataServiceService",
portName = "dataServicePort",
targetNamespace = "http://some-domain/dataservice/definition")
public class DataSIB implements DataSEI {
   // Your methods here
}

注意:这是一个 SOAP Web 服务的示例,但这可能有助于您理解框架

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    相关资源
    最近更新 更多