SpringBoot整合CXF快速实现SOAP服务

讲真,SOAP跟现在流行的RESTful WebService比起来显得很难用。冗余的XML文本信息太多,可读性差,它的请求信息有时很难手动构造,不太好调试。不过说归说,对某些企业用户来说SOAP的使用率仍然是很高的。

需求背景

接手维护的一个项目,最近客户想开放项目中的功能给第三方调用,而且接入方指定必须是SOAP接口。这项目原来的代码我看着头疼,也不想再改了,除非推倒重写。客户的需求虽然不难但要的很急,为了尽快交付就使用SpringBoot快速搭一个微服务。

开始动手

1.  .新建一个Spring Starter Project

2.  .加入cxf的maven配置

3.  <dependency>

4.  <groupId>org.apache.cxf</groupId>

5.  <artifactId>cxf-spring-boot-starter-jaxws</artifactId>

6.  <version>3.1.</version>

7.  </dependency>

编写服务代码(示例代码)

1.  @WebService(targetNamespace="http://demo.example.com/")

2.  public interface IUserService {

4.  @WebMethod

5.  User getUserById(@WebParam(name = "id") int id);

7.  @WebMethod

8.  int addUser(@WebParam(name = "user") User user);

9.  }
1.  @InInterceptors(interceptors={"com.example.demo.auth.AuthInterceptor"})

2.  @WebService(serviceName = "UserService", targetNamespace = "http://demo.example.com/", endpointInterface = "com.example.demo.soap.IUserService")

3.  @Component

4.  public class UserServiceImpl implements IUserService {

6.  private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

8.  @Autowired

9.  private IUserDAO userDAO;

11.  @Override

12.  public User getUserById(int id) {

13.  return userDAO.getUserById(id);

14.  }

16.  @Override

17.  public int addUser(User user) {

18.  logger.info("save user [" + user.getId() + "]");

19.  userDAO.addUser(user);

20.  return 0;

21.  }

22.  }

鉴权拦截器

1.  public class AuthInterceptor extends AbstractSoapInterceptor {

3.  private static final String BASIC_PREFIX = "Basic ";

4.  private static final String USERNAME = "lichmama";

5.  private static final String PASSWORD = "123456";

7.  public AuthInterceptor() {

8.  super(Phase.PRE_INVOKE);

9.  }

11.  @Override

12.  public void handleMessage(SoapMessage message) throws Fault {

13.  HttpServletRequest request = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);

14.  String auth = request.getHeader("Authorization");

15.  if (auth == null) {

16.  SOAPException exception = new SOAPException("auth failed, header [Authorization] not exists");

17.  throw new Fault(exception);

18.  }

19.  if (!auth.startsWith(BASIC_PREFIX)) {

20.  SOAPException exception = new SOAPException("auth failed, header [Authorization] is illegal");

21.  throw new Fault(exception);

22.  }

23.  String plaintext = new String(Base64.getDecoder().decode(auth.substring(BASIC_PREFIX.length())));

24.  if (StringUtils.isEmpty(plaintext) || !plaintext.contains(":")) {

25.  SOAPException exception = new SOAPException("auth failed, header [Authorization] is illegal");

26.  throw new Fault(exception);

27.  }

28.  String[] userAndPass = plaintext.split(":");

29.  String username = userAndPass[0];

30.  String password = userAndPass[1];

31.  if (!USERNAME.equals(username) || !PASSWORD.equals(password)) {

32.  SOAPException exception = new SOAPException("auth failed, username or password is incorrect");

33.  throw new Fault(exception);

34.  }

35.  }

36.  }

编写配置类

1.  @Configuration

2.  public class SoapConfig {

4.  @Autowired

5.  private IUserService userService;

7.  @Autowired

8.  @Qualifier(Bus.DEFAULT_BUS_ID)

9.  private SpringBus bus;

11.  @Bean

12.  public Endpoint endpoint() {

13.  EndpointImpl endpoint = new EndpointImpl(bus, userService);

14.  endpoint.publish("/userService");

15.  return endpoint;

16.  }

17.  }

