본문 바로가기

Program/JSP

Cookie, Connection Pooling, EE → SE 재사용

22.08.10-Cookie, Connection Pooling, EE → SE 재사용

Cookie


클라이언트 측에 남겨져있는 정보, 서버측에는 세션으로 저장되어있다.

쿠키는 파일로 저장되어 있지만 세션을 메모리에 올라와서 사용한다.

  1. 클라이언트에서 서버에 처음 접속할때 세션에 클라이언트의 정보를 메모리에 저장한다.
  2. 이 번호가 클라이언트에 전달되고 이정보가 쿠키로 파일로 저장된다
  3. 쿠키가 파일로 저장되지 않으면 브라우저를 닫게되면 정보는 사라진다.
  4. 클라이언트가 다시 접속하게 되면 서버의 세션과 클라이언트의 쿠키와 비교하면서 확인한다.
  • 코드

      <%@page import="java.sql.ResultSet"%>
      <%@page import="java.sql.PreparedStatement"%>
      <%@page import="java.sql.Connection"%>
      <%@page import="java.sql.DriverManager"%>
      <%@ page contentType="text/html;charset=UTF-8"%>
      <%!
          String url="jdbc:oracle:thin:@localhost:1521:XE"; 
          String user="java";
          String password="1234";%>
      <%
          String user_id = request.getParameter("user_id");
          String pass = request.getParameter("pass");
          Class.forName("oracle.jdbc.driver.OracleDriver");
          Connection con = null;
          PreparedStatement pstmt = null;
          ResultSet rs = null;
    
          con = DriverManager.getConnection(url,user,password);
          String sql = "SELECT * FROM member WHERE user_id=? AND pass=?";
          pstmt = con.prepareStatement(sql);
          pstmt.setString(1, user_id);
          pstmt.setString(2, pass);
    
          rs=pstmt.executeQuery();
    
          /*
          클라이언트가 전송한 아이디,패스워드를 DB에서 조회하여 만일 가입된 회원이라면 
              서버가 추후 다시 접속해도 나를 기억
    
              JSP의 내장객체중 session이라는 객체가 바로 세션을 구성
              최초의 접속자가 들어오면 세션객체를 생성한 후 고유 ID를 할당하고, 이 ID를 응답정보에 심어놓는다.(쿠키)
              다음 클라이언트 방문시 ID가 존재한다면 아는체 하고 없다면 새로운 세션을 만들고 ID발급
    
              */
              String sid = session.getId();
              out.print("당신이 할당받은 세션 아이디 :"+sid);
    
          if(rs.next()){//커서를 내렸을때 다음 레코드가 있다면
              //세션 인트턴스에는 개발자가 넣고 싶은 데이터를 넣을 수 있는데 map구조 되어있다.
              /*
                  java collection framework : java의 자료구조 java.util 패키지에 있음
                  1. list : 순서가 있는 데이터의 모임
                  2. set : 순서가 없는 데이터의 모임 
                  3. map : key-value 형태로 되어있는 데이터 
    
              */ 
              session.setAttribute("user_id", rs.getString("user_id"));
              session.setAttribute("pass", rs.getString("pass"));
              session.setAttribute("regdate",rs.getString("regdate"));
              out.print("당신의 정보 <br>");
              out.print("아이디 :" + session.getAttribute("user_id")+"<br>");
              out.print("비번 :" + session.getAttribute("pass")+"<br>");
              out.print("가입일 :" + session.getAttribute("regdate")+"<br>");
          }else{
              out.print("<script>");
              out.print("alert('회원정보가 올바르지 않습니다.');");
              out.print("history.back();");
              out.print("</script>");
          }
    
    
//자원해제
if(rs!=null)rs.close();    
if(pstmt!=null)rs.close();    
if(con!=null)rs.close();    

