2010년 7월 30일 금요일

Spring에서 파일을 포함한 Form 을 전송하고 업로드 하기


1. 먼저 form 태그에 다음의 프로퍼티를 추가한다.

 

enctype="multipart/form-data"

인코딩 타입이 Multipart 인 경우 파라미터나 업로드한 파일을 구할려면 전송 데이터를 알맞게 처리해 주어야 한다. 스프링은 Multipart 지원 기능을 제공하고 있기 때문에, 이 기능을 이용하면 추가적인 처리 없이 Multipart 형식으로 전송된 파라미터와 파일 정보를 쉽게 구할 수 있다.

 

2. MultipartResolver 설정

 

<bean id="multipartResolver"

 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

</bean>

Multipart 지원 기능을 사용하려면 먼저 MultipartResolver를 스프링 설정파일에 등록해 주어야 한다. MultipartResolever 는 Multipart 형식으로 데이터가 전송된 경우, 해당 데이터를 스프링 MVC 에서 사용할 수 있도록 변환해준다.

 

라이브러리에 다음을 추가한다.

 

commons-fileupload / commons-fileupload

commons-io            / commons-io            <- 1.4 version

 

2.1. MultipartResolver의 Property

 Property  Type  Descript
 maxUploadSize  long  최대 업로드 가능한 바이트 크기. -1 은 체한이 없음을 의미한다, Default 는 -1
 maxInMemorySize  int  디스크에 임시 파일을 생성하기 전에 메모리에 보관할 수 있는 최대 바이트 크기, 기본값은 10240 바이트이다.
 defaultEncoding  String  요청을 파싱할 때 사용할 캐릭터 인코딩. 지정하지 않을 경우 HttpServletRequest.setCharacterEncoding() 메서드로 지정한 캐릭터 셋이 사용된다. 아무 값도 없을 경우 ISO-8859-1을 사용한다.

 

 

3. Controller 에서 데이터 받아오기.

 

컨트롤러의 파라미터에 값을 받아 넣을 때 다음의 소스를 입력한다.

@RequestParam("[inputName]") MultipartFile [paramName]

 

다음은 MultipartFile 인터페이스가 제공하는 주요 메서드 이다.

 

 Method  Descript
 String    getName()  파라미터의 이름을 구한다.
 String    getOriginalFilename()  업로드 한 파일의 이름을 구한다.
 boolean isEmpty()  업로드 한 파일이 존재하지 않는 경우 true를 리턴한다.
 long      getSize()  업로드 한 파일의 크기를 구한다.
 byte[]   getBytes() throws IOException  업로드 한 파일의 데이터를 구한다.
 InputStream getInputStream() throws IOException

 업로드 한 파일 데이터를 읽어오는 InputStream을 구한다,

 InputStream의 사용이 끝나면 알맞게 종료해 주어야 한다.

 void      transferTo(File dest) throws IOException  업로드 한 파일 데이터를 지정한 파일에 저장한다.

 

if (multipartFile.isEmpty)) {

//업로드 한 파일데이터를 구하는 가장 단순한 방법은 MultipartFile.getBytes() 메서드를 이용하는 것이다. 바이트 배열을 구한 뒤에 파일이나 DB 등에 저장하면 된다.

   byte[] fileData = multipartFile.getByte();

   ...

}

 

if (multipartFile.isEmpty)) {

//업로드 한 파일 데이터를 특정 파일로 저장하고 싶다면 MultipartFile.transferTo() 메서드를 사용하는 것이 편리하다.

   File file = new File(fileName);

   multipartFile.transferto(file);

   ...

}

 

 

 

Validation Check

Validation Check 는 Data의 검증을 뜻한다.

 

Validation Check의 방법에는 크게 3가지 가 있는데

 

    1. Client-Side VC : UI에서 JS를 이용해 체크한다.
    2. Server-Side VC : Java 에서 체크한다.
    3. Database Constraint VC : Key, check, Default 등으로 체크 한다.

위 세가지중 하나라도 배제한다면 잘못된 프로그래밍 습관을 가진것이다.

2010년 7월 29일 목요일

Integer 타입에서 자주 쓰는 API

1. 숫자를 문자로 변환하기.

입력되거나 변수에서 초기화 또는 대입된 숫자를 문자로 바꿀 수 있다.

  1. 문자변수 = Integer.toString(숫자 또는 숫자변수) // 숫자 또는 숫자변수를 문자변수에 형을 변환해서 저장한다.

Spring 타입에서 자주 쓰는 API

1. String 을 숫자로 변환하기.

int num = Integer.parseInt(문자);

 

숫자를 문자로 변환하거나, nextLine() 으로 입력받은 문자를 숫자로 변환하고자 할때 사용된다.

즉, 문자 부분에 들어갈 수 있는 것은 두가지가 있다.

순수한 문자열 또는 Scanner 가 있다.

 

2. 문자열 비교하기.

Scanner 로 입력받은 문자열은 단순한 문자열로는 비교할 수 없다.

하여 Scanner 로 입력받은  문자열은 String 타입의 특정 메서드를 사용하는데

종류는 크게 3가지가 있다.

  1. String.compareTo(문자)  // 문자와 문자사이에 존재하는 문자의 개수를 리턴한다. 즉, 반환값이 0이라면 같은 문자열이다.

  2. String.equals(문자) // 문자와 문자를 순수히 비교한다. 같다면 true, 틀리면 false 를 반환한다.

  3. String.equalsIgnoreCase(문자) // 문자와 문자를 비교하는데 대소문자 구분을 하지 않는다. 다시말하면 equals 는 대소문자를 구분한다.

 

3. 문자 추출하기

문자열은 앞의 문자와 뒤의 문자를 비교할 수 있다. 또한, 시작 위치를 지정하고 추출할 길이를 추출하면 해당 길이만큼의 문자를 추출해낼 수 있다.

  1. String.startsWith(문자) // String 이 문자로 시작하는지 판단한다. 참이라면 true, 거짓이면 false 를 반환한다.

  2. String.endsWidth(문자) // String 이 문자로 끝나는지 판단한다. 참이라면 true, 거짓이면 false 를 반환한다.

  3. String.subString(시작위치, 마지막위치) // String 에서 시작위치부터 마지막 위치까지의 문자열을 반환한다.

  3. 예제 abcdefg.subString(0, 3) =>> abc

Toad 단축키

toad사용법

 SQL EDITOR상에서의 편리한 단축키

ESC: 열린 윈도우 닫기
F1: 모든 단축키를 보여준다.
F2: FULL SCREEN
F4: Table, View, Proc, Funct, Package를 DESC(테이블명에 커서를 둔 상태에서 해야함)
F6: SQL Editor와 결과창간의 전환
F7: 화면을 모두 CLEAR
F8: 실행했던 SQL들의 HISTORY
F9: 모든 쿼리 실행(Ctrl+Enter는 현재 쿼리만 실행)
Ctrl+F9: 실제 쿼리를 실행하지 않고 validate함
Ctrl+. : table Completion (매칭되는 테이블목록 출력)
Ctrl+T : Columns Dropdown (해당테이블의 컬럼목록 표시)
Alt+Up : History Up (리눅스 bash의 UP키와 같다.)
Alt+Down: History Down (리눅스 bash의 DOWN키와 같다.)
Ctrl+Tab: MDI Child윈도간 전환

그냥 'desc 테이블명' 을 치면, 팝업윈도로 해당 테이블의 컬럼목록윈도가 표시된다.
이때, 해당 컬럼을 double-click하면 SQL Editor로 반영된다.

"테이블명."까지 입력하고 좀 있으면, 해당 테이블의 컬럼목록이 표시된다.
마치 프로그래밍툴에서 클래스내 멤버들의 목록을 표시하듯이..
Ctrl+T는 출력된 목록을 취소했을 경우, 다시 불러낼때 쓰인다.

test, member 2개의 테이블이 있다고 하자.
select * from t까지 입력하고 Ctrl+.를 치면 select * from test로 테이블명을 완성시켜준다.
system계정에서는 안되더군.. 일반계정만 가능했다.

SQL문을 실행시

Ctrl+Enter
현재 커서의 SQL문 실행
여러개의 SQL문이 있을때, SQL문들을 개행문자로 분리해주면 된다.
해당 커서에서 개행문자가 있는 곳까지만 하나의 SQL문으로 간주한다.

F9
SQL Editor의 SQL문 실행하여 Grid에 출력.
여러 SQL문들을 개행문자로 구분하지 않는다는 것을 제외하면, 위의 Ctrl+Enter와 동일하다.
에디터내의 모든 SQL문은 하나로 취급하므로, 여러 개의 SQL문이 있으면 실행할 SQL문만 Selection하여 실행(F9)해준다.

F5
SQL Editor내의 모든 SQL문 실행. 여러개의 SQL문들을 모두 실행하여 SQL*PLUS와 같이 출력해준다.
이것은 출력이 Grid로 표시되지 않고 Editor윈도에 표시되므로, SQL*PLUS의 출력과 같이,
다른 편집기로의 복사/붙여넣기 할때 사용하면 유용하다.

Oracle 페이징 쿼리

페이징 기법이란

데이터가 100건이 있다고 가정한다면, 한페이지당 10개씩 보여줄수 있게하는 기법을 말합니다.

1페이지에는 0~10까지. 2페이지에는 11~20 까지.. 10페이지에는 91~100 까지의 레코드를 보여주는 것을 말합니다.

 

아래는 페이징 기법을 구현할 수 있는 쿼리문입니다.

 

 

