728x90

-MVC 프레임워크-

 

*프론트 컨트롤러 패턴

-기존의 컨트롤러들의 앞에 공통컨트롤러(서블릿)을 놓는것

-공통처리기능

-프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 됨

-스프링 웹 MVC의 DispatcherServlet이 FrontController 패턴으로 구현되어 있음

 

request.getRequestURI(); // http://localhost:8080 이후 부분만 호출 된다 ex) /front-controller/v1/hello

"/front-controller/v1/*" : /front-controller/v1 를 포함한 하위 모든 요청은 이 서블릿에서 받아들인다

실제 개발의 대부분의 경우에 절대경로를 사용하는 것이 좋다

 

728x90

스프링자체가 싱글톤을 보장해줘서 , 스프링내에선 싱글톤 안써도 됨

 

-Junit5

@AfterEach,@BeforeEach :  테스트가 시작되기 후, 전 마다 수행되는 어노테이션

@AfterEach// 메소드에 붙음 , 다음 테스트에 영향을 주지 않기 위해 종료되어야할 리소스를 처리하는 부분

@BeforeEach// 메소드에 붙음 , 테스트 할 때의 초기 환경을 setup

@Test//Junit이 수행할 코드 ,메소드에 붙음

given (ㅇㅇ 주어졌을때) -> when (ㅇㅇ 실행했을때 ) -> then (결과가 ㅇㅇ 이어야되) 로직으로 수행됨

 

then부분 ex)

Assertions.assertThat(출력값).isEqualTo(기댓값);

Assertions.assertThat(컬렉션객체).contains(member1,member2);

 

( Junit 5 기준 명령어 참고 )

 

템플릿 엔진(뷰 템블릿) : html 에다가 자바코드를 중간중간 삽입하는 것 , jsp(legacy) 타임리프(new)

 

정적 HTML 문서 : 항상고정된 HTML

동적 HTML 문서 : 시시각각 변화되는 회원목록같은 HTML

동적 HTML case : 서블릿+자바내부 html (very old) ,  템플릿 엔진단독 이용 , 서블릿+템플릿엔진(new)

 

-JSP

JSP도 서블릿으로 변환됨, 따라서  request, response를 사용가능함

JSP는 자바코드를 그대로 다 사용할 수 있다.

JSP는 <% ~ %> 에 자바코드를 입력할 수 있다

<%= ~ %> 에서는 자바코드를 출력한다

 

-서블릿과 JSP의 한계

서블릿만으로 뷰화면을 만들려면 ,  자바코드 내부에 html 을 써줘야한다는 불편함이 존재

서블릿과 JSP로 뷰화면을 만든다면 , 뷰파일에 자바영역과 , HTML 영역이 둘다 존재 ( 커밋시 문제 , 역할이 너무많음 , 유지보수의 지옥 ) 

=> MVC 패턴의 등장 (보여주는것과 비즈니스로직과의 분리) ( JSP는 뷰를 그리는 것에만 집중하게함 )

 

 

변경의 라이프사이클이 다른것들(비즈니스로직,UI)을 분리해주는것이 유지보수에 좋다

 

-MVC 패턴1(legacy)
컨트롤러(Servlet): 비즈니스 로직을 다 수행 , Model에 데이터를 담음 , 뷰로 제어권을 넘김

모델(Model)객체 : 데이터담기는 곳
뷰(ex JSP): Model에 있는 데이터를 참고해서 뷰를 완성하고 , 클라이언트에게 보냄

 

-MVC 패턴2(new)  ( CS 에서 배웠던 부분과 약간 다르지만 , 뭐 비슷하다 )

컨트롤러 : HTTP요청이 옳바른지 스펙을 확인 , 서비스 호출 , 종합적인 조종역할

서비스,리포지토리 : 비즈니스 로직, 데이터 접근 수행

모델(Model)객체 : 데이터 담기는 곳

뷰(ex JSP): Model에 있는 데이터를 참고해서 뷰를 완성하고 , 클라이언트에게 보냄

 

Servlet을 컨트롤러로 , JSP 를 뷰로처리

