1. 程式人生 > >WebService學習-02

WebService學習-02

續接上一篇
1.webservice服務

結構

pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wbs.springbootWebservice</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springbootwebservice</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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>
        <!-- cxf框架依賴  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.1.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.1.12</version>
        </dependency>
        <!-- cxf框架依賴  -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

2.config

package com.wbs.springbootwebservice.demo.config;

import com.wbs.springbootwebservice.demo.service.BookService;
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 {

    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        //預設servlet路徑/*
        return new ServletRegistrationBean(new CXFServlet(), "/services/*");
    }

    @Autowired
    private BookService bookService;

    @Autowired
    private Bus bus;

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

    @Bean
    public Endpoint endpoint(){
        EndpointImpl endpoint = new EndpointImpl(bus, bookService);
        endpoint.publish("/book");
        return endpoint;
    }
}

3.entity

package com.wbs.springbootwebservice.demo.entity;

import lombok.Data;

@Data
public class User {
    private String id;
    private String userName;

    public User(String id, String userName) {
        this.id = id;
        this.userName = userName;
    }
}

4.intercept

package com.wbs.springbootwebservice.demo.intercept;

import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.springframework.stereotype.Component;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.soap.SOAPException;
import java.util.List;

@Component
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private static final String USERNAME="admin";
    private static final String PASSWORD="123456";

    public AuthInterceptor() {
        //定義在哪個階段進行攔截
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(SoapMessage soapMessage) throws Fault {

        List<Header> headers = null;
        String username=null;
        String password=null;
        try {
            headers = soapMessage.getHeaders();
        } catch (Exception e) {
        }
        if (headers == null) {
            throw new Fault(new IllegalArgumentException("找不到Header,無法驗證使用者資訊"));
        }
        //獲取使用者名稱,密碼
        for (Header header : headers) {
            SoapHeader soapHeader = (SoapHeader) header;
            Element e = (Element) soapHeader.getObject();
            NodeList usernameNode = e.getElementsByTagName("username");
            NodeList pwdNode = e.getElementsByTagName("password");
            username=usernameNode.item(0).getTextContent();
            password=pwdNode.item(0).getTextContent();
            if( StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){
                throw new Fault(new IllegalArgumentException("使用者資訊為空"));
            }
        }
        //校驗使用者名稱密碼
        if(!(username.equals(USERNAME) && password.equals(PASSWORD))){
            SOAPException soapExc = new SOAPException("認證失敗");
            throw new Fault(soapExc);
        }

    }
}

1.service

package com.wbs.springbootwebservice.demo.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import java.io.UnsupportedEncodingException;

@WebService(name = "BookService", // 暴露服務名稱
        targetNamespace = "http://cxf.web.com/"// 名稱空間,一般是介面的包名倒序
)
public interface BookService {

    @WebMethod
    @WebResult(name = "String", targetNamespace = "")
    String sendMessage(@WebParam(name = "username") String username);


    @WebMethod
    String getUserName(@WebParam(name = "id") String id) throws UnsupportedEncodingException;

    @WebMethod
    String getUserInfo(String id) throws UnsupportedEncodingException;

}
package com.wbs.springbootwebservice.demo.service.impl;

import com.wbs.springbootwebservice.demo.entity.User;
import com.wbs.springbootwebservice.demo.service.BookService;
import org.springframework.stereotype.Component;

import javax.jws.WebService;
import java.io.UnsupportedEncodingException;

@WebService(serviceName = "BookService", // 與介面中指定的name一致
        targetNamespace = "http://cxf.web.com/", // 與介面中的名稱空間一致,一般是介面的包名倒
        endpointInterface = "com.wbs.springbootwebservice.demo.service.BookService"// 介面地址
)
@Component
public class BookServiceImpl implements BookService {

    @Override
    public String sendMessage(String username) {
        return "hello "+username;
    }

    @Override
    public String getUserName(String id) throws UnsupportedEncodingException {
        return "測試機";
    }

    @Override
    public String getUserInfo(String id)throws UnsupportedEncodingException  {
        System.out.println("==========================="+id);
        return new User("1","xxx").toString();
    }

}

啟動專案訪問:http://localhost:8090/services/book?wsdl

2.webservice客戶端

pom:跟上面的一樣

1.config

package com.example.client.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    Docket createRestApi() {
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<>();
        tokenPar.name("dicAccessToken").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        pars.add(tokenPar.build());
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.client.demo.controller"))
                .paths(PathSelectors.any())
                .build().globalOperationParameters(pars);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("webService服務介面")
                .description("webService服務介面")
                .version("1.0")
                .build();
    }

}

2.controller

package com.example.client.demo.controller;

import com.example.client.demo.service.impl.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class ClientController {

    //address:http://localhost:8090/services/book?wsdl

    @Autowired
    private ClientService clientService;

    @RequestMapping("/testTwo")
    public void testTwo(String memthodName, String address, HttpServletResponse response){
        String message=clientService.testTwo(memthodName,address);
        System.out.println(message);
        try {
            response.setCharacterEncoding("utf-8");

            response.setContentType("application/json;charset=utf-8");

            response.getWriter().write(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/testOne")
    public  void testOne(String address,HttpServletResponse response){
        String message= clientService.testOne(address);
        System.out.println(message);
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

3.intercept

package com.example.client.demo.intercept;

import lombok.Data;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.List;

@Component
@Data
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private String username="admin";
    private String password="123456";

    public AuthInterceptor() {
        //設定在傳送請求前階段進行攔截
        super(Phase.PREPARE_SEND);
    }

    public AuthInterceptor(String phase) {
        //設定在傳送請求前階段進行攔截
        super(Phase.PREPARE_SEND);

    }
    @Override
    public void handleMessage(SoapMessage soapMessage) throws Fault {
        List<Header> headers = soapMessage.getHeaders();
        Document doc = DOMUtils.createDocument();
        Element auth = doc.createElementNS("http://cxf.web.com/","SecurityHeader");
        Element UserName = doc.createElement("username");
        Element UserPass = doc.createElement("password");

        UserName.setTextContent(username);
        UserPass.setTextContent(password);

        auth.appendChild(UserName);
        auth.appendChild(UserPass);

        headers.add(0, new Header(new QName("SecurityHeader"),auth));
    }
}

4.service

package com.example.client.demo.service.impl;

import com.example.client.demo.intercept.AuthInterceptor;
import com.example.client.demo.service.BookService;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class ClientService {

    /**
     * 方式1:使用代理類工廠,需要拿到對方的介面
     */
    public  String testOne(String address) {
        BookService cs=null;
        try {
            // 代理工廠
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 設定代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            //新增使用者名稱密碼攔截器
            // 設定介面型別
            jaxWsProxyFactoryBean.setServiceClass(BookService.class);
            // 建立一個代理介面實現
            cs = (BookService) jaxWsProxyFactoryBean.create();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 呼叫代理介面的方法呼叫並返回結果  資料準備
        return cs.getUserInfo("1");

    }


    public String testTwo(String memthodName, String address) {
        // 建立動態客戶端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient(address);
        AuthInterceptor authInterceptor = new AuthInterceptor();
        authInterceptor.setPassword("123456");
        authInterceptor.setUsername("admin");
        // 需要密碼的情況需要加上使用者名稱和密碼
        client.getOutInterceptors().add(authInterceptor);
        Object[] objects = new Object[0];
        try {
            objects = client.invoke(memthodName, "1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objects[0].toString();
    }

}

BookService跟上面一樣

訪問swagger:http://localhost:8087/swagger-ui.html


專案程式碼