위 글은 해당 카테고리의 수업 강의 자료를 정리한 것입니다.
MVC 구조의 이해
MVC(Model-View-Controller)
- 대부분의 서블릿 기반 프레임워크들이 사용하는 방식
- 데이터와 처리, 화면을 분리하는 방식
- 웹에서는 Model2 방식으로 표현
스프링과 스프링 MVC
- 스프링 프레임워크 Core + 여러 Sub 프로젝트들
- 별도로 결합해서 사용하기 때문에 설정 역시 별도로 처리 가능
Spring | Projects
Spring Framework Provides core support for dependency injection, transaction management, web apps, data access, messaging, and more.
spring.io
일반적인 스프링 + 스프링 MVC
웹 프로젝트의 구조
- 스프링을 실행하는 존재
- ApplicationContext ➡️ WebApplicationContext
- 같이 연동되는 방식으로 동작하기 때문에 설정을 분리해도 통합해서 사용 가능
스프링 MVC의 기본 사상
- 서블릿 기반이긴 하지만 한 단계 더 추상화된 수준의 개발 지향
- 서블릿 API 없이도 개발이 가능한 수준
모델2 방식과 스프링 MVC
스프링 MVC의 기본 흐름
스프링 기반 웹서비스 시작과 처리 과정
- WAS가 구동되면서 web.xml이 로딩
- web.xml에 등록되어 있는 ContextLoaderListener(Java Class)가 생성됨, ContextLoaderListener 클래스는 ServletContextListener 인터페이스를 구현하고 있으며 ApplicationContext를 생성하는 역할을 수행함
- 생성된 ContextLoaderListener는 root-context.xml을 loading 함
- root-context.xml에 등록되어 있는 Spring Container가 구동됨, 이때 개발자가 작성한 비즈니스 로직에 대한 부분과 DAO, VO 객체들이 생성됨
- 클라이언트로부터 웹 애플리케이션의 요청이 옴
- DispatcherServlet(Servlet)이 생성됨
- DispatcherServlet은 servlet-context.xml을 loading 함, DispatcherServlet은 HandleMapping을 통해 Controller로 위임처리 함
- 두 번째 Spring Container가 구동되며 응답에 맞는 PageController들이 동작함, 이때 첫 번째 Spring Container가 구동되면서 생성된 DAO, VO, ServiceImpl 클래스들과 협업하여 알맞은 작업 처리
- 처리 후 controller는 view이름을 리턴하고 viewResoler를 통해 사용자에게 보여줌
DispatcherServlet이란
- 과거의 servlet 방식의 웹 어플리케이션은 web.xml에 <url-pattern>을 설정하여 클라이언트의 모든 요청을 처리하였음
- DispatcherServlet을 web.xml에 등록해도 계속 서블릿을 web.xml에 매핑해서 쓸 수 있음
- 옛 방식을 버리고 DispatcherServlet을 이용해 웹 개발을 한다면 서블릿 파일을 만들 필요도 없어짐과 동시에 획기적이고 놀라운(??) MVC의 혜택을 얻을 수 있음
- MVC 설계 원칙에 따른 웹 어플리케이션의 개발
- Model, Controller, View를 조합하여 브라우저에게 응답하는 일 수행
정적인 요소는 DispatcherServlet과 분리
- 모든 웹 리소스들은 DispatcherServlet이 가로채지 못하도록 해야함
- <resources mapping="/resources/-*" location="/resources/" />
- 이 전략은 디스패처 서블릿을 통해 들어온 요청을 처리하는데 만약 해당 요청에 대한 컨트롤러를 찾을 수 없다면 2차적으로 위의 설정된 경로를 검색하여 해당 자원을 찾아내게 되는 구조
Controller
- HttpServletRequest, HttpServletResponse를 거의 사용할 필요 없이 필요한 기능 구현
- 다양한 타입의 파라미터 처리, 다양한 타입의 리턴 타입 사용 가능
- GET, POST 방식 등 전송 방식에 대한 처리를 어노테이션 (@)으로 처리 가능
- 상속, 인터페이스 방식 대신에 어노테이션만으로도 필요한 설정 가능
@Controller, @RequestMapping
- @Controller
- 해당 클래스의 인스턴스를 스프링의 빈으로 등록하고 컨트롤러로 사용
- <component-scan>과 같이 활용
- @RequestMapping
- 특정한 URL에 대한 처리를 해당 컨트롤러나 메소드에서 처리
package org.zerock.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/sample/*")
public class SampleController {
}
@RequestMapping의 변화
- 스프링 4.3 전까지는 @RequestMapping(method='get') 방식으로 사용
- 스프링 4.3 이후에는 @GetMapping, @PostMapping 등으로 간단히 표현 가능
@RequestMapping(value = "/basic", method = {RequestMethod.GET, RequestMethod.POST})
public void basicGet() {
log.info("basic get...................");
}
@GetMapping("/basicOnlyGet")
public void basicGet2() {
log.info("basic get only get...................");
}
컨트롤러의 파라미터 수집
- 스프링 MVC의 컨트롤러는 메서드의 파라미터를 자동으로 수집, 변환하는 편리한 기능을 제공
- Java Beans 규칙에 맞게 작성되어야 함
- 생성자가 없거나 빈 생성자
- 올바른 규칙으로 만들어진 Getter/Setter
@Data
public class SampleDTO {
private String name;
private int age;
}
@GetMapping("/ex01")
public String ex01(SampleDTO dto) {
log.info("" + dto);
return "ex01";
}
리스트 또는 배열로 파라미터 넘기기
@GetMapping("/ex02List")
public String ex02List(@RequestParam("ids")ArrayList<String> ids) {
log.info("ids: " + ids);
return "ex02List";
}
@InitBinder
- Spring Validator를 사용 시 @Valid 어노테이션으로 검증이 필요한 객체를 가져오기 전에 수행할 method를 지정해주는 어노테이션
public class TodoDTO {
private String title;
private Date dueDate; //날짜 타입의 변환 필요
}
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
…생략…
@GetMapping("/ex03")
public String ex03(TodoDTO todo) {
log.info("todo: " + todo);
return "ex02";
}
@DataTimeFormat
- @InitBinder 외에도 날짜에 대한 처리가 쉽게 추가된 어노테이션
package org.zerock.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;
}
Model이라는 데이터 전달자
- Model 객체는 JSP에 컨트롤러에서 생성된 데이터를 담아서 전달하는 역할을 하는 존재
- 모델2 방식에서 사용하는 request.setAttribute()와 유사한 역할
public String home(Model model) {
model.addAttribute("serverTime", new java.util.Date());
return "home";
}
@ModelAttribute
- 컨트롤러에서 메소드의 파라미터는 기본 자료형을 제외한 객체형 타입은 다시 화면으로 전달
- @ModelAttribute는 명시적으로 화면에 전달되도록 지정
@GetMapping("/ex04")
public String ex04(SampleDTO dto, @ModelAttribute(“page”) int page) {
log.info("dto: " + dto);
log.info("page: " + page);
return "/sample/ex04";
}
<h2>SAMPLEDTO ${sampleDTO }</h2>
<h2>PAGE ${page }</h2>
RedirectAttribute
- 화면에 한번만 전달되는 파라미터를 처리하는 용도
- 내부적으로 HttpSession 객체에 담아서 한번만 사용되고 폐기
rttr.addFlashAttribute("name", "AAA");
rttr.addFlashAttribute("age", 10);
return "redirect:/";
response.sendRedirect("/home?name=aaa&age=10");
Controller의 리턴 타입
- String
- jsp를 이용하는 경우에는 jsp 파일의 경로와 파일 이름을 나타내기 위해서 사용
- 상황에 따라 다른 화면을 보여줄 필요가 있을 경우에 유용
- String 타입에는 다음과 같은 특별한 키워드를 붙여서 사용할 수 있음
- redirect: 리다이렉트 방식으로 처리
- forward: 포워드 방식으로 처리
- void
- 호출하는 URL과 동일한 이름의 jsp를 의미
@GetMapping("/ex05")
public void ex05() {
log.info("/ex05..........");
}
- VO, DTO (객체)타입
- 주로 JSON 타입의 데이터를 만들어서 반환하는 용도로 사용 (추가적인 라이브러리 필요)
- XML이나 JSON으로 처리
- @RepsoneBody 어노테이션과 같이 사용
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
@GetMapping("/ex06")
public @ResponseBody SampleDTO ex06() {
log.info("/ex06..........");
SampleDTO dto = new SampleDTO();
dto.setAge(10);
dto.setName("홍길동");
return dto;
}
- ResponsEntity 타입
- response할 때 Http 헤더 정보와 내용을 가공하는 용도로 사용 (추가적인 라이브러리 필요)
- HTTP 헤더 정보와 추가적인 데이터를 전달할 때 사용
@GetMapping("/ex07")
public ResponseEntity<String> ex07() {
log.info("/ex07..........");
// {"name": "홍길동"}
String msg = "{\"name\": \"홍길동\"}";
HttpHeaders header = new HttpHeaders();
header.add("Content-Type", "application/json;charset=UTF-8");
return new ResponseEntity<>(msg, header, HttpStatus.OK);
}
- Model, ModelAndView: Model로 데이터를 변환하거나 화면까지 같이 지정하는 경우에 사용 (최근에는 많이 사용하지 않음)
- HttpHeaders: 응답에 내용 없이 Http 헤더 메시지만 전달하는 용도로 사용
컨트롤러의 예외(Exception) 처리
- @ExceptionHandler와 @ControllerAdvice를 이용한 처리
- @ResponseEntity를 이용한 예외 메시지 구성
- @ControllerAdvice
- 예외처리와 원래의 컨트롤러가 혼합된 형태의 클래스가 작성되는 방식
- @ExceptionHandler는 해당 메소드가 () 들어가는 예외 타입을 처리한다는 것을 의미
@ControllerAdvice
@Log4j
public class CommonExceptionAdvice {
@ExceptionHandler(Exception.class)
public String except(Exception ex, Model model) {
log.error("Exception ......." + ex.getMessage());
model.addAttribute("exception", ex);
log.error(model);
return "error_page";
}
}
'강의 > KOSTA' 카테고리의 다른 글
[Spring] Spring Features and Dependency Injection (0) | 2022.05.03 |
---|---|
[Spring] Building a Spring Development Environment (0) | 2022.04.22 |
[JSP/Servlet] Model2 구현 (Day25) (0) | 2022.04.11 |
[JSP/Servlet] Model1 구현 (Day25) (1) | 2022.04.11 |
[JSP/Servlet] Session and Cookies (Day23) (0) | 2022.04.05 |