2015년 7월 24일 금요일

신입SW인력을 위한 실전 자바(Java) 스프링(Spring) 동영상과정 12,13,15_컨트롤러 작성_form에서 데이터 받기, 데이터 검증

이 게시물은
http://www.wiz.center/242
http://www.wiz.center/243
http://www.wiz.center/245

해당 링크를 청취하고 작성한 글입니다.

본인 이해도 확인을 위해서 작성한 것이니
스프링에 대해서 알고 있다면 쑥 훝어보고 끝내시고

좀 깊게 알고 싶다면 위의 링크부터 시작해서
총 30개 강의로 이루어진 스프링 과정을 청취하세요

1. 컨트롤러 클래스 작성

src 밑에 클래스를 작성 (설정파일에 명시된 패키지 밑에)
   작성된 클래스에 @Controller 를 명시

@Controller
public class MyController {
.......


2. requestMapping 으로 경로 지정 및 리턴

컨트롤러 클래스 밑에 메소드를 하나 작성하는데
   보통(관습적으로) 호출되는 jsp 파일 이름으로 작성한다.
   public String view() 를 작성
   view() return 값은 "view" 로 하고
  WEB-INF/views 밑에 view.jsp 파일을 만든다

.......
@RequestMapping("/view")   // 요청경로
 public String view(){
                .......
  return "view";     // 뷰페이지 이름
}
.......


여기서 호출되는 뷰페이지는 prefix + 뷰페이지이름+suffix 이다.

case2. requestMapping 은 class에도 적용가능하고
   이때는 class Mapping 값 + 메서드 Mapping 값이 된다.

.......
@Controller
@RequestMapping("/view")
public class MyController {
.......

@RequestMapping("/content")   // 요청경로
 public String view(){
.......


=================> /view/content 패키지에서 찾는다.


3. 값을 페이지로 넘기는 방법

.......
@RequestMapping("/view")   // 요청경로
 public String view(Model model){
                model.addAttribute("id", 30);
  return "view";     // 뷰페이지 이름
}
.......


  메서드에 Model 이라는 클래스 를 인자로 받아낼 수 있으며
   model 객체에 함수를 이용하는 방법으로 값을 넣을 수 있음.
   여기서는 id 라는 이름에 30이라는 값을 넣었음.
  model 객체는 따로 리턴하지 않아도 Spring Container 에서
   자동으로 해당 값을 넣어줌

jsp 에 다음 내용을 추가후
   id : ${id}
 서버 재가동 후에 확인하면 됨


+ 함수에 Model 인수를 받지 않고
    함수 안에서 ModelAndView mv 객체를
    생성해서 작업하는 방법도 있음 여기에서는 

.......
 public ModelAndView view(){
     ModelAndView mv = new ModelAndView();
     mv.addObject("id", 30);
     mv.setViewName("view");
  return mv;
 }
.......


    Model 인수를 받지 않는대신에 mv 객체에
     view 장소를 담고 mv 객체를 리턴해야 된다.

4. Form 에서 데이터 받기
 1) HttpServletRequest 클래스

@RequestMapping("board/confirmId")
public String confirmId(HttpServletRequest httpServletRequest, Model model) {
 String id = httpServletRequest.getParameter("id");
 String pw = httpServletRequest.getParameter("pw");
 model.addAttribute("id", id);
 model.addAttribute("pw", pw);
 return "board/confirmId";
}


   Controller 단의 메소드에서 HeepServletRequest 
    인자를 받아오는데 해당 객체에는 사용자가 요청한
    내용이 포함되어 있음.
   views/board/confirmId.jsp 에 파일을 생성후

@<page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR">
.......
<body>
 ID : ${id}
 PW : ${pw}
.........
</body>
</pre>

   이렇게 작성후 아래와 같이 실행시
http://localhost:8181/ex/board/confirmId?id=kim&pw=kim2323


입력한 id, pw 가 화면에 보이는걸 확인 가능하다.


 2) @RequestParam 어노테이션
위 컨트롤러 밑의 메서드 내용을 아래처럼 변경 가능하다

@RequestMapping("board/confirmId")
public String confirmId(@RequestParam("id") String id, @RequestParam("pw") String pw , Model model) {
 model.addAttribute("id", id);
 model.addAttribute("pw", pw);
 return "board/confirmId";
}


다만 이때는 RequestParam 에서 지정한 형식을 지켜서 반드시
   인자를 입력해야 정상적으로 실행된다.
   받기로한 인자(id, pw) 가 없거나 일치하지 않는 경우
   400 에러를 보내게된다.

 3) 데이터(커맨드) 객체
@RequestParam 의 경우 받아야할 데이터가 많아지면 길어진다.
   이를 데이터(객체)로 담아서 쓸수 있음

우선 Member 라는 클래스에는 set, get함수를 포함한 id,pw를
   멤버변수로 가지도록 작성한다. (간단해서 생략)
그리고 위에 작성한 예제를 내용을 아래와 같이 변경한다.

public String confirmId(User us){
 return "board/confirmId";
}


jsp 파일에서는 위의 내용을 아래와같이 수정한다.

........
<body>
 ID : ${user.id}

 PW : ${user.pw}
</body>
.......
이렇게만 해두면 member에 포함된 id, pw를 
   Framework 에서 자동으로 addAttribute 까지 처리한다.
   이때 객체이름은 us 라고 표시했지만 jsp단에서는
   클래스 이름 의 맨 앞글자를 소문자로 변경한
   이름으로 받아야지 받아진다.

