일반 게시판에서 사진을 업로드 할 때 방법을 설명


먼저 JSP 파일


------------------------------------------------------------------------------------------------------------------------------------

출처: https://qdgbjsdnb.tistory.com/ [하위^^]
------------------------------------------------------------------------------------------------------------------------------------

출처: https://qdgbjsdnb.tistory.com/ [하위^^]

------------------------------------------------------------------------------------------------------------------------------------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
    .outer {
        width:1000px;
        height:650px;
        background:black;
        color:white;
        margin-left:auto;
        margin-right:auto;
        margin-top:50px;
    }
    table {
        border:1px solid white;
    }
    .insertArea {
        width:500px;
        height:450px;
        margin-left:auto;
        margin-right:auto;
    }
    .btnArea {
        width:150px;
        margin-left:auto;
        margin-right:auto;
    }
    #titleImgArea {
        width:350px;
        height:200px;
        border:2px dashed darkgray;
        text-align:center;
        display:table-cell;
        vertical-align:middle;
    }
    #contentImgArea1, #contentImgArea2, #contentImgArea3 {
        width:150px;
        height:100px;
        border:2px dashed darkgray;
        text-align:center;
        display:table-cell;
        vertical-align:middle;
    }
</style>
</head>
<body>
    <%@ include file="../common/menubar.jsp" %>
    <% if(loginUser != null) { %>
    <div class="outer">
        <br>
        <h2 align="center">사진 게시판 작성</h2>
        <form action="<%=request.getContextPath() %>/insert.tn" method="post" encType="multipart/form-data"> <!-- 파일 전송 시 encType을 지정해야 한다. -->
            <div class="insertArea">
                <table align="center">
                    <tr>
                        <td>제목</td>
                        <td colspan="3"><input type="text" size="45" name="title"></td>
                    </tr>
                    <tr>
                        <td>대표 이미지</td>
                        <td colspan="3">
                            <div id="titleImgArea">
                                <img id="titleImg" width="350" height="200">
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td>내용사진</td>
                        <td>
                            <div id="contentImgArea1">
                                <img id="contentImg1" width="120" height="100">
                            </div>
                        </td>
                        <td>
                            <div id="contentImgArea2">
                                <img id="contentImg2" width="120" height="100">
                            </div>
                        </td>
                        <td>
                            <div id="contentImgArea3">
                                <img id="contentImg3" width="120" height="100">
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td width="100px">사진 메모</td>
                        <td colspan="3">
                            <textarea name="content" rows="5" cols="50" style="resize:none;"></textarea>
                        </td>
                    </tr>
                </table>
                <div id="fileArea">
                    <input type="file" id="thumbnailImg1" name="thumbnailImg1" onchange="loadImg(this, 1)">
                    <input type="file" id="thumbnailImg2" name="thumbnailImg2" onchange="loadImg(this, 2)">
                    <input type="file" id="thumbnailImg3" name="thumbnailImg3" onchange="loadImg(this, 3)">
                    <input type="file" id="thumbnailImg4" name="thumbnailImg4" onchange="loadImg(this, 4)">
                </div>
            </div>
            <div class="btnArea">
                <button>취소하기</button>
                <button type="submit">작성완료</button>
            </div>
        </form>
    </div>
   
    <script type="text/javascript">
        $(function() {
            $("#fileArea").hide(); // 버튼 숨기기
           
            $("#titleImgArea").click(function() {
                $("#thumbnailImg1").click();
            });
            $("#contentImgArea1").click(function() {
                $("#thumbnailImg2").click();
            });
            $("#contentImgArea2").click(function() {
                $("#thumbnailImg3").click();
            });
            $("#contentImgArea3").click(function() {
                $("#thumbnailImg4").click();
            });
        });
        /* function loadImg(value) { // 박스에 파일 업로드 하는 방법
            if (value.files && value.files[0]) {
                var reader = new FileReader();
               
                reader.onload = function(e) {
                    $("#titleImg").attr("src", e.target.result);
                };
               
                reader.readAsDataURL(value.files[0]);
            }
        } */
        function loadImg(value, num) { // value는 업로드한 파일
            if (value.files && value.files[0]) { // 파일을 업로드하면 배열 형태로 들어온다.
                var reader = new FileReader();
               
                reader.onload = function(e) { // reader가 실행되면 적용될 속성
                    switch (num) {
                    case 1 :
                        $("#titleImg").attr("src", e.target.result); // target.result는 업로드한 파일의 임시경로
                        break;
                    case 2 :
                        $("#contentImg1").attr("src", e.target.result);
                        break;
                    case 3 :
                        $("#contentImg2").attr("src", e.target.result);
                        break;
                    case 4 :
                        $("#contentImg3").attr("src", e.target.result);
                        break;
                    }
                };
               
                reader.readAsDataURL(value.files[0]); // reader호출, 파일의 url을 읽어 들임
            }
        }
    </script>
   
    <% } else { %>
    <%    
        request.setAttribute("msg", "잘못된 경로로 접근하셨습니다.");
        request.getRequestDispatcher("../common/errorPage.jsp").forward(request, response);
    %>
    <% } %>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------


다른 폼은 여태껏 봐왔던 html 코드들인데


스크립트 부분을 설명하면


        $(function() {
            $("#fileArea").hide(); // 버튼 숨기기
           
            $("#titleImgArea").click(function() {
                $("#thumbnailImg1").click();
            });
            $("#contentImgArea1").click(function() {
                $("#thumbnailImg2").click();
            });
            $("#contentImgArea2").click(function() {
                $("#thumbnailImg3").click();
            });
            $("#contentImgArea3").click(function() {
                $("#thumbnailImg4").click();
            });
        });


이 부분은 이미지 박스를 눌렀을 때 버튼 기능을 실행하게 하고


버튼은 숨겨 안보이게 표시하는 스크립트




        /* function loadImg(value) { // 박스에 파일 업로드 하는 방법
            if (value.files && value.files[0]) {
                var reader = new FileReader();
               
                reader.onload = function(e) {
                    $("#titleImg").attr("src", e.target.result);
                };
               
                reader.readAsDataURL(value.files[0]);
            }
        } */


type="file"에 함수를 만들어 value를 인자로 받았을 때


value는 받은 파일을 의미하게 된다.


value는 여러개가 들어올 수 있으므로 배열 형태로 들어오게 되고


files 라는 메소드는 파일이 있는지 없는지를 반환한다.




FileReader 객체를 생성하고 불러올 때 작동할 함수(onload)는 클릭한 박스의 속성의 이미지를 등록하는 것이다.


function(e) 의 e는 등록한 파일을 의미하고 e.target.result는 서버에 업로드 하기 전에 임시로 지정된 파일의 경로가 된다.


reader.readAsDataURL(value.files[0])은 파일의 경로를 한번 불러오는 것이고 호출했기 때문에 onload가 작동된다.






        function loadImg(value, num) { // value는 업로드한 파일
            if (value.files && value.files[0]) { // 파일을 업로드하면 배열 형태로 들어온다.
                var reader = new FileReader();
               
                reader.onload = function(e) { // reader가 실행되면 적용될 속성
                    switch (num) {
                    case 1 :
                        $("#titleImg").attr("src", e.target.result); // target.result는 업로드한 파일의 임시경로
                        break;
                    case 2 :
                        $("#contentImg1").attr("src", e.target.result);
                        break;
                    case 3 :
                        $("#contentImg2").attr("src", e.target.result);
                        break;
                    case 4 :
                        $("#contentImg3").attr("src", e.target.result);
                        break;
                    }
                };
               
                reader.readAsDataURL(value.files[0]); // reader호출, 파일의 url을 읽어 들임
            }
        }



2번째 스크립트의 확장으로 이미지 선택 박스의 종류 별 기능을 활성화 한다.








submit으로 설정한 버튼을 통해서


<form action="<%=request.getContextPath() %>/insert.tn" method="post" encType="multipart/form-data"> 부분의


<%=request.getContextPath() %>/insert.tn 주소로 맵핑된 부분으로 이동된다.


이동된 부분은 Servlet 파일로 서버에 업로드 된 파일을 처리한다.


단, 파일을 보낼 때는 form 속성에 무조건 encType="multipart/form-data" 를 명시해야 한다.








다음으로는 Servlet 파일

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.jsp.board.controller;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;

import com.kh.jsp.board.model.service.BoardService;
import com.kh.jsp.board.model.vo.Attachment;
import com.kh.jsp.board.model.vo.Board;
import com.kh.jsp.common.MyFileRenamePolicy;
import com.kh.jsp.member.model.vo.Member;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

@WebServlet("/insert.tn")
public class InsertThumbnailServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public InsertThumbnailServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String title = request.getParameter("title");
        System.out.println(title);
        // encType="multipart/form-data"로 데이터를 넘기면 null이 출력된다.
        // 폼전송을 multipart/form-date로 전송하는 경우에는
        // 기존처럼 request.getParameter로 값을 받을 수 없다.
       
        // cos.jar가 파일도 받고 다른 값들도 받아주는 역할을 한다.
        // com.oreilly.servlet의 약자이다.
        // http://servlets.com/cos/ 맨 아래에서 다운로드해서 lib에 추가한다.
       
        if(ServletFileUpload.isMultipartContent(request)) {
            // 전송 파일 용량 제한 : 10MB로 제한되어 있다. 그 이상은 유료
            int maxSize = 1024 * 1024; // (1mb)로 설정
           
            String root = request.getSession().getServletContext().getRealPath("/");
            System.out.println(root); // 톰캣 설정 첫번째 항목 체크를 안하면 경로가 톰캣으로 잡혀버린다.
            // thumbnale_uploadFiles 라는 폴더가 해당 경로 아래에 생기게 되므로 다음과 같이 파일 경로를 설정하자
           
            String filePath = root + "thumbnale_uploadFiles/";
           
            // MultipartRequest multiRequest = new MultipartRequest(request, filePath, maxSize, "UTF-8", new DefaultFileRenamePolicy());            // 사용자가 올린 파일명을 그대로 저장하지 않는 것이 일반적이다.
            // 1. 같은 파일명이 있는 경우 이전 파일을 덮어 쓸 수 있다.
            // 2. 한글로된 파일명, 특수기호, 띄어쓰기는 서버에 따라 문제가 생길 여지가 있다.
            // DefaultFileRenamePolicy는 cos.jar에서 제공하는 클래스
            // 같은 파일명이 존재하는지를 체크하고 있을 경우에는 뒤에 숫자를 붙여준다.
            // ex) aaa.zip, aaa1.zip, aaa2.zip
            MultipartRequest multiRequest = new MultipartRequest(request, filePath, maxSize, "UTF-8", new MyFileRenamePolicy());
           
            // 다중 파일을 묶어서 업로드 하기 위해 컬렉션 사용
            // 저장한 파일의 이름을 저장할 arrayList 생성
            ArrayList<String> saveFiles = new ArrayList<String>();
           
            // 원본 파일의 이름을 저장 할 ArrayList 생성
            ArrayList<String> originFiles = new ArrayList<String>();
           
            // 각 파일의 정보를 구해온 뒤 DB에 저장할 목적의 데이터를 꺼내온다.
            Enumeration<String> files = multiRequest.getFileNames();
           
            while (files.hasMoreElements()) {
                String name = files.nextElement();
               
                System.out.println(name);
               
                saveFiles.add(multiRequest.getFilesystemName(name));
                originFiles.add(multiRequest.getOriginalFileName(name));
               
                System.out.println("FileSystem name : " + multiRequest.getFilesystemName(name));
                System.out.println("originFile name : " + multiRequest.getOriginalFileName(name));
            }
           
            String multiTitle = multiRequest.getParameter("title");
            String multiContent = multiRequest.getParameter("content");
            System.out.println(multiTitle);
            System.out.println(multiContent);
           
            //Board객체 생성
            Board b = new Board();
            b.setbTitle(multiTitle);
            b.setbContent(multiContent);
            b.setbWriter(String.valueOf(((Member)(request.getSession().getAttribute("loginUser"))).getUno()));
           
            // Attachment 객체 생성하여 arrayList 객체 생성
            ArrayList<Attachment> fileList = new ArrayList<Attachment>();
           
            for(int i = originFiles.size() - 1; i >= 0; i--) {
                Attachment at = new Attachment();
                at.setFilePath(filePath);
                at.setOriginName(originFiles.get(i));
                at.setChangeName(saveFiles.get(i));
               
                fileList.add(at);
               
            }
           
            int result = new BoardService().insertThumbnail(b, fileList);
           
            if (result > 0) {
                response.sendRedirect(request.getContextPath() + "/selectList.tn");
            } else {
                // 실패 시 저장된 사진 삭제
                for (int i = 0; i < saveFiles.size(); i++) {
                    // 파일 시스템에 저장된 이름으로 파일 객체 생성
                    File failedFile = new File(filePath + saveFiles.get(i));
                   
                    // true, false를 리턴함
                    failedFile.delete();
                }
               
                request.setAttribute("msg", "사진게시판 등록 실패!");
                request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
            }
           
           
        }
       
       
    }
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


        // cos.jar가 파일도 받고 다른 값들도 받아주는 역할을 한다.
        // com.oreilly.servlet의 약자이다.
        // http://servlets.com/cos/ 맨 아래에서 다운로드해서 lib에 추가한다.


