웹 개발/스프링

스프링(5) - 도서 구매 프로젝트(2)

SolartheNomad 2023. 4. 2. 20:36

👩‍💻 컨트롤러란?

- 사용자 요청은 제일 먼저 디스패처 서블릿으로 전달되는데, 사실디스패처 서블릿은 요청을 전달받는 창구 역할만 할 뿐 실제로는 컨트롤러(Controller)가 요청을 처리함

- 웹 요청을 전달받아 그 내용을 해석한 후 요청을 처리할 수 있는 메서드를 호출한다.

- 해당 요청을 처리하고 나서 사용자에게 결과를 반환한다. 

 

💚 컨트롤러 구현과정 

 

1. 컨트롤러 정의 

-  컨트롤러로 사용할 자바 클래스에 @Controller를 선언한다. 

- 해당 컨트롤러와 의존 관계에 있는 모든 자바 클래스를 빈 객체로 등록하는 단계

컨트롤러 정의 구현 

package com.springmvc.JAVA;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller // @Controller : 웹 요청 URL에 대해서 디스패처 서블릿이 컨트롤러임을 인식할 수 있도록 알려주는 것
public class Example01Controller { 
    @RequestMapping(value="/exam01", method=RequestMethod.GET)

    public void requestMethod() {
        System.out.println("@Controller 예제입니다"); 
    }
}

 

 

2. 요청 매핑 경로 설정 

-@ReqeustMapping(value='/요청url', method=RequestMethod.겟이나 포스트 중 하나 선택)

- 위의 예시의

@RequestMapping(value="/exam01", method=RequestMethod.GET)

부분임 

-  'http://localhost:8080/JAVA/exam01'을 띄어주게 만든다.

 

🐤 형태

@RequestMapping(value="웹 요청 URL", method=RequestMethod.HTTP 요청 방식, ...)

🐤 속성

 

🐤 클래스 수준의 요청 매핑 경로 설정

- 웹에서 사용자가 요청한 URL에 매핑되는 @RequestMapping이 컨트롤러에 선언될 경우에 사용됨

- 기본 매핑 경로를 설정하지 않은 @RequestMapping만 선언된 요청 처리 메서드가 사용된다. 

package com.springmvc.chap05;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value="/exam02", method=RequestMethod.GET) //클래스에 매핑된 @RequestMapping
public class Example02Controller {

    @RequestMapping //메서드에 매핑된 @RequestMapping  
    public void requestMethod() {
        System.out.println("@RequestMapping 예제입니다.");
        System.out.println("웹 요청 URL은  /exam02 입니다.");
    }
}

실행 결과

🐤 메서드 수준의 요청 매핑 경로 설정

-  웹 요청 URL이 http://localhost:8080/.../JAVA이면 컨트롤러인 Example03Controller 클래스의 requestMethod() 메서드에 매핑되어 요청을 처리한다.

package com.springmvc.JAVA;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class Example03Controller {

    @RequestMapping(value="/JAVA", method=RequestMethod.GET)
    public void requestMethod() {
        System.out.println("@RequestMapping 예제입니다.");
        System.out.println("웹 요청 URL은 /JAVA 입니다.");
    }
}

 

- 웹에서 사용자가 요청한 URL에 대해 컨트롤러 안의 어떤 메서드를 처리할지 선언하여 사용하는 경우에 쓰임 

- 메서드 수준의 @ReqeustMapping은 단순화가 가능하다. 

📌 단순화 종류 

📌 구현 예시

package com.springmvc.JAVA;

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

@Controller
@RequestMapping("/home")
public class ExampleController {

    @GetMapping("/Example")
    public void requestMethod() {
        System.out.println("@RequestMapping 예제입니다.");
        System.out.println("웹 요청 URL은 /home/Example 입니다.");
    }
}

 

3. 요청 처리 메서드 구현

- 사용자의 요청을 처리하는 메서드를 구현함

public void requestMethod() {
        System.out.println("@Controller 예제입니다"); 
    }

- 에서 public void request() {}이다.

- 요청 처리 메서드 형태

 

 

4. 뷰(&모델) 반환

- 처리된 결과를 반환하도록 메서드 안에 뷰나 뷰 이름을 포함한 모델을 넣어서 return한다. 

- 위의 예시의 System.out.println("@Controller 예제입니다.") 부분으로, 웹 요청 URL에 대한 응답(@Controller 예제입니다.)를 반환한다.

 

 

💚 스프링 MVC 설정 파일(servlet-context.xml) 등록하기에 자바클래스를 빈 객체로 등록하기

