最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot集成WebService(wsdl)實(shí)踐

 更新時(shí)間:2025年09月24日 14:19:20   作者:Meta39  
文章介紹了Spring Boot項(xiàng)目中通過(guò)緩存IWebService接口實(shí)現(xiàn)類的泛型入?yún)㈩愋?減少反射調(diào)用提升性能的實(shí)現(xiàn)方案,包含依賴配置、工具類封裝、接口定義及soapUI調(diào)用參數(shù)說(shuō)明

pom.xml

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <!-- 對(duì)版本沒(méi)要求,建議跟我一樣 -->
            <version>3.4.4</version>
        </dependency>

創(chuàng)建入口

ApplicationContextUtils.java

bean調(diào)用工具

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 創(chuàng)建日期:2024-07-01
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
    //構(gòu)造函數(shù)私有化,防止其它人實(shí)例化該對(duì)象
    private ApplicationContextUtils() {
    }

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
    }

    //通過(guò)name獲取 Bean.(推薦,因?yàn)閎ean的name是唯一的,出現(xiàn)重名的bean啟動(dòng)會(huì)報(bào)錯(cuò)。)
    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    //通過(guò)class獲取Bean.(確保bean的name不會(huì)重復(fù)。因?yàn)榭赡軙?huì)出現(xiàn)在不同包的同名bean導(dǎo)致獲取到2個(gè)實(shí)例)
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    //通過(guò)name,以及Clazz返回指定的Bean(這個(gè)是最穩(wěn)妥的)
    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

}

JacksonUtils.java

Jackson 工具類

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

/**
 * jackson 工具類
 */
public abstract class JacksonUtils {
    public static final ObjectMapper JSON = new ObjectMapper();
    public static final ObjectMapper XML = new XmlMapper();

    static {
        // json 配置
        JSON.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        JSON.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        JSON.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        JSON.registerModule(new JavaTimeModule());//處理java8新日期時(shí)間類型
        // xml 配置
        XML.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        XML.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        XML.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        XML.registerModule(new JavaTimeModule());//處理java8新日期時(shí)間類型
    }

}

IWebService.java

統(tǒng)一入口

/**
 * 統(tǒng)一 post 調(diào)用
 * 創(chuàng)建日期:2024-07-01
 */
public interface IWebService<T> {

    Object handle(T req);

}

WebServiceEntry.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

/**
 * 創(chuàng)建日期:2024-07-01
 */
@Slf4j
@Service
@WebService
public class WebServiceEntry {

    /**
     * 通過(guò)實(shí)現(xiàn)了 IWebService 接口的 bean name 反射調(diào)用 handle 方法
     *
     * @param service   bean name
     * @param parameter XML 字符串請(qǐng)求參數(shù)
     */
    @WebMethod
    @SuppressWarnings("unchecked")
    public <T> String invoke(@WebParam(name = "service") String service, @WebParam(name = "parameter") String parameter) throws JsonProcessingException {
        IWebService<T> webService = (IWebService<T>) ApplicationContextUtils.getBean(service);

        // 通過(guò)緩存獲取 IWebService 實(shí)現(xiàn)類的 handle 函數(shù)泛型類型入?yún)?,這樣就不用每次請(qǐng)求都通過(guò)反射去獲取入?yún)?,提升了程序性能?
        Class<T> parameterType = (Class<T>) WebServiceTypeCache.getParameterType(service);
        // 使用 Jackson-XML 將 XML 字符串轉(zhuǎn)換為 Java 對(duì)象
        T reqObject = JacksonUtils.XML.readValue(parameter, parameterType);

        R<?> r;
        try {
            r = R.ok(webService.handle(reqObject));
        } catch (Exception e) {
            String message = e.getMessage();
            log.error(message, e);
            r = R.err(message);
        }
        return JacksonUtils.XML.writeValueAsString(r);
    }

}

WebServiceTypeCache.java

啟動(dòng)的時(shí)候把 IWebService實(shí)現(xiàn)類 handle函數(shù)的泛型入?yún)懭刖彺?,在?qǐng)求的時(shí)候直接通過(guò)緩存獲取泛型入?yún)⒌念愋?,減少每次請(qǐng)求的時(shí)候都使用反射獲取泛型入?yún)ⅲ嵘绦蛐阅堋?/p>

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * 啟動(dòng)的時(shí)候把 IWebService實(shí)現(xiàn)類 handle函數(shù)的泛型入?yún)懭刖彺?,在?qǐng)求的時(shí)候直接通過(guò)緩存獲取泛型入?yún)⒌念愋停?
 * 減少每次請(qǐng)求的時(shí)候都使用反射獲取泛型入?yún)?,提升程序性能?
 *
 * @since 2024-08-09
 */