부분은 사진으로 추가 설명


http://servlets.com/cos/ 링크로 이동




다운받은 압축파일을 풀어 lib폴더에 복사하면 된다.


대부분의 설명은 주석에 되어 있으므로 안 되있는 부분만 설명




Enumeration<String> files = multiRequest.getFileNames(); 경우는 파일을 리스트 형식으로 알아서 불러오는 객체이다.







서블릿 부분에서 데이터를 정리해서 DB 쪽으로 연결하는 코드는 아래 한 줄 부분이다.

int result = new BoardService().insertThumbnail(b, fileList);




다음은 Service 부분

------------------------------------------------------------------------------------------------------------------------------------

public int insertThumbnail(Board b, ArrayList<Attachment> fileList) {
        Connection con = getConnection();
       
        int result = 0;
       
        int result1 = new BoardDao().insertThumbnailContent(con, b);
       
        if (result1 > 0) {
            int bid = new BoardDao().selectCurrval(con);
           
            for(int i = 0; i < fileList.size(); i++) {
                fileList.get(i).setBid(bid);
            }
        }
       
        int result2 = new BoardDao().insertAttachment(con, fileList);
       
        if (result1 > 0 && result2 > 0) {
            commit(con);
            result = 1;
        } else {
            rollback(con);
        }
       
        close(con);
       
       
        return result;
    }

------------------------------------------------------------------------------------------------------------------------------------

이 부분에서는 DB에 3번의 접근이 일어나게 된다.


첫번째는 게시글 테이블에 등록


두번째는 게시글 번호 불러오기(시퀀스를 통해서 등록한 게시글 번호를 불러온다.)


세번째는 첨부파일 테이블에 게시글 번호(외래키)와 함께 파일을 등록한다.







Dao 부분은 전과 같이 DB에 Prestatement나 statement를 사용하여 쿼리문을 사용한다.

여태껏 해온 부분과 비슷하므로 생략


블로그의 예제들에서는 여태까지 DataBase에 비밀번호를 입력한 그대로 저장하여 그대로 불러왔다.


하지만 법적으로?? 비밀번호는 그대로 저장하면 안되고 입력받고 값을


전달 받으면 암호화 하여서 데이터베이스에 저장해야 한다고 한다.





왜냐하면 해커에게 공격을 당한다면 보통 DB가 타겟이 되는데


DB에 암호가 그대로 쓰여져 있다면 개인정보 뿐만 아니라 암호까지 그대로 전달되어 버린다.


그러므로 비밀번호는 절대 그대로 저장하면 안된다.





JSP에서 비밀번호를 암호화 하는 구조는 다음과 같다.


기존의 MVC를 적용한 구조가 [View - 비밀번호 입력 ->> Controller(Servlet) - 비밀번호를 받음 ->> Service ->> Dao ] 순으로 전달이 되는 구조인데


암호화 (Wrapper : 포장, 싸다)를 적용하면 다음과 같은 구조가 된다.


[View - 비밀번호 입력 ->> Wrapper(Filter), 비밀번호 암호화 ->> Controller(Servlet) - 암호화된 비밀번호를 받음 ->> Service ->> Dao ]


비밀번호를 입력 받자마자 포장하여 암호화 하고 DB에 전달해서 저장하는 것이다.



같은 값을 암호화 했을때 나오는 문구들은 결과가 똑같기 때문에

변경된 값을 비교하여 같으면 로그인에 성공하는 방식이다.






이 구조의 전제로는 암호화 알고리즘이 단방향 알고리즘이여야 한다.


단방향 : 암호화만 할 수 있고 복호화(원상 복구)는 불가능하다. 암호화된 결과를 digest라고 부른다.


양방향 : 암호화 할 수 있고 복호화 또한 가능하다.







이번의 예는 sha - 512 알고리즘을 사용하는데 정부 기관에서는 sha 256 이상 버전의 알고리즘을 권장하고 있다고 한다.


256, 512는 눈치가 빠르다면 2진수 비트수를 의미한다는 것을 눈치 챘을 것이다.







예의 프로젝트 구조는 다음과 같다.





구조를 보면 매우 복잡하다.


그러므로 암호화, Filter 관련 파일만 올린다.


나머지는 여태까지 했던 기능들과 별반 다를게 없다.


암호화에 사용하게될 클래스들은 filter 폴더와 wrapper 폴더가 된다.


다른 클래스에서는 따로 명시할 코드가 전혀 없고 여태까지 쓰던대로와 같기 때문에 설명은 생략









먼저 Filter 파일에 대한 이해가 필요하다.


생성방법은 다음과 같다.




프로젝트 네비게이터에서 만들 폴더에


우클릭 - New - Filter File 이나


우클릭 - New - Other을 눌러 다음과 같이 검색하면 된다.




선택 한 후









이와같이 설정하면 된다.


서블릿과 매우 비슷하다.


해당 2번째 사진에는 Filter mappings에 /CommonFilter을 더블클릭해서 변경하는 팝업창인데


Pattern에 '/'가 아닌 '/*'를 입력해야 한다.






생성된 필터의 내용 또한 서블릿과 비슷하다.


필터 클래스는 지정한 페이지 링크가 열리면 서블릿보다 먼저 request, response 데이터를 받아서 데이터를 수정하고


실제 이동할 서블릿에 수정된 데이터를 넘기는 것이다.


암호화를 이 부분에서 적용한다.