request.setAttribute 는 임시저장소 지만 , Model에 데이터가 들어감

컨트롤러에서는 HttpServletRequest객체.setAttribute("이름","값") 으로 Model에 데이터를 넣을수 있고,

뷰에서는 request.getAttribute("이름")로 Model에서 데이터를 꺼낼 수 있다

 

RequestDispatcher dispatcher =request.getRequestDispatcher(jsp파일경로문자열);//Controller->view 로 이동할때 사용
dispatcher.forward(request,response); //  다른 서블릿이나 JSP로 이동할 수 있는 기능 , 서버내부에서 다시 호출이 발생                                                       ,리다이렉트(웹브라우저에 갔다가 서버로 재요청)와 다르게 서버내부이동임,

                                                      Client->Server->Servlet 의 dispatcher->jsp->client

 

경로 ex)  현재 페이지 : http://localhost:8080/servlet-mvc/members/new-form

상대경로 : 클라이언트에서 save 호출시 -> http://localhost:8080/servlet-mvc/members/save

절대경로(추천) : 클라이언트에서 /save 호출시 -> http://localhost:8080/save

 

WEB-INF 폴더 : WEB-INF 내부에 있는 파일들은 컨트롤러를 거쳐야지 불려 질수 있음 ( 외부에서 호출 불가능 )

 

-redirect vs forward

redirect : client에 응답이 나가고 , HTTP헤더의 로케이션값으로 다시 서버에 요청하면서 로케이션값이 

            웹 브라우저의 url로 변경이됨 , 즉 server->client 가 두번 발생

forward : 서버 내부에서 일어나는 호출이기때문에 클라이언트가 전혀 인지하지 못함

 

jsp에서 request.getAttribute("이름") 으로 모델객체내용을 받을 수 있지만 너무 김 , 대신에..

${이름.필드변수} 로 바로 호출 가능  (프로퍼티 접근법, 필드변수만 적으면 상황에 맞게 자동으로 get or set이 호출)

 

jsp 선언부에 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 를 호출 하여 jstl 이용가능

 

MVC 패턴에서 , client에서 오는 요청은 무조건 먼저 Controller를 거친다 ( 규칙 ) 

 

-MVC 패턴의 한계 ( jsp 와 servlet 만으로 구현한 mvc 패턴 )  

컨트롤러내의 dispatcher 중복

viewPath="/WEB-INF/views/members.jsp" 의 내용중복

HttpServletRequest , HttpServletResponse 객체들이 꼭 사용되는 것은 아님 , service메소드 인자로 항상 쓰인다는 문제

공통처리가 어렵다 ( 로그처리 , 각종 중복코드 , 중복호출문제 )

=>

프론트 컨트롤러 패턴 : client 로부터 요청이 올때 다양한 공통처리를 미리 설계 해주는  객체(수문장역할)를 경유하여 서블릿으로 통하게 하는 방식 ( SPRING MVC 의 핵심 ) ,

대표컨트롤러를 두어 이후 나오는 컨트롤러들이 호출되게함

 

728x90

스프링부트는 WAS를 내장하고 있음

스프링은 WAS를 설치해줘야함

 

-서블릿-

introduction

 

@ServletComponentScan // 현재 패키지포함한 하위패키지 까지 서블릿을 찾아서 자동으로 등록후 실행하게 해줌

 

서블릿클래스를 작성하려면 , HttpServlet 를 상속받아야 함

 

@WebServlet(name , urlPatterns )  // url이 호출되면 ,  해당 어노테이션이 붙은 클래스내부의 service 메소드가 호출됨 

 

HttpServletRequest 객체 : WAS가 client->server로 오는 http 내용을 파싱해서 가공한 것

HttpServletResponse 객체 : WAS가 server->client로 보내는 http 내용을 가공하는데 이용함

 

쿼리 파라미터 : URL의 ? 뒤에 붙은 데이터들

request.getParameter() : 쿼리 파라미터 조회

response.setContentType() : 전송 데이터 타입 결정(http 헤더 정보)

response.setCharacterEncoding() : 문자 인코딩 방식 결정(http 헤더 정보)

