web server 측에서 web client가 요청한 program을 실행한 후 그 결과를 HTTP Response를 돌려준다.
이로 인해 언어마다 여러가지 기술들이 나오게 된다.
- MS : ASP, PHP
- JAVA : Servlet, JSP

Web 상에서 동작하는 Java Program을 만들기 위한 규칙이다.
Servlet → HTTPServlet → 상속해서 구현 → eclipse의 도움을 받아서 servlet을 생성
Web Server에게 우리 project의 존재를 알려줘야 한다.
server - add and remove
browser에서 URL을 이용해 request를 보낸다.
URL : HTTP://localhost:8080/html/index.html
HTML (태그, 속성)
CSS
Javascript
form
client가 서버에 데이터를 전달하는 목적으로 사용한다.
action - 입력된 내용을 가지고 요청을 보낼 서버 쪽 프로그램에 대한 URL에 해당된다.
request method - 클라이언트가 서버에 Request를 보내는 방법을 지정한다. 총 6개 존재. 이중 4개만 사용. 일반적으로는 2개만 이용 (생략 가능. 만약 생략되면 "GET")
GET, POST, PUT, DELETE

✔ GET
Query String을 이용
Query String 단점 😡
- 보내려는 데이터가 URL에 노출
- Reqeuest URL의 길이에 제한이 있기 때문에 데이터에 대한 제한이 있음
( 많은 양의 데이터를 보내지 못함, 대용량 데이터 X )
- browser 주소창에 URL 입력하고 enter → request 전달
- hypertext(링크)를 이용해서 request
a href = " " 를 이용 click해서 request 전달- Form 태그 이용 → method가 GET인 경우, 이 form을 이용해 request
✔ POST
Query String을 사용하지 않고, request header에 데이터를 포함시킨다.
- URL의 노출이 되지 않된다.
( 보안성이 있다라고 하긴 힘들지만 보안성 측면에서 그나마 나은 경우에 해당된다. )- 길이 제한이 없다.
- Form 태그 이용 → method가 POST인 경우, 이 form을 이용해서 request
Form 태그를 이용할 경우 거의 예외없이 "POST" 방식 사용하는 것을 선호한다.
왜? GET 방식과 비교했을 때 POST 방식이 더 나은 방식이기 때문이다. ( Query String 단점 )
아래 결과는 GET 방식을 통해 데이터 전달한 경우이다.
( URL을 확인해보면 Query문에 전달 데이터가 노출되는 것을 확인할 수 있다 )

Client ---------------> Server
request
+ 사용자 데이터


HttpServletRequest, HttpServletResponse 객체를 생성한 컨테이너는 요청에 알맞은 servlet을 찾게 되는데, servlet을 찾기 위해서는 개발자가 servlet을 매핑해주어야 한다.
client가 URL을 통해 HTTP request를 보내면 HTTP server가 이 request를 받고 해당 HTTP Request를 servlet container(WAS)로 보낸다.
( request - "Hello" servlet을 실행시켜 주세요! )
HTTP Request를 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 두 객체를 생성한다.
Servlet Container는 요청한 URL을 분석하여 어느 servlet에 대한 요청인지 찾고, 없으면 Java class로부터 해당 servlet 인스턴스를 생성한다.
Servlet Container는 요청을 처리할 thread를 하나 생성한다.
(요청이 들어올 때마다 thread를 생성 → thread 기반)
해당 servlet에서 service 메서드를 호출한 후 POST, GET 여부에 따라 doGet( ) 또는 doPost( )를 호출한다.
(인자 - HttpServletRequest, HttpServletResponse)
doGet( ) 혹은 doPost( ) 메서드는 동적 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보낸다.
응답이 끝나면 HttpServeltRequest, HttpServletResponse 두 객체를 소멸시킨다.
servlet은 thread의 공용 객체이다. 그러므로 servlet field는 모든 thread에 대해서 공유된다는 점 주의하자!🧐
Servlet은 싱글톤 패턴!
객체의 인스턴스가 오직 1개만 생성되는 패턴에 해당된다.
/**
* Servlet implementation class TestServlet
*/
@WebServlet("/hello")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 1. 입력을 받는다.
// 2. 로직처리 한다.
// 3. 클라이언트에게 결과를 출력해요!
// 클라이언트에게 특정 문자열을 출력해야 되기 때문에 OutputStream이 필요하다
// Response header
response.setContentType("text/html; charset=UTF-8");
// Response body
PrintWriter out = new PrintWriter(response.getOutputStream());
out.println("<html><head><body><H1>하이하이</H1></body></head></html>");
out.close();
}