이부분을 사용자가 객체이름을 바꿔 사용하고자 하는 경우
Controller 단에서

public String confirmId(@ModelAttribute("us") User us){
 return "board/confirmId";
}


라고 @ModelAttribute 로 표시하여 객체이름을
  지정 할 수 있다.

 4) @PathVariable
   요청 패스에 값을 넣어 진행하는 방법이 있는데
     @PathVariabel 를 이용하는 방법이다.
   Controller 의 Method 를 아래와 같이 작성한다.

 @RequestMapping("board/confirmId/{id}")
 public String confirmId(@PathVariable String id, Model model) {
                //String[] member = id.split(",");
  model.addAttribute("id", id);
  //model.addAttribute("pw", pw);
  return "board/confirmId";
 }


   Jsp는 이전 상태로 돌리고
   실행시에 path를 아래와 같이 부여한다.
http://localhost:8181/ex/board/confirmId/kim
   결과적으로 마지막에 부여한 path kim이
   id 라는 항목에 들어간걸 확인할 수 있다.
   여러개를 넣을수는 없고 kim 위치에 , 이용해서
   배열로 넣는 방법이 있다.
위의 주석을 풀어주고 아래 path로 확인시 kim, 1223이라는 키워드가
   각각 id, pw로 보여짐을 볼 수 있다.
http://localhost:8181/ex/board/confirmId/kim,1223

5. Form 데이터 검증
   데이터 받을때 제약조건 등을 물론 client 를 처리 가능하다 그리고
    이를 서버단에서 검증하는 방법을 알아본다.
    (숫자인지, 문자인지, 길이가 유효한지, 빈칸이 있는지 등등)

 1) Validator interface 이용한 검증
     Controller 에서 요청을 처리하는 method 에 와서
     Validator 를 활용하여 유효성 검증후 유효성 검증이 안되면
     해당 화면으로 돌리고 검증되면 view 호출이 진행되는 방식
     이때 인수로 BindingResult 라는 객체를 하나 받고
      validator.validate(인자를 포함한 객체, BindingResult br 객체)를 실행후
      에러 여부를 체크해서 리턴값을 달리 할 수 있다.

Controller 단의 RequestMapping 메서드를 다음과 같이 작성한다.

 @RequestMapping("/student/create")
 public String studentCreate(@ModelAttribute("student") Student student, BindingResult result) {
  
  String page = "createDonePage";
  
  StudentValidator validator = new StudentValidator();
  validator.validate(student, result);
  if(result.hasErrors()) {
   page = "createPage";
  }
  
  return page;
 }


그리고 validator 를 구현한다.
 여기서 errors 객체의 rejuctValue 를 함으로서
  에러를 발생할 수 있다. 그리고 유효성 검증은
  자바 형태로 검증하면 된다.

public class StudentValidator implements Validator {
//검증할 객체의 타입 정보 여기서는 Student.class 에 대해서
//검증한다.
 @Override
        public boolean supports(Class arg0) {
 return Student.class.isAssignableFrom(arg0);
 }
   @Override
public void validate(Object obj, Errors errors) {
 Student student = (Student)obj;

 String studentName = student.getName();

 if(studentName == null || studentName.trim().isEmpty()) {
  System.out.println("studentName is null or empty");
  errors.rejectValue("name", "trouble");
 }
}


이후 jsp 파일 form 에서 진행시
   validate에서 error 여부를 체크하여 Controller 단에서
   다른 페이지로 보낼 수 있는 기준을 제공하게 된다.
    여기에서는 에러를 포함하여 기존 페이지로 보내게 된다.

 2) Validator 를 implements 하여 작성된 ValidationUtils라는 클래스를
     이용하는 방법

Validator 를 위해서 작성한 StudentValidator 클래스에서
기존에 작성했던

 String studentName = student.getName();

 if(studentName == null || studentName.trim().isEmpty()) {
  System.out.println("studentName is null or empty");
  errors.rejectValue("name", "trouble");
 }


내용을 ValidationUtils 클래스를 이용해서 작성시

ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "trouble");


한줄로 표현이 가능하다 if 조건까지 포함된 내용임
  ValidationUtils 클래서에서 이런 형태의
   유효성을 체크할 수 있는 여러 메서드를 제공해준다.


 3) 어노테이션 @Vaild 와 @InitBinder 을 이용하기

Controller에서 Validator 를 호출했던 내용을 아래와 같이 수정한다.
    바뀐점은 sudent 뒤에 @Valid 라는 어노테이션을 붙여준다.

 @RequestMapping("/student/create")
 public String studentCreate(@ModelAttribute("student") @Valid Student student, BindingResult result) {
  
  String page = "createDonePage";
  
//  StudentValidator validator = new StudentValidator();
//  validator.validate(student, result);
  if(result.hasErrors()) {
   page = "createPage";
  }
  
  return page;
 }

 //위의 생략된 부분의 메서드명을 명시해주는 목적으로
 // InitBinder 어노테이션을 추가한다
 @InitBinder
 protected void initBinder(WebDataBinder binder){
  binder.setValidator(new StudentValidator());
 }


pom.xml 에 다음 의존성을 추가해준다.

 
  org.hibernate
  hibernate-validator
  4.2.0.Final
 


이렇게 Validator 객체를 생성하여 호출하는 과정을 진행하지 않았지만
    정상적으로 호출되는걸 확인 할 수 있다.

댓글 없음:

댓글 쓰기