1. 스프링 MVC 이용시 Controller의 특징
▷ HttpServletRequest, HttpServletResponse를 거의 사용할 필요 없이 필요한 기능 구현
▷ 다양한 타입의 파라미터 처리, 다양한 타입의 리턴 타입 사용 가능
▷ GET, POST 방식 등 전송 방식에 대한 처리를 어노테이션으로 처리 가능
▷ 상속/인터페이스 방식 대신에 어노테이션만으로도 필요한 설정 기능
◎ @Controller, @RequestMapping
◎ SampleController 클래스
package org.codehows.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/sample/*") public class SampleController { }
위의 클래스는 servlet-context.xml의 <context:component-scan base-package="org.codehows.controller" /> 코드를 통해 스프링의 객체에 자동으로 등록됩니다.
클래스 선언부에는 @Controller, @RequestMapping을 많이 사용함
@RequestMapping은 현재 클래스의 모든 메서드들의 기본적인 URL 경로
◎ SampleController 수정
package org.codehows.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import lombok.extern.log4j.Log4j; @Controller @RequestMapping("/sample/*") @Log4j public class SampleController { @RequestMapping("") public void basic() { log.info("basic..............."); } }
여기서 Log4j, log가 오류가 나타납니다
◎ 오류 해결 방법(pom.xml 내용 수정)
<!-- Logging --> ...(생략)... <dependency> ...(생략)... <!-- 아래의 scope 주석 처리 --> <!-- <scope>runtime</scope> --> </dependency>
runtime이 있어서 Log4j에 문제가 발생합니다.
따라서 주석처리하면 오류가 해결됩니다.
2. @RequestMapping의 변화
▷ @Controller 어노테이션은 추가적인 속성을 지정할 수 없지만, @RequestMapping의 경우 몇 가지 속성을 추가할 수 있음
▷ Method 속성은 GET 방식, POST 방식을 구분해서 사용할 때 이용
...(생략)... @RequestMapping(value="/basic", method= {RequestMethod.GET, RequestMethod.POST}) public void basicGet() { log.info("basic get..............."); } @GetMapping(value="/basicOnlyGet") public void basicGet2() { log.info("basic get only get..............."); } }
스프링 4.3버전부터는 @RequestMapping을 줄여서 사용할 수 있는 @GetMapping, @PostMapping 등의 축약형 표현을 사용하기도 함
▷ @RequestMapping은 GET, POST 방식 모두 지원해야 하는 경우 배열로 처리해서 지정 가능
▷ 최근에는 PUT, DELETE 방식 등 많이 사용하고 있음
3. Controller의 파라미터 수집
▷ Controller를 작성할 때 파라미터가 자동으로 수집되는 기능
▷ 매번 request.getParameter()를 이용하는 불편함을 없앨 수 있음
◎ SampleDTO 클래스
package src.codehows.domain; import lombok.Data; @Data public class SampleDTO{ private String name; private int age; }
▷ SampleDTO 클래스는 Lombok의 @Data 어노테이션을 이용해 처리
▷ @Data를 이용하게 되면 getter/setter, equals(), toString() 등 메소드를 자동 생성하기 때문에 편리
(1) SampleController 수정 1
▷ SampleDTO 클래스를 파라미터로 사용하게 되면 자동으로 setter 메소드가 동작하면서 파라미터 수집
package org.codehows.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import lombok.extern.log4j.Log4j; import src.codehows.domain.SampleDTO; @Controller @RequestMapping("/sample/*") @Log4j public class SampleController { ...(생략)... @GetMapping("/ex01") public String ex01(SampleDTO dto) { log.info("" + dto); return "ex01"; } }
SampleController 경로가 '/sample/*' 이므로 ex01() 메소드를 호출하는 경로는 '/sample/ex01'이 됨
http://localhost:8080/sample/ex01?name=AAA&age=10
위의 경로로 설정하면 아래와 같이 오류가 나타납니다.
대신 로그창에는 아래와 같이 나타납니다.
INFO : org.codehows.controller.SampleController - SampleDTO(name=AAA, age=10)
◎ SampleController 수정 2
▷ Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식 이용
▷ SampleDTO에는 int 타입으로 선언된 age가 자동으로 숫자로 변환되는 것을 볼 수 있음
package org.codehows.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import lombok.extern.log4j.Log4j; import src.codehows.domain.SampleDTO; @Controller @RequestMapping("/sample/*") @Log4j public class SampleController { ...(생략)... @GetMapping("/ex02") public String ex02(@RequestParam("name") String name, @RequestParam("age") int age) { log.info("name" + name); log.info("age" + age); return "ex02"; } }
http://localhost:8080/sample/ex01?name=AAA&age=10
위의 경로로 설정하면 여전히 404 오류가 나타나지만 console창에 아래와 같은 데이터가 수집된 것을 확인할 수 있습니다.
(2) 리스트, 배열 처리
▷ 동일한 이름의 파라미터가 여러 개 전달되는 경우 ArrayList<> 등을 이용해서 처리가 가능
...(생략)... @GetMapping("/ex02List") public String ex02List(@RequestParam("ids")ArrayList<String> ids) { log.info("ids" + ids); return "ex02List"; } }
스프링은 파라미터 타입을 보고 객체를 생서하므로 파라미터 타입은 List<>와 같이 인터페이스가 아닌 실제 클래스 타입으로 지정
위 코드의 경우 ids라는 파라미터가 여러개 전달되더라도 ArrayList<String>이 생성되어 자동으로 수정됨
http://localhost:8080/sample/ex02List?ids=111&ids=222&ids=333
위의 경로로 지정했을 경우 콘솔창에 아래와 같이 나타나게 됩니다.
→ INFO : org.codehows.controller.SampleController - ids[111, 222, 333]
◎ 배열을 이용한 예제...(생략)... @GetMapping("/ex02Array") public String ex02Array(@RequestParam("ids") String[] ids) { log.info("array ids" + Arrays.toString(ids)); return "ex02Array"; } }
(3) 객체 리스트
▷ 객체 타입이고 여러 개를 처리해야 한다면 SampleDTOList 클래스를 통해 처리할 수 있음
◎ SampleDTOList 클래스 생성
◎ SampleDTOList.java 생성
package org.codehows.domain; import java.util.ArrayList; import java.util.List; import lombok.Data; @Data public class SampleDTOList{ private List<SampleDTO> list; public SampleDTOList() { list = new ArrayList<>(); } }
◎ SampleController.java 내용 추가...(생략)... @GetMapping("/ex02Bean") public String ex02Bean(SampleDTOList list) { log.info("list dtos: " + list); return "ex02Bean"; } }
http://localhost:8080/sample/ex02Bean?list%5B0%5D.name=aaa&list%5B2%5D.name=bbb
(= http://localhost:8080/sample/ex02Bean?list[0].name=aaa&list[2].name=bbb)
문법이 허용되지 않아서 '[' 대신 '%5B' ']' 대신 '%5D'가 나타납니다
콘솔창은 아래와 같이 나타납니다.
INFO : org.codehows.controller.SampleController - list dtos: SampleDTOList(list=[SampleDTO(name=aaa, age=0), SampleDTO(name=null, age=0), SampleDTO(name=bbb, age=0)])
3개의 SampleDTO 객체가 생성되었고 '[ ]' 안에 인덱스 번호에 맞게 객체의 속성값이 세팅됨
(4) @lnitBinder
▷ 파라미터의 수집, 'binding(바인딩)'이라고 함
▷ 변환 가능 데이터는 자동 변환되지만 경우에 따라서 파라미터를 변환해서 처리하는 경우도 존재
◎ TodoDTO 생성 경로 및 코드 작성
◎ 코드package org.codehows.domain; import java.util.Date; import lombok.Data; @Data public class TodoDTO{ private String title; private Date dueDate; }
◎ SampleController 클래스 추가
package org.codehows.controller; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import org.codehows.domain.SampleDTO; import org.codehows.domain.SampleDTOList; import org.codehows.domain.TodoDTO; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import lombok.extern.log4j.Log4j; @Controller @RequestMapping("/sample/*") @Log4j public class SampleController { @InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(dateFormat, false)); } ...(생략)... @GetMapping("/ex03") public String ex03(TodoDTO todo) { log.info("todo: " + todo); return "ex03"; } }
http://localhost:8080/sample/ex03?title=test&dueDate=2018-01-01
위의 경로 연결하면 아래와 같은 결과가 출력됩니다.
INFO : org.codehows.controller.SampleController - todo: TodoDTO(title=test, dueDate=Mon Jan 01 00:00:00 KST 2018)
(5) @DateTimeFormat
▷ @InitBinder 이용해서 날짜 변환 가능하지만 파라미터로 사용되는 인스턴스 변수에 @DateTimeFormat을 적용해도 변환 가능
◎ TodoDTO 클래스 수정
package org.codehows.domain; import java.util.Date; import org.springframework.format.annotation.DateTimeFormat; import lombok.Data; @Data public class TodoDTO{ private String title; @DateTimeFormat(pattern = "yyyy/MM/dd") private Date dueDate; }
http://localhost:8080/sample/ex03?title=test&dueDate=2018/01/01
위의 경로로 연결하면 아래와 같은 결과가 출력됩니다.
INFO : org.codehows.controller.SampleController - todo: TodoDTO(title=test, dueDate=Mon Jan 01 00:00:00 KST 2018)
initbinder를 사용했을 때와 동일한 결과가 나타납니다!!
4. Model이라는 데이터 전달자
▷ Controller의 메소드를 작성할 때 Model이라는 타입을 파라미터로 지정할 수 있음
▷ Model 객체는 JSP의 컨트롤러에서 생성된 데이터를 담아 전달하는 역할
▷ JSP와 같은 뷰(View)로 전달해야 하는 데이터를 담아서 보낼 수 있음
▷ 메서드의 파라미터에 Model 타입이 지정된 경우에는 스프링은 특별하게 Model 타입의 객체를 만들어 메서드에 주입
Model은 모델 2 방식에서 사용하는 request.setAttribute()와 유사한 역할
1. Servlet에서 모델 2방식으로 데이터를 전달하는 방식
request.setAttribute("serverTime", new java.util.Date()); RequestDispatcher dispatcher = requset.getRequestDispatcher("/WEB-INF/jsp/home.jsp); dispatcher.forward(request, response);
2. 스프링에서 Model을 이용해 데이터 전달하는 방식
public String home(Model model){ model.addAttribue("serverTime", new java.util.Date()); return "home"; }
메소드의 파라미터를 Model 타입으로 선언하게 되면 자동으로 스프링 MVC에서 Model 타입의 객체를 만들어 주며 개발자의 입장에서 필요한 데이터를 담아주는 작업만으로 모든 작업이 완료됨.
◎ @ModelAttribute 어노테이션
▷ 웹페이지 구조는 Request에 전달된 데이터를 가지고 필요하다면 추가적인 데이터를 생성해서 화면으로 전달하는 방식
▷ Model의 경우 파라미터로 전달된 데이터는 없지만 화면에 필요한 데이터를 전달하기 위해 사용
▷ 페이지 번호는 파라미터로 전달되지만, 결과 데이터를 전달하려면 Model에 담아 전달함
◎ 기본 자료형 파라미터 선언(SampleController에 내용 추가)
...(생략)... @GetMapping("/ex04") public String ex04(SampleDTO dto, int page) { log.info("dto: " + dto); log.info("page: " + page); return "/sample/ex04"; } }
▷ ex04()는 SampleDTO 타입과 INT 타입의 데이터를 파라미터로 사용
▷ 결과 확인을 위해 'WEB-INF/views' 폴더 아래 sample 폴더 생성 및 리턴값에서 사용한 'ex04'에 해당하는 ex04.jsp 작성
◎ ex04.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html" charset="UTF-8"> <title>Insert title here</title> </head> <body> <h2>SAMPLEDTO ${sampleDTO}</h2> <h2>PAGE ${page}</h2> </body> </html>
http://localhost:8080/sample/ex04?name=aaa&age=11&page=9
위의 경로 입력시 아래의 화면 출력
int 타입으로 선언된 page는 전달되지 않습니다.
따라서 @ModelAttribute 사용(강제로 전달받은 파라미터를 Model에 담아서 전달하도록 할 때 필요한 어노테이션)
@ModelAttribute가 걸린 파라미터는 타입에 관계없이 무조건 Model에 담아서 전달되므로 파라미터로 전달된 데이터를 다시 화면에서 사용해야할 경우 유용하게 사용됨
◎ SampleController 내용 수정(ex04 내용 추가)
...(생략)... @GetMapping("/ex04") public String ex04(SampleDTO dto, @ModelAttribute("page") int page) { log.info("dto: " + dto); log.info("page: " + page); return "/sample/ex04"; } }
http://localhost:8080/sample/ex04?name=aaa&age=11&page=9
위의 경로 입력시 아래의 화면 출력
◎ RedirectAttributes
▷ Model 타입과 더불어 스프링 MVC가 자동으로 전달해 주는 타입
▷ RedirectAttributes는 일회성으로 데이터를 전달하는 용도로 사용
Model은 모델 2 방식에서 사용하는 request.setAttribute()와 유사한 역할
1. Servlet에서 redirect방식
respons.sendRedirect("/home?name=aaa&age=10");
2. 스프링 MVC 이용하는 redirect 처리
rttr.addFlashAttribute("name", "AAA"); rttr.addFlashAttribute("age", 10); return "redirect:/";
RedirectAttributes는 Model 같이 파라미터로 선언해서 사용하고, addFlashAttribute(이름, 값) 메소드를 이용해서 화면에 한 번만 사용하고 다음에는 사용되지 않는 데이터를 전달하기 위해 사용
MVC Controller를 이용해서 SampleController.java 파일을 만들어 화면창과 콘솔창에 출력해보는 예제를 실시해보았습니다.
결과가 좀 나타나니 사용하는 방법을 조금씩 익혀가는 것 같아요!
controller가 내용이 많아서 다음 글에서도 다뤄볼게요!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

'BackEnd > Spring' 카테고리의 다른 글
[코드로 배우는 스프링 웹 프로젝트] ch06 스프링 MVC Controller 3(Controller Exception) (0) | 2023.03.27 |
---|---|
[코드로 배우는 스프링 웹 프로젝트] ch06 스프링 MVC Controller 2 (0) | 2023.03.27 |
[코드로 배우는 스프링 웹 프로젝트] ch05 스프링 MVC 기본 구조 (0) | 2023.03.26 |
[코드로 배우는 스프링 웹 프로젝트] ch04 MyBatis와 스프링 연동 2( log4jdbc-log4j2) (0) | 2023.03.26 |
[코드로 배우는 스프링 웹 프로젝트] ch04 MyBatis와 스프링 연동 1 (0) | 2023.03.26 |