본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 51일차 (2023-08-02) 자바 프로그래밍_55. 웹 애플리케이션 서버 구조로 전환하기 - 웹 기술 도입_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 8. 2.
## 55. 웹 애플리케이션 서버 구조로 전환하기 - 웹 기술 도입

- 웹 기술을 도입하여 애플리케이션 서버 / 클라이언트를 구축하는 방법
- Netty, Reactor 라이브러리를 사용하여 웹서버를 구축하는 방법
- 웹브라우저를 이용하여 클라이언트를 구축하는 방법
- 쿠키와 세션을 다루는 방법

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 잠시 주석처리

 

 

Netty 라이브러리

=>

Reactor Netty 라이브러리 이용

ㄴ Gradle Installation 관련 코드 복사

=>

build.gradle

ㄴ 복사한 코드 build.gradle 파일에 붙여넣기

=>

ㄴ gradle 재설정

=>

ㄴ 프로젝트를 Refresh 해주기

 

ㄴ 라이브러리가 추가됨을 확인

 

https://godekdls.github.io/Reactor%20Netty/httpserver/

 

HTTP Server

리액터 네티로 HTTP 서버 설정하기 한글 번역

godekdls.github.io

 

=>

ServerApp.java

=>

ServerApp.java

ㄴ port 번호 추가 => 8888

ㄴ 눈으로 확인하기 위해 출력문 추가

=>

 

ServerApp.java

=>

ServerApp.java

=>

=>

=>

ㄴ 한글 깨지는 현상이 있음

 

ㄴ report-server/src/main/resources 경로에 static 이라는 이름의 폴더를 생성

 

 

ㄴ static 폴더에 index.html 파일 생성

 

index.html

 

ServerApp.java

=>

ServerApp.java

=>

 

ServerApp.java

ㄴ index.html 파일 경로 추가

=>

=>

 

ㄴ 주석 처리 후 요청 처리기 역할을 하는 해당 코드 추가

=>

ㄴ processRequest 메서드에서 HttpServerRequest와 HttpServerResponse 객체를 이용하여 요청을 처리하도록 함

 

ServerApp.java

ㄴ NettyOutbound 를 이용하도록 함

 

ServerApp.java

ㄴ try 블록에서 예외가 발생한다면 "Error!"라는 오류 응답을 생성하고 response.sendString(...)으로 클라이언트에게 오류 응답을 보내도록 함

=>

=>

=>

ㄴ 현재 /board/list 경로에서도 hello, world! 가 출력됨

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 해당 코드 제거

 

ServerApp.java

ㄴ 주석 풀어주기

 

=>

ㄴ DispatcherListener -> DispatcherServlet 으로 이름 변경해주기

 

ㄴ bitcamp.util 패키지에 Servlet 이라는 이름으로 인터페이스를 생성하기

 

Servlet.java

ㄴ reactor.netty의 HTTP 서버에서 사용될 서블릿 구현체를 정의하기위함

 

ㄴ bitcamp.util 패키지에 HttpServletRequest 라는 이름의 클래스를 생성

 

HttpServletRequest.java

=>

HttpServletRequest.java

=>

=>

HttpServletRequest.java

ㄴ HttpServletRequest 를 implements 하지않아도 되므로 제거

 

HttpServletRequest.java

ㄴ bitcamp.util 패키지에 HttpServletResponse 라는 이름의 클래스를 생성

 

HttpServletResponse.java

=>

HttpServletResponse.java

=>

HttpServletResponse.java

=>

HttpServletResponse.java

=>

HttpServletResponse.java

ㄴ PrintWriter을 사용하여 StringWriter 객체를 생성하도록 함

     => 문자열을 기록하는 PrintWriter를 생성하고, 이 PrintWriter가 실제로 문자열을 저장할 StringWriter를 생성하도록 함

 

HttpServletResponse.java

ㄴ 현재 객체가 소유하고 있는 PrintWriter 객체를 반환하도록 하는 메서드 getWriter() 생성하기

 

Servlet.java

ㄴ HttpServerRequest -> HttpServletRequest 로 변경

ㄴ HttpServerResponse -> HttpServletResponse 로 변경

 

DispatcherServlet.java

ㄴ ActionListener -> Servlet 로 변경하기

 

DispatcherServlet.java

ㄴ service 메서드 새로 오버라이딩 하기

=>

DispatcherServlet.java

ㄴ 해당 코드 지워서 새로 오버라이딩 한 메서드로 교체해주기

 

DispatcherServlet.java

ㄴ 출력 시 PrintWriter 를 이용하도록 함

 

ServerApp.java

ㄴ facadeListener -> dispatcherServlet 으로 이름 변경

 

ServerApp.java

ㄴ dispatcherServlet 객체를 사용하여 HTTP 요청을 처리하도록 함

