본문 바로가기
JSP

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(1) - 기본 세팅하기

by 김마리님 2020. 5. 28.

앞서 만들었던 회원가입 시스템은 jsp만을 이용했다. 이런 형태를 모델1 형식이라고 한다.

서블릿과 jsp를 이용해서 병행하여 사용하는 것을 모델2 형식이라고 한다.

 

다음 블로그 형식에서는 컨트롤러를 만들어 모든 사용자의 요청을 받고 이에 대한 응답을 진행할 것이다. 이 컨트롤러를 서블릿으로 만들 것이다.

 

블로그에 필요한 가장 기본적인 테이블 만들기.

오라클 기준 데이터이며, MySQL이면 int면 number, varchar2를 varchar로 변경해주자.

CREATE TABLE users(
	id number primary key,
    username varchar2(100) not null unique,
    password varchar2(100) not null,
    email varchar2(100) not null,
    address varchar2(100) not null,
    userProfile varchar2(200),
    createDate timestamp
) ;

CREATE TABLE board(
	id number primary key,
    userId number,
    title varchar2(100) not null,
    content clob,
    readCount number default 0,
    createDate timestamp,
    foreign key (userId) references users (id)
);

CREATE TABLE reply(
	id number primary key,
    userId number,
    boardId number,
    content varchar2(300) not null,
    createDate timestamp,
    foreign key (userId) references users (id) on delete set null,
    foreign key (boardId) references board (id) on delete cascade
);

시퀀스 생성

Create SEQUENCE user_seq
    start with 1
    INCREMENT by 1;
    
Create SEQUENCE board_seq
    start with 1
    INCREMENT by 1;
 
Create SEQUENCE reply_seq
    start with 1
    INCREMENT by 1;  

코드의 가독성과 객체화를 위해 서블릿에 쓸 자바 코드를 나눕니다. 효율성과 이후에 유지보수를 위해 파일을 좀 나눠두도록 합니다.

 

