대덕공부/Spring

RedirectAttributes, Model, ModelAttribute (feat.dditStudentCont)

02O2 2022. 7. 12. 21:05

@Controller

@Controller
@RequestMapping("/student")
public class DDITStudentController {

   @RequestMapping("resultView.do")
   public String resultView() {
      return "student/resultView";
   }

   @RequestMapping(value = "regist.do", method = RequestMethod.GET)
   public String getHandler() {
      return "student/registForm";

   }

   @RequestMapping(value = "regist.do", method = RequestMethod.POST)
   public String postHandler(
         @Validated(InsertGroup.class) @ModelAttribute("student") DDITStudentVO studentVO
         , Errors errors,
//         @RequestPart("photo") MultipartFile photo,
          HttpSession session, Model model,
         RedirectAttributes redirectAttributes) throws IOException {
//      model.addAttribute("gradeMap", makeGradeList());
//      model.addAttribute("licenseMap", makeLicenseList()); //생략가능 why? modelattribute로 메소드를 실행했기때문에 .

      
//      studentVO.setPhoto(photo);
      boolean valid = !errors.hasErrors();// 에러가없는게 true 
      String message = null;
      String view = null;
      if (valid) {         
         String imageFolderPath = "D:/contents";
         File saveFolder = new File(imageFolderPath);
         studentVO.saveTo(saveFolder);

         message = "등록 완료";
         redirectAttributes.addFlashAttribute("student", studentVO);
         redirectAttributes.addFlashAttribute("message", message);
         view = "redirect:/student/resultView.do";// redierct는 req가 사라지기때문에 session을 씀
         // 또다른 컨트롤러를이용해서 모델2방식

      } else {
         message = "등록 실패, 검증 실패";
         model.addAttribute("message", message); // 포워드하기때문에 model이 필요 .
         view = "student/registForm";
      }
      return view;
   }


   @ModelAttribute("gradeMap") // 파라미터로 넘어온 값을 해당 scope에 넣어준데
   public Map<String, String[]> makeGradeList() {
      Map<String, String[]> gradeMap = new LinkedHashMap<>();
      gradeMap.put("G001", new String[] { "G001", "고졸" });
      gradeMap.put("G002", new String[] { "G001", "초대졸" });
      gradeMap.put("G003", new String[] { "G001", "대졸" });
      gradeMap.put("G004", new String[] { "G001", "석사" });
      gradeMap.put("G005", new String[] { "G001", "박사" });
      return gradeMap;
   }

   @ModelAttribute("licenseMap")
   public Map<String, String[]> makeLicenseList() {
      Map<String, String[]> licenseMap = new LinkedHashMap<>();
      licenseMap.put("L001", new String[] { "L001", "정보처리산업기사" });
      licenseMap.put("L002", new String[] { "L002", "정보처리기사" });
      licenseMap.put("L003", new String[] { "L003", "정보보안산업기사" });
      licenseMap.put("L004", new String[] { "L004", "정보보안기사" });
      licenseMap.put("L005", new String[] { "L005", "SQLD" });
      licenseMap.put("L006", new String[] { "L006", "SQLP" });
      return licenseMap;
   }

}

 

@RedirectAttributes

더보기

폼 형식의 문서를 작성 후, 서버로 보내면(POST 방식) 곧이어 다른 페이지로 리다이렉트 한다. 문제는 이러한 리다이렉트 방식이 GET 방식​ 이라 데이터 전송에는 적절하지 않다.

 

리다이렉트의 특징은 다음 그림과 같다. spitter객체를 보내려고 한다.

리다이렉트가 발생하면 원래 요청은 끊어지고, 새로운 HTTP GET 요청이 시작된다.(브라우저에게 이 URL로 리다이렉트해!)  때문에 리다이렉트 실행 이전에 수행된 모델 데이터는 소멸한다. 따라서 리다이렉트로 모델을 전달하는 것은 의미 없다.

그러나 리다이렉트 방법으로도 데이터를 전달하는 방법이 있다. GET의 특징을 사용하는 것이다.

리다이렉트는 HTTP GET 메소드 방식이라고 앞서 말했다. GET방식은 아래 그림처럼 header에 ? 뒤에 파라미터를 붙여서 전달한다. 때문에 URL에 노출되는 단점이 있다.

래서 스프링은 RedirectAttributes 클래스를 제공한다. 이 클래스는 모델의 기능을 그대로 확장(extends)했으며, 몇개의 도움 메소드가 추가됐다. 

 

공부하기 위해서 검색으로 이에 대해 설명한 국내 여러 블로그를 보니 대부분이 RedirectAttributes POST 방식으로 전달한다고 설명했다. 아무래도 URL 뒤에 파라미터가 안 붙어서 POST 방식으로 전달하나 생각했나 보다. 하지만 POST 방식은 아니다. 겉으로만 그렇게 보일 뿐인데 POST와 연관 짓는 건 이건 좀 아닌 듯 싶다. 애초에 return redirect가 GET으로 가는데 말이 안되지. 리다이렉트 자체가 POST/Redirect/GET 패턴인데....

 

RedirectAttributes는 아래 그림처럼 리다이렉트가 발생하기 전에 모든 플래시 속성을 세션에 복사한다. 리다이렉션 이후에는 저장된 플래시 속성을 세션에서 모델로 이동시킨다. 헤더에 파라미터를 붙이지 않기 때문에 URL에 노출되지 않는다.

 

 

RedirectAttributes가 제공하는 메소드 addFlashAttribute()

addFlashAttribute() 는 리다이렉트 직전 플래시에 저장하는 메소드다. 리다이렉트 이후에는 소멸한다.

 

@Model

Model은 HashMap 형태를 갖고 있으며, key, value값을 가지고 있습니다. 또한 addAttribute()와 같은 기능을 통해 모델에 원하는 속성과 그것에 대한 값을 주어 전달할 뷰에 데이터를 전달할 수 있습니다.

 

@ModelAttribute

요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.

보통 @RequestParam을 사용해서 값을 받고, set을 사용해서 값을 넣어주곤 하지만 이 과정을 자동화시켜주는 것이 @ModelAttribute이다.