코드 리뷰
- required : 선택 안 하면 요청할 수가 없음
- response.setContentType("text/html; charset=UTF-8");
- 응답 시 형식이 뭔지 알리는 것
- 브라우저마다 문자코드 해석하는 default가 다르기 때문,
- request.setCharacterEncoding("UTF-8");
- post 방식으로 보내는 값이 한글 안 깨지게
- GET 방식은 톰캣이 기본적으로 자동으로 한글처리해주기 때문에 한글이 안 깨짐
- 쿼리 문자 추출 시, 한글이 추출 잘 되게
- LocalDate.parse() (LocalDate, LocalDateTime 스터디할 필요!
LocalDate parse() method in Java with Examples - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
www.geeksforgeeks.org
- post
- form 태그있어야함
- 요청 바디안에 담겨서 전달함
- 전달되는 name-value쌍 외부에 안 보임
- get
- 하이퍼링크, 이미지, form 태그 메소드 속성 생략될 때,,
- 길이의 제한있음
- 외부에 공개됨
- 요청 header만 있음
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
doGet(request, response);
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
String method = request.getMethod();
if(method.equals("POST"))
request.setCharacterEncoding("utf-8");
out.print("<h2>요청 방식 : "+method+"</h2>");
out.print("<h2>Query 문자열 : "+
request.getParameter("name")+"</h2>");
out.close();
System.out.println(method+" 방식 수행");
}
- '/'시작하면 절대 uri
- 젤 첫번째에 프로젝트 명이 나와야한다.
- 최상위 폴더 wepapp까지 자동으로 찾아감 (webapp부터 시작)
- 상대 uri : 현재 디렉토리 기준으로
- getHeader("referer")
상태정보 유지 기술
package base;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet({ "/getHTML", "/getXML", "/getJSON", "/getImage" })
public class ResponseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String uri = request.getRequestURI();
System.out.println(uri);
String filename = "";
String contentType = "";
if (uri.endsWith("getHTML")) {
filename = "c:/Temp/sample.html";
contentType = "text/html; charset=utf-8";
} else if (uri.endsWith("getXML")) {
filename = "c:/Temp/sample.xml";
contentType = "application/xml; charset=utf-8";
} else if (uri.endsWith("getJSON")) {
filename = "c:/Temp/sample.json";
contentType = "text/json; charset=utf-8";
} else {
filename = "c:/Temp/trans_duke.png";
contentType = "image/png";
}
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
response.setContentType(contentType);
if(contentType.startsWith("image")) {
byte[] content = new byte[(int)f.length()];
ServletOutputStream sos = response.getOutputStream();
fis.read(content);
sos.write(content);
sos.close();
} else {
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
BufferedReader br = new BufferedReader(isr);
PrintWriter out = response.getWriter();
String line = null;
while((line = br.readLine()) != null)
out.println(line);
out.close();
br.close();
isr.close();
}
fis.close();
}
}
- @WebServlet({ "/getHTML", "/getXML", "/getJSON", "/getImage" })
- file io : 운영체제 알맞는 패스 정보
- 읽어서 클라이언트한테 write
- io는 운영체제에 무관하게 만드는게 쉬운일이 아님
- 운영체제에 무관하게 만들려고 : Stream객체를 써서
- 한 쪽 방향으로만 흐른다. (내보내든, 읽어오든)
- txt파일 읽어온다 : textreader
- 출력 : outputStream,,,
- getOutputStream () : 이미지파일을 읽어와야해서, 통채로 읽어서 통채로 내보냄
- FileInputStream : 바이너리 스트림을 이용해서 읽어오겠다.
- InputStreamReader isr = new InputStreamReader(fis, "utf-8");
- 읽기모드로 동작하는 바이트 스트림을 문자 스트림으로 변환해주는
- servlet
- 객체 생성되면, 서버 죽을 때까지 아니면 리로드될때까지 살아있다.
- 생성된 객체 계속 재활용함
- 여러클라이언트 하나의 서비스 요청하면
- 요청한 수만큼 스레드 만들어서
- 하나의 서블릿객체 공유해서 사용함
- 처리 효율 높일 수 있음
- 맴버 변수로 하느냐, 지역변수로 하느냐 크게 달라져서 신경써야함
package base;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/memberlocal")
public class MemberLocalServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
int member_v=0;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int local_v=0;
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
member_v += 10;
local_v += 10;
out.print("<ul>");
out.print("<li>멤버변수 : "+ member_v +"</li>");
out.print("<li>지역변수 : "+ local_v +"</li>");
out.print("</ul>");
out.close();
}
}
- 멤버 변수 : 객체 생성시에 메모리 할당 됨 (최초 요청 했을 때)
- 지역 변수 : 호출 될 때마다 할당 됨
- 개별 할당은 가능함
- 메소드 수행이 끝나면 사라짐
- 어떤 클라이언트가 요청하든, 재활용 된다.
- 모든 클라이언트가 공유함 (리로드, 서버 죽을 때까지)
- 계좌번호, 개인정보는 멤버 변수에 넣으면 안됨.
- 웬만하면 지역변수
- 다른 클라이언트가 멤버 변수가 바뀔 수가 있음
- 개별할당하면서 다음 요청시에도 그대로 쓸 수 있게 하려면(ex 쇼핑카트)
HttpSession
- 클라이언트 별로 개별적으로 만들어짐
- (클라이언트별로 하나씩만들어짐) - 두개를 안 만들어줌
- 이름을 부여해서 name-value쌍으로
- 원하는 시간까지 유지
- 갯수 제한 없음
- WAS가 알아서 관리해줌 - 안 만들어져 있으면 새로 만들어줌
- 일정 시간동안 요청을 안 하면
- 세션객체는 자동 삭제된다 - WAS가
- 일정 시간 = 기본 값 : 30분 (api로 바꿀 수 있다)
- 직접 삭제도 가능
- 클라이언트 별로 객체로 만들어서 넣어주면 됨 (기본형은 못 넣음)
- 유지할 필요가 없으면 지우면 된다.
- 꺼내는 것
- 상태 정보 유지
- 목적의 데이터들 (로그인 했다, 로그인을 성공했다. 어떤 상품을 몇 개 구매하고 싶다라는 장바구니)
- 현재 어떤 상태다 (이 클라이언트는)
- 클라이언트별로 유지하는 기술
- 어떤 클라이언트것인지 구별하는 것
- 회원가입 안 해도 장바구니에 상품 담을 수 있다.
- 세션 id가 하나씩 부여됨
-
- cookie를 이용한 방법
- HttpSession객체 이용
- 서버에 클라이언트 별 상태 정보가 저장되어 있음
- 방문했던 적이 있는 클라이언트 안에 보관되어있는 데이터
- name-value쌍의 데이터
- 서블릿, 자바스크립트로 구현 가능 (서블릿만의 구현 기술이 아님)
- 서버가 클라이언트한테 응답 헤더에 set-cookie해서 줌
- 주기전에 id에 해당하는 session객체가 있는지 본다.
- 응답 헤더에 전달된 쿠키 정보를 저장
- 브라우저가 보관함
- 다시 요청할 때 요청 헤더에 저장된거 담아서 줌
- 브라우저 유효 서버가 누구인지 다 앎
- 앞으로 24시간 팝업창 띄우지 않기, 로그인 시 계정 보관
- 중요한 상태 정보는 서버에 저장
- 세션객체의 아이디만 클라이언트에 저장
- API
- getSession( true or false)
- HttpSession 리턴함
- 기본 값 true
- 이미만들어져있는 얘 찾아서 리턴
- 안 만들어져 있으면 새로 만들어서 리턴함
- false
- setAttribute(이름, 객체)
- 똑같은 이름의 객체 여러개 등록 X
- 마지막에 등록된 얘가 저장되어 있음
- 강제 형변환 필수 - 리턴 값이 object라서
- 필요없으면 removeAttribute( )
- invalidate( )
package base;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/sessiontest1")
public class SessionTestServlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
int member_v=0;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int local_v=0;
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
if(session.getAttribute("cnt") == null)
session.setAttribute("cnt", new int[1]); // 데이터를 저장할 방을 등록
int[] session_v = (int[])session.getAttribute("cnt");
session_v[0] += 10;
member_v += 10;
local_v += 10;
out.print("<ul>");
out.print("<li>멤버변수 : "+ member_v +"</li>");
out.print("<li>지역변수 : "+ local_v +"</li>");
out.print("<li>세션객체에저장된배열원소 : "+ session_v[0] +"</li>");
out.print("</ul>");
out.close();
}
}
-
- - int[] session_v = (int[])session.getAttribute("cnt");
- - cnt로 저장되어 있는 객체 꺼내오기
- session객체 id가 전달 됨
- - 유호 path : /edu
- - 새로 고침하면, 요청 해더에는 id없음.
- 응답 헤더에 id가 있다.
- - 계속 서버에 id 보냄
- 엣지로 열면 개별적으로 증가함
- - 크롬용, 엣지용 개별적으로 만들어져 있음
- - 크롬을 여러개 열어도 자원을 공유함 : 두개 만들어지진 않음
- - 다른 브라우저만, 크롬을 띄울 때 시크리티 모드면 별개의 객체 만들어짐
-
- 유효 도메인 판단된 경우에만 세션 id가 보내진다.
- - 브라우저 죽을 때 까지 유효함
package base;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/sessiontest2")
public class SessionTestServlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.print("생성된 세션객체의 ID : "+session.getId());
out.print("<br>세션 객체가 생성된 시간 : "
+ new Date(session.getCreationTime()));
out.print("<br>현재 시간 : " + new Date());
out.close();
}
}
- 유효 시간 안 주면 브라우저가 죽기 전까지 있음
-
- 현재 시간은 바뀌어도 세션 객체 만들어지는 시간은 안 바뀜
- getCreationTime() 세션 객체 만들어진 시간
- 클라이언트 별로 개별적으로 만들어진다.
package base;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/sessiontest3")
public class SessionTestServlet3 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
String action = request.getParameter("action");
HttpSession session = null;
String msg = "action=create 또는 action=destroy를 전달하시오.";
if(action != null && action.equals("create")) {
session = request.getSession();// getSession(true)와 동일
if(session.isNew())
msg = "세션 객체가 생성됨";
else
msg = "세션 객체는 이미 생성되어 있었음";
} else if (action != null && action.equals("destroy")) {
session = request.getSession(false);
if(session != null) {
session.invalidate();
msg = "세션 객체가 삭제됨";
} else
msg = "삭제할 세션 객체가 없음";
}
out.print("<h2>"+msg+"</h2>");
out.close();
}
}
- session = request.getSession(false);