일흔 번째 수업

정혅·2024년 11월 28일

더 조은 아카데미

목록 보기
74/76

오전 문제

jsp 내장 객체 영역 page영역, request영역, session영역, application영역

include문제

  • a.jsp에서 b.jsp include
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <h1>a.jsp</h1>
    <%@include file="b.jsp"%>
</body>
</html>
  • b.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<h1>b.jsp</h1>
</body>
</html>

submit 문제

SubmitTest.jsp를 만들자
SubmitTestOK.jsp를 만들자.
SubmitTest.jsp에서 이름을 입력 받아서
SubmitTestOK.jsp에서 출력하자.
SubmitTest.jsp에서 유효성 체크를 자바스크립트로 하자. + 되돌아가기 버튼도 생성

  • SubmitTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <form action="SubmitTestOK.jsp" method="post" name="nameForm" onsubmit="return check()">
        이름 : <input type="text" name="name"> <input type="submit" value="출력">
    </form>
    <script>
        function check() {
            var nameForm = document.nameForm;
            if (nameForm.name.value == "") {
                alert("이름을 입력하세요.");
                return false;
            } else
                return true;
        }
    </script>
</body>
</html>
  • SubmitTestOK.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    request.setCharacterEncoding("utf-8");
    %>
    이름 :
    <%=request.getParameter("name")%>
    <a href="SubmitTest.jsp"><button>돌아가기</button></a>
</body>
</html>

input태그의 name값 모르는 상태로 가져오기

  • getParameterNames() / getParameterValues()

  • 돌아가기 버튼과 초기화 버튼 추가했음

  • write.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <form action="writeOK.jsp" method="post">
        <table border="1">
            <tr>
                <td>제목</td>
                <td><input type="text" name="title" required></td>
            </tr>
            <tr>
                <td>이름</td>
                <td><input type="text" name="name" required></td>
            </tr>
            <tr>
                <td>비밀번호</td>
                <td><input type="password" name="password" required></td>
            </tr>
            <tr>
                <td>E-mail</td>
                <td><input type="email" name="email"></td>
            </tr>
            <tr>
                <td>취미</td>
                <td>취미: <input type="checkbox" name="hobby" value="수영">수영 <input type="checkbox"
                    name="hobby" value="야구">야구 <input type="checkbox" name="hobby" value="축구">축구 <input
                    type="checkbox" name="hobby" value="농구">농구
                </td>
            </tr>
            <tr>
                <td colspan="2"><textarea name="contents" cols="50" rows="10" style="resize: none;"></textarea></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="등록"><input type="reset" value="초기화"></td>
            </tr>
        </table>
    </form>
</body>
</html>
  • writeOK.jsp
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    request.setCharacterEncoding("utf-8");
    Enumeration<String> names = request.getParameterNames();
    while (names.hasMoreElements()) {
        String name = names.nextElement();
        String[] values = request.getParameterValues(name);
        out.write(name + " : ");
        for (int i = 0; i < values.length; i++) {
            out.print(values[i] + " ");

        }
        out.write("<br>"); // 한 줄씩 개행
    }
    %>
    <a href="write.jsp"><button>돌아가기</button></a>
</body>
</html>

게시물 개수 구하기

<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/project?serverTimeZone=UTC";
    String sqlId = "root";
    String sqlPw = "1234";
    String sql = "select count(*) from board";
    int total = 0;

    try {
        Class.forName(driver);
    } catch (ClassNotFoundException e) {
        System.out.println("드라이버 로드 실패"); //이클립스 콘솔에 출력
        out.write("드라이버 로드 실패"); //웹 브라우저 화면에 출력
    }

    try (Connection conn = DriverManager.getConnection(url, sqlId, sqlPw);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql)) {
        if (rs.next()) {
            total = rs.getInt(1);
            //total = rs.getInt("count(*)"); 이렇게도 가능

        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    %>게시물 수 :
    <%=total%>
</body>
</html>
  • 게시물 수가 현재 project 데이터베이스에 board테이블에 데이터가 2개 있기 때문에 게시물 수 : 2 라고 브라우저에 출력된다.

Servlet

package com.ironman.www;

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("/HiServlet")
public class HiServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public HiServlet() {
        super();
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.print("<!doctype html>");
        out.print("<html>");
        out.print("<head>");
        out.print("<title>폼 만들기</title>");
        out.print("</head>");
        out.print("<body>");
        out.print("<form action=\"HelloServlet\" method=\"post\">");
//        out.println("<form action='HelloOK' method='post'>"); 작은 따옴표로 해도됐던것을...
        out.print("<table border = \"1\">");

        out.print("<tr>");
        out.print("<td>이름 : </td>");
        out.print("<td><input type=\"text\" name=\"name\"></td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td>아이디 : </td>");
        out.print("<td><input type=\"text\" name=\"id\"></td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td>비밀번호 : </td>");
        out.print("<td><input type=\"password\" name=\"password\"></td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td>취미 : </td>");
        out.println("<td><input type='checkbox' name='hobby' value='독서'> 독서");
        out.println("<input type='checkbox' name='hobby' value='요리'> 요리");
        out.println("<input type='checkbox' name='hobby' value='조깅'> 조깅");
        out.println("<input type='checkbox' name='hobby' value='수영'> 수영");
        out.println("<input type='checkbox' name='hobby' value='취침'> 취침");    
        out.print("</td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td>전공 : </td>");
        out.print("<td><input type=\"radio\" name=\"major\" value=\"kor\">국어");
        out.print("<input type=\"radio\" name=\"major\" value=\"eng\">영어");
        out.print("<input type=\"radio\" name=\"major\" value=\"math\">수학");
        out.print("<input type=\"radio\" name=\"major\" value=\"design\">디자인");
        out.print("</td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td>프로토콜 : </td>");
        out.println("<td>");
        out.println("<select name='protocol'>");
        out.println("<option>http</option>");
        out.println("<option selected>ftp</option>");
        out.println("<option>smtp</option>");
        out.println("<option>pop</option>");
        out.println("</select>");
        out.print("</td>");
        out.print("</tr>");

        out.print("<tr>");
        out.print("<td colspan=\"2\"><윙input type=\"submit\" value=\"전송\"><input type=\"reset\" value=\"초기화\"></td>");
        out.print("</tr>");

        out.print("</table>");
        out.print("</body>");
        out.print("</html>");
    }

}
  • 위에서 값 받아와서 출력하기 > HelloServlet.java
package com.ironman.www;

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(description = "HelloServletTest", urlPatterns = { "/HelloServlet" })//description은 설명
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
        // TODO Auto-generated constructor stub
    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //doPost메서드로 해야지 post방식을 받을 수 있다.
        request.setCharacterEncoding("utf-8"); //request 요청 > 클라이언트가 서버에 정보를 요청 >> post방식으로 넘어오는 데이터를 인코딩
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");//response 응답 > 응답하는 페이지의 데이터를 인코딩
        PrintWriter out = response.getWriter();
        out.print("<!doctype html>");
        out.print("<html>");
        out.print("<head>");
        out.print("<title>입력 데이터 출력하기</title>");
        out.print("</head>");
        out.print("<body>");

        out.println("이름 : " + request.getParameter("name") +"<br>");
        out.println("아이디 : " + request.getParameter("id") +"<br>");
        out.println("비밀번호 : " + request.getParameter("password") +"<br>");
        out.println("취미 : [");
        String[] hobby = request.getParameterValues("hobby");
        for(int i=0;i<hobby.length;i++) {
            out.println(hobby[i]);
            if(i!=hobby.length-1)out.println(", ");
        }
        out.println("]<br>");
        out.println("전공 : " + request.getParameter("major") +"<br>");
        out.println("프로토콜 : " + request.getParameter("protocol") +"<br>");

        out.print("</body>");
        out.print("</html>");
    }

}