- . 웹에서 사용자 요청이 들어오면 디스패처 서블릿은 @Controller가 선언된 컨트롤러 여러 개를 스캔하고 스패처 서블릿이 모든 컨트롤러를 인식할 수 있도록 컨트롤러와 컨트롤러와 의존 관계에 있는 자바 클래스들을 스프링 MVC 설정 파일(servlet-context.xml)에 빈 객체로 등록해야 함 

 

🐤 컴포넌트 스캔(<context:component-scan>)

 

- 하나씩 MVC 설정파일에 자바 클래스를 등록하기 번거로우므로  @Controller가 선언된 컨트롤러를 빈 객체로 자동으로 등록할 뿐만 아니라 의존 관계에 있는 자바 클래스도 빈 객체로 자동 등록해줄 수 있게 함 

- 형식

<context:component-scan base-package="패키지 이름"/>

- 컴포넌트(@Controller, @Autowired) 자동 인식 기능을 지원한다. 

- <context:component-scan> 요소의 base-package 속성에 공통 패키지 com.springmvc.*를 설정하면 설정된 패키지 하위에 있는 컨트롤러 및 의존 관계에 있는 자바 클래스를 검색하여 빈 객체로 자동으로 등록해준다. (다른 패키지 경로에 있는 친구들을 자동으로 검색하여 빈 객체로 등록시켜주는 것)

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation="http://www.springframework.org/schema/context  
                         http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     ...
     <context:component-scan base-package="com.springmvc.*"/> // 컨트롤러의 빈 객체 등록
</beans:beans>

 

📍 컴포넌트 스캔(<context:component-scan>)이 없다면...?

- 스프링 MVC 환경 설정 파일 servlet-context.xml에 컨트롤러 및 의존 관계에 있는 자바 클래스를 빈 객체로 하나씩 직접 등록해야 한다. 

- 겁나 인생 복잡해지고 피곤해짐....BUT 굳이 컴포넌트 스캔 없이 코드를 작성해봤다. 

<beans:bean class="com.springmvc.controller.HomeController"/>

<beans:bean id="bookRepositoryImpl" class="com.springmvc.repository.BookRepositoryImpl"/>

<beans:bean id="bookServiceImpl" class="com.springmvc.service.BookServiceImpl">
    <beans:property name="bookRepository" ref="bookRepositoryImpl"/>
</beans:bean>

<beans:bean class="com.springmvc.controller.BookController">
    <beans:property name="bookService" ref="bookServiceImpl"/>
</beans:bean>

 

- 트롤러와 의존 관계에 있는 클래스의 프로퍼티에 선언된 @Autowired를 인식할 수 없기 때문에 다음과 같이 프로퍼티의 Setter() 메서드도 모두 작성해야한다. ➡ Autowired로 참조가 불가능하기 때문에 참조를 할 수 있도록 Setter을 써서 외부 패키지의 내용들을 가져와야함 

 

✍ BookController.java

private BookService bookService;
public void setBookService(BookService bookService) {
    this.bookService = bookService;
}

 

BookService.java

private BookRepository bookRepository;

    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

 

🔗 BookController 만들기

BookController.java

- 요청 매핑 경로가 /books/all인 requestAllBooks() 메서드에 ModelAndView 객체를 사용하여 모델과 뷰를 처리해준다.

package com.springmvc.controller;
...
import org.springframework.web.bind.annotation.GetMapping; // 추가
import org.springframework.web.servlet.ModelAndView; // 추가 
...
@Controller
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookService bookService;

    @GetMapping 
    public String requestBookList(Model model) {
        List<Book> list = bookService.getAllBookList();
        model.addAttribute("bookList", list);
        return "books";
    } 

     @GetMapping("/all") 
     public String requestAllBooks(Model model) { 
        // List<Book> list = bookService.getAllBookList(); 
        // modelAndView.addObject("bookList", list);//model.addAttribute("bookList", list); 
        // model.AndView.setViewName("books"); 
         return modelAndView;//return "books"; 
     }
}

 

@GetMapping

- 사용자의 웹 요청 URL이 /books인 경우 reqeustBookList()가 처리할 수 있도록 매핑하는 것

- @RequestMapping과 같은 기능을 한다.

 

 

@GetMapping("/all")

- 사용자의 웹 요청 URL이 /books/all인 경우 requestAllBooks() 메서드가 처리할 수 있도록 매핑해준다. 

-  @RequestMapping(value="/all", method=RequestMethod.GET) 또는 @RequestMapping("/all")과 같은 말이다. 

 

 

@RequestMapping(value="/books", method=RequestMethod.GET)

