【问题标题】:Spring Boot + Apache CXF. Publish endpoints with annotations onlySpring Boot + Apache CXF。仅发布带有注释的端点
【发布时间】:2020-08-04 08:22:31
【问题描述】:

根据官方 Apache CXF 文档,我们在 spring 中以这样的方式创建 SOAP 服务:

配置类

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;

@Configuration
public class WebServiceConfiguration {

    private static final String BINDING_URI = "http://www.w3.org/2003/05/soap/bindings/HTTP/";

    @Bean
    public ServletRegistrationBean<CXFServlet> disServlet() {
        return new ServletRegistrationBean<>(new CXFServlet(), "/soap-api/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        SpringBus bus = new SpringBus();
        bus.setProperty("org.apache.cxf.stax.maxTextLength", 1024 * 1024 * 1024);
        return bus;
    }

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

}

从 WSDL SOAP 接口生成:

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.2
 * Generated source version: 2.2
 * 
 */
@WebService(name = "UserServiceSoap", targetNamespace = "http://User.no/webservices/")
@XmlSeeAlso({ObjectFactory.class})
public interface UserServiceSoap {

    @WebMethod(operationName = "GetUser", action = "http://User.no/webservices/GetUser")
    @WebResult(name = "GetUserResult", targetNamespace = "http://User.no/webservices/")
    @RequestWrapper(localName = "UserServiceSoap", targetNamespace = "http://User.no/webservices/", className = "no.user.webservices.generated.UserServiceSoap")
    @ResponseWrapper(localName = "UserServiceSoapResponse", targetNamespace = "http://User.no/webservices/", className = "no.user.webservices.generated.UserServiceSoapResponse")
    public String getUser(@WebParam(name = "username", targetNamespace = "http://User.no/webservices/") String username);       

}

服务实现:

@Service
@WebService(
        endpointInterface = "no.altinn.webservices.generated.UserServiceSoap",
        serviceName = "UserServiceSoapService",
        targetNamespace = "http://User.no/webservices/",
        portName = "UserServiceSoapPort"
)
@BindingType("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
public class UserService implements UserServiceSoap {

    @Override
    public String getUser(String requestUsername) {
        //logic
    }

}

我想要什么?
是否有任何已经实现的方法来发布 SOAP 端点而不在 spring 配置中创建 bean。我想通过对服务实现的注释来做到这一点,例如 (@SoapEndpoint):

    @Service
    @SoapEndpoint(bindingUri = "http://www.w3.org/2003/05/soap/bindings/HTTP/", 
                  publish = "/users")                      
    @WebService(
            endpointInterface = "no.altinn.webservices.generated.UserServiceSoap",
            serviceName = "UserServiceSoapService",
            targetNamespace = "http://User.no/webservices/",
            portName = "UserServiceSoapPort"
    )
    @BindingType("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
    public class UserService implements UserServiceSoap {
    
        @Override
        public String getUser(String requestUsername) {
            //logic
        }
    
    }

【问题讨论】:

    标签: spring spring-boot web-services soap cxf


    【解决方案1】:

    解决方法:
    创建名为SoapService@SoapEndpoint的空接口并手动初始化endpoints

    SoapService 接口:

    public interface SoapService {
    
    }
    

    @SoapEndpoint 接口:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface SoapEndpoint {
    
        String bindingUri() default "http://www.w3.org/2003/05/soap/bindings/HTTP/";
        
        String publish();
    }
    

    手动初始化端点

    @Configuration
    public class WebServiceConfiguration {
    
        private static final String BINDING_URI = "http://www.w3.org/2003/05/soap/bindings/HTTP/";
    
        @Autowired
        private List<SoapService> endpoints;
    
        @Bean
        public ServletRegistrationBean<CXFServlet> disServlet() {
            return new ServletRegistrationBean<>(new CXFServlet(), "/soap-api/*");
        }
    
        @Bean(name = Bus.DEFAULT_BUS_ID)
        public SpringBus springBus() {
            SpringBus bus = new SpringBus();
            bus.setProperty("org.apache.cxf.stax.maxTextLength", 1024 * 1024 * 1024);
            return bus;
        }
    
        @PostConstruct
        public void init() {
            for (SoapService bean : endpoints) {
                if (bean.getClass().getAnnotation(SoapEndpoint.class) == null) {
                    throw new IllegalArgumentException("Missed @SoapEndpoint for " + bean.getClass().getName());
                }
                EndpointImpl endpoint = new EndpointImpl(springBus(), bean);
                endpoint.setBindingUri(BINDING_URI);
                endpoint.publish(bean.getClass().getAnnotation(SoapEndpoint.class).publish());
            }
        }
    }
    

    SoapService 添加到您的实现类中

    @Service
    @SoapEndpoint(publish = "/users")
    @WebService(endpointInterface = "no.altinn.webservices.generated.UserServiceSoap", serviceName = "UserServiceSoapService", targetNamespace = "http://User.no/webservices/", portName = "UserServiceSoapPort")
    @BindingType("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
    public class UserService implements UserServiceSoap, SoapService {
    
        @Override
        public String getUser(String requestUsername) {
            //logic
        }
    
    }
    

    --- 结果(我添加了实现OrganizationServiceSoapOrganitionService)---

    【讨论】:

    • 很遗憾没有实现类似的开箱即用的东西。但是您的解决方案非常好且简单。我已将它添加到我们的项目中。备注:需要为自定义注解添加@Inherited,以避免从代理类中获取它。
    猜你喜欢
    • 2018-01-05
    • 1970-01-01
    • 2016-10-18
    • 2019-08-06
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 2015-05-06
    相关资源
    最近更新 更多