오라클에서 paging을 처리하기 위해서는 오라클에서 제공되는 rownum을 사용하게 됩니다.

하지만 rownum을 잘못알고 사용을 하게 되면 저처럼 삽질을 계속 하게 된다는 ^^;;

예를들면...
  SELECT *
  FROM (
            select board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE ROWNUM >= 1 AND ROWNUM <= 10

  이렇게 쿼리문을 날리면 데이터가 나옵니다.

  하지만 ..

  SELECT *
  FROM (
            select board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE ROWNUM >= 11 AND ROWNUM <= 20

   이렇게 쿼리문을 날렸을때 그냥 보기에는 나올것 같습니다. 하지만 아무런 데이터가
   나오지를 않습니다.^^; 아주 황당합니다.

그래서 많이쓰는 방법으로... 첫번째..

  SELECT *
  FROM (
            select rownum as rnum, board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE rnum>= 11 AND rnum <= 20

  서브쿼리에서 rownum을 구해 동일한 방법으로 where 조건을 주면 아주 잘 나옵니다.

또다른 방법.. 두번째..

  row_number() over(정렬을 위한 order by) 를 사용하면 됩니다.

  SELECT *
  FROM (
            select row_number() over(order by insert_date desc) as rnum, board_seq,
                     board_name, insert_date
            from t_board
            )
   WHERE rnum>= 11 AND rnum <= 20

첫번째 방법과 두번째 방법을 했을경우 결과는 동일합니다.

차이점이 있다면 두번째 방법에서 row_nuber() over()를 이용해서 over()안에 있는
order by 순으로 rownum을 새롭게 구하는것입니다.

* 참고 : row_number()는 오라클 8.1.6.0.0 이상에서 사용이 가능합니다.

EOF, BOF(RecordSet)

EOF, BOF란?

EOF는 End Of File의 약자로 커서가 레코드의 제일 마지막에 위치해있는것을 말합니다.

이때 레코드의 마지막에 커서가 위치해있다면 True를 반환하게 되며, 그렇지 않을경우는 False를 반환하게됩니다.

 

 Field Field Field EOF
 Record  Record  Record  False
 Record  Record  Record  False
       True

 

위의 표처럼 필드내에 레코드가 있다면 EOF는 False를 반환하게 됩니다.

반면, 필드내에 레코드가 없다면 True를 반환하게 됩니다.

 

데이터베이스는 모든 필드마다 여분의 셀(cell)을 두고 있습니다.

레코드가 앞으로 얼마나 더 추가가 될지 모르기때문에 그에 대비하여 여분의 레코드를 두게 되는데

커서가 여기에 위치할경우 EOF = True 를 반환하게 됩니다.

 

BOF는 어떻게 될까요?

BOF는 Begin Of File의 약자로 커서가 레코드의 제일 첫 행에 위치해있을 경우를 말합니다.

커서가 제일 첫 행에 위치할경우 True를 반환하고, 그렇지 않을 경우 False를 반환합니다.

 

1.

 Field Field Field BOF
 Record  Record  Record False
 Record  Record  Record
       

 

2.

 Field Field Field EOF



True




 

Oracle 함수 정리

CEIL

::
소수점 이후의 값은 무조건올림하는 함수.

 

MOD

::
두 수를 나눈 나머지 값을 구하는 함수.

 

POWER

::
승수 값을 구하는 함수.

[
] SQL> select POWER(3, 2), POWER(3, -2) from dual;

[
결과]9          .11111111

 

ROUND

::
반올림 값을 구하는 함수.

[
] SQL> select ROUND(345.123, 0), ROUND(345.123,2), round(345.123, -1) from dual;

[
결과]345          345.12          350

 

TRUNC

::
버림 값을 구하는 함수.

[
] SQL> select TRUNC(345.123, 2), TRUNC(345.123,0), trunc(345.123, -1) from dual;

[
결과]345.1          345          340

 

SIGN

::
해당 값이 양수면 1, 음수면 -1, 0이면 0을 돌려준다.

[
] SQL> select SIGN(345.123), SIGN(0),SIGN(-345.123) from dual;

[
결과]1          0          -1

 

CHR, ASCII

:: ASCII
은 문자로, 문자는 ASCII 값으로반환하는 함수.

[
] SQL> select CHR(65), ASCII('A') from dual;

[
결과]A          65

 

LOWER, UPPER

::
문자열을 소문자와 대문자로 반환하는 함수.

[
] SQL> select LOWER('My'), UPPER('My') from dual;

[
결과]my          MY

 

LPAD(char1, n, char2)

:: n
자리 만큼의 공간에서 char1을 오른쪽에 붙이고, 나머지 공간을 char2로 채운다.

RPAD(char1, n, char2)

:: n
자리 만큼의 공간에서 char1을 왼쪽에 붙이고,나머지 공간을 char2로 채운다.

[
] SQL> select LPAD('LDH', 10, '#'), RPAD('LDH',10, '#') from dual;

[
결과]#######LDH          LDH#######

 

LTRIM, RTRIM

::
각 각 오른쪽(LTRIM)과 왼쪾(RTRIM)의공백(Space)을 제거한다.

 

REPLACE(char1, char2, char3)

:: char1
문자열에서 char2 char3으로치환하는 함수.

[
] SQL> select REPLACE('Orange', 'O', 'A') fromdual;

[
결과] Arange

 

SUBSTR(char1, n, m)

:: char1
문자열의 n번째부터 시작해서 m번째까지의문자열을 리턴한다.

[
] SQL> select SUBSTR('오라클Oracle', 1, 3) from dual;

[
결과] '오라클'

[
] SQL> select SUBSTR('오라클Oracle', 7, 9) from dual;

[
결과] 'acl'

[
] SQL> select SUBSTR('오라클Oracle', 10) from dual;

[
결과] 'e'

 

SUBSTRB

::
바이트 단위로 계산하여 문자열을 치환하는 함수.

[
] SQL> select SUBSTRB('오라클Oracle', 1, 3) from dual;

[
결과] ''

[
] SQL> select SUBSTRB('오라클Oracle', 7, 9) from dual;

[
결과] ' Or'

[
] SQL> select SUBSTRB('오라클Oracle', 10) from dual;

[
결과] 'acle'

 

LENGTH, LENGTHB

::
문자열의 길이를 나타낸다.

[
] SQL> select LENGTH(운동(축구)), LENGTH(운동(축구))from dual;

[
결과]6          10

 

INSTR(char1, char2, n, m)

:: char1
에서 char2가 포함된 문자열의 위치가char1을 기준으로 n번째 위치부터 시작해서 m번째로 char2와 같은 위치를 돌려준다.

 

INSTRB(char1, char2, n, m)

::
바이트 단위로 내용은 위와 같다.

[
] SQL> INSTR('간장콩장공장장', '', 1, 2), INSTRB(간장콩장공장장', '', 1, 2) from dual;

[
결과]4          7

[
] SQL> INSTR('Corporate Floor', 'or', 3, 2),INSTRB('Corporate Floor', 'or', 3, 2) from dual;

[
결과]11          11

[
] SQL> INSTR('오라클 Oracle','r', 1, 1), INSTRB('오라클 Oracle', 'r', 1, 1) from dual;

[
결과]6          9

 

SYSDATE

::
현재의 일자와 시간을 의미하고, 기본값으로 오늘일자를 돌려준다.

[
] SQL> select SYSDATE from dual;

[
결과] 04/04/19

[
] SQL> select to_char(SYSDATE, 'YYYY-MM-DDHH24:MI:SS') from dual;

[
결과] 2004-04-19 00:44:20

 

LAST_DAY

::
해당 월의 마지막 날짜를 돌려준다.

[
] SQL> select LAST_DAY(SYSDATE), SYSDATE fromdual;

[
결과]04/04/30          04/04/19

 

MONTH_BETWEEN(date1, date2)

:: date1
date2를 월 단위로 계산하여 그 값을 리턴한다. 만약, date1 date2보다크면, 양수의 결과가 나온다.

[
] SQL> select MONTH_BETWEEN('2004-01-19','2004-04-19') from dual;

[
결과] -3

 

ADD_MONTHS(date, n)

:: date
n개월 후의 값을 리턴한다.

[
] SQL> select ADD_MONTHS(SYSDATE, 2), SYSDATE fromdual;

[
결과]04/06/19          04/04/19

 

NEXT_DAY(date, n)

:: date
를 기준으로 n요일에 해당하는 다음 날짜를 리턴한다.

[
] SQL> select NEXT_DAY(SYSDATE, 2),NEXT_DAY(SYSDATE, 7), SYSDATE from dual;

[
결과]04/04/20          04/04/25          04/04/19

 

TO_CHAR(n), TO_CHAR(n, format), TO_CHAR(date, format)

:: n
format 형식의 문자로 바꾸는 함수.

[
] SQL> select TO_CHAR(123.456) from dual;

[
결과] 123

[
] SQL> select TO_CHAR(123456.789, '999,999.9999')from dual;

[
결과] 123, 456.7890

[
] SQL> select TO_CHAR(SYSDATE, 'YYYY') from dual;

[
결과] 2004

 

TO_NUMBER(char), TO_NUMBER(char, format)

:: char
format 형식의 숫자로 바꾸는 함수.

[
] SQL> select TO_NUMBER('123.12') from dual;

[
결과] 123.12

[
] SQL> select TO_NUMBER('123.12', '999.999') fromdual;

[
결과] 123.120

 

TO_DATE(char), TO_DATE(char, format)

[
] SQL> select TO_DATE('20040419') from dual;

[
결과] 2004-04-19 00:00:00

[
] SQL> select TO_DATE('20040419', 'YY/MM/DD') fromdual;

[
결과] 04/04/19

 

AVG(column_name)

::
해당 컬럼의 평균값을 리턴한다.

 

MAX(column_name)

::
해당 컬럼에서 제일 큰 값을 리턴한다.

 

MIN(column_name)

::
해당 컬럼에서 제일 작은 값을 리턴한다.

 

SUN(column_name)

::
해당 컬럼의 합계를 리턴한다.

 

COUNT(column_name)

::
조회건수를 리턴한다.

 

NVL(column_name,
대신할 데이터)

::
해당 컬럼이 Null일 경우, 대신할 문자나숫자 등을 대신 사용한다.

 

DECODE

::
연속된 조거문이라고 할 수 있는데, 가장 자주 쓰이는 함수 중에 하나이다.

[
] SQL> select DECODE(idx, 10, '', 20, '', 30, '',40, '') from dual;

[
설명] idx 10이면 ''이고, 20이면 ''이고, 30이면 ''이고, ...

 

USERENV

::
현재 세션의 환경 정보를 반환한다.

ENTRYID :
사용 가능한 Auditing entry Identifier를 반환.
LABEL :
현재 세션의 Label을 반환.
LANGUAGE :
현재 세션에서 사용중인 언어와 테리토리 값을 반환.
SESSIONID : Auditing(
감사) Session ID를 반환.
TERMINAL :
현재 세션 터미널의 OS ID를 반환.

 

GREATEST(n1, n2, n3, ...)

::
숫자나 문자 아무거나 나열하면 그 중에 가장 큰 값을 반환한다.

 

LEAST(n1, n2, n3, ...)

::
숫자나 문자 아무거나 나열하면 그 중에 가장 작은 값을 반환한다.

 

UID, USER

::
사용자 ID와 사용자의 OWNER를 돌려준다.

페이징 로직

//페이지 처리

pageNum = Integer.parseInt(request.getParameter("pageNum")); //현재 페이지

totalRecord = 총 레코드 갯수;

paging = 페이지 당 보여질 게시물 수;

pageingCount = Math.ceil(totalRecord / paging); // 총 페이지 수

start = paging * pageNum; // 페이지의 시작위치

 

//페이지 그룹 처리

pageGroup = 페이지 그룹에 포함될 페이지의 수;

pageGroupNum = Math.ceil((pageNum+1) / pageGroup); // 현재의 페이지 그룹

pageStart = (pageGroupNum - 1) * pageGroup + 1; //페이지 그릅의 첫페이지

pageEnd = pageStart + pageGroup -  1; // 페이지 그룹의 마지막 페이지

 

// 이전 그룹 처리

prevGroup = pageGroupNum - 1; // 이전 그룹

prevStart = (prevGroup - 1) * pageGroup; // 이전 페이지 그룹의 첫페이지

if(pageGroupNum != 1) {

      ?pageNum=prevStart;

}

 

// 페이지 출력

int j = 0;

for(int i = pageStart; i < pageEnd; i++) {

    if(i > pageingCount) break;   

    j = i - 1;

    ?pageNum=j 

}

 

//다음 그룹 처리

nextGroup = pageGroupNum + 1; // 다음 그룹

nextStart = (nextGroup -1) * pageGroup; // 다음페이지 그룹의 첫페이지

if(pageingCount > (nextGroup+1)) {

     ?pageNum=nextStart

}

오라클 SYSTEM, SYS 비밀번호를 잊어먹었을 때 해결 방법

비밀번호를 계속 틀려서 오라클에서 잠궜을 경우 풀어야 하는데

그 명령어는 아래와 같습니다.

ALTER USER 계정명 ACCOUNT UNLOCK;

그리고나서 아래와 같이 따라하면 풀립니다.

명령 프롬프트(즉, DOS 창)에서 다음을 실행합니다.

C:\>sqlplus "/as sysdba"

SQL> show user

USER is "SYS"

 

이제 암호를 원하는 대로 설정합니다.

 

SQL> alter user sys identified by 암호;

SQL> alter user system identified by 암호;

 

이제 접속이 잘 될 것입니다.

 

SQL> connect sys/암호 as sysdba

SQL> connect system/암호

이클립스에서 톰캣 포트관련 에러 발생했을때 처리방법

톰캣을 이클립스에서 실행하면 port 8080 관련된 에러가 발생하는데

시작 - 실행 - cmd - netstat -a -n -o 실행 후 8080 포트 PID 번호 찾아서 - Ctrl + Art + Delete 후에 프로세스에서 PID를 찾아 프로세스를 종료한다.

오라클 포트 변경

이클립스환경에서 톰캣과 오라클을 사용하다 보면

오라클의 웹 관리 페이지의 포트와 톰캣의 포트가 충돌을 하게 되는데

해결 방법은 아래와 같이 한다.

 

 

시작 - 실행 - cmd

sqlplus /nolog

sql> CONNECT SYSTEM/암호

sql> EXEC DBMS_XDB.SETHTTPPORT(새로고칠포트번호);

 

PL/SQL procedure successfully completed. 출력되면 성공

 

sql> exit

 

 

 

커넥션 풀을 이용한 DataSource 설정

스프링이 직접적으로 커넥션 풀 구현 클래스를 제공하진 않지만, DBCP API와 같은 커넥션 풀 라이브러리를 이용해서 커넥션 풀 기반의 DataSource를 설정할 수 있다. 아래 코드는 DBCP가 제공하는 BasicDataSource 클래스를 이용해서 DaeaSource를 설정하는 예제이다.

 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />

  <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />

  <property name="username" value="[username]" />

  <property name="password" value="[password]" />

  <property name="initialSize" value="5" />

</bean>

위 설정내용은 commonContext.xml 로 저장하고

web.xml 에서 로드한다.

 

그 뒤 Dao 가 쓰이는 곳에 bean property로 등록하면 완료!

Bean 파일을 분리하는 방법

web.xml 에 아래의 내용을 추가한다.

 

<context-param>

  <param-name>contextConfigLocation</param-name>

  <param-value>

    WEB-INF/config/xml 파일 이름

    ...

  </param-value>

</context-param>

 

<listener>

  <listener-class>

    org.springframework.web.context.ContextLoaderListener

  </listener-class>

</listener>

이렇게 하면 WEB-INF 의 config 밑에 있는 xml 파일중 등록된 xml 파일을 로딩하게 된다.

JUnit Test Framework 사용하기

JUnit 은 TDD 개발방식을 구현(?) 할 수 있게 하는 Framework 이다.

 

사용법 :

프로젝트를 Maven 으로 만든 후

Springframework Defenndency 를 추가한 후

Junut : Junit Defendency 를 추가 한 뒤

Maven Package 를 실행한 뒤에

Target의 라이브러리를 Webapp 의 라이브러리로 복사해 넣는다.

 

그 뒤에 src/main/java 와 src/test/java 쪽에 도메인/패키지 명을 동일하게 만든 뒤

Test 패키지 쪽에 테스트클래스명+Test 형식의 클래스 파일을 만든다.

 

코딩 중 다른 클래스를 만들게 되면 src/main/java에 만들도록 한다.

 

그 뒤에

테스트하고자 하는 메소드를 코딩 한 뒤에 Run As -> JUnit Test 를 실행하면 되는데,

이때 메소드 명 위에 마다 @Test 어노테이션이 존재하여야 JUnit Framework가 인식 할 수 있다.

 

실행하고 나면 이클립스 창 아래에 JUnit 이라는 탭이 생기는데

이 탭의 오른쪽 상단에 빨간색과, 녹색의 줄 중 하나의 줄이 생긴다.

 

빨간색 줄은 소스에 오류가 있어 테스트를 통과하지 못했다는 것이고

녹색 줄은 테스트를 통과했다는 것이다.

JUnit Annotation

JUnit4부터 어노테이션(Annotation)을 지원한다.

  1. 어노테이션의 기능

    1. @BeforeClass : 제일 처음으로 실행되는 메소드가 된다.
    2. @Before :  두번째 실행되는 메소드가 된다.
    3. @Test : 테스트 메소드가 된다.
    4. @After: 세번째 실행되는 메소드가 된다.
    5. @AfterClass : 마지막으로 실행되는 메소드가 된다.
    6. @Ignore("이 함수는 실행되지 않습니다.") : 이 메소드는 실행되지 않음.
    7. @Test(timeout=3000) : timeout에 설정되어 있는 시간을 넘어가면 에러발생.
    8. @Test(expected=IndexOutOfBoundsException.class) : try/catch 를 하지 않아도 어노테이션에 설정 되어있는 exception이 발생하면 성공으로 간주.

앞으로 배워야할 것들

DB연동부분 - iBatis 연동 / ConnectionPool 연동

 

Spring MVC - FileUpload / Download

                  - Excel / PDF download

 

Ajax(Spring 연동) - XML 개요

                          - JSON

 

Transaction 관리

 

Utility - Joda-Time (날짜처리)

        - 인증 심화 (Login, 권한)

        - Session 처리

2010년 7월 28일 수요일

Java Map(HashMap, TreeMap, Hashtable)

1. Collection
  • Map은 key와 value를 가진 집합이며, 중복을 허용하지 않는다.
  • 즉, 한개의 key에 한개의 value가 매칭된다.
  • java.util 패키지에 여러 집합들을 사용하기 위한 여러 interface와 class 들이 정의되어 있다.
2. HashMap
  • HashMap은 Map interface를 implements 한 클래스로서 중복을 허용하지 않는다.
  • Map의 특징인 key와 value의 쌍으로 이루어지며, key 또는 value 값으로써 null을 허용한다.
  • 아래의 예는 HashMap을 사용한 간단한 예제이다.

    import java.util.*;

    public class HashMapTest
    {
        public static void main(String argv[])
        {
            HashMap hm = new HashMap();
            System.out.println(hm.put("aaa", "111"));
            System.out.println(hm.put("bbb", "222"));
            System.out.println(hm.put("aaa", "444"));
            System.out.println(hm.put("ccc", "333"));   
            System.out.println(hm.put("ccc", null));      
           
            System.out.println("HashMap size : " + hm.size());
           
            Set set = hm.keySet();
            Object []hmKeys = set.toArray();
            for(int i = 0; i < hmKeys.length; i++)
            {
                String key = (String)hmKeys[i];  
                System.out.print(key);
                System.out.print(" - ");
                System.out.println((String)hm.get(key));
            }
        }
    }


    /**
    실행:java HashMapTest
    결과:
    null
    null
    111
    null
    333
    HashMap size : 3
    ccc - null
    bbb - 222
    aaa - 444
    */

3. TreeMap
  • TreeMap역시 중복을 허용하지 않으며, key와 value의 쌍으로 이루어져 있다.
  • HashMap과 다른 점은 SortedMap을 implements 하였으므로, key 값들에 대한 정렬이 이루어진다는 점이다.
  • 아래의 예는 TreeMap을 사용하여 각 요소가 몇몇 이나 나왔는지 알아보는 간단한 예제이다.

    import java.util.*;

    public class Freq
    {
        private static final Integer ONE = new Integer(1);

        public static void main(String args[])

        {
            Map m = new TreeMap();

            // Initialize frequency table from command line
            for (int i=0; i < args.length; i++)

            {
                Integer freq = (Integer) m.get(args[i]);
                m.put(args[i], (freq==null ? ONE :
                                new Integer(freq.intValue() + 1)));
            }

            System.out.println(m.size()+" distinct words detected:");
            System.out.println(m);
        }
    }


    /**
    실행:java Freq if it is to be it is up to me to delegate
    결과:
    8 distinct words detected:
    {be=1, delegate=1, if=1, is=2, it=2, me=1, to=3, up=1}
    */

4. Hashtable
  • Hashtable Map interface를 implements 한 클래스로서 중복을 허용하지 않는다.
  • Map의 특징인 key와 value의 쌍으로 이루어지며, key 또는 value 값으로써 null을 허용하지 않는다.(HashMap과의 차이점)
  • 아래의 예는 HashTable을 사용한 간단한 예제이다.

    import java.util.*;

    public class HashtableTest
    {

        public static void main(String argv[])
        {
            Hashtable ht = new Hashtable();
            System.out.println(ht.put("aaa", "111"));
            System.out.println(ht.put("bbb", "222"));
            System.out.println(ht.put("aaa", "444"));
            System.out.println(ht.put("ccc", "333"));   
           
            System.out.println("Hashtable size : " + ht.size());
           
            System.out.println("aaa value : " + (String)ht.get("aaa");
           
        }
    }


    /**
    실행:java HashMapTest
    결과:
    null
    null
    111
    null
    Hashtable size : 3
    aaa value : 444
    */

    출처 : http://pelican7.egloos.com/881589

Spring MVC를 이용한 웹 요청 처리

스프링 MVC를 이용한 웹 요청 처리



구성요소

DispatcherServlet : 클라이언트의 요청을 전달받음. 컨트롤러에게 클라이언트의 요청을 전달하고 컨트롤러가 리턴한 결과 값을 view에 전달하여 알맞은 응답을 생성하도록 한다.

HandlerMapping : 클라이언트의 요청 URL을 어떤 컨트롤러가 처리할 지를 결정

Controller : 클라이언트의 요청을 처리한 뒤, 그 결과를 DispatcherServlet에 알려줌.

ModelAndView : 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다.

ViewResolver : 컨트롤러의 처리 결과를 생성할 뷰를 결정

View : 컨트롤러의 처리 결과 화면을 생성


캐릭터 인코딩 처리를 위한 필터 설정

요청 파라미터의 캐릭터 인코딩이 ISO-8859-1이 아닌경우, request.setCharacterEncoding() 메소드를 사용해서 요청 파라미터의 캐릭터 인코딩을 설정해 줘야 하는데 모든 Controller에서 이 코드를 실행할 수 있지만 그것보다는 서블릿 필터를 이용해서 원하는 요청에 코드를 적용하는것이 더 편리.


web.xml에 추가
 <filter>
  <filter-name>encodingFilter</filter-name>
  <filter-class>
   org.springframework.web.filter.CharacterEncodingFilter
  </filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>UTF-8</param-value>
  </init-param>
 </filter>

 <filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>



웹 요청과 컨트롤러 매핑 : HandlerMapping의 구현 클래스

- SimpleUrlHandlerMapping
- BeanNameUrlHandlerMapping
- ControllerClassNameHandlerMapping
- DefaultAnnotationHandlerMapping

컨트롤러 종류

- Controller
- AbstractController
- AbstractCommandController
- SimpleFormController
- AbstractWizardFormController
- ParameterizableViewController
- UrlFilenameViewController
- MultiActionController


Annotatiln을 이용한 Controller의 구현

더 자세히


예외처리

interface Controller의 handleRequest() 메소드는 Exception을 발생할 수 있도록 정의

Controller는 서블릿과 관련된 ServletException뿐만 아니라 NullPointerException과 같은 RuntimeException등 다양한 예외를 발생시킬 수 있다.

보통은 서블릿 엔진이 제공하는 에러 화면이 웹 브라우저에 출력되는데 만약 예외에 따라 알맞은 에러 화면을 출력하고 싶다면 HandlerExceptionResolver를 사용하면 된다.
DispatcherServlet은 HandlerExceptionResolver가 등록되어 있을 경우, 예외 처리를 HandlerExceptionResolver에 맡긴다.

SimpleMappingExceptionResolver 클래스는 HandlerExceptionResolver 인터페이스를 구현하고 있으며, 스프링에서는 현재 SimpleMappingExceptionResolver 클래스만을 제공하고 있다.

 

출처 : http://flyburi.com/301

Redmine - 2.2 Subversion 연동하기 (Apache 이용)

저번 글에 이어 이제 Subversion을 Apache와 연동하는 방법을 설명하겠습니다.

구글링을 해보면 Apache 2.2.X와 Subversion 1.4.5는 연동이 안된다고 합니다. 저도 버전 안올리고 BitNami Redmine 설치된 상태로 시도해봤는데 안되더군요.

서브버전 다운로드 페이지를 열어보니 (http://subversion.tigris.org/project_packages.html ) 새 버전이 나왔군요. 혹시나 하고 찾아들어갔더니 Subversion 1.4.6 Win32 binaries for Apache 2.2.x. 라는 다운로드 링크가 있습니다.

이제 기존에 깔린 Subversion 1.4.5 버전을 Subversion 1.4.6 버전으로 무사히 바꾸는 일만 남았습니다.

1. Redmine 서비스를 모두 멈춥니다

\Bitnami Redmine Stack\servicerun.bat STOP

2. \BitNami Redmine Stack\subversion 을 subversion 1.4.5로 이름을 바꿔줍니다.

3. 다운받은 Subversion 1.4.6을 \BitNami Redmine Stack\subversion에 압축해제 합니다.

4. \Bitnami Redmine Stack\subversion 1.4.5\scripts 폴더를 \Bitnami Redmine Stak\subversion 으로 복사합니다.

5. \Bitnami Redmine Stack\subversion\bin\에 있는 mod_authz_svn.so, mod_dav_svn.so 파일을 \Bitnami Redmine Stack\Apache\modules로 복사합니다.

6. Apache basic authentication을 이용해 Subversion 인증을 처리할 것이기 때문에
\Bitnami Redmine Stack\SvnRepo 폴더에서 htpasswd 명령을 이용해 admin 계정을 세팅 합니다.

\Bitnami Redmine Stack\SvnRepo\htpasswd -cm svn.htpasswd admin

일단 파일이 만들어진 다음부터는 htpass -m 파라미터만 붙여주면 됩니다.

\Bitnami Redmine Stack\SvnRepo\htpasswd -m svn.htpasswd twiny

7. \BitNami Redmine Stack\Apache2\conf\httpd.conf 파일을 열고 맨 밑에 다음과 같이 추가합니다.

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

<VirtualHost *:88>
 <Location /svn>
   DAV svn
   SVNParentPath "C:/Program Files/BitNami Redmine Stack/SvnRepo"
   AuthName "Subversion repository"
   AuthType Basic
   <LimitExcept GET PROPFIND OPTIONS REPORT>
     Require valid-user
   </LimitExcept>
 
   AuthUserFile "C:/Program Files/BitNami Redmine Stack/SvnRepo/svn.htpasswd"
 </Location>
</VirtualHost>

앞으로 http://localhost:88/svn/ 로 들어오면 subversion에 접속이 됩니다.

8. Redmine에서는 다음과 같이 하시면 됩니다.

사용자 삽입 이미지



- 끝

 

출처 : http://twiny.tistory.com/1673

Redmine - 2.1 Subversion 연동하기 (svn protocol 이용)

별 문제없이 대략 한시간 안에 설치 마치고 이것저것 써보면서 Redmine의 매력에 푹 빠졌을텐데요. 이제부터 조금 복잡합니다. -.-;
원래 주는데로 쓰면 괜찮은데 뭐를 바꾸기 시작하면 그때부터 고생이 시작되죠.

그 처음으로 Subversion 연동을 시작해보겠습니다.

BitNami Redmine Stack은 크게

Apache 2.2.4
Ruby 1.8.6
Rails 2.0.2
Subversion 1.4.5
MySQL 5.0.45
Redmine 0.6.3

으로 구성되 있습니다.

이 중 Apache 2.2.4와 Subverion 1.4.5는 서로 연동이 불가능한 버전이라고 합니다. 뭐 저도 잘 안됐는데 되신 분 있으면 댓글을...
Apache 연동을 하려면 이 글을 읽지 말고 Redmine - 2.2 Subversion 연동하기 ( http protocol 이용) 을 읽어주세요.

그럼 이제 시작해볼까요?

1. Subversion 클라이언트 설치

이미 깔려있으면 상관없고 없다면 Subverion 1.4.5와 잘 어울리는 TortoiseSVN 1.4.5 을 깔아주세요.

2. 서브버전 저장소 생성

저장소 하나 만들고 말게 아니기 때문에 BitNami Redmine Stack 폴더 밑으로 저장소의 부모 폴더를 만들어 줍니다.

\BitNami Redmine Stack\SvnRepo 폴더 생성


그 밑에 첫번째 서브버전 저장소를 만듭니다.

\BitNami Redmine Stack\SvnRepo\Sample 폴더 생성

\BitNami Redmine Stack\SvnRepo\Sample 폴더로 이동해서 아래처럼 Create repository here 를 해주세요.

타이핑 좋아하시는 분은 \BitNami Redmine Stack\SvnRepo에서

svnadmin create --fs-type fsfs sample 라고 하시면 됩니다. (명령어 못 찾으면 Path에 추가하시거나 Full-Path 치세요. ㅎㅎ)

3. \BitNami Redmine Stack\SvnRepo\Sample\conf\passwd 파일을 열어서 계정 추가.

   예) admin = 1234

4. \BitNami Redmine Stack\SvnRepo\Sample\conf\svnserve.conf 파일 열어서 아래 내용 주석 제거 ( #을 빼주시면 되요 )

   anon-access = read
   auth-access = write
   password-db = passwd

5. 명령창에서 등록된 윈도우 서비스 중 redmineSubversion을 내립니다. ( 몰랐는데 sc 라는 명령어도 있네요)

    \BitNami Redmine Stack\Subverion\scripts\serviceinstall.bat REMOVE

6. \BitNami Redmine Stack\Subverion\scripts\serviceinstall.bat 파일을 열어서 저장소 폴더 정보를 추가로 넣어줍니다.  (port는 고치지마세요)

"C:\Program Files\BitNami Redmine Stack/subversion\scripts\winserv.exe" install redmineSubversion -displayname "redmineSubversion" -start auto "C:\Program Files\BitNami Redmine Stack/subversion\bin\svnserve.exe" -d --root "C:\Program Files\BitNami Redmine Stack\SvnRepo" --listen-port=3690

7. 다시 redmineSubverion 을 윈도우 서비스로 등록합니다.

    \BitNami Redmine Stack\Subverion\scripts\serviceinstall.bat INSTALL

8. 이제 드디어 Redmine 설정을 합니다.

프로젝트를 하나 만들고 들어가서 설정 > 저장소 를 선택 후 다음과 같이 입력...

Login과 Password는 아까 passwd에 입력했던 값을 넣어주시면 되요.

9. 위의 모든 과정이 잘 됐으면 아래와 같은 화면을 보실 수 있습니다.

10. 저장소에서 한글 보여주기

좌측 상단 "관리자" 링크 또는 " Administrator" 링크를 누르고 설정 화면에서
Repositories encodings 값에 UTF-8,EUC-KR을 추가해주면 한글 내용을 볼 수 있습니다.


- 끝 -

 

출처 : http://twiny.tistory.com/1672

Bitnami Installer

Sonar & Radar 블로그에서 발견한 유용한 사이트.


업이 System Engineer이 아닌다음에야 불친절한(?) 오픈소스를 제대로 설치하고 써보려면 많은 역경을 이겨내야 하는데 그 과정을 해결해주는 군요.

있으면 좋은 서비스가 아니라, 꼭 필요하지만 불편한 서비스를 개선해주는게 돈버는 서비스라던데...


자세한 리뷰는 위 Sonar & Radar 를 참조 하시면 됩니다.


사실 Apache + PHP + MySQL 을 편하게 설치해 주는 APM_SETUP 이나 RWAPM 같은 프로젝트는 있었지만, 그 위에 다른 오픈소스 올리는게 만만치 않았거든요.

- trac 같은 경우는 Trac On Windows 라는 프로젝트가 있어 유용하게 썼습니다. ^^;


현재 [ 2008년 2월 1일] BitNami에서 지원하는 오픈소스는 아래와 같습니다.



바로 이어 여기서 발견한 보물같은 PMS인 Redmine 리뷰에 들어갑니다.

Redmine 설치

Redmine - flexible project management web application

2008년 1월 25일 BitNami에서 Release 한 Redmine 0.6.3-2 Installer를 기준으로 쓴 글입니다.

BitNami 를 발견하고 귀차니즘 내지는 어려워서 포기하고 있었던 각종 애플리케이션을 깔아보다가 발견한 놈! 

대략적인 기능은

  • Multiple projects support
  • Flexible role based access control.
  • Flexible issue tracking system
  • Gantt chart and calendar
  • News, documents & files management
  • Feeds & email notifications.
  • Per project wiki
  • Per project forums
  • Simple time tracking functionality
  • Custom fields for issues, projects and users
  • SCM integration (SVN, CVS, Mercurial, Bazaar and Darcs)
  • Multiple LDAP authentication support
  • User self-registration support
  • Multilanguage support
  • Multiple databases support

    딱봐도 trac과 비슷한 점이 많이 보이는데 trac에서 아쉬웠던 점이 대폭 들어가 있습니다. trac에서도 plug-in깔고 Command 창 열고 열심히 타이핑하면 위의 기능을 쓸 수 있지만, Redmine은 모두 웹페이지에서 편하게 처리할 수 있습니다.

    예를들어 trac을 쓰면서는 phpBB 같은 포럼을 추가로 연동해주곤 했는데 요놈은, 자체적으로 포럼을 가지고 있고 추가로 documents 와 file 만 올려둘 수 있는 메뉴도 있습니다.  
     
    우선 설치를 해보죠.

    1.
    http://bitnami.org/stack/redmine 를 열고 입맛에 맞는 설치본을 고릅니다.


    2. 다운로드가 다 받아지면 더블클릭! (이때, 조금 걸리니 제 블로그 글 읽으면서 이올린에 추천하기를 꼬~옥 눌러주세요 ㅎㅎ)

    3. BitNami 인스톨러는 필요한 모든 구성 요소를 다 가지고 있습니다. 사용자PC 환경에 종속적이지 않기 때문에 편리하지만 간혹 Apache나 MySQL이 미리 설치되있으면 포트번호를 바꿔줘야하죠. 나중에 충돌나지 않도록 신경쓰세요.

    4. 관리에 필요한 계정 정보를 입력합니다. 기본적으로 Redmine 어드민으로 로그인하는데 이용됩니다.

    5. 모든 설치가 끝나면 http://localhost 를 열어보세요. (리눅스나 맥이라면 http://127.0.0.1:8080)

    요런 비슷한 모양의 사이트가 열리면 잘 설치가 된겁니다. 

    ㅎㅎ 설치 한 뒤 눈치챘겠지만, Redmine 사이트도 Redmine으로 유지되고 있습니다. ( 스스로 개밥을 먹어보라고 했던가요? )

    6. 이제 셋업을 위해 관리자로 로그인 합니다.

    - 아까 인스톨 할때 입력했죠?
     

    7. 자 이제 한글과 관련된 문제들을 해결해 보겠습니다.

    * BitNami 에서 설치해주는 디비 테이블이 기본적으로 UTF8을 지원하지 않는군요.
       - 그냥 써도 무관하나 혹시 몰라 확실히 고쳐보겠습니다.

    아래 작업은 도스창(Command창) 을 열어서 해야하는데 Path 문제로 타이핑이 길어지는 번거로움이 있습니다.
    C:\Program Files\BitNami Redmine Stack\scripts\setenv.bat를 먼저 실행시키고 하거나 관련 Path를 환경설정 ( 시스템 등록정보 -> 고급 -> 환경변수 중 Path )에 넣어주시면 편합니다.


    1. MySQL DB 새로 생성 - 패스워드는 설치시에 입력한 관리자 패스워드와 동일
      - 모르겠으면 \BitNami Redmine Stack\MySQL\my.ini 열어보면 있음

    \BitNami Redmine Stack\MySQL\bin\mysql -uroot -p
    Enter password: ******

    mysql> drop database redmine_production;
       mysql> create database redmine_production COLLATE utf8_general_ci;

    2. database.yml 수정 - \BitNami Redmine Stack\redmine\config\ 에 있음

    production:
      adapter: mysql
      database: redmine_production
      host: localhost
      username: bitnami
      password: bitnami
      port: 3306
      encoding: utf8

    3. redmine 데이타베이스 마이그레이션

    \BitNami Redmine Stack\redmine\rake db:migrate RAILS_ENV="production"

    4. redmine 각종 기본데이터 넣어주기

    \BitNami Redmine Stack\redmine\rake redmine:load_default_data RAILS_ENV="production"


    트러블슈팅

    • 설치시 입력한 관리자 계정으로 로그인이 안되는 경우

      간혹가다가 관리자 계정이 제대로 입력이 안되는 경우가 있습니다. 이럴때는 직접 DB에 넣어줘야죠. ^^;

      우선 우측 상단 "등록" 링크를 눌러 관리자로 쓸 계정을 하나 생성합니다. (등록 대기기 때문에 이 계정으로는 접속 불가)

      \BitNami Redmine Stack\MySQL\my.ini을 열어보면
      [mysqladmin]
      user=root
      password='*****'
      port=3306

      요런 부분이 보입니다. 편한 MySQL 관리툴을 이용해서 위의 정보로 연결.

      users 테이블을 열면 아까 입력한 계정 정보가 보일 겁니다.
         
      admin 필드 값을 1 로, status 값을 1 로 변경하세요.
    • 한글 파일 업로드 / 다운로드 문제 => 허접한 해결책
      아쉽게도 한글 파일을 업로드 하거나 다운로드 하는게 제대로 안됩니다. -.-
      소스를 조금 고치는 허접한 해결책이 있긴 합니다. 위 링크 누르세요.
    • 서브버전 레파지토리의 경우 한글 파일/한글 폴더는 접근이 안됩니다.
      이건 아직 해결책을 못찾겠네요. ThoughWorks의 Mingle은 다 잘되던데

      이 외, 다른 경우는 아직 겪어보지 못해서... 쓰다가 이상한 점이 발견되면 추가할께요

    출처 : http://twiny.tistory.com/1671

  • 2010년 7월 27일 화요일

    Spring MVC의 주요 구성요소 및 처리 흐름

     구성 요소 설 명
     DispatcherServlet  클라이언트의 요청을 전달받는다. 컨트롤러에게 클라이언트의 요청을 전달하고, 컨트롤러가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성하도록 한다.
     HandlerMapping  클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지를 결정한다.
     Controller  클라이언트의 요청을 처리한 뒤, 그 결과를 DispatcherServlet에 알려준다, 스트럿츠의 Action과 동일한 역할을 수행한다.
     ModelAndView  컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다.
     ViewResolver  컨트롤러의 처리 결과를 생성할 뷰를 결정한다.
     View  컨트롤러의 처리 결과 화면을 생성한다. JSP나 Velocity 템플릿 파일 등을 뷰로 사용한다.


    이들 각 구성 요소의 메시지 흐름은 다음과 같다.

    1. 클라이언트의 요청이 DispatcherServlet에 전달된다.

    2. DispatcherServlet은 HandlerMapping을 사용하여 클라이언트의 요청을 처리할 컨트롤러의 객체를 구한다.

    3. DispatcherServlet은 컨트롤러 객체를 이용해서 클라이언트의 요청을 처리한다.

    4. 컨트롤러는 클라이언트의 요청 처리 결과 정보를 담은 ModelAndView 객체를 리턴한다.

    5. DispatcherServlet은 ViewResolver로부터 응답 결과를 생성할 뷰 객체를 구한다.

    6. 뷰는 클라이언트에 전송할 응답을 생성한다.

     

    이 과정에서 개발자가 직접 개발해야 할 부분은 클라이언트의 요청을 처리할 컨트롤러와 클라이언트에 응답 결과 화면을 전송할 JSP나 Velocity 템플릿 등의 뷰 코드이다. 나머지 DispatcherServlet이나 HandlerMapping, ViewResolver 등은 스프링이 기본적으로 제공하는 구현 클래스를 사용하게 된다.

    MVC 패턴

    Model -> 서비스

    View  -> UI

    Controller -> 서비스 + UI

     

    MVC 패턴은 계산하는 로직과 화면을 구성하는 로직을 분리 하자는 목적의 패턴이 Model2 방식이 된다.

     

    1. 요청을 처리해서 응답을 해주는 컨트롤이 필요. -> DispatcherServler

    2. 비즈니스 로직 처리 -> Controller(서비스)

    3. 화면을 구성. -> JSP

     

    JSP의 기능이 단축된다. : 화면만 구성한다. 로직이 들어가지 않는다. 스크립트릿은 필요없다.

     

    요청/응답 컨트롤

     요청과 응답만을 전담으로 처리한다.

     DispatcherServlet 이 처리한다. 즉, Model2 방식에서의 모든 요청은 DispatcherServlet 이 한다.

     DispatcherServlet 은 보안에서도 유리하다. Post, get 이 노출이 되지 않는다.

     

    2010년 7월 26일 월요일

    Oracle System 비밀번호 잊었을 때

    명령 프롬프트(즉, DOS 창)에서 다음을 실행합니다.

    C:\>sqlplus "/as sysdba"

    SQL> show user

    USER is "SYS"


    이제 암호를 원하는 대로 설정합니다.


    SQL> alter user sys identified by 암호;

    SQL> alter user system identified by 암호;


    이제 접속이 잘 될 것입니다.


    SQL> connect sys/암호 as sysdba

    SQL> connect system/암호

     

    출처 : http://blog.bagesoft.com/644

    Ora-28000(account is locked) 해결 방법

    Ora-28000(account is locked) 해결 방법

    이 오류는 일정 횟수 이상 로그인 실패나 10g인 경우 처음 설치 후 scott 계정을 사용 할려면 만날 수 있는 오류 입니다.

    CREATE PROFILE 명령을 사용하여 로그인을 시도할 경우에 허용된 실패횟수를 지정할 수 있을 뿐 아니라 유저 계정이 잠금상태로 남아 있게 되는 시간도 지정할 수 있습니다.
    접속시에  일정 회수 이상 실패한 후 CONNECT를 시도하면 "ORA-28000: the
    account is locked" 의 ERROR를 받게 됩니다.


    SELECT USERNAME,
           ACCOUNT_STATUS,
               TO_CHAR(LOCK_DATE,'YYYY.MM.DD HH24:MI') LOCK_DATE          
    FROM DBA_USERS;

    [결과]
    TOAD                           OPEN                                            
    MGMT_VIEW                      OPEN                                            
    SYS                            OPEN                                            
    SYSTEM                         OPEN                                            
    DBSNMP                         OPEN                                            
    SYSMAN                         OPEN                                            
    SCOTT                          EXPIRED & LOCKED                 2005.09.20 19:34

    위에서 SCOTT 계정의 경우 LOCKED 이면서 EXPIRED 되어 있으니 우선 아래의 명령으로 LOCK을 풀어야 하는데 ALTER USER 명령을 사용하시면 됩니다.

    ALTER USER scott ACCOUNT UNLOCK;

    다시한번 SCOTT USER의 상태에 대해 조회를 해 보죠…

    SELECT USERNAME,
           ACCOUNT_STATUS,
               TO_CHAR(LOCK_DATE,'YYYY.MM.DD HH24:MI') LOCK_DATE          
    FROM DBA_USERS
    WHERE USERNAME = 'SCOTT'

    [결과]
    SCOTT                          EXPIRED


    이젠 EXPIRED를 풀어야 하는데 TOAD등을 사용할 경우엔 SCOTT으로 로그인 하면 새 비밀번호를 요구하게 되는데 이때 새 비밀번호를 입력하시면 되구요, 아님 오라클의 관리자 계정으로 로그인 후 alter user scott identified by tiger 라고 하시면 됩니다.

    다시 확인해 보면…

    SELECT USERNAME,
           ACCOUNT_STATUS,
               TO_CHAR(LOCK_DATE,'YYYY.MM.DD HH24:MI') LOCK_DATE          
    FROM DBA_USERS
    WHERE USERNAME = 'SCOTT'

    [결과]
    SCOTT                          OPEN

     

    출처 : http://hyunayarn.tistory.com/tag/account%20is%20locked

    2010년 7월 25일 일요일

    Maven WTP Project 생성하기

    1. CMD를 실행.

    2. 워크스페이스로 이동한다.

    3. 워크스페이스 폴더에서 다음과 같이 입력한다.

     

    mvn archetype:generate -DgroupId=package.name -DartifactId=ProjectName

    -DarchetypeArtifactId=maven-archetype-webapp

    위와 같이 입력하면 워크스페이스에 ProjectName 이라는 폴더가 생기면서 프로젝트 폴더의 구색을 갖추게 된다.

     

    Maven 기반 웹 프로젝트의 기본 디렉토리는 src/main/webapp이다. webapp 디렉토리는 자바 기반 웹 애플리케이션의 기본 웹 디렉토리 구조를 따른다. Maven Archetype에 의하여 기본으로 생성되는 war 프로젝트는 자바 소스 코드를 관리하기 위한 src/main/java, src/test/java 디렉토리를 생성하지 않는다. 따라서 웹 자원과 자바 소스 코드를 같이 관리하려면 src/main/java, src/test/java 디렉토리를 추가해야한다.

     

    그 다음으로 할일은 maven 프로젝트의 pom.xml 을 수정해야 한다.

     

    pom.xml 파일은 maven 프로젝트의 설정을 관리한다.

     

    여튼,

     

    메이븐으로 만들어진 기본 pom.xml 파일의 내용은 다음과 같다.

     

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>net.narsha</groupId>
      <artifactId>Address</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>Address Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>

     

    위의 설정에서 몇가지를 추가해야하는데 그 내용으로는, 이클립스에서 사용가능하도록 컴파일러 플러그인과, 메이븐 이클립스 플러그인, 그리고 인코딩 설정을 담고 있다.

     

    여튼 추가해보도록 하자.

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>net.narsha</groupId>
      <artifactId>Address</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>Address Maven Webapp</name>
      <url>http://maven.apache.org</url>
     <properties>
       <webapp.context>/</webapp.context>
       <maven.compiler.source>1.5</maven.compiler.source>
       <maven.compiler.target>1.5</maven.compiler.target>
       <maven.compiler.encoding>utf-8</maven.compiler.encoding>   
      </properties> 
     
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
       <finalName>Address</finalName>
       <plugins>
        <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <encoding>${maven.compiler.encoding}</encoding>
         </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-eclipse-plugin</artifactId>
          <version>2.4</version>
          <configuration>
           <wtpContextName>${webapp.context}</wtpContextName>
           <downloadSources>true</downloadSources>
           <downloadJavadocs>true</downloadJavadocs>
           <wtpversion>1.5</wtpversion>
          </configuration>     
         </plugin>
        </plugins>
       </build>
    </project>

     

    위와같이 설정을 추가했으면 다시 cmd 로 돌아가 방금 생성한 프로젝트폴더로 이동한 다음

    다음과 같이 입력한다.

     

    mvn eclipse:clean eclipse:eclipse

     

    이 명령은 Maven 기반의 프로젝트를 이클립스에서 실행할 수 있도록 만들어 준다.

    입력 후 실행을 하고 BUILD SUCCESS 가 출력된다면, 빌드에 성공한것이다.

     

    그 다음, 할일은 이클립스에서 Import 를 해주는데 General - Existing Projects into Workspace 로 들어간 뒤

    Select root directory 에서 메이븐 프로젝트를 선택 한 후 Finish 를 누르면 메이븐 프로젝트 -> 이클립스 프로젝트로 완성이 된다.

     

     

    2010년 7월 23일 금요일

    Trac, Apache, SVN 연동하기

    프로젝트의 운영관리에서 이슈관리, 버전관리, 배포관리를 위한 관리 툴 SVN 과 Trac의 연동을 해보자.

    SVNTrac은 설치에서 사용 및 응용이 쉽다. 때문에 빠르게 전파되어 지금은 많은 개발자들이 사용하는 관리 툴이 아닌가 한다. 간단하게 설명하고 바로 설치 및 연동을 해보기로 한다.


    Python으로 작성된 오픈소스로 웹기반의 프로젝트 관리 및 버그 추적 툴.
    Trac은 버전관리 프로그램(SVN)의 웹 인터페이스
    개선점 및 버그와 같은 각종 이슈의 트래킹
    위키 커뮤니티를 통한 문서의 관리 기능을 제공.





    서버-클라이언트 모델로 서버와 클라이언트는 http, https, svn, svn+ssh의 규약으로 통신한다.
    단위 등록이 가능하므로, 다른 사용자의 등록과 엉키지 않는다.
    이름을 변경, 복사, 삭제시에도 리버전 기록을 유지한다.
    파일의 저장 후 변경될 경우 차이점만 저장하기 때문에 저장소의 효율이 높다.
    디렉토리도 버전관리 할 수 있다.
    디렉토리 전체를 빠르게 이동, 복사 가능하며, 리버전 기록도 그대로 유지한다.
    저장소의 크기에 상관 없이 일정 시간안에 branching, tagging 할 수 있다.
    저장소의 접근이 최적화 되어 있어, 네트워크 트래픽을 줄일 수 있다.




     
    Apache + SVN + Trac 연동
    3가지의 소프트웨어를 연동하게 되면 보다 쉽게 프로그램의 컨트롤이 가능하다.
    Apache와 SVN을 연동하여 http통신 규약으로 SVN 컨트롤이 가능하다.
    SVN과 Trac을 연동하여 Trac을 통한 SVN저장소의 조회/관리가 가능하다.
    또한 Trac을 통하여 SVN으로 관리되고 있는 소프트웨어 및 소스코드를 배포 할 수 있다.
    이제 순서에 따라 프로그램의 설치 및 연동설정을 해보자.



    Download Program:다운로드 프로그램
    1. SVN: Setup-Subversion-1.6.5.msi
      (Apache 2.2 버전과 연동하기 위해 Apache 2.2 버전용 파일을 다운로드 받는다.)

      2009년 10월 27일 Setup-Subversion-1.6.5.msi(Apache 2.2.x)다운로드 URL
    2. SVN Client Gui Tool: TortoiseSVN-1.6.6.17493-win32-svn-1.6.6.msi
      (일명 거북이(TortoiseSVN)를 다운로드 받는다.)

      2009년 10월 27일 다운로드 URL
    3. Apache(아파치): apache_2.2.9-win32-x86-no_ssl-r2.msi
      (Apache 2.2.x 버전을 다운로드 받는다. ssl을 사용할 경우 openssl 포함 버전을 받는다.)

      2009년 10월 27일 2.2.14 no ssl 버전 다운로드 URL
      2009년 10월 27일 2.2.14 openssl 버전 다운로드 URL
    4. Python(파이슨): python-2.5.msi
      (Python 2.5 버전을 다운로드 받는다. 현재 2.6 버전까지 나와있지만 현재 Trac 및 SVN을 Apache와 연동하기 위한 연동 모듈이 2.5 버전으로 작성되어 있으므로 2.6버전을 설치하면 연동이 불가능 하다.)

      2009년 10월 27일 다운로드 URL
    5. Apache 와 SVN 연동 모듈: svn-python-1.6.5.win32-py2.5.exe
      (Apache 와 SVN의 연동 모듈로 파악.
      버전이 맞지 않을때 증상: SVN 설치, Apache 연동, Trac 생성까지는 문제가 없다. 이후 Trac 사이트를 열게되면 사이트가 열리지 않고 브라우저 에러가 발생후 페이지 표시할 수 없음을 볼 수 있다.)

      2009년 10월 27일 다운로드 URL
    6. Genshi: Genshi-0.5.1.win32-py2.5.exe

      2009년 10월 27일 다운로드 URL
    7. setuptools: ez_setup.py
    8. mod_python: mod_python-3.3.1.win32-py2.5-Apache2.2.exe
      (설치된 Apache 버전을 확인하여 사용 가능한 모듈을 다운로드 받는다.)

      modpython 사이트 : http://www.modpython.org/
      2009년 10월 27일 다운로드 URL
    9. pysqlite: pysqlite-2.5.5.win32-py2.5.exe
      2009년 10월 27일 다운로드 URL
    10. enscript: enscript-1.6.3-9-bin.exe
      2009년 10월 27일 다운로드 URL
    11. trac: easy_install http://svn.edgewall.org/repos/trac/tags/trac-0.11
      (현재 사이트에 등록되어있는 0.11.5 버전을 설치하게 되면 에러가 발생한다. easy install을 사용하여 설치하면 이상없이 사용 가능하다.)



    다운로드 해야할 파일이 생각 이상으로 많았다.
    그리고 각각의 프로그램이 버전별로 다양하여 버전을 맞추는 것도 중요한 포인트 이다.
    각각의 프로그램 및 모듈에 대한 보다 자세한 정보를 알고 싶을때에는 하단에 참고도서를 구매하여 읽어보면 많은 도움이 될것이라 생각한다.



    Install & Setting:설치에서 연동까지

     ※주의 : 본 내용은 SVN, 아파치, Trac에대한 설치 위주의 설명이다 때문에 사용법등은 자세하게 기록하고 있지 않다. 사용법에 대한 설명이 필요하신 분은 댓글로 문의 부탁드립니다. 

    1. SVN, SVN Client Tool 설치
    위자드 형식의 설치를 지원하며 특별한 처리 없이 Next를 눌러 설치 한다.
    (하단의 처리 내용은 기본설치 디렉토리 기준으로 설명을 합니다. 즉 C:\Program Files\Subversion 에 설치가 되어 있다는 가정을 합니다.)

    2. SVN 저장소 만들기
    명령 프롬프트를 실행한다.
    c:>mkdir c:\repos
    c:>cd c:\repos
    c:\repos>svnadmin create sample

    svnadmin 명령어를 사용하여 저장소를 생성할때에는 원하는 위치의 디렉토리로 이동 후에 생성할 저장소 명을 입력합니다.

    C 드라이브의 repos 디렉토리에 sample 저장소를 생성 했다.
    이 후 권한/계정/비밀번호 설정을 한다.
    (SVN 사용법에 대한 검색을 하시면 쉽게 찾아볼 수 있습니다. 따로 설명하지 않습니다.)

    3. SVN 저장소 실행
    SVN 저장소가 정상적으로 생성 및 작동하는지 확인 하기 위하여 server를 실행한다.

    명령 프롬프트를 실행한다.
    svnserve.exe -d -r c:\repos
    일반모드 실행(기본포트:3690) : 포트는 따로 설정하지 않고 기본포트를 사용한다.
    SVN Client Tool을 사용하여 CheckOut 테스트를 하여 서버의 이상 유무를 확인 한다.

    4. Apache 설치
    2.2.x 버전을 설치한다.

    5. Apache에 SVN 모듈 설치
    httpd.conf 파일을 열어 다음설정을 추가
    LoadModule dav_module modules/mod_dav.so
    LoadModule dav_svn_module "C:\Program Files\Subversion\bin\mod_dav_svn.so"
    LoadModule authz_svn_module "C:\Program Files\Subversion\bin\mod_authz_svn.so"

    ※ httpd.conf 파일은 아파치 설치 디렉토리의 bin 디렉토리에서 찾을 수 있습니다.
    대략 60라인에서 LoadModule라는 단어를 찾을 수 있습니다.
    위 내용의 모듈을 추가합니다.


    6. SVN + Apache 연동

    연동 모듈을 conf 파일에 명시한 후 Apache에서 사용할 계정/비밀번호를 설정한다.

    비밀번호 설정 파일 생성
    명령 프롬프트를 실행한다.
    c:>cd c:\repos
    c:>"C:\Program Files\Apache Software Foundation\Apache2.2\bin\htpasswd.exe" -c htpasswd admin
    권한 설정 파일 생성
    authz 파일을 저장소 Root (c:\repos)에 생성.
    파일을 메모장 등의 편집기를 통하여 다음과 같이 작성한다.
    [sample:/]
    admin = rw
    * =


    정상적으로 진행하였다면 C 디렉토리에는 다음의 디렉토리 및 파일을 찾을 수 있다.


    httpd.conf 파일에 다음설정을 추가
    NameVirtualHost *:80
    <VirtualHost *:80>
     <Location /svn>
      DAV svn
      SVNParentPath "C:\repos"

      AuthzSVNAccessFile "C:\repos\authz"

      AuthType Basic
      AuthName "Well Come !! Drake World"
      AuthUserFile "C:\repos\htpasswd"
      Require valid-user
     </Location>
    </VirtualHost>

    conf 파일을 수정한 이후 Apache를 Stop 시킨 후 Start 하여 http://localhost/svn/sample를 입력하여 저장소에 접근이 가능한지 확인 한다.
    또한 SVN Client Tool을 사용하여 http 통신 규약으로 저장소의 접근 및 관리가 가능한지 확인 한다.

    ※ 지금까지 순서에 맞게 진행하였다면 Apache 와 SVN의 설치에서 연동까지 확인이 가능할 것이다. 이제 Apache 와 SVN의 설치 및 연동을 완료하였다. 아직 갈 길이 멀다. 담배 한가치 태우면서 휴식을 취하자.







    충분히 휴식을 취하였는가? 그럼 상당히 애먹을 수 있을 작업을 시작해보자.
    위의 다운로드에서 가볍게 언급하고 지나갔지만 연동을 위해서 필수적으로 체크해야 하는 부분은 각각의 주요 프로그램들의 버전 정보의 확인 및 일치 작업이다.

    확인 및 일치 시켜야 할 버전 정보
    Apache 2.2.x
    SVN 1.6.x
    Python 2.5
    Trac 0.11

    다운로드 파일 목록의 버전 정보를 확인 후에 다운로드 파일의 버전이 일치 하지 않는다면 다시 맞는 버전을 다운로드 받는다. 설치 중 설치가 되지 않거나, 설치가 되어도 정상 작동을 하지 않는다.

    7. Trac 설치
    ※ 주의:python, svn, apache, trac 등의 버전을 확인하여 모두 일치할 수 있도록 한다.

    a. python 설치 : python-2.5.msi 실행
    b. svn-python 설치 : svn-python-1.6.5.win32-py2.5.exe 실행
    svn 과 python의 버전을 확인하여 설치된 버전에 맞는 프로그램을 설치

    c. Genshi 설치 : Genshi-0.5.1.win32-py2.5.exe 실행
    d. setuptools 설치  : ez_setup.py 실행
    e. mod_python 설치
    mod_python-3.3.1.win32-py2.5-Apache2.2.exe 실행
    apache 버전을 확인하여 설치된 버전에 맞는 프로그램을 설치
    httpd.conf 파일에 다음설정을 추가

    LoadModule python_module modules/mod_python.so

    f. pysqlite 설치 : pysqlite-2.5.5.win32-py2.5.exe 실행
    g. enscript 설치 : enscript-1.6.3-9-bin.exe 실행
    h. trac 설치
    ※ 참고한 서적에 나와있는 설치 버전과 지금 현재의 최신 버전은 버전의 차이가 있다. 또한 지금까지 설치한 다른 모듈 및 프로그램과의 버전 문제가 있어서 쉽게 설치 되지 않았다.

    현재까지 필자가 제시한 모듈 및 프로그램을 그대로 다운로드 하여 설치한다면 Trac을 다음과 같이 설치해보자.
    easy install을 사용하여 설치하는 방법으로 Python을 2.5로 설치 하였다면 C:\python25\script 디렉토리에서 easy_install 또는 easy_install.exe 파일을 발견할 수 있다.

    명령 프롬프트를 실행한다.

    c:>cd c:\python25\script
    c:\python25\script>easy_install http://svn.edgewall.org/repos/trac/tags/trac-0.11

    easy install을 실행하여 0.11 버전의 trac을 설치 한다.

    8. Trac 생성
    지금까지 설치가 정상적으로 되었다면 다음 명령어를 통하여 Trac을 생성 할 수 있다.

    Trac의 Root 디렉토리로 사용할 디렉토리(C:\trac)를 생성한다.
    명령 프롬프트를 실행한다.

    c:\Python25\Scripts>trac-admin.exe c:\trac\sample initenv

    ※ 명령어 설명
     - trac-admin.exe : trac 프로젝트를 생성하는 명령어
     - c:\trac\sample : trac root 디렉토리 c:\trac에 sample 라는 trac을 생성
     - initenv : 생성 명령어

    Trac이 정상적으로 설치 되어 있다면 다음과 같은 화면을 보게된다.



    [My Project] 에는 프로젝트 명으로 sample 를 입력.
    [sqlite:db/trac.db] 엔터를 입력하면 기본 설정된다.
    [svn] 저장소의 저장 형태를 입력하는 부분으로 엔터를 입력하면 기본 설정된다.
    [/path/to/repos] 저장소의 path를 입력한다.

    마지막 엔터를 입력한 순간 Trac이 생성된다. 모듈이 모두 정상적으로 설치되어 있다면 Congratulations! 라는 메시지를 보게되면 그렇지 않다면 오류가 나는 부분의 에러를 확인 할 수 있다.
    대부분의 에러는 버전이 일치하지 않아 발생한다.

    9. svn + apache + trac 연동설정
    마지막으로 apache 와 trac를 연동하여 웹 브라우저를 통하여 확인해 보자.

    httpd.conf 파일의 <VirtualHost> 태그의 자식 노드로 다음 내용을 추가한다.
    위에서 SVN과 Apache를 연동하기 위하여 Location 설정을 해보았다.
    기본 입력 Host에 Trac의 입력 Location을 추가하는 과정이다.
    NameVirtualHost *:80
    <VirtualHost *:80>
     <Location /svn>
      DAV svn
      SVNParentPath "C:\repos"

      AuthzSVNAccessFile "C:\repos\authz"

      AuthType Basic
      AuthName "Subversion repository"
      AuthUserFile "C:\repos\htpasswd"
      Require valid-user
     </Location>

     <Location /trac>
      SetHandler mod_python
      PythonHandler trac.web.modpython_frontend
      PythonOption TracEnvParentDir "C:\trac"
      PythonOption TracUriRoot "/trac"
     </Location>

     <LocationMatch "/trac/[^/]+/login">
      AuthType Basic
      AuthName "Trac"
      AuthUserFile "C:\repos\htpasswd"
      Require valid-user
     </LocationMatch>

    </VirtualHost>

    주의를 기울여 보면 알겠지만 C:\repos에 위치하는 htpasswd 파일을 같이 사용하여 관리한다.

    10. SVN + Apache + Trac 연동확인
    모든 작성이 완료되면 Apache 서버를 정지 후 다시 실행 시킨다. Restart를 하면 설정정보를 다시 읽어오지 않기 때문에 Stop 후 Start 하여 실행한다.

    인터넷 브라우저를 열고 http://localhost/trac를 입력하여 정상작동을 확인한다.
    생성한 sample 프로젝트의 링크를 클릭하여 정상작동을 확인한다.

    이후의 설정 및 다양한 추가 설정은 스스로 확인 해보자.
    아래 추천하는 서적을 읽어보면 필요하다 싶은 내용은 다 나와있다.


    참고 자료
    위에 설명된 내용은 기존에 알고 있던 몇가지 사항 외에는 많은 부분을 책에서 도움받았다.

    윈도우 프로젝트 필수 유틸리티 - 10점
    이재홍 지음/한빛미디어


    프로젝트의 운영관리를 위한 개발환경의 구성과 필요한 유틸리티들이 잘 소개되어 있다.
    본문의 내용중에 나온 SVN 과 Trac의 보다 많은 사용법과 특징, 개념 등에 대한 설명이 잘 되어있는 편이다. 그리고 쉽고 필요 요소만이 설명되어 있기 때문에 부담없이 볼수 있는 책이다.

    책에대한 자세한 내용은 다음에 독후감의 형식을 빌려 소개하기로 하자.

    프로그램 파일의 대부분은 Google 검색을 통하여 찾았다.
    아직은 원하는 내용의 프로그램들을 한번에 다운로드 하여 통합 설치하는 형식의 것들은 나와있지 않다.
    그리고 버전에 맞는 프로그램을 다운로드 하는 것 또한 만만한 일이 아니였다.


    출처 : http://codepedia.tistory.com/80