2주간 프로젝트를 마치고 이어서 스프링 프레임 워크에 대해 알아보자. 처음 공부하기는 상당히 어려운 부분이 많고 특히 혼자서 이해하기가 난해한 부분이 없지 않다. 그렇지만 스프링의 핵심기술 DI, AOP, MVC를 꼭 이해하도록 하자. 이를위해 우선 스프링에 대해 전반적으로 살펴보도록 하겠다. 그리고 조금씩 심화시켜나가면서 스프링에 대해 알아갈 것이다.
기존에는 JSP를 활용한 모델 1방식으로 프로젝트를 진행해보았다. 모델 1방식은 JSP와 Java Bean을 이용하여 웹 어플리케이션을 개발하는 방법을 말한다.
모델 1방식으로 개발하면 배우기가 쉬워 누구가 쉽게 만들 수 있고 때문에 개발 속도가 향상되는 장점이 있지만 큰 문제점은 JSP에서 너무 많은 코드들이 혼재되어 있고 따라서 JSP가 처리해야하는 일이 많아진다. 따라서 개발자는 유지보수의 어려움을 겪게되는 문제가 있다.
한번 만들어진 프로젝트는 오랜시간동안 서비스를 하기위해 유지보수가 필수이다. 이 유지보수를 어렵게 만든다는 점에서 개발을 위한 새로운 방법이 필요했다.
이러한 문제점 때문에 웹 어플리케이션이 복잡해지고 사용자 요구가 증가함에 따라 새로운 개발방식을 요구하게 되는데 그것이 현재 모델 2방식이다.
모델 2방식
어플리케이션을 Model - View - Controller로 분리하여 개발하는 방식을 말한다.
Model : 비즈니스 로직을 담당하며 Java Bean과의 연동을 통해 로직을 처리한다.
View : JSP로 Client에게 응답을 처리한다. 즉, 모델 1방식에서 가장 많은 역할을 해야했던 JSP는 오로지 요청에 대한 응답 페이지의 출력을 목적으로만 사용한다.
Controller : 서블릿을 이용하여 클라이언트의 요청을 받아 Model과 View사이에서 일의 흐름을 조정한다.
모델 2방식에서는 컨트롤러의 역할이 중요하다. 때문에 컨트롤러의 역할을 살펴보자면
1. 클라이언트의 요청을 받아 클라이언트가 보낸 데이터를 읽고 검사한다.
2. 모델에게 비즈니즈 로직을 처리해달라고 요청한다.
3. 모델의 처리 결과에 맞는 뷰에게 응답을 요청한다.
그렇다면 모델 2방식의 장단점에 대해 알아보자.
장점 : 비즈니스 로직과 프레젠테이션의 분리로 인해 어플리케이션이 명료해지며 유지보수와 확장이 용이하다. 따라서 디자이너와 개발자의 작업을 분리해 줄 수 있다.
단점 : 개발을 위한 설계로 인해 개발 기간이 늘어나고 MVC 구조에 대한 이해가 동반된다.
자 이제 왜 모델 2방식을 이용한 웹 어플리케이션이 필요한지 어느정도 감이 올 것이다. 스프링은 모델 2방식인 MVC구조에 대한 프레임워크를 제공하고 있으며 나아가 다양한 프레임워크와 연동을 지원하기 때문에 많은 개발자들이 배우고 있는 프레임워크이다.
그렇다면 프레임워크는 무엇이며 라이브러리와는 어떤 차이가 있을까?
라이브러리는 개발자가 원하는 목적을 위해 사용되는 API들의 묶음으로 개발자가 자신에게 필요한 것을 스스로 설정하면서 프로그램을 구현해나갈 수 있는 유용한 자료이다. 프레임 워크는 개발에 있어서 어느정도의 틀을 미리 제공하고 있다. 따라서 개발자가 처음부터 모든 것을 구현할 필요가 없다. 어느정도의 프로세스가 이미 정해져있다는 것이다.
개발자에게 있어서 프레임워크는 어떤 존재인지 생각해보자. 지금처럼 대규모의 프로젝트가 산적해있는 상황에서는 개발의 속도가 필요하다. 그렇기 때문에 하나하나씩 모든 것을 구현해 나가며 단독으로 프로젝트를 진행하는 것은 의미가 없다. 빠르게 많은 코드를 제작해 나가야 함에 있어서 프레임워크가 필수적이고 개발자마다 다른 코드 스타일을 적응해가면서 개발하는 것도 쉽지 않다. 하지만 이렇게 정해진 틀이 제공된다면 대규모 프로젝트를 진행하는데 도움이 될 것이라는 것은 당연하다.
현재 웹 어플리케이션 제작에 있어서 가장 많이 사용되는 프레임워크가 스프링이다.
스프링이란 오픈 소스 프레임워크로써 엔터프라이즈 어플리케이션 개발의 복잡성을 줄여주고 필요한 기능을 제공하기 위한 목적으로 만들어졌다. 특히 과거에 많이 사용되던 EJB의 복잡성과 느린 속도를 대처하기 위해 등장하였다.
스프링 장점
- 경향 컨테이너로써 객체의 라이프 사이클을 관리, JEE구현을 위한 다양한 API제공
- DI 지원, 설정 파일이나 어노테이션을 통해서 객체 간의 의존 관계를 설정
- AOP지원, 트랜잭션이나 로깅, 보안과 같은 공통으로 필요한 기능들을 분리해서 원하는 모듈에 적용
- POJO지원, 특정한 인터페이스를 구현하거나 클래스를 상속받지 않아 기존에 작성한 코드를 그대로 사용
- JDBC를 위한 다양한 API지원
- Transaction 처리를 위한 일관된 방법제공
- 다양한 API와의 연동 지원
장점을 보면 DI나 AOP 등등 처음 보는 개념을 많을텐데 하나씩 알아가도록하자. 개발자를 위해서 제공되는 아주 좋은 기술이다!
2013년 4월 8일 월요일
2013년 3월 18일 월요일
[JSP] 게시판 만들기!
게시판을 배워보는 것은 프로그래밍의 필수적인 요소를 모두 익힐 수 있는 좋은 과정이다.
그 이유는 게시물을 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete) 하면서 데이터의 흐름을 이해하고 어떻게 데이터를 전달하고 저장하는지에 대해 전반적으로 알아갈 수 있기 때문이다. 프로그래밍 실력을 키울 수 있는 좋은 예인 것이다.
제작할 게시판에는 다음과 같은 기능을 추가할 것이다.
1. 답글
2. 페이지 처리
3. 검색
4. 파일 업/다운
5. 이미지 게시판
지금까지 배운 JSP를 위주로 구현해 나갈 것이며 EL, JSTL태그도 많이 사용할 것이다.
코드를 위주로 알아보자.
우선 게시판을 위한 DB 테이블이 필요하다.
create table board(
b_id number(5) primary key,
b_name varchar2(20),
b_title varchar2(50),
b_content varchar2(3000),
b_pwd varchar2(10),
b_date date,
b_hit number(5) default 0,
b_ref number(5),
b_step number(5),
b_level number(5),
b_parentid number(5)
)
보통 게시판에 글을 올릴 때 필요한 데이터를 확인할 수 있다. 그러나 ref, step, level, parent라는 컬럼에 대해서는 의아할 것이다. 이 컬럼들은 해당하는 글의 답글을 달기 위해 필요한 요소이다.
ref : 부모의 그룹번호
step : 부모의 글을 기준으로 순서 결정
level : 답글을 나타내는 들여쓰기를 위한 속성
parentid : 부모의 글 번호
다음으로 게시판에 삽입될 하나의 글 객체를 위한 클래스이다.
public class Board {
private int b_id;
private String b_name;
private String b_title;
private String b_content;
private String b_pwd;
private Timestamp b_date;
private int b_hit;
private int b_ref;
private int b_step;
private int b_level;
private int b_parentid;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
글 하나를 게시판에 삽입할 Dao클래스
//////////////////////////////////////////////////////////////////////////////////////////////////
public class BoardDao {
private static BoardDao dao = new BoardDao();
public static BoardDao getInstance() {
return dao;
}
public Connection getConnection() throws Exception {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/oracle");
return ds.getConnection();
}
public int insertBoard(Board board) {
int re = -1;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";
int number = 0;// 글번호를 저장
int b_id = board.getB_id();
int b_ref = board.getB_ref();
int b_step = board.getB_step();
int b_level = board.getB_level();
int b_parentid = board.getB_parentid();
try {
con = getConnection();
// 글번호를 미리 생성
sql = "select max(b_id) from board";
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
if (rs.next()) {
number = rs.getInt(1) + 1;// 현재 작성한 글번호를 이전에 작성한 글에 +1을 해서 구한다
}
// 답변글일 때
if (b_id != 0) {
sql = "update board set b_step = b_step + 1 where b_ref = ? AND b_step > ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, b_ref);
pstmt.setInt(2, b_step);
pstmt.executeUpdate();
b_step = b_step + 1;// 나의 b_step
b_level = b_level + 1;// 나의 b_level
b_parentid = b_id;// 나의 b_parentid
} else {
// 원본글일 때
b_ref = number;
b_step = 0;
b_level = 0;
b_parentid = 0;
}
sql = "insert into board values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, number);
pstmt.setString(2, board.getB_name());
pstmt.setString(3, board.getB_title());
pstmt.setString(4, board.getB_content());
pstmt.setString(5, board.getB_pwd());
pstmt.setTimestamp(6, board.getB_date());
pstmt.setInt(7, board.getB_hit());
pstmt.setInt(8, b_ref);
pstmt.setInt(9, b_step);
pstmt.setInt(10, b_level);
pstmt.setInt(11, b_parentid);
re = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return re;
}
게시물 등록 메서드이다. 나머지는 조금씩의 수정이 필요.
[JSP] 필터
필터는 JSP/서블릿 등을 실행하기 이전에 요청이 올바른지 또는 자원에 접근할 수 있는 권한을 가졌는지의 여부를 미리 처리할 수 있도록 해주며, JSP나 서블릿이 생성한 응답 데이터를 변경하거나 취소할 수 있는 기능을 구현할 수 있도록 해준다.
2013년 3월 16일 토요일
[JSP] 쿠키와 세션
http은 웹 상에서 html화면을 브라우저로 보여주는 기능에 최적화 되어 있는 프로토콜이다. 이 프로토콜 덕분에 브라우저를 이용하여 인터넷을 사용하는데 전혀 무리가 없는 것이다.
그런데 이 프로토콜에 한가지 맹점이 있다. 그것은 웹 서버에서 사용자를 식별하거나 접속을 유지하고 있다는 사실을 인지하지 못하는 것이다.
이러한 문제점을 해결하기 위해 쿠키와 세션을 사용한다. 쿠키를 활용하면 클라이언트가 웹 서버에 요청할 때 쿠키를 함께 전달하여 서버가 사용자의 정보를 읽어올 수 있으며 서버에 세션을 활용하여 사용자의 접속상태를 확인해 줄 수 있다.
우선 쿠키에 대해 알아보자.
쿠키
- 웹 브라우저가 보관하고 있는 데이터로서, 웹 브라우저가 웹 서버에 요청을 보낼 때 쿠키를 함께 전송한다.
쿠키의 구성
이름 - 쿠쿠를 구별하는데 사용되는 이름
값 - 쿠키의 이름으로 얻을 수 있는 데이터
유효 시간 - 쿠키의 유지 시간
도메인 - 쿠키를 전송할 도메인
경로 - 쿠키를 전송할 요청 경로
쿠키 생성 후 전달
Cookie cookie = new Cookie("cookieName", "cookieValue");
response.addCookie(cookie);
쿠키 값 읽어오기
Cookie[] cookies = request.getCookie();
request 객체를 통하여 쿠키배열을 얻을 수 있다. 전송된 쿠키를 활용하기 전 항상 null인지 확인하도록 하자.
쿠키 값 변경
Cookie cookie = new Cookie("기존의 이름", "새로운 값");
쿠키 삭제 및 유효시간 설정
cookie.setMaxAge(0);//삭제
cookie.setMaxAge(60*60);//1시간 설정
도메인 설정
cookie.setDomain(".somehost.com"); www.somehost.com이나 mail.somehost.com과 같은 모든 호스트로 쿠키 전송
경로 설정
cookie.setPath("원하는 경로");
세션
- 세션은 웹 브라우저에 정보를 웹 컨테이너에 보관할 때 사용된다. 즉, 서버에서만 생성된다. 세션은 웹 브라우저마다 따로 존재하기 때문에 웹 브라우저와 관련된 1 대 1 정보를 저장하기에 알맞은 장소다. 또한 쿠키보다는 세션을 더 많이 사용하는데 가장 큰 이유는 보안 때문이다. 쿠키의 경우 웹 브라우저로부터 데이터를 전달시 중간에서 누군가에 의해 쿠키의 값을 읽을 수 있다. 하지만 세션은 서버에 데이터를 저장하기 때문에 그러한 문제점이 없다.
JSP에서는 session이 보통 내장 객체로 제공되기 때문에 쉽게 사용할 수 있다.
session 메서드
getId() : 세션의 고유 ID를 얻음
getCreationTime() : 세션이 생성된 시간을 구함
getLastAccessedTime() : 웹 브라우저가 가장 마지막에 세션을 접근한 시간
session.setAttribute("이름", "값");//세션에 이름으로 값을 저장
session.getAttribute("이름");//세션에서 이름이르 값을 얻음
session.invalidate();//세션 종료
session.setMaxInactiveInterval(60*60);//세션의 유효 시간을 1시간으로 설정(default로 30분)
그런데 이 프로토콜에 한가지 맹점이 있다. 그것은 웹 서버에서 사용자를 식별하거나 접속을 유지하고 있다는 사실을 인지하지 못하는 것이다.
이러한 문제점을 해결하기 위해 쿠키와 세션을 사용한다. 쿠키를 활용하면 클라이언트가 웹 서버에 요청할 때 쿠키를 함께 전달하여 서버가 사용자의 정보를 읽어올 수 있으며 서버에 세션을 활용하여 사용자의 접속상태를 확인해 줄 수 있다.
우선 쿠키에 대해 알아보자.
쿠키
- 웹 브라우저가 보관하고 있는 데이터로서, 웹 브라우저가 웹 서버에 요청을 보낼 때 쿠키를 함께 전송한다.
쿠키의 구성
이름 - 쿠쿠를 구별하는데 사용되는 이름
값 - 쿠키의 이름으로 얻을 수 있는 데이터
유효 시간 - 쿠키의 유지 시간
도메인 - 쿠키를 전송할 도메인
경로 - 쿠키를 전송할 요청 경로
쿠키 생성 후 전달
Cookie cookie = new Cookie("cookieName", "cookieValue");
response.addCookie(cookie);
쿠키 값 읽어오기
Cookie[] cookies = request.getCookie();
request 객체를 통하여 쿠키배열을 얻을 수 있다. 전송된 쿠키를 활용하기 전 항상 null인지 확인하도록 하자.
쿠키 값 변경
Cookie cookie = new Cookie("기존의 이름", "새로운 값");
쿠키 삭제 및 유효시간 설정
cookie.setMaxAge(0);//삭제
cookie.setMaxAge(60*60);//1시간 설정
도메인 설정
cookie.setDomain(".somehost.com"); www.somehost.com이나 mail.somehost.com과 같은 모든 호스트로 쿠키 전송
경로 설정
cookie.setPath("원하는 경로");
세션
- 세션은 웹 브라우저에 정보를 웹 컨테이너에 보관할 때 사용된다. 즉, 서버에서만 생성된다. 세션은 웹 브라우저마다 따로 존재하기 때문에 웹 브라우저와 관련된 1 대 1 정보를 저장하기에 알맞은 장소다. 또한 쿠키보다는 세션을 더 많이 사용하는데 가장 큰 이유는 보안 때문이다. 쿠키의 경우 웹 브라우저로부터 데이터를 전달시 중간에서 누군가에 의해 쿠키의 값을 읽을 수 있다. 하지만 세션은 서버에 데이터를 저장하기 때문에 그러한 문제점이 없다.
JSP에서는 session이 보통 내장 객체로 제공되기 때문에 쉽게 사용할 수 있다.
session 메서드
getId() : 세션의 고유 ID를 얻음
getCreationTime() : 세션이 생성된 시간을 구함
getLastAccessedTime() : 웹 브라우저가 가장 마지막에 세션을 접근한 시간
session.setAttribute("이름", "값");//세션에 이름으로 값을 저장
session.getAttribute("이름");//세션에서 이름이르 값을 얻음
session.invalidate();//세션 종료
session.setMaxInactiveInterval(60*60);//세션의 유효 시간을 1시간으로 설정(default로 30분)
2013년 3월 14일 목요일
[JSP] JSTL
JSTL은 유용한 커스텀 액션을 포함하고 있는 라이브러리이며, 이 라이브러리를 통한 액션 태그를 사용하여 JSP에 스크립틀릿과 같은 자바코드를 줄일 수 있다.
JSTL을 가지고 변수를 선언하고 if문, for문 등의 간단한 로직을 구현할 수 있으며 다른 JSP페이지를 호출하고 날짜, 시간, 숫자의 포맷을 변경할 수도 있다.
JSTL을 구성하는 라이브러리들이 몇몇 존재하는데 여기서는 코어와 포메팅 라이브러리에 대해 알아보도록하자. 우선 JSTL을 jakarta.apache.org에 접속하여 라이브러리를 받도록하자. 내려받은 파일은 톰켓에 lib폴더에 넣어주자. 그리고 taglib 지시자로 태그를 사용할 수 있도록 설정해야한다.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
이렇게하여 커스텀 액션 태그가 추가되었다. 그럼 커스텀 태그의 사용에 대해 알아보자.
<c:set>
- 변수를 선언하고 변수에 초기값을 대입하는 기능의 커스텀 액션
예) <c:set var="result" value="100"></c:set>
또는 <c:set var="result" value="${num}></c:set>처럼 EL문을 사용할 수도 있다. 또한 이 태그의 속성값인 scope를 통해 네 가지의 내장객체에 어트리뷰트를 저장하는 것이 가능하다는 것을 잘 알고 있도록 하자.
<c:if>
- 프로그램의 if문과 비슷한 역할
예) <c:if test="${num1>num2}">
이렇게함으로써 num1과 num2의 조건관계를 알아볼 수 있다.
<c:choose>
- 프로그램에서 switch의 역할과 비슷하다.
예)
<c:chooes>
<c:when test="${num==0}">
Hello JSP<br>
</c:when>
<c:otherwise>
Bye<br>
</c:otherwise>
<c:forEach>
- 프로그램의 for문
예 1.) <c:forEach begin="0" end="10">
Hello JSP<br>
</c:forEach>
기본적으로 0부터 10까지 증가가 1씩되면서 Hello JSP를 10번 출력한다. 증가의 수를 변경하고 싶다면 속성 step에 수를 입력하면 된다.(step="2")
예 2.) <c:forEach var="i" items="${arr}">
${i}<br>
</c:forEach>
데이터를 여러개 담고 있는 컬렉션을 하나씩 돌려 저장된 객체를 리턴시켜 줄 수 있다.
그 종류는 배열뿐만 컬렉션 아니라 arraylist, map, iterator, enumeration객체들과 콤마로 구분된 항목을의 문자열을 의미한다.
<c:forTokens>
- 자바의 StringTokenizer와 for문이 합쳐진 것과 같다.
예) <c:set var="guests" value="토끼^^거북아~사슴"/>
<c:forTokens var="animal" items="${guests}" delims="^~">
${animal}<br>
</c:forTokens>
<c:redirect>
-response.senRedirect()와 같다
예) <c:redirect url="http://~~"/>
JSTL을 가지고 변수를 선언하고 if문, for문 등의 간단한 로직을 구현할 수 있으며 다른 JSP페이지를 호출하고 날짜, 시간, 숫자의 포맷을 변경할 수도 있다.
JSTL을 구성하는 라이브러리들이 몇몇 존재하는데 여기서는 코어와 포메팅 라이브러리에 대해 알아보도록하자. 우선 JSTL을 jakarta.apache.org에 접속하여 라이브러리를 받도록하자. 내려받은 파일은 톰켓에 lib폴더에 넣어주자. 그리고 taglib 지시자로 태그를 사용할 수 있도록 설정해야한다.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
이렇게하여 커스텀 액션 태그가 추가되었다. 그럼 커스텀 태그의 사용에 대해 알아보자.
<c:set>
- 변수를 선언하고 변수에 초기값을 대입하는 기능의 커스텀 액션
예) <c:set var="result" value="100"></c:set>
또는 <c:set var="result" value="${num}></c:set>처럼 EL문을 사용할 수도 있다. 또한 이 태그의 속성값인 scope를 통해 네 가지의 내장객체에 어트리뷰트를 저장하는 것이 가능하다는 것을 잘 알고 있도록 하자.
<c:if>
- 프로그램의 if문과 비슷한 역할
예) <c:if test="${num1>num2}">
이렇게함으로써 num1과 num2의 조건관계를 알아볼 수 있다.
<c:choose>
- 프로그램에서 switch의 역할과 비슷하다.
예)
<c:chooes>
<c:when test="${num==0}">
Hello JSP<br>
</c:when>
<c:otherwise>
Bye<br>
</c:otherwise>
<c:forEach>
- 프로그램의 for문
예 1.) <c:forEach begin="0" end="10">
Hello JSP<br>
</c:forEach>
기본적으로 0부터 10까지 증가가 1씩되면서 Hello JSP를 10번 출력한다. 증가의 수를 변경하고 싶다면 속성 step에 수를 입력하면 된다.(step="2")
예 2.) <c:forEach var="i" items="${arr}">
${i}<br>
</c:forEach>
데이터를 여러개 담고 있는 컬렉션을 하나씩 돌려 저장된 객체를 리턴시켜 줄 수 있다.
그 종류는 배열뿐만 컬렉션 아니라 arraylist, map, iterator, enumeration객체들과 콤마로 구분된 항목을의 문자열을 의미한다.
<c:forTokens>
- 자바의 StringTokenizer와 for문이 합쳐진 것과 같다.
예) <c:set var="guests" value="토끼^^거북아~사슴"/>
<c:forTokens var="animal" items="${guests}" delims="^~">
${animal}<br>
</c:forTokens>
<c:redirect>
-response.senRedirect()와 같다
예) <c:redirect url="http://~~"/>
[JSP] EL(Expression Language)
JSP를 이용하고 코딩을 할 때 불편함이 있는데 그것은 자바코드와 HTML코드, 거기다 스크립트코드가 모두 혼합해서 사용될 때 너무 지저분해 보이는 것이다.
JSP에는 자바코드를 줄이고 데이터를 출력하는데 좀 더 간결한 익스프레션 언어(EL)를 제공한다. 익스프레션 언어는 다음과 같이 사용한다.
예) ${cnt};
JSP의 익스프레션과는 구별해야한다. EL에서는 어트리뷰트 이름을 이용하여 값을 출력한다. 그러므로 setAttribute()와 getAttribute()를 통해 데이터를 저장하고 얻었던 작업을 줄여서 나타낼 수 있다.
예를 들어 request.setAttribute("result", 100) 이라고 request객체에 "result"라는 이름으로 100이라는 데이터를 저장하였다. 그렇다면 이 데이터를 얻기 위해서 request의 getAttribute()메서드를 호출하여 얻어야 하지만 EL에선 ${result}로 데이터를 손쉽게 얻을 수 있다.
JSP의 내장 객체 중 scope의 범위에 따른 네 가지 종류의 객체를 살펴보았다.
page, request, session, application 이 그것이다.
이들 모두 set(), get()메서드를 이용하여 어트리뷰트에 데이터를 저장할 수 있기 때문에 당연히 EL을 통해 데이터의 출력이 가능하다.
그렇다면 이들 네 가지 객체 어떻게 EL구문 만으로 데이터를 읽어 들일 수 있을까?
그 이유는 page -> request -> session -> application 순으로 어트리뷰트를 찾아가기 때문이다.
이런 이유로 좀더 명확한 내장 객체의 어트리뷰트를 표현하기 위하여 다음과 같이 사용하기도 한다.
예) ${pageScope.result}
page내장 객체의 어트리뷰트에 result로 저장되어 있는 데이터를 출력하라는 EL구문이 되겠다.
이 네가지 내장 객체뿐만 아니라 더많은 객체가 존재하여 EL구문을 활용할 수 있다.
pageScope : page 어트리뷰트의 집합
requestScope : request 어트리뷰트의 집합
sessionScope : session 어트리뷰트의 집합
applicationScope : application 어트리뷰트의 집합
param : 웹 브라우저로부터 입력된 데이터의 집합(예 ${param.result})
paramValues : 웹 브라우저로부터 입력된 여러 데이터의 집합(예 ${paramValues.result[0]})
header : HTTP요청 메세지에 있는 HTTP헤더의 집합(사용법은 param과 같다)
headerValues : HTTP요청 메세지에 있는 여러 HTTP헤더의 집합(사용법은 paramValues와 같다)
cookie : 웹 브라우저로부터 전송된 쿠키의 집합(예 cookie.result.value)
initParam : 웹 어플리케이션의 초기화 파라미터의 집합
pageContext : JSP페이지의 환경 정보의 집합
EL은 연산과 비교조건이 가능하다. 일반적인 프로그래밍 문법과 비슷하기 때문에 설명은 생략하기로 하고 Empty 연산자를 알아보자.
${empty result}라고 사용하면 result이름으로 데이터 값이 존재하는지 유무를 확인할 수 있다. 리턴형은 Boolean이다.
JSP에는 자바코드를 줄이고 데이터를 출력하는데 좀 더 간결한 익스프레션 언어(EL)를 제공한다. 익스프레션 언어는 다음과 같이 사용한다.
예) ${cnt};
JSP의 익스프레션과는 구별해야한다. EL에서는 어트리뷰트 이름을 이용하여 값을 출력한다. 그러므로 setAttribute()와 getAttribute()를 통해 데이터를 저장하고 얻었던 작업을 줄여서 나타낼 수 있다.
예를 들어 request.setAttribute("result", 100) 이라고 request객체에 "result"라는 이름으로 100이라는 데이터를 저장하였다. 그렇다면 이 데이터를 얻기 위해서 request의 getAttribute()메서드를 호출하여 얻어야 하지만 EL에선 ${result}로 데이터를 손쉽게 얻을 수 있다.
JSP의 내장 객체 중 scope의 범위에 따른 네 가지 종류의 객체를 살펴보았다.
page, request, session, application 이 그것이다.
이들 모두 set(), get()메서드를 이용하여 어트리뷰트에 데이터를 저장할 수 있기 때문에 당연히 EL을 통해 데이터의 출력이 가능하다.
그렇다면 이들 네 가지 객체 어떻게 EL구문 만으로 데이터를 읽어 들일 수 있을까?
그 이유는 page -> request -> session -> application 순으로 어트리뷰트를 찾아가기 때문이다.
이런 이유로 좀더 명확한 내장 객체의 어트리뷰트를 표현하기 위하여 다음과 같이 사용하기도 한다.
예) ${pageScope.result}
page내장 객체의 어트리뷰트에 result로 저장되어 있는 데이터를 출력하라는 EL구문이 되겠다.
이 네가지 내장 객체뿐만 아니라 더많은 객체가 존재하여 EL구문을 활용할 수 있다.
pageScope : page 어트리뷰트의 집합
requestScope : request 어트리뷰트의 집합
sessionScope : session 어트리뷰트의 집합
applicationScope : application 어트리뷰트의 집합
param : 웹 브라우저로부터 입력된 데이터의 집합(예 ${param.result})
paramValues : 웹 브라우저로부터 입력된 여러 데이터의 집합(예 ${paramValues.result[0]})
header : HTTP요청 메세지에 있는 HTTP헤더의 집합(사용법은 param과 같다)
headerValues : HTTP요청 메세지에 있는 여러 HTTP헤더의 집합(사용법은 paramValues와 같다)
cookie : 웹 브라우저로부터 전송된 쿠키의 집합(예 cookie.result.value)
initParam : 웹 어플리케이션의 초기화 파라미터의 집합
pageContext : JSP페이지의 환경 정보의 집합
EL은 연산과 비교조건이 가능하다. 일반적인 프로그래밍 문법과 비슷하기 때문에 설명은 생략하기로 하고 Empty 연산자를 알아보자.
${empty result}라고 사용하면 result이름으로 데이터 값이 존재하는지 유무를 확인할 수 있다. 리턴형은 Boolean이다.
2013년 3월 13일 수요일
[JSP] JDBC
지금까지는 쿠키와 세션을 이용하여 사용자의 데이터를 저장하고 접속상태를 확인해 보았다. 그러나 많은 데이터나 지속적으로 보관되어야 할 데이터는 궁극적으로 데이터베이스에 저장 되어야 할 것이다.
JSP를 이용하여 데이터베이스와의 연동을 하기 위한 과정을 살펴 보도록하자.
1. JDBC 드라이버 준비
JDBC 드라이버(ojdbc14.jar)를 톰캣에 lib폴더에 복사하자. 오라클이 설치되어 있는 폴더 안에 ojdbc14.jar파일이 있다. jar이란 확장명을 보면 알 수 있듯이 자바와의 연동을 위한 드라이버이다.
2. 드라이버 로드
JSP에서 Class.forName("oracle.jdbc.driver.OracleDriver") 으로 오라클 데이터베이스의 가상드라이버를 로드한다. 그래야 오라클 데이터베이스와 연동할 API를 사용할 수 있다. MySql과 MS SQL 서버는 다음과 같다.
MySql - com.mysql.jdbc.Driver
MS SQL 서버 - com.microsoft.sqlserver.jdbc.SQLServerDriver
3. 데이터베이스 연결
데이터베이스와의 연결을 위해서 Connection이라는 객체가 필요하다. 이 객체를 구하기 위해 3가지 준비물이 필요하다.
- url
- 사용자 계정
- 패스워드
url은 데이터베이스를 구분하기 위해 사용한다. 오라클에서는 다음과 같은 url을 가진다.
jdbc:oracle:thin:@HOST:PORT:SID
위에서 thin이 의미하는 바는 자바언어로 구현되어 있다는 의미이고 OCI일 경우도 있는데 이는 네이티브 모듈을 사용한다.
사용자 계정과 패스워드는 자신이 사용하고 있는 DBMS의 계정와 패스워드를 의미한다.
4. Connection객체 얻기
위에 세 가지의 정보로 Connection 객체를 얻을 수 있는데 DriverManager클래스가 제공하는 getConnection()메서드를 사용한다.
DriverManager.getConnection(String url, Stirng uesr, String password)
5. Statement를 사용한 쿼리 실행
Connection 객체로 Statement 객체를 생성하고 쿼리 질의를 할 수 있다. 그러나 여기서는 PrepareStatment를 사용한다. 그 이유는 둘다 성능의 차이는 없으나 PrepareStatment는 sql문의 틀을 미리 생성해 놓고 값은 나중에 지정한다는 것이다.또한 sql문에 ?부분을 setString(index, 원하는값)으로 치환할 수 있는 장점이 있다.
PrepareStatement pstmt = connection.createStatement();
Preparestatement를 사용하여 쿼리를 실행 할 수 있는데 select 질의를 할 경우 리턴값은 테이블의 로우들이기 때문에 ResultSet 객체로 받아야한다.
ResultSet result = pstmt.executeQuery(String sql);
또는 insert와 update, delete와 같은 테이블 구조변경 질의를 실행하면 그 결과로 -1, 0 ,1을 전달하는데 -1일 경우는 쿼리문 실패, 0일 경우는 쿼리문에 오류는 없으나 DB의 변경이 없음, 1은 성공을 의미한다. 코드는 다음과 같다.
int result = pstmt.executeUpdate(String sql);
6. ResultSet 객체 사용
쿼리문 질의를 통해 얻은 결과로 ResultSet 객체를 얻을 경우. 하나의 row(튜플)을 검색하기 위해 next()메서드를 사용하면 된다. 하나의 로우만을 출력하기 위해서 if(rs.next())로 처리하고 많은 양의 로우를 처리하기 위해서 while(rs.next())로 처리해주어야 한다.
간단한 예로 데이터베이스에 id와 password를 입력하는 메서드를 살펴보자.
public int insertMember(Register register){
Connection con = null;
PreparedStatement pstmt = null;
String sql = "insert into Member values(?,?)";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "hr";
String password = "1234";
int check = -1;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(url, user, password);
pstmt = con.prepareStatement(sql);
pstmt.setString(1, register.getId());
pstmt.setString(2, register.getPass());
check = pstmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(Exception e){
e.printStackTrace();
}
}
if(con != null){
try{
con.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
return check;
}
이 방법이 가장 기본적인 DB와의 연결이다. 그러나 매번 데이터베이스와의 연동을 위해 해야하는 코딩이 제법 많은 편이다.
JSP를 이용하여 데이터베이스와의 연동을 하기 위한 과정을 살펴 보도록하자.
1. JDBC 드라이버 준비
JDBC 드라이버(ojdbc14.jar)를 톰캣에 lib폴더에 복사하자. 오라클이 설치되어 있는 폴더 안에 ojdbc14.jar파일이 있다. jar이란 확장명을 보면 알 수 있듯이 자바와의 연동을 위한 드라이버이다.
2. 드라이버 로드
JSP에서 Class.forName("oracle.jdbc.driver.OracleDriver") 으로 오라클 데이터베이스의 가상드라이버를 로드한다. 그래야 오라클 데이터베이스와 연동할 API를 사용할 수 있다. MySql과 MS SQL 서버는 다음과 같다.
MySql - com.mysql.jdbc.Driver
MS SQL 서버 - com.microsoft.sqlserver.jdbc.SQLServerDriver
3. 데이터베이스 연결
데이터베이스와의 연결을 위해서 Connection이라는 객체가 필요하다. 이 객체를 구하기 위해 3가지 준비물이 필요하다.
- url
- 사용자 계정
- 패스워드
url은 데이터베이스를 구분하기 위해 사용한다. 오라클에서는 다음과 같은 url을 가진다.
jdbc:oracle:thin:@HOST:PORT:SID
위에서 thin이 의미하는 바는 자바언어로 구현되어 있다는 의미이고 OCI일 경우도 있는데 이는 네이티브 모듈을 사용한다.
사용자 계정과 패스워드는 자신이 사용하고 있는 DBMS의 계정와 패스워드를 의미한다.
4. Connection객체 얻기
위에 세 가지의 정보로 Connection 객체를 얻을 수 있는데 DriverManager클래스가 제공하는 getConnection()메서드를 사용한다.
DriverManager.getConnection(String url, Stirng uesr, String password)
5. Statement를 사용한 쿼리 실행
Connection 객체로 Statement 객체를 생성하고 쿼리 질의를 할 수 있다. 그러나 여기서는 PrepareStatment를 사용한다. 그 이유는 둘다 성능의 차이는 없으나 PrepareStatment는 sql문의 틀을 미리 생성해 놓고 값은 나중에 지정한다는 것이다.또한 sql문에 ?부분을 setString(index, 원하는값)으로 치환할 수 있는 장점이 있다.
PrepareStatement pstmt = connection.createStatement();
Preparestatement를 사용하여 쿼리를 실행 할 수 있는데 select 질의를 할 경우 리턴값은 테이블의 로우들이기 때문에 ResultSet 객체로 받아야한다.
ResultSet result = pstmt.executeQuery(String sql);
또는 insert와 update, delete와 같은 테이블 구조변경 질의를 실행하면 그 결과로 -1, 0 ,1을 전달하는데 -1일 경우는 쿼리문 실패, 0일 경우는 쿼리문에 오류는 없으나 DB의 변경이 없음, 1은 성공을 의미한다. 코드는 다음과 같다.
int result = pstmt.executeUpdate(String sql);
6. ResultSet 객체 사용
쿼리문 질의를 통해 얻은 결과로 ResultSet 객체를 얻을 경우. 하나의 row(튜플)을 검색하기 위해 next()메서드를 사용하면 된다. 하나의 로우만을 출력하기 위해서 if(rs.next())로 처리하고 많은 양의 로우를 처리하기 위해서 while(rs.next())로 처리해주어야 한다.
간단한 예로 데이터베이스에 id와 password를 입력하는 메서드를 살펴보자.
public int insertMember(Register register){
Connection con = null;
PreparedStatement pstmt = null;
String sql = "insert into Member values(?,?)";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "hr";
String password = "1234";
int check = -1;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(url, user, password);
pstmt = con.prepareStatement(sql);
pstmt.setString(1, register.getId());
pstmt.setString(2, register.getPass());
check = pstmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(Exception e){
e.printStackTrace();
}
}
if(con != null){
try{
con.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
return check;
}
이 방법이 가장 기본적인 DB와의 연결이다. 그러나 매번 데이터베이스와의 연동을 위해 해야하는 코딩이 제법 많은 편이다.
피드 구독하기:
글 (Atom)