Servlet의 역할

  1. 클라이언트 요청 처리 : 클라이언트가 웹 브라우저나 다른 HTTP 클라이언트를 통해 서버에 요청을 보낼 때, 이 요청은 서블릿에 의해 처리된다.

  2. 비즈니스 로직 실행: 서블릿은 요청을 처리하고, 필요한 비즈니스 로직을 실행한다.

    • 클라이언트가 전송한 데이터를 검증하고 저장하는 등의 작업을 수행할 수 있다. > JDBC
  3. 응답 생성: 요청을 처리한 후, 서블릿은 클라이언트에게 적절한 응답을 생성하고 전송한다.

    • HTML, JSON, XML등의 다양한 형식으로 생성될 수 있고, 이를 통해 클라이언트는 필요한 정보를 받게 된다.

Servlet 동작 과정

  1. 클라이언트 요청 전송 : 사용자가 회원가입 폼을 작성하고 type이 submit인 버튼을 클릭하면, 폼 데이터는 POST 메서드로 서블릿에 전송된다.

  2. 서블릿 요청 처리 : 서블릿 컨테이너(ex: Tomcat)는 url패턴에 매핑된(action으로 던지고, 어노테이션으로 받는) 해당 서블릿 클래스 이름의 doPost 메소드를 호출한다.

    • doPost() 메소드는 클라이언트의 요청 데이터를 읽고 처리한다.
  3. 비즈니스 로직 실행 : 요청 데이터를 사용해 필요한 비즈니스 로직을 실행한다.

    • 사용자가 입력한 회원가입의 데이터들을 데이터베이스에 저장할 수 있다
  4. 응답 생성 및 전송 : 요청 처리가 완료된 후, 응답을 생성하여 클라이언트에게 전송한다. >> 회원가입 성공 메시지를 보여준다던가..

서블릿은 클라이언트와 서버 간의 상호 작용을 처리하는 서버 측 컴포넌트로, 클라이언트가 서버에 데이터를 전송할 때 핵심적인 역할을 한다.

클라이언트 요청을 처리하고, 비즈니스 로직을 실행하며, 적절한 응답을 생성해 클라이언트에게 전송하는 작업을 수행한다. > 웹 애플리케이션에서 동적인 콘텐츠 생성을 가능하게 한다.


Servlet Life Cycle > 메소드

  1. doGet(): 이 메소드는 HTTP GET 요청을 처리한다. GET요청은 주로 서버에서 정보를 검색하는데 사용된다.

    • GET요청의 데이터는 URL에 포함되어 전송되므로, 데이터의 크기가 제한적이며 민감한 정보를 전송하는데에는 적합하지 않다.
  2. doPost() : HTTP POST 요청을 처리한다. POST요청은 주로 클라이언트에서 서버로 데이터를 전송하는데 사용된다.

    • POST요청의 데이터는 요청 본문에 포함되어 전송되므로, 데이터의 크기가 크고 민감한 정보를 전송하는데 적합하다
  3. service() : HTTP 요청의 유형(GET, POST등) 에 따라 적절한 doGet(), doPost()등의 메소드를 호출한다

    • service() 메소드를 사용하면 요청 유형에 따라 적절한 처리를 자동으로 수행할 수 있다.
  4. init() : 서블릿이 초기화할 때 호출된다. 서블릿 컨테이너는 서블릿 객체를 생성하고 초기화할 때 이 메서드를 호출한다.

    • 서블릿 초기화 파라미터를 설정하거나 초기 리소스를 할당할 때 사용한다.
  5. destroy() : 서블릿이 종료될 때 호출된다. 자원 해제 등의 정리 작업을 수행한다.

  6. doPut() : HTTP PUT 요청을 처리하는 메서드다. 자원 업데이트 요청에 사용된다.

    • PUT요청에 대한 처리를 수행한다.
  7. doDelete() : HTTP DELETE요청을 처리하는 메서드다. 자원 삭제 요청에 사용된다.

    • DELETE요청에 대한 처리를 수행한다.
  8. doHead() : : HTTP HEAD 요청을 처리하는 메서드다. 서버에서 리소스에 대한 메타데이터만 반환할 때 사용된다.

    • HEAD요청에 대한 처리를 수행한다.
  9. doOptions() : HTTP OPTIONS 요청을 처리하는 메서드다. 서버에서 지원하는 HTTP 메서드 목록을 반환할 때 사용된다.

    • OPTIONS 요청에 대한 처리를 수행한다. 서버가 지원하는 HTTP메서드 목록을 응답한다.
  10. doTrace() : HTTP TRACE 요청을 처리하는 메서드다. 요청의 진단을 위해 사용된다.

    • TRACE요청에 대한 처리를 수행한다. 클라이언트에게 요청을 그대로 반환한다.

메소드 오버라이딩 예제로 보는 호출 순서

package com.ironman.www;

import java.io.IOException;

import javax.servlet.ServletConfig;
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("/LifeTest")
public class LifeTest extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public LifeTest() {
        super();
        System.out.println("생성자 호출");
    }

    public void init(ServletConfig config) throws ServletException {
        System.out.println("init() 메소드 호출");
    }

    public void destroy() {
        System.out.println("destroy() 메소드 호출");
    }

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("service() 메소드 호출");
    }

}
  • init(), service(), destroy()메소드를 오버라이딩 해 실행시키면, 콘솔창에 아래와 같이 뜬다.

    • 생성자 호출

    • init() 메소드 호출

    • service() 메소드 호출

  • 새로고침을 누르게 되면 아래와 같이 콘솔창에 뜬다.

    • service()메소드 호출
  • 후에 서버를 종료시키면 객체가 소멸되면서 아래와 같이 콘솔창에 뜬다.

    • destroy() 메소드 호출

생성자 호출 → init() 호출 → service() 호출 → 서버가 종료된 후 destroy()호출

import java.io.IOException;
import java.io.PrintWriter;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.ServletConfig;
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("/ServletLifeCycle")
public class ServletLifeCycle extends HttpServlet {
    private static final long serialVersionUID = 1L;


    public ServletLifeCycle() {
        super();
        System.out.println("ServletLifeCycle() Constructor");
    }

    @PostConstruct
    private void initPostConstruct() {
        System.out.println("@PostConstruct initPostConstruct");
    }

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("init");
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("service");
        response.setContentType("text/html; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>service</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("service");
        out.println("</body>");
        out.println("</html>");
    }

