JAVA

[SpringBoot]인스타그램 2강 컨트롤러

instagram

[SpringBoot]인스타그램 2강 컨트롤러

컨트롤러(Controller)란?

사용자의 요청에 맞는 Java 파일을 호출할 수 있게 분기해주는 역할을 한다. 프로그램의 가장 앞부분에서 분기하기 때문에 이를 FrontController라고 부른다. 웹 페이지에서 이루어지는 수 많은 요청을 관리하기 위해 요청의 종류별로 FrontController를 분류한다. 사용자에 관한 요청은 UserController, 게시판에 관한 요청은 BoardController 등 파일을 따로 만들어서 도메인 별로 분기되게 만든다. 스프링에서는 Dispatcher가 이 일을 한다.

springboot
[Spring Boot]기본 개념 3강 스프링부트 동작원리1.서블릿 컨테이너 2.web.xml 3.DispatcherServlet 4.스프링 컨테이너 5.컨트롤러로 요청 6.응답...

HTTP 요청

서버와 클라이언트가 데이터를 교환하기 위한 요청. HTTP 요청의 종류에는 GET, POST, PUT, DELETE가 있다.

HTTP 요청 종류

종류 의미 비고
GET 데이터 요청
POST 데이터 전송 HTTP BODY 필요
PUT 데이터 갱신 HTTP BODY 필요
DELETE 데이터 삭제

컨트롤러에서 HTTP 요청하기 예제

package com.cos.photogramstart;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

//@Controller // File을 응답하는 컨트롤러(클라이언트가 브라우저면 html 파일을)
@RestController // Data를 응답하는 컨트롤러(클라이언트가 핸드폰이면 데이터를) 
public class HttpController {

  // http://localhost:8080/get
  @GetMapping("/get")
  public String get() {
    return "get요청됨";
  }

  // http://localhost:8080/post
  @GetMapping("/post")
  public String post() {
    return "post요청됨";
  }

  // http://localhost:8080/put
  @GetMapping("/put")
  public String put() {
    return "put요청됨";
  }

  // http://localhost:8080/delete
  @GetMapping("/delete")
  public String delete() {
    return "delete요청됨";
  }

}

 

브라우저에서는 GET만 테스트해 볼 수 있기으니 포스트맨을 사용하여 POST, PUT, DELTE도 테스트해보자.
spring
postman으로 HTTP 요청 테스트하기Postman이란 개발한 API를 테스트하고, 테스트 결과를 공유하여 API 개발의 생산성을 높여주는 플랫폼입니다....

Path Valuable과 Query String

사용자가 데이터 요청을 구체적으로 하기 방법으로 스프링부트에서는 주로 Path Valueable방식을 사용한다.

Path Valuable 요청 방식의 주소http://localhost:8080/board/1

Query String 요청 방식의 주소http://localhost:8080?board=1

package com.cos.photogramstart;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

public class QueryPathController {
  
  @GetMapping("/chicken")
  public String chickenQuery(String type) {
    return type+"배달갑니다.(쿼리스트링)";
  }
  
  @GetMapping("/chuicken/{type}")
  public String chickenPath(@PathVariable String type) {
    return type+"배달갑니다.(패스밸리어블)";
  }
  
}

HTTP HEADER & BODY

HTTP 요청시 데이터 부가적인 정보를 전송할 수 있는데 이를 HTTP 헤더라고 부르고 전송하는 데이터를 바디라고 부른다. 헤더에는 Content-Type이라는 데이터의 타입을 명시하는 부분이 존재한다. 스프링에서는 Content-Type의 디폴트 값이 x-www-form-urlencoded 타입이다.

Context-Type의 종류

Content-Type 데이터 형태
x-www-form-urlencoded key=value
text/plain 문자열
application/json { “key” : “value” }
1.x-www-form-urlencoded
	@PostMapping("/body1")
	public String xwwwformurlencoded(String username) {
		log.info(username);
		return "key=value 전송옴";
	}
	
2.text/plain
	@PostMapping("/body2") 
	public String plaintext(@RequestBody String data) {
		log.info(data);
		return "text/plain 전송옴";
	}
3.application/json
전체 데이터
	@PostMapping("/body3")
	public String applicationjson(@RequestBody String data) {
		log.info(data);
		return "json 전송옴";
	}	
	
데이터 선택
	@PostMapping("/body4")
	public String applicationjsonToObject(@RequestBody User user) {
		log.info(user.getUsername());
		return "json 전송옴";
	}
전체코드
package com.cos.animalapp.web;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.cos.animalapp.domain.User;

@RestController
public class HttpBodyController {

  
  private static final Logger log = LoggerFactory.getLogger(HttpBodyController.class);

  
  @PostMapping("/body1")
  public String xwwwformurlencoded(String username) {
    log.info(username);
    return "key=value 전송옴";
  }
  
  @PostMapping("/body2") 
  public String plaintext(@RequestBody String data) {
    log.info(data);
    return "text/plain 전송옴";
  }
  