ㄴ Reactor Netty의 HttpServerRequest와 HttpServerResponse 객체를 HttpServletRequest와 HttpServletResponse로 변환하여 서블릿 컨테이너의 dispatcherServlet에 요청을 전달하고, 응답을 처리하도록 함

=>

ServerApp.java

 

HttpServletResponse.java

ㄴ PrintWriter를 사용하여 StringWriter에 문자열을 기록하고 StringWriter에 기록된 문자열을 얻어와서 처리하도록 함

 

HttpServletResponse.java

ㄴ getContent 라는 이름으로 buf라는 StringWriter 객체에 저장된 문자열을 반환하도록 하는 메서드 작성

 

ServerApp.java

ㄴ 이제 "hello, world!" 대신 response2.getContent() 넣어주기

    => response2에 담긴 응답을 Reactor Netty의 HttpServerResponse 객체인 response에 담아서 클라이언트에게 응답을 보내도록 함

=>

서버 실행

=>

ㄴ 한글 깨지는 현상 발생

 

HttpServletResponse.java

ㄴ 응답 콘텐트의 타입 저장할 필드 선언

ㄴ text/plain은 텍스트 형식의 콘텐츠를 나타냄

ㄴ charset=ISO-8859-1은 해당 콘텐츠의 문자 인코딩 방식을 ISO-8859-1으로 지정하도록 함

 

HttpServletResponse.java

ㄴ out 필드가 null인 경우에만 PrintWriter 객체를 생성하고 그렇지 않으면 기존의 PrintWriter 객체를 반환하도록 함

 

HttpServletResponse.java

ㄴ out 필드가 null인 경우에만 응답 콘텐트의 타입을 설정하도록 함

ㄴ 이미 출력 스트림(out)을 사용한 상태라면, 추가적인 콘텐트 설정을 무시하고 메서드를 종료하도록 함

=>

서버 실행

=>

ㄴ 개발자 도구 열기

ㄴ Response Headers, Request Headers 모두 Raw 체크

 

HttpServletResponse.java

ㄴ contentType 필드의 값을 반환하도록 하는 메서드 getContentType 생성

 

ServerApp.java

ㄴ response2 객체의 getContentType() 메서드를 호출하여 Content-Type 값을 얻어와서, 이를 response 객체의 헤더에 추가하도록 함

=>

ServerApp 실행

=>

ㄴ 설정해두었던 Content-Type 이 노출됨

 

DispatcherServlet.java

ㄴ Content-Type 을 UTF-8 로 설정하기

=>

ServerApp 실행

=>

ㄴ Content-Type 이 UTF-8 로 설정된 것과 한글 제대로 출력됨을 확인

 

DispatcherServlet.java

=>

DispatcherServlet.java

ㄴ request 객체에서 path() 메서드를 호출하여 현재 HTTP 요청의 경로(path)를 얻어서 out 객체에 해당 경로를 출력해보기

=>

ServerApp 실행

=>

 

DispatcherServlet.java

ㄴ iocContainer라는 컨테이너에서 HTTP 요청 경로에 해당하는 빈(Bean)을 가져오고, 해당 빈을 Servlet 인터페이스로 캐스팅하여 servlet 변수에 할당하도록 함

 

DispatcherServlet.java

ㄴ servlet 변수에 할당된 값이 null 이라면 "해당 요청을 처리할 수 없습니다." 라는 문구를 출력하며 예외를 던지도록 함

 

DispatcherServlet.java

ㄴ 해당 코드 제거

 

ㄴ BoardListListener -> BoardListServlet 으로 이름 변경

 

BoardListServlet.java

ㄴ ActionListener 대신 Servlet 인터페이스로 변경해주기

 

BoardListServlet.java

ㄴ service 메서드를 새롭게 오버라이딩 해주기

=>

BoardListServlet.java

ㄴ response 객체의 setContentType() 메서드를 사용하여 HTTP 응답의 콘텐츠 타입을 설정하도록 함

ㄴ getWriter() 메서드를 사용하여 출력 스트림(PrintWriter)을 얻어오도록 함

 

BoardListServlet.java

ㄴ prompt -> out 으로 변경

    => 출력 스트림을 사용하여 텍스트를 클라이언트에게 전송하도록 함

 

BoardListServlet.java

ㄴ (String) prompt.getAttribute -> request.param 으로 변경

     =>  HTTP 요청에서 "category"라는 이름의 파라미터 값을 문자열 형태로 가져옴

 

BoardListServlet.java

ㄴ prompt -> out 으로 변경

=>

ServerApp 실행

=>

 

DispatcherServlet.java

ㄴ 클라이언트의 요청을 처리하기 위해 iocContainer에서 해당 요청 경로에 등록된 서블릿을 가져와서 처리하도록 함