    public void destroy() {
        System.out.println("destroy");
    }

    @PreDestroy
    private void destoryPreDestory() {
        System.out.println("@PreDestroy destoryPreDestory");
    }
}
  • 생성자가 제일 처음에 호출되고, @PostConstruct가 붙은 메소드가 그 이후에 호출되고, init메소드가 호출되고, service메소드가 호출된다. 이 상태에서 새로고침을 누르면 service메소드만 호출되어 해당 메소드만 출력된다.

  • 서버를 종료한 후 (빨간 네모 끄면) 콘솔창을 보면 destroy()메소드가 호출되고, @PreDestory어노테이션이 붙은 메소드가 출력되는 것을 볼 수 있다.


JSP 내장 객체 영역 중 Session영역

  • session : 클라이언트가 웹 컨테이너에 최초 접속하면 자동으로 생성되는 객체로, 사용자로부터 넘어온 정보를 서버 측에 저장하는 개념으로, 웹 브라우저당 한 개의 세션이 웹 컨데이너에 저장된다.

    • 웹 서버의 서비스를 받는 사용자를 구분할 수 있는 단위로, 세션을 사용하면 여러 사이트를 돌아다녀도 사용자가 웹 서버의 세션에 의해 가상적으로 연결되어 있으므로 정보를 잃지 않는다. >> HTTP 프로토콜이 기본적으로 상태를 유지하지 않는 (stateless) 특성을 보완하기 위한 기능이다.

서버에 값을 저장하며, 서버는 세션을 사용해 클라이언트 상태를 유지할 수 있기에 로그인한 사용자의 정보를 유지하기 위한 목적 등에 사용된다. > 속성 값을 설정하거나 읽어오는 메소드들이 제공되고, 세션을 삭제하거나 세션의 유효 시간을 설정하는 기능도 제공된다.

  • 쿠키 : 웹 브라우저에 사용자의 상태를 유지하기 위한 정보를 저장 >> 세션은 웹 서버 쪽의 웹 컨테이너에 상태를 유지하기 위한 정보를 저장

    • 사용자의 상태 유지를 위한 정보를 웹 브라우저에 저장해서 웹 서버가 쿠키 정보를 읽어서 사용 > 웹 브라우저에 저장된 쿠키는 웹 서버에서 열어볼 수 있다는 점에서 보안상 문제가 발생할 수 있다.

따라서 사용자의 정보를 유지하기 위해서는 쿠키를 사용하는 것 보다 세션을 사용한 웹 브라우저와 웹 서버의 상태 유지가 훨씬 안정적이고, 보안상의 문제도 해결할 수 있다.


Session 메소드

HttpSession 인터페이스 : 웹 애플리케이션에서 클라이언트와 서버 간의 세션을 관리하기 위해 사용된다. > 세션을 생성, 삭제, 속성 추가, 만료 시간을 설정하는 등의 다양한 메서드를 제공한다.

메소드 이름리턴 타입설명
Attribute(String name, Object value)void세션 속성명이 name인 속성에 속성 값으로 value를 할당한다
setAttriute(String name, Object value)void세션의 속성을 지정한다. > 세션의 속성 값은 객체 형태만 올 수 있다.
getAttribute(String name)java.lang.Object세션 속성명이 name인 속성의 값을 Object 타입으로 리턴한다. 해당되는 속성 명이 없을 경우 null 값을 리턴한다.
getAttributeNames()java.util.Enumeratioin세션 속성의 이름들을 Enumeration 객체 타입으로 리턴한다.
getCreationTime()long1970년 1월 1일 0시 0초를 기준으로 현재 세션이 생성된 시간까지 경과한 시간을 계산하여 1/1000초 값으로 리턴한다.
getId()java.lang.String세션에 할당된 고유 식별자를 String  타입으로 리턴한다.
getMaxInactiveInterval()int현재 생성된 세션을 유지하기 위해 설정된 세션 유지 시간을  int형으로 리턴한다. 초 단위로 반환
invalidate()void현재 생성된 세션을 무효화 시킨다.
removeAttribute(String name)void세션 속성명이 name인 속성을 제거한다.
getMaxInactiveInterval()int세션이 유효한 비활성 시간을 반환한다. 기본은 30분으로 설정되어있다.
setMaxInactiveInterval(int interval)void세션을 유지하기 위한 세션 유지 시간을 초 단위로 설정한다. 음수값으로 설저하면, 세션은 절대 만료되지 않는다.
  • 세션이 만료되어서 다른 페이지로 이동시키고 싶다면, 세션을 저장하고 유효시간을 설정한 후, 리다이렉션 시켜서, 해당 파일에서 setTimeout()을 이용해, getMaxInactiveInterval()함수를 사용해 해당 유효시간이 끝나면 location.href로 이동시키를 함수를 호출하도록 코드를 짠다.

    • 여기서 getMaxInactiveInterval()함수를 실행할 때 setTimeout()함수가 밀리초 단위로 받기 때문에 초단위를 밀리세컨즈로 변환하기 위해 1000을 곱해줘야 한다.

Session의 속성 사용

  1. 세션의 속성 설정은 session객체의 setAttribute() 메소드를 사용한다.

    • 주의할 점은 세션의 속성 값은 객체 형태만 올 수 있다.

    • session객체는 웹 브라우저와 매핑되므로 해당 웹 브라우저를 닫지 않는 한, 값은 같은 창에서 열려진 페이지와 모두 같은 session객체를 공유하게 된다.

      session객체의 setAttribute()메소드를 사용해서 세션의 속성을 지정하게 되면 계속 상태를 유지하는 기능을 사용할 수 있게 된다.

  2. 세션의 속성을 사용하려면 session객체의 getAttribute() 메소드를 사용한다.

  3. 세션의 모든 속성을 삭제할 때는 session객체의 invalidate()메소드를 사용한다.


1. 세션 설정 예제

로그인 페이지 - login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <form method="post" action="loginChk.jsp">
        <%
        String id = (String) session.getAttribute("id");
        if (id == null) {
        %>
        아이디 : <input type="text" name="id"> 비밀번호 : <input type="password" name="password">
        <input type="submit" value="로그인"> <a href="memberRegister.jsp">회원가입</a><br>
        <%
        } else {
        %>
        <%=id%>님 환영합니다.<br> <a href="logout.jsp">로그아웃</a> <a href="memberModify.jsp">회원정보수정</a><br>
        <%
        }
        %>
        <a href="loginTest.jsp">loginTest</a>
    </form>
</body>
</html>
  • 폼을 입력하고 로그인 버튼을 누르면 loginChk.jsp에서 세션에 id라는 속성과 값을 저장해 login.jsp로 다시 redirect를 보낸다.

  • session.getAttribute("id");세션에 저장된 사용자의 아이디를 가져오는 것으로, 폼에서 입력받은 데이터를 가져오는게 아니다. >> 사용자가 로그인한 상태인지 아닌지를 판단하는데 사용된다.

