[Spring Boot] 스프링 웹 MVC

dsunni·2020년 8월 6일
0

1. Spring Web MVC

https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/web.html#spring-web

스프링 부트가 제공해주는 웹MVC의 기능들을 확장하고 싶을 때 추가적으로 설정 파일을 만들면 된다.

WebConfig 설정파일

spackage me.dsunni.config;

@Configuration
// @EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
}

@EnableWebMvc 어노테이션을 붙여주면 스프링부트의 기본적인 웹 MVC 기능들을 제외시키고 처음부터 생성해야 하므로 빼주자

기본적으로 많은 기능들을 제공하므로 굳이 생성할필요는 없다.



2. HttpMessageConverters

HttpMessageConverters는 스프링 프레임워크가 제공하는 인터페이스이고 스프링 MVC의 일부분이다.

HTTP 요청 본문을 객체로 변경하거나, 객체를 HTTP 응답 본문으로 변경할 때 사용한다.

보통 Spring의 @RequestBody, @ResponseBody와 함께 사용된다.


package me.dsunni.user;

import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    @PostMapping("/user")
    public User create(@RequestBody User user) {
        return null;
    }
}

어떤 요청을 받았고, 어떤 응답을 보내야하는지에 따라 HttpMessageConverters가 달라진다.

예를 들어 JSON 본문이 들어오면 JsonMessageConverter가 사용되어 JsonMessage를 User라는 객체로 Converting해준다. User 객체를 응답해야 할 때 JsonMessageConverter가 사용되며, String을 응답 할 때는 StringMessageConverter가 사용된다.

참고로 @RestController를 사용할 때는 @ResponseBody를 생략해도되지만 @Controller를 사용할 때는 @ResponseBody를 써줘야한다.

그래야지만 MessageConverter가 적용되기 때문이다.


JSONConverter 확인해보기

UserController.java

package me.dsunni.user;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    @PostMapping("/users/create")
    public User create(@RequestBody User user) {
        return user;
    }
}

User.java

package me.dsunni.user;

public class User {
    private Long id;
    private String username;
    private String password;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
		}
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

UserControllerTest.java

@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    public void createUser_JSON() throws Exception {
        String userJson ="{\"username\":\"dsunni\", \"password\":\"123\"}";

        mockMvc.perform(MockMvcRequestBuilders.post("/users/create")
        .contentType(MediaType.APPLICATION_JSON_UTF8)
        .accept(MediaType.APPLICATION_JSON_UTF8)
        .content(userJson))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.username", is(equalTo("dsunni"))))
            .andExpect(jsonPath("$.password", is(equalTo("123"))));
    }
}

JSON 데이터가 User객체로 매핑되는 것을 확인할 수 있다



3. ViewResolve

출처

출처: https://ict-nroo.tistory.com/99 [개발자의 기록습관]


스프링부트에 등록 되어있는 스프링 웹 MVC의 ContentNegotiatingViewResolver 가 어떤 contentType일 때 어떤 응답을 보내고, Accept header 요청에 의해서 해당 요청에 맞는 응답을 보내는 작업을 알아서 해준다. Accept Header에 따라 뷰 리졸버가 달라진다.

스프링 부트의 HttpMessageConverters는 HttpMessageConvertersAutoConfiguration 클래스로 인해서 적용이 된다. 해당 클래스를 찾아보면 spring-boot-autoconfigure의존성 아래에 http/ 안에 존재한다.

Accept header를 XML 타입으로 설정하고 xpath를 이용해서 XML로 받는 응답을 검증하는 테스트코드를 작성해보자.

@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void createUser_JSON() throws Exception {
        String userJson = "{\"username\":\"namjune\", \"password\":\"123\"}";
        mockMvc.perform(post("/users/create")
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .accept(MediaType.APPLICATION_XML)
            .content(userJson)
        )
            .andExpect(status().isOk())
            .andExpect(xpath("/User/username").string("namjune"))
            .andExpect(xpath("/User/password").string("123"));
    }
}

XML 메시지 컨버터 추가하기

<dependency>
   <groupId>com.fasterxml.jackson.dataformat</groupId>
   <artifactId>jackson-dataformat-xml</artifactId>
   <version>2.9.6</version>
</dependency>


4. 정적 리소스

Spring Boot Web MVC 기본 설정에서 정적 리소스를 제공한다. 정적 리소스란 웹 브라우저에서 요청이 들어왔을 때 이미 만들어져있는 리소스를 말한다.


기본 리소스 위치 /**

그 외 리소스를 제공해주는 네 가지 위치

  • classpath:/static
  • classpath:/public
  • classpath:/resources/
  • classpath:/META-INF/resources
    • 예) “/hello.html” => /static/hello.html

applciation.properties

  • spring.mvc.static-path-pattern: 맵핑 설정 변경 가능

  • spring.mvc.static-locations: 리소스 찾을 위치 변경 가능

    • application.yml에서 spring.mvc.static-path-pattern: /static/** 으로 설정 변경시

    • slocalhost:8080/hello.html => localhost:8080/static/hello.html로 접근

기본적으로 url은 / 루트로 설정되어있다. 만약 변경하고 싶으면 properties에서 설정해주면된다.

application.properties

spring.mvc.static-path-pattern=/static/**

  • Last-Modified 헤더를 보고 304 응답을 보냄.
  • ResourceHttpRequestHandler가 처리함.
    • WebMvcConfigurer의 addRersourceHandlers로 커스터마이징 할 수 있음
package me.dsunni.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/m/**")
                .addResourceLocations("classpath:/m/")
                .setCachePeriod(20);
    }
}

기존에 제공하는 리소스 핸들러는 그대로 유지하면서 원하는 리소스핸들러만 따로 추가할 수 있다.

경로 주의! "classpath:/m/" 이렇게 꼭 마지막이 / 로 끝나야한다.



5. 웹 JAR

JAR 파일은 여러개의 자바 클래스 파일들과, 관련 리소스 및 메타데이터를 하나로 묶어 자바 플랫폼에 라이브러리나 응용 소프트웨어를 배포하기 위한 소프트웨어 패키지 파일 포맷이다.

여러개의 파일들을 하나로 묶는 jar 명령을 사용해서 생성된다.


jQuery JAR 추가하기

https://mvnrepository.com/artifact/org.webjars.bower/jquery

<dependency>
  <groupId>org.webjars.bower</groupId>
  <artifactId>jquery</artifactId>
  <version>3.4.1</version>
</dependency>

버전 생략하고 사용

<dependency>
  <groupId>org.webjars</groupId>
  <artifactId>webjars-locator-core</artifactId>
  <version>0.43</version>
</dependency>

hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    Static Resource! ;)

    <script src="/webjars/jquery/dist/jquery.min.js"></script>
    <script>
   $(function() {
       console.log("ready!");
   });
</script>
</body>
</html>


6. index 페이지와 파비콘

(1) 인덱스 페이지

index페이지는 정적 페이지 혹은 동적페이지로 보여줄 수 있다.

리소스를 제공해주는 기본 위치 네가지에 index.html이라는 파일을 두면 Welcome Page, 정적인 인덱스 페이지로 사용 가능하다.


index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Index Page!</h1>
</body>
</html>

localhost:8080으로 들어가면 인덱스페이지가 보인다.


(2) 파비콘

https://favicon.io/ 에서 파비콘을 다운로드받고 static폴더 밑에 넣으면된다.



profile
https://dsunni.tistory.com/ 이사갑니답

0개의 댓글