스프링 입문 - 02. 스프링 웹 개발 기초
thymeleaf 템플릿 엔진 작동 확인
// java/hello/hellospring/controller/HelloController.java
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model){
model.addAttribute("data", "hello!!");
return "hello";
}
<!-- resources/templates/hello.html -->
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p th:text = "'안녕하세요. ' + ${data}"> 안녕하세요. 손님</p>
</body>
</html>
@Controller
Controller class 에는 @Controller 어노테이션을 적어 준다. 이는 Spring Bean으로 등록시켜 주고 Controller 클래스라고 쉽게 알 수 있게 해 준다.
@GetMapping
Controller 내 HTTP GET reqeust를 메소드와 mapping 시키기 위함이다. @GetMapping("hello)는 localhost:8080/hello의 url로 들어갈 때 동작한다.
Model
parameter로 들어가 있는 Model은 Spring Model에 추가하고, 검색하기 위한 인터페이스이다.
model.addAttribute("data", "hello!!");
는 model의 data라는 key에 hello라는 값을 추가한다는 의미이다.
html에서 ${data}로 value를 받아올 수 있다.
return "hello"
"hello"라는 이름을 가진 view를 호출한다. (여기선 templates 폴더 안의 hello.html)
템플릿 엔진 작동원리
- client가 url에 접속하여 request를 보냄.
- 내장 tomcat 웹서버에서 스프링 컨테이너로 전달
- 스프링 컨테이너가 해당 controller의 함수 실행
- controller에서 viewResolver로 데이터 전달
- viewResolver는 받은 데이터를 템플릿 엔진에서 처리
- 처리된 html 파일을 다시 tomcat 웹서버를 통해 client로 전달.
정적 콘텐츠
resources/static/hello-static.html
정적콘텐츠는 서버에서 직접 클라이언트에 파일 채로 보내주는 것인데, 여기서는 html 을 하나 만들고 controller도 없이 접근하는 것을 보여준다.
정적 컨텐츠 작동원리
- client가 url에 접속하여 request를 보냄.
- 내장 tomcat 웹서버에서 스프링 컨테이너로 전달
- 스프링 컨테이너가 해당 controller의 함수 찾아봄
- 함수가 없으므로 static 파일 중 hello-static.html을 찾아봄
- 다시 tomcat 웹서버를 통해 client로 전달.
MVC와 템플릿 엔진
@GetMapping("hello-mvc")
public String helloMVC(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
<!-- resources/templates/hello-template.html -->
<!doctype html>
<html lang="en" xmlns:th = "http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p th:text = "'hello' + ${name}">hello! empty!</p>
</body>
</html>
@RequestParam
해당 url에서 "name"이라는 query 값을 찾아서 name이라는 parameter에 넣어준다.
required가 true가 기본이므로 query가 없으면 에러가 난다. required를 false로 지정해 주면 query가 없을 때 에러가 나지 않게 해 줄 수도 있다.
API
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name){
return "hello " + name;
}
@ResponseBody
이 annotation을 사용하면 위에서 사용한 ViewResolver를 사용하지 않고 String을 직접 HTTP Body (html body 아님) 반환한다.
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name);
return hello;
}
static class Hello{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
위와 같이 String이 아닌 객체로 호출도 가능하다.
정말 신기하게도 객체를 호출하면 json형태로 반환이 된다.
ResponseBody 작동원리
- client가 url에 접속하여 request를 보냄.
- 내장 tomcat 웹서버에서 스프링 컨테이너로 전달
- 스프링 컨테이너가 해당 controller의 함수 실행
- controller에서 HttpMessageConverter로 전달
- JsonConverter 혹은 StringConverter가 작동
기본 문자 처리 : StringHttpMessageConverter
기본 객체 처리 : MappingJackson2HttpMessageConverter - 그대로 client에 전달 (string -> string, object -> json)