分享

REST方式的CXF WebService实现

 沙门空海 2018-02-23

1. REST方式的WebService概述

1.1 REST架构风格

REST是 Roy Fielding 博士在 2000 年提出的。 
REST(Representational State Transfer-表现层状态转化)是一种新的软件架构风格,它以资源(resource)为核心,使用 HTTP、 URI、XML 以及 HTML 等流行协议和标准来完成对资源的操作及显示。 这些操作包括获取、创建、修改和删除资源(CRUD),分别对应于 HTTP 协议的 GET、POST、PUT 和 DELETE 方法。

RESTful架构可以总结为以下三个内容: 
(1)每一个URI代表一种资源; 
(2)客户端和服务器之间,传递这种资源的某种表现层; 
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。

  • GET用来获取资源,
  • POST用来新建资源(也可以用于更新资源),
  • PUT用来更新资源,
  • DELETE用来删除资源。

1.2. REST风格服务

REST (风格的)服务(RESTful Service)是一种基于 HTTP 和 REST 准则的轻量级 Web 服务。

这类服务可以看作一系列资源(resource)的集合,服务的定义可以视为以下三个切面的组合 : 
- 访问 Web Service 的 URI,如:http:///resources。 
- Web Service 所支持的数据 MIME 类型,如:JSON, XML, YAML 等。 
- Web Service 使用 HTTP 协议支持的操作,如 GET, POST, PUT, DELETE。

1.3.优点

REST风格的服务的性能,效率和易用性等方面均优于 SOAP 协议: 
- 相比SOAP 和 XML-RPC, REST 服务更加简洁, 
- 它可以完全通过 HTTP 协议实现, 
- 支持多种消息格式,比如XML 、JSON 
- 还可以利用缓存 Cache 来提高响应速度(第一次访问资源 缓存,第二次访问资源,返回304客户端调用本地)。

1.4.JAX-RS

JAX-RS (JSR 311)是Java世界中的另一套Web Service规范,用于开发RESTful Web Service。它属于Java EE 6规范中的子规范,逐步取代了JAX-WS(大WebService的规范)的地位。 
基于JAX-RS规范实现的RESTful API可达到:支持资源抽象、统一接口的 “CRUD式Web服务”。

2.CXF服务端开发

CXF框架支持JAX-WS,也支持JAX-RS规范,都是远程调用。

2.1 新建maven项目,引入依赖

pom.xml

    <properties>
        <cxf.version>3.1.9</cxf.version>
        <slf4j.version>1.7.21</slf4j.version>
    </properties>

    <!-- 依赖管理 -->
    <dependencies>
        <!-- CXF RS -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- 内置jetty Web服务器 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>

        <!-- slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <!-- CXF的rs客户端 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>${cxf.version}</version>
        </dependency>

        <!-- CXF扩展提供者:提供了转换json的接口 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-extension-providers</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- CXF扩展提供者转换json需要默认的一个工具包 -->
        <dependency>
            <groupId>org.codehaus.jettison</groupId>
            <artifactId>jettison</artifactId>
            <version>1.3.8</version>
        </dependency>
    </dependencies>
    <!-- 构建 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <!-- 编译的jdk版本 -->
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

2.2 资源-实体类编写

