안경잡이개발자

728x90
반응형

  오늘은 바이오스(BIOS) 부트 옵션이 비정상적일 때 해결하는 방법에 대해서 소개하고자 합니다. 흔히 발생하는 일은 아니지만 주로 시스템 파일을 건드리거나 오류가 발생해서 컴퓨터가 정상적으로 특정한 저장 장치에서 부팅이 가능하다고 판단을 못 하는 경우, 저장장치가 정상적으로 메인보드와 SATA 케이블로 연결되지 않은 경우 등이 있습니다. 일단 아래 컴퓨터 화면은 한성 컴퓨터에서 부팅을 할 때 F2를 눌러서 바이오스(BIOS)에 진입한 모습입니다. 부트(Boot) 영역으로 가니 네트워크 어댑터만 나오고, 정작 하드 디스크나 SSD가 나오지 않아서 실제로 부팅을 할 수 없는 상황이라고 할 수 있습니다.



  이럴 때는 일단 다음과 같이 메인(Main) 영역에서 SATA 케이블이 연결이 되어 있는지 확인할 필요가 있습니다. 대략적으로 보니까 SATA 포트에는 성공적으로 HDD와 SSD가 모두 연결되어 있는 것을 확인할 수 있습니다. 결과적으로 케이블이 연결되지 않은 문제는 아니므로 노트북 뒤쪽을 분해해서 케이블을 뽑았다가 넣는 것은 하지 않아도 될 것 같습니다.



  결국 SSD에 깔려있던 윈도우 운영체제의 시스템 파일에 오류가 있다고 판단하여 USB를 하나 준비해서 다른 컴퓨터에 꼽은 뒤에, 그 컴퓨터에서 윈도우 10(https://www.microsoft.com/ko-kr/software-download/windows10)을 USB에 설치해주었습니다. 저는 그냥 정품 인증없이 일단 무료로 사용하려고 합니다. 이후에 이 USB를 다시 오류가 있던 컴퓨터에 꼽은 뒤에 바이오스(BIOS)에서 부팅 순서를 해당 USB가 우선순위를 가지도록 했습니다. 그리고 부팅하여 다음과 같은 윈도우 설치 화면을 만날 수 있었습니다.



  위와 같이 기본적인 언어 설정을 물어봅니다. 디폴트 설정으로 넘어가셔도 될 겁니다.



  이제 위와 같이 설치 프로그램이 실행되는 것을 알 수 있습니다.



  이제 여기에서는 '제품 키가 없음(I)'을 설정해서 정품 인증 없이 진행하도록 하겠습니다.



  저는 위와 같이 윈도우 10 Pro를 선택해주었습니다.



  위와 같이 소프트웨어 사용권에 동의해주도록 합니다.



  이후에는 윈도우를 설치할 디스크를 고르라고 합니다. 여기에서 HDD나 SSD를 선택해서 설치하시면 됩니다.



  다만 저는 SSD를 설치하려고 했더니 해당 디스크에 MBR 파티션 테이블이 존재해서 설치할 수 없다고 나왔습니다. 이런 경우에는 기본적으로 안에 데이터가 존재한다는 것이므로 운영체제를 설치하기 위해서는 모든 데이터를 갈아 엎어야 합니다.



  이럴 때에는 GPT 디스크로 해당 디스크를 바꾸어주면 됩니다.



  이럴 때는 위와 같이 USB 부팅 초기 화면에서 '컴퓨터 복구' 부분으로 들어가서 '명령 프롬프트'에 들어가셔야 합니다.



  이제 위와 같이 list disk를 입력해서 현재 사용가능한 디스크를 확인하도록 합니다.



  이후에 위와 같이 select disk 1과 같이 입력해서 자신이 정리하고자 하는 디스크 번호를 넣고, clean을 입력하면 됩니다. 저 같은 경우는 SSD의 디스크 번호가 1이라서 select disk 1 이후에 삭제를 해 준거에요.



  이제 위와 같이 convert gpt를 입력해서 해당 디스크를 GPT 형식으로 바꾸실 수 있습니다.



  이후에 다시 운영체제 설치 부분으로 들어오면 해당 SSD가 설치 가능한 공간으로 바뀐 것을 알 수 있습니다.



  이제 위와 같이 설치가 진행되는 것을 알 수 있습니다. 기다리시면 됩니다.



  기다리시면 설치 완료 이후에 재부팅이 되고, 윈도우로 자동 접속됩니다.



  기본적으로 키보드 정보 등을 설정한 이후에 다음으로 넘어갈 수 있습니다.



  사용자 이름을 입력하고 '다음' 버튼을 누르면 윈도우 설치가 완료됩니다.



  정상적으로 컴퓨터가 포맷되고 윈도우가 설치된 것을 알 수 있습니다.

728x90
반응형

Comment +2

728x90
반응형

  이번 시간에는 우체국 통장 인터넷 뱅킹 개설하는 방법에 대해서 포스팅하고자 합니다. 사실상 요즘에는 통장을 개설하는 것 자체는 의미가 없고 인터넷 뱅킹까지 개설해서 실질적으로 언제든지 송금할 수 있도록 서비스를 받는 것이 편리합니다. 당연한 이야기겠죠. 저 같은 경우는 우체국 통장을 구글 애드센스(Google Adsense) 수익을 받기 위해서 개설했었습니다. 2017년 7월 당시에 당시 강남역 바로 앞에 있는 우체국에서 개설을 했는데 슬프게도 요즘에 대포통장이 기승을 부리고 있어서 인터넷 뱅킹은 나중에 다시 와서 개설하라는(?) 직원의 말 때문에 바로 우체국 통장을 개설하지 못했었죠. 그래서 나중에 몇 달 뒤인 2018년 1월에 저희 집 앞 우체국으로 가서 인터넷 뱅킹 신청을 했답니다.


  근데 저는 일주일 뒤에 인터넷 뱅킹 신청을 하러 우체국에 한 번 더 가야 했답니다. 왜일까요? 그것은 인터넷 뱅킹 신청을 한 뒤에 5일 이내에 우체국 예금 사이트로 가서 바로 인터넷 뱅킹을 개설해야 하는데 그렇게 안 했기 때문입니다. 한 번 공포의 문자 메시지를 살펴보시지요. 저는 이 문자메시지를 받을 당시에 미국에 있던 터라 슬프게도 인터넷에 접속해서 공인인증서 등록이 어려웠답니다. 그래서 결과적으로 다시 우체국 지점에 방문해야만 했습니다.



  아무튼 우체국 지점에 한 번 더 방문하여 인터넷 뱅킹을 다시 뚫어달라고 했답니다. 피 같은 제 시간이 낭비되는 순간들이었습니다. 아무튼 이제야 인터넷 뱅킹을 신청할 수 있게 되었으므로 바로 우체국 예금 사이트로 이동해보도록 합시다.


  ▶ 우체국 인터넷 뱅킹 사이트: https://www.epostbank.go.kr/



  접속 이후에는 위와 같이 로그인 페이지로 이동하여 우체국 통장을 신청했을 때 자신이 입력했던 아이디로 로그인을 해주시면 됩니다. 기억이 안 나시면 발급 받은 통장 번호로 아이디를 찾으실 수 있어요.



  이제 위와 같이 '공인인증서 발급/재발급'에 들어가서 인증서를 발급해주시면 됩니다.



  인증서를 발급하기 위해서는 기본적인 보안 프로그램 설치가 필요합니다.



  설치 이후에 들어가면 위와 같이 공인인증서를 발급하라고 합니다.



  위와 같이 아이디 및 주민등록번호를 입력하면 만들 수 있어요.



  저는 위와 같이 용도제한 공인인증서로 만들었습니다. 용도제한 인증서는 특정한 용도로만 사용할 수 있는 인증서이고, 기본적으로 은행에서 인증서 관련 비용을 지불해주기 때문에 우리는 무료로 인증서를 사용할 수 있습니다.



  이제 위와 같이 계좌번호 및 보안카드를 입력하시면 됩니다. 이건 이미 은행에서 받으셨을 거에요. 그걸 그대로 입력하셔서 해당 계좌로 돈을 출금하거나 입금할 수 있도록 인터넷 뱅킹을 설정해주는 겁니다.



  위와 같이 최종적으로 인증서를 발급할 수 있습니다.



  이제 저장할 매체를 설정하라고 하는데요, 웬만하면 하드디스크에 저장하세요. 나중에 언제든지 하드디스크에서 핸드폰 등으로 인증서를 복사할 수도 있으니까 불편하지 않을 겁니다.



  인증서 비밀번호를 입력하면 위와 같이 인증서가 성공적으로 발급이 될 겁니다. 이제 편하게 인터넷 뱅킹을 이용하세요!


※ 삽질 후기 ※


  일반적으로 인터넷 뱅킹을 등록하려고 하는 사람들은 기본적으로 이미 은행에서 아이디를 만드신 분들이에요. 은행에서는 아이디만 만들어주고 비밀번호는 만들어 준 적도 없을 겁니다. 저는 처음에 헷갈려서 삽질을 좀 했습니다. 공인인증서 등록이 아니라 회원가입을 해야 인터넷 뱅킹 사용이 가능한 줄 알고, 회원가입으로 들어갔었어요. 다음과 같이요.



  들어가면 이렇게 개인정보 수집 및 이용에 동의하라고 합니다.



  이후에 다음과 같이 개인정보를 입력해서 회원가입을 할 수 있을 줄 알았죠.



  근데 이미 은행에서 아이디를 만들어 놓았기 때문에 안 된다고 하더군요. 즉 인터넷 뱅킹을 사용하기 위해서는 공인인증서 등록을 하셔야지 이렇게 회원가입에 들어가시면 안 됩니다.



728x90
반응형

Comment +0

728x90
반응형

  흔히 교육 기관, 정부 등에서는 다양한 문서를 요구하곤 하는데요. 그러한 문서들은 대부분 개개인의 서명이 포함된 PDF 파일을 요구하는 경우가 많습니다. 근데 집에 프린터기가 없는 사람들에게는 여간 귀찮은 일이 아닐 수 없습니다. 일일히 프린터로 서류를 뽑은 뒤에 거기에 서명을 한 뒤에 다시 스캔해서 PDF 파일로 보내주어야 했기 때문이에요. 그래서, 간단한 편법을 이용해서 서명을 컴퓨터 상에서 대신하는 방법에 대해서 소개하고자 합니다.


  먼저 이런식으로 펜과 종이로 서명을 해주시고, 이걸 핸드폰으로 찍으신 뒤에 카톡이든 뭐든 '공유' 기능으로 컴퓨터로 옮깁니다.



  다음으로 웹 포토샵에 접속합니다. 무료 웹 포토샵 사이트(https://pixlr.com/editor/)를 이용하시면 편합니다.



  이후에 이미지 열기를 해서 우리의 이미지를 열어줍니다.



  검은색으로 잘 쓰여진 PDF 파일을 만들기 위해 명암을 조절할 필요가 있어요. '조절' - '밝기 & 명암대비...'를 누릅니다.



  이후에 명암대비를 최대치로 올립니다.



  이제 자르기 도구를 이용해 글자가 있는 부분만 남도록 자릅니다.



  이후에 위와 같이 하나의 레이어를 추가한 뒤에, 기존에 있던 레이어의 잠금을 해제해주시고 두 개의 우선순위를 바꿉니다.



  이후에 선택 도구로 배경색을 모두 선택하신 뒤에 제거해줍니다.



  이제 저장을 해볼까요?



  결과물은 서명 답게 투명한 배경이 포함된 PNG 파일로 저장하시면 됩니다.

  


  이제 위와 같이 한글(HWP)을 실행하셔서 사진 파일을 넣어줍시다. 그리고 우클릭 해서 '개체 속성'을 누릅니다.



  이후에 '글자처럼 취급'에 체크를 해제해주시고 세 번째 유형을 누릅니다.



  그럼 이제 위와 같이 (인)이라는 글자 위에 우리의 서명이 있게 되었습니다.



  이제 여기에서 PDF로 저장해주시면 서명이 포함된 PDF 파일 만들기 간단하게 완료!

728x90
반응형

Comment +0

728x90
반응형

  KTX를 탈 때 25세 미만이신 분들은 청소년 할인을 받을 수 있다는 사실을 알고 계셨나요? 저는 20살 대학교 1학년 때부터 KTX를 여러 번 탔었는데, 탈 때마다 할인 없이 그냥 탔었네요. 그러다가 최근에 25세 미만은 '청소년'으로 할인을 받을 수 있다는 사실을 알게되어 몹시 부들부들한 상태입니다. 근데, 할인 받는 것도 그냥 회원가입하고, 핸드폰 인증을 하면 되는 게 아니고 따로 이상한 '멤버십 번호' 같은 걸 할당하는 식으로 괴랄하게 구현이 되어 있습니다. 그래서 처음에 헤매이실 수도 있어서, 이렇게 블로그에 글을 정리하고자 합니다.


  ※ 25세 미만 KTX 청소년 할인 받는 방법 ※


  1. 코레일에 가입한다.


  이 때는 코레일 홈페이지(http://www.letskorail.com/korail/com/login.do)에서 가입하셔도 되고, 스마트 폰에 코레일 톡을 설치하셔서 가입하셔도 됩니다. 여기서 유의하셔야 할 것은 가입 이후에 '멤버십 번호'를 기억하고 계셔야 한다는 것입니다.



  모바일이나 데스크탑이나 회원가입 과정 자체는 비슷할 거에요. 회원가입 이후에는 멤버십 번호를 주고요. 또한, 참고로 모바일에서는 그 번호로 회원가입 이후에 바로 로그인을 해놓으시고, 로그인 상태 유지가 되도록 하시는 게 좋습니다. 멤버십 번호를 어떻게 기억하고 있나요. 도대체 왜 아이디 대신 멤버십 번호를 쓰는지는 도저히 이해가 안 가지만, 아무튼 넘어가겠습니다.


  2. 코레일 홈페이지에 로그인 한 뒤에 '마이페이지'에 가서 휴대폰 인증 이후에 청소년 드림으로 등록한다.



  이제 위와 같이 코레일 홈페이지에 로그인을 하신 뒤에 '마이페이지'로 이동합니다. 저는 지금 청소년 드림으로 등록이 완료가 되었는데요, 아직 등록을 하지 않으신 분들은 휴대폰 인증을 통해서 청소년으로 등록할 수 있게 되어 있을 겁니다.


  3. 코레일 톡으로 로그인 및 '청소년 드림'을 확인한다.



  청소년 등록을 하신 뒤에는 코레일 톡에서 '정기할인권' 탭에 들어갑니다.



  이제 위와 같이 '청소년 드림'을 선택할 수 있는 것을 알 수 있습니다.



  한 번 아무거나 검색해서 확인해보도록 하겠습니다.



  그러면 위와 같이 적은 경우 20%부터 많은 경우 40%까지 할인이 있는 것을 알 수 있어요. 다만, 일반적으로 하루나 이틀 전에 미리 예약을 하시는 게 좋구요. 이렇게 할인해서 구매하신 승차권 같은 경우는 특정 승차권을 취소한 뒤에 다른 승차권을 구매하고자 할 때는 할인 금액을 그대로 적용받을 수 없습니다. 저도 그래서, 저번에 30% 할인 받은 승차권을 30분 앞 차로 옮겨달라고 했더니 할인 승차권이라서 안 된다고 하더라구요. 근데 KTX 객차별로 할인율이 다르니까 이는 당연하다고 생각합니다. 특히 아침 차 같은 경우는 정말로 많이 할인을 해줘서 상당히 좋습니다. 아무튼 25세 미만이신 분들은 이렇게 청소년 드림으로 할인을 받으시면 거의 왕복 2~3만원정도 절약이 가능해서, 꿀인 것 같습니다.


  (지난 몇 년 동안 이걸 모르고 살아서 공중분해된 내 피 같은 돈들이 생각날 뿐입니다. ㅂㄷㅂㄷ)

728x90
반응형

Comment +0

728x90
반응형

  일반적으로 JSP, PHP 등을 이용해서 Google Gmail STMP 서비스를 이용할 수 있습니다. 일반적으로 구글에 회원가입을 한 뒤에 핸드폰으로 인증을 하게 되면 지메일 서비스를 바로 사용할 수 있는데요, 그렇게 지메일을 사용할 수 있는 상태에서는 해당 지메일 계정을 우리의 웹 서버에서 사용할 수 있는 거죠. 일반적으로 회원가입 이후에 이메일 인증 메일을 보내거나 할 때 우리의 웹 사이트에 넣을 수 있는 모듈입니다. 찾아보시면 금방 소스코드를 구해서 구현하시는 건 어렵지 않을 건데요, 카페 24와 같은 호스팅 서비스에 이를 적용하고자 하면 문제가 발생합니다.


  하지만 호스팅 서비스를 이용하는 경우에는 콘솔(Console) 창을 직접 확인하기 어려워 정확히 어떤 오류가 발생하는지 알기 힘들죠. 저 같은 경우에도 단순히 로컬 호스트에서는 잘 돌아가던 SMTP 모듈이 카페 24 호스팅 서버에 직접 업로드하니까 오류가 발생했다고만 나오더라구요.


  카페 24(Cafe 24)에서 JSP 호스팅을 신청하면, 퓨티(Putty)와 같은 SSH 접속 프로그램을 이용해 자신이 구매한 JSP 톰캣 서버에 접속할 수 있습니다. 그 중에서도 웹 서버에 오류가 발생하는 등 로그를 확인해야 할 때는 다음과 같이 할 수 있어요.


  ▶ cd tomcat/logs/ : 톰캣의 로그 폴더로 이동합니다.

  ▶ tail -f catalina.out : 현 시점에서부터 발생하는 웹 로그를 모두 화면에 출력합니다.



  위와 같이 웹 로그 출력이 돌아가도록 만든 이후에 확인해봅시다.



  마찬가지로 다시 SMTP 오류가 나는 부분의 웹 페이지에 접속합니다. 그러면 이번에는 발생하는 오류 메시지가 위와 같이 콘솔 창에 출력되는 것을 알 수 있습니다. 대충 보니까 카페 24에서 구글 SMTP로 접속하는 과정에서 인증 오류가 발생한 것을 알 수 있습니다. 이것은 호스팅 서비스를 경유하기 때문이에요. 기존에 로컬 호스트를 사용하던 때보다 구글 측에서 자원 고갈 공격 등을 받을 여지가 있어서, 추가적인 보안 인증을 거쳐야지 지메일을 이용할 수 있도록 구글 측에서 규제를 넣은 것이랍니다. 따라서 바로 추가 인증 과정을 통해 SMTP 서비스를 사용해보도록 하겠습니다.



  바로 위와 같이 구글 서비스에서 '계정' 탭에 들어가도록 합니다. 이후에 '로그인 및 보안' 탭에 들어가시면 됩니다.



  그리고 위와 같이 '로그인 및 보안'에서 2단계 인증을 사용하도록 처리하시면 됩니다. 현재는 '사용 중지' 상태네요.



  이제 위와 같이 2단계 인증을 위해서 핸드폰 인증을 해주시면 됩니다. '시작하기' 버튼을 눌러줄게요.



  먼저 위와 같이 비밀번호를 입력하라고 할 거에요.


  이후에 위와 같이 휴대폰 인증을 해주시면 됩니다. 별 거 없어요. 핸드폰으로 문자 한 통 오는데 그 인증번호 입력해주시면 됩니다.



  휴대폰 인증이 완료되면 위와 같이 '사용 설정'을 해줄 수 있습니다.



  이제 위와 같이 다시 '로그인 및 보안' 탭에 들어가면 '앱 비밀번호' 부분이 있습니다. 이를 생성해주시면 됩니다.



  이제 위와 같이 '기타'로 하나의 비밀번호를 새롭게 추가해주시면 됩니다.



  기본적으로 위와 같이 서비스의 이름을 입력하면 알아서 비밀번호가 나온답니다.



  이제 위와 같이 비밀번호가 등장했네요. 



  위와 같이 성공적으로 서비스가 생성되었구요. 이제 SMTP 소스코드에서 인증하는 부분의 비밀번호를 아까 받은 비밀번호로 넣으시면 됩니다. 아이디는 그대로 구글 계정을 쓰시면 되구요. JSP에서의 예제는 다음과 같습니다.


package util;


import javax.mail.Authenticator;

import javax.mail.PasswordAuthentication;


public class Gmail extends Authenticator {


    @Override

    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication("구글 이메일 계정","부여받은 비밀번호");

    }

    

}


  이제 위와 같이 톰캣 서버를 재시작해주면 됩니다.


  ▶ CD ~ : 다시 홈 디렉토리로 이동하기

  ▶ ./tomcat/bin/shutdown.sh : 현재 실행 중인 톰캣을 종료시키기

  ▶ ./tomcat/bin/startup.sh : 톰캣을 다시 실행시키기



이제 한 번 테스트를 해보겠습니다.



  위와 같이 성공적으로 오류 없이 메일이 전송되는 것을 확인할 수 있습니다.

728x90
반응형

Comment +2

728x90
반응형

  이제 JSP로 강의평가(Lecture Evaluation) 웹 사이트 개발하기의 열 한 번째 포스팅을 합니다. 사실상 지난 시간에 모든 기능들이 다 구현이 되었어요. 이제는 기본적인 프로젝트 뼈대가 완성되었으므로 다양한 기능을 붙이거나, 보안적인 요소를 처리하는 것이 좋겠지요. 저는 이번 시간에서는 간단히 기초 시큐어 코딩 방법에 대해서 소개해드리려고 합니다. XSS를 방지하는 겁니다. XSS는 기본적으로 특정 사용자가 다른 사용자와 통신하는 과정에서 발생할 수 있는 해킹 방법입니다. 대표적으로는, 강의 평가 글 자체가 될 수 있습니다. 따라서 강의 평가 글을 출력할 때는 자바스크립트를 실행할 수 있는 문장을 모두 치환하면 됩니다.


  ▶ EvaluationDAO.java 내부의 write() 함수 수정하기


public int write(EvaluationDTO evaluationDTO) {

PreparedStatement pstmt = null;

try {

String SQL = "INSERT INTO EVALUATION VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0);";

pstmt = conn.prepareStatement(SQL);

pstmt.setString(1, evaluationDTO.getUserID().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(2, evaluationDTO.getLectureName().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(3, evaluationDTO.getProfessorName().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setInt(4, evaluationDTO.getLectureYear());

pstmt.setString(5, evaluationDTO.getSemesterDivide().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(6, evaluationDTO.getLectureDivide().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(7, evaluationDTO.getEvaluationTitle().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(8, evaluationDTO.getEvaluationContent().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(9, evaluationDTO.getTotalScore().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(10, evaluationDTO.getCreditScore().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(11, evaluationDTO.getComfortableScore().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

pstmt.setString(12, evaluationDTO.getLectureScore().replaceAll("<", "&lt;").replaceAll(">", " &gt;").replaceAll("\r\n", "<br>"));

return pstmt.executeUpdate();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return -1;

}


  위와 같이 설정해주면 게시글이 등록될 때 모든 꺾쇠가 치환되므로 기본적으로 자바스크립트 구문을 삽입하기가 어려워진답니다. 이미 시중에 나와있는 라이브러리가 많긴 한데, 대충 위와 같이 처리해도 XSS 공격이 까다로워지므로 나쁘지 않습니다. 테스트 결과는 다음과 같습니다.




  ※ 전체 실행 결과 (동영상 결과물) ※



728x90
반응형

Comment +0

728x90
반응형

  이번 시간에는 JSP로 강의평가(Lecture Evaluation) 웹 사이트 개발하기의 열 번째 강의입니다. 지난 시간에는 특정한 강의를 검색할 수 있고, 페이징 처리를 하여 페이지를 넘기면서 여러 강의를 볼 수 있도록 기능을 구현하는 시간을 가졌습니다. 이번 시간에는 특정한 강의를 추천하고, 자신이 작성한 글에 한해서 글을 삭제하는 기능을 개발하고자 합니다. 바로 시작해봅시다. 가장 먼저 지난 번에 데이터베이스를 설계하는 시간에 작성했었던 LIKEY 테이블을 조금 바꿔주도록 하겠습니다. 바로 다음과 같이 ALTER 명령어를 이용해서 (회원 아이디, 평가 번호)로 PRIMARY KEY를 줍시다. 왜냐하면 한 명은 특정한 글에 단 한 번만 추천을 누를 수 있어야 하기 때문입니다.


  ▶ ALTER TABLE LIKEY ADD PRIMARY KEY (userID, evaluationID);



  이후에 바로 EvaluationDAO.java 파일을 수정하도록 하겠습니다. 이번 시간에 구현할 기능을 위해 몇 가지 데이터베이스 접근 함수가 필요하기 때문이에요.


public int like(String evaluationID) {

PreparedStatement pstmt = null;

try {

String SQL = "UPDATE EVALUATION SET likeCount = likeCount + 1 WHERE evaluationID = ?";

pstmt = conn.prepareStatement(SQL);

pstmt.setInt(1, Integer.parseInt(evaluationID));

return pstmt.executeUpdate();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return -1;

}

public int delete(String evaluationID) {

PreparedStatement pstmt = null;

try {

String SQL = "DELETE FROM EVALUATION WHERE evaluationID = ?";

pstmt = conn.prepareStatement(SQL);

pstmt.setInt(1, Integer.parseInt(evaluationID));

return pstmt.executeUpdate();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return -1;

}

public String getUserID(String evaluationID) {

PreparedStatement pstmt = null;

try {

String SQL = "SELECT userID FROM EVALUATION WHERE evaluationID = ?";

pstmt = conn.prepareStatement(SQL);

pstmt.setInt(1, Integer.parseInt(evaluationID));

rs = pstmt.executeQuery();

while(rs.next()) {

return rs.getString(1);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return null;

}


  위와 같이 총 3개의 함수를 추가해줍시다. 차례대로 추천을 눌러서 특정한 글의 추천 갯수가 증가되는 함수, 특정한 강의 평가 글을 지우는 함수, 특정한 강의 평가 글을 작성한 사용자의 아이디를 구하는 함수입니다. 이제 다음과 같이 우리의 프로젝트를 구성합니다. likey 패키지를 생성해서 LikeyDTO.java, LikeyDAO.java를 생성합니다. 그리고 deleteAction.jsp 페이지와 likeAction.jsp 페이지를 생성합니다. 이 두 페이지는 강의 평가 글을 지우는 액션 페이지, 강의 평가에 추천을 누르는 액션 페이지입니다.



  ▶ LikeyDTO.java


package likey;


public class LikeyDTO {


String userID;

int evaluationID;

String userIP;

public String getUserID() {

return userID;

}

public void setUserID(String userID) {

this.userID = userID;

}

public int getEvaluationID() {

return evaluationID;

}

public void setEvaluationID(int evaluationID) {

this.evaluationID = evaluationID;

}

public String getUserIP() {

return userIP;

}

public void setUserIP(String userIP) {

this.userIP = userIP;

}

public LikeyDTO(String userID, int evaluationID, String userIP) {

this.userID = userID;

this.evaluationID = evaluationID;

this.userIP = userIP;

}


}


  ▶ LikeyDAO.java


package likey;


import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;


public class LikeyDAO {


private Connection conn;


public LikeyDAO() {

try {

String dbURL = "jdbc:mysql://localhost:3306/LectureEvaluation";

String dbID = "root";

String dbPassword = "root1234";

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(dbURL, dbID, dbPassword);

} catch (Exception e) {

e.printStackTrace();

}

}

public int like(String userID, String evaluationID, String userIP) {

String SQL = "INSERT INTO LIKEY VALUES (?, ?, ?)";

try {

PreparedStatement pstmt = conn.prepareStatement(SQL);

pstmt.setString(1, userID);

pstmt.setString(2, evaluationID);

pstmt.setString(3, userIP);

return pstmt.executeUpdate();

} catch (SQLException e) {

e.printStackTrace();

}

return -1; // 추천 중복 오류

}

}


  ▶ deleteAction.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="user.UserDAO"%>

<%@ page import="evaluation.EvaluationDAO"%>

<%@ page import="likey.LikeyDTO"%>

<%@ page import="java.io.PrintWriter"%>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

return;

}

request.setCharacterEncoding("UTF-8");

String evaluationID = null;

if(request.getParameter("evaluationID") != null) {

evaluationID = (String) request.getParameter("evaluationID");

}

EvaluationDAO evaluationDAO = new EvaluationDAO();

if(userID.equals(evaluationDAO.getUserID(evaluationID))) {

int result = new EvaluationDAO().delete(evaluationID);

if (result == 1) {

session.setAttribute("userID", userID);

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('삭제가 완료되었습니다.');");

script.println("location.href='index.jsp'");

script.println("</script>");

script.close();

return;

} else {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('데이터베이스 오류가 발생했습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

}

} else {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('자신이 쓴 글만 삭제 가능합니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

}

%>


  ▶ likeAction.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="user.UserDAO"%>

<%@ page import="evaluation.EvaluationDAO"%>

<%@ page import="likey.LikeyDAO"%>

<%@ page import="java.io.PrintWriter"%>

<%!

public static String getClientIP(HttpServletRequest request) {

    String ip = request.getHeader("X-FORWARDED-FOR"); 

    if (ip == null || ip.length() == 0) {

        ip = request.getHeader("Proxy-Client-IP");

    }

    if (ip == null || ip.length() == 0) {

        ip = request.getHeader("WL-Proxy-Client-IP");

    }

    if (ip == null || ip.length() == 0) {

        ip = request.getRemoteAddr() ;

    }

    return ip;

}

%>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

return;

}

request.setCharacterEncoding("UTF-8");

String evaluationID = null;

if(request.getParameter("evaluationID") != null) {

evaluationID = (String) request.getParameter("evaluationID");

}

EvaluationDAO evaluationDAO = new EvaluationDAO();

LikeyDAO likeyDAO = new LikeyDAO();

int result = likeyDAO.like(userID, evaluationID, getClientIP(request));

if (result == 1) {

result = evaluationDAO.like(evaluationID);

if (result == 1) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('추천이 완료되었습니다.');");

script.println("location.href='index.jsp'");

script.println("</script>");

script.close();

return;

} else {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('데이터베이스 오류가 발생했습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

}

} else {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('이미 추천을 누른 글입니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

}

%>


  이제 한 번 테스트를 해보도록 합시다.







728x90
반응형

Comment +0

728x90
반응형

  이번 시간에는 JSP 강의평가(Lecture Evaluation) 웹 사이트 개발하기의 아홉 번째 시간입니다. 이번 시간에는 등록된 강의 평가 글을 실질적으로 출력하고, 검색할 수 있는 기능을 구현해보도록 하겠습니다.


  ▶ EvaluationDAO.java에 검색 함수 추가하기


public ArrayList<EvaluationDTO> getList(String lectureDivide, String searchType, String search, int pageNumber) {

if(lectureDivide.equals("전체")) {

lectureDivide = "";

}

ArrayList<EvaluationDTO> evaluationList = null;

PreparedStatement pstmt = null;

String SQL = "";

try {

if(searchType.equals("최신순")) {

SQL = "SELECT * FROM EVALUATION WHERE lectureDivide LIKE ? AND CONCAT(lectureName, professorName, evaluationTitle, evaluationContent) LIKE ? ORDER BY evaluationID DESC LIMIT " + pageNumber * 5 + ", " + pageNumber * 5 + 6;

} else if(searchType.equals("추천순")) {

SQL = "SELECT * FROM EVALUATION WHERE lectureDivide LIKE ? AND CONCAT(lectureName, professorName, evaluationTitle, evaluationContent) LIKE ? ORDER BY likeCount DESC LIMIT " + pageNumber * 5 + ", " + pageNumber * 5 + 6;

}

pstmt = conn.prepareStatement(SQL);

pstmt.setString(1, "%" + lectureDivide + "%");

pstmt.setString(2, "%" + search + "%");

rs = pstmt.executeQuery();

evaluationList = new ArrayList<EvaluationDTO>();

while(rs.next()) {

EvaluationDTO evaluation = new EvaluationDTO(

rs.getInt(1),

rs.getString(2),

rs.getString(3),

rs.getString(4),

rs.getInt(5),

rs.getString(6),

rs.getString(7),

rs.getString(8),

rs.getString(9),

rs.getString(10),

rs.getString(11),

rs.getString(12),

rs.getString(13),

rs.getInt(14)

);

evaluationList.add(evaluation);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(rs != null) rs.close();

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return evaluationList;

}


    기본적으로 사용자가 '최신순', '추천순'으로 검색하는 쿼리에 따라서 정렬을 다르게 합니다. 이후에 한 페이지 당 5개씩 평가 글을 출력하도록 위와 같이 구성해보았습니다. 이제 다음과 같이 index.jsp를 수정합시다.


  ▶ index.jsp 수정하기


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.io.PrintWriter"%>

<%@ page import="user.UserDAO"%>

<%@ page import="evaluation.EvaluationDAO"%>

<%@ page import="evaluation.EvaluationDTO"%>

<%@ page import="java.util.ArrayList"%>

<%@ page import="java.net.URLEncoder"%>

<!doctype html>

<html>

  <head>

    <title>강의평가 웹 사이트</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- 부트스트랩 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/bootstrap.min.css">

    <!-- 커스텀 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/custom.css">

  </head>

  <body>

<%

request.setCharacterEncoding("UTF-8");

String lectureDivide = "전체";

String searchType = "최신순";

String search = "";

int pageNumber = 0;

if(request.getParameter("lectureDivide") != null) {

lectureDivide = request.getParameter("lectureDivide");

}

if(request.getParameter("searchType") != null) {

searchType = request.getParameter("searchType");

}

if(request.getParameter("search") != null) {

search = request.getParameter("search");

}

if(request.getParameter("pageNumber") != null) {

try {

pageNumber = Integer.parseInt(request.getParameter("pageNumber"));

} catch (Exception e) {

System.out.println("검색 페이지 번호 오류");

}

}

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

}

boolean emailChecked = new UserDAO().getUserEmailChecked(userID);

if(emailChecked == false) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("location.href = 'emailSendConfirm.jsp'");

script.println("</script>");

script.close();

return;

}

%>

    <nav class="navbar navbar-expand-lg navbar-light bg-light">

      <a class="navbar-brand" href="index.jsp">강의평가 웹 사이트</a>

      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">

        <span class="navbar-toggler-icon"></span>

      </button>

      <div class="collapse navbar-collapse" id="navbar">

        <ul class="navbar-nav mr-auto">

          <li class="nav-item active">

            <a class="nav-link" href="index.jsp">메인</a>

          </li>

          <li class="nav-item dropdown">

            <a class="nav-link dropdown-toggle" id="dropdown" data-toggle="dropdown">

              회원 관리

            </a>

            <div class="dropdown-menu" aria-labelledby="dropdown">

<%

if(userID == null) {

%>

              <a class="dropdown-item" href="userLogin.jsp">로그인</a>

              <a class="dropdown-item" href="userRegister.jsp">회원가입</a>

<%

} else {

%>

              <a class="dropdown-item" href="userLogout.jsp">로그아웃</a>

<%

}

%>

            </div>

          </li>

        </ul>

        <form action="./index.jsp" method="get" class="form-inline my-2 my-lg-0">

          <input type="text" name="search" class="form-control mr-sm-2" placeholder="내용을 입력하세요.">

          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">검색</button>

        </form>

      </div>

    </nav>

    <div class="container">

      <form method="get" action="./index.jsp" class="form-inline mt-3">

        <select name="lectureDivide" class="form-control mx-1 mt-2">

          <option value="전체">전체</option>

          <option value="전공" <%if(lectureDivide.equals("전공")) out.println("selected");%>>전공</option>

          <option value="교양" <%if(lectureDivide.equals("교양")) out.println("selected");%>>교양</option>

          <option value="기타" <%if(lectureDivide.equals("기타")) out.println("selected");%>>기타</option>

        </select>

        <select name="searchType" class="form-control mx-1 mt-2">

          <option value="최신순">최신순</option>

          <option value="추천순" <%if(searchType.equals("추천순")) out.println("selected");%>>추천순</option>

        </select>

        <input type="text" name="search" class="form-control mx-1 mt-2" value="<%= search %>" placeholder="내용을 입력하세요.">

        <button type="submit" class="btn btn-primary mx-1 mt-2">검색</button>

        <a class="btn btn-primary mx-1 mt-2" data-toggle="modal" href="#registerModal">등록하기</a>

        <a class="btn btn-danger ml-1 mt-2" data-toggle="modal" href="#reportModal">신고</a>

      </form>

<%

ArrayList<EvaluationDTO> evaluationList = new ArrayList<EvaluationDTO>();

evaluationList = new EvaluationDAO().getList(lectureDivide, searchType, search, pageNumber);

if(evaluationList != null)

for(int i = 0; i < evaluationList.size(); i++) {

if(i == 5) break;

EvaluationDTO evaluation = evaluationList.get(i);

%>

      <div class="card bg-light mt-3">

        <div class="card-header bg-light">

          <div class="row">

            <div class="col-8 text-left"><%=evaluation.getLectureName()%>&nbsp;<small><%=evaluation.getProfessorName()%></small></div>

            <div class="col-4 text-right">

              종합 <span style="color: red;"><%=evaluation.getTotalScore()%></span>

            </div>

          </div>

        </div>

        <div class="card-body">

          <h5 class="card-title">

            <%=evaluation.getEvaluationTitle()%>&nbsp;<small>(<%=evaluation.getLectureYear()%>년 <%=evaluation.getSemesterDivide()%>)</small>

          </h5>

          <p class="card-text"><%=evaluation.getEvaluationContent()%></p>

          <div class="row">

            <div class="col-9 text-left">

              성적 <span style="color: red;"><%=evaluation.getCreditScore()%></span>

              널널 <span style="color: red;"><%=evaluation.getComfortableScore()%></span>

              강의 <span style="color: red;"><%=evaluation.getLectureScore()%></span>

              <span style="color: green;">(추천: <%=evaluation.getLikeCount()%>)</span>

            </div>

            <div class="col-3 text-right">

              <a onclick="return confirm('추천하시겠습니까?')" href="./likeAction.jsp?evaluationID=<%=evaluation.getEvaluationID()%>">추천</a>

              <a onclick="return confirm('삭제하시겠습니까?')" href="./deleteAction.jsp?evaluationID=<%=evaluation.getEvaluationID()%>">삭제</a>

            </div>

          </div>

        </div>

      </div>

<%

}

%>

    </div>

    <ul class="pagination justify-content-center mt-3">

      <li class="page-item">

<%

if(pageNumber <= 0) {

%>     

        <a class="page-link disabled">이전</a>

<%

} else {

%>

<a class="page-link" href="./index.jsp?lectureDivide=<%=URLEncoder.encode(lectureDivide, "UTF-8")%>&searchType=<%=URLEncoder.encode(searchType, "UTF-8")%>&search=<%=URLEncoder.encode(search, "UTF-8")%>&pageNumber=<%=pageNumber - 1%>">이전</a>

<%

}

%>

      </li>

      <li class="page-item">

<%

if(evaluationList.size() < 6) {

%>     

        <a class="page-link disabled">다음</a>

<%

} else {

%>

<a class="page-link" href="./index.jsp?lectureDivide=<%=URLEncoder.encode(lectureDivide, "UTF-8")%>&searchType=<%=URLEncoder.encode(searchType, "UTF-8")%>&search=<%=URLEncoder.encode(search, "UTF-8")%>&pageNumber=<%=pageNumber + 1%>">다음</a>

<%

}

%>

      </li>

    </ul>

    <div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">

      <div class="modal-dialog">

        <div class="modal-content">

          <div class="modal-header">

            <h5 class="modal-title" id="modal">평가 등록</h5>

            <button type="button" class="close" data-dismiss="modal" aria-label="Close">

              <span aria-hidden="true">&times;</span>

            </button>

          </div>

          <div class="modal-body">

            <form action="./evaluationRegisterAction.jsp" method="post">

              <div class="form-row">

                <div class="form-group col-sm-6">

                  <label>강의명</label>

                  <input type="text" name="lectureName" class="form-control" maxlength="20">

                </div>

                <div class="form-group col-sm-6">

                  <label>교수명</label>

                  <input type="text" name="professorName" class="form-control" maxlength="20">

                </div>

              </div>

              <div class="form-row">

                <div class="form-group col-sm-4">

                  <label>수강 년도</label>

                  <select name="lectureYear" class="form-control">

                    <option value="2011">2011</option>

                    <option value="2012">2012</option>

                    <option value="2013">2013</option>

                    <option value="2014">2014</option>

                    <option value="2015">2015</option>

                    <option value="2016">2016</option>

                    <option value="2017">2017</option>

                    <option value="2018" selected>2018</option>

                    <option value="2019">2019</option>

                    <option value="2020">2020</option>

                    <option value="2021">2021</option>

                    <option value="2022">2022</option>

                    <option value="2023">2023</option>

                  </select>

                </div>

                <div class="form-group col-sm-4">

                  <label>수강 학기</label>

                  <select name="semesterDivide" class="form-control">

                    <option name="1학기" selected>1학기</option>

                    <option name="여름학기">여름학기</option>

                    <option name="2학기">2학기</option>

                    <option name="겨울학기">겨울학기</option>

                  </select>

                </div>

                <div class="form-group col-sm-4">

                  <label>강의 구분</label>

                  <select name="lectureDivide" class="form-control">

                    <option name="전공" selected>전공</option>

                    <option name="교양">교양</option>

                    <option name="기타">기타</option>

                  </select>

                </div>

              </div>

              <div class="form-group">

                <label>제목</label>

                <input type="text" name="evaluationTitle" class="form-control" maxlength="20">

              </div>

              <div class="form-group">

                <label>내용</label>

                <textarea type="text" name="evaluationContent" class="form-control" maxlength="2048" style="height: 180px;"></textarea>

              </div>

              <div class="form-row">

                <div class="form-group col-sm-3">

                  <label>종합</label>

                  <select name="totalScore" class="form-control">

                    <option value="A" selected>A</option>

                    <option value="B">B</option>

                    <option value="C">C</option>

                    <option value="D">D</option>

                    <option value="F">F</option>

                  </select>

                </div>

                <div class="form-group col-sm-3">

                  <label>성적</label>

                  <select name="creditScore" class="form-control">

                    <option value="A" selected>A</option>

                    <option value="B">B</option>

                    <option value="C">C</option>

                    <option value="D">D</option>

                    <option value="F">F</option>

                  </select>

                </div>

                <div class="form-group col-sm-3">

                  <label>널널</label>

                  <select name="comfortableScore" class="form-control">

                    <option value="A" selected>A</option>

                    <option value="B">B</option>

                    <option value="C">C</option>

                    <option value="D">D</option>

                    <option value="F">F</option>

                  </select>

                </div>

                <div class="form-group col-sm-3">

                  <label>강의</label>

                  <select name="lectureScore" class="form-control">

                    <option value="A" selected>A</option>

                    <option value="B">B</option>

                    <option value="C">C</option>

                    <option value="D">D</option>

                    <option value="F">F</option>

                  </select>

                </div>

              </div>

              <div class="modal-footer">

                <button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>

                <button type="submit" class="btn btn-primary">등록하기</button>

              </div>

            </form>

          </div>

        </div>

      </div>

    </div>

    <div class="modal fade" id="reportModal" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">

      <div class="modal-dialog">

        <div class="modal-content">

          <div class="modal-header">

            <h5 class="modal-title" id="modal">신고하기</h5>

            <button type="button" class="close" data-dismiss="modal" aria-label="Close">

              <span aria-hidden="true">&times;</span>

            </button>

          </div>

          <div class="modal-body">

            <form method="post" action="./reportAction.jsp">

              <div class="form-group">

                <label>신고 제목</label>

                <input type="text" name="reportTitle" class="form-control" maxlength="20">

              </div>

              <div class="form-group">

                <label>신고 내용</label>

                <textarea type="text" name="reportContent" class="form-control" maxlength="2048" style="height: 180px;"></textarea>

              </div>

              <div class="modal-footer">

                <button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>

                <button type="submit" class="btn btn-danger">신고하기</button>

              </div>

            </form>

          </div>

        </div>

      </div>

    </div>

    <footer class="bg-dark mt-4 p-5 text-center" style="color: #FFFFFF;">

      Copyright ⓒ 2018 나동빈 All Rights Reserved.

    </footer>

    <!-- 제이쿼리 자바스크립트 추가하기 -->

    <script src="./js/jquery.min.js"></script>

    <!-- Popper 자바스크립트 추가하기 -->

    <script src="./js/popper.min.js"></script>

    <!-- 부트스트랩 자바스크립트 추가하기 -->

    <script src="./js/bootstrap.min.js"></script>

  </body>

</html>


  이제 한 번 실행해서 테스트를 해보도록 하겠습니다.






728x90
반응형

Comment +4

  • 안경벗은개발자 2018.03.28 14:40

    위에 올려놓은 소스에 문제가 있습니다.

    1. textarea 는 type으로 text를 따로 명시하면 안됩니다.
    2. option은 value로 지정해야합니다. name으로 주면 안됩니다.
    3. connection에 대해 초기화 해주지않았습니다.
    4. connection conn에 util패키지 하위에 getConnection을 해줘야 합니다.

    • 제가 몰랐던 내용을 말씀해주셔서 감사합니다! 글은 수정이 가능한데, 유튜브에 올려 놓은 동영상 강좌는 수정이 불가능해 마음이 아프네요...

    • 안경벗은개발자 2018.04.17 09:59

      항상 응원합니다.
      유투브등으로 많은 도움이되어,
      그간의 지식에 대한 보상으로 유데미 유료결제또한 해드렸구요.
      학업으로 많이 바쁘신거같군요..
      아직 메세지 응답이나, 메일을 확인하지 못하는듯 한데.. 힘내세요

  • ji 2019.12.03 23:19

    관리자의 승인을 기다리고 있는 댓글입니다

728x90
반응형

  이번 시간에는 JSP 강의평가(Lecture Evaluation) 웹 사이트 개발하기의 여덟 번째 시간입니다. 지난 시간에는 로그인 및 로그아웃 기능을 구현했습니다. 이제 로그인 이후에 사용자들이 강의 평가 글을 등록하는 기능을 작성해보도록 하겠습니다. 또한 특정한 게시글 등에 대해서 신고를 하는 기능 또한 구현을 하려고 합니다. 바로 시작을 해보도록 합시다.



  위와 같이 두 개의 JSP 페이지를 추가합니다. 하나는 reportAction.jsp이고, 다른 하나는 evaluationRegisterAction.jsp입니다. 그리고 evaluation 패키지를 생성합니다. 이후에 해당 패키지 안에 EvaluationDTO.java, EvaluationDAO.java를 작성해주시면 됩니다.


  ▶ EvaluationDTO.java: 하나의 강의 평가 정보를 담고 있는 데이터베이스 트랜잭션 객체 역할을 담당합니다.


package evaluation;


public class EvaluationDTO {


int evaluationID;

String userID;

String lectureName;

String professorName;

int lectureYear;

String semesterDivide;

String lectureDivide;

String evaluationTitle;

String evaluationContent;

String totalScore;

String creditScore;

String comfortableScore;

String lectureScore;

int likeCount;

public int getEvaluationID() {

return evaluationID;

}

public void setEvaluationID(int evaluationID) {

this.evaluationID = evaluationID;

}

public String getUserID() {

return userID;

}

public void setUserID(String userID) {

this.userID = userID;

}

public String getLectureName() {

return lectureName;

}

public void setLectureName(String lectureName) {

this.lectureName = lectureName;

}

public String getProfessorName() {

return professorName;

}

public void setProfessorName(String professorName) {

this.professorName = professorName;

}

public int getLectureYear() {

return lectureYear;

}

public void setLectureYear(int lectureYear) {

this.lectureYear = lectureYear;

}

public String getSemesterDivide() {

return semesterDivide;

}

public void setSemesterDivide(String semesterDivide) {

this.semesterDivide = semesterDivide;

}

public String getLectureDivide() {

return lectureDivide;

}

public void setLectureDivide(String lectureDivide) {

this.lectureDivide = lectureDivide;

}

public String getEvaluationTitle() {

return evaluationTitle;

}

public void setEvaluationTitle(String evaluationTitle) {

this.evaluationTitle = evaluationTitle;

}

public String getEvaluationContent() {

return evaluationContent;

}

public void setEvaluationContent(String evaluationContent) {

this.evaluationContent = evaluationContent;

}

public String getTotalScore() {

return totalScore;

}

public void setTotalScore(String totalScore) {

this.totalScore = totalScore;

}

public String getCreditScore() {

return creditScore;

}

public void setCreditScore(String creditScore) {

this.creditScore = creditScore;

}

public String getComfortableScore() {

return comfortableScore;

}

public void setComfortableScore(String comfortableScore) {

this.comfortableScore = comfortableScore;

}

public String getLectureScore() {

return lectureScore;

}

public void setLectureScore(String lectureScore) {

this.lectureScore = lectureScore;

}

public int getLikeCount() {

return likeCount;

}

public void setLikeCount(int likeCount) {

this.likeCount = likeCount;

}

public EvaluationDTO(int evaluationID, String userID, String lectureName, String professorName, int lectureYear,

String semesterDivide, String lectureDivide, String evaluationTitle, String evaluationContent,

String totalScore, String creditScore, String comfortableScore, String lectureScore, int likeCount) {

super();

this.evaluationID = evaluationID;

this.userID = userID;

this.lectureName = lectureName;

this.professorName = professorName;

this.lectureYear = lectureYear;

this.semesterDivide = semesterDivide;

this.lectureDivide = lectureDivide;

this.evaluationTitle = evaluationTitle;

this.evaluationContent = evaluationContent;

this.totalScore = totalScore;

this.creditScore = creditScore;

this.comfortableScore = comfortableScore;

this.lectureScore = lectureScore;

this.likeCount = likeCount;

}

}


  ▶ EvaluationDAO.java: 강의 평가와 관련된 데이터베이스 접근을 가능하게 해주는 객체입니다.


package evaluation;


import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;


public class EvaluationDAO {


private Connection conn;

private ResultSet rs;


public EvaluationDAO() {

try {

String dbURL = "jdbc:mysql://localhost:3306/LectureEvaluation";

String dbID = "데이터베이스 아이디";

String dbPassword = "데이터베이스 비밀번호";

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(dbURL, dbID, dbPassword);

} catch (Exception e) {

e.printStackTrace();

}

}

public int write(EvaluationDTO evaluationDTO) {

PreparedStatement pstmt = null;

try {

String SQL = "INSERT INTO EVALUATION VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0);";

pstmt = conn.prepareStatement(SQL);

pstmt.setString(1, evaluationDTO.getUserID());

pstmt.setString(2, evaluationDTO.getLectureName());

pstmt.setString(3, evaluationDTO.getProfessorName());

pstmt.setInt(4, evaluationDTO.getLectureYear());

pstmt.setString(5, evaluationDTO.getSemesterDivide());

pstmt.setString(6, evaluationDTO.getLectureDivide());

pstmt.setString(7, evaluationDTO.getEvaluationTitle());

pstmt.setString(8, evaluationDTO.getEvaluationContent());

pstmt.setString(9, evaluationDTO.getTotalScore());

pstmt.setString(10, evaluationDTO.getCreditScore());

pstmt.setString(11, evaluationDTO.getComfortableScore());

pstmt.setString(12, evaluationDTO.getLectureScore());

return pstmt.executeUpdate();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if(pstmt != null) pstmt.close();

if(conn != null) conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

return -1;

}

}


  ▶ reportAction.jsp: 사용자가 신고서를 작성하면, 관리자의 메일로 그 신고 내용을 받습니다.


<%@page import="javax.mail.Transport"%>

<%@page import="javax.mail.Message"%>

<%@page import="javax.mail.Address"%>

<%@page import="javax.mail.internet.InternetAddress"%>

<%@page import="javax.mail.internet.MimeMessage"%>

<%@page import="javax.mail.Session"%>

<%@page import="javax.mail.Authenticator"%>

<%@page import="java.util.Properties"%>

<%@page import="java.io.PrintWriter"%>

<%@page import="user.UserDAO"%>

<%@page import="util.SHA256"%>

<%@page import="util.Gmail"%>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

return;

}

request.setCharacterEncoding("UTF-8");

String reportTitle = null;

String reportContent = null;

if(request.getParameter("reportTitle") != null) {

reportTitle = (String) request.getParameter("reportTitle");

}

if(request.getParameter("reportContent") != null) {

reportContent = (String) request.getParameter("reportContent");

}

if (reportTitle == null || reportContent == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('입력이 안 된 사항이 있습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

}

// 사용자에게 보낼 메시지를 기입합니다.

String host = "http://localhost:8080/Lecture_Evaluation/";

String from = "구글 계정 아이디";

String to = "관리자/개발자의 이메일 주소";

String subject = "강의평가 사이트에서 접수된 신고 메일입니다.";

String content = "신고자: " + userID + "<br>제목: " + reportTitle + "<br>내용: " + reportContent;

// SMTP에 접속하기 위한 정보를 기입합니다.

Properties p = new Properties();

p.put("mail.smtp.user", from);

p.put("mail.smtp.host", "smtp.googlemail.com");

p.put("mail.smtp.port", "465");

p.put("mail.smtp.starttls.enable", "true");

p.put("mail.smtp.auth", "true");

p.put("mail.smtp.debug", "true");

p.put("mail.smtp.socketFactory.port", "465");

p.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");

p.put("mail.smtp.socketFactory.fallback", "false");

 

try{

    Authenticator auth = new Gmail();

    Session ses = Session.getInstance(p, auth);

    ses.setDebug(true);

    MimeMessage msg = new MimeMessage(ses); 

    msg.setSubject(subject);

    Address fromAddr = new InternetAddress(from);

    msg.setFrom(fromAddr);

    Address toAddr = new InternetAddress(to);

    msg.addRecipient(Message.RecipientType.TO, toAddr);

    msg.setContent(content, "text/html;charset=UTF-8");

    Transport.send(msg);

} catch(Exception e){

    e.printStackTrace();

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('오류가 발생했습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

    return;

}

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('정상적으로 신고되었습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

    return;

%>


  ▶ evaluationRegisterAction.jsp: 사용자가 평가를 등록하게 되면, 그 평가 등록을 처리합니다.


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="evaluation.EvaluationDTO"%>

<%@ page import="evaluation.EvaluationDAO"%>

<%@ page import="java.io.PrintWriter"%>

<%

request.setCharacterEncoding("UTF-8");


String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

return;

}

request.setCharacterEncoding("UTF-8");

String lectureName = null;

String professorName = null;

int lectureYear = 0;

String semesterDivide = null;

String lectureDivide = null;

String evaluationTitle = null;

String evaluationContent = null;

String totalScore = null;

String creditScore = null;

String comfortableScore = null;

String lectureScore = null;

if(request.getParameter("lectureName") != null) {

lectureName = (String) request.getParameter("lectureName");

}

if(request.getParameter("professorName") != null) {

professorName = (String) request.getParameter("professorName");

}

if(request.getParameter("lectureYear") != null) {

try {

lectureYear = Integer.parseInt(request.getParameter("lectureYear"));

} catch (Exception e) {

System.out.println("강의 연도 데이터 오류");

}

}

if(request.getParameter("semesterDivide") != null) {

semesterDivide = (String) request.getParameter("semesterDivide");

}

if(request.getParameter("lectureDivide") != null) {

lectureDivide = (String) request.getParameter("lectureDivide");

}

if(request.getParameter("evaluationTitle") != null) {

evaluationTitle = (String) request.getParameter("evaluationTitle");

}

if(request.getParameter("evaluationContent") != null) {

evaluationContent = (String) request.getParameter("evaluationContent");

}

if(request.getParameter("totalScore") != null) {

totalScore = (String) request.getParameter("totalScore");

}

if(request.getParameter("creditScore") != null) {

creditScore = (String) request.getParameter("creditScore");

}

if(request.getParameter("comfortableScore") != null) {

comfortableScore = (String) request.getParameter("comfortableScore");

}

if(request.getParameter("lectureScore") != null) {

lectureScore = (String) request.getParameter("lectureScore");

}

if (lectureName == null || professorName == null || lectureYear == 0 || semesterDivide == null ||

lectureDivide == null || evaluationTitle == null || evaluationContent == null || totalScore == null ||

creditScore == null || comfortableScore == null || lectureScore == null ||

evaluationTitle.equals("") || evaluationContent.equals("")) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('입력이 안 된 사항이 있습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

} else {

EvaluationDAO evaluationDAO = new EvaluationDAO();

int result = evaluationDAO.write(new EvaluationDTO(0, userID, lectureName, professorName, lectureYear,

semesterDivide, lectureDivide, evaluationTitle, evaluationContent,

totalScore, creditScore, comfortableScore, lectureScore, 0));

if (result == -1) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('평가 등록에 실패했습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

return;

} else {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("location.href = './index.jsp';");

script.println("</script>");

script.close();

return;

}

}

%>


  이제 한 번 테스트를 해봅시다.



  위와 같이 신고를 해보겠습니다.


  

  그럼 위와 같이 관리자 이메일로 신고 내용이 도착하는 것을 알 수 있습니다.


  평가 또한 등록해보도록 하겠습니다.



  성공적으로 평가 데이터가 데이터베이스에 등록되었습니다.

728x90
반응형

Comment +7

  • 김혁유 2018.05.14 23:56

    관리자의 승인을 기다리고 있는 댓글입니다

  • 살길바라냐 2018.06.14 13:07

    인프런에 답변이 없으셔서요 jdbc 최신버전인데도 안되네요 해결방법 없나요?


    Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
    Thu Jun 14 00:00:33 KST 2018 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
    java.sql.SQLException: The server time zone value ‘´???¹?±¹ ???ؽ?’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:87)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:61)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:71)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76)
    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:862)
    at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:444)
    at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:230)
    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:226)
    at java.sql.DriverManager.getConnection(Unknown Source)
    at java.sql.DriverManager.getConnection(Unknown Source)
    at util.DatabaseUtil.getConnection(DatabaseUtil.java:14)
    at user.UserDAO.join(UserDAO.java:14)
    at org.apache.jsp.userJoinAction_jsp._jspService(userJoinAction_jsp.java:139)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
    Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value ‘´???¹?±¹ ???ؽ?’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:59)
    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:83)
    at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:128)
    at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2201)
    at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2225)
    at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1391)
    at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:993)
    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:852)
    … 36 more
    java.lang.NullPointerException
    at user.UserDAO.join(UserDAO.java:15)
    at org.apache.jsp.userJoinAction_jsp._jspService(userJoinAction_jsp.java:139)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

  • 초보입니다. 2018.07.01 16:08

    관리자의 승인을 기다리고 있는 댓글입니다

  • 2019.06.19 23:32

    비밀댓글입니다

  • 2019.10.02 01:42

    비밀댓글입니다

728x90
반응형

  이번 시간은 JSP 강의평가(Lecture Evaluation) 웹 사이트 개발하기의 일곱 번째 시간입니다. 지난 시간에는 회원가입 및 이메일 전송 기능을 구현했습니다. 이제 실질적으로 회원가입에 성공한 사람이 로그인을 할 수 있도록 해주는 것입니다. 또한 로그인 이후에는 로그아웃도 할 수 있도록 개발을 해주어야겠지요. 바로 다음과 같이 userLoginAction.jsp와 userLogout.jsp를 작성하도록 합니다.



▶ userLoginAction.jsp: 실질적인 사용자의 로그인을 처리하는 부분입니다.


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="user.UserDTO"%>

<%@ page import="user.UserDAO"%>

<%@ page import="java.io.PrintWriter"%>

<%

request.setCharacterEncoding("UTF-8");

String userID = null;

String userPassword = null;

if(request.getParameter("userID") != null) {

userID = (String) request.getParameter("userID");

}

if(request.getParameter("userPassword") != null) {

userPassword = (String) request.getParameter("userPassword");

}

UserDAO userDAO = new UserDAO();

int result = userDAO.login(userID, userPassword);

if (result == 1) {

session.setAttribute("userID", userID);

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("location.href='index.jsp'");

script.println("</script>");

script.close();

} else if (result == 0) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('비밀번호가 틀립니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

} else if (result == -1) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('존재하지 않는 아이디입니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

} else if (result == -2) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('데이터베이스 오류가 발생했습니다.');");

script.println("history.back();");

script.println("</script>");

script.close();

}

%>


▶ userLogout.jsp: 사용자의 로그인 세션을 파기하는 부분입니다.


<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@ page import="java.io.PrintWriter"%>

<%

session.invalidate();

%>

<script>

location.href = 'index.jsp';

</script>


  이제 실질적으로 로그인을 했을 때와 로그인을 하지 않았을 때를 세션으로 구분하기 위해서 다음과 같이 처리해주도록 하겠습니다.


▶ index.jsp 페이지의 윗부분


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.io.PrintWriter"%>

<%@ page import="user.UserDAO"%>

<!doctype html>

<html>

  <head>

    <title>강의평가 웹 사이트</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- 부트스트랩 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/bootstrap.min.css">

    <!-- 커스텀 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/custom.css">

  </head>

  <body>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID == null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인을 해주세요.');");

script.println("location.href = 'userLogin.jsp'");

script.println("</script>");

script.close();

}

boolean emailChecked = new UserDAO().getUserEmailChecked(userID);

if(emailChecked == false) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("location.href = 'emailSendConfirm.jsp'");

script.println("</script>");

script.close();

return;

}

%>

    <nav class="navbar navbar-expand-lg navbar-light bg-light">

      <a class="navbar-brand" href="index.jsp">강의평가 웹 사이트</a>

      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">

        <span class="navbar-toggler-icon"></span>

      </button>

      <div class="collapse navbar-collapse" id="navbar">

        <ul class="navbar-nav mr-auto">

          <li class="nav-item active">

            <a class="nav-link" href="index.jsp">메인</a>

          </li>

          <li class="nav-item dropdown">

            <a class="nav-link dropdown-toggle" id="dropdown" data-toggle="dropdown">

              회원 관리

            </a>

            <div class="dropdown-menu" aria-labelledby="dropdown">

<%

if(userID == null) {

%>

              <a class="dropdown-item" href="userLogin.jsp">로그인</a>

              <a class="dropdown-item" href="userRegister.jsp">회원가입</a>

<%

} else {

%>

              <a class="dropdown-item" href="userLogout.jsp">로그아웃</a>

<%

}

%>

            </div>

          </li>

        </ul>

        <form action="./index.jsp" method="get" class="form-inline my-2 my-lg-0">

          <input type="text" name="search" class="form-control mr-sm-2" placeholder="내용을 입력하세요.">

          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">검색</button>

        </form>

      </div>

    </nav>


▶ userLogin.jsp 페이지의 윗부분


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.io.PrintWriter"%>

<!doctype html>

<html>

  <head>

    <title>강의평가 웹 사이트</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- 부트스트랩 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/bootstrap.min.css">

    <!-- 커스텀 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/custom.css">

  </head>

  <body>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID != null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인이 된 상태입니다.');");

script.println("location.href = 'index.jsp'");

script.println("</script>");

script.close();

}

