SpringBoot создает службу WebService на основе CXF

Java

предисловие

В последнее время, поскольку системе необходимо получить доступ к новому платежному каналу, вообще говоря, использованиеRestApiдля доступа, но канал оплаты для этого доступа - оплата за границей.WebService, Мы принципиально не используем WS в реальном бизнесе, поэтому я проверил некоторые материалы и записал WS, используемую в наших собственных проектах.

Обзор веб-сервиса

  • Что такое веб-сервис
    Технология веб-сервисов позволяет различным приложениям, работающим на разных машинах, обмениваться данными или интегрироваться друг с другом, не прибегая к дополнительному специализированному программному или аппаратному обеспечению сторонних производителей. Приложения, реализованные в соответствии со спецификацией веб-сервиса, могут обмениваться данными друг с другом независимо от используемого ими языка, платформы или внутреннего протокола.
    Проще говоря, WebService — это технология удаленного вызова на разных языках программирования и платформах операционных систем.
  • WebServiceТехническая поддержка
    в основном для пониманияXML和XSD,SOAP,WSDL,UDDI, пожалуйста, обратитесь к энциклопедии Baidu за подробностями:Web Service

Обзор Apache-CXF

  • Что такое Apache-CXF
    Apache CXF – это платформа для служб с открытым исходным кодом. CXF помогает создавать и разрабатывать службы с использованием интерфейсных программных API, таких как JAX-WS и JAX-RS. Эти службы могут поддерживать различные протоколы, такие как: SOAP, XML/HTTP, RESTful HTTP или CORBA, и могут работать на различных транспортных протоколах, таких как: HTTP, JMS или JBI,
    CXF значительно упрощает создание сервисов и в то же время легко интегрируется со Spring.
    За подробностями обращайтесь к официальному:Apache CXF
  • Спецификация JAX-WS
    JAX-WS расшифровывается как Java API для веб-сервисов на основе XML. JAX-WS — это модель программирования, поддерживающая стандартную модель разработки клиентских приложений веб-службы на основе аннотаций и упрощающая разработку приложений.
    JAX-WS — это API языка программирования Java для создания веб-сервисов.
    • На стороне сервера пользователю нужно только определить интерфейс SEI (интерфейс конечной точки службы), который необходимо реализовать для удаленного вызова через язык Java, и предоставить соответствующую реализацию, которую можно опубликовать как интерфейс веб-службы, вызвав публикацию службы. интерфейс JAX-WS.
    • На стороне клиента пользователи могут создавать прокси (заменяя удаленные службы локальными объектами) через API JAX-WS для осуществления вызовов на стороне удаленного сервера. Конечно, JAX-WS также предоставляет набор вызовов API, которые работают с базовыми сообщениями.Вы можете напрямую использовать сообщения SOAP или сообщения XML для отправки запросов через Dispatch или использовать Provider для обработки сообщений SOAP или XML.
  • Общие ссылки на аннотацииСводка аннотаций WebService

Springboot интегрирует примеры CXF

Далее мы продемонстрируем, как публиковать услуги простым примером, как проводить обслуживание звонков.