ㄴ 해당 경로에 해당하는 서블릿이 없을 경우, 클라이언트에게 "해당 요청을 처리할 수 없습니다" 라는 문구의 에러 메시지를 응답하고 리턴하도록 함

 

BoardListServlet.java

ㄴ category 는 임시로 1 로 설정해두기

=>

ServerApp 실행

=>

BoardListServlet.java

ㄴ  HTTP 응답의 콘텐츠 타입 변경

     => "text/plain" -> "text/html" 으로 변경해줌

 

BoardListServlet.java

ㄴ 간단한 html 작성

    => 게시글을 표로 출력하여 확인 가능하도록 작성

=>

ServerApp 실행

=>

 

 

 

 

=>

 

ServerApp.java

ㄴ 임시로 url 을 정해주도록 함

 

https://netty.io/4.1/api/index.html

 

Netty API Reference (4.1.96.Final)

 

netty.io

ㄴ 해당 코드 복사하기

=>

ServerApp.java

ㄴ 복사한 코드 붙여넣은 후 위와 같이 변경

=>

ServerApp 실행

=>

ㄴ 테스트 성공

=>

ServerApp.java

ㄴ 테스트 코드 삭제 후 주석 풀기

 

ServerApp.java

=>

ServerApp 실행

=>

=>

ㄴ uri 를 이용하도록 함

=>

HttpServletRequest.java

ㄴ HttpServletRequest 의 생성자에서 주어진 original 객체의 URI를 이용하여 QueryStringDecoder를 생성하고, 이를 qsDecoder 필드에 저장하도록 함

 

HttpServletRequest.java

ㄴ HttpServletRequest 객체를 사용하여 서블릿 경로와 파라미터 값을 간편하게 추출할 수 있도록 메서드 생성

 

HttpServletRequest.java

ㄴ getParameterValues(String name) 메서드를 추가함

    => HttpServletRequest 객체를 사용하여 파라미터 값들을 배열로 간편하게 추출할 수 있도록 함

 

BoardListServlet.java

ㄴ request.getParameter("category")를 통해 클라이언트의 요청에서 "category" 파라미터 값을 가져와서 정수로 변환하여 boardDao.findAll() 메서드에 전달하도록 함

=>

ServerApp 실행

=>

ㄴ category 가 1 인 게시글 목록 출력

ㄴ category 가 2 인 게시글 목록 출력

 

index.html

ㄴ 메인 페이지 구성하기

 

DispatcherServlet.java

ㄴ "/" + request.path() -> request.getServletPath() 로 변경

     => 서블릿 경로 가져오도록 함

 

DispatcherServlet.java

=>

DispatcherServlet.java

=>

DispatcherServlet.java

=>

ServerApp 실행

=>

=>

ㄴ 경로 제대로 출력됨

 

DispatcherServlet.java

ㄴ getRealPath 메서드 생성

 

DispatcherServlet.java

=>

DispatcherServlet.java

=>

DispatcherServlet.java

ㄴ 요청한 경로가 "/"로 끝나면 getStaticContent() 메서드를 호출하여 해당 경로의 "index.html" 파일의 내용을 가져와서 응답으로 보내도록 함
ㄴ 서블릿의 실행을 요구하는 경우, iocContainer에서 해당 경로에 등록된 서블릿을 가져와서 요청을 처리하도록 함

    ㄴ 만약 해당 경로에 등록된 서블릿이 없으면 예외를 던지도록 함
ㄴ try-catch 블록을 사용하여 예외가 발생한 경우 해당 내용을 클라이언트에게 "해당 요청을 처리할 수 없습니다."라는 메시지로 응답하도록 함

=>

ServerApp 실행

=>

=>

DispatcherServlet.java

 

DispatcherServlet.java

=>

ServerApp 실행

=>

=>

index.html

ㄴ index 에서 회원, 게시판, 독서록을 클릭하면 이동할 수 있는 링크를 추가해주기

=>

브라우저 새로고침

ㄴ 링크 추가됨

=>

ㄴ 게시판 링크 클릭 시 게시판 목록으로 이동됨

 

ㄴ 독서록 링크 클릭 시 독서록 목록으로 이동됨

 

BoardListServlet.java

ㄴ 새 글 작성하는 링크 추가

 

ㄴ report-server/src/main/resources/static 폴더 안에 board 라는 폴더 생성

 

=>

ㄴ index.html 파일을  report-server/src/main/resources/static/board 에 복사한 후 form 이라는 이름으로 변경

 

form.html

ㄴ 해당 코드 수정

 

BoardListServlet.java

ㄴ <div> 태그 추가

=>

ServerApp 실행

=>

ㄴ 새 글 링크가 여백이 너무 없음을 확인

=>

BoardListServlet.java

ㄴ style 추가

=>

ServerApp 실행

=>

ㄴ 여백이 생김을 확인

 

DispatcherServlet.java