사용자가 입력한 값을 세션에 저장 - loginChk.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    session.setAttribute("id", request.getParameter("id"));
    response.sendRedirect("login.jsp");
%>
  • "request.getParameter("id") : 사용자가 로그인 폼에서 id 라는 이름의 필드에 입력한 값을 가져와 session.setAttribute() 에 위 아이디를 세션에 id라는 이름의 속성으로 저장하는 코드다.

    • 이렇게 하면 사용자의 아이디는 그 후의 요철에서도 계속 사용할 수 있다.

로그아웃 - 세션 무효화 logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    session.invalidate();    // 세션 무효화
    //session.removeAttribute("id");    // 특정 속성의 세션을 무효화
    response.sendRedirect("login.jsp");
%>
  • 로그아웃 후에 방금 로그인 했던 페이지로 가고싶어도 가지 못한다. 세션이 종료되었기 때문이다.

세션 확인 longinTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%
    String id = (String)session.getAttribute("id");
    if(id != null)
    {
%>
        <%=id %>님 안녕하십니까?
<%
    }
    else
    {    
%>
        로그인 되어있지 않습니다.
<%
    }
%>
</body>
</html>

2. 서블릿 세션 설정

  • 사용자에세 폼 입력 받기 -Login.java
package com.superman.ex;

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("/Login")
public class Login extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Login() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset='UTF-8'>");
        out.println("<meta name='description' content='HTML Study'>");
        out.println("<meta name='keywords' content='HTML,CSS,XML,JavaScript'>");
        out.println("<meta name='author' content='Bruce'>");
        out.println("<meta name='viewport' content='width=device-width, initial-scale=1.0'>");
        out.println("<title>Insert title here</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<form method='post' action='LoginChk'>");
        String id = (String) session.getAttribute("id");
        if (id == null) {
            out.println("아이디 : <input type='text' name='id'>");
            out.println("비밀번호 : <input type='password' name='password'>");
            out.println("<input type='submit' value='로그인'>");
            out.println("<a href='memberRegister.jsp'>회원가입</a>");
        } else {
            out.println(id + "님 환영합니다.<br>");
            out.println("<a href='Logout'>로그아웃</a> <a href='memberModify.jsp'>회원정보수정</a>");
        }
        out.println("</form>");
        out.println("</body>");
        out.println("</html>");
    }
}
  • 로그인 된 세션 저장 - LoginChk.java
package com.superman.ex;

import java.io.IOException;

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("/LoginChk")
public class LoginChk extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public LoginChk() {
        super();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();//기본 내장객체가 아니므로, 가져와야됌 out처럼
        session.setAttribute("id", request.getParameter("id"));
        response.sendRedirect("Login");
    }

}
  • 어노테이션을 이용해 서블릿간의 참조나, 서블릿과 jsp의 참조 진행 > @WebSevlet 을 이용해 괄호 안에 폼 action이름 적으면 됌 뒤 파일 확장명 빼고
  • 로그아웃 - 세션 종료 - Logout.java
package com.superman.ex;

import java.io.IOException;
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("/Logout")
public class Logout extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Logout() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.invalidate();
        // session.removeAttribute("id");
        response.sendRedirect("Login");
    }

}

3. 세션 유효시간

  • 사용자 로그인 폼 - SessionForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    String id = (String) session.getAttribute("id");
    if (id == null) {
    %>
    <form method="post" action="SessionFormOK.jsp">
        아이디 : <input type="text" name="id"><br> 비밀번호 : <input type="password" name="password"><br>
        <input type="submit" value="로그인">
        <%
        } else {
        %>
        <%=id%>님 환영합니다.<br>
        <%=session.getMaxInactiveInterval()%>
        <!-- 세션의 유효시간을 얻어오기 리턴된 단위는 초-->
        <%
        }
        %>
    </form>
</body>
</html>
  • 세션 유효시간 지정 - SessionFormOK.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    session.setMaxInactiveInterval(10);//10초뒤에 새로고침하면 세션 만료로 SessionForm.jsp로 돌아감
    // 세션 최대시간 설정 단위는 초 (서버 기본 설정은 30분)
    session.setAttribute("id", request.getParameter("id"));
    response.sendRedirect("SessionForm.jsp");
%>
  • 10초가 지난후 새로고침하면 세션이 종료되어 나가지게 된다. > 로그인 화면으로 다시 돌아감

4. 세션 유효시간 후 자동 이동

  • 로그인 화면 - SessionForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    String id = (String) session.getAttribute("id");
    if (id == null) {
    %>
    <form method="post" action="SessionFormOK.jsp">
        아이디 : <input type="text" name="id"><br> 비밀번호 : <input type="password" name="password"><br>
        <input type="submit" value="로그인">
        <%
        } else {
        %>
        <%=id%>님 환영합니다.<br>
        <%=session.getMaxInactiveInterval()%>
        <!-- 세션의 유효시간을 얻어오기 리턴된 단위는 초-->
        <%
        }
        %>
    </form>
</body>
</html>
  • 세션의 유효시간 설정 - SessionFormOK.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    session.setMaxInactiveInterval(5);//5초로 줌
    // 세션 최대시간 설정 단위는 초 (서버 기본 설정은 30분)
    session.setAttribute("id", request.getParameter("id"));
    response.sendRedirect("SessionTest.jsp");
%>
  • 유효시간이 종료되면 해당 페이지 자동으로 벗어나게끔 - SessionTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <h3>SessionTest 페이지 입니다.</h3>
    <script>
function expireSession()
{
  location.href = "SessionForm.jsp";
}
setTimeout(expireSession, <%=session.getMaxInactiveInterval() * 1000%>);//밀리세컨즈로 변환하기 위해  1000을 곱해줘야한다.
<%-- setTimeout(expireSession, <%= request.getSession().getMaxInactiveInterval() * 1000 %>); --%>
</script>
</body>
</html>

새로고침을 하지 않아도 해당 유효시간이 되면, 자동으로 화면을 벗어나 로그인 화면으로 돌아간다.

  1. expireSession() 함수 : 사용자를 SessionForm.jsp로 리디렉션한다.

  2. setTimeout(expireSession, <%= session.getMaxInactiveInterval() * 1000 %>); : 일정 시간이 지난 후 expireSession함수를 실행한다.

    • setTimeout() 은 밀리세컨즈 단위로 대기 시간을 받기 때문에, 초 단위로 반환되는 getMaxInactiveInterval()에 1000을 곱해줘서 밀리세컨즈가 되도록 변환해야한다.

    • getMaxInactiveInterval은 초 단위 값을 반환하므로 밀리초로 변환하기 위해 1000을 곱한다.


5. 세션이 없을 경우 접근하지 못하도록

  • 로그인 폼 화면 - login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="loginChk.jsp">
<%
    String id = (String)session.getAttribute("id");
    if(id == null)
    {
%>
아이디 : <input type="text" name="id">
비밀번호 : <input type="password" name="password">
<input type="submit" value="로그인">
<a href="memberRegister.jsp">회원가입</a><br>
<%
    }
    else{
%>
    <%=id %>님 환영합니다.<br>
    <a href="logout.jsp">로그아웃</a> <a href="memberModify.jsp">회원정보수정</a><br>
<%        
    }