위 문단에서 설명한 지정한 페이지란 Filter 클래스 생성 시 정한 Pattern /* 가 된다.


클래스 상단에 보면 서블릿과 똑같이 어노테이션으로 @WebFilter("/*")라고 쓰여있다.


여기서 지정한 /*란 "/로 시작하는 모든 링크(*의 의미)"라고 생각하면 된다.


다음 필터 파일은 모든 페이지에서 request, response가 발생한다면 그 데이터를 UTF-8 CharSet 설정을 하고 전달하는 것이다.

이로 인해 데이터를 받을 Servlet에서 request.setCharacterEncoding("UTF-8");를 입력 할 필요가 없다.



CommonFilter.java

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.jsp.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter("/*") // '/*'이 url패턴은 슬러쉬 뒤에 어떤 링크가 와도 모든 페이지에 이 필터가 적용이 된다라는 뜻(모든 페이지는 열 때 /가 붙는다.)
public class CommonFilter implements Filter {

    public CommonFilter() {
        System.out.println("필터 생성!");
    }

    public void destroy() {
       
    }
   
    // doget과 비슷
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8"); // 여기서 UTF-8을 지정하였기 때문에 서블릿에서 UTF-8을 지정 할 필요가 없어진다.
        response.setContentType("text/html; charset=UTF-8");
       
       
        chain.doFilter(request, response); // 다음 필터로 정보를 전달함
    }
   
    //시작 시 한번 실행
    public void init(FilterConfig fConfig) throws ServletException {
       
    }

}

------------------------------------------------------------------------------------------------------------------------------------



코드를 쭉 보면 서블릿과 비슷한 메소드들이 등장한다.


이것들의 라이프 사이클 또한 서블릿과 똑같다.


doFilter 메소드는 doGet과 같은 메소드라고 생각하면 된다. 필터가 호출되면 실행되는 문구이다.







Filter는 서버가 실행되면 같이 생성되기 때문에 생성자 CommonFilter에 입력된 코드는


서버를 동작한다면 같이 실행되게 된다.









다음으로 이 Filter를 이용한 암호화 클래스 작성이다.



IncryptFilter.java

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.jsp.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import com.kh.jsp.wrapper.LoginWrapper;

@WebFilter("*.me") // 뒤에가 .me가 되는 페이지에 전달되는 정보가 필터를 적용
// 어노테이션 말고 xml에 하면 필터의 우선순위 설정 가능
public class IncryptFilter implements Filter {

    public IncryptFilter() {
        System.out.println("나도 객체 생성!!");
    }

    public void destroy() {
       
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // ServletRequest - 부모 / HttpServletRequest - 자식 관계
        HttpServletRequest hRequest = (HttpServletRequest)request;
       
        LoginWrapper lw = new LoginWrapper(hRequest);
       
       
       
        chain.doFilter(lw, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
       
    }

}

------------------------------------------------------------------------------------------------------------------------------------

이 Filter의 패턴은 '/*.me'인데 해석하자면 /로 시작하고 .me로 끝나는 페이지는 전부 이 필터를 거치게 된다.

LoginWrapper이라는 객체를 생성하여 request로 들어온 정보를 보낸다.(보통 사용자가 입력한 정보가 들어오게 될 것이다.)

이 후 LoginWrapper 클래스를 생성해서 HttpServletRequestWrapper라는 객체를 상속 받게하여 암호화 알고리즘을 적용한다.





LoginWrapper.java

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.jsp.wrapper;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class LoginWrapper extends HttpServletRequestWrapper{

    public LoginWrapper(HttpServletRequest request) {
        super(request);
    }
   
    @Override
    public String getParameter(String key) {
        String value = "";
       
        if (key != null && key.equals("userPwd")) {
            value = getSha512(super.getParameter("userPwd"));
        } else {
            value = super.getParameter(key);
        }
       
       
        return value;
    }
    private static String getSha512(String pwd) {
        String encPwd = "";
       
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            byte[] bytes = pwd.getBytes(Charset.forName("UTF-8"));
            md.update(bytes);
           
            encPwd = Base64.getEncoder().encodeToString(md.digest());
           
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
       
       
        return encPwd;
    }
   
}

------------------------------------------------------------------------------------------------------------------------------------


LoginWrapper 객체는 HttpServletRequestWrapper를 상속받았기 때문에


request.getParameter("~") 처럼 getParameter 메소드를 사용 할 수 있다.


오버라이딩으로 getParameter 메소드를 변경하여 Key값이 비밀번호 일 경우(userPwd)


getSha512 메소드를 통해서 암호화 알고리즘을 적용한 값으로 userPwd의 value 값을 바꿔버린다.







MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] bytes = [바꿀 문자열 값].getBytes(Charset.forName("UTF-8"));
md.update(bytes);
           
[반환할 String 변수방] = Base64.getEncoder().encodeToString(md.digest());


암호화 코드는 위와 같은데 그냥 복사해서 [ ]안에 값만 조정해서 쓰면 된다.





왜냐하면 위의 코드를 이해하려면


암호화 할 알고리즘이 어떤 방식으로 돌아가는지 알아야 한다.


어떤 방식으로 돌아가는지 알게 된다면 암호화 한 값을 복호화(복구)하기 쉬워지기 때문에


공개되지 않는다.


그러므로 그냥 그대로 갓다 쓰자.








이번 프로젝트는 로그인, 회원가입, 정보수정, 탈퇴, 로그아웃을 만들어 본다.


기능은 거의 전과 비슷하다.


폴더 구조는 다음과 같다.





전에 사용했던 기술들은 모두 사용한다.


사진에는 안나와 있지만 WEB-INF 아래 lib 폴더에 ojdbc6.jar 파일이 있다.


시작페이지(form)


로그인 폼이 있다.

------------------------------------------------------------------------------------------------------------------------------------

index.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
    html{
        height: 100%;
    }
    body {
        background: skyblue;
        height: 100%;
    }
    #main{
        min-height: 90%;
    }
    h1{
        color: navy;
    }
    #title{
        color: orangered;
    }
    input[type='submit'] {
        height: 50px;
        background: orangered;
        color: white;
        border-radius: 10px;
    }
</style>
</head>
<body>
    <div id="main">
        <h1 align="center">Welcome to <label id="title">둘리's World</label></h1>
       
        <div>
            <form action="<%=request.getContextPath() %>/login" method="post">
                <table align="center">
                    <tr>
                        <td><label>ID</label></td>
                        <td colspan="2"><input type="text" name="userId"></td>
                        <td rowspan="2"><input type="submit" value="LOGIN"></td>
                    </tr>
                    <tr>
                        <td><label>PWD</label></td>
                        <td colspan="2"><input type="password" name="password"></td>
                    </tr>
                    <tr>
                        <td colspan="4"><a href="views/member/memberJoinForm.jsp">회원가입하기</a></td>
                    </tr>
                    <tr>
                        <td colspan="4"><a href="#">아이디 / 비밀번호 찾기</a></td>
                    </tr>
                </table>
            </form>
        </div>
    </div>
   
   
    <%@ include file="views/common/footer.jsp" %>
   
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------


회원가입(form, servlet)


------------------------------------------------------------------------------------------------------------------------------------

memberJoinForm.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1 align="center">회원가입</h1>
    <form action="<%= request.getContextPath() %>/insertMember" method="post">
        <table align="center">
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="userId"></td>
            </tr>
            <tr>
                <td><label>비밀번호</label></td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td><label>비밀번호 확인</label></td>
                <td><input type="password" name="password2"></td>
            </tr>
            <tr>
                <td><label>이름</label></td>
                <td><input type="text" name="userName"></td>
            </tr>
            <tr>
                <td><label>나이</label></td>
                <td><input type="number" name="age"></td>
            </tr>
            <tr>
                <td>성별</td>
                <td>
                    <input type="radio" name="gender" value="M" id="male">
                    <label for="male">남</label>
                    <input type="radio" name="gender" value="F" id="female">
                    <label for="female">여</label>
                </td>
            </tr>
            <tr>
                <td><label>이메일</label></td>
                <td><input type="email" name="email"></td>
            </tr>
            <tr>
                <td><label>전화번호</label></td>
                <td><input type="tel" name="phone"></td>
            </tr>
            <tr>
                <td><label>주소</label></td>
                <td><input type="text" name="address"></td>
            </tr>
            <tr>
                <td><label>취미</label></td>
                <td>
                    <input type="checkbox" name="hobby" value="운동" id="sports">
                    <label for="sports">운동</label>
                    <input type="checkbox" name="hobby" value="낚시" id="fishing">
                    <label for="sports">낚시</label>
                    <input type="checkbox" name="hobby" value="등산" id="climbing">
                    <label for="sports">등산</label>
                    <input type="checkbox" name="hobby" value="요리" id="cooking">
                    <label for="sports">요리</label>
                </td>
            </tr>
            <tr align="center">
                <td colspan="2">
                    <input type="reset" value="리셋"> &nbsp; &nbsp;
                    <input type="submit" value="가입하기">
                </td>
            </tr>
        </table>
    </form>
</body>
</html>




InsertMemberServlet.java



package com.kh.w7.member.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.w7.member.model.service.MemberService;
import com.kh.w7.member.model.vo.Member;

@WebServlet("/insertMember")
public class InsertMemberServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
   
    public InsertMemberServlet() {
        super();
    }
   
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 인코딩
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
       
        // 2. request에서 파라미터 값 꺼내기
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
        String userName = request.getParameter("userName");
        String gender = request.getParameter("gender");
        int age = Integer.parseInt(request.getParameter("age"));
        String email = request.getParameter("email");
        String phone = request.getParameter("phone");
        String address = request.getParameter("address");
        String[] hobby = request.getParameterValues("hobby");
       
        String hobbies = "";
        for (int i = 0; i < hobby.length; i++) {
            if (i == 0) {
                hobbies += hobby[i];
            }else {
                hobbies += ", " + hobby[i];
            }
        }
       
        // 3. Member 객체 생성
        Member reqMember = new Member();
        reqMember.setUserId(userId);
        reqMember.setPassword(password);
        reqMember.setUserName(userName);
        reqMember.setGender(gender);
        reqMember.setAge(age);
        reqMember.setEmail(email);
        reqMember.setPhone(phone);
        reqMember.setAddress(address);
        reqMember.setHobby(hobbies);
       
       
        // 4. Service 로직으로 전달
        int result = new MemberService().insertMember(reqMember);
       
        if(result > 0) {
            String page = "views/common/successPage.jsp";
            request.getSession().setAttribute("msg", "회원 가입에 성공하셨습니다.");
            response.sendRedirect(page);
        }else {
            String page = "views/common/errorPage.jsp";
            request.setAttribute("msg", "회원 가입에 실패하셨습니다!");
           
            RequestDispatcher view = request.getRequestDispatcher(page);
            view.forward(request, response);
        }
       
       
       
       
    }
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


로그인(servlet)


------------------------------------------------------------------------------------------------------------------------------------

LoginServlet.java



package com.kh.w7.member.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.kh.w7.member.model.service.MemberService;
import com.kh.w7.member.model.vo.Member;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public LoginServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 전송값에 한글이 있는 경우 인코딩 처리 해야 함
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
       
        // 2. 전송값 꺼내서 변수에 기록하기
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
       
        System.out.println("ID : " + userId);
        System.out.println("PW : " + password);
       
        Member reqMember = new Member();
       
        reqMember.setUserId(userId);
        reqMember.setPassword(password);
       
        // 3. 서비스 로직 호출
        Member loginUser = new MemberService().loginCheck(reqMember);
       
       
        // 4. 받은 결과에 따라 뷰 페이지 내보내기
        String page = "";
        if (loginUser != null) { // 성공
           
            HttpSession session = request.getSession();
            session.setAttribute("loginUser", loginUser);
           
            page = "views/main/main.jsp";
           
        }else {                     // 실패
           
            request.setAttribute("msg", "로그인 실패!");
            page = "views/common/errorPage.jsp";
           
        }
       
        RequestDispatcher view = request.getRequestDispatcher(page);
        view.forward(request, response);
       
       
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


메인 페이지, 성공, 에러 페이지(form), 로그아웃(servlet)


------------------------------------------------------------------------------------------------------------------------------------

main.jsp



<%@page import="com.kh.w7.member.model.vo.Member"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- <% Member loginUser = (Member)session.getAttribute("loginUser"); %> --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%@ include file="../common/menubar.jsp" %>
    <%-- <h1><% out.println(loginUser.getUserName()); %></h1> --%>
   
</body>
</html>




menubar.jsp(실질적인 메인)



<%@page import="com.kh.w7.member.model.vo.Member"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    Member loginUser = (Member)session.getAttribute("loginUser");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
    div > button {
        float: right;
    }
   
</style>
</head>
<body>
    <h1 align="center">메인화면</h1>
    <h3 align="right"><%= loginUser.getUserName() %>님 환영합니다.</h3>
    <div>
        <button onclick="logout()">로그아웃</button>
        <% if(!loginUser.getUserId().equals("admin")){ %>
            <button onclick="location.href='/w7/views/member/memberUpdateForm.jsp'">내 정보 수정</button>
        <% }else {%>
            <button>관리자 메뉴로</button>
        <% } %>
    </div>
   
    <script type="text/javascript">
        function logout() {
            var check = window.confirm("로그아웃 하시겠습니까?");
           
            if(check == true){
                location.href="<%= request.getContextPath() %>/logout";
               
            }
        }
    </script>
</body>
</html>




errorPage.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% String msg = (String)request.getAttribute("msg"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>에러 발생!</h1>
    <h3><%= msg %></h3>
</body>
</html>






successPage.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String msg = (String)session.getAttribute("msg");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1><%= msg %></h1>
    <a href="/w7/index.jsp">메인으로 이동</a>
</body>
</html>








LogoutServlet.java



package com.kh.w7.member.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public LogoutServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getSession().invalidate();
       
        response.sendRedirect("index.jsp");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


정보수정, 탈퇴(form, servlet)


계정삭제는 서블릿을 따로 만들지 않고 UpdateForm 스크립트에 했다.

------------------------------------------------------------------------------------------------------------------------------------

memberUpdateForm.jsp



<%@page import="com.kh.w7.member.model.service.MemberService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.w7.member.model.vo.Member"%>
<% Member loginUser = (Member)session.getAttribute("loginUser"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
    <h1 align="center"><%= loginUser.getUserName() %>님의 회원 정보 수정<button onclick="deleteMember()">탈퇴하기</button></h1>
   
    <script type="text/javascript">
        function deleteMember() {
            <%
                int result = 0;
           
                result = new MemberService().deleteMember(loginUser);
           
                if(result > 0){
                    session.invalidate();
            %>
                    alert("계정이 삭제되었습니다.");
                    window.location.href = '../../index.jsp';
            <%
                }else{
            %>
                    alert("계정 삭제에 실패했습니다.");
            <%
                }
            %>
           
        }
    </script>
   
    <form action="<%= request.getContextPath() %>/updateMember" method="post">
        <table align="center">
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="userId" value="<%= loginUser.getUserId() %>" readonly></td>
            </tr>
            <tr>
                <td><label>비밀번호</label></td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td><label>비밀번호 확인</label></td>
                <td><input type="password" name="password2"></td>
            </tr>
            <tr>
                <td><label>이름</label></td>
                <td><input type="text" name="userName" value="<%= loginUser.getUserName() %>"></td>
            </tr>
            <tr>
                <td><label>나이</label></td>
                <td><input type="number" name="age" value="<%= loginUser.getAge() %>"></td>
            </tr>
            <tr>
                <td>성별</td>
                <td>
                    <% if(loginUser.getGender().equals("M")){%>
                        <input type="radio" name="gender" value="M" id="male" checked>
                        <label for="male">남</label>
                        <input type="radio" name="gender" value="F" id="female">
                        <label for="female">여</label>
                    <% }else { %>
                        <input type="radio" name="gender" value="M" id="male">
                        <label for="male">남</label>
                        <input type="radio" name="gender" value="F" id="female" checked>
                        <label for="female">여</label>
                    <% } %>
                </td>
            </tr>
            <tr>
                <td><label>이메일</label></td>
                <td><input type="email" name="email" value="<%= loginUser.getEmail() %>"></td>
            </tr>
            <tr>
                <td><label>전화번호</label></td>
                <td><input type="tel" name="phone" value="<%= loginUser.getPhone() %>"></td>
            </tr>
            <tr>
                <td><label>주소</label></td>
                <td><input type="text" name="address" value="<%= loginUser.getAddress() %>"></td>
            </tr>
            <tr>
                <td><label>취미</label></td>
                <td>
                    <input type="checkbox" name="hobby" value="운동" id="sports">
                    <label for="sports">운동</label>
                    <input type="checkbox" name="hobby" value="낚시" id="fishing">
                    <label for="sports">낚시</label>
                    <input type="checkbox" name="hobby" value="등산" id="climbing">
                    <label for="sports">등산</label>
                    <input type="checkbox" name="hobby" value="요리" id="cooking">
                    <label for="sports">요리</label>
                </td>
            </tr>
            <tr align="center">
                <td colspan="2">
                    <input type="reset" value="리셋"> &nbsp; &nbsp;
                    <input type="submit" value="변경하기">
                </td>
            </tr>
        </table>
       
        <script type="text/javascript">
            $(function() {
                var arr = '<%= loginUser.getHobby() %>'.split(", ");
               
                $("input[name=hobby]").each(function() {
                    for (var i = 0; i < arr.length; i++) {
                        if ($(this).val() === arr[i]) {
                            $(this).attr("checked", true);
                        }else{
                           
                        }
                    }
                });
            });
           
           
        </script>
       
    </form>
</body>
</html>







UpdateMemberServlet.java



package com.kh.w7.member.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.kh.w7.member.model.service.MemberService;
import com.kh.w7.member.model.vo.Member;

@WebServlet("/updateMember")
public class UpdateMemberServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public UpdateMemberServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //인코딩
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
       
        //request객체에서 parameter꺼내기
       
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
        String userName = request.getParameter("userName");
        String gender = request.getParameter("gender");
        int age = Integer.parseInt(request.getParameter("age"));
        String email = request.getParameter("email");
        String phone = request.getParameter("phone");
        String address = request.getParameter("address");
        String[] hobby = request.getParameterValues("hobby");
       
        String hobbies = "";
        for (int i = 0; i < hobby.length; i++) {
            if (i == 0) {
                hobbies += hobby[i];
            }else {
                hobbies += ", " + hobby[i];
            }
        }
       
        //reqMember 객체 생성
        Member reqMember = new Member(userId, password, userName, gender, age, email, phone, address, hobbies);
       
        //service 로직으로 전달
        int result = new MemberService().updateMember(reqMember);
       
        //처리 결과에 따른 뷰 페이지 결정
        if (result > 0) {
            HttpSession session = request.getSession();
            session.setAttribute("loginUser", reqMember);
            response.sendRedirect("views/member/memberUpdateForm.jsp");
           
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


모델(vo, service, dao)


------------------------------------------------------------------------------------------------------------------------------------

Member.java



package com.kh.w7.member.model.vo;

import java.sql.Date;

public class Member implements java.io.Serializable{
    private String userId;
    private String password;
    private String userName;
    private String gender;
    private int age;
    private String email;
    private String phone;
    private String address;
    private String hobby;
    private Date enrollDate;
   
    public Member() {}

    public Member(String userId, String password, String userName, String gender, int age, String email, String phone,
            String address, String hobby, Date enrollDate) {
        super();
        this.userId = userId;
        this.password = password;
        this.userName = userName;
        this.gender = gender;
        this.age = age;
        this.email = email;
        this.phone = phone;
        this.address = address;
        this.hobby = hobby;
        this.enrollDate = enrollDate;
    }

    public Member(String userId, String password, String userName, String gender, int age, String email, String phone,
            String address, String hobby) {
        super();
        this.userId = userId;
        this.password = password;
        this.userName = userName;
        this.gender = gender;
        this.age = age;
        this.email = email;
        this.phone = phone;
        this.address = address;
        this.hobby = hobby;
    }
   
   

    @Override
    public String toString() {
        return "Member [userId=" + userId + ", password=" + password + ", userName=" + userName + ", gender=" + gender
                + ", age=" + age + ", email=" + email + ", phone=" + phone + ", address=" + address + ", hobby=" + hobby
                + ", enrollDate=" + enrollDate + "]";
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public Date getEnrollDate() {
        return enrollDate;
    }

    public void setEnrollDate(Date enrollDate) {
        this.enrollDate = enrollDate;
    }
   
   
   
}





MemberService.java



package com.kh.w7.member.model.service;

import java.sql.Connection;

import com.kh.w7.member.model.dao.MemberDao;
import com.kh.w7.member.model.vo.Member;
import static com.kh.w7.common.JDBCTemplate.*;

public class MemberService {
   
    // 로그인용 메소드
    public Member loginCheck(Member reqMember) {
        Connection con = getConnection();
       
        System.out.println(con);
       
        Member loginUser = new MemberDao().loginCheck(con, reqMember);
       
        close(con);
       
        return loginUser;
    }

    public int insertMember(Member reqMember) {
        Connection con = getConnection();
       
        System.out.println(con);
       
        int result = new MemberDao().insertMember(con, reqMember);
       
        if (result > 0) {
            commit(con);
        }else {
            rollback(con);
        }
       
        close(con);
       
        return result;
    }

    public int updateMember(Member reqMember) {
        Connection con = getConnection();
       
        System.out.println(con);
       
        int result = new MemberDao().updateMember(con, reqMember);
       
        if (result > 0) {
            commit(con);
        }else {
            rollback(con);
        }
       
        close(con);
       
        return result;
    }
   
    public int deleteMember(Member reqMember) {
        Connection con = getConnection();
       
        System.out.println(con);
       
        int result = new MemberDao().deleteMember(con, reqMember.getUserId());
       
        if (result > 0) {
            commit(con);
        }else {
            rollback(con);
        }
       
        close(con);
       
        return result;
    }

}







MemberDao.java



package com.kh.w7.member.model.dao;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import com.kh.w7.member.model.vo.Member;
import static com.kh.w7.common.JDBCTemplate.*;

public class MemberDao {
   
    private Properties prop = new Properties();

    public MemberDao() {
        String fileName = MemberDao.class.getResource("/sql/member/member-query.properties").getPath();
               
        try {
            prop.load(new FileReader(fileName));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
    public Member loginCheck(Connection con, Member reqMember) {
        PreparedStatement pstmt = null;
        ResultSet rset = null;
        Member loginUser = null;
       
        String query = prop.getProperty("loginCheck");
       
        try {
            pstmt = con.prepareStatement(query);
            pstmt.setString(1, reqMember.getUserId());
            pstmt.setString(2, reqMember.getPassword());
           
            rset = pstmt.executeQuery();
           
            if (rset.next()) {
                loginUser = new Member();
               
                loginUser.setUserId(rset.getString("USER_ID"));
                loginUser.setPassword(rset.getString("PASSWORD"));
                loginUser.setUserName(rset.getString("USER_NAME"));
                loginUser.setGender(rset.getString("GENDER"));
                loginUser.setAge(rset.getInt("AGE"));
                loginUser.setEmail(rset.getString("EMAIL"));
                loginUser.setPhone(rset.getString("PHONE"));
                loginUser.setAddress(rset.getString("ADDRESS"));
                loginUser.setHobby(rset.getString("HOBBY"));
                loginUser.setEnrollDate(rset.getDate("ENROLL_DATE"));
               
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(rset);
            close(pstmt);
        }
       
        return loginUser;
    }

    public int insertMember(Connection con, Member reqMember) {
        PreparedStatement pstmt = null;
        int result = 0;
       
        String query = prop.getProperty("insertMember");
       
        try {
            pstmt = con.prepareStatement(query);
            pstmt.setString(1, reqMember.getUserId());
            pstmt.setString(2, reqMember.getPassword());
            pstmt.setString(3, reqMember.getUserName());
            pstmt.setString(4, reqMember.getGender());
            pstmt.setInt(5, reqMember.getAge());
            pstmt.setString(6, reqMember.getEmail());
            pstmt.setString(7, reqMember.getPhone());
            pstmt.setString(8, reqMember.getAddress());
            pstmt.setString(9, reqMember.getHobby());
           
            result = pstmt.executeUpdate();
       
       
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(pstmt);
        }
        return result;
    }

    public int updateMember(Connection con, Member reqMember) {
        PreparedStatement pstmt = null;
        int result = 0;
       
        String query = prop.getProperty("updateMember");
       
        try {
            pstmt = con.prepareStatement(query);
           
            pstmt.setString(1, reqMember.getPassword());
            pstmt.setString(2, reqMember.getUserName());
            pstmt.setString(3, reqMember.getGender());
            pstmt.setInt(4, reqMember.getAge());
            pstmt.setString(5, reqMember.getEmail());
            pstmt.setString(6, reqMember.getPhone());
            pstmt.setString(7, reqMember.getAddress());
            pstmt.setString(8, reqMember.getHobby());
            pstmt.setString(9, reqMember.getUserId());
           
           
            result = pstmt.executeUpdate();
           
           
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(pstmt);
        }
        return result;
    }

    public int deleteMember(Connection con, String userId) {
        PreparedStatement pstmt = null;
        int result = 0;
       
        String query = prop.getProperty("deleteMember");
       
        try {
            pstmt = con.prepareStatement(query);
           
            pstmt.setString(1, userId);
           
            result = pstmt.executeUpdate();
           
           
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(pstmt);
        }
        return result;
    }

}

------------------------------------------------------------------------------------------------------------------------------------


그 외 (Properties, Template, footer)


------------------------------------------------------------------------------------------------------------------------------------

JDBCTemplate.java



package com.kh.w7.common;

import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTemplate {
    public static Connection getConnection() {
        Connection conn = null;
        Properties prop = new Properties();
       
        String fileName = JDBCTemplate.class.getResource("/sql/driver.properties").getPath();
               
        System.out.println(fileName);
       
        try {
            prop.load(new FileReader(fileName));
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String user = prop.getProperty("user");
            String password = prop.getProperty("password");
           
            // 아래 클래스 구문은 신버전에서는 자동으로 추가되어서 생략해도 되지만
            // 구버전 호환을 위해 명시해두자.
            Class.forName(driver);
           
            conn = DriverManager.getConnection(url, user, password);
           
            conn.setAutoCommit(false);
           
            System.out.println(conn);
           
        } catch (Exception e) {
            e.printStackTrace();
        }
        // prop 파일을 수정할 때 classes 폴더 아래의 파일을 수정하면 서버 껏따 킬때 재생성 되기 때문에 사라진다.
        // 그리고 바로바로 수정사항이 적용이 안될 때도 있는데 메뉴바 상단의 Project - clean을 실행하면 강제 재컴파일 시켜준다.
       
        return conn;
    }
   
    public static void close(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void close(Statement stmt) {
        try {
            if(stmt != null && !stmt.isClosed()) {
                stmt.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void close(ResultSet rset) {
        try {
            if(rset != null && !rset.isClosed()) {
                rset.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void commit(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.commit();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void rollback(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.rollback();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}





driver.properties


driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=jsp
password:jsp



member-query.properties


loginCheck=SELECT * FROM member WHERE user_id=? AND password=?
insertMember=INSERT INTO member VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)
updateMember=UPDATE member SET password = ?, user_name = ?, gender = ?, age = ?, email = ?, phone = ?, address = ?, hobby = ? WHERE user_id = ?
deleteMember=DELETE FROM member WHERE user_id = ?







footer.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
    hr {
        color: gray;
    }
    p {
        text-align: center;
    }
</style>
</head>
<body>
    <hr>
    <p>Copyright, All right reserved</p>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------





특별한 기능은 없다.


전부 전에 설명했던 기능들을 짜집기하여 만든 예시이다.


로그아웃 시 Session을 invalidate 하여 삭제한다.




MVC 패턴을 적용한 이번 예의 구조를 살펴보자





폴더의 수가 많고 매우 복잡해 보이지만


파일 하나하나가 잘 분류되어 어떤 기능을 하는지 예상이 된다.


WEB-INF / lib / ojdbc6.jar 파일은 예5 게시글과 같이 끌어오면 된다.





이번 예는 DB를 조회, 입력하여 로그인, 회원가입, 로그아웃을 만들어보자.


새로 나오는 개념은 Session이라는 개념으로 로그인을 성공 했을 경우 로그인의 정보들(계정정보 등)을


담아두어 여러 페이지에서 사용 할 수 있는 방이라고 생각하면 된다.


예를 들어서 네이버에 로그인을 하고 아무 활동도 안하고 시간이 지나면 "세션이 만료되었습니다." 하고 자동 로그아웃 된다.


세션은 로그인 시점부터 관련 정보를 Session을 통해서 담고 있다가


설정해둔 일정 시간이 지나면 파기하게끔 설정해둔 것이다.


파기가 되면 로그아웃 처리가 되는것이다.






그리고 이번에는 java를 공부할 때 다루었던 Properties 파일을 이용해서


반복적으로 사용할 키워드들을 Key, Value 형태로 다룬다.


예에서는 서버의 jdbc.oracle~~~이나 oracle:jdbc:thin과 같이 쓰기 귀찮은 구문을 미리 입력해둔다.










예를 확인해보자.




먼저 로그인폼


index.jsp, loginForm.jsp

------------------------------------------------------------------------------------------------------------------------------------

index.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1 align="center">MVC model2 방식을 이용한 회원 로그인</h1>
    <h3 align="center"><a href="views/member/loginForm.jsp">회원 서비스 테스트</a></h3>
</body>
</html>





loginForm.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
    input[type='submit'] {
        height:55px;
    }
</style>
</head>
<body>
    <div align="center">
        <h2>로그인 테스트</h2>
        <form action="<%=request.getContextPath() %>/login" method="post">
            <table>
                <tr>
                    <td><label>아이디</label></td>
                    <td><input type="text" name="userId"></td>
                    <td rowspan="2"><input type="submit" value="로그인"></td>
                </tr>
                <tr>
                    <td><label>비밀번호</label></td>
                    <td><input type="password" name="password"></td>
                </tr>
                <tr>
                    <td colspan="3"><input type="button" onclick="location.href='newAccount.jsp'" value="회원가입"></td>
                </tr>
            </table>
        </form>
       
    </div>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------


로그인 기능구현 MemberService.java는 멤버 추가도 포함되어 있다.


LoginServlet.java, MemberService.java, MemberDao.java

------------------------------------------------------------------------------------------------------------------------------------

LoginServlet.java



package com.kh.w6.member.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.kh.w6.member.model.service.MemberService;
import com.kh.w6.member.model.vo.Member;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
   
    // 로그인처리를 위한 상수 선언
    public static int LOGIN_OK = 1;
    public static int WRONG_PASSWORD = 0;
    public static int ID_NOT_EXIST = -1;
   
    public LoginServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 전송값에 한글이 있는 경우
        request.setCharacterEncoding("UTF-8");
       
        // 2. 전송값 꺼내서 변수에 기록하기
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
       
        System.out.println("ID : " + userId);
        System.out.println("Pwd : " + password);
       
        //3. 비지니스 로직을 처리할 서비스 클래스의 메소드로 전달값 넘김
        Member requestMember = new Member();
        requestMember.setUserId(userId);
        requestMember.setPassword(password);
               
        Member loginUser = new MemberService().loginCheck(requestMember);
       
        //4. 받은 결과에 따라서 성공/실패 페이지 내보내기
            String view = "";
           
            if(loginUser.getStatus() == LOGIN_OK) {
                view = "views/main/main.jsp";
               
                HttpSession session = request.getSession();
               
                session.setAttribute("loginUser",  loginUser);
               
            }else {
                String msg;
               
                if(loginUser.getStatus() == WRONG_PASSWORD) {
                    msg = "패스워드를 잘못 입력하셨습니다.";
                }else {
                    msg = "존재하지 않는 아이디입니다.";
                }
               
                request.setAttribute("msg", msg);
               
                view = "views/common/errorPage.jsp";
               
            }
           
           
            RequestDispatcher reqDispatcher = request.getRequestDispatcher(view);
            reqDispatcher.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}







MemberService.java



package com.kh.w6.member.model.service;

import java.sql.Connection;
import java.sql.SQLException;

import static com.kh.w6.common.JDBCTemplate.*;

import com.kh.w6.member.controller.LoginServlet;
import com.kh.w6.member.model.dao.MemberDao;
import com.kh.w6.member.model.vo.Member;

public class MemberService {
    //로그인 처리용 메소드
    public Member loginCheck(Member requestMember) {
        Connection con = getConnection();
       
        MemberDao mDao = new MemberDao();
       
        int result = mDao.checkStatus(con, requestMember);
       
        Member loginUser = new Member();
        if(result == LoginServlet.LOGIN_OK) { // 로그인 성공
            loginUser = mDao.selectOne(con, requestMember);
            loginUser.setStatus(LoginServlet.LOGIN_OK);
        }else {
            if (result == LoginServlet.WRONG_PASSWORD) { // 비밀번호 틀림
                loginUser.setStatus(LoginServlet.WRONG_PASSWORD);
            }else { // 아이디 틀림
                loginUser.setStatus(LoginServlet.ID_NOT_EXIST);
            }
        }   
       
        return loginUser;
    }
   
    // 회원 추가용 메소드
    public int addMember(Member newMember) {
        Connection con = getConnection();
       
        MemberDao mDao = new MemberDao();
       
        int result = mDao.updateMember(con, newMember);

        try {
            if(result > 0){
                con.commit();
            }else{
                con.rollback();
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
        return result;
    }
}








MemberDao.java



package com.kh.w6.member.model.dao;

import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import com.kh.w6.member.controller.LoginServlet;
import com.kh.w6.member.model.vo.Member;
import static com.kh.w6.common.JDBCTemplate.*;

public class MemberDao {
    private Properties prop = new Properties();
   
    public MemberDao() {
        String fileName = MemberDao.class.getResource("/sql/member/member-query.properties").getPath();
   
        try {
            prop.load(new FileReader(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
       
    }
   
    // 로그인 상태 조회용 메소드
    public int checkStatus(Connection con, Member requestMember) {
        PreparedStatement pstmt = null;
        int result = LoginServlet.ID_NOT_EXIST; // 실패했을 때를 위한 초기화
        ResultSet rset = null;
       
        String query = prop.getProperty("checkStatus");
       
        try {
            pstmt = con.prepareStatement(query);
            pstmt.setString(1, requestMember.getUserId());
           
            rset = pstmt.executeQuery();
           
            String userId = "";
            String password = "";
           
            if (rset.next()) {
                userId = rset.getString("USER_ID");
                password = rset.getString("PASSWORD");
               
            }
           
            if (requestMember.getUserId().equals(userId) && requestMember.getPassword().equals(password)) {
                result = LoginServlet.LOGIN_OK;
            }else if (requestMember.getUserId().getClass().equals(userId) && !requestMember.getPassword().equals(password)) {
                result = LoginServlet.WRONG_PASSWORD;
            }else {
                result = LoginServlet.ID_NOT_EXIST;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rset);
            close(pstmt);
        }
       
       
        return result;
    }

    // 로그인 정보 조회용 메소드
    public Member selectOne(Connection con, Member requestMember) {
        Member loginUser = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;
       
        String query = prop.getProperty("selectOne");
       
       
        try {
            pstmt = con.prepareStatement(query);
            pstmt.setString(1, requestMember.getUserId());
            pstmt.setString(2, requestMember.getPassword());
           
           
            rset = pstmt.executeQuery();
           
            if (rset.next()) {
                loginUser = new Member();
               
                loginUser.setUserId(rset.getString("USER_ID"));
                loginUser.setPassword(rset.getString("PASSWORD"));
                loginUser.setUserName(rset.getString("USER_NAME"));
                loginUser.setGender(rset.getString("GENDER"));
                loginUser.setAge(rset.getInt("AGE"));
                loginUser.setEmail(rset.getString("EMAIL"));
                loginUser.setPhone(rset.getString("PHONE"));
                loginUser.setAddress(rset.getString("ADDRESS"));
                loginUser.setHobby(rset.getString("HOBBY"));
                loginUser.setEnrollDate(rset.getDate("ENROLL_DATE"));
               
               
               
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(rset);
            close(pstmt);
        }
       
       
        return loginUser;
    }

    public int updateMember(Connection con, Member newMember) {
        PreparedStatement pstmt = null;
        int result = 0;
        String query = prop.getProperty("updateOne");
       
        try {
            pstmt = con.prepareStatement(query);
           
            pstmt.setString(1, newMember.getUserId());
            pstmt.setString(2, newMember.getPassword());
            pstmt.setString(3, newMember.getUserName());
            pstmt.setString(4, newMember.getGender());
            pstmt.setInt(5, newMember.getAge());
            pstmt.setString(6, newMember.getEmail());
            pstmt.setString(7, newMember.getPhone());
            pstmt.setString(8, newMember.getAddress());
            pstmt.setString(9, newMember.getHobby());
           
            result = pstmt.executeUpdate();
           
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(pstmt);
        }

       
        return result;
    }

}

------------------------------------------------------------------------------------------------------------------------------------



driver.properties, member-query.properties

------------------------------------------------------------------------------------------------------------------------------------

driver.properties



driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=jsp
password=jsp






member-query.properties



checkStatus=SELECT * FROM member WHERE user_id = ?
selectOne=SELECT * FROM member WHERE user_id = ? AND password = ?
updateOne=INSERT INTO MEMBER VALUES(?,?,?,?,?,?,?,?,?,SYSDATE)

------------------------------------------------------------------------------------------------------------------------------------



멤버의 정보가 담길 객체



Member.java

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.w6.member.model.vo;

import java.sql.Date;

public class Member implements java.io.Serializable{
    private String userId;
    private String password;
    private String userName;
    private String gender;
    private int age;
    private String email;
    private String phone;
    private String address;
    private String hobby;
    private Date enrollDate;
    private int status = 99; // 1또는 0으로 로그인 성공 실패를 가리기 때문에 쓰레기값을 넣어놓는다.
   
    public Member() {}

    public Member(String userId, String password, String userName, String gender, int age, String email, String phone,
            String address, String hobby, Date enrollDate, int status) {
        super();
        this.userId = userId;
        this.password = password;
        this.userName = userName;
        this.gender = gender;
        this.age = age;
        this.email = email;
        this.phone = phone;
        this.address = address;
        this.hobby = hobby;
        this.enrollDate = enrollDate;
        this.status = status;
    }

    public Member(String userId, String password, String userName, String gender, int age, String email, String phone,
            String address, String hobby) {
        super();
        this.userId = userId;
        this.password = password;
        this.userName = userName;
        this.gender = gender;
        this.age = age;
        this.email = email;
        this.phone = phone;
        this.address = address;
        this.hobby = hobby;
    }
   
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return super.toString();
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public Date getEnrollDate() {
        return enrollDate;
    }

    public void setEnrollDate(Date enrollDate) {
        this.enrollDate = enrollDate;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
   
   
   
}

------------------------------------------------------------------------------------------------------------------------------------




로그아웃, 회원가입


LogoutServlet.java, newAccount.java

------------------------------------------------------------------------------------------------------------------------------------

LogoutServlet.java



package com.kh.w6.member.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class LogoutServlet
 */
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LogoutServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.getSession().invalidate();
       
        response.sendRedirect("views/member/loginForm.jsp");
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}



