제 경운 어제 소스코드 버전 관리를 위해 '서브버전'이라는 툴을 사용해보기로 했습니다.

처음엔 제 컴퓨터(로컬)에 관리툴 서버역할(저장소)를 설치하겠다는 목표였고

각 블로그를 참고하며 빠르게 성공할 수 있었습니다.(visual svn server)

 

 

두번째 목표가 바로 생겼는데 '휴대성및 원격 작업을 편하게 하기위해' 웹상에

저장소를 만들어보면 어떨까?란 발상을 하게 되었고 이런 저런 정보를 찾던중

아영이를 통해 네이버 개발자 센터라는 것을 알게되었고 그곳에서 svn도 지원을

 

해주더군요, 순조롭게 작업 진행중 계속 commit이 실패하는 문제가 생겼고,

저는 이 문제에 대해 약 12시간 가량 매달렸던것 같습니다.

 

 

(수업에 집중도 못하고, 제가 공부하고 있는  jsp진도도 못나가고.. 자괴감에

오늘 아침엔 악몽까지 꿨습니다.)

 

 

만약, 애초에 제가 계획한 제 로컬에 저장소 설치를 완료했으니, 네이버 저장소

이용이 계속적으로 실패했다면..

 

"적당히 끊을줄 아는 지혜가 필요했던것 같습니다."

 

 

 

예전 로또 프로젝트에서 로또번호란 vo데이터를 문자열로 처리하겟다는 마음을

먹고 엄청나게 고생을 했던 경험이 있엇는데도요..(덕분에 문자열 처리 관련해

이런 저런 경험을 쌓을수 있었지만요)

참고: http://cafe.naver.com/javachobostudy/96627

 

<추가> 로또 번호를 문자열로 만든 의미를 알게 되었음. 선생님께서 웹상의 유저 입력

데이터를 자바 단(서블릿)으로 가져올때 문자열로 밖에 가져올수 없다고 말씀하심.

결국 파싱 작업이 필요하다. 내가 String lottoNumber를 처리를 위해 int[] makeIntArray

(String lottoNumbers) 이걸 만들었었다. (etx)이름은 convertXXX가 더 나을듯 하다.

 

웹의 모든 데이터는 자바에서 문자열로 읽게되나? <-- 이 문제는 아마 나름 api들이

getInt()식으로 구현을 해놓지 않았을까 한다..

 

저는 생각보다 고집이 강한가 봅니다. 제가 발상을 떠올렸으면.. 그것을 무조건

성공시켜야 하고, 그것이 잘 풀리지 않을땐 엄청난 스트레스를 받아서 자포자기의

감정까지 발생을 시키고.. (자포자기 전까진 고집 때문에 다른 방법, 적당한 타협을

받아들이려 하지 않는것 같습니다.)

 

이전에 오라클 12c설치 작업을 할때에도, 기타 이런 저런 공부를 할때에도 비슷한

느낌을 받았습니다. 지훈이 형님께선 반드시 필요한 정보만 찾아 쉽게쉽게 접근을

하시는 것을 보고 느낀점이 많았는데.. (공부는 수단일뿐 목적이 아니다는 명언)

 

저는 어제 또한번 헤매고 좌절감을 경험했네요..

 

 

신은 개개인에게 다양한 재능을 주신듯 합니다. 제가 문제를 푸는 것을 좋아하고,

적당히를 모르고 몰입하는 성향이 있는 반면, 다른 분야를 좋아하고 그것을 행함

에 있어 다른 성향을 보이는 분들도 계실테고..  "누가 좋다,옳다,뛰어나다"는 아닌

것 같습니다.(저의 고집있는 성향도 어딘가에 쓸모가 있을 수 있겠지요 ^^;)

 

서로 다른 개체간에 영향을 받아가며 조화를 이루는 과정.. 저도 여러분들께 많이많이

배우고 싶습니다. (저와 다른 다양한 생각들,문제 처리 방법들을 수용하고 싶습니다.

자칫 저만의 잘못된 아집으로 이번 처럼 삽질할 수 있으니까요)

 

 

ps.제가 이것 저것 욕심이 많아서 바빠 보이지만, 사실 저도 별로 실속은 없습니다.

저의 도움이 필요한데, 혹시 제가 부담스러워 할까봐 도움 청함을 망설이시는 분들

부담 내려놓고 요청하세요. 가능한 범위에서 , 확실하게 아는 범위에서 도와드릴께요.

(무엇보다 선생님께 질문하고 정답을 얻는것이 가장 현명한 방법입니다. 기억에도

오래남을테고요)

 

(추가로 제게 도움을 청하실때 문제풀이,개발 관련 질문이라면 조건을 하나 달겠습니다.

묻기 전에 수첩에 로직or자신의 문제 풀이 접근 아이디어or 모르는 상황을 서술해 올것.

문제를 저와 함께 풀어 냈을땐 최소 2명에게 공유할것! 입니다.)

 

 

이전에 저는 제일만 책임지고 싶다고 강조한 적이 있었는데.. 그 선언은 민망하지만,

오늘의 깨달음으로 철회하겠습니다. "함께 고민한다"의 중요성을 알아버렸기도 하고,