@XmlRootElement 指定序列化(转换XML、JSON) 对象名字。

        //指定序列化(转换XML、JSON) 对象名字 
        //实体类:资源对应的类
        //@XmlRootElement//默认情况下,该对象在传输表现的时候,表现方式xml,要转成xml,根元素:<user类名></user> name:默认类名小写
        @XmlRootElement(name="users")//根元素:<users></users>
        //比如查询列表:<users><user><id>123</id>....</user></users>
        //如果是json:{users:[{"id":"2342",...},{...}}
        public class User {

            private Integer id;
            private String username;
            private String password;
            private Integer age;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.3 SEI业务

第一种 @Path 服务访问资源路径 
如果访问saveUser方法 /userService/user 
第二种 @Produces 生成(方法返回值) @Consumes 消费 (方法参数) 
@Consumes 指定能够处理客户端传递过来数据格式 
@Produces 指定能否生成哪种格式数据返回给客户端 
第三种 @GET 查询 @PUT 修改 @POST 增加 @DELETE 删除 
第四种: 
@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数

//SEI的接口:对外暴露
        //加上注解path,类似于具体的服务的名字"/mobile"
        @Path("/userService")//暴露出去访问资源的服务路径:http://127.0.0.1:8888//userService/users/
        public interface UserService {

            //定义CRUD方法
            /**
             * 说明:保存用户
             * @param user
             */
            @Path("/users")//访问的资源
            @POST//新建资源动作
            //配置表现:setContenttype(....)
            //消费:接收客户端传过来的消息的格式
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            //没有产品
            public void saveUser(User user);
            /**
             * 
             * 说明:修改用户
             * @param user
             */
            @Path("/users")
            @PUT//更新操作
            //可接收客户端传递过来的格式
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public void updateUser(User user);

            /**
             * 
             * 说明:直接根据id删除
             * @param id
             */
            @Path("/users/{id}")
            @DELETE//删除,uri:/users/1
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})//消费
            public void deleteUser(@PathParam("id")Integer id);

            /**
             * 
             * 说明:查询所有数据列表
             * @return
             */
            @Path("/users")
            @GET
            //产品(生产):返回给客户端的格式
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public List<User> findUserList();

            /**
             * 
             * 说明:根据id来查询用户
             * @param id
             * @return
             */
            @Path("/users/{id}")
            @GET
            //消费者
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            //生产者:
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            //127.0.0.1:8888/cxf_jaxrs/userService/users/1
            //资源后面都是参数,参数,类似于命名占位符
            public User findUserById(@PathParam("id")Integer id);


            /**
             * 
             * 说明:使用参数传参:/users?id=1
             * @param id
             * @return
             */
            @Path("/usersparam")
            @GET
            //消费者
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            //生产者:
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public User findUserById2(@QueryParam("id")Integer id);
        }

        /**
         * SEI实现
         */
        public class UserServiceImpl implements UserService {

            @Override
            public void save(User user) {
                //调用dao
                System.out.println("----保存:"+user);
            }

            @Override
            public void update(User user) {
                //调用dao
                System.out.println("-----更新对象:"+user);
            }

            @Override
            public void delete(Integer id) {
                //调用dao
                System.out.println("-----删除的id:"+id);
            }

            @Override
            public List<User> findUserList() {
                List<User> userList =  new ArrayList<>();
                userList.add(new User(1,"jack","123",19));
                userList.add(new User(2,"rose","1234",18));
                return userList;
            }

            @Override
            public User findUserById(Integer id) {
                System.out.println("----根据id查询,id是:"+id);
                return new User(1,"jack","123",19);
            }

            @Override
            public User findUserById2(Integer id) {
                System.out.println("----根据id参数查询,id是:"+id);
                return new User(2,"rose","1234",18);
            }

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125

2.4 发布服务

        public class CxfJaxRsServer {

            public static void main(String[] args) {
                // 发布rest服务
                //1.构建服务工厂对象
                JAXRSServerFactoryBean jaxrsServiceFactoryBean = new JAXRSServerFactoryBean();
                //2.在工厂上设置几个属性
                //2.1服务地址
                jaxrsServiceFactoryBean.setAddress("http://localhost:8888/cxf_jaxrs");
                //2.2资源的类型
                jaxrsServiceFactoryBean.setResourceClasses(User.class);
                //2.3服务对象.自动反射接口
                jaxrsServiceFactoryBean.setServiceBean(new UserServiceImpl());

                //c创建并发布服务
                jaxrsServiceFactoryBean.create();
                System.out.println("rest服务发布了!");

                //资源访问的方式:web地址+服务地址+资源名字

            }

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2.5 测试

浏览器测试(只能是get方法测试) 
查询所有:http://localhost:8888/cxf_jaxrs/userService/users 
根据id查询(路径方式):http://localhost:8888/cxf_jaxrs/userService/users/1 
根据id查询(参数方式):http://localhost:8888/cxf_jaxrs/userService/users?id=1

3. CXF客户端开发

客户端编程有两种做法: 
1)HttpClient工具需要自己对HTTP协议内容进行定制和解析。 
2)WebClient工具类(CXF自带)(使用)。