%>
<a href="loginTest.jsp">loginTest</a>
</form>
</body>
</html>
  • 로그인 버튼 누르면 세션 저장
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    session.setAttribute("id", request.getParameter("id"));
    response.sendRedirect("login.jsp");
%>
  • 세션 존재하는지 안하는지 loingTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%
    String id = (String)session.getAttribute("id");
    if(id != null)
    {
%>
        <%=id %>님 안녕하십니까?
<%
    }
    else
    {    
%>
<script>
    alert("잘못된 접근입니다.");
    location.href="login.jsp";
</script>
<%
    }
%>
</body>
</html>
  • 로그인 해서 세션을 가지고 Test를 한다면 안녕하십니까? 가 보이고, 로그인을 하지 않고 Test를 했다면 잘못된 접근이라고 경고창이 뜬 후 로그인 페이지로 다시 이동할 것이다.

  • logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    session.invalidate();    // 세션 무효화
    //session.removeAttribute("id");    // 특정 속성의 세션을 무효화
    response.sendRedirect("login.jsp");
%>

Validation - 검증

Validaion(코드 검증) : 입력된 데이터가 예상된 형식과 일치하는지 확인하는 과정

validaiont1.html

<!DOCTYPE html>
<html>
<body>

<h1>JavaScript Can Validate Input</h1>

<p>Please input a number between 1 and 10:</p>

<input id="numb">

<button type="button" onclick="myFunction()">Submit</button>

<p id="demo"></p>

<script>
function myFunction() {
    var x, text;

    // Get the value of the input field with id="numb"
    x = document.getElementById("numb").value;

    // If x is Not a Number or less than one or greater than 10
    if (isNaN(x) || x < 1 || x > 10) {
        text = "Input not valid";
    } else {
        text = "Input OK";
    }
    document.getElementById("demo").innerHTML = text;
}
</script>

</body>
</html>

validation2.htm

<!DOCTYPE html>
<html>
<head>
<script>
function validateForm() {
    var x = document.forms["myForm"]["fname"].value;
    if (x == "") {
        alert("Name must be filled out");
        return false;
    }
}
</script>
</head>
<body>

<form name="myForm" action="hello.htm"
onsubmit="return validateForm()" method="post">
Name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>

</body>
</html>

form 태그 내에서 name을 이용해 이름을 정의하는 이유는 javascript 에서 폼을 잠조하기 위함이다.

onsubmit= 속성은 폼이 제출될 떄 실행할 javascript 함수를 지정한다.

document.forms : 웹 페이지에 있는 모든 form 태그를 참조하는 js객체의 컬렉션이다.

document.forms["myForms"] 라고 한다면, "myForms"의 이름을 가진 폼을 참조하는 것이다.

  • var x = document.forms["myForm"]["fname"].value;는 “myForm” 폼의 “fname” 필드의 값을 가져와 x 변수에 저장한다.

  • x의 값이 비었다면, 즉 사용자가 아무것도 입력하지 않았다면, 경고 메시지를 표시하고 false를 반환한다. > 이 반환값에 따라 폼을 제출시킬지 중단시킬지 결정한다. >> false는 폼 제출을 중단시킨다.

hello.htm

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello
</body>
</html>

Validation 문제

  1. 숫자를 1 부터 10사이의 값을 입력받을 수 있도록 input을 만들자. 입력필수. (유효성 검사를 html5로 한다.)
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>

<body>
    <form method="post" action="hello.htm">
        <input type="number" min="1" max="10" step="1" required>
        <input type="submit" value="전송">
    </form>
</body>

</html>
  • html에서 input태그의 type 속성을 number로 설정하면, 사용자는 숫자만 입력할 수 있게 된다.

    • min, max, step 을 설정해 최소 1에서 최대 10까지의 값을 입력할 수 있고, 사용자가 입력할 수 있는 숫자의 간격을 1로 지정했기에 1씩 증가하는 정수만 입력할 수 있다.

  1. 1번 문제의 input type="text"로 하고 유효성 검사를 javascript로 한다. 입력필수.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

</head>
<body>
<form name="myForm" method="post" action="hello.htm" onsubmit="return validation()">
    <input type="text" name="number">
    <input type="submit" value="전송">
</form>
<script>
    function validation()
    {
        var x = document.forms["myForm"]["number"].value;

        if (isNaN(x) || x < 1 || x > 10 || x=="") {
           alert("Input not valid");
           return false;
        } else {
            alert("Input OK");
            return true;
        }
    }
</script>
</body>
</html>

js 를 이용해서 alert형태로 유효성 체크

  • hello.html > 위에서 유효한 값을 입력하면 이 파일로 이동해 Hello를 보여준다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello
</body>
</html>

  1. 비밀번호와 비밀번호확인을 만들고 두 값이 다르면 submit을 하지 않도록 javascript로 유효성 검사를 한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form name="myForm" method="post" action="hello.htm" onsubmit="return validation()">
    비밀번호 : <input type="password" name="password"><br>
    비밀번호확인 : <input type="password" name="passwordChk"><br>
    <input type="submit" value="전송">
</form>
<script>
    function validation()
    {
        var password = document.forms["myForm"]["password"].value;
        var passwordChk = document.forms["myForm"]["passwordChk"].value;

        if(password ==="" || passwordChk === ""){
            alert("비밀번호를 입력해 주세요.");
            return false;            
        }
        if (password != passwordChk) {
           alert("비밀번호가 일치하지 않습니다.");
           return false;
        } 
    }
</script>
</body>
</html>
  • 동일한 패스워드를 입력하지 않으면, alert를 이용해 출력 > 동일하다면 hello.html로 이동

document.forms[폼 이름][해당 입력 폼의 name이름]


회원가입 - 로그인 기능 구현(JDBC, Session이용)

main화면 - main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로그인 및 회원가입</title>
<script>
function confirmDelete() {
    /*탈퇴를 눌렀을 때 경고 메시지를 표시 확인을 누르면 true, 취소를 누르면 false를 반환*/
    return confirm("정말 탈퇴하시겠습니까?");
}
</script>
</head>
<body>
    <form action="${pageContext.request.contextPath}/LoginOk" method="post">
        <%
        String id = (String) session.getAttribute("id");
        if (id == null) {
        %>
        아이디 : <input type="text" name="id"><br> 비밀번호 : <input type="password" name="password"><br>
        <input type="submit" value="로그인"> <a href="memberRegister.jsp">회원가입</a><br>
        <%
        } else {
        %>
        <%=id%>님 환영합니다.<br> <a href="${pageContext.request.contextPath}/Logout">로그아웃</a>   <a
            href="memberModify.jsp">개인정보수정</a><br> <a href="loginTest.jsp">loginTest</a>

             <a href="${pageContext.request.contextPath}/Break" onclick="return confirmDelete();">탈퇴</a>
        <%
        }
        %>
    </form>
</body>
</html>
    </form>