@Component
public class WebServiceTypeCache implements ApplicationRunner {
    /**
     * 只能在啟動(dòng)的時(shí)候 put,運(yùn)行的時(shí)候 get。不能在運(yùn)行的時(shí)候 put,因?yàn)?HashMap 不是線程安全的。
     */
    private static final Map<String, Class<?>> typeCache = new HashMap<>();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Map<String, IWebService> beans = ApplicationContextUtils.getBeansOfType(IWebService.class);
        //循環(huán)map,forEach(key,value) 是最現(xiàn)代的方式,使用起來(lái)簡(jiǎn)潔明了。也可以用 for (Map.Entry<String, IWebService> entry : beans.entrySet()){}。
        beans.forEach((bean, type) -> {
            // AopProxyUtils.ultimateTargetClass 解決Spring Boot 使用 @Transactional 事務(wù)注解的問(wèn)題。
            Class<?> beanClass = AopProxyUtils.ultimateTargetClass(type);
            // 獲取 IWebService 實(shí)現(xiàn)類的泛型類型
            Type[] genericInterfaces = beanClass.getGenericInterfaces();
            for (Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

                    if (actualTypeArguments.length > 0) {
                        Class<?> parameterType = (Class<?>) actualTypeArguments[0];
                        //把泛型入?yún)⒎湃刖彺?。防止每次?qǐng)求都通過(guò)反射獲取入?yún)?,影響程序性能?
                        typeCache.put(bean, parameterType);
                    }
                }
            }
        });
    }

    /**
     * 通過(guò)緩存獲取 IWebService 實(shí)現(xiàn)類 handle 函數(shù)的 泛型入?yún)?
     *
     * @param serviceName IWebService實(shí)現(xiàn)類的 bean name
     */
    public static Class<?> getParameterType(String serviceName) {
        return typeCache.get(serviceName);
    }

}

WebServiceConfig.java

配置類

有些依賴千萬(wàn)不要導(dǎo)錯(cuò),所以我依賴都粘貼進(jìn)來(lái)了。防止導(dǎo)錯(cuò)包。

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

import javax.xml.ws.Endpoint;

/**
 * 創(chuàng)建日期:2024-07-01
 */
@Configuration
public class WebServiceConfig {

    @Bean(name = "cxfServlet")
    public ServletRegistrationBean<?> cxfServlet() {
        //urlMappings默認(rèn)是:services
        return new ServletRegistrationBean<>(new CXFServlet(), "/services/*");
    }

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

    @Bean
    public Endpoint helloServiceEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), new WebServiceEntry());
        //services后面的uri地址
        endpoint.publish("/WebServiceEntry");
        return endpoint;
    }

}

WebMvcConfig.java

web的配置類,因?yàn)樵黾恿藊ml依賴,springboot會(huì)默認(rèn)把json放到xml后面,因此要手動(dòng)改回默認(rèn)json。

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        //引入 jackson-dataformat-xml 后,原本默認(rèn)返回json變成了默認(rèn)返回xml。因此這里要設(shè)置默認(rèn)返回json
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
    }

}

實(shí)現(xiàn)IWebService接口

如:WebServiceImpl

@Service("Hello")
public class Hello implements IWebService<HelloReq> {

    @Override
    public HelloRes handle(HelloReq req) {
        String name = req.getName();
        List<Work> works = req.getWorks();

        if (!StringUtils.hasText(name)) {
            throw new RuntimeException("Name 不能為空");
        }
        if (!CollectionUtils.isEmpty(works)) {
            for (Work work : works) {
                String workName = work.getWorkName();
                log.info("workName={}", workName);
            }
        }

        HelloRes res = new HelloRes();
        res.setName(name);
        res.setAge(18);
        return res;
    }

}

HelloReq.java

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;

import java.util.List;

@Data
@JacksonXmlRootElement(localName = "Params")
public class HelloReq {

    @JacksonXmlProperty(localName = "Name")
    private String name;

    @JacksonXmlElementWrapper(localName = "Works")
    @JacksonXmlProperty(localName = "Work")
    private List<Work> works;

}

HelloRes.java

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import lombok.Data;

@Data
public class HelloRes {

    @JacksonXmlProperty(localName = "Name")
    private String name;

    @JacksonXmlProperty(localName = "Age")
    private Integer age;

}

Work.java

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;

@Data
@JacksonXmlRootElement(localName = "Work")
public class Work {

    @JacksonXmlProperty(localName = "WorkName")
    private String workName;

}

統(tǒng)一返回類

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 統(tǒng)一返回類
 * 創(chuàng)建日期:2024-07-01
 */
@Data
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@JacksonXmlRootElement(localName = "R")
public class R<T> {
    @JacksonXmlProperty(localName = "Code")
    private Integer code;
    @JacksonXmlProperty(localName = "Message")
    private String message;
    @JacksonXmlProperty(localName = "Data")
    private T data;

    public static <T> R<T> ok() {
        return ok(null);
    }

    public static <T> R<T> ok(T data) {
        return new R<>(200, "success", data);
    }

    public static <T> R<T> err(String message) {
        return err(400, message);
    }