  @PostMapping("/body3")
  public String applicationjson(@RequestBody String data) {
    log.info(data);
    return "json 전송옴";
  }	
  
  @PostMapping("/body4")
  public String applicationjsonToObject(@RequestBody User user) {
    log.info(user.getUsername());
    return "json 전송옴";
  }
  
  
}

json 응답 – 데이터 리턴

json 타입의 데이터를 응답받을 때 스프링부트가 내부적으로 가지고 있는 MessageConverter를 이용하면 직접 json으로 코드를 짜서 응답하는 불편함을 해결해 줄 수 있다. MessageConverter는 @RestController를 사용했을 때만 작동한다. @Controller를 사용할 경우 리턴타입에 @ResponseBody를 추가하면 MessageConverter를 작동 시킬 수 있다.

package com.cos.animalapp.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.animalapp.domain.User;

@RestController
public class HttpResponseJsonController {

  @GetMapping("/resp/json")
  public String respJson() {
    return "{\"username\":\"cos\"}";
  }
  
  @GetMapping("/resp/json/object")
  public String respJsonObject() {
    User user = new User();
    user.setUsername("홍길동");
    
    String data = "{\"username\":\""+user.getUsername()+"\"}";
    return data;
  }
  
  
  @GetMapping("/resp/json/javaobject")
  public User respJsonJavaObject() {
    User user = new User();
    user.setUsername("홍길동");
    return user; // 1. MessageConverter 작동 : JavaObject를 Json(旧 xml)으로 변경해서 통신을 통해 응답을 해준다.
               // 2. @RestController 일때만 MessageConverter가 작동한다.
  }
  
}
@Controller에서 @ResponseBody 사용법
package com.cos.animalapp.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.animalapp.domain.User;

@Controller
public class HttpResponseJsonController {

	@GetMapping("/resp/json/javaobject")
	public @ResponseBody User respJsonJavaObject() {
		User user = new User();
		user.setUsername("홍길동");
		return user;
	}
	
}
결과 화면

html 응답 – 파일 리턴

자바코드가 포함되어 있는 파일을 브라우저가 해석하기 위해서는 템플릿 엔진(Template Engine)을 사용한다. 내부적으로 템플릿 엔진을 포함하고 있는 대표적인 예로 mustache와 jsp가 있다. 기본적으로 스프링에서는 mustache를 지원하지만 여전히 한국에서는 jsp를 많이 사용하기 때문에 jsp 사용법도 알아두는 것이 좋다.

txt 파일 응답

디폴트 경로 : resources/static

Controller
	@GetMapping("/txt")
	public String txt() {
		return "a.txt";
	}
a.txt
This file is a.txt.
결과 화면

mustache 파일 응답

디폴트 경로 : resources/templates

mustache 사용하기
<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mustache -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mustache</artifactId>
        </dependency>

라이브러리 추가 후 서버 재시작

controller
	@GetMapping("/mus")
	public String mus() {
		return "b";
	}
b.mustache
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This file is b.mustache.</h1>
</body>
</html>

jsp 파일 응답

디폴트 경로 : src/main/webapp/WEB-INF/views

jsp 사용하기
<dependencies>

  <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper</artifactId>
    <version>9.0.41</version>
  </dependency>

라이브러리 추가 후 서버 재시작. 템플릿 엔진은 하나만 사용할 수 있다.

경로 설정하기

jsp는 스프링부트에서 지원하고 있지 않기 때문에 경로를 직접 설정(viewResolver 설정)해야 한다.

spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
controller
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>This file is c.jsp</h1>
</body>
</html>
c.jsp
	@GetMapping("/jsp")
	public String jsp() {
		return "c";
	}

jsp 파일에서 Java 코드 사용

방법1

controller
	@GetMapping("/jsp/java")
	public String jspToJava() {
		return "d";
	}
	
d.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This File is d.jsp</h1>
<%
	int num = 10;
%>
<h3>num의 값은 <%=num %></h3>
</body>
</html>
결과 화면

방법2

controller
@GetMapping("/jsp/java/model")
	public String jspToJavaToModel(Model model) { // 1. 함수의 파라미터에 Model을 선언한다.
		
		User user = new User();
		user.setUsername("sai");
		
		model.addAttribute("username", user.getUsername()); // 2.addAttribute 함수로 전달한다.
		
		return "e";
	}
e.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This file is e.jsp</h1>
<h3>${username}</h3>
</body>
</html>
결과 화면

Redirect

리다이렉트는 이미 만들어둔 코드를 재사용하기 위해 사용하는 방법으로 요청한 주소와 응답한 주소가 서로 다르다.

package com.cos.animalapp.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HttpRedirectionController {

	@GetMapping("/home")
	public String home() {
		return "home";
	}
	
	@GetMapping("/away")
	public String away() {
		return "redirect:home";
	}
	
}

리다이렉트

 

최신글