본문 바로가기
Spring

Spring_1주차-(2)

by shulk 2023. 11. 1.

0. servlet 이란 동적인 웹 페이지를 생성하고 클라이언트의 요청을 처리하는 데 사용하는거로 이해하면 된다.

 

1. Spring MVC

* 일단 MVC는 디자인 패턴이고 어떠한 효율적인 방법들을 패턴화 해놓은것들 말한다.

*  MVC 패턴은 소프트웨어를 구성하는 요소들을 Model, View, Controller로 구분하여 각각의 역할을 분리한다.

* Model 은 데이터베이스와 연동하여 데이터를 저장하고 불러오는 등의 작업을 수행하고,

  View는 사용자가 보는 화면과 버튼, 폼 등을 디자인하고 구현하는 인터페이스를 담당하고

  컨트롤러는 Model과 View 사이의 상호작용을 조정하고 제어한다.

 

* Spring MVC는 쉽게 말하면 Spring에서 MVC 디자인 패턴을 적용하여 HTTP 요청을 효율적으로 처리하고 있다

 

2. Controller

* 보통 하나의 Contoller 에 모든 API를 넣지는 않고, 유사한 성격의 API 를 하나의 Controller 로 관리한다.

* 메소드 이름도 내 마음대로 설정 가능하나 클래스 내의 중복메소드명은 불가

* 컨트롤러 클래스에는 이 클래스가 컨트롤러다 명시해야하니 @Controller 어노테이션 적용해준다

* 어떤 클래스가 있을때 그안에 메소드들이 모두 공통적으로 url 시작부분에 "/api "들어가면 중복으로 보이는게 싫으니 

  클래스 위에  @RequestMapping 이 어노테이션 이용하고 @RequestMapping("/api") 한다. 

 

3. 정적,동적 페이지

* 2번의 예시 코드를 보면 각 메소드에 @ResponseBody가 있는데 이거는 뒤에서 더 자세히 배우지만 지금 상황에서는 리턴 문자 열 자체를 반환할때 사용하는듯하다. 만약 @ResponseBody없으면 템플릿의 html파일을 리턴하는거다.

 

* 정적 페이지는 static패키지, 동적 페이지는 templates패키지에 넣는다.

* 정적 페이지는 처리할게 없으니 컨트롤러를 안통하고 바로 localhost:8080/hello.html 치고 볼 수 있는데 그냥 컨트롤러를 통해 정적 페이지 보고 싶으면 build.gradle의 dependencies에 이부분을 주석으로 한뒤 다시 적용하고 해당 페이지 url 처주면 된다. -> localhost:8080/static-hello

* 동적 페이지의 경우에는 dependencies의 타임리프 주석 아닌상태일때 자동으로 컨트롤러가 resources-templetes안에서 해당 html파일 찾아서 보내주고, 리턴부분엔 .html생략해도 된다.

 

* 하지만 어떠한 상황에서는 정적,동적으로 클라한테 보내야 할때도 있으니 타임리프 적용상태에서 정적 페이지 보내고 싶으면 리턴부분에 "redirect:/ " 적어준다

4. 동적페이지 처리 과정

* 어떤 페이지에서 방문횟수 보여주고 싶을때 

  -데이터는 모델에 넣으니 매개변수쪽에 스프링프레임워크 ui인 모델 객체를 넣어준다

  -데이터를 모델에 넣을땐 addAttribute() 사용하고 매개변수 첫번째에는 html코드에서 식별할수있는 이름 넣고 두번째에는 데이터를 넣어준다 

  - 이러고 html코드에서는 "${이름}" 으로 이름에 해당된 벨류값을 매핑해서 넣어준다는 뜻이다.

@Controller
public class HtmlController {

    private static long visitCount = 0;

    @GetMapping("/html/dynamic")
    public String htmlDynamic(Model model) {
        visitCount++;
        model.addAttribute("visits", visitCount);
        return "hello-visit";
    }
}
<div>
  (방문자 수: <span th:text="${visits}"></span>)
</div>

 

5. Json으로 반환

