@RequestMapping(value , method )
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SampleController {
@RequestMapping(value = "/hello", method = RequestMethod.GET) //http메소드를 지정하지 않으면 모든 http 메소드 허용
@ResponseBody // 없으면 이름에 해당하는 뷰로 돌아간다, 있으면 문자열을 응답으로 보냄
public String hello() {
return "hello";
}
}
url에 해당하는 HTTP 메소드가 없는경우 테스트를 진행해 보았다 "/hello"라는 url이 있어도 해당 HTTP 메소드가 없는 경우 테스트가 실패하는 것을 확인 할 수 있다
@ExtendWith(SpringExtension.class)
@WebMvcTest //mock을 주입해준다
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void helloTest() throws Exception{
mockMvc.perform(put("/hello"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello"));
}
}

@GetMapping, @PostMapping
하나의 HTTP 요청만을 처리하고 싶은경우 @GetMapping 등의 annotation을 사용 할 수 있다
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class SampleController {
@GetMapping("/hello")
@RequestBody
public String hello() {
return "hello";
}
}
HTTP Method
GET, POST, PUT, PATCH, DELETE
GET Request
클라이언트가 서버의 리소스를 요청할 때 사용한다
캐싱 할 수 있다
응답을 보낼때 캐시와 관련된 헤더를 응답에 넣어서 보낼 수 있다 동일 한 요청을 브라우저에서 보내면 조건적인 GET으로 바뀌어, if-not-modified, modified-since 헤더를 사용 하여 not-modified인 경우 서버가 응답에 ResponseBody를 없이 보내 클라이언트가 캐싱하고 있던 값을 그대로 사용가능하다
브라우저 기록에 남는다
북마크 할 수 있다
민감한 데이터를 보낼 때 사용하지 말아야 한다
url에 정보가 노출된다
idemponent
동일한 GET요청은 항상 동일한 응답을 응답한다.
POST 요청은 idemponent하지 않다.
POST Request
PUT Request
PATCH Request
DELETE Request
여러 문자열과 맵핑
@RequestMapping과 @GetMapping 등의 annotation에 배열 형태로 URI를 넣어준 경우 여러 문자열과 맵핑이 가능하다
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.ResponseBody;
@Controller
@RequestMapping(method = RequestMethod.GET)
public class SampleController {
@RequestMapping({"/hello", "/hi"}) //http메소드를 지정하지 않으면 모든 http 메소드 허용
@ResponseBody // 없으면 이름에 해당하는 뷰로 돌아간다, 있으면 문자열을 응답으로 보냄
public String hello() {
return "hello";
}
}
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(SpringExtension.class)
@WebMvcTest //mock을 주입해준다
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void helloTest() throws Exception{
mockMvc.perform(get("/hello"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello"));
mockMvc.perform(get("/hi"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello"));
}
}

특정 패턴으로 맵핑하기
@RequestMapping은 다음의 패턴을 지원한다
?
한 글자와 맵핑된다
"/hello/??" → "/hello/ee"
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.ResponseBody;
@Controller
@RequestMapping(method = RequestMethod.GET)
public class SampleController {
@GetMapping("/hello?")
@ResponseBody
public String hello() {
return "hello";
}
}
@ExtendWith(SpringExtension.class)
@WebMvcTest //mock을 주입해준다
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void helloTest() throws Exception{
mockMvc.perform(get("/hello1"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello"));
}
}

여러 글자와 맵핑된다
"/hello/*" → "hello/hongik"
**
여러 패스와 맵핑된다
"hello/**" → "hello/hongik/ce"
클래스에 선언한 @RequestMapping과 조합
클래스에 @RequestMapping annotation이 있는 경우 클래스의 @RequestMapping annotation URI 패턴 뒤에 이어서 메소드에 있는 @RequestMapping이 조합된다
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.ResponseBody;
@Controller
@RequestMapping("/hello")
public class SampleController {
@GetMapping("/**")
@ResponseBody
public String hello() {
return "hello";
}
}
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(SpringExtension.class)
@WebMvcTest //mock을 주입해준다
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void helloTest() throws Exception{
mockMvc.perform(get("/hello/hi/dd"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello"));
}

정규 표현식으로 맵핑
정규 표현식을 이용해 맵핑을 할 수 있다 @PathVariable을 이용해 path를 받아와 name으로 데이터 바인딩을 하고 이를 출력하였다
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/hello")
public class SampleController {
@GetMapping("/{name:[a-z]+}")
@ResponseBody
public String hello(@PathVariable String name) {
return "hello " + name;
}
}
@Test
public void helloTest() throws Exception{
mockMvc.perform(get("/hello/hongik"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello hongik"));
}
패턴이 중복될때
가장 구체적으로 맵핑되는 핸들러가 선택된다
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/hello")
public class SampleController {
@GetMapping("/hongik")
@ResponseBody
public String helloHongik() {
return "hello hongik";
}
@GetMapping("/**")
@ResponseBody
public String hello() {
return "hello";
}
}
@Test
public void helloTest() throws Exception{
mockMvc.perform(get("/hello/hongik"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello hongik"));
}

URI 확장자 맵핑
스프링 MVC의 경우
@RequestMapping("/hi")로 작성한경우 @RequestMapping({"/hi", "/hi.*"})로 맵핑을 자동으로 해준다
스프링 부트의 경우
보안 이슈(RFD Attack), URI변수 매개변수, URI 인코딩을 사용할 때 불명확 함으로 지원 해주지 않는다