Spring Web MVC - 핸들러 메소드
핸들러 메소드에서 다양한 아규먼트를 사용할 수 있다.
핸들러 메소드 아규먼트 | 설명 |
---|---|
WebRequest NativeWebRequest ServletRequest/Reponse HttpServletRequest/Reponse |
요청 또는 응답 객체에 접근 가능한 API |
InputStream Reader OutputStream Writer |
요청 본문을 읽어 오거나, 응답 본문을 쓸 때 사용할 수 있는 API |
PushBuilder | Spring 5에 추가됨. HTTP/2에서 사용할 수 있다. 리소스 푸쉬에 사용된다. 일반적으로 일어나는 HTTP 요청 : 1 클라이언트가 뷰 요청 2 서버 응답 (이 때 뷰에 다른 리소스 자원이 있어서 불러오고 싶음) 3 클라이언트가 이미지를 요청 4 서버 응답 PushBuilder : 1 클라이언트가 뷰 요청 2 서버 뷰 응답 3 서버가 리소스도 응답 (pushBuilder를 통해 서버가 능동적으로 push 를 미리 할 수 있다.) |
HttpMethod | GET, POST 등에 대한 정보 |
Locale TimeZone ZoneId |
LocaleResolver 가 분석한 요청의 Locale 정보를 파리미터로 받아서 사용할 수 있다. |
@PathVariable |
URI 탬플릿 변수를 읽을 때 사용한다. |
@MatrixVariable |
URI 경로 중 key/value 쌍을 읽어올 때 사용한다. |
@RequestParam |
서블릿 요청 매개변수 값을 선언한 메소드 아규먼트 타입으로 변환해준다. 단순 타입인 경우 이 애노테이션을 생략할 수 있다. |
@RequestHeader |
요청 헤더값을 선언한 메소드 아규먼트 타입으로 변환해준다. |
@ResponseBody |
리턴 값을 HttpMessqgeConverter 를 사용해서 응답 본문으로 바꾼다. |
HttpEntity, ResponseEntity | 응답 본문 뿐 아니라 헤더 정보까지, 전체 응답을 만들 때 사용한다. |
String | ViewResolver 를 사용해서 뷰를 찾을 때 사용할 뷰 이름이다. |
View | 암묵적인 모델 정보를 렌더링 할 뷰 인스턴스이다. |
Map, Model | 암묵적으로 판단한 뷰 렌더링 때 사용할 모델 정보이다. (RequestToViewNameTranslaator 를 통해 판단한다.) |
@ModelAtrribute |
암묵적으로 판단한 뷰 렌더링 때 사용할 모델 정보에 축가한다. (RequestToViewNameTranslaator 를 통해 판단한다.) 어노테이션 생략이 가능하다. |
핸들러 메소드 리턴은 주로 응답 또는 모델을 렌더링할 뷰에 대한 정보를 제공하는데 사용된다.
URI 패턴
@PathVariable
요청 URI 패턴의 일부를 핸들러 메소드의 아규먼트로 받는 방법이다.
타입 변환을 지원한다. 아래 컨트롤러 예시에서 보면, URI 는 String
타입인데 이를 자동으로 Integer
타입의 id 를 받아오는 것을 볼 수 있다.
기본값이 반드시 있어야 한다. 만약 없다면 null 을 받아오는데 이 때는 Optional
을 사용해서 null 처리를 할수는 있다. Optional<Integer>
이런 식으로 받아온다.
@MatrixVariable
요청 URI 패턴에서 키/값 쌍의 데이터를 핸들러 메소드의 아규먼트로 받는 방법이다. 이 역시 타입변환을 지원한다. 기본값도 반드시 있어야 하고, Optional 도 지원한다.
간단한 테스트 코드 및 컨트롤러 예제이다.
@WebMvcTest
class NewsControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void getNews() throws Exception {
// Given & When
mockMvc.perform(get("/news/1;title=today"))
.andDo(print())
// Then
.andExpect(status().isOk())
.andExpect(jsonPath("id").value(1))
.andExpect(jsonPath("title").value("today"))
;
}
}
@Getter @Setter
public class News {
private Integer id;
private String title;
}
@Controller
public class NewsController {
@GetMapping("/news/{id}")
@ResponseBody
public News news(@PathVariable Integer id, @MatrixVariable String title) {
News news = new News();
news.setId(id);
news.setTitle(title);
return news;
}
}
이렇게 실행하면 오류가난다. 세미콜론을 자동으로 제거하는 옵션 때문이다. 그런데 MatrixVariable
문법을 사용하려면 이를 URL 에 포함시켜 주어야 한다. 따라서 웹설정을 바꿔보도록 하자.
@Configuration
public class StoreWebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
@RequestParam
@RequestParam
를 통해 요청 매개변수에 들어있는 단순 타입 데이터를 핸들러 메소드의 아규먼트로 받아올 수 있다.
요청 매개변수란 쿼리 매개변수나 폼 데이터를 말한다.
이 애노테이션은 생략이 가능하지만, 명시적으로 코드가 헷갈리지 않게 적어주는 것을 추천한다.
@PostMapping("/news")
@ResponseBody
public News news(@RequestParam(value = "title", required = false, defaultValue = "무제") String myTitle) {
News news = new News();
news.setTitle(myTitle);
return news;
}
- 위와 같이하면, URL 에서 "title" 이라는 파라미터를 핸들러 메소드의 아규먼트로 받아올 수 있다.
required
의 기본값은 true 이며, 파라미터로 받아온 값이 반드시 있어야 한다. 기본값을 정하지 않아도 된다면required = false
로 할 수 있다. 그리고 이 때 기본값을defaultValue
로 설정할 수 있다. 또는Optional
로 기본값이 없는 경우 null 로 받아올 수도 있다.
간단하게 수정한 후 테스트를 해보자.
@Controller
public class NewsController {
@PostMapping("/news")
@ResponseBody
public News news(@RequestParam String title) {
News news = new News();
news.setTitle(title);
return news;
}
}
@Test
public void postNews() throws Exception {
// 쿼리 매개변수
mockMvc.perform(post("/news?title=무제"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("title").value("무제"))
;
}
// 폼 데이터
// mockMvc.perform(post("/news")
// .param("title", "무제"))
Map<String, String> 또는 MultiValueMap<String, String> 를 사용해서 요청 매개변수를 받아올 수 있다.
아래와 같이 코딩할 수 있다.
@Controller
public class NewsController {
@PostMapping("/news")
@ResponseBody
public News news(@RequestParam String title,
@RequestParam Integer limit) {
News news = new News();
news.setTitle(title);
news.setLimit(limit);
return news;
}
}
@Test
public void postNews() throws Exception {
mockMvc.perform(post("/news")
.param("title", "무제")
.param("limit", "20"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("title").value("무제"))
;
}
폼 서브밋
브라우저로 직접 확인하며 폼 서브밋 테스트하기
1) /news/form
GET 요청하여 폼 화면 불러오기
2) 화면에서 title 입력, limit 입력
3) 생성(submit) 버튼 클릭 하면 /news
로 POST 요청
4) POST 요청 컨트롤러를 통해 반환된 화면 보기
컨트롤러 구현
@Controller
public class NewsController {
// 1) /news/form GET 요청하여 폼 화면 불러오기
@GetMapping("/news/form")
public String newsForm(Model model) {
News news = new News();
news.setLimit(10); // 필드값 하나를 채워서 보내본다. 테스트용
model.addAttribute("news", news);
return "/news/form";
}
// 4) POST 요청 컨트롤러를 통해 반환된 화면 보기
@PostMapping("/news")
@ResponseBody
public News news(@RequestParam String title,
@RequestParam Integer limit) {
News news = new News();
news.setTitle(title);
news.setLimit(limit);
return news;
}
}
POST 요청을 보낼 form 화면을 만들어보자. resources/templates
폴더에 넣어주면 된다.
resources/templates/news/form.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Form</title>
</head>
<body>
<form action="#" th:action="@{/news}" method="post" th:object="${news}">
<!-- 2) 화면에서 title 입력, limit 입력 -->
<input type="text" title="title" th:field="*{title}" />
<input type="text" title="limit" th:field="*{limit}" />
<!-- 3) 생성(submit) 버튼 클릭 하면 `/news` 로 POST 요청 -->
<input type="submit" value="생성" />
</form>
</body>
</html>
Thymeleaf 문법
- @{} : 링크(URL) 표현식
- ${} : variable 표현식
- *{} : selection 표현식
form 태그를 보면, submit
이 일어난 경우 th:action="@{/news}"
로 액션을 취하라고 되어있다. 즉 <input type="submit" value="생성" />
버튼을 누르게 되면, /news
URL 로 POST 요청을 보내게 된다. 이 때 news 라는 이름의 object 가 함께 요청본문으로 보내진다.
또는 Postman 이라는 앱을 다운받고, POST 요청을 쉽게 전송할 수 있다.
테스트 코드 작성
@Test
public void newsForm() throws Exception {
mockMvc.perform(get("/news/form"))
.andDo(print())
.andExpect(view().name("/news/form"))
.andExpect(model().attributeExists("news"))
;
}
- 백기선님 스프링 웹 MVC 참고
'Java, Kotlin, Spring > Spring Web MVC' 카테고리의 다른 글
Spring Web MVC - Attributes, 멀티 폼 서브밋 (0) | 2021.02.21 |
---|---|
Spring Web MVC - ModelAttribute, 폼 서브밋 (0) | 2021.02.21 |
Spring Web MVC - RequestMapping (0) | 2021.02.15 |
Spring Web MVC - HTTP Message Converter (0) | 2021.02.13 |
Spring Web MVC - 여러가지 설정 1 (0) | 2021.02.13 |
댓글