무엇보다 사실.. 저는 여러분들을 좋아하거든요 ㅎㅎ

 

단지 조급함 (제 처지:나이-실무경험-시간부족) 때문에 선을 그으려 한것이고요. 

반성할께요~ 오늘도 좋은(행복+의미있는) 하루가 되기를!

 

 

ps2.오늘 버스타고 오면서 생각한 잡설

 

1.디폴트 생성자의 역할.

=>저는 여전히 모든 멤버 필드(어트리뷰트)를 받는 생성자만이 필요하다고 생각하지만,

해당 클래스가 상속 트리 계층에 속해 있다면, 상위타입(부모)의 생성자를 호출해주는

연결 과정은 무척 중요합니다. 모든 멤버 필드를 받는 하위 클래스의 생성자에서도

명시적으로 super(); 를 호출해 줘야하듯이..

 

즉 디폴트 생성자는 위험성은 있지만, 상위 타입의 생성자를 호출하는 super()가 암시적으

로 숨어있기에 자칫 깜박하고 super()를 비호출하는 위험을 줄여준다고 생각했습니다.

(정확히 맞는지는 모르겠네요)

 

아 그러고 어제 배운 object클래스의 equal,hashcode,copy란 개념은 확실히 해두시는 것이

좋습니다. 제 예전글에서 한번 집어본 기억이 있는데.. 개체간의 "비교"한다는 연산은

전산에서 중요한 연산중 하나입니다. 서로 같은지 다른지 알아야 식별해서 조회도 할것이며,

식별이 되야 정렬도 할것이며, 식별을 해야 추가및 삭제도 할것이며..

 

레퍼런스 형의 메모리상 주소 비교&대입(치환) 연산   vs    개체가 가지고 있는 멤버필드들(어트리뷰트들)간

의 비교&대입 연산의 구분!   을 강조합니다.  (hash란 개념은 "식별"보단 "효율적인 식별과 배치"

의 개념이니 논외할께요)

 

개인적으로 훌륭한 블로그라 생각합니다. 제게 엄청난 영감과 깨달음을 주는 곳

(불펌)  http://iilii.egloos.com/4427484

 

 

-(추가) equals , hashCode 재정는 아래처럼 한다. (.는 멤버필드의 value이고

hashCode에서 상위 클래스(Object등)에 정의된 hashCode값에 비트연산 xor(서로 비트값이 다를떄만 1을 리턴)

를 하는것에 주목할것!   <--> 비트 마스크를(&연산) 이용해 추출하는 것과 다른 xor의 사용법임!

원본 1100 xor 암호키 1000 => 암호데이터 0100 xor 암호키 1000 => 1100 이거 + 비트간 자리수 이동 반복이 DES?

 RSA는 머였지? 공개키 머시기 였는데;;)

*********************************************************************************

     public boolean equals(Object obj) {
         return obj instanceof GregorianCalendar &&
             super.equals(obj) &&
              == ((GregorianCalendar)obj).;
     }

    
Generates the hash code for this GregorianCalendar object.
 
     public int hashCode() {
         return super.hashCode() ^ (int);
     }

 

*************************************************************************************

 

 

-(추가2) 매개변수를 잘못 받은 워커측의 대처 방법 ㅋㅋ (콜러야 니잘못이다 나는 처리 못한다. 옛다 받어라~

그러면 콜러측에선 입력값에 대한 재처리등 작업을 할 수 있다. 물론 내가 정의한 익셉션 객체를 던지면

추가 정보도 전달해 줄 수 있을것이고. (ex)선생님이 말씀하신 주문수량 vs 재고수량 tradeOff)

 

**************************************************************************************

 