%>

    <nav class="navbar navbar-expand-lg navbar-light bg-light">

      <a class="navbar-brand" href="index.jsp">강의평가 웹 사이트</a>

      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">

        <span class="navbar-toggler-icon"></span>

      </button>

      <div class="collapse navbar-collapse" id="navbar">

        <ul class="navbar-nav mr-auto">

          <li class="nav-item active">

            <a class="nav-link" href="index.jsp">메인</a>

          </li>

          <li class="nav-item dropdown">

            <a class="nav-link dropdown-toggle" id="dropdown" data-toggle="dropdown">

              회원 관리

            </a>

            <div class="dropdown-menu" aria-labelledby="dropdown">

<%

if(userID == null) {

%>

              <a class="dropdown-item" href="userLogin.jsp">로그인</a>

              <a class="dropdown-item" href="userRegister.jsp">회원가입</a>

<%

} else {

%>

              <a class="dropdown-item" href="userLogout.jsp">로그아웃</a>

<%

}

%>

            </div>

          </li>

        </ul>

        <form action="./index.jsp" method="get" class="form-inline my-2 my-lg-0">

          <input type="text" name="search" class="form-control mr-sm-2" placeholder="내용을 입력하세요.">

          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">검색</button>

        </form>

      </div>

    </nav>