ㄴ request 객체의 서블릿 경로(getServletPath())가 ".html"로 끝나는 경우, 해당 HTML 문서를 읽어서 클라이언트에게 응답으로 보내도록 함

 

form.html

ㄴ form 태그에 action="/board/add" 추가

=>

ServerApp 실행

=>

=>

=>

ㄴ 내용을 입력하여 [등록] 버튼을 선택할 경우 "해당 요청을 처리할 수 없습니다." 문구 출력됨

=>

form.html

=>

ServerApp 실행

=>

=>

ㄴ 내용을 입력하여 [등록] 버튼을 선택할 경우 "해당 요청을 처리할 수 없습니다." 문구 출력됨

 

 

ㄴ BoardAddListener -> BoardAddServlet 으로 이름 변경

=>

BoardAddServlet.java

ㄴ ActionListener -> Servlet 으로 인터페이스 변경해주기

 

BoardAddServlet.java

ㄴ service 메서드 오버라이딩 새로하기

 

form.html

ㄴ category 넘겨주도록 함

=>

ServerApp 실행

=>

ㄴ category 넘겨주는 게 눈으로 보이므로 보이지 않도록 해줌

=>

form.html

=>

브라우저 새로고침

=>

=>

=>

 

HttpServletRequest.java

ㄴ attrMap 라는 이름으로 HashMap 객체 생성

 

HttpServletRequest.java

ㄴ setAttribute, getAttribute 메서드 생성

 

DispatcherServlet.java

ㄴ loginUser 를 임시로 no 가 3인 직원으로 설정해두기

 

BoardAddServlet.java

ㄴ loginUser 에 담긴 사용자 정보를 가져와서 작성자를 설정하도록 함

 

BoardAddServlet.java

ㄴ response 객체의 콘텐츠 타입(setContentType())을 "text/html;charset=UTF-8"로 설정하고, 해당 응답 객체의 PrintWriter를 얻어오도록 함

 

BoardAddServlet.java

ㄴ html 태그들을 추가함

=>

ServerApp 실행

=>

=>

 

BaordAddServlet.java

ㄴ meta 태그를 이용하여 글 작성 후 바로 목록을 보여주도록 설정

=>

ServerApp 실행

=>

=>

ㄴ 글 작성 후 1초뒤에 노출됨을 확인

 

 

ㄴ BoardDetailListener -> BoardDetailServlet 으로 이름 변경해줌

=>

BoardAddServlet 과 비슷한 방법으로 코드 수정 및 추가해주기

=>

BoardDetailServlet.java

 

BoardListServlet.java

ㄴ BoardListServlet 코드 수정

=>

ServerApp 실행

=>

ㄴ 게시글 목록이 표에 출력되며, 제목에 링크가 추가됨을 확인

=>

ㄴ 게시글이 표로 출력되도록 해줘야함

=>

BoardDetailServlet.java

=>

ServerApp 실행

=>

=>

BoardDetailServlet.java

=>

ServerApp 실행

=>

 

BoardDetailServlet.java

ㄴ 제목 style 설정 및 입력 가능하도록 설정

=>

BoardDetailServlet.java

ㄴ 내용 style 설정 및 입력 가능하도록 설정

=>

ServerApp 실행

=>

 

BoardDetailServlet.java

ㄴ form 태그 추가

 

BoardDetailServlet.java

ㄴ 번호는 readonly='readonly' 를 사용하여 수정할 수 없도록 함

ㄴ 스타일은 맨 위에만 적용해주면 되므로 번호에만 스타일 적용

ㄴ readonly 만 적어줘도 되지만 readonly='readonly' 로 적어주는 것을 권장

 

BoardDetailServlet.java

ㄴ hidden 타입으로 category 를 설정해주도록 함

 

BoardDetailServlet.java

ㄴ category 를 임의로 정하지 말고 getCategory 를 이용하여 받아오기

=>

ServerApp 실행

=>

=>

=>

ㄴ 내용 수정 후 [변경] 버튼 선택 시 위와 같이 출력됨

 

ㄴ BoardUpdateListener -> BoardUpdateServlet 으로 이름 변경

 

BoardUpdateServlet.java

ㄴ 코드 수정 및 추가

 

BoardAddServlet.java

ㄴ 코드 수정

 

BoardUpdateServlet.java

ㄴ prompt -> out 으로 변경하기

ㄴ 예외를 던지는 대신 "게시글 변경 실패입니다!" 라는 문구를 출력하도록 함

 

BoardUpdateServlet.java

ㄴ html 닫는 태그 추가

=>

ServerApp 실행

=>

=>

ㄴ 내용 변경 후 [변경] 버튼 선택 시 변경된 내용이 게시글 목록에 제대로 변경되어 노출됨을 확인

 

ㄴ 다른 직원의 글을 변경하려고 함

