kok202
스프링 부트 강의 정리 (13~14 : HttpMessageConverter, Static content)

2019. 4. 21. 04:26[공부] 영상/스프링 부트 강의

스프링 부트는 Tomcat, jetty, undertow, netty등을 내장하고 있어서 Web 개발에 유용하다.

spring-boot-web 를 이용하면 빠르게 웹개발을 빠르게 시작해볼 수 있다.

spring-boot-starter-webflux 를 이용하면 reactive web 어플리케이션을 개발 할 수 도 있다.

 

 

 

 

 

spring mvc : controller, restcontroller 로 http request를 핸들링한다. 

spring boot 는 spring web mvc를 위한 auto configuration을 제공한다. 

 

Spring Web Auto-configuration의 특징

controller의 return string -> ViewResolver -> View -> ContentNegotiatingViewResolver -> View

1. ContentNegotiatingViewResolver 를 내장한다. : 요청이 어떤 형태인지 판단하고 적절한 타입으로 뷰를 리턴하는 것. (ex. html 다큐먼트를 요구하는 요청 이면 html 파일을 전달해준다.)

2. BeanNameViewResolver : Bean 타입의 View를 리턴하려고 할 때 스트링을 기반으로 Bean의 이름에 맞춰 찾게 해주는 resolver. 

3. static resources 제공 : favicon, index.html 등...

4. Automatic Converter 제공

5. HttpMessageConverter : controller의 리턴 타입에 따라 어떻게 반환할 것이냐

6. MessageCodeResolver

등...

 

 

 

 

WebMvcConfigurer

@Configuration
public class WebMVCConfiguration implements WebMvcConfigurer{
    // 원하는 설정에 맞는 메소드 오버라이딩
}

Spring boot 를 완전히 컨트롤 하고 싶으면 @EnableWebMvc를 적용하면 된다. -> 일일히 다 오버라이딩 해줘야하는 단점이 있다.

 

 

 

 

 

HttpMessageConverter

- 기본적으로 스트링은 UTF-8로 인코딩해준다.

- @ResponseBody 가 붙은 타입을 Converting 하는 방법들이 적힌 클래스다.

- @ResponseBody 가 붙은 변수는 모두 HttpMessageConverter를 거친다.

- 추가로 컨트롤러의 메소드가 어떤 값을 반환할 때도 HttpMessageConverter를 거친다. 메소드의 반환 타입을 정의해줄 때 원래 @ResponseBody가 붙어야하는건데 생략할 수 있게 된 것 뿐이다.

@ArgsConstructor
public class User{
    public String id;
    public String pwd;
}
@RestController
@RequestMapping("/user")
public class UserController{

    @GetMapping("/test")
    public User test(){
        return new User("scott", "tiger");
    }
    
//    @GetMapping("/test")
//    public @ResponseBody User test(){
//        return new User("scott", "tiger");
//    }

}

- 즉 위의 예시에서 new User("scott", "tiger") 는 JsonHttpMessageConverter를 통해서 Converting이 되고 이 결과를 return하는 것이다. 

 

 

 

 

 

스프링 프레임워크에 기본적으로 내장되어있는 HttpMessageConverter 들

  • ByteArrayHttpMessageConverter
  • StringHttpMessageConverter
  • JsonHttpMessageConverter
  • XmlHttpMessageConverter
  • ResourceHttpMessageConverter 등 ...

converter list 에 customConverter를 추가할 수도 있다.

ex. gson이 기본적으로 내장이 안되있으니 gson을 추가해보자

@Configuration
public class WebConfig implements WebMvcConfigurer{
    @Bean
    public HttpMessageConverters customConverter(){
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        return new HttpMessageConverters(converter);
    }
}

* 메이븐에 gson 모듈을 import하면 스프링 부트가 알아서 GsonHttpMessageConverter를 추가한다.

단 gson이 있더라도 jackson이 있다면 JacksonHttpMessageConverter를 우선해서 converter로 추가한다.

이런 경우 위와 같이 굳이 customConverter를 등록해주지 않아도 하는 properties로 GsonHttpMessageConverter를 추가하는 방법이 존재한다. 그리고 이게 조금더 안전해보여서 권장된다.

spring.http.converters.preferred-json-mapper=gson

 

 

 

 

 

@JsonComponent

JsonHttpMessageConverter 가 Jackson으로 serialize 하거나 deserialize 할 때 @JsonComponent 를 사용한 클래스 안에 선언한 serializer, deserializer 를 사용하게 만들 수 있다. @JsonComponent 에 정의된 내부 클래스들이 스프링 부트에서 이미 선언된 ObjectMapper에 자동으로 들어가게 된다.

 

 

 

 

MessageCodeResolver

Error코드를 어떻게 생성할 것이냐?를 정의 할 수 있다.

@Controller
@RequestMapping("/user")
public class UserController{
    @GetMapping("/signup")
    public String signUp(){
        return "user/signUpForm";
    }
    
    @PostMapping("/signup")
    public String signUpComplete(@ModelAttribute @Valid User user,BindingResult error){
        if(error.hasErrors()){
            return "user/signUpForm";
        }
        return "redirect:/user";
    }
}

 

 

 

 

Static Content

resource/static/hello.html 로 정의 해두면 localhost:8080/hello.html 으로 접근할 때 controller 없이도 hello.html을 보여주도록 할 수 있다. hello.html을 처리하는 핸들러는 DefaultServletHttpRequestHandler가 담당한다. 다만 이 핸들러의 우선순위는 가장 낮다. 어노테이션 매핑을 실패하고 넘어온 URL 이 이 핸들러를 거친다.

 

Static content 관련 properties

spring.mvc.static-path-pattern= /static/**
spring.resources.static-location= classpath:/html

localhost:8080/static 으로 들어오는 요청은 static content를 찾아 출력하겠다.

localhost:8080/static/hello.html 으로 요청이 들어올 경우 resource/html/hello.html 을 찾아보겠다.