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
- Create a project
spring-boot-cxf-service
- 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
- 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 - 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
- test
accesshttp://localhost:8080/NBA/player?wsdlValidation:
Client build
- Create a project
spring-boot-cxf-client
- 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
- 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 - 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
- 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.