public void add(int fieldint amount) {

         // If amount == 0, do nothing even the given field is out of
         // range. This is tested by JCK.
         if (amount == 0) {
             return;   // Do nothing!
         }
 
         if (field < 0 || field >= ) {
             throw new IllegalArgumentException();
         }

 

*************************************************************************************

 

2.저는 인터페이스를 두가지 의미로 구분을 했는데.. 조금 더 구분을 할 필요를 느꼇습니다.

a.해당 클래스 계층 트리에서 설계의 의미.

b.다른 역할 클래스(비지니스 클래스,입력처리 클래스,화면 그리기 클래스,데이터 관리 클래스

기타 등등) 및 패키지및 서스시스템... 과 서로간 association(상대 객체가 제공하는 메서드 호출)

관계에서 public으로 노출해주는 메서드명.

 

이중 b를 한번 더 쪼개야 할듯 싶단 생각을 했습니다.

b.클래스 외부에 노출하는 public 메서드 = 외부 인터페이스

c.클래스 내부의 각종 작업을 위해 쪼개진 private 메서드들 간에도 서로간 소통 관계(associ...)

있기 때문에 그것을 = 내부 인터페이스

 

정확한 지식이 아닌, 착상 수준의 느낌입니다. 주의해주세요!




<2013.11.27 코드컴플리트중 상속과 오버라이딩 관련 추가>


1. 상속 계층 트리에서 메서드 오버라이딩 할때 구분할 개념들





a.오버라이드 가능한 "추상" 루틴(=메서드)은 파생 클래스가 루틴의 인터페이스를 상속받지만 구현부는 상속받지


않는다는 것을 의미한다.=>설계(interface)와 구현의 분리




b.오버라이드 가능한 루틴은 파생 클래스가 루틴의 인터페이스의 기본 구현을 상속받으며 기본 구현을 오버라이드할


수 있다는 것을 의미한다. =>Object 클래스의 equal() , hashcode(), copy() 등을 내 클래스의 사용 목적에 맞게 재정의


하는것




c.오버라이드 불가능한 루틴은 파생 클래스가 루틴의 인터페이스와 기본 구현을 상속 받지만 루틴의 구현을 오버라이드


할수 없다는 것을 의미한다. =>즉 해당 인터페이스 클래스가 외부에 노출시키는 public 인터페이스(메서드)를 의미




(ex)


 public abstract class Base


{


a. public abstract void method;




b. public void method()


{


   doSomething~ 

}




c. public final void method()


{


   doSomething~

}



}





=> 인터페이스를 상속(a)받고 싶을땐 구현 상속(b)을 주의하고, 구현을 상속받고 싶을땐 인터페이스 상속을 주의하고


만약 인터페이스는 필요없고 구현만 사용하고 싶다면 상속 대신 포함(agreegacion)을 사용하라! => stratergy패턴을 의미






2.오버라이드 불가능한 멤버 루틴을 오버라이드 하지 말것 (ex) Base의 private void method()를 Child가 private void method()


=> 별개의 루틴이지만, 이름이 똑같이에 다형성인듯 착각되기 쉽기 때문




3.공통적으로 사용되는 인터페이스,데이터,행위를 상속트리에서 가능한 한 가자 높은 곳으로 이동시킨다


=>높이는 정도는 해당 루틴이 해당 객체의 추상화를 깰때. 음.. Dog 에 있는 eat() Tiger 에 있는 eat()는 


   Animal의 eat()으로 이동이 가능하지만, eat()을 Object클래스에 올리면 Object 클래스의 '일반적'개념이 부셔지지..




4.인스턴스가 하나뿐인 클래스를 의심하자


=>파생시킨 클래스가 별개의 클래스로서가 아니라 데이터로 표현될수 있나?를 고려해야 한다. is a가 아닌, has a 인지,


   이도 저도 아니라면 서로 다른 계층 트리에서 xxAble이라고 interface class를 통해 특정한 속성의 집합으로 묶을수 있다.


   단, 싱글턴은 예외이다. 동물들에 싸움 기능을 추가하고 싶다고 dog -> fightAbleDog , nonFighterAble로 파생시켜 확장


   하는 것은 미친짓. 차라리 Animal에 FighteAble 필드를 추가하거나, FighteAlbe을 인터페이스 클래스로 구현해 implements


   하거나..




5.파생클래스가 하나뿐인 기본 클래스를 의심하자


=>너무 앞서서 설계했다. 가능한한 현재의 작업을 분명하고 직관적이며 단순하게 만드는게 중요하다.




6.루틴을 오버라이드하고 파생된 루틴 내부에서는 아무것도 하지 않는 클래스들을 의심하자.


=>기본 클래스 설계의 오류를 암시한다. "is a   vs    has a "




7.깊은 상속 트리를 피하자


=>내 경우에 awt를 분석하고 java api의 클래스들간 관계성을 분석할때 해당 클래스가 깊은 계층 트리에 있어서 복잡성


이 심했다.




8.간결및 직관성 vs 디자인 패턴


=> 무조건 패턴(추상적인 설계)을 적용시켜야만 할까?





(ex)


switch( ui.Command() )


{


 case Command_OpenFile:


         OpenFile();


          break;


  


  case Command_Print:


          Print();


          break;




  case Command_Save:


          Save();


          break;




  case Command_Exit:


           Exit();


          break;


   ...


}




=> 이 경우에 기본 클래스를 생성하여 각 명령에 대한 다형성 DoCommand()메서드를 만들수 있다


( Command패턴 ) 하지만 위처럼 switch case간단하고 명확한 경우엔 굳이 Command패턴을


사용해 비 직관적이게 만들 필요가 없다.





9.상속 계층 트리에서 기본 클래스의 모든 데이터(멤버필드)를 protected가 아닌 private로 만들자?


=>상속은 캡슐화를 부순다(joshua bloch) 그럼으로 파생 클래스에서 기본 클래스의 특성을 접근해야


한다면 protected 접근 메서드를 대신 제공하라.  <- 개념엔 동의를 하지만, 실제 구현시 너무 귀찮아짐으로


패스





10.다중 상속은 미친짓


=>다이아몬드 상속구조와 그에 따른 메서드명 중복, 생성&소멸자의 호출순서등 너무 복잡해짐으로 무조건 동의. 


더이상 노코멘트 








1~10 정리


a.만약 다중 클래스가 데이터는 공유하지만 행위를 공유하지 않는다면, 클래스가 포함할수 있는 객체를 만든다.


=>연산은 공유하지 않고 특성만 공유할 경우(has a)





b.만약 다중 클래스가 행위는 공유하지만 데이터를 공유하지 않는다면, 공통적인 루틴들을 정의한 기본 클래스를 


상속받는다.


=>인터페이스(외부 노출 public 메서드에 대한 계약or통제) 즉, 인터페이스 클래스의 존재 의의와 개념





c.만약 다중 클래스가 데이터와 행위를 공유한다면, 공통적인 데이터와 루틴들을 정의해 기본 클래스를 상속받는다.


=>일반 베이스 클래스 or 추상 클래스의 존재 의의와 개념





d.인터페이스를 제어하기 위한 기본 클래스가 필요할 때에는 상속을 하고(인터페이스 클래스를 의미), 인터페이스를


제어하고 싶다면 포함시킨다.(stratergy패턴 = 메서드의 확장)











<멤버 함수와 데이터를 효율적으로 구현하기 위한 몇가지 지침들>





1.클래스에 가능한 한 적은 수의 루틴을 유지





2.원하지 않는 멤버 함수와 연산자들이 암시적으로 생성되지 않도록 주의


=>자바의 경우 컴파일러가 추가해주는 암시적 default 생성자및 Object클래스에서 상속 받게 되는 


copy() 참조주소 복사 , equal() 참조주소 비교 , hashCode() 참조주소를 통한 해쉬코드 등을 의미한다.


즉 내 클래스의 목적과 특성에 맞도록 재정의해야만 하고, 또한 주의해야만 한다.





3.클래스에서 호출되는 루틴의 수를 최소화


=>클래스가 타 클래스와 assciation이 많아지면 오류가 증가할 가능성이 많아지고 이것을 "팬아웃" 이란 용어로 사용





4.다른 클래스에 대한 간접 루틴 호출을 최소화("데미테르의 법칙")


=> 객체 A가 객체 B를 인스턴스화했다면, B가 제공하는 루틴은 어느 것이던 호출이 가능하지만 , B에 의해 제공되는


객체들(C,D)의 루틴은 호출하지 말아야 한다.


(ex) account.contactPerson()   vs   account.contactPerson().dayTimeContactInfo()





5.일반적으로 클래스가 다른 클래스와 협력하는 정도를 최소화(4번을 다시 설명)


a.인스턴스화되는 객체의 수


b.인스턴스화된 객체에 대한 서로 다른 직접적인 루틴 호출의 수


c.인스턴스화된 다른 객체에 의해서 리턴되는 객체에 대한 루틴 호출의 수 








<생성자에 필요한 지침>





1.가능하다면 모든 멤버 데이터를 모든 생성자에서 초기화


=>내 경우에도 이것을 동의함. 매개변수 없는 생성자는 너무 위험하다고 느낌.(reflect를 이용해 생성할때


  클래스에 정의된 매개변수있는 생성자 타입 객체를 만드는게 가능한데.. 왜 프레임워크 들에서 단순하게 


  디폴트 생성자 타입 객체를 인스턴스화하고 거기에 invoke를 이용해 setter로 멤버 데이터를 초기화 하는진 의문임..)





2.private 생성자를 사용하여 싱글턴 속성을 구현


=>잘 알기에 패스 (단, 멀티스레드 환경을 고려할때 getInstance()의 if(instance == null) syncronized(instance) if(instance


  == null) {instance = new ClassType();} <- 이 패턴을 기억해둘것 (첫번째 if조건은 비 인스턴스화시 불필요한 연산을 


  방지하기 위한 성능 향상 목적이고, 두번째 if조건은 멀티스레드 환경을 고려한 구문임)





3.다른 사항이 증명될 때까지 얕은 복사보다 깊은 복사를 하자


=>동의함. value비교,복사는 시간은 오래 걸리지만, 객체의 독립성을 보장해줌. reference(주소)비교 복사는 시간은 빠르지만


객체의 독립성을 보장해주지 않고, 객체의 메모리상 존재만 보장해줌. 그럼으로 copy, equal, hashCode 는 기계적으로 해주자. 나중에 참조 형태로 풀어주더라도..








<클래스를 작성하는 이유>





1.실세계의 객체를 모델링





2.추상 객체들을 모델링





3.복잡성을 줄인다 


=>캡슐화&정보은닉&무엇을 public으로 노출시킬것인가 = 무엇을 private로 감출 것인가에 대한 고찰





4.복잡성을 고립시킨다.


=>클래스의 역할및 개념정의 책임의 영역 설정, 타 클래스와의 불필요한 관계 단절





5.세부적인 정보를 숨기자(3번과 동일. Interface적 의미)





6.변경의 영향을 제한할것(3,5의 정보 은닉과 동일)


=>(ex)하드웨어에 의존적인 부분(display,io등), 비지니스 규칙, 복잡한 데이터형





7.전역 데이터를 숨길것


=>클래스에서 public 으로 멤버 필드를 노출해주면 전역 데이터 처럼 사용이 가능한데.. 이것은 멀티스레드에


   안전하지 않을 뿐더러 관계되는 여러 클래스들이 전역 데이터에 의존적이게 됨





8.association에서 매개변수의 전달을 간소화


=>만약 어떤 매개변수를 여러 루틴들 사이에서 전달하고 있다면, 매개변수를 객체 데이터로 공유하는 클래스에 


이 루틴들을 포함시켜야 할 필요성이 있다는 것을 암시





9.중앙 집중 관리할것 


=>Format, Word(비지니스로직)의 설계를 reminding , 즉 Word는 여러개의 부분들을 통합해 의미 있는 업무


 를 창출하는 중앙 통제자의 역할임





=> 이해가 부족함. 코드 컴플릿2 236p.. 매우 중요한 개념 같은데.. 프레임 워크의 개념을 의미하는 것일까?





10.코드의 재사용을 도울것


=>재사용 가능성이 높은 일반적인 연산이라면 별도의 클래스로 추출하는 것이 효과적(중복 코드 방지)


   내 경운 이것을 클래스or 멤버 메서드로 뽑아내는 것만 생각했지 클래스로 추출한다는 것은 생각을 못했음.


   왜냐하면 객체지향이란, 연산의 집합이 아닌, 데이터 + 연산의 집합이기 때문.





11.프로그램군(family)를 위한 계획을 작성 (10을 다시 설명)





(ex) 수년전에 나는 보험을 파는 고객이 사용할 일련의 프로그램들을 작성하는 팀을 관리했얶다. 우리는 각 프로그


램을 작성하는 팀을 관리했었다. 우리는 각 프로그램을 고객의 보험률과 보고서 양식등에 맞추어야 했다. 하지만 프로그램의


많은 부분들이 유사했었다. 잠재적인 고객에 대한 정보를 입력하고 고객 데이터베이스에 정보를 저장하고, 보험률을 검색하고


,특정 그룹의 전체 보험료를 계산하는 클래스들이 비슷했다. 처음 프로그래밍했을 때는 석 달 정도 결렸던 것 같은데, 새로운


고객이 생겼을 때에는 새로운 고객을 위해서 새로운 클래스를 몇 개만 작성하여 나머지 코드 부분에 추가하였다.


몇일 동안 작업을 한 다음 , 소프트웨어 완성!  





=>내 이해가 부족해서 책의 내용을 그대로 옮겼음. 하지만 다수의 인스턴스를 관리하는 매니저 클래스의 연산인


   생성,삽입,조회,정렬,수정,제거,소멸은 알고 있다.





12.연관된 기능을 패키지화하자


=>정보를 숨기거나, 데이터를 공유하거나, 유연한 계획을 세울 수 없는 경우엔 관련된 기능들을 도메인 그룹으로 패키지


화 해서 묶자. 문제 발생시 전체 시스템에 파장이 적어진다. (즉 위에서 집어본 독립성과 동일한 개념)





13.특정한 리팩토링을 수행 (아직 개념이 정립이 안돼서 패스)





(ex)하나의 클래스를 두 개의 클래스로 변환하고(역할,개념적 분리?) 델리게이트(delegate=대표)를 감추고,


미들 맨 (middle man)을 제거하고, 확장 클래스를 만드는 방법으로 새로운 클래스들이 만들어진다. 





=>책의 내용 그대로 옮김(추후에 이해될듯.. 현재로선 내가 아는 범위 밖의 내용임)








<피해야할 클래스>


1.만능 클래스를 생성하지 말것


=>당연.. 코드가 더럽게 꼬이고 추후 수정도 거의 불가능





2.관련이 없는 클래스들을 제거할것


=>클래스의 위상이 아니다, 끽해봐야 내부 클래스 위상





3.동사가 따라오는 클래스를 피할것


=>다른 클래스의 루틴의 일부로








<전체 요약>


1.실세계의 객체를 모델링


2.추상객체를 모델링


3.복잡성을 줄일것


4.복잡성을 고립시킬것


5.세부적인 정보를 숨길것


6.변경의 영향을 제한할것


7.전역 데이터를 숨길것


8.매개변수의 전달을 최소화 할것


9.중앙 집중 관리할것


10.코드의 재사용을 도울것


11.프로그램군을 위한 계획을 작성할것 (이해 상당히x)


12.연관된 기능을 패키지화 할것(아주 살짝 이해)


13.특정한 리팩토링을 수행할것 (이해 전혀x)



by givingsheart 2014. 1. 1. 15:15
  
Called by the server (via the service method) to allow a servlet to handle a OPTIONS request. The OPTIONS request determines which HTTP methods the server supports and returns an appropriate header. For example, if a servlet overrides doGet, this method returns the following header:

Allow: GET, HEAD, TRACE, OPTIONS

There's no need to override this method unless the servlet implements new HTTP methods, beyond those implemented by HTTP 1.1.

Parameters:
req the HttpServletRequest object that contains the request the client made of the servlet
resp the HttpServletResponse object that contains the response the servlet returns to the client
Throws:
java.io.IOException if an input or output error occurs while the servlet is handling the OPTIONS request
javax.servlet.ServletException if the request for the OPTIONS cannot be handled
    protected void doOptions(HttpServletRequest reqHttpServletResponse resp)
        throws ServletExceptionIOException
    {
//아까 분석한 대로 내가 재정의한 HttpServlet 파생 클래스부터 HttpServelt 이전 까지 정의도니 내가
//"재정의한" 메서드들 리턴.
        Method[] methods = getAllDeclaredMethods(this.getClass());
        
        boolean ALLOW_GET = false;
        boolean ALLOW_HEAD = false;
        boolean ALLOW_POST = false;
        boolean ALLOW_PUT = false;
        boolean ALLOW_DELETE = false;
        boolean ALLOW_TRACE = true;
        boolean ALLOW_OPTIONS = true;
        
        for (int i=0; i<methods.lengthi++) {
            String methodName = methods[i].getName();

     //너무 직관적인 코드니 생략. get은 <a> <img>였나? 이미지나 문자 보낼때 자동으로
     //get메서드 실행되고, 그외엔 보안등 강점을 이유로 대부분 post로 사용한다고
    //했었던 기억이 뇌리를 스침..
            if (methodName.equals("doGet")) {
                ALLOW_GET = true;
                ALLOW_HEAD = true;
            } else if (methodName.equals("doPost")) {
                ALLOW_POST = true;
            } else if (methodName.equals("doPut")) {
                ALLOW_PUT = true;
            } else if (methodName.equals("doDelete")) {
                ALLOW_DELETE = true;
            }
            
        }
        
        // we know "allow" is not null as ALLOW_OPTIONS = true
        // when this method is invoked

//오 위에서 직관적이라 표현한 부분이 아래의 처리를 위해서 그런거였구나..
//내가 재정의한 메서드를 통해 나만의 스타일로 스크립트 문자열을 만들어주고 있는듯?
        StringBuilder allow = new StringBuilder();
        if (ALLOW_GET) {
            allow.append();
        }
        if (ALLOW_HEAD) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        if (ALLOW_POST) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        if (ALLOW_PUT) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        if (ALLOW_DELETE) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        if (ALLOW_TRACE) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        if (ALLOW_OPTIONS) {
            if (allow.length() > 0) {
                allow.append(", ");
            }
            allow.append();
        }
        
        resp.setHeader("Allow"allow.toString());
    }
    
    
    
Called by the server (via the service method) to allow a servlet to handle a TRACE request. A TRACE returns the headers sent with the TRACE request to the client, so that they can be used in debugging. There's no need to override this method.

Parameters:
req the HttpServletRequest object that contains the request the client made of the servlet
resp the HttpServletResponse object that contains the response the servlet returns to the client
Throws:
java.io.IOException if an input or output error occurs while the servlet is handling the TRACE request
javax.servlet.ServletException if the request for the TRACE cannot be handled
    protected void doTrace(HttpServletRequest reqHttpServletResponse resp
        throws ServletExceptionIOException
    {
        
        int responseLength;
//캐리지 리턴과 라인 넥스트의 조합? 한칸 내리고 제일 앞으로 땡기고? 타이핑?
// == 엔터키를 쳣을때 입력되는 값을 의미한다. (엔터치면 \r\n 이 들어옴)
        String CRLF = "\r\n";

// TRACE 도 스크립트 언어인듯함? 유저의 url주소 적어주고, 유저가 보낸 프로토콜(일반적으론 http)
//적어주고
        StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
            .append(" ").append(req.getProtocol());
//대충 .jsp파일 만들었을때 제일 앞에 위치하던.. 이 정보를 만드는 과정 아닐까? 싶은데..
//아직 기본개념및 이해가 부족하다...
/*
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

*/
        Enumeration<StringreqHeaderEnum = req.getHeaderNames();
        whilereqHeaderEnum.hasMoreElements() ) {
            String headerName = reqHeaderEnum.nextElement();
            buffer.append(CRLF).append(headerName).append(": ")
                .append(req.getHeader(headerName));
        }
        buffer.append(CRLF);
        responseLength = buffer.length();
        resp.setContentType("message/http");
        resp.setContentLength(responseLength);
        ServletOutputStream out = resp.getOutputStream();
        out.print(buffer.toString());
    }


    
Receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class. This method is an HTTP-specific version of thejavax.servlet.Servlet.service(javax.servlet.ServletRequest,javax.servlet.ServletResponse) method. There's no need to override this method.

Parameters:
req the HttpServletRequest object that contains the request the client made of the servlet
resp the HttpServletResponse object that contains the response the servlet returns to the client
Throws:
java.io.IOException if an input or output error occurs while the servlet is handling the HTTP request
javax.servlet.ServletException if the HTTP request cannot be handled
See also:
javax.servlet.Servlet.service(javax.servlet.ServletRequest,javax.servlet.ServletResponse)
    protected void service(HttpServletRequest reqHttpServletResponse resp)
        throws ServletExceptionIOException
    {
//유저가 보낸 요청 메서드는 무엇이냐? get?post?
        String method = req.getMethod();
        if (method.equals()) {


//getLastModified가 뭐였지? part1에 있던건가.. part1에서 잘라왔음.
/*
<div class="line" id="line-245" style="font-family: 'Lucida Grande', Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: -2px 0px 0px; padding: 0px 0px 0px 10px; color: rgb(68, 29, 42); white-space: normal;"><div class="lnml" id="lnml-245" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><div class="ln" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px 6px; display: inline;">
245
</div><div class="lnmr" id="lnmr-245" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><pre style="margin-top: 0px; margin-bottom: 0px; display: inline;">    protected long getLastModified(HttpServletRequest req) {</pre></div><div class="line" id="line-246" style="font-family: 'Lucida Grande', Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: -2px 0px 0px; padding: 0px 0px 0px 10px; color: rgb(68, 29, 42); white-space: normal;"><div class="lnml" id="lnml-246" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><div class="ln" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px 6px; display: inline;">
246
</div><div class="lnmr" id="lnmr-246" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><pre style="margin-top: 0px; margin-bottom: 0px; display: inline;">        return -1;</pre></div><div class="line" id="line-247" style="font-family: 'Lucida Grande', Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: -2px 0px 0px; padding: 0px 0px 0px 10px; color: rgb(68, 29, 42); white-space: normal;"><div class="lnml" id="lnml-247" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><div class="ln" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px 6px; display: inline;">
247
</div><div class="lnmr" id="lnmr-247" style="font-family: 돋움, dotum, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: 0px; padding: 0px; display: inline;"></div><pre style="margin-top: 0px; margin-bottom: 0px; display: inline;">    }
</pre></div><div class="line" id="line-247" style="font-family: 'Lucida Grande', Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 12px; list-style: none; margin: -2px 0px 0px; padding: 0px 0px 0px 10px; color: rgb(68, 29, 42); white-space: normal;"><pre style="margin-top: 0px; margin-bottom: 0px; display: inline;">*/</pre></div>


            long lastModified = getLastModified(req);
//수정된 서블릿은 부가적 작업을 건너뛰네?
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(reqresp);
            } else {
//어떤 경우에 일로 빠지는 거지? (maybeSetlastModified()가 변경하는건가?)
//나머진 내일 분석!!!!!
                long ifModifiedSince = req.getDateHeader();
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resplastModified);
                    doGet(reqresp);
                } else {
                    resp.setStatus(.);
                }
            }
        } else if (method.equals()) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resplastModified);
            doHead(reqresp);
        } else if (method.equals()) {
            doPost(reqresp);
            
        } else if (method.equals()) {
            doPut(reqresp);
            
        } else if (method.equals()) {
            doDelete(reqresp);
            
        } else if (method.equals()) {
            doOptions(req,resp);
            
        } else if (method.equals()) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //
            String errMsg = .getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsgerrArgs);
            
            resp.sendError(.errMsg);
        }
    }
    
    /*
     * Sets the Last-Modified entity header field, if it has not
     * already been set and if the value is meaningful.  Called before
     * doGet, to ensure that headers are set before response data is
     * written.  A subclass might have set this header already, so we
     * check.
     */
    private void maybeSetLastModified(HttpServletResponse resp,
                                      long lastModified) {
        if (resp.containsHeader())
            return;
        if (lastModified >= 0)
            resp.setDateHeader(lastModified);
    }
   
    
    
