Day65 실습프로젝트(Servlet)
Servlet
ListServlet 만들기
init(ServletConfig config)
- 생성자 역할을 대신하는 메서드로 클래스 구동에 필요한 서버정보를 호출 한다.
- ServletConfig에는 리스너에서 담았던 Context객체가 담겨있다.
service(ServletRequest req, ServletResponse res)
- 서블릿컨테이너에서 해당 클래스를 호출하면 실행되는 메서드이다.
- 웹브라우저가 받을 정보는 res에서, 웹브라우저에서 가져올 정보는 req로 받는다.
res.setContentType(MIME;CharaterSet)
으로 출력 인코딩을 설정한다.PrintWriter out = res.getWriter()
으로 출력 스트림을 생성한다.- 동적 HTML을 작성해서 Out 스트림에 보낸다.
HTML문서에서 링크 만들기
- 태그에 링크를 연결하기 위해서는
<a href="url">내용</a>
를 작성한다. 내용을 클릭하면 설정한 url로 이동한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
@WebServlet("/user/list") public class UserListServlet implements Servlet { private ServletConfig config; private UserDao userDao; @Override public void init(ServletConfig config) throws ServletException { // 서블릿 객체를 생성한 후 바로 호출됨(물론, 생성자가 먼저 호출된다.) // 서블릿이 작업할 사용할 의존 객체를 준비하는 일을 이 메서드에서 수행한다. this.config = config; ServletContext ctx = config.getServletContext(); userDao = (UserDao) ctx.getAttribute("userDao"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // 웹브라우저에서 이 서블릿을 실행해달라고 요청이 들어오면 이 메서드가 호출된다. // 누가 호출하는가? 서블릿 컨테이너가 호출한다. // 출력할 콘텐트의 타입을 먼저 지정한 후 출력 스트림을 얻는다. res.setContentType("text/html;charset=UTF-8"); // 출력 콘텐트를 어떤 문자집합으로 인코딩 할 지 지정하지 않고 출력 스트림을 꺼내면 // 출력 문자열(UTF-16BE)은 ISO-8859-1 문자집합에 맞춰 인코딩된다. // 만약 UTF-16BE 에 있는 문자가 ISO-8859-1에 정의되어 있지 않다면, // '?' 문자로 변환된다. PrintWriter out = res.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='UTF-8'>"); out.println(" <title>Title</title>"); out.println(" <link href='/css/common.css' rel='stylesheet'>"); out.println("</head>"); out.println("<body>"); try { out.println("<header>"); out.println(" <a href='/'><img src='/images/home.png'></a>"); out.println(" 프로젝트 관리 시스템"); out.println("</header>"); out.println("<h1>회원 목록</h1>"); out.println("<p><a href='/user/form.html'>새 회원</a></p>"); out.println("<table>"); out.println(" <thead>"); out.println(" <tr><th>번호</th><th>이름</th><th>이메일</th></tr>"); out.println(" </thead>"); out.println(" <tbody>"); for (User user : userDao.list()) { out.printf(" <tr><td>%d</td><td><a href='/user/view?no=%1$d'>%s</a></td><td>%s</td></tr>\n", user.getNo(), user.getName(), user.getEmail()); } out.println(" </tbody>"); out.println("</table>"); } catch (Exception e) { out.println("<p>목록 조회 중 오류 발생!</p>"); } out.println("</body>"); out.println("</html>"); } @Override public void destroy() { // 서블릿 컨테이너가 종료되기 전에 해제할 자원이 있다면 이 메서드에서 수행한다. } @Override public String getServletInfo() { // 서블릿 컨테이너 관리 화면에서 서블릿을 정보를 출력할 때 이 메서드가 호출된다. // 서블릿에 대한 간단한 정보를 문자열로 리턴하면 된다. return "회원 목록 조회"; } @Override public ServletConfig getServletConfig() { // 서블릿의 정보를 조회할 때 사용할 ServletConfig 객체를 리턴해 준다. // 이 메서드가 리턴할 ServletConfig 객체는 // init() 메서드가 호출될 때 파라미터로 넘어온 객체다. // 따라서 init() 메서드가 호출될 때 ServletConfig 객체를 보관해 둬야 한다. return this.config; } }
ViewServlet 만들기
GenericServlet
을 상속받아서 클래스를 작성한다.- init() : init(ServletConfig config)을 호출하면 다시 init()을 호출한다.
- GenericServlet에서는 config외 호출 할 정보를 이 메서드에 작성하면 된다.
- GenericServlet에서는 ServletContext객체도 서블렛 컨테이너로 부터 받아오기 때문에 getServletContext을 통해 ctx를 만들수 있다.
- service(ServletRequest req, ServletResponse res)
- res로 출력 인코딩과 출력 스트림을 생성한다.
- req를 통해 조회할 no를 받아온다.
- 웹브라우저에서
/user/view?no=xx
를 컨테이너에 request하면 컨테이너는 /user/view url을 가진 클래스를 호출 하고 no를 매개변수로 넘긴다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
@WebServlet("/user/view") public class UserViewServlet extends GenericServlet { private UserDao userDao; @Override public void init() throws ServletException { // 서블릿 컨테이너 ---> init(ServletConfig) ---> init() 호출한다. userDao = (UserDao) this.getServletContext().getAttribute("userDao"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/html;charset=UTF-8"); PrintWriter out = res.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='UTF-8'>"); out.println(" <title>Title</title>"); out.println(" <link href='/css/common.css' rel='stylesheet'>"); out.println("</head>"); out.println("<body>"); try { out.println("<header>"); out.println(" <a href='/'><img src='/images/home.png'></a>"); out.println(" 프로젝트 관리 시스템"); out.println("</header>"); out.println("<h1>회원 조회</h1>"); int userNo = Integer.parseInt(req.getParameter("no")); User user = userDao.findBy(userNo); if (user == null) { out.println("<p>없는 회원입니다.</p>"); out.println("</body>"); out.println("</html>"); return; } out.printf("<p>이름: %s</p>\n", user.getName()); out.printf("<p>이메일: %s</p>\n", user.getEmail()); out.printf("<p>연락처: %s</p>\n", user.getTel()); } catch (Exception e) { out.println("<p>조회 중 오류 발생!</p>"); } out.println("</body>"); out.println("</html>"); } }
AddServlet 만들기
form.html만들기
- 정적HTMl을 만들어서 브라우저에 보낼수도 있다.
- 이는 webserver에서 관리를 하는 페이지이기 때문에 webapp에서 작성을 한다.
<form atction="url" method="GET|POST">
: 폼이 완료되면 액션 메서드가 실행된다.- method=”GET”: 데이터가 URL의 쿼리 스트링(예: ?name=value)으로 전송된다.
- method=”POST”: 데이터가 HTTP 요청의 본문에 포함되어 전송된다.
<link href="url" rel='stylesheet">
: 해당 url경로에 있는 stylesheet을 찾아서 연결한다.<input name="name" type="type">
: 입력창을 만드는 태그이다.- name : 태그가 req로 반환될 때 파라미터 명이다.
- type : 입력받을 type이며, type에 따라 입력창이 다르게 출력된다. (특히 모바일)
<input type="submit" value="등록">
: 입력창을 만드는 태그이고, 클릭하면 폼의 액션이 호출된다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="/css/common.css" rel="stylesheet"> </head> <body> <header> <a href="/"><img src="/images/home.png"></a> 프로젝트 관리 시스템 </header> <h1>회원 등록</h1> <form action="/user/add"> 이름: <input name="name" type="text"><br> 이메일: <input name="email" type="email"><br> 암호: <input name="password" type="password"><br> 연락처: <input name="tel" type="tel"><br> <input type="submit" value="등록"> </form> </body> </html>
AddServlet만들기
- form action이 실행되면 action에 설정된 url의 servlet이 실행된다.
- AddServlet을 동적으로 HTML을 생성하여 req의 파라미터를 받아온다.
query string에서 값을 받아오는 방법은 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/html;charset=UTF-8"); PrintWriter out = res.getWriter(); req.getRequestDispatcher("/header").include(req, res); try { out.println("<h1>회원 등록 결과</h1>"); User user = new User(); user.setName(req.getParameter("name")); user.setEmail(req.getParameter("email")); user.setPassword(req.getParameter("password")); user.setTel(req.getParameter("tel")); userDao.insert(user); sqlSessionFactory.openSession(false).commit(); out.println("<p>등록 성공입니다.</p>"); } catch (Exception e) { sqlSessionFactory.openSession(false).rollback(); out.println("<p>등록 중 오류 발생!</p>"); } out.println("</body>"); out.println("</html>"); ((HttpServletResponse) res).setHeader("Refresh", "1;url=/user/list"); }
URL
- URI (Uniform Resource Identifier) : URI는 인터넷에 있는 자원의 식별자이다. 웹 상의 자원(문서, 이미지, 파일 등)을 식별하고 위치를 나타내는 데 사용된다. URI는 일반적으로 URL과 URN을 포함하는 상위 개념이다.
- URN (Uniform Resource Name) : URN은 자원의 이름을 식별하는 URI의 일종이다. URN은 자원의 위치에 의존하지 않고, 그 자원의 고유한 이름을 나타낸다.
URL (Uniform Resource Locator) : URL은 자원의 위치를 식별하는 URI의 일종이다. URL은 자원의 접근 방법(프로토콜)과 그 자원이 위치한 장소를 나타낸다.
URL인코딩
project member 받아오기
- project member를 받아오기 위해서는 form이 동적으로 생성되어야한다.
<input name='member' value='%d' type='checkbox'>
를 통해 AddServlet에 user_id를 파라미터로 전달한다.1 2 3 4 5 6 7
out.println(" <ul>"); List<User> users = userDao.list(); for (User user : users) { out.printf(" <li><input name='member' value='%d' type='checkbox'> %s</li>\n", user.getNo(), user.getName()); } out.println(" </ul>");
AddServlet에서는 req.getParameterValuse("memeber")
을 통해서 user_id의 배열 받아온다.1 2 3 4 5 6 7 8
String[] memberNos = req.getParameterValues("member"); if (memberNos != null) { ArrayList<User> members = new ArrayList<>(); for (String memberNo : memberNos) { members.add(new User(Integer.parseInt(memberNo))); } project.setMembers(members); }
loginServlet 만들기
- BoardAddServlet에 작성자를 저장하기 위해서는 LoginServlet이 필요하다.
로그인을 하는 Form을 만들어 LoginServlet에게 값을 전달한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="/css/common.css" rel="stylesheet"> </head> <body> <header> <a href="/"><img src="/images/home.png"></a> 프로젝트 관리 시스템 </header> <h1>로그인</h1> <form action="/auth/login"> 이메일:<input name="email" type="email"><br> 암호:<input name="password" type="password"><br> <input type="submit" value="로그인"> </form> </body> </html>
LoginServlet에서 로그인정보를 Session에 저장한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
String email = req.getParameter("email"); String password = req.getParameter("password"); User user = userDao.findByEmailAndPassword(email, password); if (user == null) { out.println("<p>이메일 또는 암호가 맞지 않습니다.</p>"); out.println("</body>"); out.println("</html>"); ((HttpServletResponse) res).setHeader("Refresh", "1;url=/auth/form"); return; } // HTTP 프로토콜 관련 기능을 사용하려면 // 파라미터로 받은 ServletRequest 객체를 원래 타입으로 형변환 해야 한다. // 즉 req 레퍼런스는 실제 HttpServletRequest 객체를 가리키고 있다. HttpServletRequest httpReq = (HttpServletRequest) req; // 클라이언트 전용 보관소를 알아낸다. HttpSession session = httpReq.getSession(); // 클라이언트 전용 보관소에 로그인 사용자 정보를 보관한다. session.setAttribute("loginUser", user); out.println("<p>로그인 성공입니다!</p>");
BoardAddServlet에서는 Session의 로그인 유저를 꺼내온다.
1 2
User loginUser = (User) ((HttpServletRequest) req).getSession().getAttribute("loginUser"); board.setWriter(loginUser);
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.