[Spring] Spring MVC - Controller (0806)

왕감자·2024년 8월 6일

KB IT's Your Life

목록 보기
117/177

Controller


1) HandlerMapping

🔸 @RequestMapping

  • 수용할 HTTP method 설정 (GET, POST, PUT, DELETE 등)
  • @RequestMapping(value="/basic", method={RequestMethod.GET, RequestMethod.POST})
    • 설정하지 않으면 모두 허용

🔸 메서드별 Mapping

: 일반적으로 한 가지 메서드로 매핑

  • GetMapping / PostMapping / PutMapping / DeleteMapping

url - 메서드 확인

log4j.xml

    <logger name="_org.springframework.web.servlet.HandlerMapping">
        <level value="debug" />
    </logger>

2) HandlerAdapter

🔸 Controller 파라미터 수집

⭐⭐요청의 쿼리 파라미터 수집⭐⭐

  • request.getParameter() 대체
  1. ⭐DTO 객체 사용 (기본 생성자 必)
    • HandlerAdapter가 요청한 DTO 객체 생성 (자동으로 request scope에 저장)
      - DI 요청 ➔ DTO 객체 생성
      • DTO의 property(getter/setter에 의해 접근 가능한 정보) 설정 (setter)
      • 컨트롤러의 요청 처리 메서드의 인자로 전달
    • 자동으로 view에 전달
    • form의 name과 DTO의 멤버 변수명이 같아야함
  2. @RequestParam("파라미터명")
    • 개별적으로 받기
    • view에 전달 X

1. DTO 객체 사용

// SampleController

    @GetMapping("/ex01")
    public String ex01(SampleDTO dto){ // DI 요청 (SampleDTO 만들어 달라고 요청 -> DTO 객체 생성)
        log.info("" + dto); // log는 문자열만 받아서 ""로 문자열 처리
        return "ex01";  // view 이름
    }

2. DTO 객체 사용 X - 개별적으로 받기 : @RequestParam

    @GetMapping("/ex02")
    public String ex02(
            @RequestParam("name") String name,
            @RequestParam("age") int age
    ){
        log.info("name: " + name);
        log.info("age: " + age);

        return "ex02";
    }

🤔age를 안 쓴다면? / age에 int가 아닌 문자열을 넣는다면?

NumberFormatException


🔸 리스트 배열 처리

  • 동일 이름의 파라미터가 여러 개 전달 된 경우 (ex. checkbox)
  • ArrayList<> , 배열 사용
// ArrayList
    @GetMapping("/ex02List")
    public String ex02List(
            @RequestParam("ids") ArrayList<String> ids) {
        log.info("ids: " + ids);

        return "ex02List";
    }

🔸 날짜 처리 (@DateTimeFormat)

  • DTO 객체의 Date 타입 필드에 @DateTimeFormat
    • 포맷을 Spring에게 알려줘야 함~! @DateTimeFormat(pattern = "포맷")
// TodoDTO
@Data
public class TodoDTO {
    private String title;
    
    @DateTimeFormat(pattern = "yyyy/MM/dd")
    private Date dueDate;
}
//SampleController
    @GetMapping("/ex03")
    public String ex03(TodoDTO todo) {
        log.info("todo: " + todo);
        return "ex03";
    }


3) Controller

🔸 Model (데이터 전달자)

Controller 메서드의 매개변수 - Model

기존 모델1

  • 컨트롤러에서 생성된 데이터를 JSP에 전달
    • request 스코프에 속성으로 저장 ➔ jsp로 forward
  • Model
    • 결과 데이터를 담아 뷰에 전달
    • Map의 일종
    • request scope에 저장
    • 결과 데이터를 담아 뷰에 전달
//HomeController
    @GetMapping("/") //  getMap.put("/", 메서드)
    public String home(Model model) {
        model.addAttribute("name", "홍길동"); //request scope에 저장
        return "index"; // view 이름  →  /WEB-INF/views/index.jsp
    }
<%--indext.jsp--%>
<body>
<h1>${name}님 환 영 합 니 도</h1>
</body>

🔸 @ModelAttribute

@RequestParam 뷰로 전달

@ModelAttribute("파라미터명")

  • DTO 쿼리 파라미터는 자동으로 뷰로 전달
  • 기본 자료형 쿼리 파라미터는 뷰로 전달 안 됨
  • 쿼리 파라미터를 request scope에 저장
//SampleController
    @GetMapping("/ex04")
    public String ex04(SampleDTO dto, int page){
        log.info("dto: " + dto); 
        //메서드가 실행되면 dto 객체를 자동으로 모델에 추가
        //모델 속성 이름: sampleDTO (앞글자소문자,자동생성) - jsp에서 ${sampleDTO}로 접근
        
        log.info("page:" + page);

        return "sample/ex04";
    }
}
<!--ex04.jsp-->
<body>
    <h2>SAMPLE DTO : ${sampleDTO}</h2>
    <h2>PAGE : ${page}</h2>
</body>

쿼리(요청)파라미터(page) = 변수명(int page) ⇨ @RequestParam 생략 가능


page도 view로 넘기기~

    @GetMapping("/ex04")
    public String ex04(SampleDTO dto, @ModelAttribute("page") int page){
        log.info("dto: " + dto);
        log.info("page:" + page);

        return "sample/ex04";
    }

🔸 Controller 매서드 리턴 타입

  • String : 뷰 이름 리턴 / redirect 경로
  • void : 호출한 URL의 경로 = 뷰 이름
  • VO, DTO : JSON 데이터로 변화하여 브라우저로 응답
  • ResponseEntity : Http 헤더 정보와 내용을 가공하여 직접 브라우저로 응답

⇨ 지금은 jsp를 쓰지만 최종적으로 Vue를 사용, axios를 통해 API 호출할 예정


void 타입

    @GetMapping("/ex05") //url=뷰이름 : /sample/ex05
    public void ex05() {
        log.info("/ex05..........");
    }

String 타입

  • forward : "뷰 이름" 문자열 리턴
  • redirect : "redirect:요청URL" 문자열 리턴

🔸 RedirectArrtibutes

  • Servlet에서 redirect 방식
    • response.sendRedirect("/sample/ex06?name=aaa&age=10")
    • 쿼리 스트링 ? 이때 필요함 ↴ (리다이렉트하고 어느 경로로 가야할지~ 경로 저장해아함)
  • 리다이렉트할때 사용하는 Arribute
  • 값 저장
    1. 쿼리 스트링: ra.addAttribute("name", "gamza")
    2. session 사용: session에 잠깐 저장~! - 전달 후 삭제
    @GetMapping("/ex06")
    public String ex06(RedirectAttributes ra) {
        log.info("/ex06..........");
        ra.addAttribute("name", "AAA");
        ra.addAttribute("age", 10);
        
        return "redirect:/sample/ex06-2";
    }

🔸 객체 타입

  • 객체 자체를 리턴 - JPS를 안 쓰고 바로 데이터 자체를 리턴
  • JSON 타입 응답하는 경우 사용
  • jackson-databind 라이브러리 필요 (bundle.gradle)
  • @ResponseBody 붙임~
    • 메서드 반환값이 직접 HTTP 응답으로 전송
    @GetMapping("/ex07")
    public @ResponseBody SampleDTO ex07() {
        log.info("/ex07..........");

        SampleDTO dto = new SampleDTO();
        dto.setAge(10);
        dto.setName("홍길동");

        return dto;
    }

0개의 댓글