Dispatches client requests to the protected service method. There's no need to override this method.

Parameters:
req the HttpServletRequest object that contains the request the client made of the servlet
res the HttpServletResponse object that contains the response the servlet returns to the client
Throws:
java.io.IOException if an input or output error occurs while the servlet is handling the HTTP request
javax.servlet.ServletException if the HTTP request cannot be handled
See also:
javax.servlet.Servlet.service(javax.servlet.ServletRequest,javax.servlet.ServletResponse)
    @Override
    public void service(ServletRequest reqServletResponse res)
        throws ServletExceptionIOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }
        request = (HttpServletRequestreq;
        response = (HttpServletResponseres;
        service(requestresponse);
    }
/*
 * A response that includes no body, for use in (dumb) "HEAD" support.
 * This just swallows that body, counting the bytes in order to set
 * the content length appropriately.  All other methods delegate directly
 * to the wrapped HTTP Servlet Response object.
 */
// file private
    private static final ResourceBundle lStrings
        = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
    private NoBodyOutputStream noBody;
    private PrintWriter writer;
    private boolean didSetContentLength;
    private boolean usingOutputStream;
    // file private
        super(r);
         = new NoBodyOutputStream();
    }
    // file private
    void setContentLength() {
        if (!) {
            if ( != null) {
                .flush();
            }
            setContentLength(.getContentLength());
        }
    }
    @Override
    public void setContentLength(int len) {
        super.setContentLength(len);
         = true;
    }
    @Override
    public void setContentLengthLong(long len) {
        super.setContentLengthLong(len);
         = true;
    }
    @Override
    public void setHeader(String nameString value) {
        super.setHeader(namevalue);
        checkHeader(name);
    }
    @Override
    public void addHeader(String nameString value) {
        super.addHeader(namevalue);
        checkHeader(name);
    }
    @Override
    public void setIntHeader(String nameint value) {
        super.setIntHeader(namevalue);
        checkHeader(name);
    }
    @Override
    public void addIntHeader(String nameint value) {
        super.addIntHeader(namevalue);
        checkHeader(name);
    }
    private void checkHeader(String name) {
        if ("content-length".equalsIgnoreCase(name)) {
             = true;
        }
    }
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if ( != null) {
            throw new IllegalStateException(
                .getString("err.ise.getOutputStream"));
        }
         = true;
        return ;
    }
    @Override
        if () {
            throw new IllegalStateException(
                .getString("err.ise.getWriter"));
        }
        if ( == null) {
            OutputStreamWriter w = new OutputStreamWriter(
                getCharacterEncoding());
             = new PrintWriter(w);
        }
        return ;
    }
