preface

Recently, the system needs to access a new payment channel. Generally, the RestApi is used for access. However, the payment channel this time is for overseas payment, and the WebService is used, which is basically not used in our actual business.

WebService overview

  • What is a web service

    Web Service technology enables different applications running on different machines to exchange data or integrate with each other without the need for additional, specialized third-party software or hardware. Applications implemented according to the Web Service specification can exchange data with each other, regardless of their language, platform, or internal protocol.

    Simply put, WebService is a remote invocation technology across programming languages and operating system platforms.
  • WebServcie technical support

    It’s about understandingXML and XSD,SOAP,WSDL,UDDI, please refer to Baidu Baike for details:Web Service

Apache CXF – an overview

  • What is the Apache CXF

    Apache CXF is an open source Services framework that helps you leverage the Frontend programming API to build and develop Services such as JAX-WS and JAX-RS. These Services can support multiple protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA, and can run over multiple transport protocols such as HTTP, JMS, or JBI.

    CXF greatly simplifies the creation of Services, and it naturally integrates seamlessly with Spring.

    For details, please refer to official:Apache CXF
  • JAX – WS specification

    Jax-ws full name: Java API for XML-based Web Services. Jax-ws is a programming model that simplifies application development by enabling annotation-based standard models to be used to develop Web Service applications and clients.

    Jax-ws is an API for creating Web services in the Java programming language.
    • On the server side, the user only needs to define the interface SEI (Service Endpoint Interface) for the remote invocation through the Java language and provide the relevant implementation, which can be published as a WebService interface by calling jax-WS’s service Publishing interface.
    • On the client side, the user can use JAX-WS’s API to create a proxy (replacing the remote service with a local object) to invoke the remote server side. Of course jax-WS also provides a set of API calls to operate on the underlying messages. You can send requests directly using SOAP or XML messages via Dispatch or use the Provider to process SOAP or XML messages.
  • For common annotations, refer to the Summary of WebService annotations

SpringBoot integrates CXF instances

Next, let’s show a simple example of how to publish a service and how to invoke it.

Server build

  1. Create a projectspring-boot-cxf-service
  2. Introducing Maven dependencies
    <dependencies>
        <! --spring-boot-starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <! -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <! - the test relies on - >
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <! - CXF dependence - >
        <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>
    Copy the code
  3. Create the required entities

    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(a) {
           return "Current NBA player" + name + ", office" + position.value + "Now in force" + team + "Used to play for the team."+ teams.toString(); }}Copy the code

    2.Positon.java

    public enum Position {
       FORWARD("Small forward"),
       SHOOTING("Point guard");
       String value;
       Position(String value) {
           this.value = value;
       }
       public String value(a) {
           return value;
       }
       public static Position fromValue(String v) {
           for (Position c : Position.values()) {
               if (c.value.equals(v)) {
                   returnc; }}throw newIllegalArgumentException(v); }}Copy the code

    3.NBAPlayerSoapService.java

    @WebService(targetNamespace = WsConst.NAMESPACE_URI, name = "NBAPlayerSoap")
    public interface NBAPlayerSoapService {
        /** * name = name ** date 2019/10/15 **@param NBAPlayerName
         * @return cn.forward.springboot.cxf.service.entity.NBAPlayer
         */
        @WebMethod(operationName = "getNBAPlayerByName")
        NBAPlayer getNBAPlayerByName(@WebParam(name = "NBAPlayerName") String NBAPlayerName);
    
        * date 2019/10/15 **@return java.util.List<cn.forward.springboot.cxf.service.entity.NBAPlayer>
         */
        @WebMethod
        List<NBAPlayer> getNBAPlayerList(a);
    
    }
    Copy the code

    4.NBAPlayerSoapImpl.java

    @WebService(
        targetNamespace = WsConst.NAMESPACE_URI, // The WSDL namespace
        name = "NBAPlayerSoap".PortType Name Indicates the name of the interface when the client generates code
        serviceName = "NBAPlayerSoapService".// Service name Name
        portName = "NBAPlayerPortName"./ / the port name
        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(a) {
            return generatorList();
        }
        public List<NBAPlayer> generatorList(a) {
            List<NBAPlayer> resultList = new ArrayList<>();
            NBAPlayer LBJ = new NBAPlayer();
            LBJ.setName("Lebron James");
            LBJ.setTeam(Los Angeles Lakers);
            LBJ.setTeams(Arrays.asList("Cleveland Cavaliers (2003−2010)"."Miami Heat (2010−2014)"));
            LBJ.setPosition(Position.FORWARD);
            LBJ.setDescription(LBJ.toString());
            resultList.add(LBJ);
            NBAPlayer WS = new NBAPlayer();
            WS.setName("Russell Westbrook");
            WS.setTeam("Houston Rockets");
            WS.setTeams(Arrays.asList("Oklahoma City Thunder (2008-2019)"));
            WS.setPosition(Position.SHOOTING);
            WS.setDescription(WS.toString());
            resultList.add(WS);
            returnresultList; }}Copy the code

    5.WsConst.java

    public class WsConst {
        public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice";
    }
    Copy the code

    6.CxfWebServiceConfig.java

    @Configuration
    public class CxfWebServiceConfig {
        // The core class of SpringMVC is DispatcherServlet
        // If you do not rename the bean, the original MVC will be overridden. To view the configuration class: DispatcherServletAutoConfiguration
        // One way is to change the method name or specify the bean name
        If beanName is not named cxfServletRegistration, two CXFservlets will be created.
        / / specific to view the automatic configuration class: Declaration org.. Apache CXF. Spring. The boot. The autoconfigure. CxfAutoConfiguration
        // You can also configure cxf.path to modify the access path without setting the bean
        @Bean("cxfServletRegistration")
        public ServletRegistrationBean dispatcherServlet(a) {
            // Register the servlet to block requests starting with /NBA without setting the default: /services/*
            return new ServletRegistrationBean(new CXFServlet(), "/NBA/*");
        }
        /** * declare that the business process class can also be annotated directly on the implementation class@Service
         * @author ShiFan
         */
        @Bean
        public NBAPlayerSoapService authorService(a) {
            return new NBAPlayerSoapImpl();
        }
        /** * Non-essential */
        @Bean(name = Bus.DEFAULT_BUS_ID)
        public SpringBus springBus(a) {
            SpringBus springBus = new SpringBus();
            return springBus;
        }
        /** * Publish endpoint */
        @Bean
        public Endpoint endpoint(NBAPlayerSoapService NBAPlayerSoap) {
            EndpointImpl endpoint = new EndpointImpl(springBus(), NBAPlayerSoap);
            // Publish the address
            endpoint.publish("/player");
            returnendpoint; }}Copy the code

    Notes:When configuring the ServletRegistrationBean, be careful not to set the method name or bean name to be the same as the default DispatcherServlet class, as the original MVC interface will not be used because it will be overwritten. You can change the access path by setting ServletRegistrationBean. At the same time, you need to set the bean name to cxfServletRegistration. Otherwise, multiple CXFServlets will be registered. Specific reasons can view the automatic configuration class: org.. Apache CXF. Spring. The boot. Autoconfigure. CxfAutoConfiguration.

    Therefore, you can also change the access path through the configuration item cxF. path. The default access URL is: /services

  4. Create a startup class and start the application