=>

ㄴ 변경되지 않음을 확인

 

 

ㄴ BoardDeleteListener -> BoardDeleteServlet 으로 변경

 

BoardDeleteServlet.java

ㄴ 코드 수정

 

DispatcherServlet.java

ㄴ 코드 수정

 

ServerApp.java

ㄴ "Error!" -> response2.getConent() 으로 변경

ㄴ HttpServletRequest, HttpServletResponse 객체는 try 문 밖에서 생성해주도록 함

 

ServerApp.java

ㄴ 해당 코드 주석 풀어주기

=>

ServerApp 실행

=>

=>

=>

ㄴ 내용 수정 후 [변경] 버튼 선택

=>

 

BoardDetailServlet.java

ㄴ 삭제 버튼 추가하기

 

SqlSessionFactoryProxy.java

ㄴ sqlSession 을 close 하도록 함

 

BoardListServlet.java

ㄴ 제목이 입력되지 않았다면 "제목없음" 이라는 문구로 저장되도록 함

 

SqlSessionFactoryProxy.java

ㄴ openSession 에 true 를 전달하도록 함

 

SqlSessionFactoryProxy.java

ㄴ 해당 코드 수정

 

MySQLBoardDao.java

ㄴ true -> false 로 수정

 

BoardListServlet.java

ㄴ </table> 태그가 빠져있으므로 추가

ㄴ 메인 링크 추가

=>

ㄴ 메인 링크 추가됨을 확인

 

ㄴ 메인 링크 클릭 시 메인으로 이동됨을 확인

 

ㄴ handler 패키지에 BoardAddServlet.java 파일을 복사하여 BoardFormServlet 라는 이름으로 붙여넣기

 

BoardFormServlet.java

ㄴ add -> form 으로 변경

 

BoardFormServlet.java

ㄴ 해당 코드 제거

 

BoardFormServlet.java

ㄴ 해당 코드 제거

 

BoardFormServlet.java

ㄴ 해당 코드 제거

=>

BoardFormServlet.java

 

 

BoardListServlet.java

ㄴ 해당 코드 추가

 

BoardListServlet.java

=>

BoardListServlet.java

ㄴ 새 글 링크 경로의 category 는 직접 정해주는 것이 아니라 받아와서 설정하도록 함

 

ㄴ 이제 form.html 은 필요 없으므로 제거

    => BoardFormServlet 이용

 

BoardFormServlet.java

ㄴ category 값을 받아와서 설정하도록 함

 

MySQLMemberDao.java

ㄴ list, findBy, findByPhoneAndPassword 메서드 모두 openSession 에 false 를 넘겨주도록 함

 

MySQLItemDao.java

ㄴ list, findBy 메서드 모두 openSession 에 false 를 넘겨주도록 함

 

SqlSessionFactoryProxy.java

ㄴ 스레드에서 SqlSession 이 제거됨을 눈으로 확인하기 위해 출력문 추가

 

SqlSessionFactoryProxy.java

ㄴ original. 제거

=>

ServerApp 실행

=>

=>

=>

=>

=>

=>

 

 

=>

=>

=>

=>

=>

ㄴ 필요 없는 파일 모두 삭제하기

 

=> MemberXxxListener 와 ItemXxxListener 도 BoardXxxListener 와 같은 방식으로 변경해주기

 

LoginListener.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/auth/login")
public class LoginServlet implements Servlet {

  MemberDao memberDao;

  public LoginServlet(MemberDao memberDao) {
    this.memberDao = memberDao;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
    Member m = new Member();
    m.setPhone(request.getParameter("phone"));
    m.setPassword(request.getParameter("password"));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.println("<title>로그인</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>로그인</h1>");

    Member loginUser = memberDao.findByPhoneAndPassword(m);
    if (loginUser == null) {
      out.println("<p>회원 정보가 일치하지 않습니다.</p>");
    } else {
      out.println("<p>로그인 성공입니다!</p>");
    }

    out.println("</body>");
    out.println("</html>");
  }
}

 

MemberActionListener.java 파일은 제거

 

MemberAddServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/member/add")
public class MemberAddServlet implements Servlet {

  MemberDao memberDao;
  SqlSessionFactory sqlSessionFactory;

  public MemberAddServlet(MemberDao memberDao, SqlSessionFactory sqlSessionFactory) {
    this.memberDao = memberDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Member m = new Member();
    m.setName(request.getParameter("name"));
    m.setPhone(request.getParameter("phone"));
    m.setPassword(request.getParameter("password"));
    m.setPosition(request.getParameter("position").charAt(0));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.printf("<meta http-equiv='refresh' content='1;url=/member/list'>");
    out.println("<title>직원</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>직원 등록</h1>");

    try {
      memberDao.insert(m);
      sqlSessionFactory.openSession(false).commit();
      out.println("<p>등록 성공입니다!</p>");

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      out.println("<p>등록 실패입니다!</p>");
      e.printStackTrace();
    }

    out.println("</body>");
    out.println("</html>");
  }
}

 