Get방식의 한글처리를 위한 변경
만약 한글 데이터를 전달받으려면 약간의 처리를 해 주어야 한다!
만약 GET방식인 경우, Tomcat의 입력 stream의 encoding을 변경해줘야 한다.
( server-tomcat-server.xml-아래 코드와 같이 변경해주어야 한다 )

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 입력받고 (request 객체를 받아야 함)
// 한가지 주의해야 할 점은... 입력을 받을 때 사용되는 Stream의 encoding이 ISO-8859-1 (한글이 깨짐)
// 만약 한글 데이터를 전달받으려면 약간의 처리를 해 주어야 해요!
// - 만약 GET방식인 경우, Tomcat의 입력 stream의 encoding을 변경해줘야 한다. (server-tomcat-server.xml 수정)
// - 만약 POST방식인 경우,
// request.setCharacterEncoding("EUC-KR");
String email = request.getParameter("userEmail");
String pw = request.getParameter("userPassword");
System.out.println(email+ ", "+ pw);
// 2. 로직처리
// 3. 출력처리
}

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 여러 thread에 의해 공용된다. (필드는 공용됨)
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Exception e) {
// TODO: handle exception
}
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 입력받고 (request 객체를 받아야 함)
// 한가지 주의해야 할 점은... 입력을 받을 때 사용되는 Stream의 encoding이 ISO-8859-1 (한글이 깨짐)
// 만약 한글 데이터를 전달받으려면 약간의 처리를 해 주어야 해요!
// - 만약 GET방식인 경우, Tomcat의 입력 stream의 encoding을 변경해줘야 한다. (server-tomcat-server.xml 수정)
String email = request.getParameter("userEmail");
String pw = request.getParameter("userPassword");
// 2. 로직처리
// 입력된 email과 password가 database table에 존재하는지 확인!
// JDBC code
String jdbcURL = "jdbc:mysql://localhost:3306/sqldb?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean loginStatus = false;
try {
con = DriverManager.getConnection(jdbcURL, "root", "test1234");
String sql = "SELECT * FROM tmpuser where email=? and password=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, email);
pstmt.setString(2, pw);
rs = pstmt.executeQuery();
if (rs.next()) {
loginStatus = true;
}
} catch (Exception e) {
// TODO: handle exception
} finally {
// close 처리 진행
try {
rs.close();
pstmt.close();
con.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
// 3. 출력처리
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = new PrintWriter(response.getOutputStream());
if (loginStatus) {
out.println("환영합니다!"); }
else {
out.println("로그인에 실패했습니다");
}
out.close();
}
해당 데이터베이스가 없으므로 실패로 뜹니다..!


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 입력
// 2. 로직
// ServletContext를 사용해보아요!
// ServletContext 객체를 얻어와요! ( 공유객체에 대한 Reference를 획득)
ServletContext context = getServletContext();
// 획득한 ServletContext에 특정 정보를 저장해 보아요!
context.setAttribute("product", "냉장고");
// 3. 출력
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 입력
// 2. 로직
ServletContext context = getServletContext();
String product = (String)context.getAttribute("product");
// 3. 출력
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = new PrintWriter(response.getOutputStream());
out.println("얻어온 결과는 : " + product);
out.close();
}
http://localhost:8080/html/servletb 먼저 실행
( 얻어온 결과는 : null )
http://localhost:8080/html/servleta 실행
( 냉장고 문자열 저장 )
http://localhost:8080/html/servletb 실행
( 얻어온 결과는 : 냉장고 )


- session은 분 단위의 시간 설정을 해줄 수 있고, 타임아웃되면 객체를 사용할 수 없는 상태가 된다.
- 웹 컨테이너는 기본적으로 한 웹 브라우저마다 한 세션을 생성한다.
- 웹 브라우저마다 세션이 따로 존재하기 때문에, 세션은 웹 브라우저와 관련된 정보를 저장하기에 알맞은 장소이다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 입력
String id = request.getParameter("myID");
// 2. 로직
// 해당 client에게 session을 할당하거나 할당된 session을 찾아와요!
HttpSession session = request.getSession();
session.setAttribute("id", id);
// 3. 출력
}
// 1. 입력
// 2. 로직
HttpSession session = request.getSession();
String result = (String)session.getAttribute("id");
// 3. 출력
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = new PrintWriter(response.getOutputStream());
out.println("얻어낸 결과는 : "+result);
out.close();
session에 데이터를 저장
http://localhost:8080/html/mysession?myID=kim
session에서 데이터를 추출
http://localhost:8080/html/usesession
얻어낸 결과는 : kim다른 브라우저에서 usesession을 불러오면, null로 뜬다.
즉, 한 웹 브라우저마다 한 세션을 생성한다.