修改 CXF 默认发布路径(application.properties)

1.  server.port=8000

2.  cxf.path=/soap

启动项目后访问 http://localhost:8000/soap/userService?wsdl

0d64b378a0d648fb7df34b45e9656c43.png

使用 SoapUI 测试一下,看上去没什么问题

18d778b7a8a0e1813852de82d24c074e.png

客户端增加对 Basic Auth 的支持:

1.  /*

2.  使用Eclipse自动生成Web Service Client,在SoapBingdingStub的createCall()方法中加入一下代码:

3.  */

5.  // basic auth

6.  _call.setProperty("javax.xml.rpc.security.auth.username", "lichmama");

7.  _call.setProperty("javax.xml.rpc.security.auth.password", "123456");

然后正常调用即可,这里提供一下自己写的 SoapClient:

1.  public class GeneralSoapClient {

3.  private String WSDL;

5.  private String namespaceURI;

7.  private String localPart;

9.  public GeneralSoapClient() {

11.  }

13.  public GeneralSoapClient(String WSDL, String namespaceURI, String localPart) {

14.  this.WSDL = WSDL;

15.  this.namespaceURI = namespaceURI;

16.  this.localPart = localPart;

17.  }

19.  public String getWSDL() {

20.  return WSDL;

21.  }

23.  public void setWSDL(String WSDL) {

24.  this.WSDL = WSDL;

25.  }

27.  public String getNamespaceURI() {

28.  return namespaceURI;

29.  }

31.  public void setNamespaceURI(String namespaceURI) {

32.  this.namespaceURI = namespaceURI;

33.  }

35.  public String getLocalPart() {

36.  return localPart;

37.  }

39.  public void setLocalPart(String localPart) {

40.  this.localPart = localPart;

41.  }

43.  private boolean requireAuth = false;

45.  private String username;

47.  private String password;

49.  public boolean isRequireAuth() {

50.  return requireAuth;

51.  }

53.  public void setRequireAuth(boolean requireAuth) {

54.  this.requireAuth = requireAuth;

55.  }

57.  public String getUsername() {

58.  return username;

59.  }

61.  public void setUsername(String username) {

62.  this.username = username;

63.  }

65.  public String getPassword() {

66.  return password;

67.  }

69.  public void setPassword(String password) {

70.  this.password = password;

71.  }

73.  /**

74.  * 创建Soap Service实例

75.  * @param serviceInterface

76.  * @return

77.  * @throws Exception

78.  */

79.  public <T> T create(Class<T> serviceInterface) throws Exception {

80.  URL url = new URL(WSDL);

81.  QName qname = new QName(namespaceURI, localPart);

82.  Service service = Service.create(url, qname);

83.  T port = service.getPort(serviceInterface);

84.  if (requireAuth) {

85.  BindingProvider prov = (BindingProvider) port;

86.  prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);

87.  prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);

88.  }

89.  return port;

90.  }

91.  }
1.  public class TestSoap {

3.  public static void main(String[] args) throws Exception {

4.  String wsdl = "http://localhost:8080/soap/userService?wsdl";

5.  String namespaceURI = "http://demo.example.com/";

6.  String localPart = "UserService";

7.  GeneralSoapClient soapClient = new GeneralSoapClient(wsdl, namespaceURI, localPart);

8.  soapClient.setRequireAuth(true);

9.  soapClient.setUsername("lichmama");

10.  soapClient.setPassword("123456");

11.  IUserService service = soapClient.create(IUserService.class);

12.  User user = service.getUserById(101);

13.  }

14.  }

最后交代一下开发环境

1.  STS 3.7.3 + SpringBoot 2.0.1 + JDK1.8

收工下班了。


作者:lichmama

来源链接:

https://www.bbsmax.com/A/gVdn0qppJW/

68b9049dd5476b00c469bfc92398803e.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值