%>
```

Connection Pooling


Connection Pooling 기법이란 : 접속자가 없더라도, Tomcat서버의 메모리에 미리 다수의 Connection 객체를 확보해 놓고 메모리 pool 모아놓는 커넥션 관리 기법

사용 모습 : 클라이언트 접속 → pool에 모여있는 Connectio중에 하나를 추출하여 요청을 처리한 Connction을 사용함, 이때 쿼리문 수행 모두 종료되었을때도 Connection을 Close()하지 않고 다시 pool로 돌려보낸다.

장점 : 다수에 클라이언트를 처리할때 부하가 걸리지 않음

구현 방법 :

  1. 개발자가 직접 알고리즘을 적용하여 개발
  2. 나보다 실력이 뛰어난 다른 개발자의 코드 사용,공식적인 인증 받지 않음
  3. 공식적인 라이브러리를 이용(apache.org 의 Connection pool제공 ⇒ DBCP)

좋은 소식 ) Tocat 서버는 DBCP를 이용한 커넥션 풀을 지원..

선행학습 : JNDI(Java Naming Directory Interface) : 자원을 이름으로 지정하고 사용⇒ Connection Pool을 이름으로 접근

Tomcat JNDI

Tomcat JNDI

                <Context docBase="web0810" path="/" reloadable="true"
                    source="org.eclipse.jst.jee.server:web0810">
                    <!-- 이 웹 어플리케이션이 사용하게 될 Connection pool을 등록 이와 같이 java코드가 아닌, 외부의 xml과 
                        같은 자원에 정보를 이용하는 방법을 javaSE에서는 JNDI로 지원 -->
                    <Resource name="jdbc/myoracle" auth="Container"
                        type="javax.sql.DataSource"
                        driverClassName="oracle.jdbc.driver.OracleDriver"
                        url="jdbc:oracle:thin:@localhost:1521:XE" username="java"
                        password="1234" maxActive="20" maxIdle="10" maxWait="3000" />
                </Context>
<ResourceLink type="javax.sql.DataSource"
                      name="jdbc/myoracle"
                      global="jdbc/myoracle" />

JSP_SL/web0810 at master · dltmdcks98/JSP_SL

EE→ SE로 ⇒ 재사용


$1.class → FormWin의 내부익명클래스라는 것

$1.class → FormWin의 내부익명클래스라는 것

package com.aca.web0810.gui;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.aca.web0810.model.BoardManager;

/*웹 기반이 아닌 독립 실행형 기반인 GUI모드로 등록폼을 정의*/
public class FormWin extends JFrame {
    JButton bt;// has a 관계 : 객체가 다른 객체를 멤버로 보유한 관계
    JTextField t_title, t_writer;
    JTextArea area;
    BoardManager boardManager;

    public FormWin() {

        t_title = new JTextField(17);
        t_writer = new JTextField(17);
        area = new JTextArea(10,23);//row,col
        area.setBackground(Color.yellow);
        bt = new JButton("등록");
        boardManager = new BoardManager();
        //레이아웃 스타일 명시
        this.setLayout(new FlowLayout());//일렬로 배치되는 레이아웃
        add(t_title);
        add(t_writer);
        add(area);
        add(bt);

        setSize(300,400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);//윈도우창을 닫을때 프로그램도 같이 종료 

        //버튼과 리스너 연결
        //내부 익명 클래스 ->java파일을 더 생성하지말고 일회성인 코드들은 내부에 넣는거
        bt.addActionListener(new ActionListener() {
            //클래스 안에 클래스 -> 내부 익명클래스 => java를 개발자가 파일로 만들었다는 것은 재사용성을 염두하고 정의하는 것 
            //굳이 .java까지 만들 필요없는 1회성 코드들이 있을때 (주로 이벤트 연결) 이름없는 내부 클래스로 간단히 처리할 수 있다. 
            //주의)
            public void actionPerformed(ActionEvent e) {
                regist();
            }
        });
    }
    //중립적으로 정의된  BoardManager를 이용해서 오라클에 글 넣기
    public void regist() {
        String title = t_title.getText();
        String writer = t_writer.getText();
        String content = area.getText();
        boardManager.insert(title,writer,content);
    }
    public static void main(String[] args) {
        new FormWin();

    }
}
package com.aca.web0810.model;

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

//이 클래스는 웹 기반 뿐만 아니라 스탠다드 기반에서도 공용으로 쓸 수 있는 수준으로 정의해놓자
//재사용을 위해서 

public class BoardManager {
    String url="jdbc:oracle:thin:@localhost:1521:XE";
    String user="java";
    String password="1234";
    //레코드 넣기 
    public void insert(String title, String writer, String content) {

        Connection con = null;
        PreparedStatement pstmt=null;

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            con=DriverManager.getConnection(url,user,password);
            String sql = "INSERT INTO board(board_id,title,writer,content)VALUES(seq_board.nextval,?,?,?)";
            pstmt=con.prepareStatement(sql);

            pstmt.setString(1, title);
            pstmt.setString(2, writer);
            pstmt.setString(3, content);
            int result = pstmt.executeUpdate();

        }catch (ClassNotFoundException e) {
            // TODO: handle exception
        }catch (SQLException e) {
            // TODO: handle exception
        }finally {
            if(pstmt!=null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(con!=null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }



    }
}
package com.aca.web0810.notice;

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.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
//중의적인 클래스를 이용한 웹용  

import com.aca.web0810.model.BoardManager;
public class WriteController extends HttpServlet{
    BoardManager boardManager;

    //이 서블릿 클래스가 최초의 접속자에 의해 인스턴스화 될떄 딱 한번 호출되는 생명주기 메서드
    @Override
    public void init() throws ServletException {
        boardManager = new BoardManager();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        request.setCharacterEncoding("utf-8");
        String title         = request.getParameter("title");
        String writer     = request.getParameter("writer");
        String content = request.getParameter("content");

        //넘어온 파라미터를 이용해서 DB에 insert하되, 직접이 아닌 중립적 객체를 이용할 것임
        int result = boardManager.insert(title, writer, content);
        out.print("<script>");
         if(result==0) {
             out.print("alret('등록실패');");
             out.print("history.back();");
         }else {
             out.print("alert('등록성공');");
             out.print("location.href='/notice/list.jsp';");//밑에 문장들도 실행됨
         }
         out.print("</script>");

    }
}