@Controller
public class RegisterController {

    @Autowired
    UserService userService;

    @InitBinder
    public void convert(WebDataBinder binder) {
        // dateformat으로 변환
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(df,false));
        binder.setValidator(new GlobalValidator());
    }

    @GetMapping("/register")
    public String register() {

        return "registerForm";
    }

    @PostMapping("/register")
    public String register(@Valid UserDto userDto, BindingResult result, Model m) {

        try {
            if(!result.hasErrors()) {
                userService.registerUser(userDto);
                return "registerInfo";
            }
            throw new Exception("Register failed");
        } catch (Exception e) {
            e.printStackTrace();
            m.addAttribute("userDto", userDto);
            m.addAttribute("msg", "REG_ERR");
            return "registerForm";
        }

    }

    @PostMapping("/idCheck")
    @ResponseBody
    public Boolean idcheck(@RequestBody String id) throws Exception {
        if(8 <= id.length() && id.length() <= 12 && userService.selectUser(id)==null) {
            return true;
        }
        return false;
    }
}

다음과 같이 InitBinder에 Validator를 등록한 경우,

 

ajax에서 POST 방식으로 데이터를 전송할 때

해당 데이터를 받는 메서드가 InitBinder가 있는 컨트롤러에 포함되어 있는 경우에

 

java.lang.illegalstateexception: invalid target for validator 라는 에러가 발생한다.

 

Validator가 POST 방식의 메서드에 적용되기 때문에,

내가 원하지 않던 메서드에도 Validator가 매개변수에 대해 검증을 시도하는 것 같아 보인다.

 

 

그러므로 id를 체크하는 메서드를 단순하게 GET 방식으로 바꾸면 해결될 줄 알았는데

Validator 관련 에러는 사라졌지만 새로운 에러가 발생했다.

 

 

WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.Boolean com.youtubealbum.myapp.controller.RegisterController.idcheck(java.lang.String) throws java.lang.Exception

 

GET 방식으로 데이터를 전송하면 쿼리스트링에 데이터가 전달되기 때문에 RequestBody로는 전달이 되지 않는것 같다.

 

 

그래서 @RequestBody 애너테이션을 빼고 @RequestParam으로 데이터를 전달 받을 수 있게 하였다.

(기본형 매개변수+String에 @RequestParam이 생략이 가능해서 생략하였음)

 

@GetMapping("/idCheck")
@ResponseBody
public Boolean idcheck(String id) throws Exception {
    if(8 <= id.length() && id.length() <= 12 && userService.selectUser(id)==null) {
        return true;
    }
    return false;
}

 

이렇게 하니까 더 이상 Validator도 이 메서드에 적용이 되지 않고

원하는 데이터도 이상없이 잘 전달되었다.

 

 

알게 된 점은

 

1. Validator는 POST 방식의 메서드에 적용된다.

2. ajax로 GET 방식을 통해 데이터를 전송하면 쿼리스트링에 데이터를 전송하기 때문에 @RequestBody로

데이터를 받을 수 없으며

대신 @RequestParam으로 데이터를 받는다. (또는 Setter가 있는 객체로 받거나)

 

(2번에 대해서는 100% 확실하진 않아서 좀 더 알아봐야 할 것 같음

다만 POST 방식으로 데이터를 전송할 때는 @RequestBody로도 이상없이 잘 전달되는거 보면

데이터가 어떻게 전달되느냐에 따라 차이가 나는 것 같음)

 

 

 

검색을 통해 ajax로 POST, GET 방식 데이터 전송에 관하여 알게된 정보로는

POST 방식으로 데이터를 전송받을 때는 Jackson2HttpMessageConverter 가 객체에 데이터를 넣어주고

GET 방식으로 데이터를 전송받을 때는 WebDataBinder를 통해 객체에 있는 Setter로 데이터가 주입이 된다고 한다

즉, POST 방식을 사용해서 데이터를 전송받을 때는 전송받는 객체에 Setter가 없어도 됨

이와 관련된 출처 -> https://jojoldu.tistory.com/407?category=635883

 

+ Recent posts