앞에서는 <form>태그에서 바로 서블릿으로 데이터를 전송했지만 전송 전에 로그인하면 id와 비밀번호 입력 유무 체크하기처럼 전송 데이터에 대해 유효성 검사를 하는 경우가 많습니다. 이런 기능은 자바스크립트로 구현하므로 자바스크립트로 서블릿에 요청하는 방법을 알아보겠습니다.
if(command != null && command.equals("calculate")) { //최초 요청 시 command가 null이면 계산기 화면을 출력하고, command값이 calculate이면 계산 결과를 출력합니다.
String result = calculate(Float.parseFloat(won), operator); pw.print("변환결과"); pw.print(""+ result + ""); pw.print("환율 계산기"); return; } pw.print(""); pw.print("환율 계산기"); pw.print("
"); pw.print(""); pw.close(); } // 원화를 선택한 외화로 환산합니다. private static String calculate(float won, String operator) { String result = null; if(operator.equals("dollar")) { result = String.format("%.6f", won / USD_RATE); }else if (operator.equals("en")) { result = String.format("%.6f", won / JPY_RATE); }else if (operator.equals("wian")) { result = String.format("%.6f", won / CNY_RATE); }else if (operator.equals("pound")) { result = String.format("%.6f", won / GBP_RATE); }else if (operator.equals("euro")) { result = String.format("%.6f", won / EUR_RATE); } return result; } }
#정규 표현식 # 단순 문자열 매칭이 아니라 문자열의 패턴으로 검색하는 것 import re
# 사용시 : 패턴 컴파일 -> 패턴 객체의 메서드로 검색 수행 p = re.compile(r"P[a-z]+") #[] 패턴 1글자 + 1글자 이상 #대문자 P로 시작하고 소문자(a-z) 1글자 이상 있는 문자열 print(p.match("Life"))# 현재 패턴이 life와 일치하는지? print("p match Python?", p.match("Python")) print("p match Pizza?", p.match("Pizza"))
source = "Life is too short, you need Python" # 방법 1. 패턴 컴파일 후 검색 수행 p = re.compile(r"L[a-z]+") print(p.match("Life"))
# 방법 2. 축약형, 패턴 문자열과 검색 대상 문자열을 함께 제공 print(re.match(r"[A-Z][a-z]+", source)) # 매치된 내용을 추출할 경우 group() 메서드로 뽑을 수 있다 print("Match 된 내용:", re.match(r"[A-Z][a-z]+", source).group())
#축약 문자 # \d(숫자), \w(문자), \s (공백문자) # \D(숫자가 아닌 것), \W(문자가 아닌 것), \S(공백문자 아닌것) # search -> 전체 문자열 대상 패턴 검색 #findall -> 전체 문자열 대상 검색 후 list로 반환 # finditer -> 검색 후 iterator(반복자)를 반환 source = "Paint C JavaScript 123 456 Perl Java Python P123 Ruby" #p로 시작되는 문자열 패턴만 검색해서 iterator을 반환 iter = re.finditer(r"\bp\w+", source, re.IGNORECASE) #re.IGNORECASE는 대소문자를 구분하지 말고 검색하라는 의미다 for x in iter: print("검색된 단어:", x)
# 자주 사용될 수 있는 패턴들 # 전화번호의 예 tel = re.compile(r"(\d{2,3})-(\d{3,4})-(\d{4})") m = tel.match("010-1234-5678") print("result:", m) # () 로 묶은 것은 groups() 메서드로 추출 print("groups:", m.groups()) #groups #매칭된 전체 내용을 추출: group() print("매칭된 내용:", m.group()) #group tel= re.compile(r"(?P<area>\d{2,3})-(?P<exchange>\d{3,4})-(?P<number>\d{4})") # 그룹핑시 (?P<이름>) 형식을 부여하면 매칭 결과에 이름을 부여할 수 있다 # 이름이 부여된 매칭 결과는 groupdict()메서드로 사전으로 반환받을 수 있다. m = tel.match("010-1234-5678") print(m.groups()) # 그룹핑된 결과 확인 print(m.group()) #매칭된 전체 결과 print(m.groupdict()) #부여한 이름을 기반으로 한 dict 객체 반환 # 이메일 pattern = r"\w+[\w\.]*@[\w\.]*\.[a-z]+" source = "skyun.nam@gmail.com" print(re.match(pattern, source))
# 한글 매칭 (Unicode 기반) # 한국어 정규식의 예제 source = "English 대한민국 Japan China" p = re.compile(r"[가-힣]+") print(p.findall(source))
# class """ -새로운 이름 공간을 지원하는 단위: 데이터의 설계도 - 새로운 클래스는 새로운 자료형을 정의하는 것 - 인스턴스는 이 자료형의 객체를 생성하는 것 - 클래스와 인스턴스는 직접적인 영향을 갖는다 -인스턴스에서 클래스 멤ㅂ와 접근은 자능 -클래스 맴버에서 인스턴스 멤버의 접근은 불가 """ class MyString(str): # str은 상속받은 새로운 클래스 pass #특정 클래스를 상속받지 않을 경우, object 상속 s = MyString() # 생성자 호출 print(type(s))
# 어떤 클래스를 상속 받은 클래스잉ㄴ가? # __bases__ -> 부모의 목록을 튜플로 반환 print("MyString의 부모:", MyString.__bases__)
#특정 부모를 상속받지 않을 경우() 없어도 된다 class myobj: #object를 상속 pass print(myobj.__bases__) #파이썬은 여러 부모로부터의 상속을 허용한다 #파이썬은 여러 부모로부터의 상속을 허용한다 class Complex(str, myobj): # str로부터 모든 맴버들 #myobj로부터 모든 멤버들을 물려받는다 pass print("Complex의 부모:", Complex.__bases__)
#특정 클래스가 다른 클래스의 자식인지 확인 # issubclass 함수 print("Complex가 str의 자식인가?", issubclass(Complex,str))
#클래스의 생성 # 인스턴스를 위한 멤버는 항상 self를 붙여준다 class Point: # 클래스 멤버: # 클래스 이름 공간 내에 생성 # 모든 인스턴스 맴버 공유 # 클래스 맴버는 인스턴스 생성 없이도 사용할 수 있다. instance_count = 0 def __init__(self, x = 0, y = 0): # 생성자 #파이썬은 여러 개의 생성자를 만들 수 없으므로 # 범용적으로 사용될 수 있는 유일한 생성자를 작성 self.x = x self.y = y Point.instance_count +=1 #소멸자 def __del__(self): #객체가 제거될 때 호출 Point.instance_count -= 1 #__str__ def __str__(self):#문자열 출력 #str() 호출 혹은 print를 할 때 사용되는 비공식 문자열(일반 사용자 대상) return "Point x={}, y={}".format(self.x, self.y) #__repr__ def __repr__(self): #문자열 출력 # 개발자용, 공식문자열 # repr() 함수로 전달 받을 수 있다. # 이 문자열로 해당 객체를 복원해 낼 수 있어야 한다. return "Point({},{})".format(self.x,self.y)
def setX(self,x): self.x = x def setY(self, y): self.y = y def getX(self): return self.x def getY(self): return self.y
#연산자 오버로딩 # 새로운 데이터 타입에 필요한 연산자의 행동을 재정의하는 것 # 산술 연산자 오버로딩 예제 def __add__(self, other): # Point(self) + other # other 타입을 점검해서 각기 다른 행독을 취하도록 if isinstance(other, Point): #합산된 객체가 Point self.x += other.x self.y += other.y elif isinstance(other, int): self.x += other self.y += other else: self += other
return self #역이항 연산자 : other + Point def __radd__(self,other): if isinstance(other, str): return other + str(self) elif isinstance(other, int): self.x += other self.y += other else: self + other return self def bound_class_method(): #생성된 인스턴스를 통해 직접 메서드에 접근하는 방법 p = Point() # bound 방식의 경우, 첫 번째 인자 self는 전달하지 않아도 된다. p.setX(10) p.setY(20)
# 클래스 멤버는 모든 인스턴스에서 접근 가능 # 생성 없이도 직접 접근 가능 print("p1의 instance_count의 주소:", id(p1.instance_count)) print("p2의 instance_count의 주소:", id(p2.instance_count))
#클래스 멤버의 변경 # 공유 메모리 영역으로 활용할 수 있다 Point.instance_count += 1 p1.instance_count += 1 p2.instance_count += 1 print("p2의 instance_count:", p2.instance_count) print("p1의 instance_count:", p1.instance_count)
#class_member() def lifecycle(): # 생성자와 소멸자 테스트 p1 = Point() # 생성자의 기본값이 사용 print(p1) print("instance_count:", Point.instance_count)
del p2 print("instance_count:", Point.instance_count)
#lifecycle() def str_repr(): p = Point(10,20) print(p) # __str__ 호출 print("포인트 p=" + str(p)) # __str__ #repr 함수를 사용하면 __repr__ 문자열을 얻을 수 있다. print("repr of p:", repr(p))
#eval 함수를 사용하면 파이썬 코드를 테스트 할 수 있다. #이때 repr로 전달 받은 문자열(개발자용)을 넘겨주면 같은 객체가 복원되어야 한다. p_repr = eval(repr(p)) print(p_repr, type(p_repr))