newAccount.java



package com.kh.w6.member.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.w6.member.model.service.MemberService;
import com.kh.w6.member.model.vo.Member;

@WebServlet("/newaccount")
public class newAccount extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public newAccount() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
       
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
        String userName = request.getParameter("userName");
        int age = Integer.parseInt(request.getParameter("age"));
        String gender = request.getParameter("gender");
        String email = request.getParameter("email");
        String phone = request.getParameter("phone");
        String address = request.getParameter("address");
        String[] hobbies = request.getParameterValues("hobby");
       
        String hobby = String.join(",", hobbies);
       
        System.out.println("입력한 정보----------\r\n"
                + userId + "\r\n"
                + password + "\r\n"
                + userName + "\r\n"
                + age + "\r\n"
                + gender + "\r\n"
                + email + "\r\n"
                + phone + "\r\n"
                + address + "\r\n"
                + hobby);
       
        Member newMember = new Member(userId, password, userName, gender, age, email, phone, address, hobby);
       
        System.out.println(newMember.toString());
       
        int result = new MemberService().addMember(newMember);
       
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
       
        if(result > 0){
            out.println("<script>alert('성공적으로 회원 가입 되었습니다.');</script>");
            out.println("<script>location.href='views/member/loginForm.jsp';</script>");
            out.close();
           
        }else{
            out.println("<script>alert('회원 가입에 실패했습니다.');</script>");
            out.println("<script>history.back();</script>");
            out.close();
           
        }

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------




