Light Blue Pointer
본문 바로가기
TIL(Develop)

Controller이해하기

by 개발바닥곰발바닥!!! 2023. 11. 2.

Controller이해하기

프로젝트 생성

  • Name: spring-mvc
  • Language: Java
  • Build system: Gradle - Groovy
  • Group: com.sparta
  • JDK: 17
  • 프로젝트 경로(Location)는 자유롭게 설정

Dependencies

Thymeleaf, Spring web, ,lombok 추가

 

controller package만듦

그리고 HelloController 클래스 생성

package com.sparta.springmvc.controller;

import org.springframework.stereotype.Controller;

@Controller//->이거 달아
public class HelloController {
}
package com.sparta.springmvc.controller;

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

@Controller
public class HelloController {
    @GetMapping("/api/hello")
    public String hello(){
        return "Hello World!";

    }
}

@Controller annotation을 달면 class에서 반환이 될때 resources→templates→HTML 파일을 찾아서 Hello world라는 HTML이 있는지 봐서 그 HTML을 반환한대

View name의 정보를 전달하는 것

그런데 지금은 순수하게 문자열을 반환하는거라 @ResponseBody 를 달아줌

⭐ResponseBody에 대해서 더 읽어봄

https://docs.spring.io/spring-framework/reference/web/webflux/controller/ann-methods/responsebody.html

You can use the @ResponseBody annotation on a method to have the return serialized to the response body through an HttpMessageWriter. The following example shows how to do so:

@GetMapping("/accounts/{id}")
@ResponseBody
public Account handle() {
	// ...
}

⭐HttpMessageWriter is one of codecs

Codecs

See equivalent in the Servlet stack

The spring-web and spring-core modules provide support for serializing and deserializing byte content to and from higher level objects through non-blocking I/O with Reactive Streams back pressure. The following describes this support:

The spring-core module provides byte[], ByteBuffer, DataBuffer, Resource, and String encoder and decoder implementations. The spring-web module provides Jackson JSON, Jackson Smile, JAXB2, Protocol Buffers and other encoders and decoders along with web-only HTTP message reader and writer implementations for form data, multipart content, server-sent events, and others.

ClientCodecConfigurer and ServerCodecConfigurer are typically used to configure and customize the codecs to use in an application. See the section on configuring HTTP message codecs.

 

다시 내용으로 돌아감

package com.sparta.springmvc.controller;

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

@Controller
public class HelloController {
    @ResponseBody
    @GetMapping("/api/hello")
    public String hello(){
        return "Hello World!";

    }
}

Run,

Postman 에 GET>http://localhost:8080/api/hello>Send

또 다른 get method 만들어봄

@GetMapping("/api/get")
    @ResponseBody
    public String get(){
        return "GET Method 요청";
    }

Postman→GET→http://localhost:8080/api/get→Send

잘 나온다 근데 그냥 브라우저에다 주소 입력해도 됨

post method 만들어봄

@PostMapping("/api/post")
    @ResponseBody
    public String post(){
        return "Post method 요청";
    }

새로 빌드 안 하고 했더니 오류난다

다시 하고 했더니 잘 됐다

 

Q. GET은 되는데 POST는 브라우저에서 안 되는 이유가 뭐지?

 

delete method 만들어봄

@DeleteMapping("/api/delete")
    @ResponseBody
    public String delete(){
        return "Delete Method 요청";
    }

⚠️api 경로는 같을 수 있지만 메서드는 달라야 한다고 함

@PostMapping("/api/hello")
@ResponseBody
    public String post(){
        return "Post method 요청";
    }

@ResponseBody
@GetMapping("/api/hello")
    public String hello(){
        return "Hello World!";

    }

둘 다 "/api/hello" 지만 GET이랑 POST로 달라서 괜찮대

실행해보니까 둘 다 잘 됨

 

@RequestMapping 을 이용해서 중복되는 상위경로 분리할 수 있음

@Controller
public class HelloController {
    @ResponseBody
    @GetMapping("/api/hello")
    public String hello(){
        return "Hello World!";

    }
    @GetMapping("/api/get")
    @ResponseBody
    public String get(){
        return "GET Method 요청";
    }

    @PostMapping("/api/hello")
    @ResponseBody
    public String post(){
        return "Post method 요청";
    }

