Java Spring은 MVC 디자인 패턴을 사용한다.
데이터 모델을 표현하는 POJO (Plain Old Java Object)
// SamplePayload.java
public class SamplePayload {
private String name; // 사용자의 이름을 저장하는 멤버 변수
private int age; // 사용자의 나이를 저장하는 멤버 변수
private String occupation; // 사용자의 직업을 저장하는 멤버 변수
// 생성자
public SamplePayload(String name, int age, String occupation) {
this.name = name;
this.age = age;
this.occupation = occupation;
}
// name에 대한 getter
public String getName() {
return name;
}
// name에 대한 setter
public void setName(String name) {
this.name = name;
}
// age에 대한 getter
public int getAge() {
return age;
}
// age에 대한 setter
public void setAge(int age) {
this.age = age;
}
// occupation에 대한 getter
public String getOccupation() {
return occupation;
}
// occupation에 대한 setter
public void setOccupation(String occupation) {
this.occupation = occupation;
}
// 객체의 정보를 문자열로 변환해주는 toString 메서드
@Override
public String toString() {
return "SamplePayload{" +
"name='" + name + '\'' +
", age=" + age +
", occupation='" + occupation + '\'' +
'}';
}
}
RESTful 웹 서비스의 endpoint들을 정의하는 컨트롤러
// SampleRestController.java
@RestController // REST API를 제공하기 위한 컨트롤러 어노테이션
@RequestMapping("/rest") // 이 컨트롤러의 기본 URL 경로 설정
public class SampleRestController {
private static final Logger logger = LoggerFactory.getLogger(SampleRestController.class ); // 로깅을 위한 객체
// SamplePayload 객체를 반환하는 endpoint
@GetMapping("/sample-payload")
public SamplePayload samplePayloadGet() {
logger.info("Returning SamplePayload object");
return new SamplePayload("taeho", 25, "student");
}
// 이미지 파일을 반환하는 endpoint
@GetMapping(
value = "/sample-image",
produces = MediaType.IMAGE_PNG_VALUE // 클라이언트에 반환되는 응답의 MIME 타입을 설정
)
public byte[] sampleImage() throws IOException {
logger.info("Returning image");
InputStream inputStream = getClass().getResourceAsStream("/static/img.png"); // 이미지 파일을 읽어옴
assert inputStream != null; // inputStream이 null이 아닌지 확인
return inputStream.readAllBytes(); // 이미지 파일의 바이트 배열을 반환
}
}
결과
아주 잘 된다
웹 애플리케이션에서 사용되는 서버사이드 템플릿 엔진
Java를 기반으로 하는 웹 애플리케이션을 위한 서버사이드 템플릿 엔진
자바 웹 애플리케이션을 위한 모던 서버사이드 Java 템플릿 엔진
Spring Framework와의 통합이 잘 되어 있다.
// SampleController.java
@Controller // 컨트롤러 클래스를 정의. 웹 요청을 처리하는 클래스임을 나타냄.
public class SampleController {
private static final Logger logger = LoggerFactory.getLogger(SampleController.class); // 로거 객체 생성
@GetMapping("/sample-thyme") // "/sample-thyme" URL에 대한 GET 요청을 처리.
public ModelAndView sampleThyme() {
logger.info("in sample thyme"); // 로깅 정보 출력
ModelAndView modelAndView = new ModelAndView(); // ModelAndView 객체 생성. 데이터와 뷰 정보를 담아 반환하는 객체
List<SamplePayload> profiles = new ArrayList<>(); // SamplePayload 객체 리스트 생성
// SamplePayload 객체들을 리스트에 추가
profiles.add(new SamplePayload("taeho", 25, "students"));
profiles.add(new SamplePayload("ahyoung", 25, "students"));
profiles.add(new SamplePayload("hyundong", 26, "students"));
profiles.add(new SamplePayload("sungho", 24, "students"));
modelAndView.addObject("profiles", profiles); // profiles 리스트를 ModelAndView 객체에 추가
modelAndView.setViewName("view-thyme"); // 뷰 이름 설정. Thymeleaf 템플릿을 찾을 때 사용.
return modelAndView; // ModelAndView 객체 반환
}
<!-- resources/templates/view-thyme.html -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
<!-- Thymeleaf 네임스페이스와 기본 HTML 네임스페이스 선언 -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>View Profiles</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Occupation</th>
</tr>
</thead>
<tbody>
<!-- Thymeleaf 반복문을 사용하여 profiles 리스트의 각 항목을 순회하며 테이블 로우 생성 -->
<tr th:each="profile: ${profiles}">
<td th:text="${profile.name}"></td> <!-- 프로필의 이름 출력 -->
<td th:text="${profile.age}"></td> <!-- 프로필의 나이 출력 -->
<td th:text="${profile.occupation}"></td> <!-- 프로필의 직업 출력 -->
</tr>
</tbody>
</table>
</body>
</html>
서버를 실행시키고 브라우저에서 접속해보자~
Post 요청을 날려보자
// SampleRestController.java
@RestController // REST API 응답을 위한 어노테이션. 별도의 View가 아닌 데이터만을 반환.
@RequestMapping("/rest") // 이 컨트롤러의 기본 URL 경로 설정.
public class SampleRestController {
private static final Logger logger = LoggerFactory.getLogger(SampleRestController.class); // 로깅을 위한 객체 초기화.
// JSON 형식의 SamplePayload 객체를 받는 POST 메서드.
@PostMapping("/sample-payload")
@ResponseStatus(HttpStatus.NO_CONTENT) // 정상적으로 로직이 처리되었을 때 응답할 HTTP 상태 코드.
public void samplePayloadPost(@RequestBody SamplePayload samplePayload) {
// 받아온 객체의 정보를 로깅.
logger.info(samplePayload.toString());
}
// Multipart 형식의 데이터를 받는 POST 메서드.
@PostMapping(
value = "/sample-multipart",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE // 이 endpoint는 multipart form data를 받음.
)
@ResponseStatus(HttpStatus.NO_CONTENT) // 정상적으로 로직이 처리되었을 때 응답할 HTTP 상태 코드.
public void sampleMultipartPost(
@RequestParam("name") String name, // form에서 "name" 파라미터를 받음.
@RequestParam("age") Integer age, // form에서 "age" 파라미터를 받음.
@RequestParam("occupation") String occupation, // form에서 "occupation" 파라미터를 받음.
@RequestParam("file") MultipartFile multipartFile // form에서 "file" 파라미터(파일)을 받음.
) {
// 받아온 파라미터들의 정보를 로깅.
logger.info("name: " + name);
logger.info("age: " + age);
logger.info("occupation: " + occupation);
logger.info("file: " + multipartFile.getOriginalFilename()); // 파일의 원래 이름을 로깅.
}
}
타입 설정을 안해주었기 때문에, json으로 작성해서 날려야 잘 작동한다.
짜잔~
요건 타입 설정을 해주었기 때문에 이렇게 요청 가능하다.
짜자잔~
자바 재밌다