@SpringBootApplication
@Slf4j
public class SpringBootCxfServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootCxfServiceApplication.class, args);
		log.info("Spring - the boot - CXF - service start!"); }}Copy the code

Viewing input Logs

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 the context path '2019-10-15 15:49:17. 967 INFO - 16100 [main] F.S.C.S.S pringBootCxfServiceApplication: Started SpringBootCxfServiceApplication in 3.35seconds (JVM running for 4.454)The 15:49:17 2019-10-15. 16100-969 the INFO [main] F.S.C.S.S pringBootCxfServiceApplication: spring - the boot - CXF - service start!Copy the code
  1. test

    accesshttp://localhost:8080/NBA/player?wsdlValidation:

Client build

  1. Create a projectspring-boot-cxf-client
  2. Introducing Maven dependencies
    <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>
    Copy the code
  3. Create the WSDL file and create the related classes using the plug-in: 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>
    Copy the code

    Tip:Place the WSDL file under main/resources/ WSDL. Then run the: MVN generate-sources command to automatically create the corresponding class file. Copy the corresponding class file to the SRC/Java directory. Or you can specify the sourceRoot

  4. Create configuration classes, access classes, and so on
  • WsCont.java
    public class WsConst {
        public static final String SERVICE_ADDRESS= "http://localhost:8080/NBA/player? wsdl";
    }
    Copy the code
  • CxfClientConfig.java
    @Configuration
    public class CxfClientConfig {
        /** * By proxy **@return NBAPlayerSoap
         */
        @Bean
        public NBAPlayerSoap createAuthorPortTypeProxy(a) {
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            jaxWsProxyFactoryBean.setServiceClass(NBAPlayerSoap.class);
            jaxWsProxyFactoryBean.setAddress(WsConst.SERVICE_ADDRESS);
            return (NBAPlayerSoap) jaxWsProxyFactoryBean.create();
        }
    
        /** * Dynamic factory mode does not need to specify service interface */
        @Bean
        public Client createDynamicClient(a) {
            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(WsConst.SERVICE_ADDRESS);
            returnclient; }}Copy the code
  • NBAPlayerController.java
    @RestController
    @RequestMapping("/nba/player")
    public class NBAPlayerController {
    
        @Resource
        NBAPlayerSoap nbaPlayerSoap;
    
        /** * description Specifies the name of the player@param nbaPlayerName
         * @return cn.lqdev.webservice.NbaPlayer
         */
        @GetMapping("/getNBAPlayerByName")
        public NbaPlayer getNBAPlayerByName(@RequestParam("nbaPlayerName") String nbaPlayerName) {
            return nbaPlayerSoap.getNBAPlayerByName(nbaPlayerName);
        }
    
        /** * select * from player where player is located@return java.util.List<cn.lqdev.webservice.NbaPlayer>
         */
        @GetMapping("/getNBAPlayerList")
        public List<NbaPlayer> getNBAPlayerList(a) {
            returnnbaPlayerSoap.getNBAPlayerList(); }}Copy the code
  1. Create a startup class and test it
    @SpringBootApplication
    @Slf4j
    public class SpringBootCxfClientApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootCxfClientApplication.class, args);
            log.info("Spring - the boot - CXF - client start!"); }}Copy the code

    Access:http://localhost:8081/nba/player/getNBAPlayerByName?nbaPlayerName= lebron James

    Verification results:

    {description: lebron James is a small forward who plays for the Los Angeles Lakers. He has played for the Cleveland Cavaliers (2003−2010) and the Miami Heat (2010−2014). Name: name: position: "FORWARD", team: "Los Angeles Lakers ", teams: [" Cleveland Cavaliers (2003−2010) "," Miami Heat (2010−2014) "]}Copy the code

6. Refer to articles

  • CXF builds the WebService service
  • Spring Web Servcies integration and use

conclusion

This article is to share springBoot based on CXF WebService building process.