    @DeleteMapping("/api/delete")
    @ResponseBody
    public String delete(){
        return "Delete Method 요청";
    }

    }

반복되는 “/api”를 분리함

@Controller
@RequestMapping("/api")
public class HelloController {
    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        return "Hello World!";

    }
    @GetMapping("/get")
    @ResponseBody
    public String get(){
        return "GET Method 요청";
    }

    @PostMapping("/hello")
    @ResponseBody
    public String post(){
        return "Post method 요청";
    }

    @DeleteMapping("/delete")
    @ResponseBody
    public String delete(){
        return "Delete Method 요청";
    }

    }

@RequestMapping("/api")을 달아놓으면

/api에 해당하는 요청은 저 클래스로 다 온 후에 이후 /경로에 따라서 매핑된다 함

 

Controller의 장점 예제

회원 관리 API

기능 Method URL 반환

로그인 페이지 GET /user/login login 페이지
로그아웃 처리 GET /user/logout "/" 으로 redirect
회원가입 페이지 GET /user/signup signup 페이지
회원가입 처리 POST /user/signup "/" 으로 redirect

(1) Servlet Code

@WebServlet(urlPatterns = "/user/login")
public class UserLoginServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}
}
@WebServlet(urlPatterns = "/user/logout")
public class UserLogoutServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}
}
@WebServlet(urlPatterns = "/user/signup")
public class UserSingUpServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}

	@Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}

}

Spring MVC에 Front Controller 패턴이 적용되어있지 않았다면 이처럼 단 4개의 API를 처리하기 위해 무려 3개의 클래스를 만들어야 함.

(2) Controller Code

다행히 Spring MVC는 효율적인 API 처리를 위해 Front Controller 패턴을 적용

이제는 API 마다 파일을 만들 필요가 없다

하나의 Contoller 에 모든 API를 넣지는 않는다

유사한 성격의 API 를 하나의 Controller 로 관리

메서드 이름도 내 마음대로 설정 가능 (단, 클래스 내의 중복메서드명 불가)

@Controller
@RequestMapping("/user")
public class UserController {
	@GetMapping("/login")
	public String login() {
	    // ...
	}

  @GetMapping("/logout")
  public String logout() {
      // ...
  }

	@GetMapping("/signup")
	public String signup() { 
		// ... 
	}
	
	@PostMapping("/signup")
  public String registerUser(SignupRequestDto requestDto) {
		// ... 
	}
}

@Controller
public class HelloController {
    @GetMapping("/api/hello")
    @ResponseBody
    public String hello() {
        return "Hello World!";
    }
}

@Controller는 해당 클래스가 Controller의 역할을 수행할 수 있도록 등록해줌

 

@GET, @POST, @PUT, @DELETE

각각의 HTTP Method에 매핑되는 애너테이션

@GET

@GetMapping("/api/get")
@ResponseBody
public String get() {
    return "GET Method 요청";
}

@POST

@PostMapping("/api/post")
@ResponseBody
public String post() {
    return "POST Method 요청";
}

@PUT

@PutMapping("/api/put")
@ResponseBody
public String put() {
    return "PUT Method 요청";
}

@DELETE

@DeleteMapping("/api/delete")
@ResponseBody
public String delete() {
    return "DELETE Method 요청";
}

 

@RequestMapping

@RequestMapping은 중복되는 URL를 단축시켜줄 수 있다

package com.sparta.springmvc.controller;

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

@Controller
@RequestMapping("/api")
public class HelloController {
    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        return "Hello World";
    }

    @GetMapping("/get")
    @ResponseBody
    public String get() {
        return "GET Method 요청";
    }

    @PostMapping("/post")
    @ResponseBody
    public String post() {
        return "POST Method 요청";
    }

    @PutMapping("/put")
    @ResponseBody
    public String put() {
        return "PUT Method 요청";
    }

    @DeleteMapping("/delete")
    @ResponseBody
    public String delete() {
        return "DELETE Method 요청";
    }
}

'TIL(Develop)' 카테고리의 다른 글

데이터를 클라이언트에게 반환하는 방법  (0) 2023.11.06
정적페이지와 동적페이지  (1) 2023.11.03
Spring MVC  (0) 2023.11.02
Lombok과 application.properties  (0) 2023.11.02
테스트코드  (0) 2023.11.02