MemberDeleteServlet.java

package bitcamp.report.handler;

import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.MemberDao;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/member/delete")
public class MemberDeleteServlet implements Servlet {

  MemberDao memberDao;
  SqlSessionFactory sqlSessionFactory;

  public MemberDeleteServlet(MemberDao memberDao, SqlSessionFactory sqlSessionFactory) {
    this.memberDao = memberDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    try {
      if (memberDao.delete(Integer.parseInt(request.getParameter("no"))) == 0) {
        throw new Exception("해당 번호의 직원이 없습니다!");
      } else {
        response.sendRedirect("/member/list");
      }
      sqlSessionFactory.openSession(false).commit();

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      throw new RuntimeException(e);
    }
  }

}

 

MemberDetailServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/member/detail")
public class MemberDetailServlet implements Servlet {

  MemberDao memberDao;

  public MemberDetailServlet(MemberDao memberDao) {
    this.memberDao = memberDao;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Member member = memberDao.findBy(Integer.parseInt(request.getParameter("no")));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.println("<title>직원</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>직원</h1>");

    if (member == null) {
      out.println("<p>해당 번호의 직원이 없습니다!</p>");
    } else {
      out.println("<form action='/member/update'>");
      out.println("<table border='1'>");
      out.printf("<tr><th style='width:120px;'>번호</th>"
          + " <td style='width:300px;'><input type='text' name='no' value='%d' readonly></td></tr>\n",
          member.getNo());
      out.printf("<tr><th>이름</th>"
          + " <td><input type='text' name='name' value='%s'></td></tr>\n", member.getName());
      out.printf("<tr><th>전화번호</th>"
          + " <td><input type='tel' name='phone' value='%s'></td></tr>\n", member.getPhone());
      out.printf("<tr><th>암호</th>"
          + " <td><input type='password' name='password'></td></tr>\n", member.getName());
      out.printf("<tr><th>직책</th>"
          + " <td><select name='position'>\n"
          + " <option value='0' %s>관리자</option>\n"
          + " <option value='1' %s>일반직원</option></select></td></tr>\n", 
          (member.getPosition() == '0' ? "selected" : ""),
          (member.getPosition() == '1' ? "selected" : ""));
      out.println("</table>");
      
      out.println("<div>");
      out.println("<button>변경</button>");
      out.println("<button type='reset'>초기화</button>");
      out.printf("<a href='/member/delete?no=%d'>삭제</a>\n", member.getNo());
      out.println("<a href='/member/list'>목록</a>\n");
      out.println("</div>");
      out.println("</form>");
    }
    
    out.println("</body>");
    out.println("</html>");
    
  }
}

 

MemberListServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import java.util.List;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/member/list")
public class MemberListServlet implements Servlet {

  MemberDao memberDao;

  public MemberListServlet(MemberDao memberDao) {
    this.memberDao = memberDao;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.println("<title>직원</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>직원 목록</h1>");
    out.println("<div style='margin:5px;'>");
    out.println("<a href='/member/form.html'>새 직원</a>");
    out.println("</div>");
    out.println("<table border='1'>");
    out.println("  <tr><th>번호</th> <th>이름</th> <th>전화번호</th></tr>");
    out.println("</thead>");

    List<Member> list = memberDao.findAll();
    for (Member m : list) {
      out.printf("<tr>"
          + " <td>%d</td>"
          + " <td><a href='/member/detail?no=%d'>%s</a></td>"
          + " <td>%s</td></tr>\n", 
          m.getNo(), m.getNo(), m.getName(), m.getPhone());
    }

    out.println("</tbody>");
    out.println("</table>");
    out.println("<a href='/'>메인</a>");
    out.println("</body>");
    out.println("</html>");
  }

}

 

MemberUpdateServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/member/update")
public class MemberUpdateServlet implements Servlet {

  MemberDao memberDao;
  SqlSessionFactory sqlSessionFactory;

