SpringBoot使用cxf框架开发WebServices以及配置安全验证机制

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

目前为止cxf不支持较新的SpringBoot;支持版本为 ( SpringBoot版本 >= 1.5.0 and < 2.1.0.M1 )

服务端工程

配置 build.gradle :

    compile 'org.apache.cxf:cxf-spring-boot-starter-jaxrs:3.2.5'
    // https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxws
    compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxws', version: '3.2.5'
  // https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http
    compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version: '3.2.5'
  // https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http
    compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version: '3.2.5'

工程结构如下
在这里插入图片描述

服务接口的实现

package cn.cxfdemo.WebServices;

import javax.jws.WebMethod;
import javax.jws.WebService;
import java.util.List;

@WebService
public interface SaySomeThing {
    @WebMethod
    String getOne();
    @WebMethod
    List<String> getMultil();
    @WebMethod
    String getOneById(Integer id);
}

服务接口实现类

package cn.cxfdemo.WebServices;

import javax.jws.WebService;
import java.util.ArrayList;
import java.util.List;

/* 接口实现类名称前的注解targetNamespace是当前类实现接口所在包名称的反序(加上反斜线),endpointInterface是当前需要实现接口的全称; */

@WebService(targetNamespace = "http://WebServices.cxfdemo.cn/",endpointInterface = "cn.cxfdemo.WebServices.SaySomeThing")
public class SaySomeThingImpl implements SaySomeThing{

    @Override
    public String getOne() {
        return "this is a person";
    }

    @Override
    public List<String> getMultil() {
        List<String> results = new ArrayList<>();
        results.add("jack");
        results.add("willin");
        return results;
    }

    @Override
    public String getOneById(Integer id) {
        String result = "";
        switch (id){
            case 1 :{
                result = "first";
            }break;
            case 2:{
                result = "second";
            }break;
            default:{
                result = "other";
            }
        }
        return result;
    }
}

在这里插入图片描述

服务发布类

package cn.cxfdemo.WebServices;

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 WebServiceConfig {
    @Bean
    public ServletRegistrationBean dispatcherServlet(){
        return new ServletRegistrationBean(new CXFServlet(),"/WebServices/*");//发布服务名称
    }

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

    @Autowired
    private Bus bus;
    @Bean
    public SaySomeThing saySomeThingService()
    {
        return  new SaySomeThingImpl();
    }
    
    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint=new EndpointImpl(springBus(), new SaySomeThingImpl());//绑定要发布的服务
        endpoint.publish("/user"); //显示要发布的名称
        return endpoint;
    }
}

启动服务端

在这里插入图片描述
这样就完成了服务端的制作。
如果需要发布多个webservice,需要配置多个Config实现类文件;

客户端工程

生成客户端代码

CXF提供了根据WSDL生成客户端代码的命令wsdl2java.exe 。它是根据jdk1.7生成的本地代码,所以,有可能需要对生成的代码做一点点修改。

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

下载二进制压缩包;
解压后
在这里插入图片描述
有些朋友在这里给wsdl2java设置环境变量方便使用命令,其实不经常使用这个的话就没必要了。

C:\Users\Administrator\Downloads\apache-cxf-3.3.2\apache-cxf-3.3.2\bin>wsdl2java -d E:\\Youxun -client -impl -p cn.cxfclientdem
calhost:8080/WebServices/user?wsdl

在这里插入图片描述
特别注意一点:在使用wsdl2java生成客户端代码时的包路径和一定要和你的客户端工程一致;不然会出现“ServiceConstructionException“错误
参数 -p 指定包路径

在这里插入图片描述
生成的客户端代码:
在这里插入图片描述
附wsdl2java用法:

wsdl2java -p com -d D:\src -all xx.wsdl
-p 指定其wsdl的命名空间,也就是要生成代码的包名:
-d 指定要产生代码所在目录
-client 生成客户端测试web service的代码
-server 生成服务器启动web service的代码
-impl 生成web service的实现代码
-ant 生成build.xml文件
-all 生成所有开始端点代码:types,service proxy,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file.

编写客户端代码

build.gradle 添加依赖与服务端一致

将wsdl2java生成的代码放到工程里
在这里插入图片描述

客户端调用代码

package cn.cxfclientdemo.Controller;

import cn.cxfclientdemo.WebServices.SaySomeThing;
import cn.cxfclientdemo.WebServices.SaySomeThingImplService;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
public class AccessWSController {
// 第一种调用方式:动态调用
    @RequestMapping("/one")
    public String getOneProc(){
        JaxWsDynamicClientFactory dcflient= JaxWsDynamicClientFactory.newInstance();
        Client client=dcflient.createClient("http://localhost:8080/WebServices/user?wsdl");
        try {
            Object[] results= client.invoke("getOne", "");
            return results[0].toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
// 调用方式二,通过接口协议获取数据类型
    @RequestMapping("/multi")
    public List<String> getmulti(){
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean=new JaxWsProxyFactoryBean();
        jaxWsProxyFactoryBean.setAddress("http://localhost:8080/WebServices/user?wsdl");
        jaxWsProxyFactoryBean.setServiceClass(SaySomeThing.class);

        SaySomeThing saySomeThing=(SaySomeThing) jaxWsProxyFactoryBean.create();

        List<String> results = saySomeThing.getMultil();
        results.forEach((i)->{
            System.out.println(i);
        });
        return results;
    }

// 调用方式三,通过接口协议获取数据类型,设置链接超时和响应时间
    @RequestMapping("/byid")
    public String getmulti(Integer id){
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean=new JaxWsProxyFactoryBean();
        jaxWsProxyFactoryBean.setAddress("http://localhost:8080/WebServices/user?wsdl");
        jaxWsProxyFactoryBean.setServiceClass(SaySomeThing.class);

        SaySomeThing saySomeThing=(SaySomeThing) jaxWsProxyFactoryBean.create();

        Client proxy= ClientProxy.getClient(saySomeThing);
        HTTPConduit conduit=(HTTPConduit)proxy.getConduit();
        HTTPClientPolicy policy=new HTTPClientPolicy();
        policy.setConnectionTimeout(1000);
        policy.setReceiveTimeout(1000);
        conduit.setClient(policy);

        String results = saySomeThing.getOneById(id);
        return results;
    }
}

因为我的这个服务端和客户端运行在一台机器上为了避免端口号冲突,把客户端的端口改为8081

测试客户端

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ok,三个方法都成功运行了。

给WebServices增加安全方案

第一种:在调用API时增加一两个参数验证用户身份;
public Json wsFunc(param , userid , password);

第二种:使用ws-security框架,网上不少的关于此类框架的资料我就不在这赘述了。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值