목차
spring에서 @RequestBody로 String type의 변수 받기
스프링 RestFul방식으로 클라이언트에서 데이터를 전달 받을 때 당황했던 경험이 있어 이를 기록한다.
보통 스프링에서 클라이언트에서 전달한 데이터를 Dto나 Vo등의 객체 타입으로 바인딩 시 아래처럼 객체로 전달 받도록 하면 된다.
package study.lsyrestapitest1.controller.api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.lsyrestapitest1.domain.dto.UserDto;
import study.lsyrestapitest1.service.UserService;
@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping(value = "/v1/users")
public class UserApiController {
private final UserService userService;
@GetMapping(value = "")
public Object findList(@RequestBody UserDto userDto) throws Exception {
return null;// 이건 일단 무시하자
}
}
하지만 만일 클라이언트에서 전달 받는 parameter가 여러개가 아니라 객체로 받기 애매한 경우는?
예를 들어 user_name등 1개만 전달 받는 경우, 뭔가 데이터 1개만 받기 위해 객체를 만드는 좀 애매하다는 생각이 들어 당연히 아래처럼 @RequestBody를 선언한 다음 String타입으로 userName을 받았다.
테스트를 위해 아래처럼 코드들을 작성했다.
테이블
--table create
CREATE TABLE `temp_user` (
`user_seq` int(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(30) NOT NULL COMMENT '사용자명',
`user_email` varchar(30) NOT NULL COMMENT '사용자 이메일',
`reg_date` timestamp NULL DEFAULT NULL COMMENT '대출일',
PRIMARY KEY (`user_seq`,`user_email`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--------------------------------------------------------------------------------------
--test data insert
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(1, '토르', 'thor@naver.com', '2022-12-21 22:57:07.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(2, '헐크', 'hulk@naver.com', '2022-12-21 22:57:07.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(3, '타노스', 'tanos@naver.com', '2022-12-21 22:57:07.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(4, '타노스', 'ta@naver.com', '2023-01-03 18:17:00.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(5, '루갈', 'lo@naver.com', '2023-01-03 18:22:49.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(6, '리본', 'libon@naver.com', '2023-01-03 18:25:31.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(7, '', 'libon@naver.com', '2023-01-03 18:26:02.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(8, '로키', 'libon@naver.com', '2023-01-03 18:28:13.000');
INSERT INTO reno.temp_user
(user_seq, user_name, user_email, reg_date)
VALUES(9, '테란', 'terran@naver.com', '2023-01-03 21:55:14.000');
dto
package study.lsyrestapitest1.domain.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter
@ToString
@NoArgsConstructor
public class UserDto {
private int user_seq;
private String user_name;
private String user_email;
private String reg_date;
}
controller
package study.lsyrestapitest1.controller.api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.lsyrestapitest1.service.UserService;
@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping(value = "/v1/users")
public class UserApiController {
private final UserService userService;
@GetMapping(value = "")
public Object findList(@RequestBody String userName) throws Exception {
return userService.findMembers(userName);
}
}
service
package study.lsyrestapitest1.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import study.lsyrestapitest1.domain.dto.UserDto;
import study.lsyrestapitest1.mapper.UserMapper;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserService {
private final UserMapper userMapper;
public List<UserDto> findMembers(String userName) throws Exception{
return userMapper.findMembers(userName);
}
}
mapper(interface)
package study.lsyrestapitest1.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import study.lsyrestapitest1.domain.dto.UserDto;
import java.util.List;
@Mapper @Repository
public interface UserMapper {
List<UserDto> findMembers(String userName);
}
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="study.lsyrestapitest1.mapper.UserMapper">
<select id="findMembers" parameterType="String" resultType="study.lsyrestapitest1.domain.dto.UserDto">
SELECT user_seq
, user_name
, user_email
, reg_date
FROM temp_user
<where>
<if test="userName != null and userName != ''" >user_name = #{userName}</if>
</where>
</select>
</mapper>
위에서 사용된 <where></where>는 아래를 참조
잘 되겠지?😅 테스트를 해봤는데 아래처럼 당황스러운 결과를 확인 했다.
클라이언트에서 호출
이상하다. "토르"라는 사용자명은 테이블에 있는 데이터다.
서버 쿼리 확인
뭔가 제대로 변환되지 않은 느낌이다.
구글링 결과 String타입의 변수 1개만 받을 경우는 아래처럼 map으로 받으면 된다.
이제 테스트를 하면 아래처럼 결과가 정상적으로 반환된다.
정확히 이해 하려면 스프링의 HttpMessageConvert 내부적으로 공부해야 하고 나도 정확히 이해하지 못했으니 이 곳에 기록하지 않는게 낫겠다는 판단을 했다.
나중에 시간 내서 HttpMessageConvert에 대해서도 공부해 보자.(나한테 하는 말이다.)
관련해서 훨씬 잘 정리된 블로그 글들이 많다.
오늘 새로운 경험을 했으니 다음번엔 삽질 시간이 줄어들 것이다.
'IT > development' 카테고리의 다른 글
[java] PKIX path building failed 해결방법(HTTPS 통신 에러) (2) | 2023.02.01 |
---|---|
[devTool] postman으로 파일 전송 테스트 (0) | 2023.01.30 |
[spring/mybatis] Rest API 계층구조(1:N) 객체 조회(feat .쉬운 예제) (0) | 2022.12.25 |
[springBoot/html] table값 변경 후 DB update(feat.contenteditable) (0) | 2022.12.17 |
[티스토리] 코드블럭 클립보드에 복사 추가하기(feat. clipboard.js) (0) | 2022.12.17 |