  public MemberUpdateServlet(MemberDao memberDao, SqlSessionFactory sqlSessionFactory) {
    this.memberDao = memberDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {


    Member member = new Member();
    member.setNo(Integer.parseInt(request.getParameter("no")));
    member.setName(request.getParameter("name"));
    member.setPhone(request.getParameter("phone"));
    member.setPassword(request.getParameter("password"));
    member.setPosition(request.getParameter("position").charAt(0));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.printf("<meta http-equiv='refresh' content='1;url=/member/list'>");
    out.println("<title>직원</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>직원 변경</h1>");

    try {
      if (memberDao.update(member) == 0) {
        out.println("<p>회원이 없습니다.</p>");
      } else {
        sqlSessionFactory.openSession(false).commit();
        out.println("<p>변경했습니다!</p>");
      }

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      out.println("<p>변경 실패입니다!</p>");
      e.printStackTrace();
    }

    out.println("</body>");
    out.println("</html>");
  }

}

 

 

static/auth/form.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비트 캠프</title>
</head>
<body>
<h1>로그인</h1>
<form action='/auth/login'>
<table border='1'>
<tr>
  <th>전화번호</th> <td><input type='tel' name='phone'></td>
</tr>
<tr>
  <th>암호</th> <td><input type='password' name='password'></td>
</tr>
</table>
<button>로그인</button>
</form>
</body>
</html>

 

static/index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비트 캠프</title>
</head>
<body>
<h1>Mart Management</h1>
<ul>
  <li><a href="/member/list">회원</a></li>
  <li><a href="/board/list?category=1">게시글</a></li>
  <li><a href="/board/list?category=2">공지사항</a></li>
  <li><a href="/auth/form.html">로그인</a></li>
</ul>
</body>
</html>

 

static/member/form.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비트 캠프</title>
</head>
<body>
<h1>직원</h1>
<form action='/member/add'>
<table border='1'>
<tr>
  <th>이름</th> <td style="width:200px;"><input type='text' name='name'></td>
</tr>
<tr>
  <th>전화번호</th> <td><input type='tel' name='phone'></td>
</tr>
<tr>
  <th>암호</th> <td><input type='password' name='password'></td>
</tr>
<tr>
  <th>직책</th>
    <td>
      <select name="position">
        <option value="0">관리자</option>
        <option value="1">일반직원</option>
      </select>
    </td>
</tr>
</table>
<button>등록</button>
</form>
</body>
</html>

 

ItemAddServlet.java

package bitcamp.report.handler;

import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.ItemDao;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/item/delete")
public class ItemDeleteListener implements Servlet {

  ItemDao itemDao;
  SqlSessionFactory sqlSessionFactory;

  public ItemDeleteListener(ItemDao itemDao, SqlSessionFactory sqlSessionFactory) {
    this.itemDao = itemDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    try {
      if (itemDao.delete(Integer.parseInt(request.getParameter("no"))) == 0) {
        throw new Exception("해당 번호의 물품이 없습니다!");
      } else {
        response.sendRedirect("/item/list");
      }
      sqlSessionFactory.openSession(false).commit();

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      throw new RuntimeException(e);
    }
  }

}

 

ItemDeleteServlet.java

package bitcamp.report.handler;

import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.ItemDao;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/item/delete")
public class ItemDeleteServlet implements Servlet {

  ItemDao itemDao;
  SqlSessionFactory sqlSessionFactory;

  public ItemDeleteServlet(ItemDao itemDao, SqlSessionFactory sqlSessionFactory) {
    this.itemDao = itemDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    try {
      if (itemDao.delete(Integer.parseInt(request.getParameter("no"))) == 0) {
        throw new Exception("해당 번호의 물품이 없습니다!");
      } else {
        response.sendRedirect("/item/list");
      }
      sqlSessionFactory.openSession(false).commit();

    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      throw new RuntimeException(e);
    }
  }

}

 

ItemDetailServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import bitcamp.report.dao.ItemDao;
import bitcamp.report.vo.Item;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/item/detail")
public class ItemDetailServlet implements Servlet {

  ItemDao itemDao;

  public ItemDetailServlet(ItemDao itemDao) {
    this.itemDao = itemDao;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Item item = itemDao.findBy(Integer.parseInt(request.getParameter("no")));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.println("<title>물품</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>물품</h1>");

    if (item == null) {
      out.println("<p>해당 번호의 물품이 없습니다!</p>");
    } else {
      out.println("<form action='/item/update'>");
      out.println("<table border='1'>");
      out.printf("<tr><th style='width:120px;'>번호</th>"
          + " <td style='width:300px;'><input type='text' name='no' value='%d' readonly></td></tr>\n",
          item.getNo());
      out.printf("<tr><th>물품 이름</th>"
          + " <td><input type='text' name='name' value='%s'></td></tr>\n", item.getName());
      out.printf("<tr><th>물품 가격</th>"
          + " <td><input type='text' name='price' value='%d'></td></tr>\n", item.getPrice());
      out.printf("<tr><th>물품 종류</th>"
          + " <td><select name='type'>\n"
          + " <option value='식료품' %s>식료품</option>\n"
          + " <option value='생활용품' %s>생활용품</option>\n"
          + " <option value='의류' %s>의류</option>\n"
          + " <option value='가전제품' %s>가전제품</option>\n"
          + " <option value='리빙' %s>리빙</option></select></td></tr>\n",
          (item.getType() == "식료품" ? "selected" : ""),
          (item.getType() == "생활용품" ? "selected" : ""),
          (item.getType() == "의류" ? "selected" : ""),
          (item.getType() == "가전제품" ? "selected" : ""),
          (item.getType() == "리빙" ? "selected" : ""));
      out.println("</table>");

      out.println("<div>");
      out.println("<button>변경</button>");
      out.println("<button type='reset'>초기화</button>");
      out.printf("<a href='/item/delete?no=%d'>삭제</a>\n", item.getNo());
      out.println("<a href='/item/list'>목록</a>\n");
      out.println("</div>");
      out.println("</form>");
    }
    
    out.println("</body>");
    out.println("</html>");
  }
  
}

 

ItemListServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import java.util.List;
import bitcamp.report.dao.ItemDao;
import bitcamp.report.vo.Item;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/item/list")
public class ItemListServlet implements Servlet {

