SpringBoot整合CXF,使用webService


1、SpringBoot整合CXF,使用webService

CXF,Apache CXF = Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF,继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。Apache CXF已经是一个正式的Apache顶级项目。

1、导包

1.1、确定SpringBoot版本,才能正确导入与之版本契合的CXF包

使用IDEA打开已有的项目,显示如图所示,打开左侧Project面板;在project面板下找到如图所示的External Libraries;

在External Libraries面板下中找到如图所示的Spirng-boot:xx.xx.xxrelease,即是xx.xx.xx的版本。

或者

或者点击界面右侧的Maven Project按钮;打开dependencies后,找到如图所示的spring-boot-start,即可查看到版本。

1.2、正确引入pom.xml文件
<!--webService接口依赖-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-rt-frontend-jaxws</artifactId>
	<version>3.1.6</version>
</dependency>
<dependency>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-rt-transports-http</artifactId>
	<version>3.1.6</version>
</dependency>

2、创建实体类

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = -3628469724795296287L;
    private  int id;
    private String userName;
    private String passWord;
    private String userSex;
    private String nickName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

}

3、创建Service接口

package com.alibaba.wms.service;

import com.alibaba.wms.model.User;
import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 * name 暴露服务名称
 * targetNamespace 命名空间,一般是接口的包名反转
 */
@WebService(
        name = "UserService",
        targetNamespace = "http://service.wms.alibaba.com"
)
public interface UserService {

    /**
     * @WebMethod 标注该方法为webservice暴露的方法,用于向外公布,它修饰的方法是webservice方法,去掉也没影响的,类似一个注释信息。
     * @param userId
     * @return
     */
    @WebMethod
    User getUser(String userId);

    @WebMethod
    String getUserName( String userId);
}

4、创建接口实现类

package com.alibaba.wms.service.impl;

import com.alibaba.wms.model.User;
import com.alibaba.wms.service.UserService;
import org.springframework.stereotype.Component;
import javax.jws.WebService;
import java.util.HashMap;
import java.util.Map;

/**
 * serviceName 与接口中指定的name一致
 * targetNamespace 与接口中的命名空间一致,一般是接口的包名反转
 * endpointInterface 接口地址
 */
@WebService(serviceName="UserService",//对外发布的服务名
        targetNamespace="http://service.wms.alibaba.com",//指定你想要的名称空间,通常使用使用包名反转
        endpointInterface="com.alibaba.wms.service.UserService")
@Component
public class UserServiceImpl implements UserService {

    private Map<String, User> userMap = new HashMap<String, User>();
    public UserServiceImpl() {
        System.out.println("向实体类插入数据");
        User user = new User();
        user.setId(111);
        user.setUserName("test1");

        userMap.put(user.getId()+"", user);

        user = new User();
        user.setId(112);
        user.setUserName("test2");
        userMap.put(user.getId()+"", user);

        user = new User();
        user.setId(113);
        user.setUserName("test3");
        userMap.put(user.getId()+"", user);
    }
    @Override
    public String getUserName(String userId) {
        return "userId为:" +userMap.get( userId).getUserName();
    }
    @Override
    public User getUser(String userId) {
        System.out.println("userMap是:"+userMap);
        return userMap.get(userId);
    }

}

5、创建CXF类

package com.alibaba.wms.config;


import com.alibaba.wms.service.UserService;
import com.alibaba.wms.service.impl.UserServiceImpl;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;

@Configuration
public class CxfConfig {

    /**
     * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
     * 此方法被注释后:wsdl访问地址为http://127.0.0.1:8080/services/user?wsdl
     * 去掉注释后:wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
     * @return
     */
    @Bean
    public ServletRegistrationBean disServlet() {
        return new ServletRegistrationBean(new CXFServlet(),"/soap/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    @Autowired
    UserService userService;

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), userService);
        endpoint.publish("/UserService");
        return endpoint;
    }


   /* 非自动注入 UserService 的调用方式
    @Bean
    public UserService userService() {
        return new UserServiceImpl();
    }

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), userService());
        endpoint.publish("/UserService");
        return endpoint;
    }*/
}