Сборка сервера

  1. Создать проектspring-boot-cxf-service
  2. Внедрение зависимостей maven
    <dependencies>
        <!--spring-boot-starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--lombok懒人依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--test依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--cxf依赖 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <!--commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
  3. Создайте необходимые сущности
    1.NBAPlayer.java
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public class NBAPlayer {
       String name;
       String team;
       List<String> teams;
       String description;
       Position position;
       @Override
       public String toString() {
           return "NBA现役球员" + name + ",司职" + position.value + "现效力于" + team + ",曾效力球队" + teams.toString();
       }
    }
    
    2.Positon.java
    public enum Position {
       FORWARD("小前锋"),
       SHOOTING("控球後衛");
       String value;
       Position(String value) {
           this.value = value;
       }
       public String value() {
           return value;
       }
       public static Position fromValue(String v) {
           for (Position c : Position.values()) {
               if (c.value.equals(v)) {
                   return c;
               }
           }
           throw new IllegalArgumentException(v);
       }
    }
    
    3.NBAPlayerSoapService.java
    @WebService(targetNamespace = WsConst.NAMESPACE_URI, name = "NBAPlayerSoap")
    public interface NBAPlayerSoapService {
        /**
         * description  根据姓名获取球员信息
         * date         2019/10/15
         *
         * @param NBAPlayerName
         * @return cn.forward.springboot.cxf.service.entity.NBAPlayer
         */
        @WebMethod(operationName = "getNBAPlayerByName")
        NBAPlayer getNBAPlayerByName(@WebParam(name = "NBAPlayerName") String NBAPlayerName);
    
        /**
         * description  获取球员列表
         * date         2019/10/15
         *
         * @return java.util.List<cn.forward.springboot.cxf.service.entity.NBAPlayer>
         */
        @WebMethod
        List<NBAPlayer> getNBAPlayerList();
    
    }
    
    4.NBAPlayerSoapImpl.java
    @WebService(
        targetNamespace = WsConst.NAMESPACE_URI, //wsdl命名空间
        name = "NBAPlayerSoap",                  //portType名称 客户端生成代码时 为接口名称
        serviceName = "NBAPlayerSoapService",    //服务name名称
        portName = "NBAPlayerPortName",          //port名称
        endpointInterface = "cn.forward.springboot.cxf.service.service.NBAPlayerSoapService")
    public class NBAPlayerSoapImpl implements NBAPlayerSoapService {
    
        @Override
        public NBAPlayer getNBAPlayerByName(String name) {
            List<NBAPlayer> nbaPlayers = getNBAPlayerList();
            AtomicReference<NBAPlayer> player = new AtomicReference<>(nbaPlayers.get(new Random().nextInt(2)));
            nbaPlayers.forEach(nbaPlayer -> {
                if (nbaPlayer.getName().equals(name)) {
                    player.set(nbaPlayer);
                }
            });
            return player.get();
        }
        @Override
        public List<NBAPlayer> getNBAPlayerList() {
            return generatorList();
        }
        public List<NBAPlayer> generatorList() {
            List<NBAPlayer> resultList = new ArrayList<>();
            NBAPlayer LBJ = new NBAPlayer();
            LBJ.setName("勒布朗·詹姆斯");
            LBJ.setTeam("洛杉矶湖人");
            LBJ.setTeams(Arrays.asList("克里夫蘭騎士(2003−2010)", "邁阿密熱火(2010−2014)"));
            LBJ.setPosition(Position.FORWARD);
            LBJ.setDescription(LBJ.toString());
            resultList.add(LBJ);
            NBAPlayer WS = new NBAPlayer();
            WS.setName("罗素·威斯布鲁克");
            WS.setTeam("休斯頓火箭");
            WS.setTeams(Arrays.asList("奧克拉荷馬雷霆 (2008-2019)"));
            WS.setPosition(Position.SHOOTING);
            WS.setDescription(WS.toString());
            resultList.add(WS);
            return resultList;
        }
    }
    
    5.WsConst.java
    public class WsConst {
        public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice";
    }
    
    6.CxfWebServiceConfig.java
    @Configuration
    public class CxfWebServiceConfig {
        //这里需要注意  由于springmvc 的核心类 为DispatcherServlet
        //此处若不重命名此bean的话 原本的mvc就被覆盖了。可查看配置类:DispatcherServletAutoConfiguration
        //一种方法是修改方法名称 或者指定bean名称 
        //这里需要注意 若beanName命名不是 cxfServletRegistration 时,会创建两个CXFServlet的。
        //具体可查看下自动配置类:Declaration org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration
        //也可以不设置此bean 直接通过配置项 cxf.path 来修改访问路径的
        @Bean("cxfServletRegistration")
        public ServletRegistrationBean dispatcherServlet() {
            //注册servlet 拦截/NBA 开头的请求 不设置 默认为:/services/*
            return new ServletRegistrationBean(new CXFServlet(), "/NBA/*");
        }
        /**
         * 申明业务处理类 当然也可以直接 在实现类上标注 @Service
         * @author ShiFan
         */
        @Bean
        public NBAPlayerSoapService authorService() {
            return new NBAPlayerSoapImpl();
        }
        /**
         * 非必要项
         */
        @Bean(name = Bus.DEFAULT_BUS_ID)
        public SpringBus springBus() {
            SpringBus springBus = new SpringBus();
            return springBus;
        }
        /**
         * 发布endpoint
         */
        @Bean
        public Endpoint endpoint(NBAPlayerSoapService NBAPlayerSoap) {
            EndpointImpl endpoint = new EndpointImpl(springBus(), NBAPlayerSoap);
            //发布地址
            endpoint.publish("/player");
            return endpoint;
        }
    }
    
    Меры предосторожности:При настройке ServletRegistrationBean вам необходимо обратить внимание на установку имени метода или имени компонента, чтобы оно не совпадало с именем класса DispatcherServlet по умолчанию, что приведет к тому, что исходный интерфейс mvc станет непригодным для использования, поскольку он будет перезаписан. Путь для изменения доступа можно изменить, установив ServletRegistrationBean, но в то же время следует отметить, что имя компонента должно быть установлено как cxfServletRegistration, иначе будет зарегистрировано несколько CXFServlet. По конкретным причинам см. класс автоматической настройки: org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration.
    Таким образом, изменить путь доступа также можно с помощью настройки элемента: cxf.path. Его URL-адрес доступа по умолчанию: / services
  4. Создайте класс запуска и одновременно запустите приложение