▶ userRegisterAction.jsp 페이지의 윗부분


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.io.PrintWriter"%>

<!doctype html>

<html>

  <head>

    <title>강의평가 웹 사이트</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- 부트스트랩 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/bootstrap.min.css">

    <!-- 커스텀 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/custom.css">

  </head>

  <body>

<%

String userID = null;

if(session.getAttribute("userID") != null) {

userID = (String) session.getAttribute("userID");

}

if(userID != null) {

PrintWriter script = response.getWriter();

script.println("<script>");

script.println("alert('로그인이 된 상태입니다.');");

script.println("location.href = 'index.jsp'");

script.println("</script>");

script.close();

}

%>

    <nav class="navbar navbar-expand-lg navbar-light bg-light">

      <a class="navbar-brand" href="index.jsp">강의평가 웹 사이트</a>

      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">

        <span class="navbar-toggler-icon"></span>

      </button>

      <div class="collapse navbar-collapse" id="navbar">

        <ul class="navbar-nav mr-auto">

          <li class="nav-item active">

            <a class="nav-link" href="index.jsp">메인</a>

          </li>

          <li class="nav-item dropdown">

            <a class="nav-link dropdown-toggle" id="dropdown" data-toggle="dropdown">

              회원 관리

            </a>

            <div class="dropdown-menu" aria-labelledby="dropdown">