(Repository라는 것은 사용할 모든 데이터들의 연결구라고 생각하면 될 것 같습니다. 예전에는 DAO(data access object)라고 불렀지요. 

 

이후에 DB 데이터가 들어갈 DB 모델들을 model 패키지에 만듭니다.

(필자는 lombok 라이브러리를 사용합니다. 쓰지 않는다면 getter,setter 등 알아서 다 만드셔야 합니다.)

 

-Users.java

package com.cos.blog.model;

import com.sun.jmx.snmp.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Users {
	private int id;
	private String username;
	private String password;
	private String email;
	private String address;
	private String userProfile;
	private Timestamp createDate;
}

 

-Board.java

package com.cos.blog.model;

import com.sun.jmx.snmp.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Users {
	private int id;
	private String username;
	private String password;
	private String email;
	private String address;
	private String userProfile;
	private Timestamp createDate;
}

 

-Reply.java

package com.cos.blog.model;

import com.sun.jmx.snmp.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Reply {
	private int id;
	private int userId;
	private int boardId;
	private String content;
	private Timestamp createDate;

 

이후 데이터베이스를 연결한다. 이전처럼 계속 conn 방식이 아닌 pull 방식으로 데이터베이스를 연결할 것이다.

데이터베이스 설정을 외부 서버파일의 xml등에 하면 배포 이후에 재설정을 해야하므로, 배포될 프로젝트 내부에 xml 파일을 만들어 오버로딩을 시킨다.

 

pull 방식을 이용한 서버 세팅 방법은 apache에 기술되어있다.

 

http://tomcat.apache.org/

 

Apache Tomcat® - Welcome!

The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies. The Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket specifications ar

tomcat.apache.org

apache에 본인이 사용하고 있는 버전의 (필자는 8.5버전을 사용중이다.)의 문서(documentation)를 들어가보면 

JDBC DataSource - Configuring a JNDI DataSource with a DB connection pool. Examples for many popular databases.

 

Apache Tomcat 8 (8.5.55) - JNDI Datasource How-To

JNDI Datasource configuration is covered extensively in the JNDI-Resources-HOWTO. However, feedback from tomcat-user has shown that specifics for individual configurations can be rather tricky. Here then are some example configurations that have been poste

tomcat.apache.org

라는 링크가 있다. 링크를 눌러보자. 좀 내려보면, web.xml 설정과 context.xml 설정을 할 수 있는 코드가 있다.

context와 web.xml 파일을 만들어 저 코드를 넣자.

 

 

- context.xml

<?xml version="1.0" encoding="UTF-8"?>
<context>
<Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
              url="jdbc:oracle:thin:@localhost:1521:xe"
              username="cos" password="bitc5600" maxTotal="20" maxIdle="10"
              maxWaitMillis="-1"/>
</context>   

 

이 때 본인이 사용하는 데이터베이스가 무엇인지, driverClassName이 무엇인지, sidID와 IP주소가 맞는지 잘 확인하고 넣도록 합시다. (..확인 안하면 오류 납니다..)

 

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                       http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

		<filter>
		<filter-name>setCharacterEncodingFilter</filter-name>
		<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>setCharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<resource-ref>
 <description>Oracle Datasource example</description>
 <res-ref-name>jdbc/myoracle</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>

</web-app>

web.xml에서 받아오는 이름 res-ref-name과 context의 리소스 이름이 겹치는지 확인한다. web.xml이 context에서 데이터를 받아오기 때문에 이름이 일치하지 않으면 데이터를 가져올 수가 없다.

 

다음 데이터베이스 연결 파일을 따로 만들어서 관리한다. (이것도 톰캣 홈페이지 글을 긁어오세요. 임포트도 앚지 말고)

package com.cos.blog.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class DBConn {
	public static Connection getConnection() {
		try {
			Context initContext = new InitialContext();
			Context envContext  = (Context)initContext.lookup("java:/comp/env");
			DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
			System.out.println("DBConn : 데이터베이스 연결 성공");
			Connection conn = ds.getConnection();
			return conn;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("DBConn : 데이터베이스 연결 실패");
			System.out.println("DBConn : Message : "+e.getMessage());
			return null;
		}
	}
	public static void close(Connection conn, PreparedStatement pstmt) {
		try {
			conn.close();
			pstmt.close();
		} catch (Exception e) {
			System.out.println("DB종료시 오류가 발생 : "+e.getMessage());
		}
	}
	
	public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
		try {
			conn.close();
			pstmt.close();
			rs.close();
		} catch (Exception e) {
			System.out.println("DB종료시 오류가 발생 : "+e.getMessage());
		}
	}
}

 

다음 데이터베이스에서 값을 가져올 repository를 만든다. 데이터를 가져올 곳이 세 군데이므로 세 군데의 repository를 만든다.

 

-UserRepository.java

package com.cos.blog.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.cos.blog.db.DBConn;
import com.cos.blog.model.Users;

//싱글톤 패턴
//Dao
public class UsersRepository {
	
	private static final String TAG="UserRepository : ";
	private static UsersRepository instance=new UsersRepository();
	private UsersRepository(){}
	public static UsersRepository getInstance() {
		return instance;
	}
	
	private Connection conn=null;
	private PreparedStatement pstmt=null;
	private ResultSet rs=null;
	
	public int save(Users user) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"save : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int update(Users user) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"update : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int deleteByID(int id) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"deleteByID : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public List<Users> findAll() {
		final String SQL="";
		List<Users> users=new ArrayList<>();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//while
			return users;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	public Users findById(int id) {
		final String SQL="";
		Users user=new Users();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//if -> rs
			return user;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	
	
}

 

가입이나, 수정, 삭제의 경우 성공/실패로써 유효성을 논하게 되므로 int으로 값을 return 받아

1이면 성공, -1이면 실패로 오류를 측정하게 된다.

이 때, e.printStackTrace(); 의 경우 연쇄된 오류까지 모두 이야기하므로

이후에 추가적으로 e.getMessage()를 이용해서 정확한 오류를 찾는 것이 이후 오류 생성 시 처리하기 편해진다.

추가적으로 게시판과 덧글 기능까지 마저 제작해보자.

 

 

-BoardRepository.java

package com.cos.blog.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.cos.blog.db.DBConn;
import com.cos.blog.model.Board;
import com.cos.blog.model.Users;

//싱글톤 패턴
//Dao
public class BoardRepository {
	
	private static final String TAG="BoardRepository : ";
	private static BoardRepository instance=new BoardRepository();
	private BoardRepository(){}
	public static BoardRepository getInstance() {
		return instance;
	}
	
	private Connection conn=null;
	private PreparedStatement pstmt=null;
	private ResultSet rs=null;
	
	public int save(Board board) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"save : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int update(Board board) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"update : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int deleteByID(int id) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"deleteByID : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public List<Board> findAll() {
		final String SQL="";
		List<Board> boards=new ArrayList<>();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//while
			return boards;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	public Board findById(int id) {
		final String SQL="";
		Board user=new Board();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//if -> rs
			return user;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	
	
}

 

-ReplyResponsitory.java

package com.cos.blog.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.cos.blog.db.DBConn;
import com.cos.blog.model.Board;
import com.cos.blog.model.Reply;
import com.cos.blog.model.Users;

//싱글톤 패턴
//Dao
public class ReplyRepository {
	
	private static final String TAG="BoardRepository : ";
	private static ReplyRepository instance=new ReplyRepository();
	private ReplyRepository(){}
	public static ReplyRepository getInstance() {
		return instance;
	}
	
	private Connection conn=null;
	private PreparedStatement pstmt=null;
	private ResultSet rs=null;
	
	public int save(Reply reply) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"save : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int update(Reply reply) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"update : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public int deleteByID(int id) {
		final String SQL="";
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"deleteByID : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return -1;
	}
	
	public List<Reply> findAll() {
		final String SQL="";
		List<Reply> replys=new ArrayList<>();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//while
			return replys;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	public Reply findById(int id) {
		final String SQL="";
		Reply reply=new Reply();
		try {
			conn=DBConn.getConnection();
			pstmt = conn.prepareStatement(SQL);
			//물음표 완성하기
			
			
			//if -> rs
			return reply;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(TAG+"findAll : "+e.getMessage());
		}finally {
			DBConn.close(conn, pstmt);
		}
		
		return null;
	}
	
	
	
}

 

 

Next --

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(2) - 웹에서 데이터베이스로 값 넣기

 

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(2) - 웹에서 데이터베이스로 값 넣기

https://itstudy-mary.tistory.com/117?category=919831 Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(1) - 기본 세팅하기 앞서 만들었던 회원가입 시스템은 jsp만을 이용했다. 이런 형태를 모델1 형식이라..

itstudy-mary.tistory.com

 

반응형