</body>
</html>
  • 해당 브라우저의 세션 아이디가 null이라면 로그인 폼과, 회원가입이 보이게하고, 세션 아이디 값을 가지고 있다면, 로그아웃, 개인정보 수정, 탈퇴가 보이게 한다.

회원가입 폼 - memberRegister.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원가입</title>
</head>
<body>
    <h1>회원 가입</h1>
    <form action="${pageContext.request.contextPath}/MemberRegisterOK" method="post" name="userForm"
        onsubmit="return validationPw()">
        <table>
            <tr>
                <td>이름</td>
                <td><input type="text" name="name" required></td>
            </tr>
            <tr>
                <td>아이디</td>
                <td><input type="text" name="id" required></td>
            </tr>
            <tr>
                <td>비밀번호</td>
                <td><input type="password" name="password" required></td>
            </tr>
            <tr>
                <td>비밀번호 확인</td>
                <td><input type="password" name="passwordCheck" required></td>
            </tr>
            <tr>
                <td>성별</td>
                <td><input type="radio" name="sex" value="남자"><input type="radio" name="sex"
                    value="여자"></td>
            </tr>
            <tr>
                <td>이메일</td>
                <td><input type="email" name="email"></td>
            </tr>
            <tr>
                <td>취미</td>
                <td><input type="checkbox" name="hobby" value="수영">수영 <input type="checkbox"
                    name="hobby" value="야구">야구 <input type="checkbox" name="hobby" value="영화감상">영화감상
                    <input type="checkbox" name="hobby" value="음악감상">음악감상</td>
            </tr>
            <tr>
                <td>핸드폰</td>
                <td><select name="numStart">
                        <option>010</option>//value 속성을 사용하지 않으면 브라우저는 해당 텍스트 내용을 value로 사용한다. 
                        <option>031</option>
                        <option>011</option>
                        <option>016</option>
                </select> <input type="text" name="phoneNum"></td>
            </tr>
            <tr>
                <td><input type="submit" value="회원가입"> <input type="reset" value="초기화"></td>
            </tr>
        </table>
    </form>
    <script>
    function validationPw() {
        var pw = document.forms["userForm"]["password"].value;
        var pwCheck = document.forms["userForm"]["passwordCheck"].value;

        if(pw != pwCheck){
            alert("비밀번호가 일치하지 않습니다.");
            return false;
        }
    }
    </script>
</body>
</html>
  • 회원가입 폼에 name을 줘서 script에서 폼 name이 'userForm'인 폼에서 사용자가 입력한 password의 값을 가지고오고, 똑같이 사용자가 입력한 passwordCheck값을 가져와서 비교해, 일치한지 아닌지 유효성 검사를 진행한다.

  • submit으로 회원가입 버튼을 누르게되면 post방식으로 서블릿으로 전송하게 했는데 action="${pageContext.request.contextPath}/MemberRegisterOK 이는 jsp에서 서블릿으로 값을 보내고 서로 참조할 수 있게 한것이다. <> 서블릿에서는 어노테이션으로

    • pageContext : jsp에서 제공하는 내장 객체 중 하나로, 현재 페이지와 관련된 여러 정보를 담고 있다.

    • request : 현재 요청 객체를 나타낸다.

    • contextPath : 현재 웹 애플리케이션의 컨텍스트 경로를 반환한다.

    그러므로 위 코드에서 contextPath 가 의미하는것은 HelloJSP 일것이다. 최종 URL = HelloJSP/MemberRegisterOK 가 될것이다.


회원가입 폼 db에 넣기 (서블릿으로 구현) - MemberRegister.java

package com.batman.www;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

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("/MemberRegisterOK")
public class MemberRegisterOK extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public MemberRegisterOK() {
        super();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");// 한글로 읽어들이기
        response.setContentType("text/html; charset=UTF-8");// 한글로 응답 보내기

        PrintWriter out = response.getWriter();
        String name = request.getParameter("name");
        String id = request.getParameter("id");
        String pw = request.getParameter("password");
        String sex = request.getParameter("sex");
        String email = request.getParameter("email");

        String[] hobbyValues = request.getParameterValues("hobby");
        String hobbies = String.join(" ", hobbyValues);

        String phoneNum = request.getParameter("numStart");
        phoneNum += request.getParameter("phoneNum");

        // 입력받은 폼 데이터베이스 넣기
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/project?serverTimeZone=UTC";
        String sqlId = "root";
        String sqlPw = "1234";
        String sql = "insert into member (name, id, password, sex, email, hobby, phoneNum) values (?, ?, ?, ?, ?, ?, ?)";
        int result = 0;

        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            out.write("드라이버 로드 실패");
            e.printStackTrace();
        }
        try (Connection conn = DriverManager.getConnection(url, sqlId, sqlPw);
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            pstmt.setString(2, id);
            pstmt.setString(3, pw);
            pstmt.setString(4, sex);
            pstmt.setString(5, email);
            pstmt.setString(6, hobbies);
            pstmt.setString(7, phoneNum);
            result = pstmt.executeUpdate();
            if (result > 0) {
                response.sendRedirect("PracticeFile/Example1/SignInMembership/main.jsp");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}
  • request.setCharacterEncoding("utf-8"); : 클라이언트에서 서버 보낸 정보를 한글로 읽어들이기

  • response.setContentType("text/html; charset=UTF-8"); : 서버가 클라이언트에게 응답을 보낼 때, 응답 데이터의 인코딩을 설정해, 클라이언트가 응답 데이터를 올바르게 해석할 수 있게 한다.

  • @WebServlet("/MemberRegisterOK")를 이용해 main에서 form action으로 보낸 것을 이 어노테이션을 이용해 받는다.

  • 데이터베이스에 데이터 삽입을 성공했다면, reponse.sendRedirect()를 이용해 다시 클라이언트 화면으로 돌아간다.


로그인 후 해당 계정이 존재 하면 세션 아이디 생성(서블릿) - LoginOK.java

package com.batman.www;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

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("/LoginOk")
public class LoginOK extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public LoginOK() {
        super();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");// 한글로 읽어들이기
        response.setContentType("text/html; charset=UTF-8");// 한글로 응답 보내기

        PrintWriter out = response.getWriter();
        String id = request.getParameter("id");
        String pw = request.getParameter("password");

        if (id.isEmpty() || pw.isEmpty()) {
            out.print("<script>alert('ID 또는 비밀번호를 정확히 입력해주세요.'); history.back();</script>");
            return;
        }

        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/project?serverTimeZone-UTC";
        String sqlId = "root";
        String sqlPw = "1234";
        String sql = "SELECT * FROM member WHERE id = ?";
        ResultSet rs = null;

        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            out.write("드라이버 로드 실패");
            e.printStackTrace();
        }
        try (Connection conn = DriverManager.getConnection(url, sqlId, sqlPw);
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, id);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                String dbPw = rs.getString("password");
                if (dbPw.equals(pw)) {
                    // 로그인 성공
                    HttpSession session = request.getSession();
                    session.setAttribute("id", id);
                    response.sendRedirect("PracticeFile/Example1/SignInMembership/main.jsp");
                } else {
                    // 비밀번호가 일치하지 않는 경우
                    out.print(
                            "<script>alert('비밀번호가 일치하지 않습니다.'); window.location.href = 'PracticeFile/Example1/SignInMembership/main.jsp';</script>");
                }
            } else {
                // 아이디가 존재하지 않는 경우
                out.print(
                        "<script>alert('해당되는 아이디가 없습니다.'); window.location.href = 'PracticeFile/Example1/SignInMembership/main.jsp';</script>");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}
  • main.jsp에서 사용자가 입력한 데이터를 데이터베이스의 primaryKey와 비교해 존재하는지 확인하고, getString()을 이용해 해당 아이디가 데이터베이스에 있는 정보와 일치하는지 확인 후 일치한다면 해당 session을 가져와 setAttribute()를 이용해 id라는 속성에 사용자가 입력한 id를 값으로 넣어준다.

    • 아이디와 비밀번호를 데이터베이스와 비교해서 아이디, 비밀번호가 맞는지 틀린지 alert로 알려준다.
  • 그렇게 정보가 일치하면 생성된 세션을 들고 main.jsp로 돌아간다.

    • main.jsp에서 getAttribute("id")를 통해 만들어준 id속성에 값이 있는지 확인해 사용자에게 보일 내용을 if문과 스크립틀릿으로 구분해 만들어준다.

