67_[jsp servlet]데이터베이스 커넥션 풀 dbcp
데이터베이스 커넥션 풀 DBCP
🌹 커넥션
- 데이터베이스 및 DBMS를 사용하기 위한 접속 요청을 통한 연결 상태(꼭 선행되어야 함!)
DBCP; Database Connection Pool
- 웹 페이지에 대한 클라이언트 요청이 많은 경우, 서버의 부하 증가로 인한 서버 다운 현상을 해결해주기 위한 방법
- DB의 효율성 및 속도 향상에 도움
-
DBCP 매니저가 어느 정도의 연결을 확보해두고 있다가, 클라이언트 요청이 들어오면 연결해주고, 작업이 다 끝나면 클라이언트의 연결을 다시 DBCP 매니저에게 반환하도록 함
(위의 그림이 그 과정을 잘 보여주고 있음)
🌻 그러면, 만약, 커넥션 풀이 가진 연결 양 < 클라이언트 요청 이라면??
▶️ 커넥션 풀이 가진 연결 양이 n개라면, 그 n 개 중 작업이 마무리 되는 대로 빈 자리에 연결된다!
🌻 만약, 커넥션 풀이 가진 연결 양 > 클라이언트 요청이라면?
▶️ 커넥션 풀이 가진 연결 양이 n개 라면, 클라이언트 요청이 그 숫자보다 적더라도, 항상 n 개 모두 열려있다!
🌺 커넥션 풀이 가진 연결 양은 옵션을 이용해서 수정할 수 있다!!
DBCP 설치하기
- 프로젝트 내부에 ojdbcX.jar 파일과 JSTL을 위한 jar 파일을 복사해두기!(WEB-INF/lib 폴더 내부에!)
- jsp 파일을 생성, 실행하여 server.xml에서 context 패스 설정하기(이클립스에서는 실행하면 자동생성됨)
- 위의 context 패스 형태를 아래처럼 바꾸어, DBCP 이용을 위한 Resource 태그를 넣을 준비를 해주기
<Context docBase="web-study-09-DBCP"
path="/web-study-09-DBCP" reloadable="true"
source="org.eclipse.jst.jee.server:web-study-09-DBCP"></Context>
- 아파치 홈페이지 http://tomcat.apache.org 에서 Documentation의 Tomcat X.X 선택
- 저는 톰캣 버전 9를 이용하고 있으므로 Documentation의 Version 9.0을 선택하겠습니다
-
버전마다 항목 순서는 다를 수 있는데, “JDBC DataSource(s)”를 선택합니다
-
나타나는 화면에서 “4. Oracle 8i, 9i & 10g” 선택
- 저는 지금 oracle 11g 를 사용하고 있지만, 문제되지 않을 것임을 확인하였습니다. (현재 아파치에서 업그레이드 되지 않은 상태라고 합니다)
[https://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html#Oracle_8i,9i&10g](https://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html#Oracle_8i,_9i&_10g)
- “1. Context Configuration”에 있는 Resource 내용을 복사해서 붙여넣어 줍니다!
- url 부분에서 저는 포트는 1521번, ip 주소는 로컬호스트로 동일하지만, 서비스는 xe로 이용하고 있으므로 mysid부분을 xe로 변경해주도록 하겠습니다!(sid 혹은 서비스네임, 아이디, 비밀번호를 반드시 확인 후 기입해주셔야 합니다!)
<Context docBase="web-study-09-DBCP"
path="/web-study-09-DBCP" reloadable="true"
source="org.eclipse.jst.jee.server:web-study-09-DBCP">
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
username="scott" password="tiger" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/>
</Context>
- 프로젝트에 생성했던 jsp 파일 내부에 위에서 참고한 아파치에 있는 “3. Code example” 부분을 가져와서 스크립트릿으로 넣어줍니다!
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
**<%@ page import="java.sql.Connection" %>
<%@ page import="javax.sql.DataSource" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page import="javax.naming.Context" %>**
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DB연동</title>
</head>
<body>
<%
**Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();**
%>
</body>
</html>
하나하나 오목조목 살펴보도록 합시다!
(1) InitialContext 객체 생성
Context initContext = new InitalContext();
Context와 InitialContext에 대해서 각각 Open Declaration, Open Select를 통해서 확인해보면
InitialContext는 Context 라는 인터페이스를 구현한 클래스인 것을 확인해볼 수 있습니다
이를 바탕으로 이해해보았을 때, 위의 경우는,
InitialContext 객체를 생성하는데, 다형성이 적용되어서
Parent p = new Child();
의 형태임을 나타내고 있음을 알 수 있습니다
상기시켜볼 점은
Up-casting
- 크기가 작은 자료형 ▶️ 크기가 큰 자료형
- 자식 클래스 ▶️ 부모 클래스
되었기 때문에, 암시적인 캐스팅이 되어 형변환자를 생략해도 된다는 점이다!
🌺 잠깐! 인터페이스의 활용성 중 하나였던, 추상클래스를 이용한 활용도 다시 살펴보자!
- 아래처럼 하나의 인터페이스에 대해서는 사용할 기능 및 필드를 알려주기만 하고,
- 추상메서드에서 이를 상속받아서 더 상세하게 기능 및 필드를 명시해주는 것이 인터페이스를 사용하였을 때, 기능이 유사한 클래스들에서의 구현이 보다 간편해질 수 있다!
-인터페이스
package com.poly.part01.test06;
public interface Area {
String print =" 면적: ";
public void print();
public void make();
}
-추상메서드
package com.poly.part01.test06;
//인터페이스를 구현하는데, 메서드를 구현하고 싶지 않다면
//클래스와 메서드를 추상클래스, 추상메서드로 만들어도 됨
public abstract class AreaImpl implements Area{
private String result;
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println(Area.print +result);
}
@Override
public abstract void make();
public void setResult(String result)
{
this.result = result;
}
}
- 또한 이 방식을 이용했을 때, 추상 클래스의 장점으로써, 상세 기능은 추상클래스를 상속받을 클래스에서 작성할 수 있도록 추상 메서드로 설정해둘 수도 있다는 점도 존재한다!
(2) Context 객체의 lookup 메서드로 DBCP에서 지정한 이름찾기
- jdbc/myoracle은 Resource 태그에 존재했던 name 속성의 값!
- DataSource 객체는 Resource 태그에서 존재했던 type 속성의 javax.sql.DataSource에 해당!
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
(3) DataSource 객체로 커넥션 객체 얻어내기(JDBC에서는 DriverManager로 얻어냈던 것과 유사하지만, url이나 id, pwd 부분이 매개변수에 기입되지 않아도 된다는 점이 눈에 띈다! 그 이유는 server.xml에서 url 부분과 아이디, 비밀번호, JDBC 드라이버를 로드하는 데에 필요한 부분이 Resource 태그 내에 기입되어 있기 때문인 것 같다!)
Connection conn = ds.getConnection();
DAO 객체와 VO 객체
🌹 DAO: Database Access Object
- DB의 데이터에 접근하기 위한 객체
- DB 레코드의 조회, 추가, 수정, 삭제 역할을 수행
- DB에서 얻은 데이터를 VO에 저장
🌹 VO : Value Object
- 회원 테이블의 정보를 자바에서 얻어오기 전에 회원 정보를 저장할 공간을 위한 준비 과정
- 자바 빈 객체 클래스와 동일한 기능을 한다고 이해하면 쉽다! 데이터를 담고 있는 객체!
- 속성, setter & getter 메서드로 구성됨
- 데이터를 전달하는 목적으로 사용한다고 해서 DTO(Data Transfer Object)라고도 부름
▶️ 자바 빈 == VO == DTO
VO, DAO 객체를 이용하여 회원 관리 시스템 연습해보기
먼저 로그인 로직을 살펴보자
데이터베이스 풀- 로그인 로직
먼저 구동 원리는 요청과 DB 처리를 위한 DAO, DTO(VO) 처리 단 사이에 컨트롤러가 위치하고, 컨트롤러가 필요에 의해서 DAO에게 일련의 작업을 요청하면, DAO는 DB와 DTO 객체를 주고받음으로써 작업을 수행한다. 그리고 그 결과는 컨테이너에게 전달하게 된다!
컨트롤러는 크게 로그인을 구현하는 LoginServlet, 아이디를 사용할 수 있는지 확인하는 IdCheckServlet, 회원가입을 진행하는 JoinServlet, 회원정보를 수정하는 memberUpdate, 로그아웃을 구현하는 LogoutServlet 으로 구성된다!
그리고 각 컨트롤러는 요청에 따라 1)LoginServlet 은
- login.do 로 url을 매핑
- DB에 존재하는 회원이 확인되면, main.jsp로 이동
- DB에 존재하는 회원이 아니거나, 비밀번호가 일치하지 않으면 기존 페이지에 메시지를 띄우기
2) IdCheckServlet은
- IdCheck.do로 url 매핑
- 회원가입 페이지(join.jsp)에서 자바스크립트로 해당 주소로 아이디가 전달되면서 IdCheck.jsp로 이동된다!
3) JoinServlet은
- join.do로 url 매핑
- 각 입력양식의 최대 길이를 만족하고, 기존 사용자 아이디와 겹치지 않으면 회원가입이 완료됨
- 회원가입이 완료되거나 되지 않아도 login.jsp로 이동하되, 메시지는 다르게 띄우기
4) memberUpdate는
- main.jsp에서 접근할 수 있고, main.jsp로부터 id를 이용해서 dao 객체로부터 사용자 정보를 얻어오고, memberUpdate.jsp로 이동한 후, 수정할 정보를 가져오기
- memberUpdate.do로 url 매핑
- memberUpdate.jsp로부터 받은 정보를 VO 객체에 담고, 세션에 갱신된 정보를 저장한 후, login.jsp로 리다이렉트
5) LogoutServlet은
- session을 invalidate() 메서드를 통해서 무효화 시키면 된다!
- 그 후에는 login.jsp페이지로 이동한다!
- VO 클래스 만들기
- 먼저, 데이터를 전달하기 위한 클래스로, VO 클래스를 만들어보자
- 데이터는 아래와 같이 구성해보기로 한다
위의 데이터를 담기 위한 테이블 MEMBER 테이블을 아래의 질의문으로 생성해보자
- 주석으로 각 데이터에 대한 설명도 넣어주었다!
DROP TABLE MEMBER;
CREATE TABLE MEMBER(
USERID VARCHAR2(10) PRIMARY KEY,
NAME VARCHAR2(10),
PWD VARCHAR2(10),
EMAIL VARCHAR2(20),
PHONE CHAR(13),
ADMIN NUMBER(1) DEFAULT 0 --0: 사용자, 1: 관리자
);
COMMENT ON COLUMN MEMBER.USERID IS '사용자아이디';
COMMENT ON COLUMN MEMBER.NAME IS '사용자이름';
COMMENT ON COLUMN MEMBER.PWD IS '사용자비밀번호';
COMMENT ON COLUMN MEMBER.EMAIL IS '사용자이메일주소';
COMMENT ON COLUMN MEMBER.PHONE IS '사용자연락처';
COMMENT ON COLUMN MEMBER.ADMIN IS '모드식별';
SELECT * FROM USER_COL_COMMENTS WHERE TABLE_NAME='MEMBER';
INSERT INTO MEMBER
VALUES('SOMI','이소미','1234','gmd@gmail.com','010-2362-5157',0);
INSERT INTO MEMBER
VALUES('SANG12','하상오','1234','ha12@naver.com','010-5629-8888',1);
INSERT INTO MEMBER
VALUES('LIGHT','김윤승','1234','youn1004@naver.com','010-9999-8282',0);
SELECT USERID, NAME, PWD, EMAIL, PHONE, ADMIN
FROM MEMBER;
com.js.dto 패키지명으로 MemberVO 클래스를 생성하자!
package com.js.dto;
public class MemberVO {
//데이터필드
private String name;
private String userId;
private String pwd;
private String email;
private String phone;
private int admin;
//constructors
public MemberVO() {
// TODO Auto-generated constructor stub
}
public MemberVO(String name, String userId, String pwd, String email, String phone, int admin) {
this.name = name;
this.userId = userId;
this.pwd = pwd;
this.email = email;
this.phone = phone;
this.admin = admin;
}
//getters & setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getAdmin() {
return admin;
}
public void setAdmin(int admin) {
this.admin = admin;
}
//jsp 파일에서 넘어오는 값은 String이므로 integer로 바꾸어주기!(<-오버로딩 이용!)
public void setAdmin(String admin) {
this.admin = Integer.valueOf(admin);
}
//toString()
@Override
public String toString() {
return "MemberVO [name=" + name + ", userId=" + userId + ", pwd=" + pwd + ", email=" + email + ", phone="
+ phone + ", admin=" + admin + "]";
}
}
(1) 먼저 위에서 만든 DB 테이블을 참고하여 데이터 필드를 만들고
(2) 생성자, getter, setter 를 만든다
(3) 그 후에는 toString을 오버라이딩하여 데이터 객체를 String으로 손쉽게 추출할 수 있도록 한다!
- DAO 객체 만들기
🌟 싱글톤 패턴
- 매번 DB의 데이터를 VO 객체를 통해 얻어오거나, VO 객체에 저장된 값을 DB에 추가할 때 매번 DAO 객체를 생성하는 것은 비효율적!
- 따라서, DAO 객체는 싱글톤 패턴으로 설계하는 것이 보다 효율적!
- 인스턴스는 오로지 단 하나만 존재하여, 객체를 메모리에 단 한 번만 올려놓고 시스템 전반에 걸쳐서 특정 자원(Object, Module, Component)을 공유할 때 사용되는 패턴
- 싱글톤 패턴의 모습을 아래의 구조로 살펴보자!
public class MemberDao{
private MemberDao(){
//1.private한 생성자
}
//2.DAO객체를 클래스객체로, private하게 필드로 만들어두기
private static MemberDao dao = new MemberDao();
//3. 외부에서 객체에 접근하는 수단으로써 public 메서드를 두기
//static 멤버를 반환해주어야 하고, 동시에 메모리에 실행 시 먼저 로드되는 static 특성상
//static 메서드로 이용
public static MemberDao getInstance(){
return dao;
}
}
즉,
1.private한 생성자
2.Dao 클래스 내부에 private한 Dao 객체를 필드로 두기
🌟3.외부에서 접근할 수 있는 public 메서드를 두기
와 같은 형태로 설계하여 사용할 수 있다!
조심할 부분은, 3번인데, public static을 사용한 이유는
public으로 두어서 외부에서 dao 객체에 간접적으로 접근할 수 있도록 하기 위함
static 메서드 특성상 메모리에 프로그램 실행 시작 시, 먼저 탑재되고 static 멤버를 전달해줄 수 있다는 점
에서 사용한 것으로 조심스레 생각해본다!
이를 이용하여 DAO 객체를 위한 클래스를 만들어보자!
- 그리고!! DAO 객체에는 VO 객체를 이용한 데이터 송수신이 필요하므로 , 커넥션 객체를 위한 getConnection() 메서드를 작성해두자!
package com.js.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import com.js.dto.MemberVO;
import com.js.invalidException.InvalidException;
public class MemberDao {
Connection conn = null;
Statement st = null;
PreparedStatement ps = null;
ResultSet rs = null;
//싱글톤 패턴
//2.클래스 변수로 Dao 클래스 객체 만들어두기
private static MemberDao dao = new MemberDao();
//1.private 생성자
private MemberDao() {
}
//3.외부에서 객체를 반환받을 수 있는 메서드
public static MemberDao getInstance() {
return dao;
}
//4.커넥션 객체 얻어오기
public Connection getConnection() throws Exception{
//커넥션 객체 준비
Connection conn = null;
//InitialContext 객체 생성
Context context = new InitialContext();
//initial context의 lookup 메서드로 name 속성에 접근하기
Context envContext = (Context) context.lookup("java:/comp/env");//Object->Context! 따라서 명시적 형변환!!
//DataSource
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");//Object->DataSource
//커넥션 객체 생성
conn = ds.getConnection();
conn.setAutoCommit(false);//transaction autocommit 방지
return conn;
}
//DAO에서 사용자 인증을 위함
public int userCheck(String userId, String pwd) {
//성공 or 실패 변수
int res = -1;//비밀번호가 일치하면 1, 아이디만 존재하면 0 , 아이디가 존재하지 않으면 -1
String confirmQuery = "SELECT PWD FROM MEMBER WHERE USERID=?";//아이디값으로 비밀번호를 찾아와서 일치 여부 확인
try {
//dbcp로부터 connection가져오기
conn = getConnection();
//statement 준비
ps = conn.prepareStatement(confirmQuery);
ps.setString(1, userId);
//query 실행 ->그 결과를 result set으로 받기
rs = ps.executeQuery();
if(rs.next()) {
//존재하는 것이 확인된다면
//confirm process
//null check가 선행되는 것이 보다 검색 성능이 좋을 것! 따라서 이를 먼저 적기!
String compPwd =rs.getString(1);
if(compPwd!=null && pwd.equals(compPwd)) {
res = 1;//아이디, 비밀번호 모두 존재, 일치
}else {
res = 0;//아이디만 존재하고 비밀번호는 불일치!
}
}else {
//존재하지 않는다면
res = -1;
}
}catch(Exception e1) {
System.out.println("[ERR]Failed to identify user "+userId);
e1.printStackTrace();
}finally {
try {
rs.close();
ps.close();
conn.close();
}catch(Exception e2) {
System.out.println("[ERR]ERROR INDUCED DURING CLOSING CONN IN USERCHECK!");
e2.printStackTrace();
}
}
return res;//성공 케이스 혹은 실패 케이스 여부 변수 전달(from database to was)(from was to web server)
//tomcat은 was+web server이므로 위의 두 역할을 모두 수행
}
//아이디(기본키->식별자)로 회원 정보를 가져오기
public MemberVO getMemberInfo(String userId) {
//정보를 담을 vo 객체
MemberVO mVo = new MemberVO();
//회원 정보를 담기 위한 조회 쿼리
String getUserInfoQuery = "SELECT USERID, NAME, PWD, EMAIL, PHONE, ADMIN FROM MEMBER WHERE USERID=?";
try {
//dbcp로부터 커넥션 가져오기
conn = getConnection();
//statement 준비
ps = conn.prepareStatement(getUserInfoQuery);
ps.setString(1, userId);
rs = ps.executeQuery();
if(rs.next()) {
//조회 결과가 존재한다면, vo객체에 정보를 매핑해주기
mVo.setUserId(rs.getString(1));
mVo.setName(rs.getString(2));
mVo.setPwd(rs.getString(3));
mVo.setEmail(rs.getString(4));
mVo.setPhone(rs.getString(5));
mVo.setAdmin(rs.getInt(6));
}else {
//조회 결과가 존재하지 않는다면, 즉 그러한 레코드가 전혀 존재하지 않으면 콘솔에 문구 띄우기
throw new InvalidException(new StringBuilder(userId+"는 존재하지 않습니다. 다시 확인해보세요").toString());
}
}catch(Exception e1) {
System.out.println("[ERR]GET USER INFO FAILED! CHECK LOG");
e1.printStackTrace();
}finally {
try {
rs.close();
ps.close();
conn.close();
}catch(Exception e2) {
System.out.println("[ERR]CLOSING CONN ERR (GET USER INFO)");
e2.printStackTrace();
}
}
return mVo;//정보 넘기기
}
//아이디 중복 체크
public int confirmId(String userId) {
//기존 아이디가 존재하면 1, 존재하지 않으면 -1 반환
int res = -1;
String confirmIdQuery= "SELECT USERID FROM MEMBER WHERE USERID=?";
try {
conn = getConnection();
ps = conn.prepareStatement(confirmIdQuery);
ps.setString(1, userId);
rs = ps.executeQuery();
if(rs.next()) {
res = 1;
}else {
res = -1;
}
}catch(Exception e1) {
System.out.println("[ERR]아이디 중복체크 중 에러 발생 !!");
e1.printStackTrace();
}finally {
try {
rs.close();
ps.close();
conn.close();
}catch(Exception e2) {
System.out.println("[ERR]CLOSE ERROR(USER ID CHECKING)");
e2.printStackTrace();
}
}
return res;
}
//DB에 회원 정보 추가(저장)
public int insertMember(MemberVO vo) {
//insert 성공 여부
int resIns = -1;
String insertQuery="INSERT INTO MEMBER VALUES(?,?,?,?,?,?)";
try {
conn = getConnection();
ps = conn.prepareStatement(insertQuery);
//USERID, NAME, PWD, EMAIL, PHONE, ADMIN
ps.setString(1, vo.getUserId());
ps.setString(2, vo.getName());
ps.setString(3, vo.getPwd());
ps.setString(4, vo.getEmail());
ps.setString(5, vo.getPhone());
ps.setInt(6, vo.getAdmin());
resIns = ps.executeUpdate();
if(resIns>0) {
System.out.println("INSERT 성공");
conn.commit();
}else {
System.out.println("INSERT 실패");
conn.rollback();
}
}catch(Exception e1) {
System.out.println("[ERR]INSERT FAILED");
e1.printStackTrace();
}finally {
try {
ps.close();
conn.close();
}catch(Exception e2) {
System.out.println("[ERR]Close Error at INSERTING");
e2.printStackTrace();
}
}
return resIns;
}
//회원 정보 갱신시키기
public int updateMember(MemberVO vo) {
int resUp = -1;
//USERID, NAME, PWD, EMAIL, PHONE, ADMIN
String updateQuery="UPDATE MEMBER SET USERID=?, NAME=?, PWD=?, EMAIL=?, PHONE=?, ADMIN=? WHERE USERID=?";
try {
//dbcp에서 커넥션 얻어오기
conn = getConnection();
//preparedStatement 준비
//memberUpdate.jsp의 request객체에 담겨져 있는 정보가 memberUpdate.do에 해당되는
//서블릿 내부에서 처리 및 전달될 것이고, 그 내부의 dao객체 호출로 그 정보가 전달되어, 작업이 이루어질 것!
ps = conn.prepareStatement(updateQuery);
ps.setString(1, vo.getUserId());
ps.setString(2, vo.getName());
ps.setString(3, vo.getPwd());
ps.setString(4, vo.getEmail());
ps.setString(5, vo.getPhone());
ps.setInt(6, vo.getAdmin());
ps.setString(7, vo.getUserId());
System.out.println(updateQuery+", data:"+vo.toString());
//실행
resUp = ps.executeUpdate();
if(resUp > 0) {
conn.commit();
}else {
conn.rollback();
}
}catch(Exception e1) {
System.out.println("[ERR]UPDATE USER INFO ERROR!");
e1.printStackTrace();
}finally {
try {
ps.close();
conn.close();
}catch(Exception e2) {
System.out.println("[ERR] CLOSE ERROR AT UPDATE USER INFO");
e2.printStackTrace();
}
}
return resUp;
}
}
- 더불어서, DAO 객체는 질의를 담당하므로, 그에 대한 메서드도 준비해두어야 한다!
- 아래의 표는 위의 DB 정보와 VO 클래스를 바탕으로 필요한 기능을 정리한 것이다!
[백견불여일타 JSP&SERVLET p.473 참조]
회원 인증을 위한 아이디, 비밀번호 입력 폼 login.jsp , LoginServlet.java
- 아이디, 비밀번호를 입력받는 폼 ▶️ jsp 페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원관리</title>
</head>
<body>
<header>
<h1>로그인</h1>
</header>
<section>
<article>
<form action="./login.do" method="post" name="frm">
<table>
<tr>
<td>아이디 </td>
<td><input type="text" name="userId" id="userId" value="${userId }"></td>
</tr>
<tr>
<td>비밀번호 </td>
<td><input type="password" name="pwd" id="pwd"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="로그인" id="login" onclick="return loginCheck();">
<input type="reset" value="취소" title="모든 값이 지워집니다">
<input type="button" value="회원가입" onclick="location.href=`join.do`">
</td>
</tr>
<tr>
<td colspan="2">${msg}</td>
</tr>
</table>
</form>
</article>
<%-- <article>
<%
String connect ="./index.jsp";
%>
<jsp:include page="${connect }"/>
</article> --%>
</section>
<script src="../js/member.js"></script>
</body>
</html>
- 로그인을 위한 정보가 null인지 확인하는 방법 ▶️ 자바스크립트를 이용
/**
* 아이디, 비밀번호 유효성 검사
*/
//const login=document.getElementById("login");
const form = document.frm;
const id = document.frm.userId;
const pwd = document.frm.pwd;
function loginCheck(){
if(id.value.length===0 || id.value===""){
alert(`아이디 확인 요망!`);
return false;
}
if(pwd.value.length===0 || pwd.value===""){
alert(`비밀번호 확인 요망`);
return false;
}
return true;
}
- 입력받은 양식은 login.do로 연결되도록 하는데, 이를 통하여 서블릿에서 jsp 페이지를 실행할 수 있도록 하기◀️ url 매핑(pattern)을 login.do로 설정[@WebServlet(“/login.do”)]
package com.js.controller;
import java.io.IOException;
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;
import javax.servlet.http.HttpSession;
import com.js.dao.MemberDao;
import com.js.dto.MemberVO;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String url = "member/login.jsp";
HttpSession session=request.getSession();
/*
* 이미 로그인된 사용자라면 메인페이지로,
* 그렇지 않으면 기본적으로 login.jsp로 이동
*
* */
//로그인되어있었다면
if(session.getAttribute("logInUser")!=null) {
//밑에 있는 post 등을 통해서 세션에 저장해둔 obj이 있었는지 확인
//MemberDao dao = MemberDao.getInstance();
MemberVO mVo = (MemberVO)session.getAttribute("logInUser");
session.setAttribute("logInUser", mVo);
url = "main.jsp";
}
RequestDispatcher dispatcher= request.getRequestDispatcher(url);
dispatcher.forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//연결되는 url
String connUrl = "member/login.jsp";
//url로 연결되었기 때문에 request객체로부터 값을 가져올 수 있음
String userId = request.getParameter("userId");
String pwd = request.getParameter("pwd");
MemberDao dao = MemberDao.getInstance();//singleton
RequestDispatcher dispatcher = null;
//login처리
int logInCk = dao.userCheck(userId, pwd);
if(logInCk ==1) {
//성공 시 유저 정보 가져오기
MemberVO mVo = dao.getMemberInfo(userId);
//세션정보를 얻어와서 세션에 정보 저장해두기
HttpSession session = request.getSession();
session.setAttribute("logInUser", mVo);
//로그인[회원가입] 성공 메시지는 세션에 저장할 필요는 없고 request객체 범위에만 저장해도 됨
//그 이유는 로그인 정보는 사이트 내에서 사용자 정보가 공유되어야 로그인 이후 서비스 제공이 가능해지기 때문
request.setAttribute("msg", "로그인/회원가입에 성공했습니다!");
//페이지 포워딩을 위해서 url을 지정
connUrl = "./main.jsp";
}else if(logInCk ==0) {
//비밀번호가 틀린 경우
//메시지만 띄우기
request.setAttribute("msg", "비밀번호가 맞지 않습니다");
}else if(logInCk == -1) {
//그런 사용자가 존재하지 않는 경우
request.setAttribute("msg", "존재하지 않는 회원입니다");
}
dispatcher = request.getRequestDispatcher(connUrl);
dispatcher.forward(request, response);
}
}
⚠️ 위에서는 jsp 파일을 실행하지 않고 login.do로 요청하여 수행하도록 하고자 하였으나, login.jsp로 바로 실행하는 경우도 있으며, 주소 입력란에 직접 입력하기 어렵기 때문에 이를 방지하기 위해서 index.jsp 파일을 만들어 홈페이지로 사용 ▶️ 컨텍스트 패스까지만 입력하면 index.jsp 페이지로 이동됨
- 원리- 기본적으로 톰캣서버를 이용할 때 web.xml 내부에서
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
위와 같이 프론트 페이지 리스트가 설정되어 있기 때문!! 다른 파일을 프론트 페이지로 하고 싶다면 추가하면 된다!
회원가입을 위한 Join.jsp, JoinServlet.java
- 회원 가입 부분은 중간에 자바스크립트 오프너를 통해서 idCheck.do와 연결되므로 같이 다루도록 하겠다!
먼저, 앞에서 언급했던 연결되는 부분은 자바스크립트 오프너를 이용해서 팝업창처럼 띄워지게 된다!
/**
* 아이디, 비밀번호 유효성 검사
*/
//const login=document.getElementById("login");
const form = document.frm;
const id = document.frm.userId;
const pwd = document.frm.pwd;
function loginCheck(){
if(id.value.length===0 || id.value===""){
alert(`아이디 확인 요망!`);
return false;
}
if(pwd.value.length===0 || pwd.value===""){
alert(`비밀번호 확인 요망`);
return false;
}
return true;
}
function idCheck(){
const url = "http://localhost:8081/web-study-09-DBCP/idCheck.do?userId="+id.value;//아이디 중복 체크 결과만 "출력"할 것이므로 get!!
if(id.value.length===0 || id.value===""){
alert(`아이디 확인 요망!`);
id.focus();
return false;
}
window.open(url,"_blank","toolbar=no, menubar=no, scrollbars=yes, resizable=no, width=450,height=200");
}
그러면, idCheck.do에서는 dao를 통해 db에서 일치하는 정보가 있는지 찾아서, 그 결과와 아이디를 request객체에 저장한다! 그 이유는 굳이 중복 여부만 확인하는 것인데, 세션에 저장할 필요가 없기 때문이다!
package com.saeyan.controller;
import java.io.IOException;
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;
import com.js.dao.MemberDao;
/**
* Servlet implementation class IdCheckServlet
*/
@WebServlet("/idCheck.do")
public class IdCheckServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public IdCheckServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String userId = request.getParameter("userId");//member.js를 통해서 넘어오게 됨!
MemberDao dao = MemberDao.getInstance();
int res = dao.confirmId(userId);
//그저 중복확인만하는 것이기 때문에, 세션 전체에 알리는 것보다는 request간 알리는 것이 보다 효율적
request.setAttribute("userId", userId);
request.setAttribute("confirmId", res);
RequestDispatcher dispatcher = request.getRequestDispatcher("./member/idCheck.jsp");
dispatcher.forward(request, response);
}
/**
* @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);
// }
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% request.setCharacterEncoding("UTF-8"); %>
<% response.setContentType("text/html;charset=UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>아이디 중복 체크</title>
</head>
<body>
<header>
<h1>아이디 중복 확인</h1>
</header>
<form action="idCheck.do" method="get" name="frm">
<label>아이디 <input type="text" name="userId" value="${userId}"></label>
<input type="submit" value="중복 체크">
<br>
<c:if test="${confirmId==1}">
<script>
opener.document.frm.userId.value="":
</script>
${userId}는 이미 사용 중인 아이디입니다
</c:if>
<c:if test="${confirmId==-1}">
${userId}는 사용 가능한 아이디입니다
<input type="button" value="사용" class="cancel" onclick="idOk();">
</c:if>
</form>
<script src="./js/member.js"></script>
</body>
</html>
그리고 사용한다는 버튼을 누르게 되면, 자바스크립트의 idOk 함수를 통해서 idCheck.jsp와 join.jsp 간 값 연결을 명시해준다!
function idOk(){
//join.jsp와 연결될 것!(from idCheck.jsp)
opener.frm.userId.value=document.frm.userId.value;//오프너를 통해서 아이디값 이어주기
opener.frm.reId.value =document.frm.userId.value;
self.close();
}
JoinServlet은 회원가입 요청이 들어오면, 그저 join.jsp 페이지로 연결해주고
join.jsp로부터 post 요청(정보 저장 요청으로써)이 들어오면, dao 객체를 통해 insert 작업을 수행하고, 그 결과에 따라 login.jsp 페이지에 띄울 메시지를 저장해준다 ! 최소한 범위가 request이상이면 되나, 세션을 조금 더 공부중인 상황이었기 때문에 session 객체로 메시지와 사용자 아이디를 저장해주었다.
package com.saeyan.controller;
import java.io.IOException;
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;
import javax.servlet.http.HttpSession;
import com.js.dao.MemberDao;
import com.js.dto.MemberVO;
/**
* Servlet implementation class JoinServlet
*/
@WebServlet("/join.do")
public class JoinServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public JoinServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//연결될 페이지
RequestDispatcher dispatcher= request.getRequestDispatcher("./member/join.jsp");
dispatcher.forward(request,response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//회원정보를 저장하여 dao로 넘기기
//인코딩 설정
request.setCharacterEncoding("UTF-8");
//join.jsp에 명시했던 name속성으로 가져오기
String name = request.getParameter("name");
String userId = request.getParameter("userId");
String pwd = request.getParameter("pwd");
String email = request.getParameter("email");
String phone = request.getParameter("phone");
int admin = Integer.valueOf(request.getParameter("admin"));
MemberVO vo = new MemberVO();
MemberDao dao = MemberDao.getInstance();
int resIns = 0;
HttpSession session = request.getSession();
vo.setUserId(userId);
vo.setName(name);
vo.setPwd(pwd);
vo.setEmail(email);
vo.setPhone(phone);
vo.setAdmin(admin);
resIns = dao.insertMember(vo);
if(resIns ==1) {
session.setAttribute("userId",vo.getUserId());
session.setAttribute("msg", "회원 가입에 성공했습니다");
}else {
session.setAttribute("msg", "회원 가입에 실패했습니다");
}
RequestDispatcher dispatcher=request.getRequestDispatcher("./member/login.jsp");
dispatcher.forward(request, response);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8");%>
<% response.setContentType("text/html; charset=UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원 관리</title>
<style>
em{
color:red;
}
</style>
</head>
<body>
<header>
<h1>회원 가입</h1>
</header>
<section>
<article>
<div><em>* 표시 항목은 필수 입력 항목입니다</em></div>
<form action="join.do" method="post" name="frm">
<!-- 정보 출력은 get, 저장은 post로 주로 사용됨! -->
<table border="1">
<tr>
<td>이름<pre> </pre></td>
<!-- size는 maxlength를 지정 -->
<td><input type="text" name="name" size="20">*</td>
</tr>
<tr>
<td>아이디<pre> </pre></td>
<td>
<input type="text" name="userId" size="20" id="userId">*
<input type="hidden" name="reId" size="20">
<input type="button" value="중복체크" onclick="idCheck();">
</td>
</tr>
<tr>
<td>암호<pre> </pre></td>
<td><input type="password" name="pwd" size="20">*</td>
</tr>
<tr height="30">
<td width="80">암호 확인</td>
<td><input type="password" name="pwdCheck" size="20">*</td>
</tr>
<tr>
<td>이메일</td>
<!-- string으로 받는 의미를 살리기 위해 text type 이용 -->
<td><input type="text" name="email" size="20"></td>
</tr>
<tr>
<td>전화번호</td>
<td><input type="text" name="phone" size="20"></td>
</tr>
<tr>
<td>이용모드</td>
<td>
<input type="radio" name="admin" value="0" checked>일반회원
<input type="radio" name="admin" value="1">관리자
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="확인" onclick="return joinCheck();"><pre> </pre>
<input type="reset" value="취소">
</td>
</tr>
<tr>
<td colspan="2">${msg}</td>
</tr>
</table>
</form>
</article>
</section>
<script src="./js/member.js"></script>
</body>
</html>
//회원정보 유효성 검사
function joinCheck(){
if(document.frm.name.value.length ===0 || document.frm.name.value===""){
//이름 입력이 빠진 경우
alert(`이름을 써주세요`);
frm.name.focus();
return false;
}
if(document.frm.userId.value.length===0 || document.frm.userId.value===""){
//아이디 입력이 빠진 경우
alert(`아이디를 써주세요`);
frm.userId.focus();
return false;
}
if(document.frm.userId.length<4){
//아이디 입력 크기가 4이상으로 되도록 제한시키기!
alert(`아이디는 4글자 이상이어야 합니다`);
frm.userId.focus();
return false;
}
if(document.frm.pwd.value.length=== 0 || document.frm.pwd.value===""){
//비밀번호 입력이 빠진경우
alert(`비밀번호는 반드시 입력해야 합니다`);
frm.pwd.focus();
return false;
}
if(document.frm.pwd.value !== document.frm.pwd_check.value){
//비밀번호가 일치하지 않는 경우
alert(`비밀번호가 일치하지 않습니다`);
frm.pwd.focus();
return false;
}
if(document.frm.reId.value.length ===0 || document.frm.reId.value ===0){
//아이디 중복확인 후 입력되는 부분이 비어있는 경우
alert(`아이디 중복체크를 하지 않았습니다`);
frm.userId.focus();
return false;
}
return true;
}
회원 정보를 수정하기
- 회원 정보를 수정하기 위해서, 먼저 가입된 회원이기 때문에 main.jsp 에서 요청을 할 수 있도록 한다
- 해당 요청이 들어오면, memberUpdate.do로 사용자 아이디와 함께 이동되는데, 그러면 그 요청을 받은 memberUpdate 서블릿은 memberUpdate.jsp로 연결해준다
- 그 후 memberUpdate.jsp에서 수정할 정보가 입력되면, memberUpdate.do로 요청이 들어오고, dao 객체를 통해서 update 작업이 이루어지고, 세션의 객체를 갱신시킨다
- 그 다음에는 세션에 저장을 했기 때문에 리다이렉트가 이루어져도 된다
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% request.setCharacterEncoding("UTF-8"); %>
<% response.setContentType("text/html;charset=UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>개인 정보 수정</title>
</head>
<body>
<header>
<h1>나의 정보 수정</h1>
</header>
<section>
<article>
<form action="memberUpdate.do" method="post" id="frm">
<table border="1" >
<tr>
<td>이름</td>
<td><input type="text" name="name" size="20" value="${targetToUpdate.name}"></td>
</tr>
<tr>
<td>아이디</td>
<td><input type="text" name="userId" size="20" value="${targetToUpdate.userId }"></td>
</tr>
<tr>
<td>비밀번호</td>
<td><input type="password" name="pwd" size="20" value="${targetToUpdate.pwd }">*</td>
</tr>
<tr>
<td>암호확인</td>
<td><input type="password" name="pwd_check" size="20">*</td>
</tr>
<tr>
<td>이메일</td>
<td><input type="text" name="email" size="20" value="${targetToUpdate.email }"></td>
</tr>
<tr>
<td>전화번호</td>
<td><input type="text" name="phone" size="20" value="${targetToUpdate.phone }"></td>
</tr>
<tr>
<td>등급</td>
<td>
<c:choose>
<c:when test="${targetToUpdate.admin==0 }">
<label><input type="radio" name="admin" value="0" checked>일반회원</label>
<label><input type="radio" name="admin" value="1">관리자</label>
</c:when>
<c:otherwise>
<label><input type="radio" name="admin" value="0">일반회원</label>
<label><input type="radio" name="admin" value="1" checked>관리자</label>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="확인" onclick="return joinCheck();"><pre> </pre>
<input type="reset" title="입력한 정보가 모두 지워집니다" value="취소" onclick="location.href='./main.jsp';">
</td>
</tr>
</table>
</form>
</article>
</section>
<script src="./js/member.js"></script>
</body>
</html>
package com.saeyan.controller;
import java.io.IOException;
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;
import javax.servlet.http.HttpSession;
import com.js.dao.MemberDao;
import com.js.dto.MemberVO;
/**
* Servlet implementation class memberUpdate
*/
@WebServlet("/memberUpdate.do")
public class memberUpdate extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public memberUpdate() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//메인페이지의 request 객체로부터 정보 가져오기
String userId = request.getParameter("userId");
MemberDao dao = MemberDao.getInstance();
//userId로 사용자 정보 가져오기
MemberVO mVo = dao.getMemberInfo(userId);
HttpSession session = request.getSession();
session.setAttribute("targetToUpdate",mVo);//정보를 수정할 대상임을 나타내도록 변수 네이밍
//get을 이용해서는 정보수정을 위한 정보를 받아올 폼페이지로 이동
RequestDispatcher dispatcher = request.getRequestDispatcher("member/memberUpdate.jsp");
dispatcher.forward(request, response);
}
/**
* @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);
//dao로 정보 갱신을 위한 정보를 넘기기 위한 일련의 작업 수행
MemberVO mVo = new MemberVO();
//dao instance
MemberDao dao = MemberDao.getInstance();
HttpSession session = request.getSession();
//0.encoding setting for post method
request.setCharacterEncoding("UTF-8");
//1. get info from memberUpdate.jsp
String name=request.getParameter("name");
String userId = request.getParameter("userId");
String pwd = request.getParameter("pwd");//js에서 이미 validation이 수행되었으므로
//request중 pwd_check를 가져올 필요는 없음
String email = request.getParameter("email");
String phone = request.getParameter("phone");
int admin = Integer.valueOf(request.getParameter("admin"));
//2.mapping vars to membervo obj
mVo.setName(name);
mVo.setUserId(userId);
mVo.setPwd(pwd);
mVo.setEmail(email);
mVo.setPhone(phone);
mVo.setAdmin(admin);
//3.dao에게 update를 수행시키기
dao.updateMember(mVo);
//4세션에 저장하기
session.setAttribute("logInUser",mVo);
//5.정보를 넘길 필요없이 리다이렉트로 페이지만 넘겨도 됨
response.sendRedirect("login.do");
}
}
로그아웃하기
- 로그아웃은 가장 간단하다! 지금 세션에 로그인된 사용자 정보가 담겨져 있었는데 이를 무효화하면서, login.jsp 페이지로 이동하면 된다!
package com.saeyan.controller;
import java.io.IOException;
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;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class LogoutServlet
*/
@WebServlet("/logout.do")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LogoutServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//세션무효화->로그아웃
HttpSession session = request.getSession();
session.invalidate();
RequestDispatcher dispatcher = request.getRequestDispatcher("./member/login.jsp");
dispatcher.forward(request, response);
}
/**
* @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);
}
}
데이터베이스 커넥션풀을 이용한 로그인 로직 구현