@SpringBootApplication
@Slf4j
public class SpringBootCxfServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootCxfServiceApplication.class, args);
		log.info("spring-boot-cxf-service启动!");
	}
}

Просмотр журнала ввода

2019-10-15 15:49:17.964  INFO 16100 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-10-15 15:49:17.967  INFO 16100 --- [           main] .f.s.c.s.SpringBootCxfServiceApplication : Started SpringBootCxfServiceApplication in 3.35 seconds (JVM running for 4.454)
2019-10-15 15:49:17.969  INFO 16100 --- [           main] .f.s.c.s.SpringBootCxfServiceApplication : spring-boot-cxf-service启动!
  1. контрольная работа
    доступhttp://localhost:8080/NBA/player?wsdlпроверять:
    Snipaste_2019-10-15_16-16-26.png

Сборка клиента

  1. Создать проектspring-boot-cxf-client
  2. Внедрение зависимостей maven
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.5.17</version>
        </dependency>
    </dependencies>
    
  3. Создайте файл wsdl и используйте плагин: cxf-codegen-plugin для создания связанных классов.
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- cxf-codegen-plugin -->
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.2.5</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${project.basedir}/src/main/java</sourceRoot>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>src/main/resources/wsdl/player.wsdl</wsdl>
                                    <wsdlLocation>classpath:wsdl/player.wsdl</wsdlLocation>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
    提示:Поместите файл wsdl в каталог main/resources/wsdl. После выполнения команды mvn generate-sources соответствующий файл класса будет создан автоматически. Скопируйте соответствующие файлы классов в каталог src/java. Или также можно указать sourceRoot напрямую
  4. Создавайте классы конфигурации, классы доступа и т. д.
  • WsCont.java
    public class WsConst {
        public static final String SERVICE_ADDRESS= "http://localhost:8080/NBA/player?wsdl";
    }
    
  • CxfClientConfig.java
    @Configuration
    public class CxfClientConfig {
        /**
         * 采用代理方式
         *
         * @return NBAPlayerSoap
         */
        @Bean
        public NBAPlayerSoap createAuthorPortTypeProxy() {
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            jaxWsProxyFactoryBean.setServiceClass(NBAPlayerSoap.class);
            jaxWsProxyFactoryBean.setAddress(WsConst.SERVICE_ADDRESS);
            return (NBAPlayerSoap) jaxWsProxyFactoryBean.create();
        }
    
        /**
         * 采用动态工厂方式 不需要指定服务接口
         */
        @Bean
        public Client createDynamicClient() {
            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(WsConst.SERVICE_ADDRESS);
            return client;
        }
    }
    
  • NBAPlayerController.java
    @RestController
    @RequestMapping("/nba/player")
    public class NBAPlayerController {
    
        @Resource
        NBAPlayerSoap nbaPlayerSoap;
    
        /**
         * description  根据球员名称获取球员信息
         * date         2019/10/15
         *
         * @param nbaPlayerName
         * @return cn.lqdev.webservice.NbaPlayer
         */
        @GetMapping("/getNBAPlayerByName")
        public NbaPlayer getNBAPlayerByName(@RequestParam("nbaPlayerName") String nbaPlayerName) {
            return nbaPlayerSoap.getNBAPlayerByName(nbaPlayerName);
        }
    
        /**
         * description  获取全部球员信息
         * date         2019/10/15
         * @return java.util.List<cn.lqdev.webservice.NbaPlayer>
         */
        @GetMapping("/getNBAPlayerList")
        public List<NbaPlayer> getNBAPlayerList() {
            return nbaPlayerSoap.getNBAPlayerList();
        }
    }
    
  1. Создать класс запуска, протестировать
    @SpringBootApplication
    @Slf4j
    public class SpringBootCxfClientApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootCxfClientApplication.class, args);
            log.info("spring-boot-cxf-client启动!");
        }
    }
    
    доступ:http://localhost:8081/nba/player/getNBAPlayerByName?nbaPlayerName=Леброн Джеймс
    Результаты проверки:
    {
        description: "NBA现役球员勒布朗·詹姆斯,司职小前锋现效力于洛杉矶湖人,曾效力球队[克里夫蘭騎士(2003−2010), 邁阿密熱火(2010−2014)]",
        name: "勒布朗·詹姆斯",
        position: "FORWARD",
        team: "洛杉矶湖人",
        teams: [
        "克里夫蘭騎士(2003−2010)",
        "邁阿密熱火(2010−2014)"
        ]
    }
    

6. Справочные статьи

Суммировать

В этой статье в основном рассказывается о процессе создания Springboot сервисов WebService на основе CXF.