요즘은 문자인코딩 방식은 utf-8로 통일되어 있음

response.getWriter().write() : http 바디에 데이터 삽입

 

*로그확인

application.properties -> logging.level.org.apache.coyote.http11=debug    ->http 헤더 정보를 보여줌 

-개발에서만 적용해보고 , 운영서버에서는 삭제해줘야함

 

main/webapp/index.html 은 웰컴페이지로 초기화면임

 

HttpServletRequest

 

     

HttpServletRequest : 서블릿이 개발자대신에 Http 메시지를 파싱해서 HttpServletRequest 객체에 담아줌

request.setAttribute(name, value)  : 임시 저장소 기능

request.getAttribute(name) : 임시 저장소 값 조회

request.getSession : 세션 정보를 받아옴 , HttpSession 객체로도 동일한 기능 수행

HTTP 스펙을 꼭 아는게 좋음

 

@WebServlet 이 붙은 클래스 내부의 메소드인 service는 접근제어자가 protected 이어야 한다.

 

HTTP 구성도 :  START LINE , 헤더 , 바디

 

*HTTP 해더조회

request.getHeaderNames(); //HTTP에 있는 모든 헤더정보를 열거형으로 반환  (old)

request.getHeaderNames().asIterator()
                .forEachRemaining(headerName -> System.out.println(headerName + ": " + request.getHeader(headerName)));   (new)

request.getHeader("원하는 헤더종류") // 헤더종류에 대한 값 반환

 

HTTP헤더 -> Accept-Language :  가장우선하는 언어 순으로 데이터가 들어감

 

request.getServerName() = localhost
request.getServerPort() = 8080
request.getLocale() = ko_KR //가장 우선순위 높은 브라우저 언어를 꺼내줌

request.getCookies() //쿠키들을 가져와서 반환해줌 , 쿠키도 HTTP 헤더에 담긴다
request.getContentType() = null // GET 방식은 null이다
request.getContentLength() = -1
request.getCharacterEncoding() = UTF-8

 

*네트워크 정보 조회

[Remote 정보] // 상대(클라이언트)의 정보
request.getRemoteHost() = 0:0:0:0:0:0:0:1
request.getRemoteAddr() = 0:0:0:0:0:0:0:1
request.getRemotePort() = 62036

[Local 정보] // 내 (서버) 정보
request.getLocalName() = 0:0:0:0:0:0:0:1
request.getLocalAddr() = 0:0:0:0:0:0:0:1
request.getLocalPort() = 8080

 

*HTTP 요청 데이터

-GET(url+쿼리파라미터)

ex ) http://url/?username=hello&age=20

body 에 데이터를 보내지 않음

url의 쿼리 파라미터에 데이터를 포함해서 전송할뿐

검색,필터,페이징등

 

-POST(HTML form)

 

Content-Type : body에 대한 타입

 

메세지 바디에 쿼리 파라미터 형식으로 전달 , username=hello&age=20

회원가입,상품주문

 

-HTTP message body

HTTP message body 에 데이터를 직접 담아서 요청

 REST API=HTTP API 에서 주로 사용

JSON(주로쓰임),XML,TEXT 형식으로 담아서 보냄

POST,PUT,PATCH 사용가능

 

*GET  쿼리파라미터

request.getParameterNames().asIterator()
         .forEachRemaining(paramName ->System.out.println(paramName+"="+request.getParameter(paramName)));  //모든요청파라미터 전부꺼냄

request.getParameter(name) // 단일 파라미터 조회   , 이름중복않됬을 경우에 사용하는게 원칙 

request.getParameterValues(name); // 이름 동일한 복수파라미터들 반환

HTTP 바디가 비어있으므로, content-type 이 null이다

 

*POST HTML Form

HTTP 메시지바디에 데이터가 다들어감

 

클라이언트에서 html 페이지는 서블릿 설정안해도 , url만 잘 작성하면 들어갈수 있다(정적 html)

request.getParameter(name) 으로 get방식과 동일하게 post방식에서도 데이터를 꺼내온다

content-type 이 필수로 적혀 있음

 

*HTTP message body