/*
 * Servlet output stream that gobbles up all its data.
 */
// file private
    private static final String LSTRING_FILE =
        "javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings =
        ResourceBundle.getBundle();
    private int contentLength = 0;
    // file private
    NoBodyOutputStream() {}
    // file private
    int getContentLength() {
        return ;
    }
    @Override
    public void write(int b) {
        ++;
    }
    @Override
    public void write(byte buf[], int offsetint len)
        throws IOException
    {
        if (buf == null) {
            throw new NullPointerException(
                    .getString("err.io.nullArray"));
        }
        if (offset < 0 || len < 0 || offset+len > buf.length) {
            String msg = .getString("err.io.indexOutOfBounds");
            Object[] msgArgs = new Object[3];
            msgArgs[0] = Integer.valueOf(offset);
            msgArgs[1] = Integer.valueOf(len);
            msgArgs[2] = Integer.valueOf(buf.length);
            msg = MessageFormat.format(msgmsgArgs);
            throw new IndexOutOfBoundsException(msg);
        }
         += len;
    }
    public boolean isReady() {
        return false;
    }
    public void setWriteListener(WriteListener writeListener) {
    }


'프로그래밍 > JSP' 카테고리의 다른 글

jsp에서 빈의 사용3  (0) 2014.01.01
jsp에서 빈의 사용2  (0) 2014.01.01
빈을 이용한 컴포넌트 방식의 설계1  (0) 2014.01.01
jsp 스크립트  (0) 2014.01.01
javax.servlet.http.HttpServlet 소스코드 part1 (2013/11/27)  (0) 2014.01.01
by givingsheart 2014. 1. 1. 15:10


