IT/development

[spring] @RequestBody String type 받기

알 수 없는 사용자 2023. 1. 24. 17:59
반응형

목차

    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>는 아래를 참조

    [mybatis] mybatis 동적쿼리(feat. <where></where>)

    목차 mybatis Dynamic SQL 😃 계속 실수 했던 동적쿼리이다. 오늘 나는 이걸 이해 했지만 미래의 넌 또 까먹을 수 있으니 여기에 메모해 둔다. 동적 WHERE 회원 테이블에서 회원이름과 이메일의 존재에

    yaga.tistory.com

    잘 되겠지?😅 테스트를 해봤는데 아래처럼 당황스러운 결과를 확인 했다.
    클라이언트에서 호출
    이상하다. "토르"라는 사용자명은 테이블에 있는 데이터다.

    서버 쿼리 확인

    뭔가 제대로 변환되지 않은 느낌이다.
    구글링 결과 String타입의 변수 1개만 받을 경우는 아래처럼 map으로 받으면 된다.

    이제 테스트를 하면 아래처럼 결과가 정상적으로 반환된다.

    정확히 이해 하려면 스프링의 HttpMessageConvert 내부적으로 공부해야 하고 나도 정확히 이해하지 못했으니 이 곳에 기록하지 않는게 낫겠다는 판단을 했다.
    나중에 시간 내서 HttpMessageConvert에 대해서도 공부해 보자.(나한테 하는 말이다.)
    관련해서 훨씬 잘 정리된 블로그 글들이 많다.
    오늘 새로운 경험을 했으니 다음번엔 삽질 시간이 줄어들 것이다.

    반응형