SpringFramework/RestAPI

[ REST API] REST클라이언트 프로그램을 통한 (클라이언트 → 서버) JSON형태 전송 ' @ResponseBody '

유혁스쿨 2020. 9. 8. 23:36
728x90
반응형

클라이언트 에서 서버에게 JSON데이터 형태로 데이터전송하기.

 

REST방식은 다양한 디바이스 장치로부터 서버에 데이터와 작업을 요청하고, 결과를 받는다는 점에서 유용하지만,
일반적인 웹 페이지와는 달리 화면을 제작하지 않는 형태로 처리되기 때문에, 브라우저로 결과를 체크할수가 없습니다.

최근에는 여러 종류의 REST클라이언트 테스트 프로그램이 존재합니다. 

좀더 쉽게 결과를 테스트하기 위해서 크롬 브라우저의 앱으로 존재하는  Advanced REST Client나  PostMan등의 프로그램을 사용하여 테스트를 할 수 있습니다.


PostMan 프로그램을 사용하여 클라이언트로부터 JSON데이터를 받은후 DB에 저장하는 과정을 포스팅 하겠습니다.

 

구글에 POSTMAN검색후 64비트 다운로드를 받으신 후 실행시켰을때 로그인을 하라는 메시지가 뜨는데 무시하시고

상단의 file탭을 누르신다음 closewindow를 눌러줍니다.

 

POSTMAN 프로그램 실행 사진

 

 

create table mvc_user(
	account varchar2(80) primary key, --계정 정보 id
	password varchar2(80) not null,
	name varchar2(100) not null,
	reg_date date
); 

테이블을 구축하고 VO클래스를 생성하여 각 컬럼에 맞는 필드선언과, Setter Getter메서드를 오버라이딩해줍니다.

public class UserVO {
	private String account;
	private String password;
	private String name;
	private Date regDate;
	
    /*(setter,getter,toString() 생성코드 생략)*/
	
}

 