helloStringJson() 보면 String형 리턴이라 text타입으로 반환하고 {\"name\":\"Robbie\",\"age\":95}" 부분 보면 

 {"name" : "Robbie", "age" 95} 딕셔너리 형태이다.

* 두번째 helloClassJson() 메소드를 보면 이거는 String이 아닌 Star객체 리턴하는거인데 스프링이 해당 객체를 json형태로 변환해서 보내준다.

@Controller
@RequestMapping("/response")
public class ResponseController {
    // [Response header]
    //   Content-Type: text/html
    // [Response body]
    //   {"name":"Robbie","age":95}
    @GetMapping("/json/string")
    @ResponseBody
    public String helloStringJson() {
        return "{\"name\":\"Robbie\",\"age\":95}";
    }

    // [Response header]
    //   Content-Type: application/json
    // [Response body]
    //   {"name":"Robbie","age":95}
    @GetMapping("/json/class")
    @ResponseBody
    public Star helloClassJson() {
        return new Star("Robbie", 95);
    }
}

@Getter
public class Star {
    String name;
    int age;

    public Star(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Star() {}
}

 

* 이렇게 html자체 제외 반환할땐 @ResponseBody가 있어야 한다 했는데 어떤 클래스의 메소드들이 모두 문자자체나 json으로 반환하는거라면 클래스 위에 @RestController 를 해준다. 

*@RestController는 @ResponseBody + @Controller 합친거고, 이제 메소드위에 @ResponseBody  할필요 없다.

 

6.Jackjson

* jackson은 json 데이터구조를 처리해주는 라이브러리이고  ObjectMapper라는 클래스 사용해서  

Object에서 json형태로 변경 or Json형태에서 object형태로 변경을 한다.

* 보통  @RestController 이용해서 자동으로 json관련 처리했는데 직접 처리해야 할 경우 Jackjson을 이용한다.

 

*직렬화- 직렬화는 해당 클래스에 Getter가 있어야하고 writeValueAsString(A클래스) 를 이용해서 A클래스의 필드값들을  json형태로 변환해준다.

void test1() throws JsonProcessingException {
        Star star = new Star("Robbie", 95);

        ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper
        String json = objectMapper.writeValueAsString(star);


        System.out.println("json = " + json);
    }

*역직렬화-  역직렬화는 만드려는 클래스에 기본 생성자가  ObjectMapper에 의해 필수이고,생성후 필드에 접근을 위해 Getter or Setter도 필수다.  

 readValue(json 타입의 String형,생성할클래스.class) 하면 프론트한테 받은 json내용으로 해당 클래스 생성한다.

void test2() throws JsonProcessingException {
        String json = "{\"name\":\"Robbie\",\"age\":95}"; // JSON 타입의 String

        ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper

        Star star = objectMapper.readValue(json, Star.class);
        System.out.println("star.getName() = " + star.getName());
    }

 

7. Path Variable 과 Request Param

// [Request sample]
// GET http://localhost:8080/hello/request/star/Robbie/age/95
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age)
{
    return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
}

* 데이터를 받기 위해서는 /star/{name}/age/{age} 이처럼 URL 경로에서 데이터를 받고자 하는 위치의 경로에 {data} 중괄호를 사용

* 매개변수쪽 @PathVariable을 통해 url값 받아 온다.

*  @PathVariable 생략 불가

 

// [Request sample]
// GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
    return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
}

*  Query String 이랑 연관있기도 하다(url에 ?name=Robbi 이렇게 명시하니)

*데이터를 받기 위해서는 ?name=Robbie&age=95 에서 key 부분에 선언한 name과 age를 사용하여 value에 선언된 Robbie, 95 데이터를 받아올 수 있다.

* 매개변수쪽 마찬가지로 @RequestParam 을 사용하여 받아오는데 @ RequestParam는 생략이 가능하다 

* body형식으로 데이터 보내고 서버가 받을때도 @RequestParam  이용한다

  (body는 쿼리 스트링이랑 반대로 url에 입력한 값이 안보이고 메세지 형태로 안보이게 전송한다.예를들어 비번 같은건 url주소에 보이면 안되니 이럴때 body형식으로 보낸다.)

 

8. (required = false)

* @PathVariable 이나 @RequestParam 옆에 (required = false) 적어주면 Client에서 전달받은 값들에서 해당 값이 포함되어있지 않아도 오류가 발생하지 않는다. 전달하지 않은 해당 변수는 null로 초기화한다.

* (required = Ture) 는 값을 전달해야한다는거인데 안적어도 된다.생략하면 평소 True로 설정된다는거니

public String helloGetRequestParam(@RequestParam (required=false )String name,  int age) {
        return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
    }

 

9. @ModelAttribute

* ModelAttribute는 body형식, 쿼리 스트링둘다 가능이고 생략도 가능이다

* ModelAttribute는 객체로 하는데 사용 이유는 만약 이름,나이,취미,성별,사는곳,번호등등 엄청 많으면 PathVariable이나RequestParam에 매개변수 엄청 길어지니 그렇다.

* 하지만 이 받아온 정보는 내가 만든 Star클래스에 저장한다는거니 Star클래스에 받아오는 필드들 다 만들어주고 값을 저장 해야하니 Star클래스에서 @Setter도 해줘야한다.

@GetMapping("/form/param/model")
    @ResponseBody
    public String helloRequestParam(@ModelAttribute Star star) {
        return String.format("Hello, @ModelAttribute.<br> (name = %s, age = %d) ", star.name, star.age);
    }

 

10. @RequestBody 

* RequestBody 는 HTTP Body에 JSON 데이터를 담아 서버에 전달할 때 해당 Body 데이터를 Java의 객체로 전달 받을 수 있는 방법이다. 

* RequestBody 도 @Setter,@Getter 해야한다.

* RequestBody 는 생략하면 ModelAttribute 로 작동하니 생략하면 안된다!

 

'Spring' 카테고리의 다른 글

Spring_4주차-(1)  (0) 2023.11.10
Spring_3주차-(1)  (0) 2023.11.07
Spring_2주차-(2)  (0) 2023.11.02
Spring_2주차-(1)  (0) 2023.11.02
Spring_1주차-(1)  (0) 2023.10.31