SpringMVC-1일차

박상원·2024년 5월 13일

spring

목록 보기
4/15

Context


Spring에서 Context는 스프링이 관리하는 빈들이 담겨있는 컨테이너이다.

Root-Context

  • 모든 Servlet이 공유할 수 있는 Bean들이 모인 공간
  • @Repository, @Service, @Component, @Configuration

Bean Factory

  • Bean 생성및 의존관계 설정을 담당하는 가장 기본적인 IoC Container
  • Lazy loading : XmlBeanFactory 방식
    • 빈 로딩 요청을 받는 시점에 인스턴스를 만들고 로딩하는 방식
  • Pre loading : ApplicationContext 방식
    • 모든 빈들과 설정 파일들이 ApplicationContext에 의해 로드 요청이 될 때 인스턴스로 만들어지고 로드 되는 방식

ApplicationContext

  • Spring에서는 Root-Context를 ApplicationContext라고 부른다.
  • BeanFactory를 상속
  • ApplicationContext 구현체
    • ClassPathXmlApplicationContext
    • FileSystemXmlApplicationContext
    • AnnotationConfigWebApplicationContext

WebApplicationContext

  • Servlet 단위로 생성되는 context
    • DispatcherServlet(front Controller)
    • URL 관련 설정이 있는 bean
      • Interceptor, @Controller
      • Servlet 간에는 bean을 공유할 수 없음

root context, application context는 전역으로 공유되는 context이고
web application context, servlet context는 servlet 내부에서만 공유되는 context이다.

dispatcherServlet

  • Spring MVC Framework의 중심이 되는 Servlet
  • Controller로 향하는 모든 웹 요청의 entry point
  • Front Controller 디자인 패턴의 표현
  • 서블릿 이름에 해당되는 xml파일을 읽어드려 파일에 정의된 Bean들을 Spring IoC 컨테이너에 생성한다.

basse package 설정

  • use-default-filters=true(default = true)
    • @Controller, @Repository, @Component, @Service, @Configuration ... 스켄을 한다.
  • use-default-filters=false + include-filter를 사용해서 @Controller만 스켄될 수 있도록 설정
<context:component-scan base-package="com.nhnacademy.springmvc" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

use-default-filters를 false로 두는 이유는 scope를 정해주기 위해서이다. 스켄이 될 필요가 없는 Bean을 제외하기 위해 필요한 것만 처리를 하기 위해 사용한다.

WebMvc Configuration

@EnableWebMvc

  • 기본설정
  • WebMvcConfigurationSupport에서 구성한 Spring MVC 구성을 사용하겠다는 의미

ServletContainerInitializer와 ServletContextListener 차이

  • ServletContainerInitializer(SCI)를 이용한 초기화
    • ServletContainerInitializer는 서블릿 컨테이너가 시작될 때 자동으로 실행되므로, 개발자가 별도의 초기화 코드를 작성할 필요가 없다.
    • SCI를 사용하면 웹 어플리케이션은 서블릿 컨테이너와 독립적으로 유지될 수 있다.
    • 서블릿, 필터, 리스너, 그리고 컨트롤러 등의 초기화 작업을 한꺼번에 처리할 수 있다.
  • ServletContextListener를 이용한 초기화
    • 개발자는 웹 어플리케이션의 생명주기 이벤트를 통해 필요한 초기화 및 정리 작업을 수행할 수 있다.
    • 특정 이벤트에서만 필요한 초기화 코드를 작성할 수 있다.
    • 웹 어플리케이션이 시작되거나 종료될 때 특정 리소스를 초기화하거나 종료하는 작업을 수행할 때 유용하다.

Listener를 사용하면 Servlet에 의존하고 Initializer는 Servlet에 독립적이라 확장이 용이하다.

URL Pattern


