zoukankan      html  css  js  c++  java
  • WebService

    一.WebService概述

    1.1WebService简介

    Web Service(WEB服务)能够快捷和方便地综合结合各种系统、商务和任何应用平台。利用最新的Web Service 标准能够使任何软件系统和系统之间的应用互通互联,方便,而且更加廉价。

    1.2WebService的应用场景

    • 跨越防火墙通信

    • 集成应用程序

    • 复用软件

    1.3其他远程应用调用解决方案

    • 使用Socket远程通信

    • 使用Apache的HttpClient

    • RMI(Remote Method Invoke)

    1.4WebService的三个规范

    • JAXM&SAAJ(废弃)

    • JAX-WS :采用标准SOAP(Simple Object Access Protocol) 协议传输,soap协议传输是xml数据。

    • JAX-RS:Java针对REST(Representation State Transfer)风格制定的一套Web服务规范。

    二.Apache的CXF

    Apache CXF是一个开源的Web Service 框架,CXF 帮助我们构建和开发 Web Service,它支持多种协议,如:SOAP, XML/HTTP、RESTful或者CORBA。

    官网:http://cxf.apache.org/

    下载地址:http://cxf.apache.org/download.html

    三.基于JAX-WS规范的入门

    3.1JAX-WS的三要素

    • SOAP:基于HTTP协议,采用XML格式,用来传递信息的格式。

    • WSDL:用来描述如何访问具体的服务

    • UDDI:用户可按UDDI标准搭建UDDI服务器,用来管理分发,查询WebService。其他用户可以自己注册发布WebService调用。

    3.2入门案例

    我们在使用WebService时,更多的时候充当的是调用者。因为服务端别人已经写好了。

    3.2.1编写服务端

    第一步:创建Maven工程导入CXF坐标
    <!-- 导入cxf相关坐标 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-features-logging</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>3.3.0</version>
    </dependency>
    第二步:编写服务接口和实现类
    /**
     * 提供实时公交的服务接口
     * @author Mr.song
     * @date 2019/05/20 9:55
     */
    @WebService //表明当前接口是一个WebService服务
    public interface BusService {
        /**
         * 根据公交线路查询公交实时站点
         * @param line 公交线路
         * @return
         */
        String getBusByLine(String line);
    }
    //==========================================
    /**提供实时公交的服务实现类
     * @author Mr.song
     * @date 2019/05/20 9:57
     */
    public class BusServiceImpl implements BusService {
        public String getBusByLine(String line) {
            if ("916".equals(line)){
                return "距您还有3站";
            }
            return "未知";
        }
    }

    Tips:注意加入@WebService注解

    第三步:编写测试类(main方法启动)
    /**
     * @author Mr.song
     * @date 2019/05/20 10:17
     */
    public class WebBusServiceTest {
        public static void main(String[] args) {
            //1.创建发布服务的对象
            JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
            //2.设置服务地址
            factoryBean.setAddress("http://localhost:8847/bus");
            //3.设置服务的对象
            factoryBean.setServiceBean(new BusServiceImpl());
            //4.发布服务
            factoryBean.create();
        }
    }
    第四步:浏览器访问测试

    地址为:http://localhost:8847/bus/?wsdl

    若控制台无错误,则表明服务端编写正确。

    3.2.2编写客户端

    第一步:创建Maven工程导入CXF坐标(同上)
    第二步:使用jdk提供的命令生成本地代码

    使用的是jdk bin目录下的wsimport.exe工具

    进入到客户端工程java目录下,按住shift右击,在此处打开shell窗口输入命令:wsimport -s . http://localhost:8847/bus/?wsdl 即可完成解析,并生成代码。(此处的链接是服务端浏览器测试时访问的)| -s 指定生成文件目录 . 指当前文件夹下

    第三步:编写测试类
    /**
     * @author Mr.song
     * @date 2019/05/20 16:32
     */
    public class BusTest {
    
        @Test
        public void testBus(){
            //1.创建客户端的代理工厂bean
            JaxWsProxyFactoryBean proxy = new JaxWsProxyFactoryBean();
            //2.设置说明书的地址
            proxy.setAddress("http://localhost:8847/bus?wsdl");
            //3.设置客户端需要使用的服务接口类字节码
            proxy.setServiceClass(BusService.class);
            //4.使用proxy创建服务接口的代理对象
            Object obj = proxy.create();
            //5.如果obj是service接口的代理实现类,强转成service接口
            BusService busService = (BusService) obj;
            //6.执行service中的方法
            String rtValue = busService.getBusByLine("916");
            System.out.println(rtValue);
        }
    }

    Tips: 运行测试端代码时,保证服务端不要关闭

    3.3Spring整合CXF

    3.3.1编写服务端

    第一步:创建Maven的Web工程并导入CXF坐标(同上)
    第二步:编写服务接口和实现类(同上)
    第三步:配置 Spring 的配置文件
    <?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:jaxws="http://cxf.apache.org/jaxws"
           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">
        <!-- 配置服务端的服务 -->
        <!-- 主机和端口用tomcat的,http协议 -->
        <jaxws:server address="/bus">
            <!-- 配置具体服务实现类 -->
            <jaxws:serviceBean>
                <bean class="cn.dintalk.service.BusServiceImpl"/>
            </jaxws:serviceBean>
        </jaxws:server>
    </beans>
    第四步:在 web.xml 中配置Spring容器在应用加载时创建
    <?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"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
      <!-- 配置应用加载监听器 -->
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-cxf-server.xml</param-value>
      </context-param>
    
      <!-- CXF框架的核心控制器:CXFServlet -->
      <servlet>
        <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中含有/ws/*的请求 -->
        <url-pattern>/ws/*</url-pattern>
      </servlet-mapping>
    </web-app>
    第五步:浏览器访问测试

    地址:http://localhost:8080/ws/bus?wsdl

    若控制台无错误,则表明服务端编写正确。

    3.3.2编写客户端

    第一步:创建Maven的Web工程并导入CXF坐标(同上)
    第二步:使用 jdk 提供的命令生成客户端代码(同上)
    第三步:编写 Spring 配置文件
    <?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:jaxws="http://cxf.apache.org/jaxws"
           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">
        <!-- 配置服务端访问地址和应用接口 -->
        <jaxws:client id="client"
                      address="http://localhost:8080/ws/bus?wsdl"
                      serviceClass="cn.dintalk.service.BusService"></jaxws:client>
    </beans>
    第四步:编写测试类
    /**
     * @author Mr.song
     * @date 2019/05/20 17:29
     */
    public class BusTest {
        @Test
        public void testBus(){
            //1.读取配置文件,创建容器
            ApplicationContext ac = new
                    ClassPathXmlApplicationContext("classpath:applicationContext-cxf-client.xml");
            //2.根据bean的id获取对象
            BusService busService = (BusService) ac.getBean("client");
            //3.执行方法
            String rtValue = busService.getBusByLine("916");
            System.out.println(rtValue);
        }
    }

    Tips: 运行测试类测试时,主要不要关闭服务端。

    四.基于JAX-RS规范的入门

    4.1JAX-RS和Restful

      ​ JAX-RS 是一个 Java 编程语言接口,被设计用来简化使用 REST 架构的应用程序的开发。JAX-RS API 使用 Java 编程语言的注解来简化 RESTful web service 的开发。开发人员使用 JAX-RS 的注解修饰Java编程语言的类文件来定义资源和能够应用在资源上的行为。JAX-RS的注解是运行时的注解,因此运行时的映射会为资源生成辅助类和其他的辅助文件。包含 JAX-RS 资源类的 Java EE 应用程序中资源是被配置好的,辅助类和辅助文件是生成的,资源通过被发布到 Java EE 服务器上来公开给客户端。

      ​ RESTful web service 是创建来能在 web 更好的运行的 web service。REST 是一种架构类型,指定了如统一的接口等应用于 web service 的约束。REST 提供了如性能、可扩展性和可变性等特性,使得 service 能够更好的在web上工作。在 REST 框架中,数据和功能被认为是资源,是通过 URI来访问的,通常是 web链接。资源是通过使用一组简单的、定义良好的操作来生效。REST 的架构方式限定了客户/服务器架构,是设计来使用无状态的通信协议的,通常是 HTTP。在 REST 框架类型中,客户端和服务器使用标准的接口和协议交换资源的representation。

    4.2入门案例

    4.2.1编写服务端

    第一步:创建Maven工程并导入坐标
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxrs</artifactId>
        <version>3.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>3.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-rs-client</artifactId>
        <version>3.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-rs-extension-providers</artifactId>
        <version>3.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jettison</groupId>
        <artifactId>jettison</artifactId>
        <version>1.3.7</version>
    </dependency>
    第二步:编写实体类(业务实体)
    @XmlRootElement(name = "User")
    public class User {
        private Integer id;
        private String username;
        private String city;
    
        private List<Car> cars = new ArrayList<Car>();
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public List<Car> getCars() {
            return cars;
        }
    
        public void setCars(List<Car> cars) {
            this.cars = cars;
        }
    
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", city=" + city + ", cars=" + cars + "]";
        }
    @XmlRootElement(name = "Car")
    public class Car {
        private Integer id;
        private String carName;
        private Double price;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getCarName() {
            return carName;
        }
    
        public void setCarName(String carName) {
            this.carName = carName;
        }
    
        public Double getPrice() {
            return price;
        }
    
        public void setPrice(Double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car [id=" + id + ", carName=" + carName + ", price=" + price + "]";
        }
    }
    第三步:编写业务接口和实现类
    @Path("/userService")
    @Produces("*/*")
    public interface UserService {
        @POST
        @Path("/user")
        @Consumes({ "application/xml", "application/json" })
        public void saveUser(User user);
    
        @PUT
        @Path("/user")
        @Consumes({ "application/xml", "application/json" })
        public void updateUser(User user);
    
        @GET
        @Path("/user")
        @Produces({ "application/xml", "application/json" })
        public List<User> findAllUsers();
    
        @GET
        @Path("/user/{id}")
        @Consumes("application/xml")
        @Produces({ "application/xml", "application/json" })
        public User finUserById(@PathParam("id") Integer id);
    
        @DELETE
        @Path("/user/{id}")
        @Consumes({"application/xml", "application/json"})
        public void deleteUser(@PathParam("id") Integer id);
    }
    /**
     * @author Mr.song
     * @date 2019/05/20 19:39
     */
    public class UserServiceImpl implements UserService {
    
        public void saveUser(User user) {
            System.out.println("save user:" + user);
        }
    
        public void updateUser(User user) {
            System.out.println("update user:" + user);
        }
    
        public List<User> findAllUsers() {
            List<User> users = new ArrayList<User>();
            User user1 = new User();
            user1.setId(1);
            user1.setUsername("小明");
            user1.setCity("北京");
    
            List<Car> carList1 = new ArrayList<Car>();
            Car car1 = new Car();
            car1.setId(101);
            car1.setCarName("保时捷");
            car1.setPrice(1000000d);
            carList1.add(car1);
            Car car2 = new Car();
            car2.setId(102);
            car2.setCarName("宝马");
            car2.setPrice(400000d);
            carList1.add(car2);
            user1.setCars(carList1);
    
            users.add(user1);
    
            User user2 = new User();
            user2.setId(2);
            user2.setUsername("小丽");
            user2.setCity("上海");
            users.add(user2);
    
            return users;
        }
    
        public User finUserById(Integer id) {
            if (id == 1) {
                User user1 = new User();
                user1.setId(1);
                user1.setUsername("小明");
                user1.setCity("北京");
                return user1;
            }
            return null;
        }
    
        public void deleteUser(Integer id) {
            System.out.println("delete user id :" + id);
        }
    }
    第四步:编写服务发布类
    /**
     * jaxrs服务的发布
     * @author Mr.song
     * @date 2019/05/20 19:45
     */
    public class UserTest {
        public static void main(String[] args) {
            //1.创建jaxrs服务工厂bean对象
            JAXRSServerFactoryBean factoryBean = new JAXRSServerFactoryBean();
            //2.设置服务地址
            factoryBean.setAddress("http://localhost:8848");
            //3.设置提供服务的类
            factoryBean.setServiceBean(new UserServiceImpl());
            //4.设置日志输入和输出的两个拦截器
            factoryBean.getInInterceptors().add(new LoggingInInterceptor());
            factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
            //5.发布服务
            factoryBean.create();
        }
    }

    4.2.2编写客户端

    第一步:创建Maven工程并导入坐标(同时)
    第二步:编写业务实体类(同上)
    第三步:编写测试类
    /**
     * @author Mr.song
     * @date 2019/05/20 19:55
     */
    public class UserClientTest {
        /**
         *  注意:它和jaxws规范的区别是,它使用的是restful的url
         */
        @Test
        public void test(){
            User user = new User();
            user.setId(1);
            user.setUsername("test");
            //1.使用WebClient创建访问地址 : 在服务端接口中有/userService  /user的路径规则
            Object rtValue = WebClient.create("http://localhost:8848/userService/user")
                    .type(MediaType.APPLICATION_XML).post(user);
            System.out.println(rtValue);
        }
    
        @Test
        public void test2(){
            //1.使用WebClient创建访问地址
            Object rtValue = WebClient.create("http://localhost:8848/userService/user/123")
                    .type(MediaType.APPLICATION_JSON).delete();
            System.out.println(rtValue);
        }
    }

    Tips: 测试时保证服务端开启。

    4.3Spring整合CXF

    4.3.1编写服务端

    第一步:创建Maven的Web工程并导入坐标(同上)
    第二步:编写业务代码(实体类和服务接口及实现类)同上
    第三步:编写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"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
        <!-- 配置应用加载监听器 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-cxf-rs.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <!-- CXF的核心控制器 -->
        <servlet>
            <servlet-name>cxfServlet</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>cxfServlet</servlet-name>
            <!-- 配置拦截的路径 -->
            <url-pattern>/rs/*</url-pattern>
        </servlet-mapping>
    </web-app>
    第四步:编写Spring配置文件
    <?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: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/jaxrs
            http://cxf.apache.org/schemas/jaxrs.xsd">
        <!-- 配置服务:ip、端口用tomcat的 -->
        <!-- 这里配置了address,接口类就不要配置注解了(@Path("/userService")) -->
        <jaxrs:server id="userService" address="/userService">
            <jaxrs:serviceBeans>
                <bean class="cn.dintalk.service.UserServiceImpl"/>
            </jaxrs:serviceBeans>
            <!-- 配置拦截器 -->
            <jaxrs:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
            </jaxrs:inInterceptors>
            <jaxrs:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
            </jaxrs:outInterceptors>
        </jaxrs:server>
    </beans>

    4.3.2编写客户端

    第一步:创建Maven工程并导入坐标(同上)
    第二步:创建业务实体类(同上)
    第三步:编写测试类
    @Test
     public void test04(){
         User user = WebClient.create("http://localhost:8080/rs/userService/user/1")
                 .type(MediaType.APPLICATION_XML).get(User.class);
         System.out.println(user);
     }
    //输出如下:
    //User [id=1, username=小明, city=北京, cars=[]]

    Tips: 测试时要保证服务端开启。

  • 相关阅读:
    [POJ1151]Atlantis
    [POJ1177]Picture
    [POJ1765]November Rain
    Adaptively handling remote atomic execution based upon contention prediction
    Webpack 2.0 的文档
    PAT乙级 1025. 反转链表 (25)
    PAT乙级 1024. 科学计数法 (20)(未通过全部测试,得分18)
    PAT乙级 1023. 组个最小数 (20)
    PAT乙级 1022. D进制的A+B (20)
    PAT乙级 1021. 个位数统计 (15)
  • 原文地址:https://www.cnblogs.com/dintalk/p/10910061.html
Copyright © 2011-2022 走看看