JDBCTemplate.java

------------------------------------------------------------------------------------------------------------------------------------

JDBCTemplate.java



package com.kh.w6.common;

import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTemplate {
    public static Connection getConnection() {
        Connection conn = null;
        Properties prop = new Properties();
       
        String fileName = JDBCTemplate.class.getResource("/sql/driver.properties").getPath();
               
        System.out.println(fileName);
       
        try {
            prop.load(new FileReader(fileName));
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String user = prop.getProperty("user");
            String password = prop.getProperty("password");
           
            // 아래 클래스 구문은 신버전에서는 자동으로 추가되어서 생략해도 되지만
            // 구버전 호환을 위해 명시해두자.
            Class.forName(driver);
           
            conn = DriverManager.getConnection(url, user, password);
           
            conn.setAutoCommit(false);
           
            System.out.println(conn);
           
        } catch (Exception e) {
            e.printStackTrace();
        }
        // prop 파일을 수정할 때 classes 폴더 아래의 파일을 수정하면 서버 껏따 킬때 재생성 되기 때문에 사라진다.
        // 그리고 바로바로 수정사항이 적용이 안될 때도 있는데 메뉴바 상단의 Project - clean을 실행하면 강제 재컴파일 시켜준다.
       
        return conn;
    }
   
    public static void close(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void close(Statement stmt) {
        try {
            if(stmt != null && !stmt.isClosed()) {
                stmt.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void close(ResultSet rset) {
        try {
            if(rset != null && !rset.isClosed()) {
                rset.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void commit(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.commit();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   
    public static void rollback(Connection con) {
        try {
            if(con != null && !con.isClosed()) {
                con.rollback();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

------------------------------------------------------------------------------------------------------------------------------------





이 외의 폼들은 다음과 같다.


main.jsp, newAccount.jsp, errorPage.jsp

------------------------------------------------------------------------------------------------------------------------------------

main.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.w6.member.model.vo.Member"%>
<% Member loginUser = (Member)session.getAttribute("loginUser"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
    #userInfo {
        float:right;
    }
</style>
</head>
<body>
    <h1 align="center">Welcome to MVC 랜드</h1>
    <div id="userInfo">
        <label><%= loginUser.getUserName() %>님 환영합니다.</label><br>
        <button id="changeInfo">정보수정</button>
        <button id="logout">로그아웃</button>
    </div>
    <script type="text/javascript">
        $(function name() {
            $("#logout").click(function() {
                location.href="<%=request.getContextPath()%>/logout";
            });
        });
    </script>
</body>
</html>





newAccount.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="<%=request.getContextPath() %>/newaccount" method="post">
        <input type="text" placeholder="아이디" name="userId" id="userId">
        <br>
        <input type="password" placeholder="패스워드" name="password" id="password">
        <br>
        <input type="text" placeholder="이름" name="userName" id="userName">
        <br>
        <input type="text" placeholder="나이" name="age" id="age">
        <br>
        <input type="email" placeholder="이메일" name="email" id="email">
        <br>
        <input type="tel" placeholder="휴대폰" name="phone" id="phone">
        <br>
        <input type="text" placeholder="주소" name="address" id="address">
        <br>
        <label>성별 : </label>
        <input type="radio" name="gender" id="male" value="M">
        <label for="male">남</label>
        <input type="radio" name="gender" id="female" value="F">
        <label for="female">여</label>
        <br>
        <label>취미 : </label>
        <input type="checkbox" name="hobby" id="hobby0" value="운동">
        <label for="hobby0">운동</label>
        <input type="checkbox" name="hobby" id="hobby1" value="등산">
        <label for="hobby1">등산</label>
        <input type="checkbox" name="hobby" id="hobby2" value="독서">
        <label for="hobby2">독서</label>
        <input type="checkbox" name="hobby" id="hobby3" value="게임">
        <label for="hobby3">게임</label>
        <input type="checkbox" name="hobby" id="hobby4" value="여행">
        <label for="hobby4">여행</label>
        <br><br>
        <input type="submit" value="가입">&nbsp;&nbsp;
        <input type="reset" value="취소">
    </form>
</body>
</html>






errorPage.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% String msg = (String)request.getAttribute("msg"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1><%= msg %></h1>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------











MemberException.java 파일은 따로 내용을 수정 안하였으니 만들 내용이 없다.





MVC 패턴이란 Model, View, Controller의 구조로 이루어진걸 말한다.


Run에서 Main 스레드에 의해 프로그램이 실행되고


View를 통해서 화면을 보여주고


Controller에서 사용자가 이용할 기능들을 view와 연결한다.


Model은 Controller에서 사용할 객체와 같은 모델들을 사용하게 된다.


모델에서는 DB와의 통신을 통해 조회, 수정 등 SQL문을 사용한다.




MVC 2 패턴에서는


Controller와 Model 사이에 공통적으로 사용할 기능(DB연결이나 기능) Common이 추가된다.





이 후의 예제는 위와 같은 구조로 작성된다.



이번 폴더구조는 다음과 같다.




이미지 파일 첨부


images.zip





이번에는 JSP 프로젝트에 JDBC 기능을 사용한다.


WEB-INF 폴더 아래에 lib 폴더를 만들고


ojdbc6.jar을 복사하자.(JDBC 할 때 build Path 추가와 같은 작업)


이 파일은 jdbc를 공부할 때 어디있는지 한번 설명을 했었다. (https://qdgbjsdnb.tistory.com/196?category=726465)


위의 글 설명 그대로


sql을 사용하기 위한 Library 파일을 불러온다.


계속 사용했던 oracle에 설치 폴더에 있는 파일을 불러온다.


경로는 설치 경로 + oraclexe/app/oracle/product/11.2.0/server/jdbc/lib 에 ojdbc6이라는 파일이 존재한다.



출처: https://qdgbjsdnb.tistory.com/196?category=726465 [하위^^]

sql을 사용하기 위한 Library 파일을 불러온다.


계속 사용했던 oracle에 설치 폴더에 있는 파일을 불러온다.


경로는 설치 경로 + oraclexe/app/oracle/product/11.2.0/server/jdbc/lib 에 ojdbc6이라는 파일이 존재한다.



출처: https://qdgbjsdnb.tistory.com/196?category=726465 [하위^^]

sql을 사용하기 위한 Library 파일을 불러온다.


계속 사용했던 oracle에 설치 폴더에 있는 파일을 불러온다.


경로는 설치 경로 + oraclexe/app/oracle/product/11.2.0/server/jdbc/lib 에 ojdbc6이라는 파일이 존재한다.



출처: https://qdgbjsdnb.tistory.com/196?category=726465 [하위^^]으

sql을 사용하기 위한 Library 파일을 불러온다.


계속 사용했던 oracle에 설치 폴더에 있는 파일을 불러온다.


경로는 오라클 설치 경로 + oraclexe/app/oracle/product/11.2.0/server/jdbc/lib 에 ojdbc6이라는 파일이 존재한다.




파일을 찾아서 lib 폴더에 복사하면 된다.







01_testPerson.jsp는 선호도 조사로 선택한 항목, 입력 값 등을 통해서


해당하는 이미지를 출력한다.


또한 선택을 안했을 경우의 예외처리도 전부 JSP 파일에서 구현한다.





02_memberJoin.jsp는 JSP에서 데이터 베이스에 접근하여 새로운 정보를 추가하여 회원가입을 구현한다.



index.jsp

------------------------------------------------------------------------------------------------------------------------------------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>MVC Model1</h1>
    <p>jsp도 서블릿이다!</p>
    <h3><a href="views/01_testPerson.jsp">선호도 조사</a></h3>
    <h3><a href="views/02_memberJoin.jsp">회원가입</a></h3>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------


01_testPerson.jsp, 01_testPersonResult.jsp

------------------------------------------------------------------------------------------------------------------------------------

01_testPerson.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>개인 취향 테스트(MVC)</h2>
    당신의 취향을 테스트합니다.<br>
    데이터 입력 후 확인 버튼을 누르세요
   
    <form action="01_testPersonResult.jsp" name="personFrm" method="post">
        <ul style="list-style: none; line-height: 200%;">
            <li>이름은? <input type="text" name="name" size="10"></li>
            <li> 좋아하는 색?
                <input type="radio" name="color" id="color-red" value="빨강">
                <label for="color-red">빨강</label>
                <input type="radio" name="color" id="color-blue" value="파랑">
                <label for="color-blue">파랑</label>
                <input type="radio" name="color" id="color-yellow" value="노랑">
                <label for="color-yellow">빨강</label>
            </li>
            <li>좋아하는 동물?
                <select name="animal" id="animal">
                    <option value="강아지">강아지</option>
                    <option value="고양이">고양이</option>
                    <option value="금붕어">금붕어</option>
                </select>
            </li>
            <li>좋아하는 음식?(모두 고르세요)
                <input type="checkbox" name="food" id="food1" value="짜장면">
                <label for="food1">짜장면</label>
                <input type="checkbox" name="food" id="food2" value="짬뽕">
                <label for="food2">짬뽕</label>
                <input type="checkbox" name="food" id="food3" value="탕수육">
                <label for="food3">탕수육</label>
                <input type="checkbox" name="food" id="food4" value="양장피">
                <label for="food4">양장피</label>
                <input type="checkbox" name="food" id="food5" value="팔보채">
                <label for="food5">팔보채</label>
            </li>
            <li>
                <br>
                <input type="submit" value="확인">&nbsp;&nbsp;
                <input type="reset" value="취소">
            </li>
        </ul>
    </form>
   
</body>
</html>






01_testPersonResult.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    //1.전달 파라미터 한글 처리
    request.setCharacterEncoding("utf-8");

    //2.전달된 파라미터 변수에 담기
    String name = request.getParameter("name");
    String color = request.getParameter("color");
    String animal = request.getParameter("animal");
    String[] foodArr = request.getParameterValues("food");
   
   
   
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
    <div id="container">
        <div id="header">
            <h2><span style="color: blue;"><%= name %></span>님의 개인 취향 테스트</h2>
        </div>
        <div id="color">
            <span class="title">당신이 좋아하는 색깔은?</span>
        </div>
       
        <div id="animal">
            <span class="title">당신이 좋아하는 동물은?</span>
        </div>
        <div id="food">
            <span class="title">당신이 좋아하는 음식은?</span>
        </div>
   
    </div>
    <script>
        $(function(){
            <%
                if(color != null){
                switch(color){
                    case "빨강" :
            %>
                            $("#color").append("<img src='<%=request.getContextPath()%>/images/red.png'>");
            <%                break;
                    case "파랑" :
            %>
                            $("#color").append("<img src='<%=request.getContextPath()%>/images/blue.png'>");
            <%                break;
                    case "노랑" :
            %>
                            $("#color").append("<img src='<%=request.getContextPath()%>/images/blue.png'>");
            <%                break;
                }
                }else{
            %>
                    $("#color").append("선택한 색깔이 없습니다 ㅜㅜ");
            <%
                }
            %>
        });
    </script>
    <script>
        $(function(){
            <%
                switch(animal){
                    case "강아지" :
            %>
                            $("#animal").append("<img src='<%=request.getContextPath()%>/images/dog.png'>");
            <%                break;
                    case "고양이" :
            %>
                            $("#animal").append("<img src='<%=request.getContextPath()%>/images/cat.png'>");
            <%                break;
                    case "금붕어" :
            %>
                            $("#animal").append("<img src='<%=request.getContextPath()%>/images/fish.png'>");
            <%                break;
                }
            %>
        });
    </script>
    <script>
        $(function(){
            <%
                try{
                for(int i = 0; i < foodArr.length; i++){   
                    switch(foodArr[i]){
                        case "짜장면" :
            %>
                            $("#food").append("<img src='<%=request.getContextPath()%>/images/jjm.png'>");
            <%
                            break;
                        case "짬뽕" :
            %>
                            $("#food").append("<img src='<%=request.getContextPath()%>/images/jjbong.png'>");
            <%
                            break;
                        case "탕수육" :
            %>
                            $("#food").append("<img src='<%=request.getContextPath()%>/images/tangsy.png'>");
            <%
                            break;
                        case "양장피" :
            %>
                            $("#food").append("<img src='<%=request.getContextPath()%>/images/yang.png'>");
            <%
                            break;
                        case "팔보채" :
            %>
                            $("#food").append("<img src='<%=request.getContextPath()%>/images/palbc.png'>");
            <%
                            break;
                    }   
                }
                }catch(Exception e){
            %>
                            $("#food").append("선택한 음식이 없습니다 ㅜㅜ");
            <%
                }
            %>
        });
    </script>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------





02_memberJoin.jsp, 02_memberJoinResult.jsp

------------------------------------------------------------------------------------------------------------------------------------

02_memberJoin.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <div align="center">
        <h2>회원 가입 정보 입력</h2>
        <br>
        <form action="02_memberJoinResult.jsp" method="post">
            <input type="text" placeholder="아이디" name="userId" id="userId">
            <br>
            <input type="password" placeholder="패스워드" name="password" id="password">
            <br>
            <input type="text" placeholder="이름" name="userName" id="userName">
            <br>
            <input type="text" placeholder="나이" name="age" id="age">
            <br>
            <input type="email" placeholder="이메일" name="email" id="email">
            <br>
            <input type="tel" placeholder="휴대폰" name="phone" id="phone">
            <br>
            <input type="text" placeholder="주소" name="address" id="address">
            <br>
            <label>성별 : </label>
            <input type="radio" name="gender" id="male" value="M">
            <label for="male">남</label>
            <input type="radio" name="gender" id="female" value="F">
            <label for="female">여</label>
            <br>
            <label>취미 : </label>
            <input type="checkbox" name="hobby" id="hobby0" value="운동">
            <label for="hobby0">운동</label>
            <input type="checkbox" name="hobby" id="hobby1" value="등산">
            <label for="hobby1">등산</label>
            <input type="checkbox" name="hobby" id="hobby2" value="독서">
            <label for="hobby2">독서</label>
            <input type="checkbox" name="hobby" id="hobby3" value="게임">
            <label for="hobby3">게임</label>
            <input type="checkbox" name="hobby" id="hobby4" value="여행">
            <label for="hobby4">여행</label>
            <br><br>
            <input type="submit" value="가입">&nbsp;&nbsp;
            <input type="reset" value="취소">
        </form>
    </div>


</body>
</html>





02_memberJoinResult.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.sql.*"%>
<%
    //1.한글 인코딩 처리
    request.setCharacterEncoding("utf-8");

    //2.전송값 꺼내서 변수에 기록
    String userId = request.getParameter("userId");
    String password = request.getParameter("password");
    String userName = request.getParameter("userName");
    int age = Integer.parseInt(request.getParameter("age"));
    String gender = request.getParameter("gender");
    String email = request.getParameter("email");
    String phone = request.getParameter("phone");
    String address = request.getParameter("address");
   
    String[] hobbies = request.getParameterValues("hobby");
   
    //String[]을 구분자로 연결하는 String의 스태틱메소드 join
    String hobby = String.join(",", hobbies);
   
    //3.비즈니스로직 작성
    Connection conn = null;
    PreparedStatement pstmt = null;
    int result = 0;
    String msg = "";
   
    String query = "INSERT INTO MEMBER VALUES(?,?,?,?,?,?,?,?,?,SYSDATE)";
   
    try{
        Class.forName("oracle.jdbc.driver.OracleDriver");
       
        conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "jsp", "jsp");
       
        pstmt = conn.prepareStatement(query);
        pstmt.setString(1, userId);
        pstmt.setString(2, password);
        pstmt.setString(3, userName);
        pstmt.setString(4, gender);
        pstmt.setInt(5, age);
        pstmt.setString(6, email);
        pstmt.setString(7, phone);
        pstmt.setString(8, address);
        pstmt.setString(9, hobby);
       
        result = pstmt.executeUpdate();
       
        if(result > 0){
            conn.commit();
            msg = "성공적으로 회원 가입 되었습니다.";
        }else{
            conn.rollback();
            msg = "회원 가입에 실패했습니다.";
        }
       
       
    }catch(Exception e){
        e.printStackTrace();
    }finally {
        try{
            pstmt.close();
            conn.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
   
   
   
   
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <ul style="list-style: none; line-height: 200%">
        <li>아이디 : <%= userId %></li>
        <li>패스워드 : <%= password %></li>
        <li>이름 : <%= userName %></li>
        <li>나이 : <%= age %></li>
        <li>이메일 : <%= email %></li>
        <li>성별
            <span id="gender" style="font-weight: bold;
            color: <%
                    String genderColor = "";
                    if("M".equals(gender)){
                        genderColor = "blue";
                    }else{
                        genderColor = "red";
                    }
                %><%=genderColor%>"><%=gender %></span>
        </li>
        <li>휴대폰 : <%= phone %></li>
        <li>주소 : <%= address %></li>
        <li>취미 : <%= hobby %></li>
   
    </ul>
    <hr>
    <p><%= msg %></p>


</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------





주목해야 할 점은 html문 중간중간에 <%%>를 사용하여 연산된 데이터를 표현하는 것


또한 Jquery 문에도 조건문과 섞어서 사용하는 방법을 주목하자.












이번 예는 간단한 JSP 기능들을 이용한 페이지들을 사용해보자.


테이블 구조는 다음과 같다.







총 4가지의 페이지를 볼 수 있는데 01_sum은 연산의 결과가 오류일 때 정해진 오류 페이지를 보여준다.


페이지를 열 때 브라우저에 400번대 에러와 500번대 에러는 흔히 볼 수 있는데


500번대 에러는 서버측의 에러이기 때문에 해커가 현재 서버가 어떤 문제가 있는지 코드에 어떤 오류가 있는지


알 수 있기 때문에 500번 오류는 노출하지 않는걸 권장한다.




두번째로 02_date인데 웹브라우저에서 자주 사용하는 날짜 함수를 JSP에서 어떻게 사용하는지 확인해보자.



세번째로 03_fortune은 다른 페이지(jsp 파일)를 불러와 현재 페이지에 포함(include)하는 방법을 확인해보자



네번째 04_menu는 간단하게 get방식으로 값을 넘겨서 연산처리를 하여 결과를 확인해보자.






index.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>JSP 테스트</h1>
    <h3><a href="views/01_sum.jsp">테스트1</a></h3>
    <h3><a href="views/02_date.jsp">테스트2</a></h3>
    <h3><a href="views/03_fortune.jsp">테스트3</a></h3>
    <h3><a href="views/04_menu.jsp">테스트4</a></h3>
</body>
</html>










01_sum.jsp




<%-- directive page : 페이지 지시자 태그'<%@' --%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%--
        아래의 코드(System.out.println)를 보면 에러가 발생하는 구문이다.
        실행하면 에러페이지에 아래 코드가 출력이 되는데 코드가 그대로 노출되기 때문에 보안에 매우 취약하다.
        따라서 에러 페이지를 따로 지정하면 된다.
    --%>
    <%@ page errorPage="errorPage.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<%-- JSP는 동적 컴파일을 지원하기 때문에 변경사항이 있어도 서버를 껏다 킬 필요가 없다. --%>
<body>
    <%-- JSP 주석 '<%--' --%>
    <!-- HTML 주석 -->
   
   
   
    <%-- Scripting Element 1 : scriptlet --%>
    <%-- <%로 시작해서 %>로 끝나는 것을 스크립틀릿이라고 부른다. --%>
    <%
        int total = 0;
       
        for(int i = 1; i <= 10; i++){
            total += i;
        }
       
        // 아래의 코드를 보면 에러가 발생하는 구문이다.
        // 실행하면 에러페이지에 아래 코드가 출력이 되는데
        String s = null;
        System.out.println(s.charAt(0));
    %>
   
   
   
    <%-- Scripting element 2 : expression 기능은 자바 코드에서 작성한 결과값을 출력한다. --%>
    <%-- expression 태그는 세미콜론이 있으면 에러가 난다. --%>
    <h4>1부터 10까지의 합은 : <span style="color: red; font-size: 16pt; "><%= total %></span></h4>
    <h4>1부터 10까지의 합은 : <span style="color: red; font-size: 16pt; "><% out.println(total); %></span></h4>
    <%-- out은 선언하지 않았는데 사용할 수 있음 - 내장객체이므로 가능 --%>
</body>
</html>





errorPage.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>에러페이지</h1>
    <h3>에러 종류 : <%= exception.getClass().getName() %></h3>
</body>
</html>











02_date.jsp




<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%
        Date now = new Date();
       
        String date = String.format("%tF", now);
        String time = String.format("%tp %tT", now, now);
        String today = String.format("%tY년 %tm월, %td일, %tA", now, now, now, now);
       
        /*
        날짜 타입           설명
        ------------------------------------------
        %tF          날짜를 yyyy-mm-dd 형식으로 포맷
        %tT          날짜의 시각을 HH:MM:SS 형식으로 포맷
        ------------------------------------------
        %tY          4자리 년도만 출력
        %ty          2자리 년도만 출력
        %tB          월의 이름 영문(January, Febuary, ....)
        %tm          월을 숫자로 (01, 02, 03 ~ 12)
        %td          일수를 1 ~ 31로 표현
        %te          %td와 같다.
        %tA          요일명 출력
        ------------------------------------------
        %tp          오전, 오후 출력
        %tk          시간을 0 ~ 23 으로 출력
        %tl          시간을 1 ~ 12로 출력
        %tM          분을 00 ~ 59로 출력
        %tS          초를 00 ~ 59로 출력
        ------------------------------------------
        */
    %>
   
    <ul style="list-style: decimal;">
        <li>오늘의 날짜 : <%= date %></li>
        <li>현재 시간 : <%= time %></li>
        <li>오늘은 <span style="color: red;"><%= today %></span>입니다.</li>
       
    </ul>
</body>
</html>










03_fortune.jsp



<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%--
<%
    Date now = new Date();
    String today = String.format("%tY년 %tm월 %td일 %tA", now, now, now, now);
%>
--%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%-- <h2>오늘의 운세<sub style="color:lightgray"><%= today %></sub></h2> --%>
    <h2>오늘의 운세<%@ include file="today.jsp" %></h2>
    <%-- 위의 date 때문에 오류가 나기 때문에 주석으로 감싼다. --%>
    <select>
        <option>쥐띠</option>
        <option>소띠</option>
        <option>호랑이띠</option>
        <option>토끼띠</option>
        <option>용띠</option>
        <option>뱀띠</option>
        <option>말띠</option>
        <option>양띠</option>
        <option>원숭이띠</option>
        <option>닭띠</option>
        <option>개띠</option>
        <option>돼지띠</option>
    </select>
   
</body>
</html>






today.jsp




<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    Date now = new Date();
    String today = String.format("%tY년 %tm월 %td일 %tA", now, now, now, now);
%>
<%-- include 전용 파일에 HTML 코드들이 있으면 다같이 딸려가기 때문에 지워둔다. iframe과 유사 --%>
<sub style="color: lightgray;"><%= today %></sub>











04_menu.jsp




<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>오늘의 메뉴<%@ include file="today.jsp" %></h2>
   
    <!--  13번째 줄과 14번째 줄은 같은 의미 -->
    <!-- <form action="/w4/menu.Order.do" method="get" name="menuFrm"></form> -->
    <form action="<%= request.getContextPath() %>/menuOrder" method="get" name="menuFrm">
        <select id="menu" name="menu">
            <option value="햄버거">햄버거</option>
            <option value="짜장면">짜장면</option>
            <option value="짬뽕">짬뽕</option>
            <option value="순대국">순대국</option>
        </select>
        <input type="submit" value="선택완료">
    </form>
   
</body>
</html>











MenuOrderServlet.java




package com.kh.servletTest.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/menuOrder")
public class MenuOrderServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public MenuOrderServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 전송값에 한글이 있을 경우 인코딩 처리 해야 함, 그냥 항상 하자
        request.setCharacterEncoding("utf-8");
       
        // 2. 전송갑 꺼내서 변수에 기록하기
        String menu = request.getParameter("menu");
       
        // 3. 비지니스 로직
        int price = 0;
        switch (menu) {
        case "햄버거":
            price = 5000;
            break;
        case "짬뽕":
            price = 4000;
            break;
        case "짜장면":
            price = 4500;
            break;
        case "순대국":
            price = 6000;
            break;
        }
       
        // 4. 실행 결과 처리 및 전송 (박싱이 자동으로 처리됨, 오토 박싱)
        request.setAttribute("menu", menu);
        request.setAttribute("price", price);
       
        RequestDispatcher view = request.getRequestDispatcher("views/04_menuResult.jsp");
       
        view.forward(request, response);
       
       
       
       
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}










04_menuResult.jsp





<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String menu = (String)request.getAttribute("menu");
    int price = (int)request.getAttribute("price");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>감사합니다.</h2>
    주문하신 <%= menu %>의 결제 금액은 <%= price %>원 입니다.
</body>
</html>















번호별로 주목할 점은 위에서 설명한거와 같이 넘버별로 하나씩



01_sum <%@ page errorPage="errorPage.jsp" %>을 통해서 임의의 에러 페이지를 지정하고


errorPage.jsp에서는 <%= exception.getClass().getName() %>을 통해서 에러 코드(널포인터 익셉션)를 표시해준다






02_date는 <%%> 구문안에 Date를 사용하고 사용하기 위해서 상단에 import해야 하는것을 확인하자.


그 외 실제로 확인하는 방법은 주석문에 정리해두었다.






03_fortune은 <%@ include file="today.jsp" %>을 통해서 적절한 부분에 해당 jsp 파일을 불러온다.


불러올 파일의 내용을 전부 가져오기 때문에 HTML 태그라던가 head body 등 쓸모없는 부분은 지워서 작성한다.






네번째 04_menu는 JSP -> Servlet -> JSP 순으로 데이터의 흐름이 어떻게 움직이는지 확인해보자.





1. Tomcat이 페이지의 default 값 파일이 저장되어 있는 위치



톰캣을 이클립스 Server에 연동 시키면 프로젝트 구조에 다음과 같은 Servers라는게 생긴다




이 파일들이 전부 default 값으로 설정 해 둔 정보들이 담겨있는 파일이다.


예를 들어 페이지의 맨 첫번째 페이지를 지금까지 index.html으로 사용했는데


이것은 어디서 결정되는지 궁금했을거다.


이것은 위의 파일들에 담겨있는 정보들에 지정이 전부 되어있다.


또한 프로젝트에서 이 기본 정보들을 변경 할 수 있다.


이 파일들을 복사해서 프로젝트에 붙여넣고 내용을 바꾼다.(파일 이름은 절대 바꾸면 안된다.)


프로젝트에 동일한 이름의 파일이 있다면 톰캣은 default 파일들을 기준으로 잡지 않고


프로젝트에 있는 파일들의 설정을 따른다.





2. java 파일이 서버에 적용되는 원리


위의 사진에서 네모친 web.xml에 java 파일을 서버에 올리는 작업 대상이 될 폴더가 명시되어 있다.






다음과 같이 <context> 부분의 속성에 workDir="원하는 경로"를 입력하면


그 쪽에 java파일들이 컴파일러에 의해 처리가 되어 class 파일로 저장된다.










이번 예제는 get과 post의 차이를 확인해보자.


코드를 복사 붙여넣기를 하면 무조건 오류난다.


왜냐하면 코드에 경로 관련해서 정보를 많이 입력하기 때문에


한 줄 한 줄 복사 붙여넣기 하거나 읽으면서 해보길 권장.


폴더 구조는 다음과 같다.




프로그램 흐름과 작성 순서는


index.html - testPerson1.html


TestPersonServlet.java - result.jsp


testPerson2.html - TestPersonServlet2.java








index.html



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>서블릿 테스트</h1>
    <h2><a href="views/testPerson1.html">1. 개인 취향 테스트(get)</a></h2>
    <h2><a href="views/testPerson1.html">2. 개인 취향 테스트(post)</a></h2>
   
   
   
</body>
</html>





testPerson1.html



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>개인 취향 테스트(GET)</h2>
    당신의 취향을 테스트 합니다.<br>
    데이터를 입력 후 확인 버튼을 누르세요<br>
   
    <form action="/w3/testPerson" name="personFrm" method="get">   
        <ul style="list-style: none; line-height: 200%">
            <li>이름은?
                <input type="text" name="name" size="10">
            </li>
            <li>좋아하는 색?
                <input type="radio" name="color" value="빨강" id="red">
                <label for="red">빨강</label>
                <input type="radio" name="color" value="파랑" id="blue">
                <label for="blue">파랑</label>
                <input type="radio" name="color" value="노랑" id="yellow">
                <label for="yellow">노랑</label>
                <input type="radio" name="color" value="초록" id="green">
                <label for="green">초록</label>
            </li>
            <li>좋아하는 동물은?
                <select name="animal">
                    <option value="강아지">강아지</option>
                    <option value="고양이">고양이</option>
                    <option value="병아리">병아리</option>
                </select>
            </li>
            <li>좋아하는 음식?(모두 고르세요)
                <input type="checkbox" name="food" id="food1" value="짜장면">
                <label for="food1">짜장면</label>
                <input type="checkbox" name="food" id="food2" value="짬뽐">
                <label for="food1">짬뽐</label>
                <input type="checkbox" name="food" id="food3" value="탕수육">
                <label for="food1">탕수육</label>
                <input type="checkbox" name="food" id="food4" value="양장피">
                <label for="food1">양장피</label>
                <input type="checkbox" name="food" id="food5" value="팔보채">
                <label for="food1">팔보채</label>
            </li>
            <li>
                <br>
                <input type="submit" name="btnOk" id="btnOk" value="확인">
                &nbsp; &nbsp;
                <input type="reset" value="취소">
            </li>
           
       
        </ul>
    </form>
</body>
</html>






TestPersonServlet.java




package controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/testPerson")
public class TestPersonServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public TestPersonServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 첫 번째 파라미터인 HttpServletRequest는
        // 웹 브라우저에서 사용자가 요청한 내용을 받아주는 용도로 쓰인다.
        // 두 번째 파라미터인 HttpServletResponse는
        // 첫 번째 파라미터에서 처리한 결과를 웹 브라우저를 통해 사용자에게 보여주기 위한 용도로 쓰인다.
       
        String name = request.getParameter("name");
        String color = request.getParameter("color");
        String animal = request.getParameter("animal");
       
        String[] foodArr = request.getParameterValues("food");
       
        System.out.println("name : " + name + "\r\n" +
                            "color : " + color + "\r\n" +
                            "animal : "+ animal);
       
        for (int i = 0; i < foodArr.length; i++) {
            System.out.println("foodArr [" + i + "] : " + foodArr[i]);
        }
       
        // Response 핸들링 : 화면출력
        response.setContentType("text/html; charset=UTF-8");
       
        PrintWriter out = response.getWriter();
       
        out.println("<html>"
                + "<head>"
                + "<title>개인 취향 테스트 결과 화면</title>"
                + "</head>"
                + "<body>"
                + "<h2 style='color: red;'>개인 취향 테스트 결과(GET)</h2>");
        out.printf("<span style='color: lightblue;'>%s</span>님의 개인 취향은 <br><br>", name);
        out.printf("<span style='color: lightgreen; font-weight: bold;'>%s</span>, <span style='color: lightred; font-weight: bold;'>%s</span>를 좋아합니다<br><br>", color, animal);
        out.println("좋아하는 음식은 ");
        for (int i = 0; i < foodArr.length; i++) {
            if (i == 0) {
                out.printf("%s", foodArr[i]);
            } else {
                out.printf(", %s", foodArr[i]);
            }
        }
        out.println("입니다."
                + "</body>"
                + "</html>");
       
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}



result.jsp




<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String name = (String)request.getAttribute("name");
    String color = (String)request.getAttribute("color");
    String animal = (String)request.getAttribute("animal");
    String foods = (String)request.getAttribute("foods");
    String recommendation = (String)request.getAttribute("recommendation");
%>

<!DOCTYPE html>
<!-- 꺽쇠 + % 키워드로 자바 코드를 입력할 수 있다. -->
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>개인 취향 테스트 결과(POST) - jsp</h2>
    <span style="color: lightblue; font-weight: bold;"><%= name %></span>님의 개인 취향은
    <br><br>
    <span style="color: lightgreen; font-weight: bold;"><%= color %></span>색을 좋아하고
    <span style="color: lightred; font-weight: bold;"><%= animal %></span>를 좋아합니다.
    <br><br>
    좋아하는 음식은 <%= foods %>입니다.
    <br>
    <h3>둘리의 추천!</h3>
    <p><%= recommendation %> 어떠세요?</p>

</body>
</html>





testPerson2.html




<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>개인 취향 테스트(POST)</h2>
    당신의 취향을 테스트 합니다.<br>
    데이터를 입력 후 확인 버튼을 누르세요<br>
   
    <form action="/w3/testPerson2" name="personFrm" method="post">   
        <ul style="list-style: none; line-height: 200%">
            <li>이름은?
                <input type="text" name="name" size="10">
            </li>
            <li>좋아하는 색?
                <input type="radio" name="color" value="빨강" id="red">
                <label for="red">빨강</label>
                <input type="radio" name="color" value="파랑" id="blue">
                <label for="blue">파랑</label>
                <input type="radio" name="color" value="노랑" id="yellow">
                <label for="yellow">노랑</label>
                <input type="radio" name="color" value="초록" id="green">
                <label for="green">초록</label>
            </li>
            <li>좋아하는 동물은?
                <select name="animal">
                    <option value="강아지">강아지</option>
                    <option value="고양이">고양이</option>
                    <option value="병아리">병아리</option>
                </select>
            </li>
            <li>좋아하는 음식?(모두 고르세요)
                <input type="checkbox" name="food" id="food1" value="짜장면">
                <label for="food1">짜장면</label>
                <input type="checkbox" name="food" id="food2" value="짬뽐">
                <label for="food1">짬뽐</label>
                <input type="checkbox" name="food" id="food3" value="탕수육">
                <label for="food1">탕수육</label>
                <input type="checkbox" name="food" id="food4" value="양장피">
                <label for="food1">양장피</label>
                <input type="checkbox" name="food" id="food5" value="팔보채">
                <label for="food1">팔보채</label>
            </li>
            <li>
                <br>
                <input type="submit" name="btnOk" id="btnOk" value="확인">
                &nbsp; &nbsp;
                <input type="reset" value="취소">
            </li>
           
       
        </ul>
    </form>
</body>
</html>





TestPersonServlet2.java




package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/testPerson2")
public class TestPersonServlet2 extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public TestPersonServlet2() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // request 문자셋 변경
        // 넘겨받은 데이터가 한글일 경우(영어가 아닐 경우) 인코딩 처리를 해야 한다.
        // [중요] request.getParameter()보다 먼저 기술해야 한다.
        request.setCharacterEncoding("UTF-8");
       
        String name = request.getParameter("name");
        String color = request.getParameter("color");
        String animal = request.getParameter("animal");
       
        String[] foodArr = request.getParameterValues("food");
       
        String foods = "";
       
        for (int i = 0; i < foodArr.length; i++) {
            if (i == 0) {
                foods += foodArr[i];
            } else {
                foods += ", " + foodArr[i];
            }
        }
       
       
        // 사용자가 좋아하는 색을 기준으로 상품을 추천해 줌
        String recommendation = "";
        switch (color) {
        case "빨강":
            recommendation = "빨간 페라리";
            break;
        case "노랑":
            recommendation = "노란 카레";
            break;
        case "초록":
            recommendation = "초록 붕어빵";
            break;
        case "파랑":
            recommendation = "파란 캔디바";
            break;
        }
       
        response.setContentType("text/html; charset=UTF-8");
       
        request.setAttribute("name", name);
        request.setAttribute("color", color);
        request.setAttribute("animal", animal);
        request.setAttribute("foods", foods);
        request.setAttribute("recommendation", recommendation);
       
        RequestDispatcher view
                = request.getRequestDispatcher("views/result.jsp");
        view.forward(request, response);
       
       
       
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}



특별히 어려운 부분은 없다.

JSP는 간단하게 이해하면 HTML + CSS + JS + JQ + java 문서이다.


그냥 html 부분은 모든 기능을 쓸 수 있는 방법이 있다고 이해하면 된다.


먼저 아래 표부터 보자



강사님께서 주신 자료에서 따온 표인데 형태가 정말 잘 표현되었다고 생각해서 가져왔다.


Servlet은 java 파일로 자바에서 HTML을 컨트롤 할 수 있다.


JSP의 경우는 HTML에서 JAVA를 컨트롤 한다.


Java에서 할 경우 HTML 코드를 컨트롤 할 수 있지만 매우 귀찮고 번거로운 노가다 작업이 된다.


JSP에선 좀 더 편하게 할 수 있다.


핵심 키워드는 <%%> 이다.


<%%> 키워드도 여러 종류가 있다.





<%-- 내용 --%> : 주석


<%@ 내용 %> : 다양한 페이지 설정들을 명시할 때 사용


<%! 내용 %> : JSP에서 선언시 사용


<% 내용 %> : java 코드들을 입력하는 부분


<%= 내용 %> : 표현식, 예로 설명 ------- <h1><%= 변수 %><h1>은 <h1>변수의 값<h1>과 같다.



+ Recent posts