## 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/
=>
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
ㄴ 해당 코드 복사하기
=>
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
'네이버클라우드 > JAVA 웹 프로그래밍' 카테고리의 다른 글
JAVA 53일차 (2023-08-04) 자바 프로그래밍_Tomcat (0) | 2023.08.05 |
---|---|
JAVA 52일차 (2023-08-03) 자바 프로그래밍_55. 웹 애플리케이션 서버 구조로 전환하기 - 웹 기술 도입_개인프로젝트 - 마트 관리 시스템 (0) | 2023.08.03 |
JAVA 50일차 (2023-08-01) 자바 프로그래밍_54. IoC 컨테이너 적용하기_개인프로젝트 - 마트 관리 시스템 (0) | 2023.08.01 |
JAVA 49일차 (2023-07-31) 자바 프로그래밍_주석 (0) | 2023.08.01 |
JAVA 49일차 (2023-07-31) 자바 프로그래밍_54. IoC 컨테이너 적용하기_개인프로젝트 - 마트 관리 시스템 (0) | 2023.07.31 |