본문 바로가기

Spring/Spring

Spring+Apache cxf를 이용한 SOAP XML 통신 튜토리얼 (RESTful api? Web Services, SOAP UI)

반응형

Spring + Apache cxf로 SOAP 통신하기 

apache cxf 프레임워크를 이용하면 SOAP 통신을 할 수 있다.

apache cxf의 장점은 spring과의 연동이 가능하다는 점이다.

각설하고 다소 유행(RESTful API - JSON)에 뒤떨어지지만 산업에서 표준 문제로 사용하는 SOAP를 이용해서 XML을 만들어본다. (웹에서 OPEN API, oauth2.0 등에 사용할꺼면 json을 이용하는 RESTful API를 쓰는게 맞다)


아무것도 모르는데 일단 따라하는 tutorial

* 개발 환경

JDK1.8 / Spring 4.1.7 / apache cxf 2.6.2

 

1. spring legacy project 생성

2. apache cxf 2.6.2 버전 다운로드 (https://archive.apache.org/dist/cxf/2.6.2/)

    - 이상한거 다운로드하면 안되고 제일 밑에 apache-cxf.zip 다운로드하면 됨.

3. web services에 apache cxf 등록

이클립스 상단 메뉴에서 window > Perferences에 Web Services에 Server and Runtime 탭에서 Web service runtime을 Apache CXF 2.x로 변경

그 다음에 똑같이 Web Services에 CXF 2.x Perferences 탭에서 Add... 버튼을 누른 후 Browse를 눌러서 아까 2번에서 다운받은 apache-cxf-2.6.2.zip을 압축을 풀은 디렉토리를 잡아줌

그러면 알아서 Version이랑 Type이 생성됨. finish하고 Apply and Close

4. pom.xml에 dependency 추가

apache cxf 사용을 위한 메이븐 디펜던시 추가

5. web.xml 수정

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
        /WEB-INF/spring/appServlet/cxf-context.xml
        </param-value>
    </context-param>
    
    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- cxf servlet -->
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
    <!-- encoding filter -->
     <filter>
      <filter-name>encodingFilter</filter-name>
      <filter-class>
       org.springframework.web.filter.CharacterEncodingFilter
      </filter-class>
      <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
       <param-name>forceEncoding</param-name>
       <param-value>true</param-value>
      </init-param>
     </filter>
     
     <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
     </filter-mapping>

</web-app>

기존에 있던 servlet 지워버리고 cxf servlet 만듦

+ cxf 설정이 있는 cxf-context.xml을 연결시킴 (있다가 cxf-context.xml 만들꺼임, 이름 마음대로 해도 됨)

+ encoding 설정 (해도 되고 안 해도 됨)

6. cxf-context.xml 생성

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 

 <jaxws:endpoint 
  id="deptProcess" 
  implementor="net.jeong.pro.DeptProcessImpl" 
  address="/DeptProcess" />
   
</beans>
 

import로 cxf 자원들 불러오고 endpoint만들어서 어떤 address로 왔을 때 어떤 인터페이스에서 제공할 것인지 설정.

7. 본인 패키지에 POJO로 DI받을 것(DeptVo) 준비 (여기서는 부서정보)

package net.jeong.pro;

import java.io.Serializable;

public class DeptVo implements Serializable {
    private int deptNo;
    private String deptName;
    private String location;
    public int getDeptNo() {
        return deptNo;
    }
    public void setDeptNo(int deptNo) {
        this.deptNo = deptNo;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public String getLocation() {
        return location;
    }
    public void setLocation(String location) {
        this.location = location;
    }
}
 

딱, net.jeong.pro 패키지에 뭐 DAO니 DTO니 안만들고 바로 class만들면 됨. 제일 밑에 디렉토리 구조 있음.

(부서번호, 부서명, 위치) getter/setter

8. 인터페이스 만들기 (DeptProcess)

package net.jeong.pro;

import java.util.List;

import javax.jws.WebService;
@WebService
public interface DeptProcess {
    List<DeptVo> processDept();
}
 

,9. 인터페이스 구현하기 (DeptProcessImpl)

package net.jeong.pro;

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

import javax.jws.WebService;
@WebService(endpointInterface = "net.jeong.pro.DeptProcess")
public class DeptProcessImpl implements DeptProcess {
    //20개 부서 데이터 생성
    @Override
    public List<DeptVo> processDept() {
        System.out.println("웹서비스호출");
        List<DeptVo> deptVos = new ArrayList<DeptVo>();
        for(int i=0;i<20;i++) {
            DeptVo deptVo = new DeptVo();
            deptVo.setDeptName("부서명"+i);
            deptVo.setDeptNo(i);
            deptVo.setLocation("지역"+i);
            deptVos.add(deptVo);
        }
        return deptVos;
    }
}
 

* 프로젝트 구조

별로 건드린 것 없이 그대로 만들고 적으면 됨.


결과화면

 

localhost:8080으로 갔을 때와 localhost:8080/DeptProcess?wsdl로 갔을 때

apache cxf는 wsdl을 저절로 만들어줘서 편리

실제로 내가 작성한 내용인 부서 20개를 보려면 SOAP UI라는 TEST 프로그램을 설치해야함.

(https://www.soapui.org/downloads/latest-release.html)


SOAP UI를 통해 데이터 확인해보기

SOAP UI 사용법은 간단하게 정리함.

1. file > new SOAP Project 클릭

2. 2화면이 뜸

3. initial WSDL 란에다가 아까 우리가 확인하고 싶었던 WSDL, "localhost:8080/DeptProcess?wsdl" 이것을 복사 붙여넣기 한뒤 OK버튼

4. 왼쪽에 request 1 이런식으로 나온 것을 더블 클릭

5. 왼쪽 상단에 실행 화살표 누르면 옆에 XML이 쭉 나옴(부서명1,부서번호,지역1)

 

반응형