3.1 客户端调用类

主要的方法说明: 
- create:调用服务资源路径,并建立连接 
- type:客户端发送给服务器的数据(资源)格式,对应服务端的@consumes的数据类型 
- accept:客户端接收服务器的数据(资源)格式,对应服务端的@Produces的数据类型 
- get,post,put,delete四个方法,分别是要采用HTTP协议的那种方式访问服务器。

        public class CxfRsClient {

            public static void main(String[] args) {
                //----方法说明
                //create:调用服务资源路径,并建立连接
                //type:客户端发送给服务器的数据(资源)格式,对应服务端的@consumes的数据类型
                //accept:客户端接收服务器的数据(资源)格式,对应服务端的@Produces的数据类型
                //get,post,put,delete四个方法,分别是要采用HTTP协议的那种方式访问服务器。

                // 目标:调用服务端:crud
                //WebClient:客户端工具类
                //保存
                //new对象
        //      User user = new User();
        //      user.setId(101);
        //      user.setUsername("xiaohong");
        //      user.setPassword("666");
        //      user.setAge(28);
        //      //访问的资源http://127.0.0.1:8888/cxf_jaxrs/userService/users
        //      //参数:访问的服务器上的资源
        //      WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users")
        //      //消费者(对于服务端)
        //      .type(MediaType.APPLICATION_JSON)//设置表现形式,内容类型,怎么传数据,服务器可接收什么
        //      .post(user)//自动将对象转换成xml或json
        //      ;

                //更新
        //      User user2 = new User();
        //      user2.setId(102);
        //      user2.setUsername("xiaohong2");
        //      user2.setPassword("6662");
        //      user2.setAge(28);
                //资源uri
        //      WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users")
        //      .type(MediaType.APPLICATION_JSON)
        //      .put(user2);

                //删除
                //资源uri
        //      WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users/1")
        ////        .path("/"+id);//类似于Stringbuffer的.append("xxxx")
        //      .type(MediaType.APPLICATION_JSON)
        //      .delete();

                //查询所有列表
                //资源uri
        //      Collection<? extends User> userList = WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users")
        //      //生产者(针对服务器来说,客户端能接收)
        //      .accept(MediaType.APPLICATION_JSON)
        ////        .get().getEntity()//获取内容
        //      .getCollection(User.class);//列表对象
        //      System.out.println(userList);

                //根据id查询一个对象
                //资源uri
        //      User user = WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users/1")
        //      //消费者
        //      .type(MediaType.APPLICATION_JSON)
        //      //生产者
        //      .accept(MediaType.APPLICATION_JSON)
        //      .get(User.class);//获取一个对象
        //      System.out.println(user);

                //有时候查询先判断有没有查询成功,还不想要结果。
                int status = WebClient.create("http://127.0.0.1:8888/cxf_jaxrs/userService/users")
                .accept(MediaType.APPLICATION_JSON)
                .get()
                .getStatus();
                System.out.println(status);


                System.out.println("客户端操作完成!");

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

4. CRM系统的CXF服务端构建开发(与spring整合)

4.1. SSH基础环境搭建

技术架构: 
Spring + Hibernate(spring和hibernate直接整合)+CXF+Oracle

4.1.1 新建Maven项目

引入Maven坐标: 
Spring、Hibernate、数据库和连接池、日志、Servlet、JSP、junit、编译版本覆盖、tomcat端口覆盖8888:

    <project xmlns="http://maven./POM/4.0.0" 
        xmlns:xsi="http://www./2001/XMLSchema-instance" 
        xsi:schemaLocation="http://maven./POM/4.0.0 
        http://maven./xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <groupId>cn.aric.project</groupId>
          <artifactId>crm</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <packaging>war</packaging>
          <name>crm</name>
          <description>物流的客户子系统</description>
          <properties>
                <spring.version>3.2.12.RELEASE</spring.version>
                <hibernate.version>3.6.10.Final</hibernate.version>
                <slf4j.version>1.7.5</slf4j.version>
                <c3p0.version>0.9.1.2</c3p0.version>
                <oracle.version>10.2.0.4.0</oracle.version>
                <servlet.version>2.5</servlet.version>
                <jsp.version>2.0</jsp.version>
                <junit.version>4.11</junit.version>
                <cxf.version>3.1.9</cxf.version>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-orm</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-test</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-core</artifactId>
                    <version>${hibernate.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                    <version>${slf4j.version}</version>
                </dependency>
                <dependency>
                    <groupId>c3p0</groupId>
                    <artifactId>c3p0</artifactId>
                    <version>${c3p0.version}</version>
                </dependency>
                <dependency>
                    <groupId>com.oracle</groupId>
                    <artifactId>ojdbc14</artifactId>
                    <version>${oracle.version}</version>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                    <version>${servlet.version}</version>
                    <scope>provided</scope>
                </dependency>
                <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>jsp-api</artifactId>
                    <version>${jsp.version}</version>
                    <scope>provided</scope>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                    <scope>test</scope>
                </dependency>       
                <dependency>
                    <groupId>javassist</groupId>
                    <artifactId>javassist</artifactId>
                    <version>3.12.0.GA</version>
                </dependency>
                <!-- CXF RS -->
                <dependency>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-frontend-jaxrs</artifactId>
                    <version>${cxf.version}</version>
                </dependency>
                <!-- CXF扩展提供者:提供了转换json的接口 -->
                <dependency>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-rs-extension-providers</artifactId>
                    <version>${cxf.version}</version>
                </dependency>
                <!-- CXF扩展提供者转换json需要默认的一个工具包 -->
                <dependency>
                    <groupId>org.codehaus.jettison</groupId>
                    <artifactId>jettison</artifactId>
                    <version>1.3.8</version>
                </dependency>   
                <!-- CXF的rs客户端 -->
                <dependency>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-rs-client</artifactId>
                    <version>${cxf.version}</version>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>tomcat-maven-plugin</artifactId>
                        <version>1.1</version>
                        <configuration>
                            <port>8888</port>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-resources-plugin</artifactId>
                        <version>2.6</version>
                        <configuration>
                            <encoding>UTF-8</encoding>
                        </configuration>
                    </plugin>
                <!-- 编译的jdk版本 -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.1</version>
                        <configuration>
                            <source>1.7</source>
                            <target>1.7</target>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </project>
    </project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149

4.1.2 整合spring

配置Spring整合Hibernate(几个配置文件:applicationContext.xml、db.properties,web.xml,log4j.properties等)

web.xml

    <?xml version="1.0" encoding="UTF-8"?>
        <web-app xmlns:xsi="http://www./2001/XMLSchema-instance" 
        xmlns="http://java./xml/ns/javaee" 
        xsi:schemaLocation="http://java./xml/ns/javaee 
        http://java./xml/ns/javaee/web-app_2_5.xsd" version="2.5">
          <display-name>crm</display-name>
          <!-- cxf的前端控制器 -->
            <servlet>
                <description>Apache CXF Endpoint</description>
                <display-name>cxf</display-name>
                <servlet-name>cxf</servlet-name>
                <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
            <servlet-mapping>
                <servlet-name>cxf</servlet-name>
                <url-pattern>/services/*</url-pattern>
            </servlet-mapping>
          <!-- spring配置文件位置 -->
          <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
          </context-param>  
          <!-- spring核心监听器 -->
          <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>
          <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
          </welcome-file-list>
        </web-app>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

db.properties

        jdbc.driver=oracle.jdbc.driver.OracleDriver
        jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:xe
        jdbc.user=scott
        jdbc.password=tigger
  • 1
  • 2
  • 3
  • 4

log4j.properties

        ### direct log messages to stdout ###
        log4j.appender.stdout=org.apache.log4j.ConsoleAppender
        log4j.appender.stdout.Target=System.err
        log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
        log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

        ### direct messages to file mylog.log ###
        log4j.appender.file=org.apache.log4j.FileAppender
        log4j.appender.file.File=d:/mylog.log
        log4j.appender.file.layout=org.apache.log4j.PatternLayout
        log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

        ### set log levels - for more verbose logging change 'info' to 'debug' ###

        log4j.rootLogger=info, stdout
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

applicationContext.xml

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

            <!-- 引入外部的属性配置文件     -->
            <context:property-placeholder location="classpath:db.properties"/>
            <!-- 连接池 -->
            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <property name="driverClass" value="${jdbc.driver}"/>
                <property name="jdbcUrl" value="${jdbc.url}"/>
                <property name="user" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </bean>

            <!-- spring来整合hibernate
            AnnotationSessionFactoryBean:spring提供的专门来整合hibernate注解
             -->
            <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                <!-- 注入数据源 -->
                <property name="dataSource" ref="dataSource"/>
                <!-- hibernate一般属性 -->
                <property name="hibernateProperties">
                    <props>
                        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                        <prop key="hibernate.show_sql">true</prop>
                        <prop key="hibernate.format_sql">true </prop>
                    </props>
                </property>
                <!-- 映射的类 
                packagesToScan:扫描哪个包,会将脑门上带@Entity的类,注册为实体类
                -->
                <property name="packagesToScan">
                    <list>
                        <value>cn.aric.crm.domain</value>
                    </list>
                </property>
            </bean>
            <!-- 事务管理器 -->
            <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                <property name="sessionFactory" ref="sessionFactory" />
            </bean>
            <!-- 注解驱动 -->
            <tx:annotation-driven transaction-manager="transactionManager"/>

            <!-- 开启spring的bean组件扫描(默认也会开启注解功能) -->
            <context:component-scan base-package="cn.aric.crm.service,cn.aric.crm.dao"/>

            <!-- 引入cxf配置 -->
            <import resource="applicationContext-cxf.xml"/>
        </beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

4.2 新建实体类

        @Entity
        @Table(name="t_customer",schema="scott")
        public class Customer {

            @Id
            @GeneratedValue(strategy=GenerationType.AUTO)//auto代表自动
            private Integer id;//OID属性
            private String name;//客户名称
            private String address;//住所
            private String telephone;//联系电话
            private String decidedZoneId;//定区编号(客户和定区关联的字段)

            public Integer getId() {
                return id;
            }
            public String getName() {
                return name;
            }
            public String getAddress() {
                return address;
            }
            public String getTelephone() {
                return telephone;
            }
            public String getDecidedZoneId() {
                return decidedZoneId;
            }
            public void setId(Integer id) {
                this.id = id;
            }
            public void setName(String name) {
                this.name = name;
            }
            public void setAddress(String address) {
                this.address = address;
            }
            public void setTelephone(String telephone) {
                this.telephone = telephone;
            }
            public void setDecidedZoneId(String decidedZoneId) {
                this.decidedZoneId = decidedZoneId;
            }

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

测试上面的配置,启动服务,自动建表:tomcat:run

4.3 引入CXF环境 ###

        <properties>        
                <cxf.version>3.1.9</cxf.version>
        </properties>
        <dependencies>      
            <!-- CXF RS -->
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-frontend-jaxrs</artifactId>
                <version>${cxf.version}</version>
            </dependency>
            <!-- CXF扩展提供者:提供了转换json的接口 -->
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-rs-extension-providers</artifactId>
                <version>${cxf.version}</version>
            </dependency>
            <!-- CXF扩展提供者转换json需要默认的一个工具包 -->
            <dependency>
                <groupId>org.codehaus.jettison</groupId>
                <artifactId>jettison</artifactId>
                <version>1.3.8</version>
            </dependency>   
            <!-- CXF的rs客户端 -->
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-rs-client</artifactId>
                <version>${cxf.version}</version>
            </dependency>
        </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.4 Spring整合CXF-RS的服务

        @Entity
        @Table(name="t_customer",schema="SCOTT")
        @XmlRootElement(name="customer")
        public class Customer {
            @Id
            //如果没有给主键策略,不管oid什么类型,都需要手动主键值
            //但如果有主键策略,根据主键策略来走。
            @GeneratedValue(strategy=GenerationType.AUTO)//auto代表自动
            //--自动:根据OID的属性的类型来自动选择
            //如果String类型,主键数据库不会自动生成,要么手动赋值(对于数据库来说手动主键),要么让hibernate的uuid赋值
            //如果是Integer,Long,值自增长的,会自动创建一个序列,使用序列的值作为主键值(数据库提供的序列值--hibernate调用)。
            private Integer id;//OID属性
            private String name;//客户名称
            private String address;//住所
            private String telephone;//联系电话
            private String decidedZoneId;//定区编号(客户和定区关联的字段)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4.4.1 编写SEI

@Path("/customerService")//具体服务的名字路径
                @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
        @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
        public interface CustomerService {

            //提供三个暴露的方法
            /**
             * 
             * 说明:查询没有关联定区的客户的列表
             * @return
             */
            @Path("/customers")//某个方法的操作的资源
            @GET
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public List<Customer> findCustomerListNoDecidedZoneId();
            /**
             * 
             * 说明:查询关联某个定区的客户的列表
             * @return
             */
            @Path("/customers/{decidedZoneId}")//某个方法的操作的资源
            @GET
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public List<Customer> findCustomerListByDecidedZoneId(@PathParam("decidedZoneId")String decidedZoneId);

            /**
             * 
             * 说明:批量更新定区编号,通过客户编号
             * @param decidedZoneId:DQ001
             * @param customerIds:用逗号分割编号:2,3
             */
            @Path("/customers/{decidedZoneId}/{customerIds}")//某个方法的操作的资源
            @PUT
            @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
            public void updateDecidedZoneIdByIds(@PathParam("decidedZoneId")String decidedZoneId,@PathParam("customerIds")String customerIds);

        }

        //SEI:客户的业务实现类
        //客户操作的业务层实现
        Service("customeService")
        @Transactional
        public class CustomerServiceImpl implements CustomerService{
            //注入dao
            @Autowired
            private GenericDAO<Customer, Integer> customerDAO;

            @Override
            public List<Customer> findCustomerListNoDecidedZoneId() {
                //条件构建
                DetachedCriteria criteria =DetachedCriteria.forClass(Customer.class)
                        .add(Restrictions.isNull("decidedZoneId"));
                //查询
                return customerDAO.findByCriteria(criteria);
            }

            @Override
            public List<Customer> findCustomerListByDecidedZoneId(String decidedZoneId) {
                //条件构建
                DetachedCriteria criteria =DetachedCriteria.forClass(Customer.class)
                        .add(Restrictions.eq("decidedZoneId", decidedZoneId));
                //查询
                return customerDAO.findByCriteria(criteria);
            }

            @Override
            public void updateDecidedZoneIdByIds(String decidedZoneId, String customerIds) {
                //快照更新
                //====先去掉指定定区的所有的关联(update)
                //查询出所有原来已经关的客户列表
                DetachedCriteria criteria =DetachedCriteria.forClass(Customer.class)
                        .add(Restrictions.eq("decidedZoneId", decidedZoneId));
                List<Customer> customerList = customerDAO.findByCriteria(criteria);
                //快照
                for (Customer customer : customerList) {
                    customer.setDecidedZoneId(null);
                }

                //====关联需要关联指定定区的客户(update)
                if(!StringUtils.isEmpty(customerIds)){
                    String[] customerArray = customerIds.split(",");
                    for (String customerId : customerArray) {
                        Customer customer = customerDAO.findById(Customer.class, Integer.parseInt(customerId));
                        customer.setDecidedZoneId(decidedZoneId);
                    }
                }

                //等待flush
            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
    }

4.4.2 编写DAO

4.4.3 配置web.xml(CXF的核心控制器)

        <!-- cxf的前端控制器 -->
        <servlet>
            <description>Apache CXF Endpoint</description>
            <display-name>cxf</display-name>
            <servlet-name>cxf</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>cxf</servlet-name>
            <url-pattern>/services/*</url-pattern>
        </servlet-mapping>

cxf配置:applicationContext-cxf.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www./schema/beans"
            xmlns:xsi="http://www./2001/XMLSchema-instance" 
            xmlns:jaxws="http://cxf./jaxws"
            xmlns:jaxrs="http://cxf./jaxrs"
            xmlns:jaxrsclient="http://cxf./jaxrs-client"
            xsi:schemaLocation=" http://www./schema/beans 
            http://www./schema/beans/spring-beans.xsd 
            http://cxf./jaxws 
            http://cxf./schemas/jaxws.xsd
            http://cxf./jaxrs
            http://cxf./schemas/jaxrs.xsd
            http://cxf./jaxrs-client
            http://cxf./schemas/jaxrs-client.xsd">
            <!-- cxf服务servlet的初始化 -->
            <import resource="classpath:META-INF/cxf/cxf.xml" />
            <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

            <!-- 配置REST服务 -->

            <!-- 
                jaxrs:server:JAXRSServerFactoryBean+bean
                address:请求分发的具体服务地址
                serviceClass:sei接口
             -->
            <jaxrs:server id="customerWebService" address="/CustomerWS" >
                <jaxrs:serviceBeans>
                    <ref bean="customerService" />
                </jaxrs:serviceBeans>
                <!-- 输入日志拦截器 -->
                <jaxrs:inInterceptors>
                    <ref bean="loggingInInterceptor"/>
                </jaxrs:inInterceptors>
                <!-- 输出日志拦截器 -->
                <jaxrs:outInterceptors>
                    <ref bean="loggingOutInterceptor" />
                </jaxrs:outInterceptors>
            </jaxrs:server>
            <!-- 输入日志拦截器 -->
            <bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
            <!-- 输出日志拦截器 -->
            <bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
        </beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

4.4.4 测试

测试的访问路径: 
web上下文+cxf前端控制器+配置的服务路径+类上的具体的服务路径 
web上下文+cxf前端控制器+配置的服务路径+类上的具体的服务路径+资源路径(方法上)

使用SoapUI—webservice的调试工具,Encoding改UTF-8。

5. BOS系统的CXF客户端

5.1.项目中引入CXF开发环境

引入Maven坐标(Pom.xml):

        <cxf.version>3.1.9</cxf.version>

        <!-- CXF扩展提供者:提供了转换json的接口 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-extension-providers</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- CXF扩展提供者转换json需要默认的一个工具包 -->
        <dependency>
            <groupId>org.codehaus.jettison</groupId>
            <artifactId>jettison</artifactId>
            <version>1.3.8</version>
        </dependency>   
        <!-- CXF的rs客户端 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>${cxf.version}</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

5.2 CXF-RS的客户端开发

5.2.1 编写Domain

        //dto
        @XmlRootElement(name="customer")
        public class Customer {
            private Integer id;//OID属性
            private String name;//客户名称
            private String residence;//住所
            private String telephone;//联系电话
            private String decidedZoneId;//定区编号(客户和定区关联的字段)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5.2.2 编写Jsp

5.2.3 后台代码

    //列出没有关联定区的客户
    @Action("decidedZone_listCustomerListNoDecidedZoneId")
    public String listCustomerListNoDecidedZoneId(){
        //直接调用webservice接口
        //基本服务连接
        WebClient webClient = WebClient.create("http://localhost:8888/crm/services");
        Collection<? extends Customer> collection = webClient
        .path("/crmService/customerService")//具体服务
        .path("/customers")//资源路径
        .accept(MediaType.APPLICATION_JSON)//客户端要接收的类型
        .type(MediaType.APPLICATION_JSON)//发出去的数据类型,java对象会转换为该类型
        .getCollection(Customer.class);

        //压入栈顶
        pushToValuestackRoot(collection);
        //json数组
        return JSON; //JSON在父类中配置常量
    }
    //列出已经关联定区的客户
    @Action("decidedZone_listCustomerListHasDecidedZoneId")
    public String listCustomerListHasDecidedZoneId(){
        //直接调用webservice接口
        //基本服务连接
        WebClient webClient = WebClient.create("http://localhost:8888/crm/services");
        Collection<? extends Customer> collection = webClient
        .path("/crmService/customerService")//具体服务
        .path("/customers")//资源路径
        .path("/"+model.getId())
        .accept(MediaType.APPLICATION_JSON)//客户端要接收的类型
        .type(MediaType.APPLICATION_JSON)//发出去的数据类型,java对象会转换为该类型
        .getCollection(Customer.class);

        //压入栈顶
        pushToValuestackRoot(collection);
        //json数组

        return JSON;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多