springboot+CXF(WebService)+aop日志拦截

1. 导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>myService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>myService</name>
    <description>myService</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.6.13</spring-boot.version>

        <cxf-spring-boot-starter.version>3.5.3</cxf-spring-boot-starter.version>
        <xstream.version>1.4.19</xstream.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-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.25</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.15</version>
        </dependency>

        <!--配置多数据源依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

        <!--json格式-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.39</version>
        </dependency>

        <!-- cxf webservice 依赖 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>${cxf-spring-boot-starter.version}</version>
        </dependency>
        <!-- xml bean 转换工具类-->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>${xstream.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.8.0</version>
        </dependency>
        <!--压缩依赖-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.21</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <artifactId>asm</artifactId>
                    <groupId>org.ow2.asm</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.15.1</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>org.example.myservice.MyServiceApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2. 写配置

spring:
  profiles: #启动运行环境
    active: dev

  # 连接池配置
  datasource:
    druid:
      initial-size: 5 #初始化连接池大小
      min-idle: 5 #最小连接数
      max-active: 20 #最大连接数
      max-wait: 60000 #最长等待时间
      #单位:ms,默认1min,两个作用
      #1.Destroy线程运行周期,每隔多久运行一次,配合min-evictable-idle-time-millis和max-evictable-idle-time-millis使用;
      #2.若testWhileIdle为true,申请连接时,若空闲时间大于time-between-eviction-runs-millis,则执行validation-query语句检测连接是否有效。
      time-between-eviction-runs-millis: 60000 #关闭空闲连接间隔(ms)
      # 单位:ms,连接保持空闲而不被驱逐的最小时间,默认30min
      #连接被destroy线程关闭条件:大于minIdle且空闲时间大于1800000
      min-evictable-idle-time-millis: 300000
      test-while-idle: true   #判断连接是否可用
      test-on-borrow: true    #在获得连接前是否要进行测试
      test-on-return: false   #在归还连接前是否要进行测试
      remove-abandoned: false #用于自动回收超时连接
      remove-abandoned-timeout: 1800
      #pool-prepared-statements: false  #不缓存pstmt,oracle可以配true
      #max-pool-prepared-statement-per-connection-size: 20 #配置pstmt缓存个数
      filters: stat, wall
      validation-query: SELECT 'x' #数据库状态检测
      aop-patterns: com.eleadmin.*.*.service.*
      #配置servlet,开启druid登录页和首页
      stat-view-servlet:
        url-pattern: /druid/*
        reset-enable: true
        login-username: admin
        login-password: admin

application-dev.yml

server: #开发环境
  port: 8082

spring:
  # 配置文件上传的大小
  servlet:
    multipart:
      max-file-size: 200MB

  jackson: #格式时间格式--在数据库添加的时候存入时间是转换后的时间
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

  datasource:
    dynamic:
      primary: db1 # 配置默认数据库
      datasource:
        db1:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/dome?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
          username: root
          password: 123456

  redis:
    host: 127.0.0.1   # Redis服务器地址
    port: 6379        # Redis服务器连接端口
    database: 0       # Redis数据库索引(默认为0)
    jedis:
      pool:
        max-active: 10  # 最大的连接数
        max-idle: 10    # 最大最小的空闲连接数
        min-idle: 0
        max-wait: -1    # 最大阻塞时间 -1 没有限制

mybatis-plus:
  #配置映射器的位置
  mapper-locations: classpath*:/mapper/**Mapper.xml
  #打印sql日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #这是因为mybatis默认开启驼峰命名法,按规则数据表中的lastName字段应对应实体类中的last_name属性,
    #而实体类中的lastName属性应对应数据表中的last_name字段。
    map-underscore-to-camel-case: true

3. cxfConfig

package org.example.myservice.config;

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.example.myservice.service.cxf.IptvUserService;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;

/**
 * cxf配置
 *
 * @author th
 * @date 2024/03/07
 */
@Configuration
public class CxfConfig {
    /**
     * iptvUser请求
     */
    @Resource
    private IptvUserService iptvUserService;

    /**
     * 暴露接口-http://127.0.0.1:8082/soap
     *
     * @return
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(
                new CXFServlet(),
                "/soap/*"
        );
    }

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


    @Bean
    public Endpoint iptvUserServiceEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), iptvUserService);
        endpoint.publish("/cxf/bossUser");
        return endpoint;
    }
}

4. 写cxf接口

IptvUserService.java

package org.example.myservice.service.cxf;

import org.example.myservice.service.cxf.impl.vo.ExecCmdResponse;
import org.example.myservice.service.cxf.impl.vo.Product;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * iptv用户服务
 *
 * @Package: org.example.myservice.service.cxf
 * @ClassName: IptvUserService
 * @作者: th
 * @创建时间: 2024/3/7 10:12
 * @描述:
 * @date 2024/03/07
 */
@WebService(targetNamespace = "http://cxf.service.myservice.example.org"// 命名空间,一般是接口的包名倒序
)
public interface IptvUserService {

    /**
     * 增加新用户,开户后用户激活
     *
     * @param BossUsercode BOSS计费账号(重庆移动使用用户手机号码作为计费账号)
     * @param Userid       业务子帐号
     * @param Password     密码
     * @param STBID        用户绑定的机顶盒ID(机顶盒32位串号)
     * @param Areacode     用户所属业务区代码省市区
     * @param Productlist  用户订购的产品列表(数组),用户开户订购的产品。重庆移动开户只携带一个基础产品。
     * @param UsergroupID  用户分组ID,用于区分用户分组。
     * @return
     */
    // WebMethod注解配置的是接口的方法名
    @WebMethod(operationName = "SubscriptionUser")
    ExecCmdResponse SubscriptionUser(@WebParam(name = "BossUsercode") String BossUsercode,
                                     @WebParam(name = "Userid") String Userid,
                                     @WebParam(name = "Password") String Password,
                                     @WebParam(name = "STBID") String STBID,
                                     @WebParam(name = "Areacode") String Areacode,
                                     @WebParam(name = "Productlist") Product Productlist,
                                     @WebParam(name = "UsergroupID") int UsergroupID
    );

    @WebMethod(operationName = "test01")
    ExecCmdResponse test01(@WebParam(name = "BossUsercode") String BossUsercode,
                           @WebParam(name = "Userid") String Useri
    );

    /**
     * 取消订阅用户
     *
     * @param userid userid
     * @param state  状态
     * @return {@link ExecCmdResponse}
     */
    @WebMethod(operationName = "UnsubscriptionUser")
    ExecCmdResponse UnsubscriptionUser(@WebParam(name = "userid") String userid,
                                       @WebParam(name = "state") String state
    );
}

IptvUserServiceImpl.java

package org.example.myservice.service.cxf.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.myservice.aspect.Logging;
import org.example.myservice.service.cxf.IptvUserService;
import org.example.myservice.service.cxf.impl.vo.ExecCmdResponse;
import org.example.myservice.service.cxf.impl.vo.Product;
import org.springframework.stereotype.Service;

import javax.jws.WebService;

/**
 * iptv用户服务实现
 *
 * @author th
 * @Package: org.example.myservice.service.cxf.impl
 * @ClassName: IptvUserServiceImpl
 * @作者: th
 * @创建时间: 2024/3/7 10:35
 * @描述:
 * @date 2024/03/07
 */
@Slf4j
@Service
@WebService(serviceName = "IptvUserService",
        targetNamespace = "http://cxf.service.myservice.example.org",
        endpointInterface = "org.example.myservice.service.cxf.IptvUserService")
public class IptvUserServiceImpl implements IptvUserService {
    @Override
    @Logging(isWebService = true)
    public ExecCmdResponse SubscriptionUser(String BossUsercode, String Userid, String Password, String STBID, String Areacode, Product Productlist, int UsergroupID) {
        log.info("SubscriptionUser: BossUsercode:{}, Userid:{}, Password:{}, STBID:{}, Areacode:{}, Productlist:{}, UsergroupID:{}", BossUsercode, Userid, Password, STBID, Areacode, Productlist, UsergroupID);

        ExecCmdResponse response = new ExecCmdResponse();
        response.setResult(0);
        response.setErrorDescription("succ");
        return response;
    }


    @Override
    public ExecCmdResponse test01(String BossUsercode, String Useri) {
        log.warn("test01: BossUsercode:{}, Useri:{}", BossUsercode, Useri);

        ExecCmdResponse response = new ExecCmdResponse();
        response.setResult(0);
        response.setErrorDescription("succ");
        return response;
    }

    @Override
    public ExecCmdResponse UnsubscriptionUser(String userid, String state) {
        log.info("UnsubscriptionUser: userid:{}, state:{}", userid, state);

        ExecCmdResponse response = new ExecCmdResponse();
        response.setResult(0);
        response.setErrorDescription("succ");
        return response;
    }
}

5. 控制层

package org.example.myservice.controller;

import org.example.myservice.client.LiveMetadataManagementClient;
import org.example.myservice.common.JsonResult;
import org.example.myservice.service.cxf.impl.vo.Product;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * <p>
 * PBOSS用户表 前端控制器
 * </p>
 *
 * @author admin
 * @since 2024-03-07 11:05:47
 */
@RestController
@RequestMapping("/bossUserEntity")
public class BossUserController {


    @RequestMapping("/get")
    public JsonResult get() {
        String url = "http://127.0.0.1:8082/soap/cxf/bossUser?wsdl";
        boolean b = false;
        try {
            b = LiveMetadataManagementClient.c1("1", url, "13912345678", "zz13912345678");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return JsonResult.ok().setData(b);
    }

    @RequestMapping("/getAdd")
    public JsonResult getAdd() {
        String url = "http://127.0.0.1:8082/soap/cxf/bossUser?wsdl";
        boolean b = false;
        try {

            Product p = new Product();
            p.setProductID("1234567890");

            b = LiveMetadataManagementClient.UserAdd(url, "13912345678", "zz13912345678", "1234567890", "机顶盒id", "502252525", p, 1);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return JsonResult.ok().setData(b);
    }

}

对应的vo

package org.example.myservice.service.cxf.impl.vo;

import javax.xml.bind.annotation.XmlElement;
import java.io.Serializable;

/**
 * 响应
 *
 * @author th
 * @date 2024/03/07
 */
public class ExecCmdResponse implements Serializable {

    private int Result;
    private String ErrorDescription = "";

    @XmlElement(name = "Result")
    public int getResult() {
        return Result;
    }

    public void setResult(int result) {
        Result = result;
    }

    @XmlElement(name = "ErrorDescription")
    public String getErrorDescription() {
        return ErrorDescription;
    }

    public void setErrorDescription(String errorDescription) {
        ErrorDescription = errorDescription;
    }

}

Product

@Data
public class Product implements Serializable {
    /**
     * OTT产品编号
     */
    private String ProductID;
}

ResultNotifyVO

package org.example.myservice.service.cxf.impl.vo;

import lombok.Data;

/**
 * @author kai
 */
@Data
public class ResultNotifyVO {

    /**
     * 接收消息结果
     * 0:成功 -1:失败
     */
    private int Result;

    /**
     * 错误信息详细描述
     */
    private String ErrorDescription;

}

6. client客户端-发送请求

package org.example.myservice.client;

import lombok.extern.slf4j.Slf4j;
import org.example.myservice.service.cxf.impl.vo.Product;
import org.example.myservice.utils.WebServiceClientUtil;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

/**
 * soap客户端
 *
 * @author wukai
 * @date 2022/7/12 14:16
 */
@Slf4j
public class LiveMetadataManagementClient {

    /**
     * 移动id-C2
     */
    public static final String ID = "CQYDCOS3";


    /**
     * U_ADD_XML格式-添加用户
     */
    public static String U_ADD_XML;
    /**
     * U_XH_XML格式-销户
     */
    public static String U_XH_XML;

    static {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        // 读取C1_REQ_XML格式
        Resource resource = resolver.getResource("classpath:cxf/User-add.xml");
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
            U_ADD_XML = bufferedReader.lines().collect(Collectors.joining());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 读取移动C1_REQ_XML格式
        resource = resolver.getResource("classpath:cxf/User-xh.xml");
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
            U_XH_XML = bufferedReader.lines().collect(Collectors.joining());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送c1请求
     *
     * @param domain       下发域-判断走向接口
     * @param url          接口地址
     * @param BossUsercode BOSS计费账号
     * @param Useri        业务子帐号
     * @return boolean
     * @throws IOException IOException
     */
    public static boolean c1(String domain, String url, String BossUsercode, String Useri) throws IOException {
        String content = String.format(
                "0".equals(domain) ? U_ADD_XML : U_XH_XML,
                BossUsercode, Useri);

        String response = WebServiceClientUtil.httpClientPost(url, content, "");
        log.info("c1反馈,domain:{},url:{},BossUsercode:{},Useri:{},response:{}", domain, url, BossUsercode, Useri, response);
        return true;
    }

    /**
     * 用户添加
     *
     * @param BossUsercode BOSS计费账号(重庆移动使用用户手机号码作为计费账号)
     * @param Userid       业务子帐号
     * @param Password     密码
     * @param STBID        用户绑定的机顶盒ID(机顶盒32位串号)
     * @param Areacode     用户所属业务区代码省市区
     * @param Productlist  用户订购的产品列表(数组),用户开户订购的产品。重庆移动开户只携带一个基础产品。
     * @param UsergroupID  用户分组ID,用于区分用户分组。
     * @param url          url
     * @return boolean
     * @throws IOException IOException
     */
    public static boolean UserAdd(String url, String BossUsercode, String Userid, String Password, String STBID, String Areacode, Product Productlist, int UsergroupID) throws IOException {
        String content = String.format(U_ADD_XML, BossUsercode, Userid, Password, STBID, Areacode, Productlist, UsergroupID);
        String response = WebServiceClientUtil.httpClientPost(url, content, "");
        log.info("c1反馈,url:{},BossUsercode:{},Userid:{},Password:{},STBID:{},Areacode:{},Productlist:{},UsergroupID:{},response:{}", url, BossUsercode, Userid, Password, STBID, Areacode, Productlist, UsergroupID, response);
        return true;
    }
    //
    // /**
    //  * 发送c2回执
    //  *
    //  * @param url         c2回执地址
    //  * @param correlateId 相关性标识
    //  * @param cspId       互相约定的上层标识
    //  * @param cmdResult   命令执行结果:0:成功 -1:通常失败 其他结果待定义
    //  */
    // public static boolean c2Notify(String url, String correlateId, String cspId, String lspId, Integer cmdResult) throws IOException {
    //     String content = String.format(C2_NOTIFY_XML, cspId, lspId, correlateId, cmdResult, "");
    //     String response = WebServiceClientUtil.httpClientPost(url, content, "");
    //     // TODO: 2022/7/4 可能需要根据播控返回的response判断是否处理成功
    //     return true;
    // }

}

7. WebServiceClientUtil

package org.example.myservice.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.http.ResponseEntity;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author kai
 */
@Slf4j
public class WebServiceClientUtil {

    /**
     * 使用apache的HttpClient发送http请求
     *
     * @param url        请求的WSDL地址(或ASMX
     * @param content    请求的完整XML报文
     * @param soapAction 命名空间+方法名, 如为SOAP1.2协议不需要此项
     * @return XML字符串
     */
    public static String httpClientPost(String url, String content, String soapAction) throws IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        // 创建Post请求
        HttpPost httpPost = new HttpPost(url);
        RequestConfig config = RequestConfig.custom()
                // 默认连接超时5s
                .setConnectionRequestTimeout(5000)
                // 请求超时5s
                .setSocketTimeout(5000)
                .build();
        httpPost.setConfig(config);

        // 将数据放入entity中
        StringEntity entity = new StringEntity(content, "UTF-8");
        httpPost.setEntity(entity);

        // 响应模型
        String result;
        CloseableHttpResponse response = null;

        try {
            // 设置请求头
            // 特别说明一下,此处为SOAP1.1协议
            // 如果用的是SOAP1.2协议,改为:"application/soap+xml;charset=UTF-8"
            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
            // 命名空间+方法名
            // 如为SOAP1.2协议不需要此项
            httpPost.setHeader("SOAPAction", soapAction);
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            log.info("发送URL为:{}", url);
            log.info("发送内容为:{}", content);
            log.info("响应ContentType为:{}", responseEntity.getContentType());
            log.info("响应状态为:{}", response.getStatusLine());
            result = EntityUtils.toString(responseEntity);
            log.info("响应内容为: {}", result);
        } finally {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        }
        return result;
    }

    /**
     * 使用Spring Boot的RestTemplate发送http请求
     *
     * @param url        请求的WSDL地址(或ASMX)
     * @param content    请求的完整XML报文
     * @param soapAction 命名空间+方法名, 如为SOAP1.2协议不需要此项
     * @return XML字符串
     */
    public static String restTemplatePost(String url, String content, String soapAction) {
        Map<String, String> headers = new HashMap<>();
        // 设置请求头
        // 特别说明一下,此处为SOAP1.1协议
        // 如果用的是SOAP1.2协议,改为:"application/soap+xml;charset=UTF-8"
        headers.put("Content-Type", "text/xml;charset=UTF-8");
        // 命名空间+方法名
        // 如为SOAP1.2协议不需要此项
        headers.put("SOAPAction", soapAction);
        ResponseEntity<String> entity = RestTemplateUtils.post(url, headers, content, String.class);
        System.out.println(entity.getStatusCode());
        System.out.println(entity.getBody());
        log.info("发送URL为:{}", url);
        log.info("发送内容为:{}", content);
        return entity.getBody();
    }
}

8. cxf.xml

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cxf="http://cxf.service.myservice.example.org">
    <soapenv:Header/>
    <soapenv:Body>
        <cxf:SubscriptionUser>
            <!--Optional:-->
            <BossUsercode>%s</BossUsercode>
            <!--Optional:-->
            <Userid>%s</Userid>
            <!--Optional:-->
            <Password>%s</Password>
            <!--Optional:-->
            <STBID>%s</STBID>
            <!--Optional:-->
            <Areacode>%s</Areacode>
            <!--Optional:-->
            <Productlist>
                <!--Optional:-->
                <productID>%s</productID>
            </Productlist>
            <UsergroupID>%s</UsergroupID>
        </cxf:SubscriptionUser>
    </soapenv:Body>
</soapenv:Envelope>

9. aop切换,注解获取日志

LoggingAspect.java

package org.example.myservice.aspect;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * webService日志方面
 *
 * @author th
 * @date 2024/03/11
 */
@Slf4j
@Aspect
@Component
public class LoggingAspect {

    /**
     * 创建环绕通知切点,切点以日志注解开启
     */
    @Pointcut("@annotation(org.example.myservice.aspect.Logging)")
    public void pointcut() {
    }

    /**
     * 织入通知
     *
     * @return
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 1.获取注解信息  pjp.getTarget().getClass().getAnnotation 无法直接获取自定义的上下文注解,需要通过执行方法获取
        // 执行方法需要通过方法签名得到方法的方法名,执行空间
        // 获取方法签名
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        // 得到执行方法
        Method method = signature.getMethod();

        Class<?> clazz = pjp.getTarget().getClass();
        Method declaredMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
        // 获取方法上的注解,存在日志注解才进行以下操作
        Logging logging = declaredMethod.getAnnotation(Logging.class);
        if (logging != null) {
            long start = System.currentTimeMillis();
            StringBuffer sb = new StringBuffer();
            // 2.如果日志注解开启webservice信息记录
            if (logging.isWebService()) {
                // 获取webservice请求信息
                WebService webService = clazz.getAnnotation(WebService.class);
                // 请求地址
                String namespace = webService.targetNamespace();
                sb.append("WebService请求地址:").append(namespace).append("/").append(webService.serviceName());
            } else {
                // http请求获取请求信息
                Object[] args = pjp.getArgs();
                for (Object arg : args) {
                    if (arg instanceof HttpServletRequest) {
                        sb.append("http请求地址:")
                                .append(((HttpServletRequest) arg).getRequestURI());
                        // .append("请求头信息:").append(((HttpServletRequest) arg).getHeader());
                    }
                }

            }
            Object[] args = pjp.getArgs();
            sb.append("; 入参:").append(JSON.toJSONString(args));
            // 3.方法处理前记录请求
            log.info(sb.toString());
            Object proceed = pjp.proceed();
            // 4.记录方法处理后结果
            log.info("耗时:{}s; 输出参数:{}, ", (System.currentTimeMillis() - start) / 1000, JSON.toJSONString(proceed));
            return proceed;
        }
        return pjp.proceed();
    }


}

注解是打在IptvUserServiceImpl 服务实现方法上的

    @Override
    @Logging(isWebService = true)
    public ExecCmdResponse SubscriptionUser(String BossUsercode, String Userid, String Password, String STBID, String Areacode, Product Productlist, int UsergroupID) {
        log.info("SubscriptionUser: BossUsercode:{}, Userid:{}, Password:{}, STBID:{}, Areacode:{}, Productlist:{}, UsergroupID:{}", BossUsercode, Userid, Password, STBID, Areacode, Productlist, UsergroupID);

        ExecCmdResponse response = new ExecCmdResponse();
        response.setResult(0);
        response.setErrorDescription("succ");
        return response;
    }

这里只是记录一下,如果有更好的方式 ,方便告知一下

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了您的问题。使用Spring BootCXF框架搭建一个Webservice服务端的步骤如下: 1. 首先,在您的项目中添加CXFSpring Boot的依赖,例如: ``` <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.3.6</version> </dependency> ``` 注意,这里使用的是CXF的JAX-WS模块,您也可以根据需要选择其他模块。 2. 接着,在您的配置文件中添加CXF的配置,例如: ``` @Configuration public class CxfConfig { @Bean public ServletRegistrationBean<CXFServlet> cxfServlet() { return new ServletRegistrationBean<>(new CXFServlet(), "/yourWebserviceUrl/*"); } @Bean(name = Bus.DEFAULT_BUS_ID) public SpringBus springBus() { return new SpringBus(); } @Bean public YourWebService yourWebService() { return new YourWebService(); } @Bean public Endpoint yourWebServiceEndpoint() { EndpointImpl endpoint = new EndpointImpl(springBus(), yourWebService()); endpoint.publish("/YourWebServiceUrl"); return endpoint; } } ``` 这里配置了CXF的Servlet,以及您自己实现的Webservice服务类和Endpoint。注意,您需要将 "/yourWebserviceUrl/" 和 "/YourWebServiceUrl" 替换为您自己的URL。 3. 最后,您可以实现您的Webservice服务类,例如: ``` @Service @WebService(serviceName = "YourWebService") public class YourWebService { @WebMethod public String hello(@WebParam(name = "name") String name) { return "Hello, " + name + "!"; } } ``` 这里实现了一个简单的hello方法,接收一个name参数并返回一个包含该参数的问候语。 完成以上步骤后,您就成功地搭建了一个基于CXFSpring BootWebservice服务端。当您在浏览器中输入"http://localhost:8080/YourWebServiceUrl?wsdl"时,您将看到您的Webservice服务的WSDL文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值