Serlet에서의 URL Pattern

  • / : default servlet
  • /* : 하위 경로 전체
  • *.do : 확장자 매칭 (확장자가 '.do'인 경우)

Spring MVC에서의 URL Pattern

Apache Ant

  • xml기반의 빌드툴

Ant style Pattern 지원

  • ? : 1글자 매칭
    • : 0글자 이상 매칭
  • ** : 0글자 이상 하위경로 매칭

@ModelAttribute


@ModelAttribute-1

메서드 인자로 선언된 경우 : 모델에서 속성 값을 추출해올 때 사용

@PostMapping("/user/register")
public String registerUser(@ModelAttribute UserRegisterRequest userRequest) {
    // ...
}

@ModelAttribute를 사용하지 않는다면

@PostMapping
public ModelAndView registerUser(String id, String password, String age) {
    // ...
}

Request Parameter Binding은 사실 @ModelAttribute를 생략할 수 있다.

public ModelAndView registerUser(UserRegisterRequest userRequest){
    //...
}

@ModelAttribute-2

메서드에 선언된 경우 : 모든 @RequestMapping에 앞서 호출되어 공통 속성을 제공

@ModelAttribute("user")
public User getUser(@PathVariable("userId") String userId) {
    return userRepository.getUser(userId);
}
@GetMapping("/{userId}")
public String getUserInfo(@ModelAttribute("user") User user, Model model) {

    if (Objects.isNull(user)) {
        model.addAttribute("exception", new UserNotFoundException());
        return "error";
    }

    model.addAttribute("user", user);
    return "userInfo";
}

Controller


  • MVC 패턴에서 Controller역할
    • 요청 처리 및 흐름 제어 담당
  • Front Controller 패턴에서 Command interface 구현 클래스에 해당
    • 실제 웹 요청을 처리하는 역할

Controller 구현

@Controller

  • stereo type bean 중 하나 : component scan 과정을 통해 자동으로 bean 등록

Controller 구현 2

**@RestController

  • @RestController = @Controller + @ResponseBody
  • @Controller가 view 이름을 반환하면 ViewResolver가 view를 처리하는 반면
  • @RestController는 ViewResolver가 아닌 HttpMessageConverter가 응답 객체를 처리

Controller Method에서 사용 가능한 method argument

  • HttpServletRequest, HttpServletResponse, HttpSession, WebRequest
  • Locale
  • InputStream, OutputStream, Reader, Writer
  • @PathVariable, @RequestParam, @RequestHeader, @CookieValue, @Value
  • Map, Model, ModelMap, @ModelAttribute, @RequestBody
  • Errors, BindingResult, ...

Controller Method에서 사용 가능한 return type

  • ModelAndView, View
  • Map, Model, ModelMap
  • String
  • void
  • @ResponseBody
  • POJO

Model 이용하기

  • 개발자가 직접 request.setAttribute를 이용해서 전달해도 되지만 전달 되는 부분을 추상화한 것이 Model이다.

Model로 이용할 수 있는 type

  • java.util.Map interface
  • org.springframework.ui.Model interface
  • org.springframework.ui.ModelMap class

실제 처리되는 내용

  • Model에 설정한 속성(attribute)이 View에 request.attribute로 전달됨

요청 parameter 받아오기

@RequestParam

  • 요청 URL의 Query String을 처리하기 위한 어노테이션

요청 URL의 가변 인자 가져오기

@PathVariable

  • 요청 URL의 Resource(Path)을 처리하기 위한 어노테이션
    • @RequestMapping의 path에 변수명을 입력받기 위한 place holder가 필요함

Post form 같은 경우는 @Requestparam을 사용해서 처리할 수는 있지만 parameter가 많아질 수 있기 때문에 비효율적이므로 @ModelAttribute를 통해 처리한다.

요청 Header 값 읽어오기

@RequestHeader

  • 요청의 HTTP 헤더를 처리하기 위한 어노테이션

@CookieValue

  • HTTP 쿠키를 처리하기 위한 어노테이션

@ControllerAdvice

@ControllerAdvice는 스프링 프레임워크에서 전역으로 적용되는 컨트롤러에서 발생하는 예외를 처리하고 공통된 코드를 적용하는 데 사용되는 어노테이션이다.
이 어노테이션을 사용하면 여러 컨트롤러에 대한 예외 처리를 한 곳에서 일괄적으로 관리할 수 있다.

전역 예외 처리

@ExceptionHandler 어노테이션을 사용하여 특정 예외 타입에 대한 처리 로직을 정의할 수 있다.
이 예외 처리 로직은 어떤 컨트롤러에서든 발생한 예외에 대해 적용된다.

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception e) {
        ModelAndView modelAndView = new ModelAndView("errorView");
        modelAndView.addObject("error", e.getMessage());
        return modelAndView;
    }
}

전역 모델 속성 추가

@ModelAttribute 어노테이션을 사용하여 전역적으로 모델 속성을 추가할 수 있다.
이는 모든 컨트롤러에서 공통적으로 사용되는 데이터를 설정할 때 유용하다.

@ControllerAdvice
public class GlobalControllerAdvice {

    @ModelAttribute("commonAttribute")
    public String addCommonAttribute() {
        return "This is a common attribute";
    }
}

전역 초기화 작업

@InitBinder 어노테이션을 사용하여 컨트롤러에서 전역적으로 초기화 작업을 수행할 수 있다.
주로 데이터 바인딩 설정이나 검증 관련 초기화에 사용된다.

@ControllerAdvice
public class GlobalInitBinder {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 데이터 바인딩 설정
    }
}

Validation

  • @Value : 이 어노테이션이 적용된 클래스는 불변하게 만들어진다. @Value 어노테이션이 사용되면 해당 클래스는 필드에 대한 게터 메서드, 생성자, equals, hashCode, toString 메서드가 자동으로 생성된다.
  • @NotBlank : Bean Validation의 어노테이션 중 하나로, 해당 필드가 null이 아니거나 빈 문자열이 아닌지를 검증한다. 만약 null이거나 빈 문자열이라면 유효성 검사에 실패하게 된다.
  • @Length : Bean Validation의 어노테이션 중 하나로, 해당 필드의 길이가 자동으로 지정된 범위 내에 있는지를 검증한다.

Spring's Validation

Spring에서 Validation을 적용하기 위해서는 Validator interface를 구현해야한다.

public interface Validator {
	boolean supports(Class<?> clazz);
	void validate(Object target, Errors errors);
}
@Component
public class PostRegisterRequestValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return PostRegisterRequest.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "", "title is empty");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "content", "", "content is empty");

        PostRegisterRequest request = (PostRegisterRequest) target;
        String content = request.getContent();
        if (content.length() > 100) {
            errors.rejectValue("content", "", "content max length is 100");
        }
    }
}

0개의 댓글