<%

if(userID == null) {

%>

              <a class="dropdown-item" href="userLogin.jsp">로그인</a>

              <a class="dropdown-item" href="userRegister.jsp">회원가입</a>

<%

} else {

%>

              <a class="dropdown-item" href="userLogout.jsp">로그아웃</a>

<%

}

%>

            </div>

          </li>

        </ul>

        <form action="./index.jsp" method="get" class="form-inline my-2 my-lg-0">

          <input type="text" name="search" class="form-control mr-sm-2" placeholder="내용을 입력하세요.">

          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">검색</button>

        </form>

      </div>

    </nav>


  이후에 현재 소스코드에서는 이메일 인증이 되지 않은 사람은 메인 페이지로 접속할 수 없습니다. 따라서 이메일 인증이 되지 않은 사람이 메인 페이지에 접속하면 emailSendConfirm.jsp로 이동하도록 만들었습니다. 그러므로 emailSendConfirm.jsp를 새롭게 만들어줍시다.



▶ emailSendConfirm.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!doctype html>

<html>

  <head>

    <title>강의평가 웹 사이트</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- 부트스트랩 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/bootstrap.min.css">

    <!-- 커스텀 CSS 추가하기 -->

    <link rel="stylesheet" href="./css/custom.css">

  </head>

  <body>

    <nav class="navbar navbar-expand-lg navbar-light bg-light">

      <a class="navbar-brand" href="index.jsp">강의평가 웹 사이트</a>

      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">

        <span class="navbar-toggler-icon"></span>

      </button>

      <div class="collapse navbar-collapse" id="navbar">

        <ul class="navbar-nav mr-auto">

          <li class="nav-item active">

            <a class="nav-link" href="index.jsp">메인</a>

          </li>

          <li class="nav-item dropdown">

            <a class="nav-link dropdown-toggle" id="dropdown" data-toggle="dropdown">

              회원 관리

            </a>

            <div class="dropdown-menu" aria-labelledby="dropdown">

              <a class="dropdown-item" href="userLogout.jsp">로그아웃</a>

            </div>

          </li>

        </ul>

        <form action="./index.jsp" method="get" class="form-inline my-2 my-lg-0">

          <input type="text" name="search" class="form-control mr-sm-2" placeholder="내용을 입력하세요.">

          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">검색</button>

        </form>

      </div>

    </nav>

