基于cxf开发restful风格的Web Service

一、写在前面

  webservice一些简单的其他用法和概念,就不在这里赘述了,相信大家都可以在网上查到,我也是一个新手,写这篇文章的目的一方面是想记录自己成长的历程,另一方面是因为学习这个的时候花了点时间,希望本文章能为大家节约点时间。当然描述的可能不到位,望谅解。

二、创建项目

2.1、创建公用接口project

  为了方便服务端和客户端调用接口可以先创建一个接口java project,单独建一个接口project的用处后面再说。

然后导入对应jar包,可以去cxf官网下载http://cxf.apache.org/download.html把里面的所有包可以都导入

新建一个实体类User

定义实体类

package com.test.entity;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User { 
    private String name;
    private String sex;
    private Integer age;
    
    public User(){
        
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", sex=" + sex + ", age=" + age + "]";
    }
    
    
}

新建对应接口和继承接口

对应代码

package com.test.interfaces;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import com.test.entity.User;

@Path(value="/user")
public interface IuserFacade extends CommonFacade{
         public final static String FACADE_NAME = "testFacade";
         
            @POST
            @Path(value="/getString")
            public String getString() throws Exception;
            
            @POST
            @Path(value="/getUserName")
            public User getUser() throws Exception;
            

    }
package com.test.interfaces;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;

@Consumes(value = { CommonFacade.APPLICATION_JSON_UTF_8, CommonFacade.APPLICATION_XML_UTF_8 })
@Produces(value = { CommonFacade.APPLICATION_JSON_UTF_8, CommonFacade.APPLICATION_XML_UTF_8 })
public interface CommonFacade {
    
    
    public final static String APPLICATION_JSON_UTF_8 = "application/json; charset=UTF-8";
    
    public final static String APPLICATION_XML_UTF_8 = "application/xml; charset=UTF-8";
}

接口定义完成,下面创建web service。

2.2、创建实现接口web service

  这里创建的普通的web project,实现web service主要是看配置文件。

因为这里的需要实现上面建的接口,所以先关联Test-interfacse

 

这样在实现的时候才可以用不然会提示不存在

实现类为

package com.test.interfacesImpl;

import org.springframework.stereotype.Service;

import com.test.entity.User;
import com.test.interfaces.IuserFacade;

@Service(value = IuserFacade.FACADE_NAME)
public class IuserFacadeImpl implements IuserFacade{

    @Override
    public String getString() throws Exception {
        
        return "this is ws test";
    }

    @Override
    public User getUser() throws Exception {
        User user=new User();
        user.setAge(13);
        user.setName("minzhou");
        user.setSex("man");
        return user;

    }

}

配置web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>    
  
       <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:conf/applicationContext*.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
        <!-- CXF Servlet -->
    <servlet>
        <servlet-name>CXFService</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFService</servlet-name>
        <url-pattern>/rs/*</url-pattern>
    </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

创建conf ,在conf里面创建对应xml

对应applicationContext-cxf.xml和applicationContext-default.xml分别为

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    


    <jaxrs:server id="rest-container" address="/">
        
        <jaxrs:serviceBeans>
            <ref bean="testFacade" />

        </jaxrs:serviceBeans>
    </jaxrs:server>

</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop  
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        ">

    <context:annotation-config />
    <aop:aspectj-autoproxy/>
    <context:component-scan base-package="com" />
    
    
</beans>

运行后输入http://localhost:8080/Test-WS/rs/?_wadl得到

这里web service端就完成了,通过把地址发给别人就可以访问了,这里面的接口project就可以同时打包发过去,调用的时候就可以引用接口jar包,和地址,访问了。

当然到这里还存在问题,在客户端调用的时候就会发现问题,有兴趣的可以先把这放着,直接写客户端代码,然后调用,看看是什么问题。为了避免问题我先把代码加上

新加一个类

package com.test.interfacesImpl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;

public class ISSJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
    public ISSJacksonJaxbJsonProvider(ObjectMapper objectMapper){
        super(objectMapper, DEFAULT_ANNOTATIONS);
    }
}

修改applicationContext-cxf.xml 增加<jaxrs:providers></jaxrs:providers>引用新建的类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    


    <jaxrs:server id="rest-container" address="/">
        <jaxrs:providers>
            <bean class="com.test.interfacesImpl.ISSJacksonJaxbJsonProvider">
                <constructor-arg type="com.fasterxml.jackson.databind.ObjectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="serializationInclusion" value="NON_NULL" />
                    </bean>
                </constructor-arg>
            </bean>
        </jaxrs:providers>
        <jaxrs:serviceBeans>
            <ref bean="testFacade" />

        </jaxrs:serviceBeans>
    </jaxrs:server>

</beans>

三、客户端实现web service

  创建一个web project Test-Client同理关联接口,当然也可以不关联接口,直接把接口所导成的jar包导入即可。因为是本地项目所以可以这样,若是给人调用,只需要把web service接口地址和打包的接口jar给人就可以。

创建调用外部webservice控制器

 

testcontroller.java代码

package com.test.conroller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.test.entity.User;
import com.test.interfaces.IuserFacade;

@Controller
@RequestMapping("/test")
public class TestController {
    @Resource(name =  "testfacade")
    private IuserFacade testfacae;
    
    @RequestMapping("/getString")
    public @ResponseBody
    void testGetString()throws Exception {
        String tests=testfacae.getString();
        System.out.println(tests);
    }
    
    @RequestMapping("/getUser")
    public  @ResponseBody
    String testGetUser()throws Exception{
        
        User users=testfacae.getUser();
        System.out.println(users.toString());
        
        System.out.println("my name is:"+users.getName()+" and my age is "+users.getAge());
        return users.toString();
        
    /*    UserQueryResp uq=userFacade.getUserQueryRespById("40289518501706fe01504a91cc2c00d8");*/
        

        
    }
}

