14. Spring MVC
1> MVC 아키텍쳐
가. 서블릿/JSP MVC 아키텍쳐(Model 2 Architecture)
- Model 1 은 jsp 만 가지고 사용하는데 현재는 사용하지 않음.
요청 (Controller) (Model)
웹브라우저 ----------------> 서블릿(개발자가 구현) ---------> Service ---------> DAO ---------> DB
ListServlet(/list): 데이터 가져오는 담당
AddServlet(/add): 데이터 저장 담당
....
|
| <== 요청위임(redirect/foward)
▽
jsp(View)
TestServlet 까지 올려면 요청 URL?
http://서버IP:port번호/context명/서블릿매핑
http://localhost:8090/context명/list ---> ListServlet
http://localhost:8090/context명/add ---> AddServlet
==> 서블릿까지만 오면 처리가능
TestServlet 했던 주요한 작업들?
- 요청처리
ex> request.getParameter("name");
...
- 응답처리
ex> 직접 응답 또는 jsp 위임작업
* 요청위임
(1) redirect 방식
- HttpServletResponse 이용
- 문법:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.sendRedirect("타켓");
}
1> 요청(/xxx)
웹브라우저 ------------------> MainServlet("/xxx") 2> doGet실행
HttpServletRequest request(100번지) 생성
request(100번지).setAttribute("xxx","홍길동")
3>
response.sendRedirect(" a.jsp");
<-------------------
4>응답(서블릿이 응답)
5> 재요청(a.jsp)
------------------> a.jsp HttpServletRequest request(200번지)
<------------------ request.getAttribute("xxx"); null 반환
6> 응답
- url이 변경됨. ( /xxx --> a.jsp )
- 서블릿에서 request scope에 저장된 데이터는
리다이렉트된 jsp에서 참조 불가 (null 반환)
따라서 session scope 또는 application scope를 사용해야 된다.
(2) foward 방식
- HttpServletRequest 이용
- 문법:
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
RequestDispatcher dis = request.getRequestDispatcher("타켓");
dis.forward(request, response);
}
}
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
RequestDispatcher dis = request.getRequestDispatcher("a.jsp");
dis.forward(request, response);
}
}
1> 요청 서버
웹브라우저 --------------------------------> MainServlet("/xxx") 2> doGet 실행
| HttpServletRequest request 생성
| request.setAttribute("xxx", "홍길동");
|
| 3> 포워드 위임(요청)
- 1번에서 만든 request 를 재사용.
| request.getRequestDispatcher("a.jsp");
| dis.forward(request, response);
<----------------------------------- a.jsp
==> forward 방식은 서블릿을 요청할 때 생성했던 request 를 jsp 로 위임(요청)할 때도 재사용한다.
따라서, 하나의 request로 서블릿도 요청하고 jsp 도 요청하는 방식으로서 request를
확장시킬수 있는 개념이다.
==> 서블릿에서 request.setAttribute(key,value) 로 저장된 데이터를
JSP 에서 request.getAttribute(key) 하면 value 를 얻을 수 있다.
==> 브라우저 url 변경 안됨
서블릿맵핑값으로 계속 유지됨.
나. Spring MVC 아키텍쳐
요청
웹브라우저 ----------------> 서블릿(spring 제공) ---------> Controller ---------> Service ---------> Repository ---------> DB
DispatcherServlet(/)
Mapping servlets: dispatcherServlet urls=[/]
/list 역할
/add 역할
<---------
jsp + jsp 에서 보여줄 데이터(응답처리)
|
|<== 요청위임(redirect/forward)
jsp
DispatcherServlet 까지 올려면 요청 URL?
httP://서버IP:port번호/context명/서블릿매핑
http://localhost:8090/context명/
==> 404이기 때문에 White Label page 가 보임.
Controller 까지 올려면 요청 URL?(*)
httP://서버IP:port번호/context명/서블릿매핑/요청맵핑값
http://localhost:8090/context명/list ---> Controller
http://localhost:8090/context명/add ---> Controller
==> Controller 까지 와야지 처리가능
DispatcherServlet 에서는
이전 ListServlet 에서 했던 요청처리 및 응답처리를
직접 구현할 수 없다.
따라서 다른 클래스(Controller)를 이용해서 이전 서블릿에서
했던 작업들을 구현한다.
2> Spring MVC 실습
가. 의존성 실습
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
나. port 번호 및 context 명 변경
port 번호 및 context 명 변경
# application.properties
# tomcat port 번호 변경
server.port=8090
# context 명 변경
server.servlet.context-path=/app
요청은 http://localhost:8090/app/ 이고 whitelabel error page 보임.
/app : context 명
/ : 서블릿맵핑명(/app 뒤의 /)
다. Controller 작성
- 이전 서블릿/jsp 버전의 서블릿 역할 담당.(요청처리 및 응답처리)
- POJO 기반
- 빈으로 자동생성될 수 있도록 권장 패키지 구조를 준수 + @Controller 로 지정.
- 요청 url과 일치하는 요청맵핑값을 설정
반드시 유일한 값으로 지정해야한다.
ex>
http://localhost:8090/app/요청맵핑값
http://localhost:8090/app/list <== list 역할의 메서드 실행
http://localhost:8090/app/add <== add 역할의 메서드 실행
문법:
// list 역할 가정
@RequestMapping("/list") // `/list` 값이 요청맵핑값이다.
public String 메서드명([변수, ...]) {
return "(보여줄 jsp정보)"; // 기본적으로 forward 방식으로 jsp 에 위임한다.
}
// add 역할 가정
@RequestMapping("/add") // `/add` 값이 요청맵핑값이다.
public String 메서드명([변수, ...]) {
return "(보여줄 jsp정보)";
}
- Controller 의 메서드 리턴타입은 다양한 타입 지정 가능.
ex> String, void, DeptDTO, List<DeptDTO>, ...
만약 String 이면 View 정보가 된다. (JSP 정보.)
- Controller 의 메서드 파타미터도 다양한 타입 지정 가능.
- Controller 의 @RequestMapping 에 설정하는 요청맵핑값은 다양한 포맷지정이 가능하다.
ex> /list, /list*, /list/*, /list/**
라. jsp 저장
- jsp 및 css/js/image 등을 저장하기 위해서는
기본적인 웹 어플리케이션 디렉토리 구조가 있음.
src
main
java ( *.java 가 저장됨 )
webapp
META-INF
MANIFEST.MF
WEB-INF
lib
web.xml
hello.html (정적)
test.css
test.js
test.png
world.jsp (동적)
그런데 spring boot 에서는 기본적으로 웹 어플리케이션 디렉토리 구조를 제공 안함.
이유는 spring boot 는 jsp 권장을 안하고 대신 thymeleaf(타임리프) 권장.
https://www.thymeleaf.org/
- spring boot의 웹 디렉토리 구조는 다음과 같다.
src/main/resources
ㄴ META-INF
ㄴ resources
ㄴ WEB-INF
ㄴ views(폴더)
ㄴ *.jsp <== WEB-INF 에 저장한 이유는 웹브라우저에서 직접 접근불가.
Controller 가 알려준 jsp 정보를 가진 DispatcherServlet만 접근가능.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
- jsp 위한 이클립스 플러그인 설치하기
이클립스 Help > Eclipse Marketplace > 'eclipse web' 검색 >
Eclipse Enterprise java and Web Developer tools 3.33 설치하기
package com.exam;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.exam.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MainController {
Logger logger = LoggerFactory.getLogger(getClass());
// 요청 url 문법? http://localhost:8090/app/요청맵핑값 (*)
// 요청 url? http://localhost:8090/app/list
@RequestMapping("/list")
public String list() { // String 값은 view 정보
logger.info("logger: MainController:{}", "/list요청");
return "/WEB-INF/views/hello.jsp"; // jsp 정보 (기본적으로 forward 방식 - url 이 변경이 안됨.)
}
// url 변경 -> redirect 방식
// url 변경 x -> forward 방식
// 요청 url? http://localhost:8090/app/add
@RequestMapping("/add")
public String add() {
logger.info("logger: MainController:{}", "/add요청");
return "/WEB-INF/views/hello.jsp"; // jsp 정보
}
}
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>안녕하세요</p>
<p>Hello</p>
</body>
</html>
# application.properties
logging.level.org.springframework=info
# tomcat port 번호 변경
server.port=8090
# context 명 변경
server.servlet.context-path=/app
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.exam</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
'[study]이론정리 > Spring Boot' 카테고리의 다른 글
Spring MVC - JSP(js,css,image) (0) | 2024.07.02 |
---|---|
Spring MVC - JSP (prefix & suffix) (0) | 2024.07.02 |
Spring 기반의 DB 연동 - mybatis + mysql: 연동2 - @Mapper 인터페이스(TodoMapper.java) + TodoMapper.xml 연동 (1) | 2024.07.02 |
Spring 기반의 DB 연동 - springframework 및 SpringBoot 트랜잭션 처리 (0) | 2024.07.02 |
Spring 기반의 DB 연동 - mybatis + mysql: 연동1 - @Repository 클래스 + TodoMapper.xml 연동 (1) | 2024.07.02 |