<div class="container">

    <div class="alert alert-warning mt-4" role="alert">

  이메일 주소 인증을 하셔야 이용 가능합니다. 인증 메일을 받지 못하셨나요?

</div>

<a href="emailSendAction.jsp" class="btn btn-primary">인증 메일 다시 받기</a>

    </div>

    <footer class="bg-dark mt-4 p-5 text-center" style="color: #FFFFFF;">

      Copyright ⓒ 2018 나동빈 All Rights Reserved.

    </footer>

    <!-- 제이쿼리 자바스크립트 추가하기 -->

    <script src="./js/jquery.min.js"></script>

    <!-- Popper 자바스크립트 추가하기 -->

    <script src="./js/popper.min.js"></script>

    <!-- 부트스트랩 자바스크립트 추가하기 -->

    <script src="./js/bootstrap.min.js"></script>

  </body>

</html>


  이제 테스트하면 로그인, 로그아웃, 회원가입, 이메일 인증 및 메인 페이지에서의 세션 관리 부분까지 완전하게 동작하는 것을 확인할 수 있습니다.



728x90
반응형

Comment +8

  • 안경벗은개발자 2018.03.15 16:42

    훌륭합니다.
    개인적으로 다른 어떤 강좌보다 best of best 입니다.
    동영상도 아주 훌륭하고.. 대단하네요 동빈사리님

    jsp 처음접하다가 동빈사리님꺼보고 실력 많이 올랐어요 감사합니다.
    개인적으로 스프링강좌도 올라왔으면 너무좋겠네요
    게시판에서 댓글기능도 한번 구현해보았으면 좋겠네요

    화이팅하세요. 성공하실겁니다 ^^

  • 최형주 2018.03.16 13:19

    안녕하세요, 블로그 글을 보면서 많이 배우고 있습니다.
    다름이 아니라 본문을 보다가 잘못된점이 보여서 알려드릴려고 이렇게 글을 쓰게 되었습니다.

    본문 내용중 ▶ userRegisterAction.jsp 페이지의 윗부분 <--- 이부분이 userRegister.jsp인것 같습니다~^^
    수고하십시오~!!

  • 2019.08.14 18:05

    비밀댓글입니다

  • 2020.04.25 23:09

    비밀댓글입니다