아하하.. 반갑다 java.lang.reflect 여기서도 보는구나  
아래 매개변수 선언은 상속 계층트리에 속하는 타입이라면 매개변수로 받을수 있다는
의미!  ( Class<? extends HttpServlet> <--요까지가 클래스 타입   c )
    private Method[] getAllDeclaredMethods(Class<? extends HttpServletc) {
        Class<?> clazz = c;
        Method[] allMethods = null;
//아래는 상속 계층에서 HttpServlet 계층 트리에 속한 내가 정의한 실제 구체적 타입 부터 
최대 HttpServlet 타입 바로전 까지 반복하는 작업 (간단하게 내가 정의한 클래스계층 -> HttpServlet 전까지 조회 한다는 의미)
        while (!clazz.equals(HttpServlet.class)) {
//이번 턴에 찾아낸 클래스에 정의된 모든 메서드 타입 객체(object에 상속받았으니 객체)를 가져와라~
            Method[] thisMethods = clazz.getDeclaredMethods();
//이미 찾은게 있냐?
            if (allMethods != null && allMethods.length > 0) {
//기존에 찾은 메소드를 임시변수인 서브클래스 메소드에 담아두고
                Method[] subClassMethods = allMethods;
//새로 찾은 메소드와 기존 메소드의 갯수를 합친 크기만큼 새롭게 저장 공간을 할당한다.
                allMethods =
                    new Method[thisMethods.length + subClassMethods.length];
//많이 보던 시스템 어레이카피 = 깊은 복사
//방금 찾은 따뜻한 메소드 부터 배열의 앞에 복사해준다.
                System.arraycopy(thisMethods, 0, allMethods, 0,
                                 thisMethods.length);
//기존에 찾았던 메소드들은 그 뒤에 복사해준다.
                System.arraycopy(subClassMethods, 0, allMethodsthisMethods.length,
                                 subClassMethods.length);
            } else {
//처음 찾은 메소드라면
                allMethods = thisMethods;
            }
//현재 클래스(http서블릿클래스의 파생 클래스)의 상위 클래스에 선언된 메서드도
//찾으러 가자
            clazz = clazz.getSuperclass();
        }
//찾은 메서드들 있으면 리턴, 못찾았으면 빈 메서드 생성해서 리턴
        return ((allMethods != null) ? allMethods : new Method[0]);
    }
//결국 내가 만든 클래스부터 최상위 클래스(httpServlet)전까지 정의된 모든 메서드들의 정보를 찾아냈다.
//이 의미는 httpServlet에 정의된 메서드중 무엇을 내가 재정의 했는지를 알 수 있게 해준다.


'프로그래밍 > JSP' 카테고리의 다른 글

jsp에서 빈의 사용3  (0) 2014.01.01
jsp에서 빈의 사용2  (0) 2014.01.01
빈을 이용한 컴포넌트 방식의 설계1  (0) 2014.01.01
jsp 스크립트  (0) 2014.01.01
part2(2013/11/27)  (0) 2014.01.01
by givingsheart 2014. 1. 1. 15:08