개인정보수정 - memberModify.jsp

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/project?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "1234";

String name = null, id = null, sex = null, email = null, hobby = null, mobilePhone = null;
try {
    Class.forName(driver);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

try (Connection conn = DriverManager.getConnection(url, user, password);
        PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM MEMBER WHERE ID=?")) {

    pstmt.setString(1, (String) session.getAttribute("id"));
    try (ResultSet rs = pstmt.executeQuery()) {
        if (rs.next()) {
    name = rs.getString("name");
    id = rs.getString("id");
    sex = rs.getString("sex");
    email = rs.getString("email");
    hobby = rs.getString("hobby");
    mobilePhone = rs.getString("phoneNum");
        }
    }
} catch (SQLException e) {
    e.printStackTrace();
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <h2>회원정보수정</h2>
    <form name="member" method="post" action="${pageContext.request.contextPath}/MemberModifyOK"
        onsubmit="return validateForm()">
        <table>
            <tr>
                <td>이름</td>
                <td><input type="text" name="name" value="<%=name%>" disabled></td>
            </tr>
            <tr>
                <td>아이디</td>
                <td><input type="text" name="id" value="<%=id%>" readonly></td>
            </tr>
            <tr>
                <td>비밀번호</td>
                <td><input type="password" name="password" required></td>
            </tr>
            <tr>
                <td>비밀번호확인</td>
                <td><input type="password" name="passwordChk" required></td>
            </tr>
            <tr>
                <td>성별</td>
                <td><input type="radio" name="sex" value="남자" <%if (sex.equals("남")) {%> checked <%}%>><input type="radio" name="sex" value="여자" <%if (sex.equals("여")) {%> checked <%}%>></td>
            </tr>
            <tr>
                <td>이메일</td>
                <td><input type="email" name="email" value="<%=email%>" required></td>
            </tr>
            <tr>
                <td>취미</td>
                <td><input type="checkbox" name="hobby" value="수영" <%if (hobby.indexOf("수영") != -1) {%>
                    checked <%}%>>수영 <input type="checkbox" name="hobby" value="야구"
                    <%if (hobby.indexOf("야구") != -1) {%> checked <%}%>>야구 <input type="checkbox" name="hobby"
                    value="영화감상" <%if (hobby.indexOf("영화감상") != -1) {%> checked <%}%>>영화감상 <input
                    type="checkbox" name="hobby" value="음악감상" <%if (hobby.indexOf("음악감상") != -1) {%> checked <%}%>>음악감상
                </td>
            </tr>
            <tr>
                <td>핸드폰</td>
                <td><select name="mobilePhone1">
                        <option value="010" <%if (mobilePhone.substring(0, 3).equals("010")) {%> selected <%}%>>010</option>
                        <option value="011" <%if (mobilePhone.substring(0, 3).equals("011")) {%> selected <%}%>>011</option>
                        <option value="016" <%if (mobilePhone.substring(0, 3).equals("016")) {%> selected <%}%>>016</option>
                </select> <input type="text" name="mobilePhone2" value="<%=mobilePhone.substring(3)%>" required>
                </td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="정보수정"> <input type="reset" value="초기화"></td>
            </tr>
        </table>
    </form>
    <script>
        function validateForm() {
            var password = document.forms["member"]["password"].value;
            var passwordChk = document.forms["member"]["passwordChk"].value;
            if (password != passwordChk) {
                alert("비밀번호와 비밀번호확인이 서로 다릅니다.");
                return false;
            }
        }
    </script>
</body>
</html>
  • 현재 유지되고 있는 세션의 아이디를 받아와 데이터베이스의 저장된 아이디에 해당하는 데이터들을 불러와 사용자가 회원가입때 작성했던 개인정보를 수정할 수 있게 해준다.

  • <%if (hobby.indexOf("수영") != -1) {%> checked <%}%>: 만약 "수영" 문자열이 hobby에 포함되어 있다면, checkbox가 선택되도록한다.

    • indexOf() : 문자열에서 특정 문자열이 처음 발견되는 위치의 인덱스를 반환한다. 만약 찾는 문자열이 없으면 -1을 반환한다.
  • mobilePhone.substring(0, 3): mobilePhone 문자열의 첫 번째 문자부터 세 번째 문자까지의 부분 문자열을 반환해, substring() 을 사용해 각 옵션의 값과 비교한다.

    • 옵션의 값과 현재 전화번호의 앞 세자리가 동일하다면, 해당 옵션이 선택되도록 selected속성을 추가했다.

이렇게 위처럼 함으로써, 사용자가 이전에 선택한 옵션을 회원 정보 수정 폼에서 기본값으로 표시할 수 있다.


수정한 회원정보 데이터를 데이터베이스에 업데이트(서블릿) - MemberModifyOK.java

package com.batman.www;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
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("/MemberModifyOK")
public class MemberModifyOK extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public MemberModifyOK() {
        super();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id = null, password = null, sex = null, email = null, hobby = "", mobilePhone = null;
        String[] tmp = null;
        String driver = "com.mysql.cj.jdbc.Driver";
        String mysqlUrl = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
        String mysqlUser = "root";
        String mysqlPassword = "1234";
        int result = 0;
        request.setCharacterEncoding("UTF-8");

        id = request.getParameter("id");
        password = request.getParameter("password");
        sex = request.getParameter("sex");
        email = request.getParameter("email");
        tmp = request.getParameterValues("hobby");
        for (int i = 0; i < tmp.length; i++)
            hobby += tmp[i] + " ";
        mobilePhone = request.getParameter("mobilePhone1") + request.getParameter("mobilePhone2");
        System.out.println(id + " " + password + " " + sex + " " + email + " " + mobilePhone + " " + hobby);

        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try (Connection conn = DriverManager.getConnection(mysqlUrl, mysqlUser, mysqlPassword);
                PreparedStatement pstmt = conn.prepareStatement(
                        "UPDATE MEMBER SET PASSWORD=?, SEX=?, EMAIL=?, HOBBY=?, phoneNum=? WHERE id=?")) {
            pstmt.setString(1, password);
            pstmt.setString(2, sex);
            pstmt.setString(3, email);
            pstmt.setString(4, hobby);
            pstmt.setString(5, mobilePhone);
            pstmt.setString(6, id);
            result = pstmt.executeUpdate();

            if (result > 0)
                response.sendRedirect("PracticeFile/Example1/SignInMembership/main.jsp");
            else {
                request.setAttribute("errMSG", "데이터베이스 수정실패");
                request.setAttribute("url", "main.jsp");
                RequestDispatcher dispatcher = request
                        .getRequestDispatcher("PracticeFile/Example1/SignInMembership/error.jsp");
                dispatcher.forward(request, response);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • request.setAttribute() 를 사용해 특정 이름과 값을 가진 속성을 요청 객체에 저장한다. 이 속성은 같은 요청 내에서만 유효하다.

    • errMsg라는 이르의 속성에 '데이터베이스 수정 실패 ' 라는 값을 저장한다. > request.getAttribute("errMsg")를 사용해 위 메시지를 가져와 화면에 출력할 수 있다.

오류 페이지 - error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
<script>
    alert('<%=request.getAttribute("errMSG")%>');
    location.href = '<%=request.getAttribute("url")%>';
</script>
</head>
<body>
</body>
</html>

회원 탈퇴 및 세션 삭제 (servlet) - Break.java

package com.batman.www;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

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("/Break")
public class Break extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Break() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");// 한글로 읽어들이기
        response.setContentType("text/html; charset=UTF-8"); // 한글로 응답 보내기

        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/project?serverTimeZone=UTC";
        String sqlId = "root";
        String sqlPw = "1234";
        String sql = "delete from member where id = ?";
        String userId = (String) session.getAttribute("id");
        int result = 0;

        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            System.out.println("드라이버 로드 실패");
        }
        try (Connection conn = DriverManager.getConnection(url, sqlId, sqlPw);
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, userId);
//            System.out.println(userId + "아이디 가져오기 성공"); 디버깅 용도

            result = pstmt.executeUpdate();
            if (result > 0 && userId != null) {
                session.invalidate();// 해당 아이디 세션 무효화
                out.print("<script>alert('회원 정보를 성공적으로 삭제했습니다.');</script>");
//                response.sendRedirect("PracticeFile/Example1/SignInMembership/main.jsp");
// 위와 같은 방법으로 리다이렉트하면, 클라이언트가 리다이렉트 되기 때문에 스크립트는 클라이언트에게 전달되지 않는다. 그러므로, 리다이렉트를 자바스크립트 코드로 처리하는 것이 좋다.
                out.print("<script>location.href='PracticeFile/Example1/SignInMembership/main.jsp';</script>");
                out.flush(); // 버퍼 강제 비우기
            } else {
                out.print("<script>alert('회원 정보 삭제를 실패했습니다.');history.back();</script>");
                out.flush(); // 버퍼 강제 비우기
                System.out.print("회원 정보 삭제 안됐음");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}
  • doGet()메소드를 이용해 해당 폼의 세션 아이디로, 데이터베이스에 접근해 데이터를 삭제하고, 삭제 성공했다면 해당 아이디 세션을 무효화 시키고, script를 이용해 삭제했다는 스크립트를 띄운다.

    • 처음에 getParameter("id")를 이용했는데 해당 값이 null을 반환해 계속 오류가 났었다. 현재 폼에 데이터를 기입하고 submit하는것이 아니기 때문에 처음에 저장했던 세션의 id속성의 값을 가지고와서, 해당 아이디로 데이터베이스의 값을 수정한다.    

    • session.getAttribute()를 이용해 id를 불러온다.

  • 여기서 주의할 점은 해당 세션을 삭제하고, 다시 로그인 페이지로 가야하는데 이를 위해 내가 response.sendRedirect()를 이용해 변경을 해줬더니 스크립트가 기능하지 않는것이다.

    • 그 이유는 response.sendRedirect()메소드는 클라이언트가 리다이렉트 되기 때문에 out.print로 출력되는 자바스크립트가 클라이언트에게 전달되지 않기 때문이다.

로그아웃 세션


다시 외우는 이클립스 단축키

  • 주석 처리

    • Ctrl + Shift + / : 블록을 주석으로 처리 (/* */)
    • Ctrl + Shift + \ : 블록 주석을 해제
    • Ctrl + / : 한 줄 또는 블록 주석 처리/해제 (//)
  • 검색

    • Ctrl + F : 키워드 검색 (해당 소스에서만)
    • Ctrl + H : 키워드 검색 (프로젝트 전체에서)
    • Ctrl + Shift + R : 전체 리소스에서 파일 찾기
    • Ctrl + Shift + T : Jar 포함 클래스 찾기
    • Ctrl + Alt + H : 특정 클래스 호출 위치 찾기
    • Ctrl + K : 찾을 문자열을 블럭으로 지정하고 검색
    • Ctrl + Shift + K : 밑에서 문자열 검색 위치 이동
    • Ctrl + 특정 클래스 마우스 왼쪽 클릭 (F3) : 특정 클래스로 이동
  • 소스 편집

    • Ctrl + Z : 소스 수정 취소
    • Ctrl + Y : 소스 수정 취소의 취소
    • Ctrl + S : 소스코드 저장 (현재 파일만)
    • Ctrl + Shift + S : 모든 소스코드 저장
    • Ctrl + Shift + X : 대문자로 변환
    • Ctrl + Shift + Y : 소문자로 변환
    • Ctrl + Space : 입력 중에 완성 기능 호출
    • Ctrl + D : 한 줄 삭제
    • Ctrl + Shift + F : 소스 정렬
    • Ctrl + I : 들여쓰기 자동 수정
    • Ctrl + Shift + Space : 메소드 파라미터 목록
    • Ctrl + Shift + O : 자동 import, 안쓰는 import 삭제
    • Ctrl + Alt + Up (Down) : 한 줄 (블럭) 복사
    • Ctrl + , 또는 Ctrl + . : 다음 annotation (에러, 워닝, 북마크) 점프
    • Ctrl + T : 상속 계층 팝업 창
    • Ctrl + F6 : 창 전환
    • Alt + 방향키 (↑,↓) : 위 (아래) 줄과 바꾸기
    • Alt + Shift + R : 같은 변수명 네이밍 전체 변경
    • F3 : 선언된 변수나 메소드 정의로 이동
    • F2 : 파일 이름 변경
    • F11 : 디버깅 시작
    • F8 : 디버깅 계속
    • F6 : 한 줄씩 디버깅
    • F5 : 한 줄씩 디버깅할 때 함수인 경우 함수 내부까지 디버깅
    • F12 : Editor 창으로 이동

0개의 댓글