- 요청 매핑 경로를 books로 지정한다. 

 

-요청 처리 메서드를 정의해준다. 

요청 처리 메서드 형태

- 사용자의 요청을 처리하는 메서드 

@RequestMapping에 설정된 요청 매핑 경로에 따라서 호출됨

@RequestMapping(...)
public String 메서드 이름() {
    // 모델(객체)에 응답 데이터 저장
    return "뷰 이름";
}

모델 :  사용자의 웹 요청을 처리한 결과 데이터를 관리하고 전달한다.

뷰 :  처리된 결과 데이터를 웹 브라우저에 출력하는 웹 페이지 역할을 함 

 

응답 데이터를 저장하는 모델 유형들(모델 클래스)

Model 인터페이스를 이용한 메서드 작성 

- Model 인터페이스는 사용자 요청에 대한 처리 결과를 뷰에 보여 주는 데 필요한 데이터를 Model 객체의 addAttribute() 메서드에 담아 전달함 : 데이터를 ModelAtrribute에 담아서 뷰에 전달함

 

Model addAttribute(String attributeName, Object attributeValue)

// 역할: 제공된 이름으로 제공된 속성을 등록합니다.
// 매개변수:
 // attributeName: 모델 속성 이름(null이 될 수 없음)
 // attributeValue: 모델 속성 값(null이 될 수 있음)

 

Model 인터페이스 구현 예시

- 요청 처리 메서드 requestMethod() Model 객체를 사용하여 모델 속성 이름 data data2에 뷰로 전송할 값을 각각 저장한다.

-  뷰 이름을 webpage05로 반환하면 webpage05.jsp 파일을 웹 브라우저에 출력한다. = url은 /exam05로 들어가게 됨. 페이지 이름은 webpage05.jsp 가 됨 

Model Interface가 반환한 뷰 페이지 webpage05.jsp 

<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>chap05</title>
</head>
<body>
    <p>${data}
    <p>${data2}
</body>
</html>

 

 

 

 

 

ModelMap 인터페이스

- Model 인터페이스와 동일함

- 사용자 요청에 대한 처리 결과를 뷰에 보여주는 데 필요한 데이터를 Model 객체의 addAtrribute() 메서드에 담아서 전달한다.

ModelMap addAttribute(String attributeName, Object attributeValue)

- 지정된 이름(attributeName)과 속성(attributeValue)을 등록한다.
- 매개변수:
   attributeName: 모델 속성의 이름(null이 될 수 없음)
   attributeValue: 모델 속성의 값(null이 될 수 있음)

 

 

package com.springmvc.chap05;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/home")
public class Example06Controller {

    @GetMapping("/exam06")
    public String requestMethod(ModelMap model) {
        model.addAttribute("data", "ModelMap 예제입니다");
        model.addAttribute("data2", "웹 요청 URL은 /home/exam06 입니다");
        return "webpage05";

ModelAndView 클래스를 사용한 메서드 작성

- ModelAndView 클래스는 모델과 뷰를 합쳐놓은 것

- 사용자 요청에 대한 처리 결과 데이터를 ModelAndView 객체의 addObject() 메서드에 담아 전달하고 setViewName() 메서드로 뷰 이름을 설정해준다. 

 

ModelAndView addObject() 메서드 

ModelAndView addObject(String attributeName, Object attributeValue)

역할 : 지정한 이름(attributeName)으로 제공된 속성(attributeValue)을 등록한다(addObject). 

매개변수 

     attributeName : 모델 속성의 이름

     atrributeValue : 모델 속성의 값 

 

void setViewName() 메서드

void setViewName(String viewName)

- ModelAndView를 위한 뷰 이름을 설정한다

viewName : 뷰 이름 매개변수 

 

ModelAndView 요청 처리 메서드 결과 페이지 

 - 사용자의 웹 요청 URL http://localhost:8080/chap05/home/exam07에 대한 응답으로 웹 브라우저에 webpage05 페이지를 출력하는 과정

 

모델(뷰) 클래스 유형

 

 

RequestBookList 요청 처리 메서드 예시

 public String requestBookList(Model model) {
        List<Book> list = bookService.getAllBookList(); //도서 목록을 bookService으로부터 가져와준다.
        model.addAttribute("bookList", list); //도서 목록을 booklist에 저장한다.
        return "books"; //뷰이름 books로 반환한다.
    }

model.addAttribute("현재 모델 변수 이름", 저장대상)

- 모델로 설정하여 books로 반환될 booklist에 외부에서 가져온(getBookList)를 넣어준다. 

 

http://localhost:8080/BookMarket/books에 대한 출력 결과