Mapper xml파일 생성및 쿼리문을 구현 합니다

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.spring.mvc.user.repository.IUserMapper">
	
    <resultMap type="com.spring.mvc.user.model.UserVO" id="userMap">
        <result property="account" column="account"/>
        <result property="password" column="password"/>
        <result property="name" column="name"/>
        <result property="regDate" column="reg_date"/>
    </resultMap>
	
    <!-- 회원가입 SQL -->
    <insert id="register">
        INSERT INTO mvc_user
        (account,password,name,reg_date) 
        values (#{account},#{password},#{name},sysdate)
    </insert>
	
    <!-- 회원 삭제 -->
    <delete id="delete">
        DELETE FROM mvc_user
        WHERE account=#{account}
    </delete>
    <!-- 회원 정보 -->
    <select id="selectOne" resultMap="userMap">
        SELECT * FROM mvc_user
        WHERE account=#{account}
    </select>
    <!-- 회원 목록 -->
    <select id="selectAll" resultMap="userMap">
        SELECT * FROM mvc_user 
    </select>
	
</mapper>

! 데이터 수신 테스트 본격 시작 !

 

클라이언트로부터 JSON 데이터를 받아 컨트롤러 메서드를 구현해보겠습니다

RestAPI는 컨트롤러만 일반방식에서 Rest방식으로 체인지될분 나머지 서비스나 레포지토리는 변하지 않습니다.

@Controller 
@RequestMapping("/user")
public class UserController {
	
    @Autowired
    private IUserService service;
	
    @PostMapping("/")
    public String register(@RequestBody UserVO user) {
        System.out.println("/user/ POST 요청 방식!");
        System.out.println("param : "+user);		
        service.register(user);
        return "joinSuccess";
    }
    
//	@RequestMapping(value="/", method=RequestMethod.DELETE) 
    @DeleteMapping("/{account}")
    public String delete(@PathVariable String account) {
        service.delete(account);		
        return "delSuccess";
    }
	
    @GetMapping("/{account}")
    public UserVO selectOne(@PathVariable String account) {				
        UserVO user = service.selectOne(account);		
        return user;
    }
	
    @GetMapping("/")
    public List<UserVO> selectAll() {				
        List<UserVO> ulist = service.selectAll();
        return ulist;
    }
}

 

입력 수정 삭제 조회 각각 REST API 전송방식에 맞는 메서드 전송방식을

POST, PUT, DELETE, GET으로 지정해줍니다.

 

 

 

[ 입력 Insert - POST ] 클라이언트로부터 수신

@RestController
@RequestMapping("/user")
public class UserController {
	
    @Autowired
    private IUserService service;
	
    @PostMapping("/") 
    public String register(UserVO user) {
        System.out.println("/user/ POST 요청 방식!");
        System.out.println("param : "+user);
		
        service.register(user);
        return "joinSuccess";
    }
}

REST API에서는 입력을 POST방식으로 합니다. 그러므로 메서드 요청방식이 POST 인 @PostMapping 어노테이션을 선언해줍니다.

 

컨트롤러 입력 기능 로직을 구현 한 후 POSTMAN을 통해 작업을 수행해 줄 uri와 전송할 데이터를 작성하여 데이터를 보냅니다.

동그라미 친 부분을 메서드의 방식에 맞는 POST선택, 데이터를 받는 메서드의 uri주소 기입후 바로아래에서 Body를 선택한 후 라디오버튼에서row를 체크, 우측에서 JSON을 선택한 후에

각 컬럼에 넣을 데이터들을 JSON데이터 형태로 작성한 후 실행합니다.

 

 

정상적으로 실행 되지 않고브라우저에 Status 500 Internal Server Error 가 발생하면서

 Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='account', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #1 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 부적합한 열 유형: 1111

라는 오류메시지를 빵빵 띄웁니다.

 

 

UserVO객체에 값이 하나도 들어가지 않음.

콘솔창에 객체에 값이 정상적으로 저장되었는지 출력하는 로그를 확인하면 값이 모두 null값인 상태입니다.

 

 

오류의 이유는 이렇습니다.

public String register(UserVO user) {

RestController에서 메서드의 매개변수로 UserVO user 라는건
자바 유즈빈과의 통신. 즉, 클라이언트에서 폼데이터 즉, input같은걸로 보낼때에만 읽어들일수 잇습니다.

POSTMAN 클라이언트를 통해 body에 담아서보냈습니다. 여기서 body라는것은 requestBody입니다. 요청바디인 것이죠.

 

따라서 POSTMAN 클라이언트로부터 바디에 담긴 데이터를 서버로 받기 위해서는   

@RequestBody

서버측 컨트롤러 메서드에 @RequestBody라는 어노테이션을 추가해야 합니다.

public String register(@RequestBody UserVO user) {
@RestController
@RequestMapping("/user")
public class UserController {
	
    @Autowired
    private IUserService service;
	
    @PostMapping("/") 
    public String register(@RequestBody UserVO user) {
        System.out.println("/user/ POST 요청 방식!");
        System.out.println("param : "+user);
		
        service.register(user);
        return "joinSuccess";
    }
}

Status 200 OK라는 전송 성공 코드와 함께 메서드의 반환문자열 joinSuccess를 띄워줍니다

전송에 성공 했으며 DB에도 값이 들어왔습니다.

 

 

 

[ 수정 삭제 조회 ] 클라이언트로부터 수신

수정 - PUT

삭제 - DELETE

조회 - GET

@RestController //rest API구축을 위해 @ResponseBody를 상속받는 RestController로 등록
@RequestMapping("/user")
public class UserController {
	
    @Autowired
    private IUserService service;
	
    //회원 삭제 요청 처리
    @DeleteMapping("/{account}")
    public String delete(@PathVariable String account) {
        service.delete(account);		
        return "delSuccess";
    }
    //회원 조회 요청 처리
    @GetMapping("/{account}")
    public UserVO selectOne(@PathVariable String account) {
				
        UserVO user = service.selectOne(account);		
        return user;
	}
	//회원 목록 요청 처리
    @GetMapping("/")
    public List<UserVO> selectAll() {
				
        List<UserVO> ulist = service.selectAll();
        return ulist;
    }
}

 

 

[ DELETE ] 삭제 요청을 받을 메서드입니다.

    //회원 삭제 요청 처리
    @DeleteMapping("/{account}")
    public String delete(@PathVariable String account) {
        service.delete(account);		
        return "delSuccess";
}

DeleteMapping 어노테이션을 선언하고 기존 uri경로에 작업의 기준이 되는 전달인자를 받을수 있도록 새로운 uri /{account}를 지정해줍니다

DELETE방식을 체크하고 uri path에 작업의 기준이 될 account 값을 입력해주고 Send 요청을 보냅니다.

 

200K 요청 성공 사인과 삭제메시지 반환성공

바로 Select 쿼리문을 통해 삭제수행에 대한 결과를 확인을 해볼수 있겠으나, 생략 후 이어서 목록조회를 수행함으로써 이전 DELETE작업의 성공유무까지 함께 확인해 보도록 하겠습니다.

 

 

 

[ SELECT ] 목록 요청을 받을 메서드입니다.

    @GetMapping("/")
    public List<UserVO> selectAll() {
				
        List<UserVO> ulist = service.selectAll();
        return ulist;
    }

 

삭제한 aaa1234에 대한 정보를 제외하고, 모든 목록을 가져오는것에 성공했습니다

이것을 통해 DELETE도 성공한것이 확인이됩니다.

 

여기서 집고 넘어가야할 것은 현재 목록을 조회하는 uri가 입력할때의 uri와 동일합니다.

동일한 uri임에도 서로 다른 작업을 담당하는 각각의 메서드가 따로 호출된 이유는 메서드 요청방식이 달랐기 때문입니다.

 

 

동일한 uri에 동일한 GET방식의 메서드요청방식을 사용할때 또 다른 작업을 수행하는 예를 보여드리겠습니다.

    //회원 정보 요청 처리
    @GetMapping("/{account}")
    public UserVO selectOne(@PathVariable String account) {
				
        UserVO user = service.selectOne(account);		
        return user;
    }

uri에 pathVariable처리를 해준다면 동일 uri이후 추가uri가 들어왔을때 핸들러매핑이 메서드를 찾아주게 될 것입니다.

 

 

 

 

 

 

포스팅을 마치겠습니다. 감사합니다.

 

728x90
반응형