6、开放访问权限

package com.alibaba.wms.config;

import com.alibaba.commons.constants.PermitAllUrl;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName:  ResourceServerConfig
 * @Description:TODO 资源服务配置
 */
@EnableResourceServer
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {


   @Override
   public void configure(HttpSecurity http) throws Exception {
      http.csrf().disable().exceptionHandling()
            .authenticationEntryPoint(
                  (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and().authorizeRequests()
            //非常重要,必须 放开权限的url,否则只有登录之后才可以访问
            .antMatchers(PermitAllUrl.permitAllUrl("/soap/**")).permitAll() 
            .anyRequest().authenticated().and().httpBasic();
   }

   @Bean
   public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
   }
}

7、页面访问

8、编写测试类

Client的pom文件引入

<dependency>              
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.5</version>
</dependency>
package com.huaxun.springboot;

import com.huaxun.springboot.service.UserService;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;


import org.apache.http.HttpEntity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

public class Test {


    public static void main(String[] args) {
        Test.main1();
        Test.main2();
    }

    /**
     * 1.代理类工厂的方式,需要拿到对方的接口地址
     */
    public static void main1() {
        try {
            // 接口地址
            String address = "http://127.0.0.1:8080/soap/user?wsdl";
            // 代理工厂
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 设置代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            // 设置接口类型
            jaxWsProxyFactoryBean.setServiceClass(UserService.class);
            // 创建一个代理接口实现
            UserService us = (UserService) jaxWsProxyFactoryBean.create();
            // 数据准备
            String userId = "111";
            // 调用代理接口的方法调用并返回结果
            String result = us.getUserName(userId);
            System.out.println("返回结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2:httpClient调用
     */
    public static void main2() {
        try {

            final String SERVER_URL = "http://127.0.0.1:8080/soap/user"; // 定义需要获取的内容来源地址

            HttpPost request = new HttpPost(SERVER_URL);
            String soapRequestData = getRequestXml();
            HttpEntity re = new StringEntity(soapRequestData, HTTP.UTF_8);
            request.setHeader("Content-Type","application/soap+xml; charset=utf-8");

            request.setEntity(re);

            HttpResponse httpResponse = new DefaultHttpClient().execute(request);


            if (httpResponse.getStatusLine().getStatusCode() ==200) {
                String xmlString = EntityUtils.toString(httpResponse.getEntity());
                String jsonString = parseXMLSTRING(xmlString);


                System.out.println("---"+jsonString);

            }


        } catch (Exception e) {


            e.printStackTrace();

        }

    }

    public static String parseXMLSTRING(String xmlString) {
        String returnJson = "";
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
            Element root = doc.getDocumentElement();//根节点
            Node node = root.getFirstChild();
            while (!node.getNodeName().equals("String")) {
                node = node.getFirstChild();
            }
            if (node.getFirstChild() != null) returnJson = node.getFirstChild().getNodeValue();
            System.out.println("获取的返回参数为:" + returnJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnJson;
    }

    private static String getRequestXml(){
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\"?>");
        sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        sb.append(" xmlns:sam=\"http://service.springboot.huaxun.com/\" ");  //前缀,这一串由服务端提供
        sb.append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"");
        sb.append(" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        sb.append("<soap:Header/>");
        sb.append("<soap:Body>");
        sb.append("<sam:getUserName>");  //“getUserName”调用方法名
        sb.append("<userId>111</userId>"); //传参,“userId”是配置在服务端的参数名称,“111”是要传入的参数值
        sb.append("</sam:getUserName>");
        sb.append("</soap:Body>");
        sb.append("</soap:Envelope>");
        return sb.toString();
    }


}

9、参考链接:

springboot整合CXF - 简书 (jianshu.com)


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM