웹브라우저 ---> 서블릿 (개발자가 구현) ---> Service --> DAO --> DB
ListServlet (/list)
AddServlet (/add) 등등 각 기능에 맞는 서블릿을 만들었었음
|
| 요청 위임 (redirct/forward)
jsp
cf) 요청 위임
public void doGet (HttpServletRequest request, HttpServletResponse response) {
response.sendRedirect("타겟");
}
public void doGet (HttpServletRequest request, HttpServletResponse response) {
RequestDispatcher dis = request.getRequestDispatcher("타겟");
dis.forward(request, response);
}
웹브라우저 ---> 서블릿 (Spring 제공) ---> Controller --> Service --> Repository --> DB
DispatcherServlet (/) /list 역할
/add 역할
<---
jsp + jsp에서 보여줄 데이터 (응답처리)
|
| 요청 위임 (redirct/forward)
jsp
DispatcherServlet에서는 이전 ListServlet에서 했던 요청 처리 및 응답 처리를 직접 구현할 수 없다
따라서 다른 클래스를 이용해서 이전 서블릿에서 했던 작업들을 구현함
DispatcherServlet 까지 오려면 요청 URL?
http://서버IP:port/context명/서블릿맵핑
http://localhost:8090/context명/
==> 404이기 때문에 while label page가 보임
Controller 까지 오려면 요청 URL?
http://서버IP:port/context명/서블릿맵핑/요청맵핑값 ⭐⭐
http://localhost:8090/context명/list
DispatcherServlet에서는 이전 ListServlet에서 했던 요청 처리 및 응답 처리를 직접 구현할 수 없다
따라서 다른 클래스 (Controller)를 이용해서 이전 서블릿에서 했던 작업들을 구현함
<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>
application.properties
- tomcat port 번호 변경
예> server.port=8090
- context명 변경
예> server.servlet.context-path=/app
요청은 : http://localhost:8090/app/ 이고 white label page 보임
/app : context명
/ : 서블릿맵핑명
@RequestMapping("/list ")
public String list([변수,...]) {
return "보여줄 jsp 정보"; // 기본적으로 forward 방식으로 jsp에게 위임한다
}
@RequestMapping("/add")
public String add([변수,...]) {
return "보여줄 jsp 정보";
}
Controller의 메서드 리턴 타입은 다양한 타입 지정 가능
예> String, void, DeptDTO, List< DeptDTO>,...
만약 String이면 View 정보를 의미한다 (JSP 정보)
Controller의 메서드 파라미터도 다양한 타입 지정 가능
Controller의 @RequestMapping에 설정하는 요청맵핑값은 다양한 포맷 지정이 가능하다
예> /list, /list, /list/, /list/**
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 권장)
src/main/resources
META-INF
resources
WEB-INF
views (폴더)
*.jsp
==> jsp 를 WEB-INF 안에 저장한 이유는 웹브라우저에서 직접 접근이 불가하기 때문에
==> Controller가 알려준 jsp를 가진 DispatcherServlet만 접근이 가능하다
# JSP 의존성 설정
<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>
현재 코드
return "/WEB-INF/views/hello.jsp";
경로가 길고 확장자가 jsp로 고정되어 있음
수정 코드
return "hello";
파일명만 지정
추가로 application.properties에 파일 경로와 확장자 정보를 알려줌
src/main/resources/
static
js
test.js
css
test.css
images
logo_daum.png
<link rel="stylesheet" href="css/test.css">
<script src="js/test.js"></script>
<img src="images/logo_daum.png" width="100" height="100">
@RequestMapping("요청맵핑값")
예>
@RequestMapping("/list")
@RequestMapping(value = {"/list2","/listAll"})
@RequestMapping("/update*")
@RequestMapping("/delete/*")
@RequestMapping("/add/**")
@RequestMapping("/find/**/board") <== 패턴 에러
해결: spring.mvc.pathmatch.matching-strategy=ant-path-matcher 붙이기
@RequestMapping("요청맵핑값") 의 클래스 레벨 사용가능
현재
==> 회원정보보기/ 회원생성하기 / 회원수정하기/ 회원삭제하기
@RequestMapping("/member")
@RequestMapping("/member/list")
@RequestMapping("/member/add")
@RequestMapping("/member/update")
@RequestMapping("/member/delete")
적용 (/member가 중복되므로 /member를 클래스 레벨에서 사용할 수 있다)
@RequestMapping("/member")
public class MainController2{
@RequestMapping("/list")
public String list(){}
@RequestMapping("/add")
public String add(){}
@RequestMapping
public String default(){}
}
@RequestMapping("/loginForm") <== 화면 요청, GET 방식 이용이 일반적
public String loginForm(){}
@RequestMapping("/login") <== 로직 요청, POST 방식 이용이 일반적
public String login(){}
// 화면 요청, GET 방식 이용이 일반적
@RequestMapping(value="/login", method=RequestMethod.GET)
public String loginForm(){}
// 로직 요청, POST 방식 이용이 일반적
@RequestMapping(value="/login", method==RequestMethod.POST)
public String login(){}
@RequestMapping(value="/login", method=RequestMethod.GET)
==>@GetMapping("/login")
@RequestMapping(value="/login", method==RequestMethod.POST)
==>@PostMapping("/login")
====> PRG (Post-Redirect-Get) 패턴을 적용해서 최종적인 작업은 post가 아닌 get로 끝나게 처리하기 !!!!!!!!
// 화면 요청
@GetMapping("/login")
public String list() {
return "loginForm";
}
// 로직 요청
@PostMapping("/login")
public String add() {
return "redirect:xxx";
}
// PRG 패턴 적용
@GetMapping("/xxx")
public String hello() {
return "hello";
}
@PostMapping("/login")
public String add(HttpServletRequest request) {
String userid = request.getParameter("userid");
String passwd = request.getParameter("passwd");
}
@PostMapping("/login")
public String login(@RequestParam("userid") String userid,
@RequestParam("passwd") String passwd) {
logger.info("logger:userid={},passwd={}", userid, passwd);
}
@PostMapping("/login")
public String login(@RequestParam(name = "userid2",
required = false,
defaultValue = "aaa") String userid,
@RequestParam("passwd") String passwd)
@PostMapping("/login")
public String login(@RequestParam String userid,
@RequestParam("passwd") String pw)
(단, name 값과 DTO의 변수명이 동일한 경우)
@PostMapping("/login")
public String login(LoginDTO dto) {
logger.info("logger:userid={},passwd={}", dto.getUserid(), dto.getPasswd() );
}
@PostMapping("/login")
public String login(@RequestParam Map<String, String> map) {
logger.info("logger:Map={}", map );
}
: 이전 서블릿/jsp의 request.getParameterValues("name") 역할
@PostMapping("/member1")
public String member1( @RequestParam("userid") String userid,
@RequestParam("passwd") String passwd,
@RequestParam("email") String[] email
)
@PostMapping("/member2")
public String member2( @RequestParam("userid") String userid,
@RequestParam("passwd") String passwd,
@RequestParam("email") List<String> email
)
public class MemberDTO {
String userid;
String passwd;
List<String> email; // String [] email 가능
@PostMapping("/member")
public String member(MemberDTO dto) {
logger.info("logger:MemberDTO:{}", dto);
==> 헤더의 name값은 기본적으로 대소문자 구별 안 함
@GetMapping("/header")
public String header(HttpServletRequest request) {
Enumeration<String> names = request.getHeaderNames();
while(names.hasMoreElements()) {
String name = names.nextElement();
String value = request.getHeader(name);
logger.info("logger:header name:{}, header value:{}", name, value);
}
return "hello";
}
@GetMapping("/header2")
public String header2(@RequestHeader("user-agent") String x,
@RequestHeader("Accept-language") String x2,
@RequestHeader("Accept") String x3
) {
logger.info("logger:user-agent:{}, accept-language:{}, accept:{}", x, x2, x3);
return "hello";
}
@GetMapping("/get-cookie1")
public String get_cookie1(HttpServletRequest request) {
Cookie [] cookies = request.getCookies();
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
logger.info("logger:쿠키 name:{}, 쿠키 value:{}", name, value);
}
return "hello";
}
@GetMapping("/get-cookie")
public String get_cookie(@CookieValue("userid") String userid) {
logger.info("logger:쿠키 name:userid, 쿠키 value:{}", userid);
return "hello";
}