메시지바디에 내가원하는 데이터를 직접실어서 서버에 전송하는 것

HTTP API=REST API  방식

전송 데이터중 JSON,XML(legacy),TEXT 가 있지만 대부분 JSON 사용

서버 <-> 서버 통신  ,  앱 <->서버  , js기반클라이언트 <->서버

request.getInputStream();//얻어온 HTTP 바디의 내용을 바이트코드로 반환

StreamUtils.copyToString(인풋스트림, StandardCharsets.UTF_8);

//바이트를 문자열로 변환할 때는 어떤 인코딩 인지 알려줘야함 , 역의 경우도 마찬가지

 

-JSON 형식으로 데이터 주고받기

content-type: application/json 으로 해줘야함

서버에서 json데이터를 객체로 파싱해서 사용함

json의 key값에 매칭되는 클래스를 만들어주고 , getter &setter 을 생성해줘야함 -> 

jackson이 setter에 매칭되게 객체로 파싱해줌

getter , setter를 삽입 대신에  , @Getter @Setter 를 클래스위에 넣어주면 동일한 기능을 함(롬복기능)

( 자바 빈 개념 참고 )

 

* Lombok은 여러가지 어노테이션을 제공, 컴파일과정에서 코드를 생성해 주는 방식으로 동작하는 라이브러리

 

 

private ObjectMapper objectMapper = new ObjectMapper(); // instance value
HelloData helloData=objectMapper.readValue(제이슨문자열, HelloData.class); //json형태 문자열-> 객체로 파싱 (old) 

나중에 Spring mvc가 제공하는 기능을 이용하면 , 더 간략화 된다(new)

 

JSON 변환 라이브러리 : Jackson(default),Gson

 

HttpServletResponse

HTTP 응답 메세지 생성

200같은 HTTP 응답코드 , 헤더 , 바디를 일부자동생성 or 완전 자동생성 해줌

사용자가 Content-Type,쿠키,Redirect  셋팅을 편리하게 할 수 있게 해줌

response.setStatus(응답코드);//HTTP 응답코드를 넣읗 수 있음

 

HTTP스펙에서 응답의 첫번째는 'status-line' (응답코드) 이라고함

response.setHeader(name,value) // 헤더정보를 삽입

 

-Header 편의 메서드

response.setContentType("text/plain");   // 콘텐트 편의메소드
response.setCharacterEncoding("utf-8"); // 콘텐트 편의메소드

response.addCookie(cookie); // 쿠키 편의 메소드

response.setStatus(HttpServletResponse.SC_FOUND); //redirect 편의 메소드 , HTTP 응답코드 수정
response.setHeader("Location", "/basic/hello-form.html"); //redirect 편의 메소드 ,  리다이렉트할 위치지정

response.sendRedirect("/basic/hello-form.html"); //redirect 편의 메소드 , 윗 두줄과 동일한 기능을 수행(302상태코드)

( 301 , 302 리다이렉션의 의미 )

 

PrintWriter writer = response.getWriter(); // 메세지 바디에 데이터 삽입
writer.println("ok");

 

-HTTP 응답스펙

START LINE , 헤더 , 바 디

 

*HTTP응답데이터 - 단순 텍스트 , HTML , JSON 응답

-단순텍스트

PrintWriter writer = response.getWriter(); // 메세지 바디에 데이터 삽입
writer.println("ok");

 

-HTML 응답(HTTP 바디에 html내용 삽입하기)

HTTP 응답으로 HTML을 반환할 때는 content-type: text/html 로 지정해줘야함

헤더편의 메소드를 통해 Encoding방식을 잡아줘야함

 

-JSON 보내기

HTTP 메세지 바디에 JSON 넣어보내기

객체 -> JSON 으로 파싱해야함

private ObjectMapper objectMapper = new ObjectMapper(); //인스턴스 value
objectMapper.writeValueAsString(객체);  // json형 문자열반환  (old)

 

application/json은 스펙상 utf-8형식이 디폴트로 알아서 잡혀진다

 

Form data를 body에 담아 전송할 때는 POST방식만 허용한다

+ Recent posts