  ItemDao itemDao;

  public ItemListServlet(ItemDao itemDao) {
    this.itemDao = itemDao;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.println("<title>물품</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>물품 목록</h1>");
    out.println("<div style='margin:5px;'>");
    out.println("<a href='/item/form.html'>새 물품</a>");
    out.println("</div>");
    out.println("<table border='1'>");
    out.println("  <tr><th>번호</th> <th>물품 이름</th> <th>물품 가격</th> <th>물품 종류</th></tr>");
    out.println("</thead>");

    List<Item> list = itemDao.findAll();
    for (Item item : list) {
      out.printf("<tr>" 
          + " <td>%d</td>" 
          + " <td><a href='/item/detail?no=%d'>%s</a></td>"
          + " <td>%d</td>"
          + " <td>%s</td></tr>\n", 
          item.getNo(), item.getNo(), item.getName(), item.getPrice(), item.getType());
    }

    out.println("</tbody>");
    out.println("</table>");
    out.println("<a href='/'>메인</a>");
    out.println("</body>");
    out.println("</html>");

  }

}

 

ItemUpdateServlet.java

package bitcamp.report.handler;

import java.io.PrintWriter;
import org.apache.ibatis.session.SqlSessionFactory;
import bitcamp.report.dao.ItemDao;
import bitcamp.report.vo.Item;
import bitcamp.util.Component;
import bitcamp.util.HttpServletRequest;
import bitcamp.util.HttpServletResponse;
import bitcamp.util.Servlet;

@Component("/item/update")
public class ItemUpdateServlet implements Servlet {

  ItemDao itemDao;
  SqlSessionFactory sqlSessionFactory;

  public ItemUpdateServlet(ItemDao itemDao, SqlSessionFactory sqlSessionFactory) {
    this.itemDao = itemDao;
    this.sqlSessionFactory = sqlSessionFactory;
  }

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Item item = new Item();
    item.setNo(Integer.parseInt(request.getParameter("no")));
    item.setName(request.getParameter("name"));
    item.setPrice(Integer.parseInt(request.getParameter("price")));
    item.setType(request.getParameter("type"));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("<meta charset='UTF-8'>");
    out.printf("<meta http-equiv='refresh' content='1;url=/item/list'>");
    out.println("<title>물품</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>물품 변경</h1>");

    try {
      if (itemDao.update(item) == 0) {
        out.println("<p>물품이 없습니다.</p>");
      } else {
        sqlSessionFactory.openSession(false).commit();
        out.println("<p>변경했습니다!</p>");
      }
    } catch (Exception e) {
      sqlSessionFactory.openSession(false).rollback();
      out.println("<p>변경 실패입니다!</p>");
      e.printStackTrace();
    }

    out.println("</body>");
    out.println("</html>");
  }

}

 

static/item/form.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비트 캠프</title>
</head>
<body>
<h1>물품</h1>
<form action='/item/add'>
<table border='1'>
<tr>
  <th>물품 이름</th> <td style="width:200px;"><input type='text' name='name'></td>
</tr>
<tr>
  <th>물품 가격</th> <td><input type='text' name='price'></td>
</tr>
<tr>
  <th>물품 종류</th>
    <td>
      <select name="type">
        <option value="1">식료품</option>
        <option value="2">생활용품</option>
        <option value="3">의류</option>
        <option value="4">가전제품</option>
        <option value="5">리빙</option>
      </select>
    </td>
</tr>
</table>
<button>등록</button>
</form>
</body>
</html>

 

static/index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비트 캠프</title>
</head>
<body>
<h1>Mart Management</h1>
<ul>
  <li><a href="/member/list">회원</a></li>
  <li><a href="/item/list">물품</a></li>
  <li><a href="/board/list?category=1">게시글</a></li>
  <li><a href="/board/list?category=2">공지사항</a></li>
  <li><a href="/auth/form.html">로그인</a></li>
</ul>
</body>
</html>

 

DispatcherServlet.java

ㄴ 코드 수정

 

static/auth/form.html