    public static <T> R<T> err(Integer code, String message) {
        return new R<>(code, message, null);
    }

}

啟動(dòng)SpringBoot

訪問(wèn)

http://localhost:8080/services/WebServiceEntry?wsdl
  • 會(huì)出現(xiàn)如下所示界面

用soapUI去調(diào)用接口

ws = "http://ws.bsjkt.bsoft.com/"這里每個(gè)人可能不一樣
service = bean name
parameter = XML 請(qǐng)求參數(shù)
  • 入?yún)ⅲ?/strong>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.springbootwebservicedemo.fu.com/">
    <soapenv:Header/>
    <soapenv:Body>
        <ws:invoke>
            <service>Hello</service>
            <parameter>
                <![CDATA[
            <Params><Name>哈哈</Name><Works><Work><WorkName>Java</WorkName></Work>
                </Works>
            </Params>
        ]]>
    </parameter>
</ws:invoke>
</soapenv:Body>
</soapenv:Envelope>
  • 出參:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:invokeResponse xmlns:ns2="http://ws.springbootwebservicedemo.fu.com/">
            <return><R><Code>200</Code><Message>success</Message><Data><Name>哈哈</Name><Age>18</Age></Data></R></return>
        </ns2:invokeResponse>
    </soap:Body>
</soap:Envelope>

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis各種查詢接口使用詳解

    Mybatis各種查詢接口使用詳解

    這篇文章主要介紹了Mybatis各種查詢接口使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-11-11
  • java 讀取zip文件的兩種方式示例詳解

    java 讀取zip文件的兩種方式示例詳解

    ZIP(壓縮文件)是一種常見(jiàn)的文件格式,在Java中可以使用java.util.zip包提供的API來(lái)讀取和處理ZIP文件,本文將介紹如何使用Java讀取ZIP文件,并提供代碼示例,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Mybatis-plus多數(shù)據(jù)源配置的兩種方式總結(jié)

    Mybatis-plus多數(shù)據(jù)源配置的兩種方式總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Mybatis-plus中多數(shù)據(jù)源配置的兩種方式,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-10-10
  • Idea為java程序添加啟動(dòng)參數(shù)(含:VM?options、Program?arguments、Environment?variable)

    Idea為java程序添加啟動(dòng)參數(shù)(含:VM?options、Program?arguments、Environme

    設(shè)置啟動(dòng)參數(shù)的意義就是當(dāng)啟動(dòng)程序時(shí),程序會(huì)優(yōu)先讀取idea的配置參數(shù),這樣就可以不用修改配置文件,下面這篇文章主要給大家介紹了關(guān)于Idea為java程序添加啟動(dòng)參數(shù)(含:VM?options、Program?arguments、Environment?variable)的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • SpringBoot+Redis使用AOP防止重復(fù)提交的實(shí)現(xiàn)

    SpringBoot+Redis使用AOP防止重復(fù)提交的實(shí)現(xiàn)

    本文主要介紹了SpringBoot+Redis使用AOP防止重復(fù)提交的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • java程序打包成exe與jar的圖文教程

    java程序打包成exe與jar的圖文教程

    這篇文章主要介紹了java程序打包成exe與jar的圖文教程,有需要的朋友可以參考一下
    2014-01-01
  • JAVA CountDownLatch與thread-join()的區(qū)別解析

    JAVA CountDownLatch與thread-join()的區(qū)別解析

    這篇文章主要介紹了JAVA CountDownLatch與thread-join()的區(qū)別解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Mybatis框架之工廠模式(Factory Pattern)

    Mybatis框架之工廠模式(Factory Pattern)

    MyBatis中使用工廠模式來(lái)管理和創(chuàng)建SqlSession對(duì)象,從而簡(jiǎn)化數(shù)據(jù)庫(kù)訪問(wèn)的配置和管理過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • 基于JVM 中常見(jiàn)垃圾收集算法介紹

    基于JVM 中常見(jiàn)垃圾收集算法介紹

    下面小編就為大家分享一篇基于JVM 中常見(jiàn)垃圾收集算法介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示

    深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示

    堆排序基于二叉堆結(jié)構(gòu)即完全二叉樹(shù),可利用最大堆和最小堆的組建方式來(lái)進(jìn)行排序,這里就來(lái)深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示
    2016-06-06

最新評(píng)論

灵宝市| 洛阳市| 东海县| 长治县| 洪雅县| 台南市| 内乡县| 寻乌县| 上杭县| 六枝特区| 青岛市| 封开县| 武威市| 镇原县| 南郑县| 察哈| 格尔木市| 巴里| 富宁县| 石嘴山市| 紫金县| 建阳市| 卓资县| 措勤县| 靖西县| 调兵山市| 福海县| 巴楚县| 巢湖市| 同德县| 南平市| 娱乐| 田阳县| 扎鲁特旗| 江永县| 喀什市| 武夷山市| 巍山| 泗洪县| 红安县| 潞西市|