这里@Resource(name =  "testfacade")需要在xml中配置

具体applicationContext-cxf.xml代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd   http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/transports/http/configuration   http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/jaxrs   http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context.xsd ">

    <http-conf:conduit name="{WSDL Namespace}portName.http-conduit">
        <http-conf:client ConnectionTimeout="30000"
            ReceiveTimeout="30000" />
    </http-conf:conduit>

    <cxf:bus>
        <cxf:features>
            <cxf:logging />
            <!--<cxf:fastinfoset force="false" /> -->
        </cxf:features>

        <!-- compress the exchange data size -->
        <cxf:inInterceptors>
            <bean class="org.apache.cxf.transport.common.gzip.GZIPInInterceptor" />
        </cxf:inInterceptors>
        <cxf:outInterceptors>
            <bean class="org.apache.cxf.transport.common.gzip.GZIPOutInterceptor" />
        </cxf:outInterceptors>
    </cxf:bus>


    <jaxrs:client id="testfacade" address="${dataserver.rs.address}"
        serviceClass="com.test.interfaces.IuserFacade"
        inheritHeaders="true">

        <jaxrs:headers>
            <entry key="Accept" value="application/json" />
            <entry key="Content-Type" value="application/json;charset=UTF-8" />
            <entry key="Authorization" value="Basic dG9tOjEyMzQ1Njc4" />
        </jaxrs:headers>
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
        </jaxrs:providers>
    </jaxrs:client>

</beans>

其中用到${dataserver.rs.address}这里配置到了DEV_dataserver.properties

dataserver.rs.address=http://127.0.0.1:8080/Test-WS/rs/?_wadl

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>    
  
  <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:conf/applicationContext*.xml</param-value>
    </context-param>
     <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:conf/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/dispatcher/*</url-pattern>
    </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

dispatcher-servlet.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
         http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">


    <context:annotation-config />

    <aop:aspectj-autoproxy proxy-target-class="true" />

    <context:component-scan base-package="com.test" />

    <util:list id="messageConverters">
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
    </util:list>



    <!-- content neotiating view resolver, a delegate over the accept header -->
    <bean id="contentNegotiatingViewResolver"
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="contentNegotiationManager">
            <bean
                class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
                <property name="mediaTypes">
                    <props>
                        <prop key="atom">application/atom+xml;charset=UTF-8</prop>
                        <prop key="xml">application/xml;charset=UTF-8</prop>
                        <prop key="html">text/html;charset=UTF-8</prop>
                        <prop key="json">application/json;charset=UTF-8</prop>
                    </props>
                </property>
            </bean>
        </property>

        <property name="defaultViews">
            <list>
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
                </bean>

            </list>
        </property>

        <property name="viewResolvers">
            <list>
                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
                <bean
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="viewClass"
                        value="org.springframework.web.servlet.view.JstlView" />
                    <property name="prefix" value="/page/" />
                    <property name="suffix" value=".jsp" />
                </bean>
            </list>
        </property>
    </bean>


    <bean
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
    </bean>


</beans>

applicationContext-default.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"  
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop  
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
    
    <context:component-scan base-package="com" />
    <aop:aspectj-autoproxy/>
    <context:property-placeholder location="classpath:conf/DEV_dataserver.properties" ignore-unresolvable="true"/>
   <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html; charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html; charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
</beans>

这样启动项目后可以访问http://localhost:8080/Test-Client/dispatcher/test/getUser得到,这样通过客户端访问服务端就可以得到相应的值,这里面的值比较简单,若是webservice端链接上数据库,就可以取得对应数据,客户端也可以在对应页面上获取值,本文只是写对应过程。当然里面的配置文件可能会有多余的,但是大致思想是这样的。

总结:1、通过创建web service 暴露对应访问地址,可以让开发人员调用而保护数据。

   2、单独创建接口project可以避免在服务端和客户端同时编辑接口,而且给外部访问的时候可以通过导入jar包提供方便

    3、对应代码下载https://files.cnblogs.com/files/minzhousblogs/TestWebServise001.zip 里面没有jar包,可以直接放jar

posted on 2016-05-06 17:43  孤王就是朕  阅读(9034)  评论(2编辑  收藏  举报