메이븐 기반 웹프로젝트

게시판에 파일 입력하기

 

  • pom.xml

⇒ MultipartResolver를 사용하기 위해 Apache Commons FileUpload를 pom.xml 디펜던시에 추가

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
cs

 

 

  • jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        <!-- 파일업로드는 multipart/form-data -->
        <form action="" id="frm" method="post" enctype="multipart/form-data">
            <br/><br/>
            <div class="form-group">
                제목
                <input type="text" class="form-control" id="title" name="title">
                <div id="title_check"></div>
            </div>
            
            <div class="form-group">
                파일 
                <input type="file" class="form-control" id="file" name="file">
            </div>
            
            <div class="form-group">
                내용 
                <textarea class="form-control" rows="10" id="content" name="content"></textarea>
                <div id="content_check"></div>
            </div>
            
            <div class="text-center">
                <a id="sendBtn" class="btn btn-primary">작성</a>
                <a id="resetBtn" class="btn btn-danger">취소</a>
            </div>
        </form>
cs

 

 

  • javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//작성버튼을 눌렀을 경우
    $("#sendBtn").click(function(){
        var formData = new FormData($("#frm")[0]);
        
        $.ajax({
            url: "boardInsert.do",
            type: "post",
            enctype: "multipart/form-data",
            data: formData,
            processData: false,
            contentType: false,
            success: function(val){
                if(val == 1){
                    alert("글을 입력하였습니다."); location.href="/mvnschool/board.do";
                }else{
                    alert("전송 실패");
                }
            },
            error: function(e){
                alert(e);
            }
        })//ajax
    }); //sendBtn
cs

 

 

 

  • Controller

⇒ 컨트롤러에서 부를때 그냥 HttpServletRequest로 부르지말고 MultipartHttpServletRequest로 불러야함

⇒ MultipartFile 객체를 생성하여 MultipartHttpServletRequest의 getFile메소드로 불러온 파일을 저장

⇒ 저장할 경로 지정

⇒ 가져온 원본파일의 이름에 중복방지를 위해 time을 추가하고 지정한 경로에 파일 생성

⇒ db에는 그 파일의 이름이 저장됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    @RequestMapping(value="/boardInsert.do", method = RequestMethod.POST)
    @ResponseBody
    public int boardInsert(HttpServletRequest request, MultipartHttpServletRequest multiRequest,
            @ModelAttribute Board board) throws IllegalStateException, IOException{
        //글쓴이 정보 생성
        HttpSession session = request.getSession();
        String userno = (String)session.getAttribute("userno");
        User user = userDAO.userView(userno);
        String name = user.getName();
 
        //board에 글쓴이 정보를 세팅
        board.setUserno(userno);
        board.setName(name);
        
        MultipartFile mf = null;
        //파일을 업로드 하지 않는다면 fileupload 컬럼에는 그냥 null이 입력됨
        if(multiRequest.getFile("file").getSize() != 0){
            mf = multiRequest.getFile("file"); //input file로 넘어온 값
            
            //경로 지정
            String path = "D:\\kj\\mvnschool\\webapp\\WEB-INF\\upload";
            File fileDir = new File(path);
            if(!fileDir.exists()){
                fileDir.mkdirs();
            }
 
            //중복방지를 위해 time 추가
            long time = System.currentTimeMillis();
            String originFileName = mf.getOriginalFilename(); //원본 파일명
            String saveFileName = String.format("%d_%s", time, originFileName); //저장 파일명
            
            //파일 생성
            mf.transferTo(new File(path, saveFileName)); 
 
            board.setFileupload(saveFileName);
        }
        
        int result = boardDAO.boardInsert(board);
        
        return result;
    }
cs

 

 

  • dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//게시판 업로드
    public int boardInsert(Board board){
        Connection conn = null;
        PreparedStatement pstmt = null;
        int result = 0;
        
        try {
            conn = getConnection();
            String sql = "insert into board "
                    + "(bnum, userno, name, title, content, hit, regdate, replycnt, fileupload) "
                    + "values('BOA' || board_seq.nextval, ?, ?, ?, ?, 0, sysdate, 0, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, board.getUserno());
            pstmt.setString(2, board.getName());
            pstmt.setString(3, board.getTitle());
            pstmt.setString(4, board.getContent());
            pstmt.setString(5, board.getFileupload());
            result = pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeConnection(conn, pstmt);
        }
        return result;
    }
cs
 
 
 

1. 메이븐 기반 프로젝트이므로 pom.xml에 javax.mail 디펜던시 추가

 

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>
cs

 

 

2. selectbox 선택부분

  • jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<table class="table table-hover">
            <colgroup>
            <col width="5%"/>
            <col width="5%"/>
            <col width="10%"/>
            <col width="10%"/>
            <col width="40%"/>
            <col width="10%"/>
            <col width="20%"/>
        </colgroup>
        <thead>
            <tr>
                <th scope="col"><input type="checkbox" name="select_all" id="select_all" value="select_all"></th>
                <th scope="col">No.</th>
                <th scope="col">이름</th>
                <th scope="col">아이디</th>
                <th scope="col">주소</th>
                <th scope="col">전화번호</th>
                <th scope="col">이메일</th>
            </tr>
        </thead>
        <tbody>
                <c:forEach items="${list}" var="list" varStatus="st">
                    <tr>
                        <td><input type="checkbox" name="select_tch" id="select_tch" value="${list.userno}"></td>
                        <td>${rowNo-st.index}</td>
                        <td>${list.name}</td>
                        <td>${list.userid}</td>
                        <td>${list.address}</td>
                        <td>${list.phone}</td>
                        <td>${list.email}</td>
                    </tr>
                </c:forEach>
        </tbody>
</table>
cs

 

  • javascript

맨 윗줄 checkbox를 체크하면 전체선택이 되도록, 한번더 누르면 전체선택이 해제되도록 설정

 

1
2
3
4
5
6
7
8
//전체선택 구현 (id=select_all을 누르면 모든 checkbox 타입의 input box의 checked를 true로 바꿔라)
    $("#select_all").on("click",function(){
        if($("input:checkbox[id = 'select_all']").prop("checked")){
            $("input[type=checkbox]:not(:disabled)").prop("checked"true);
        }else{
            $("input[type=checkbox]:not(:disabled)").prop("checked"false);
        }
    });
cs

 

교사 승인 버튼을 눌렀을 경우 체크박스의 value (user의 userno, email값)를 배열에 담고 json형태로 바꿔서 넘기기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//교사 승인 버튼을 눌렀을경우 체크박스의 value(user의 userno), email 값을 배열에 담고 json형태로 바꿔서 넘긴다.
    $("#tchProveBtn").click(function(){
        var checkbox = $("input[name='select_tch']:checked");
        var jarr = [];
        
        $(checkbox).each(function(i){
            var tr = checkbox.parent().parent().eq(i);
            var td = tr.children();
            
            var userno = $(this).val(); //체크박스의 value값
            var email = td.eq(6).text(); //0번째부터 시작이므로 마지막 줄의 td의 값
            
            jarr.push({"userno": userno, "email": email}); //배열에 userno와 email을 담는다.
        });
        var jStr = JSON.stringify(jarr); //json형태 문자열로 바꾸기
        
        if(jarr.length >= 1){
//json형태 data를 컨트롤러로 넘긴다.
            $.ajax({
                url: "tchProve.do",
                type: "post",
                data: {
                    "jStr": jStr
                },
                success: function(val){
                    if(val>=1){
                        alert("교사 승인이 완료되었습니다.");
                        location.href="/mvnschool/tchWaitList_pre.do";
                    }
                }
            })
        }
    }); //tchProveBtn
cs

userno는 dao에서 update를 하기 위해 필요한 값이고

email은 수신자 메일주소이다.

 

 

  • Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//교사 승인 -> dao를 통해 role이 2로 업데이트되고, 해당회원의 이메일로 메일 발송
    @RequestMapping(value="tchProve.do", method = RequestMethod.POST)
    @ResponseBody
    public int tchProve(@RequestParam(value="jStr"String jStr) throws AddressException, MessagingException{
        int result = -1;
        JSONArray jsonArr = new JSONArray(jStr);

//이메일 주소들을 List에 담는다.
        List<String> emailList = new ArrayList<>();
        for(int i=0; i<jsonArr.length(); i++){
            JSONObject jsonObject = jsonArr.getJSONObject(i);
            String userno = (String) jsonObject.getString("userno");
            String email = (String) jsonObject.getString("email");
            emailList.add(email);
            result = userDAO.tchProve(userno);
        }
        
        //이메일로 메일 발송
        SendEmail.sendEmail(emailList);
        
        return result;
    }
cs

JSONArray를 통해 받아온 jStr을 다시 JSON 배열 형태로 풀어준다. 

그 배열의 크기만큼 반복문을 돌려서 JSONObject로 하나씩 뽑아낸다. 

 

userno는 dao와 연결시키고,

email은 List에 담은 후 자바메일 발송을 위해 만들어놓은 클래스의 함수와 연결시킨다.

 

 

  • dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//교사 승인
    public int tchProve(String userno){
        Connection conn = null;
        Statement st = null;
        int result = 0
        try {
            conn = getConnection();
            String sql = "update user_haksa set role =2 where userno='"+userno+"'";
            st = conn.createStatement();
            result = st.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeConnection(conn, st, null);
        }
        return result; 
    }
cs

 

 

  • SendEmail.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.mvnschool.vo;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
public class SendEmail {
    static String host = "smtp.naver.com";
    static int port = 465;
    static String username = "네이버아이디@naver.com";
    static final String password = "네이버비밀번호";
    
    static String subject = "교사 승인";
    static String contents = "교사 승인 알람 메일";
 
    public static void sendEmail(List<String> emailList) throws AddressException, MessagingException{
        //서버정보 설정
        Properties props = System.getProperties();
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", port);
        props.put("mail.smtp.auth""true");
        props.put("mail.smtp.ssl.enable""true");
        props.put("mail.smtp.ssl.trust", host);
        
        //세션 생성 & 발신자 smtp 서버 로그인 인증
        Session session = Session.getInstance(props, new javax.mail.Authenticator(){
            protected javax.mail.PasswordAuthentication getPasswordAuthentication(){
                return new javax.mail.PasswordAuthentication(username, password);
            }
        });
        session.setDebug(true); //디버그 모드
        
        //MimeMessage 생성 & 메일 세팅
        Message mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(username)); //발신자
        
        System.out.println("mailSession success");
        
        //가져온 리스트의 사이즈만큼 InternetAddress 배열 크기 정하기
        InternetAddress[] addArray = new InternetAddress[emailList.size()];
        for(int i=0; i<emailList.size(); i++){ //배열에 이메일을 저장
            addArray[i] = new InternetAddress(emailList.get(i));
        }
        mimeMessage.setRecipients(Message.RecipientType.TO, addArray);
        mimeMessage.setSubject(subject); //메일 제목
        mimeMessage.setText(contents); //메일 내용
        
        //메일 보내기
        Transport.send(mimeMessage);
        System.out.println("success sending email");
        
    }
}
cs

⇒ 자바메일 설정하는 동안 만났던 오류들
1. ssl관련 에러

("mail.smtp.ssl.enable", "true" , "mail.smtp.ssl.true", "smtp.naver.com" 처럼 설정을 해주니까 해결)


2. username과 password 관련 에러

(발신자 smtp 서버 로그인 인증을 해야함. Authenticator만들기. 관련 주석의 밑에줄)

 

3. 그 외

메일을 보낼때 mimeMessage에 addRecipients말고 setRecipients(Message.RecipientType.TO, addArray)를 하니까

(List로 가져온 메일 주소 String을 배열 []로 풀어서 저장) 잘 보내짐.

 

 

다음과 같이 subject 테이블과 attend 테이블을 조인해서 데이터를 가져온다

(rownum은 페이징 처리를 위해서 사용. dao의 sql문 안에서는 ? 로 대체하고 인자값으로 endRow와 startRow가 들어감)

1
2
3
4
5
6
7
8
9
select * from 
    (select aa.*, rownum rn from 
        (select a.subno, a.subname, a.teachername, s.cnt, count(a.subno) currentCnt, a.status
        from attend a
        join subject s
        on s.subno = a.subno 
        where stuno = 'USER1'
        group by a.subno, a.subname, a.teachername, s.cnt, a.status) aa
            where rownum<=5where rn>=1;
cs
결과값

 

 

보통 jsp에서 <table> <tr> <td> 에 값을 뿌릴때는 List<vo클래스> 로 add해서 뿌렸었는데..

저렇게 조인으로 가져오면 단일 vo클래스가 아니므로 그 방법은 사용할 수 없다.

인터넷 서치하니까 아예 vo를 또 만들던지 map을 사용하라는데.. vo를 만드는건 스프링할때 해봤으니까 map으로 사용.

 

 

  • DAO.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public List<Object> myAttendPre(int startRow, int endRow, String userno){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<Object> list = new ArrayList<>();
        
        try {
            conn = getConnection();
            String sql = "select * from "
                        + "(select aa.*, rownum rn from "
                        + "(select a.subno, a.subname, a.teachername, s.cnt, s.submemo, count(a.subno) currentCnt, a.status "
                        + "from attend a "
                        + "join subject s "
                        + "on s.subno = a.subno "
                        + "where stuno = '"+userno+"' "
                        + "group by a.subno, a.subname, a.teachername, s.cnt, s.submemo, a.status) aa "
                        + "where rownum<=?) where rn>=?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, endRow);
            pstmt.setInt(2, startRow);
            rs = pstmt.executeQuery();
            while(rs.next()){
                Map<StringString> hm = new HashMap<>();
                hm.put("status", Integer.toString(rs.getInt("status")));
                hm.put("subno", rs.getString("subno"));
                hm.put("subname", rs.getString("subname"));
                hm.put("teachername", rs.getString("teachername"));
                hm.put("cnt", Integer.toString(rs.getInt("cnt")));
                hm.put("currentCnt", rs.getString("currentCnt"));
                list.add(hm);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeConnection(conn, pstmt, rs);
        }
        return list;
    }
cs

 

맵을 while문 바깥에 선언하게 되면 당연히 key값 (status, subno, subname 등..) 이 같으므로 value값이 덮어쓰기 된다.

list에 담고나면 컨트롤러에서 model에 담고 jsp에서 원래 하던대로 el태그 안에 뿌리면 된다..

github.com/kkj0712/Moodtracker-App

 

kkj0712/Moodtracker-App

Android and JSP Application Project. Contribute to kkj0712/Moodtracker-App development by creating an account on GitHub.

github.com

 

New Dynamic Web Project로 Jsoup_test 생성

com.jsoup.test 패키지에 Test01.java 클래스 생성

 

 

https://mvnrepository.com/artifact/org.jsoup/jsoup/1.11.3

 

Maven Repository: org.jsoup » jsoup » 1.11.3

jsoup is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods. jsoup implements the WHATWG HTML5 specification, and parses HTML to the s

mvnrepository.com

에서 jsoup-1.11.3.jar 다운받아서 WEB-INF 내 lib 폴더에 붙여넣기

 

다음 사이트에서 영화 검색, 검색창 주소 복사해서 Jsou.connnet 함수 인자로 넣기


 

Test01.java

package com.jsoup.test;

import java.io.IOException;

import java.util.ArrayList;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.select.Elements;

public class Test01 {

    public static void main(String[] args) {

        try {

            Document doc=Jsoup.connect("https://search.daum.net/search?w=tot&DA=YZR&t__nil_searchbox=btn&sug=&sugo=&sq=&o=&q=%EC%98%81%ED%99%94").get();

//          System.out.println(doc);

            

            Elements movie_list=doc.select("ol.movie_list li");

//          System.out.println(movie_list);

            System.out.println("====제목====");

            Elements titleContainer=movie_list.select("div.info_tit a");

//          System.out.println(titleContainer);

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

//              System.out.println(titleContainer.get(i).text());

//          }

//          

//          System.out.println("====평점====");

            Elements scoreContainer=movie_list.select("em.rate");

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

//              System.out.println(scoreContainer.get(i).text());

//          }

            

            ArrayList<Movie> arr=new ArrayList<Movie>();

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

                Movie movie=new Movie();

                String title=titleContainer.get(i).text();

                String rate=scoreContainer.get(i).text();

                movie.setTitle(title);

                movie.setRate(rate);

                arr.add(movie);

            }

            for(Movie movie:arr) {

                System.out.println("제목:"+movie.getTitle());

                System.out.println("평점: "+movie.getRate());

                System.out.println();

            }

            

        } catch (IOException e) {

            e.printStackTrace();

        }

        

    }

}

Movie.java

 

package com.jsoup.test;

public class Movie {

    private String title;

    private String rate;

    

    public String getTitle() {

        return title == null ? "" : title.trim();

    }

    public void setTitle(String title) {

        this.title = title;

    }

    public String getRate() {

        return rate == null ? "" : rate.trim();

    }

    public void setRate(String rate) {

        this.rate = rate;

    }

}

 


손흥민의 프로필 출력하기

 

Son.java

 

package com.jsoup.test;

import java.io.IOException;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.select.Elements;

public class Son {

    public static void main(String[] args) {

        try {

            Document doc=Jsoup.connect("https://search.daum.net/search?w=tot&DA=YZR&t__nil_searchbox=btn&sug=&sugo=&sq=&o=&q=%EC%86%90%ED%9D%A5%EB%AF%BC").get();

            Elements container=doc.select("div.type_thumb_s160 dl");

            Elements title=doc.select("div.type_thumb_s160 dl dt");

            Elements data=doc.select("div.type_thumb_s160 dl dd");

            System.out.println("손흥민에 대한 정보");

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

                String titleText=title.get(i).text();

                String dataText=data.get(i).text();

                System.out.println(titleText+":"+dataText);

            }

        

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

 

 


 

최근 로또 5회차의 당첨번호 출력하기

 

Lottery2.java

package com.jsoup.test;

import java.io.IOException;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

public class Lottery2 {

    public static void main(String[] args) {

        Document doc;

        try {

            doc=Jsoup.connect("https://m.dhlottery.co.kr/common.do?method=main").get();

            Elements lottoNo=doc.select("#lottoDrwNo"); //회차

            Elements lottoDrwNo=doc.select("div.prizeresult"); //로또번호

        

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

                System.out.println(lottoNo.get(i).text()+" 당첨번호"); //회차

                //회차에 해당하는 로또 번호

                System.out.println(lottoDrwNo.get(i).select("span").text());

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}



 

환율 출력하기

 

Exchage.java

 

package com.jsoup.test;

import java.io.IOException;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

public class Exchage {

    public static void main(String[] args) {

        Document doc;

        try {

            doc=Jsoup.connect("https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=%ED%99%98%EC%9C%A8").get();

            Elements table=doc.select("table.rate_table_info");

            Elements tr=table.select("tbody tr");

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

                String country=tr.get(i).select("th a").text();

                String ratio=tr.get(i).select("td").first().text();

                System.out.println(country+"=>"+ratio);

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}


 

<상세보기>

상세보기는 num이 파라미터 값이다. 그리고 돌아오는 값은 DTO이다.

따라서 ObjectMapper.xml 에서 parameterType, resultType 둘다 써줘야한다.

 

addrList.jsp에서 다음과 같이 제목을 클릭하면 상세보기로 넘어가도록 함

<td><a href="viewAction.amy?num=${arr.num}">${arr.name}</a></td>

 


ViewAction.java

 

package org.addrMy.action;

import java.io.IOException;

import java.util.List;

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 org.addrMy.config.MybatisManager;

import org.addrMy.model.AddressVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

/**

 * Servlet implementation class ViewAction

 */

@WebServlet("/address_my/viewAction.amy")

public class ViewAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public ViewAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

        int num=Integer.parseInt(request.getParameter("num"));

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        AddressVO vo=sqlSession.selectOne("viewData",num);

        request.setAttribute("address", vo);

        RequestDispatcher rd=request.getRequestDispatcher("arrView.jsp");

        rd.forward(request, response);

    }

    /**

     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

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

        doGet(request, response);

    }

}


addrView.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="updateAction.amy" method="post" name="frm">

<input type="hidden" name="num" value="${address.num}">

<table>

    <tr>

        <td colspan="2">주소록 수정하기</td>

    </tr>

    <tr>

        <td>이름</td>

        <td><input type="text" name="name" value="${address.name}"></td>

    </tr>

    <tr>

        <td>우편번호 </td>

        <td><input type="text" name="zipcode" size=10 value="${address.zipcode}">

        <input type="button" name="search" value="검색" onclick="zipfinder()"></td>

    <tr>

        <td>주소

        <td><input type="text" name="addr" size=30 value="${address.addr}"></td>

    </tr>

    <tr>

        <td>전화번호</td>

        <td><input type="text" name="tel" value="${address.tel}"></td>

    </tr>

    <tr>

        <td colspan="2">

        <input type="submit" value="수정" onclick="location.href='updateAction.amy?num=${address.num}'">

        <input type="button" value="삭제" onclick="location.href='deleteAction.amy?num=${address.num}'"> <!-- del()이라는 함수를 부른다. -->

        <input type="reset" value="취소">

        </td>

    </tr>

</table>

</form>

</body>

</html>

 


 

<수정하기>

상세보기 후 수정 버튼을 눌러서 수정되도록.

받아오는 값들을 다 써주고 Address vo 객체에 담는다. vo 객체를 들고 업데이트를 시켜야한다. 그 후 전체보기로 넘어간다.

 

UpdateAction.java

 

package org.addrMy.action;

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 org.addrMy.config.MybatisManager;

import org.addrMy.model.AddressVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

/**

 * Servlet implementation class UpdateAction

 */

@WebServlet("/address_my/updateAction.amy")

public class UpdateAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public UpdateAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        

        

    }

    /**

     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

        AddressVO vo=new AddressVO();

        vo.setAddr(request.getParameter("addr"));

        vo.setName(request.getParameter("name"));

        vo.setNum(Integer.parseInt(request.getParameter("num")));

        vo.setTel(request.getParameter("tel"));

        vo.setZipcode(request.getParameter("zipcode"));

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        sqlSession.update("updateData",vo);

        sqlSession.commit();

        response.sendRedirect("listAction.amy");

    }

}

 

<삭제하기>

 

DeleteAction.java

 

package org.addrMy.action;

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 org.addrMy.config.MybatisManager;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

/**

 * Servlet implementation class DeleteAction

 */

@WebServlet("/address_my/deleteAction.amy")

public class DeleteAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public DeleteAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

        int num=Integer.parseInt(request.getParameter("num"));

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        sqlSession.delete("deleteData", num);

        sqlSession.commit();

        response.sendRedirect("listAction.amy");

    }

    /**

     * @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);

    }

}

 


 

ObjectMapper.xml 주의점

 

<경로지정 혹은 형 지정>

ObjectMapper.xml 에 resulttype을 쓸때 경로가 아니므로 . 을 쓴다.

resultType="org/addrMy/model/AddressVO" 가 아닌

resultType="org.addrMy.model.AddressVO" 이다.

 

=>이름이 너무 기므로 별칭으로 대신 써주고 싶다면 Configuration.xml을 수정해야함

<typeAliases>, <typeAlias type="타입이름" alias="별칭">

 

ObjectMapper.xml에 다음과 같이 쓸 수 있다.

resultType="별칭"

 

<like 연산자 쓸때 주의점>

sql문에 like가 들어갈때  #{변수}는 홑따옴표를 포함하고 있기 때문에

'%#{dong}%' 이렇게 쓰면 안되고  '%'||#{dong}||'%' 이렇게 써야함.

 


 

<우편번호>

이번엔 API를 쓰지 않고 전국 주소 엑셀을 SQL에서 임포트하여 우편번호 DB를 만들었다.

ZipcodeVO.java

 

package org.addrMy.model;

public class ZipcodeVO {

    private String zipcode;

    private String sido;

    private String gugun;

    private String dong;

    private String bunji;

    private int seq;

    

    public String getZipcode() {

        return zipcode == null ? "" : zipcode.trim();

    }

    public void setZipcode(String zipcode) {

        this.zipcode = zipcode;

    }

    public String getSido() {

        return sido == null ? "" : sido.trim();

    }

    public void setSido(String sido) {

        this.sido = sido;

    }

    public String getGugun() {

        return gugun == null ? "" : gugun.trim();

    }

    public void setGugun(String gugun) {

        this.gugun = gugun;

    }

    public String getDong() {

        return dong == null ? "" : dong.trim();

    }

    public void setDong(String dong) {

        this.dong = dong;

    }

    public String getBunji() {

        return bunji == null ? "" : bunji.trim();

    }

    public void setBunji(String bunji) {

        this.bunji = bunji;

    }

    public int getSeq() {

        return seq;

    }

    public void setSeq(int seq) {

        this.seq = seq;

    }

}

zipCheck.jsp에서 비동기함수 $.post를 사용해서 ZipAction.java액션으로 갔다. Mybatis를 수행후 결과값이 List에 담겨있다. 그 값을 가지고 어디로 출력할 것인가? zipCheck.jsp에 다시 돌아온다. 비동기함수는 자신에게 돌아오는 함수이다. 

그런데 ZipAction.java에서 dispatcher를 사용하면 다른 페이지로 이동한다.

따라서 JSON 방법을 사용해서 값을 가지고, 데이터를 기다리고 있는 jsp에 가야한다.

예전에는 json simple jar를 이용하여 JSON object, array를 만들었는데.. 이번엔 gson-2.8.5.jar를 maven repository에서 다운받아 사용한다. 

https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5

 

Maven Repository: com.google.code.gson » gson » 2.8.5

com.google.code.gson gson 2.8.5 // https://mvnrepository.com/artifact/com.google.code.gson/gson compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5' // https://mvnrepository.com/artifact/com.google.code.gson/gson libraryDependencies += "co

mvnrepository.com

 

ZipAction.java

 

package org.addrMy.action;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.HashMap;

import java.util.List;

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 org.addrMy.config.MybatisManager;

import org.addrMy.model.ZipcodeVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import com.google.gson.Gson;

/**

 * Servlet implementation class ZipAction

 */

@WebServlet("/address_my/zipAction.amy")

public class ZipAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public ZipAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        RequestDispatcher rd=request.getRequestDispatcher("zipCheck.jsp");

        rd.forward(request, response);

    }

    /**

     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

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

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        List<ZipcodeVO> zarr=sqlSession.selectList("zipData", dong);

        

        HashMap<String, Object> hm=new HashMap<String, Object>();

        hm.put("zarr",zarr);

        //java->json형태로 값 출력

        Gson gson=new Gson();

        String obj=gson.toJson(hm); //자바 오브젝을 json으로 만들어준다.

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out=response.getWriter();

        out.println(obj.toString());

    }

}

zipCheck.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>

<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<script>

$(document).ready(function(){

    $("#send").click(function(){

        if($("#dong").val()==""){

            alert("동이름 입력");

            return false;

        }

        $.post("zipAction.amy",

              {"dong":$("#dong").val()},

              function(data){

                var res=JSON.parse(data); //JSON으로 부른게 아니기 때문에 파싱 필요

                var htmlStr="<table>";

                $.each(res.zarr,function(key,val){

                    var bunji=val.bunji==null?"":val.bunji;

                    var gugun=val.gugun==null?"":val.gugun;

                    htmlStr+="<tr>";

                    htmlStr+="<td>"+val.zipcode+"</td>";

                    htmlStr+="<td>"+val.sido+"</td>";

                    htmlStr+="<td>"+gugun+"</td>";

                    htmlStr+="<td>"+val.dong+"</td>";

                    htmlStr+="<td>"+bunji+"</td>";

                    htmlStr+="</tr>";

                });//each

                htmlStr+="</table>";

                $("#area").html(htmlStr);

             }//콜백함수

        )//post

    })//send

    

    $("#area").on("click","tr",function(){

        var address=$("td:eq(1)", this).text()+" "+

                    $("td:eq(2)", this).text()+" "+

                    $("td:eq(3)", this).text()+" "+

                    $("td:eq(4)", this).text();

        $(opener.document).find("#zipcode").val($("td:eq(0)",this).text());

        $(opener.document).find("#addr").val(address);

        self.close();

    })//area

})//document

</script>

</head>

<body>

<table>

    <tr>

        <td> 동이름입력: <input type="text" name="dong" id="dong">

        <input type="button" value="검색" id="send">

        </td>

    </tr>

    <tr>

        <td>*주소를 클릭하면 주소록에 자동 입력 됩니다</td>

    </tr>

</table>

<div id="area"></div>

</body>

</html>

 

 


 

<검색>

field값과 word값을 받아와서 selectList에 같이 들고 가야하는데 selectList는 Stirng 두개를 달고 가지 못한다. 따라서 해쉬맵에 field와 word를 저장한다.

그리고 List로 돌아온 검색결과를 뿌리기 위해 해쉬맵을 하나 더 만들어서 저장하고 gson을 이용하여 JSON으로 형변환후 toString으로 다시 돌려준다.

 

 

addrList.jsp 에서 검색부분을 삽입

addrList.jsp

<div align="left">

    <form name="search" id="search">

        <select name="field" id="field">

            <option value="name">이름</option>

            <option value="tel">전화</option>

        </select>

        <input type="text" name="word" id="word">

        <input type="button" value="검색" id="btnSearch">

    </form>

</div>

검색 버튼을 누르면 검색 실행

$(document).ready(function(){

    $("#btnSearch").click(function(){

        $.getJSON("searchAction.amy",

                 {"field":$("#field").val(), "word":$("#word").val()},

                 function(data){

                         $("#count").html("개수:"+data.count);

                        var htmlStr="";

                    $.each(data.arr, function(key,val){

                        htmlStr+="<tr>";

                        htmlStr+="<td>순서</td>";

                        htmlStr+="<td>"+val.num+"</td>";

                        htmlStr+="<td>"+val.name+"</td>";

                        htmlStr+="<td>"+val.addr+"</td>";

                        htmlStr+="<td>"+val.tel+"</td>";

                        htmlStr+="<td onclick='javascript:fdelete("+val.num+")'>"+삭제+"</td>";

                        htmlStr+="</tr>";

                    });

                        $("table tbody").html(htmlStr);

                }

        ); //getJSON

    })//btnSearch

});//document

 


SearchAction.java

 

package org.addrMy.action;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.HashMap;

import java.util.List;

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.addrMy.config.MybatisManager;

import org.addrMy.model.AddressVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import com.google.gson.Gson;

/**

 * Servlet implementation class SearchAction

 */

@WebServlet("/address_my/searchAction.amy")

public class SearchAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public SearchAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

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

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

        HashMap<String, String> map=new HashMap<String, String>();

        map.put("field", field);

        map.put("word", word);

        

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        List<AddressVO> arr=sqlSession.selectList("searchData", map);

        int count=sqlSession.selectOne("countSearchData",map);

        

        HashMap<String,Object> hm=new HashMap<>();

        hm.put("arr",arr);

        hm.put("count",count);

        Gson gson=new Gson();

        String obj=gson.toJson(hm);

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out=response.getWriter();

        out.println(obj.toString());

    }

    /**

     * @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);

    }

}

 


 

ajax로 삭제하기

 

addrList.jsp의 결과 테이블 td값에 자바스크립트 함수 포함

<td onclick="fdelete(${arr.num})">삭제</td>

function fdelete(num){

    if(confirm("정말 삭제하시겠습니까?")){

        $.getJSON("deleteAjaxAction.amy",

                 {"num":num},

                 function(data){

                     $("#count").html("개수:"+data.count);

                        var htmlStr="";

                     $.each(data.arr, function(key,val){

                        htmlStr+="<tr>";

                        htmlStr+="<td>순서</td>";

                        htmlStr+="<td>"+val.num+"</td>";

                        htmlStr+="<td><a href='viewAction.amy?num="+val.num+"'>"+val.name+"</a></td>";

                        htmlStr+="<td>"+val.addr+"</td>";

                        htmlStr+="<td>"+val.tel+"</td>";

                        htmlStr+="<td onclick='fdelete("+val.num+")'>삭제</td>";

                        htmlStr+="</tr>";

                    });

                        $("table tbody").html(htmlStr);

                 }

        )//getJSON

    }

}//fdelete

위 사항들을 종합한 ObjectMApper.xml 의 sql문들

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

 <mapper namespace="org.addrMy.config.ObjectMapper">

 <sql id="search">

    <where>

        <if test="word!=null and field=='name'">

            <!-- name like '%'||#{word}||'%' -->

            name like '%${word}%'

        </if>

        <if test="word!=null and field=='tel'">

            tel like '%'||#{word}||'%'

        </if>

    </where>

 </sql>

 

 <!-- insert -->

 <insert id="insertData" parameterType="org.addrMy.model.AddressVO">

    insert into address(num, name, zipcode, addr, tel)

    values(address_seq.nextval,#{name},#{zipcode},#{addr},#{tel})

 </insert>

 

 <!-- all select -->

 <select id="listData" resultType="org.addrMy.model.AddressVO">

    select * from address

 </select>

 

 <!-- count -->

 <select id="countData" resultType="Integer">

    select count(*) from address

 </select>

 

 <!-- view -->

 <select id="viewData" parameterType="Integer" resultType="org.addrMy.model.AddressVO">

    select * from address where num=#{num}

 </select>

 

 <!-- update -->

 <update id="updateData" parameterType="org.addrMy.model.AddressVO">

    update address set name=#{name}, zipcode=#{zipcode}, addr=#{addr}, tel=#{tel} where num=#{num}

 </update>

 

 <!-- delete -->

 <delete id="deleteData" parameterType="Integer">

    delete from address where num=#{num}

 </delete>

 

 <!-- zipcode select -->

 <select id="zipData" parameterType="String" resultType="zipvo">

    select * from zipcode where dong like '%'||#{dong}||'%'

 </select>

 

 <!-- search -->

 <select id="searchData" parameterType="java.util.Map" resultType="org.addrMy.model.AddressVO">

    select * from address

    <include refid="search"></include>

 </select>

 

 

 <!-- countSearchData -->

 <select id="countSearchData" resultType="Integer" parameterType="java.util.Map">

    select count(*) from address

    <include refid="search"></include>

 </select>

 </mapper>

 

 

  • DAO 대신 MyBatis 사용하기 (DB연결, sql문 처리)


  • New Dynamic Web Project로 0_AddressMybatis 생성

  • WebContent에 address_my 폴더 생성후 addressInsert.jsp 만들기

 

addressInsert.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>

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

<script>

$(function(){

    $("#btn").on("click",function(){

        if($("#name").val()==""){

            alert("이름을 입력하세요");

            return false;

        }

        if($("#zipcode").val()==""){

            alert("우편번호을 입력하세요");

            return false;

        }

        if($("#addr").val()==""){

            alert("주소를 입력하세요");

            return false;

        }

        if($("#tel").val()==""){

            alert("전화번호를 입력하세요");

            return false;

        }

        frm.submit();

    });

})

function zipfinder(){

    window.open("zipAction.amy","","width=700 height=400");   

}

</script>

</head>

<body>

<a href="list.jsp">전체보기</a> <br>

<form action="insertAction.amy" method="post" name="frm" id="frm">

<table>

    <tr>

        <td colspan="2">주소록 등록하기</td>

    </tr>

    <tr>

        <td>이름</td>

        <td><input type="text" name="name" id="name" size=15></td>

    </tr>

    <tr>

        <td>우편번호 </td>

        <td><input type="text" name="zipcode" id="zipcode" size=10>

        <input type="button" name="search" value="검색" onclick="zipfinder()"></td>

    <tr>

        <td>주소

        <td colspan="2"><input type="text" name="addr" id="addr" size=30>

        </td>

    </tr>

    </tr>

        <td>전화번호</td>

        <td colspan="2"><input type="text" name="tel" id="tel" size=15></td>

    <tr>

        <td colspan="2">

        <input type="submit" value="등록">

        <input type="reset" value="취소"></td>

    </tr>

</table>

</form>

</body>

</html>

 

  • src에 org.addrMy.action 패키지 생성 후 InsertAction.java 서블릿 만들기.

  • 이 서블릿에 Mybatis를 연결할 것이다.

  • AddressVO 클래스의 vo객체를 생성하고 파라미터로 넘어온 값들을 저장할 것이다.

 


  • org.addrMy.model 패키지. AddressVO.java 생성

AddressVO.java 

package org.addrMy.model;

public class AddressVO {

    private int num;

    private String name;

    private String addr;

    private String tel;

    private String zipcode;

    

    public int getNum() {

        return num;

    }

    public void setNum(int num) {

        this.num = num;

    }

    public String getName() {

        return name == null ? "" : name.trim();

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getAddr() {

        return addr == null ? "" : addr.trim();

    }

    public void setAddr(String addr) {

        this.addr = addr;

    }

    public String getTel() {

        return tel == null ? "" : tel.trim();

    }

    public void setTel(String tel) {

        this.tel = tel;

    }

    public String getZipcode() {

        return zipcode == null ? "" : zipcode.trim();

    }

    public void setZipcode(String zipcode) {

        this.zipcode = zipcode;

    }

}

 

 


  • 이번에는 DAO를 만들지 않고 Mybatis를 이용하여 sql문을 처리한다.

  • org.addrMy.config 패키지를 생성하고 Configuration.xml 만들기 (New File)

 

 

 

Configuration.xml

(MyBatis-3-User-Guide_ko.pdf 에서 복사 붙여넣기)

https://kldp.net/fwko/release/3410-MyBatis-3-User-Guide_ko.pdf

 

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration

 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-config.dtd">

 

 <configuration>

 <properties resource="org/addrMy/config/jdbc.properties"/>

  <environments default="development">

     <environment id="development">

     <transactionManager type="JDBC"/>

     <dataSource type="POOLED">

         <property name="driver" value="${driver}"/>

         <property name="url" value="${url}"/>

         <property name="username" value="${username}"/>

         <property name="password" value="${password}"/>

     </dataSource>

     </environment>

  </environments>

  <mappers>

    <mapper resource="org/addrMy/config/ObjectMapper.xml"/>

  </mappers>

 </configuration>


${변수} 는 어딘가에서 내보낸 값들이 저장된다. 어디서 내보낸 걸까?

같은 패키지 경로에 jdbc.properties를 New File로 생성한다.

 

jdbc.properties

driver = oracle.jdbc.driver.OracleDriver

url = jdbc:oracle:thin:@localhost:1521:xe

username = scott

password = 1234

 


 

https://mvnrepository.com/artifact/org.mybatis/mybatis/3.4.6

 

Maven Repository: org.mybatis » mybatis » 3.4.6

 

mvnrepository.com

에서 MyBatis.jar 파일을 다운받는다. 3.4.6버전이다. WEB-INF의 lib 폴더에 붙여넣는다.

 

 


 

org.addrMy.config 안에 MybatisManager.java 클래스를 생성한다.

 

MybatisManager.java

package org.addrMy.config;

import java.io.IOException;

import java.io.Reader;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisManager {

    public static SqlSessionFactory sqlMapper;

    static {

        String resource="org/addrMy/config/Configuration.xml";

        Reader reader;

        try {

            reader=Resources.getResourceAsReader(resource);

            sqlMapper=new SqlSessionFactoryBuilder().build(reader);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    public static SqlSessionFactory getSqlMapper() {

        return sqlMapper;

    }

}

여기서 Resources는 ibatis라 적힌것을 임포트 해야한다.

 


 

InsertAction.java

package org.addrMy.action;

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 org.addrMy.config.MybatisManager;

import org.addrMy.model.AddressVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

/**

 * Servlet implementation class InsertAction

 */

@WebServlet("/address_my/insertAction.amy")

public class InsertAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public InsertAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        RequestDispatcher rd=request.getRequestDispatcher("addressInsert.jsp");

        rd.forward(request, response);

    }

    /**

     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

        AddressVO vo=new AddressVO();

        vo.setName(request.getParameter("name"));

        vo.setAddr(request.getParameter("addr"));

        vo.setNum(Integer.parseInt(request.getParameter("num")));

        vo.setTel(request.getParameter("tel"));

        vo.setZipcode(request.getParameter("zipcode"));

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

sqlSession.insert("insertData", vo);

        sqlSession.commit();

response.sendRedirect("listAction.amy");

    }

}

 


 

org.addrMy.config 패키지 내에 ObjectMapper.xml 생성

Mybatis 가이드북에서 mapper.dtd 복사 붙여넣기

 

ObjectMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

 <mapper namespace="org.addrMy.config.ObjectMapper">

 

 <insert id="insertData" parameterType="org.addrMy.model.AddressVO">

  insert into address(num, name, zipcode, addr, tel)

  values(address_seq.nextval,#{name},#{zipcode},#{addr},#{tel})

 </insert>

 <!-- all select -->

 <select id="listData" resultType="org.addrMy.model.AddressVO">

    select * from address

 </select>

 

 <!-- count -->

 <select id="countData" resultType="Integer">

    select count(*) from address

 </select>

 </mapper>

 

ListAction.java

 

package org.addrMy.action;

import java.io.IOException;

import java.util.List;

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 org.addrMy.config.MybatisManager;

import org.addrMy.model.AddressVO;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import sun.rmi.server.Dispatcher;

/**

 * Servlet implementation class ListAction

 */

@WebServlet("/address_my/listAction.amy")

public class ListAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public ListAction() {

        super();

        // TODO Auto-generated constructor stub

    }

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

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

        request.setCharacterEncoding("utf-8");

        SqlSessionFactory sqlMapper=MybatisManager.getSqlMapper();

        SqlSession sqlSession=sqlMapper.openSession(ExecutorType.REUSE);

        List<AddressVO> arr=sqlSession.selectList("listData");

        int count=(Integer)sqlSession.selectOne("countData");

        request.setAttribute("arr", arr);

        request.setAttribute("count", count);

        RequestDispatcher rd=request.getRequestDispatcher("addrList.jsp");

        rd.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);

    }

}

 

 

addrList.jsp

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

<table>

<div align="left">

    <a href="insertAction.amy">글쓰기 <a/>/ 개수 (${count}) </span>

</div>

    <thead>

        <tr>

            <td>번호</td>

            <td>이름</td>

            <td>주소</td>

            <td>전화번호</td>

        </tr>

    </thead>

    <tbody>

    <c:forEach items="${arr}" var="arr">

        <tr>

            <td>${arr.num}</td>

            <td><a href="detail.do?num=${arr.num}">${arr.name}</a></td>

            <td>${arr.addr}</td>

            <td>${arr.tel}</td>

        </tr>

    </c:forEach>

    </tbody>

</table>

    <select name="field" id="field">

    <option value="name">이름</option>

    <option value="tel">전화</option>

    </select>

    <input type="text" name="word" id="word">

    <input type="button" value="검색" id="searchBtn">

</body>

</html>

ListAction.java를 실행하면 목록이 보인다.

이전글

https://amongthestar.tistory.com/152?category=411827

 

JSP 개인프로젝트-영어 학습 사이트 만들기 (수강후기 상세보기 및 수정 삭제, 댓글 입력 및 삭제)

이전글 https://amongthestar.tistory.com/151?category=411827 JSP 개인프로젝트-영어 학습 사이트 만들기 (수강후기 게시판 전체보기, 게시글 입력) 이전글 https://amongthestar.tistory.com/150 JSP 개인프로..

amongthestar.tistory.com

 


이번에 포스팅할 내용은 강의 상세보기 화면에서 "등록하기" 버튼을 눌렀을때 생기는 장바구니 담기 기능에 대해서다.

장바구니는 DB도 따로 있으니 DTO도 따로 생성했다.

 

WCartDTO.java

package com.wmember.model;

public class WCartDTO {
	private int cartnum;
	private int classnum;
	private String classname;
	private String userid;
	
	public int getCartnum() {
		return cartnum;
	}
	public void setCartnum(int cartnum) {
		this.cartnum = cartnum;
	}
	public int getClassnum() {
		return classnum;
	}
	public void setClassnum(int classnum) {
		this.classnum = classnum;
	}
	public String getClassname() {
		return classname == null ? "" : classname.trim();
	}
	public void setClassname(String classname) {
		this.classname = classname;
	}
	public String getUserid() {
		return userid == null ? "" : userid.trim();
	}
	public void setUserid(String userid) {
		this.userid = userid;
	}
}

강의 상세보기 화면에서 "등록하기" 버튼을 눌렀을때의 로직은 $.ajax함수를 이용했다.

 

//등록하기 클릭
	$("#subscribe").click(function(){
		if(${sessionScope.userid==null}){
			alert("로그인 필요");
			location.href="/Tutoring/member/login";
		}else{
			if(confirm("장바구니에 추가하시겠습니까?")){
				//장바구니에 있는지 확인
				$.ajax({
					type : "post",
					url  : "/Tutoring/class/cartCheck",
					data : {"classnum":$("#classnum").val(), "userid":$("#userid").val()},
					success : function(value){
						if(value.trim()=="1"){
							alert("이미 장바구니에 있는 강의입니다.");
						}else{
							$.ajax({
								  type:    "post",
				                  url :    "/Tutoring/class/cartInsert",
				                  data:    {"classnum":$("#classnum").val(), "userid":$("#userid").val(), "classname":$("#classname").val()},
				                  success:function(d){
				                	   if(d.trim()=="1"){
					                	   alert("장바구니에 강의가 담겼습니다!");
					                	   if(confirm("장바구니로 이동하시겠습니까?")){
					                		   location.href="/Tutoring/member/cartList.jsp";
					                	   }
				                	   }
				                  },
				                  error: function(e){
				                       alert("error:"+e);
				                  }
							})//ajax	
						}
					},
					error: function(e){
						alert("error:"+e);
					}
				})//ajax
			}//if
		}//else
	})//subscribe

 

가장먼저 로그인을 하도록 유도하고, 로그인이 되어있다면 카드에 있는지 확인하는 cartCheck을 수행한다.

동일한 강의일 경우 장바구니에 1개만 추가될 수 있기 때문이다. 

 

cartCheck을 수행하고 나면 장바구니에 추가할 수 있다. 추가 후에는 다음과 같은 메시지들이 뜬다. 

 


WCartCheck.java

(장바구니에 있는 확인하는 서블릿. 경로는 "/Tutoring/class/cartCheck"이다.)

 

package com.wclass.action;

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.wmember.model.WCartDAO;
import com.wmember.model.WCartDTO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 RequestDispatcher rd=request.getRequestDispatcher("courseDetail.jsp");
         rd.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
        int classnum=Integer.parseInt(request.getParameter("classnum"));
        String userid=request.getParameter("userid");
        WCartDAO dao=WCartDAO.getInstance();
        int flag=dao.cartCheck(classnum, userid); //이미 userid에 classnum이 동일하게 있다면 flag=1;
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println(flag);
	}

}

 

파라미터 값으로 받아온 강의번호와 아이디를 인자로하여 WCartDAO.java에서 cartCheck 메소드를 수행한다. 반환값을 받아서 다시 ajax으로 이동한다.

 


<WCartDAO.java에서 cartCheck 메소드>

 

//디비셋팅
	private static WCartDAO instance=new WCartDAO();
	public static WCartDAO getInstance() {
		return instance;
	}
	private Connection getConnection() throws Exception{
		Context initCtx=new InitialContext();
		Context envCtx=(Context) initCtx.lookup("java:comp/env");
		DataSource ds=(DataSource) envCtx.lookup("jdbc/wiser"); //context.xml의 name을 jdbc/member로 바꾸기
		return ds.getConnection();
	}

//장바구니 체크
	public int cartCheck(int classnum, String userid) {
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		int flag=-1;
		try {
			con=getConnection();
			String sql="select classnum, classname from wcart where userid='"+userid+"'";
			st=con.createStatement();
			rs=st.executeQuery(sql);
			if(rs.next()) { //id 맞음
				if(rs.getInt("classnum")==classnum) { //비번 일치
					flag=1;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return flag;
	}
    
//닫기 closeConnection
	private void closeConnection(Connection con, PreparedStatement ps) {
		try {
			if(ps!=null) ps.close();
			if(con!=null) con.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
	}
	private void closeConnection(Connection con, Statement st, ResultSet rs) {
		try {
			if(st!=null) st.close();
			if(con!=null) con.close();
			if(rs!=null) rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
	}

 


cartCheck후 리턴된 flag 값이 1일 경우 장바구니에 있는 강의라는 메시지가 출력되고,

그게 아닐 경우 장바구니에 추가하는 cartInsert를 실행한다.

success : function(value){
	if(value.trim()=="1"){
		alert("이미 장바구니에 있는 강의입니다.");
	}else{
		$.ajax({
		type:    "post",
		url :    "/Tutoring/class/cartInsert",
		data:    {"classnum":$("#classnum").val(), "userid":$("#userid").val(), "classname":$("#classname").val()},
		success:function(d){
          if(d.trim()=="1"){
            alert("장바구니에 강의가 담겼습니다!");
            if(confirm("장바구니로 이동하시겠습니까?")){
            	location.href="/Tutoring/member/cartList.jsp";
          		}
			}
        },
        error: function(e){
            alert("error:"+e);
        }
		})//ajax	
	}
},

 


WCartInsert.java

(장바구니 추가 진행 서블릿. 경로는 "/Tutoring/class/cartInsert"이다.)

 

package com.wclass.action;

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.wmember.model.WCartDAO;
import com.wmember.model.WCartDTO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher rd=request.getRequestDispatcher("courseDetail.jsp");
        rd.forward(request, response);
    }
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        WCartDTO cart=new WCartDTO();
        cart.setClassname(request.getParameter("classname"));
        cart.setClassnum(Integer.parseInt(request.getParameter("classnum")));
        cart.setUserid(request.getParameter("userid"));
        WCartDAO dao=WCartDAO.getInstance();
        int flag=dao.cartInsert(cart);
        PrintWriter out = response.getWriter();
        out.println(flag);
    }
}

 

파라미터 값으로 받아온 강의이름, 강의번호, 아이디를 WCartDTO형의 cart객체에 담고 WCartDAO.java의 cartInsert메소드를 수행한다. 리턴값을 내보낸다.

 

 


<WCartDAO.java의 cartInsert메소드>

 

//장바구니 추가
	public int cartInsert(WCartDTO vo) {
		Connection con=null;
		PreparedStatement ps=null;
		int flag=0;
		
		try {
			con=getConnection();
			String sql="INSERT INTO wcart(cartnum, classnum, userid, classname) VALUES(wcart_seq.nextval,?,?,?)";
			ps=con.prepareStatement(sql);
			ps.setInt(1, vo.getClassnum());
			ps.setString(2, vo.getUserid());
			ps.setString(3, vo.getClassname());
			flag=ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps);
		}
		return flag;
	}

 

장바구니에 추가가 되었다면 int 형의 flag 값이 1이 된다.

 

 


flag 값이 1이라면 장바구니에 강의가 담겼습니다! 메시지가 출력된다. 그리고 장바구니로 이동하겠냐는 confirm창에서 확인을 누르면 cartList.jsp로 이동한다.

success:function(d){
      if(d.trim()=="1"){
        alert("장바구니에 강의가 담겼습니다!");
        if(confirm("장바구니로 이동하시겠습니까?")){
        location.href="/Tutoring/member/cartList.jsp";
      }
	}
},

cartList.jsp

장바구니 리스트를 getJSON을 통해 불러온다.

 

$(document).ready(function(){
	//장바구니 리스트를 불러옴
	$.getJSON("/Tutoring/member/cartList", 
				{userid:$("#userid").val()}, 
				function(d){
					var htmlStr="<table class='table table-hover table-bordered table-sm'>";
						htmlStr+="<thead><tr>";
		            	htmlStr+="<th style='width: 10%; text-align: center;'>강의 번호</th>";
		            	htmlStr+="<th style='text-align: center;'>강의명</th>";
		            	htmlStr+="<th style='width: 10%; text-align: center'>삭제</th>";
		            	htmlStr+="</tr></thead>";
		            	htmlStr+="<tbody>";
					$.each(d.carr, function(key, val){ 
		            	htmlStr+="<tr>";
	            		htmlStr+="<td>"+val.cartnum+"</td>";
	            		htmlStr+="<td>"+val.classname+"</td>";
	            		htmlStr+="<td style='text-align: center;'><a href='javascript:cartdel("+val.cartnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";
						htmlStr+="</tr>";
					})
						htmlStr+="</tbody></table>";
						$(".back2").html(htmlStr);
				}
	)
})

 


WCartList.java

(장바구니 리스트 기능을 구현하는 서블릿. 경로는 "/Tutoring/member/cartList"이다.)

package com.wclass.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

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 org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.wmember.model.WCartDAO;
import com.wmember.model.WCartDTO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String userid=request.getParameter("userid");
		WCartDAO dao=WCartDAO.getInstance();
		ArrayList<WCartDTO> arr= dao.cartList(userid);
		
		JSONObject mainObj=new JSONObject();
		JSONArray jarr=new JSONArray();
		
		for(WCartDTO cd:arr) {
			JSONObject obj=new JSONObject();
			obj.put("userid", cd.getUserid());
			obj.put("cartnum", cd.getCartnum());
			obj.put("classnum", cd.getClassnum());
			obj.put("classname", cd.getClassname());
			jarr.add(obj);
		}
		mainObj.put("carr", jarr);
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(mainObj.toString());
	}

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

}

 

WCartDAO의 cartList 메소드를 수행하고 arr 객체에 담는다. 그 arr 객체를 다시 JSONObject과 JSONArray로 처리하고 object 객체를 내보낸다.

 


<WCartDAO의 cartList 메소드>

 

//장바구니 전체보기
	public ArrayList<WCartDTO> cartList(String userid) {
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		ArrayList<WCartDTO>arr=new ArrayList<WCartDTO>();
		
		try {
			con=getConnection();
			String sql="select * from wcart where userid='"+userid+"'";
			st=con.createStatement();
			rs=st.executeQuery(sql);
			while(rs.next()) {
				WCartDTO dto=new WCartDTO();
				dto.setCartnum(rs.getInt("cartnum"));
				dto.setClassnum(rs.getInt("classnum"));
				dto.setUserid(rs.getString("userid"));
				dto.setClassname(rs.getString("classname"));
				arr.add(dto);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return arr;
	}

 

cartList.jsp에서 불러온 장바구니 목록을 볼 수 있다.

 


장바구니에서 해당 강의를 삭제하는 것은 어떻게 구현할 수 있을까?

자신이 쓴 글이면 삭제할수 있도록 휴지통 아이콘이 나타난다. 그 아이콘에 자바스크립트 함수를 붙여넣는다.

 

htmlStr+="<td style='text-align: center;'><a href='javascript:cartdel("+val.cartnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";

 

장바구니 삭제함수가 호출되면 getJSON을 이용하여 cartDelete 경로로 이동한다. 삭제되고 나서도 나머지 목록이 보여야하므로 $.each로 값을 출력한다.

//장바구니 삭제함수
function cartdel(cartnum){
	if(confirm("장바구니에서 삭제하시겠습니까?")){
		$.getJSON("/Tutoring/member/cartDelete", 
				{"cartnum":cartnum, userid:$("#userid").val()}, 
				function(d){
						var htmlStr="<table class='table table-hover table-bordered table-sm'>";
						htmlStr+="<thead><tr>";
		            	htmlStr+="<th style='width: 10%; text-align: center;'>강의 번호</th>";
		            	htmlStr+="<th style='text-align: center;'>강의명</th>";
		            	htmlStr+="<th style='width: 10%; text-align: center'>삭제</th>";
		            	htmlStr+="</tr></thead>";
		            	htmlStr+="<tbody>";
					$.each(d.carr, function(key, val){ 
		            	htmlStr+="<tr>";
	            		htmlStr+="<td>"+val.classnum+"</td>";
	            		htmlStr+="<td>"+val.classname+"</td>";
	            		htmlStr+="<td style='text-align: center;'><a href='javascript:cartdel("+val.cartnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";
						htmlStr+="</tr>";
					})
						htmlStr+="</tbody></table>";
						$(".back2").html(htmlStr);
				}
		)
	}
}

 

 


WCartDelete.java

(장바구니 삭제를 진행하는 서블릿. 경로는 "/Tutoring/member/cartDelete"이다.)

 

package com.wclass.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

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.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.wmember.model.WCartDAO;
import com.wmember.model.WCartDTO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String userid=request.getParameter("userid");
		int cartnum=Integer.parseInt(request.getParameter("cartnum"));
		WCartDAO dao=WCartDAO.getInstance();
		dao.cartDel(cartnum);
		response.sendRedirect("/Tutoring/member/cartList?userid="+userid);
	}

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

}

 

삭제한 뒤에는 userid를 들고 장바구니 목록으로 다시 돌아간다.


<WCartDAO.java의 cartDel 메소드>

 

//장바구니에서 삭제
	public void cartDel(int cartnum) {
		Connection con=null;
		Statement st=null;
		try {
			con=getConnection();
			String sql="delete from wcart where cartnum='"+cartnum+"'";
			st=con.createStatement();
			st.executeUpdate(sql);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, null);
		}
	}

 


<아쉬운 점>

1. 장바구니 외에 따로 결제 기능을 구현하지 못했다. 다른 라이브러리를 배우는데로 업데이트할 예정이다. 다른 사이트들은 잘 모르겠지만.. 캠블리는 장바구니가 아니라 단위 기간별로 결제를 먼저 하는 것 같았는데 그 로직을 이해하지 못했기 때문이다. 

 

2. 또한 영어를 화상으로 튜터와 1:1로 배우는 특성을 살리지 못한 점. 꼭 동영상 수업이 아니더라도.. 그러려면 튜터 DB를 하나 생성해서 학생과 매치시켜야겠지. 그게 어떻게 가능할까?

 

3. 내 강의실을 만들고, 학습하고, 남은 강의일수를 확인하는 시스템을 넣지 못한 점. 결제가 안되기 때문에 장바구니에서 제목을 클릭하면 강의 상세 페이지로 이동만 시켰다. 

 

이로써 JSP 개인프로젝트 리뷰를 마치겠다.

 

https://github.com/kkj0712/JspProject_Tutoring

 

kkj0712/JspProject_Tutoring

Contribute to kkj0712/JspProject_Tutoring development by creating an account on GitHub.

github.com

 

 

이전글

 

https://amongthestar.tistory.com/151?category=411827

 

JSP 개인프로젝트-영어 학습 사이트 만들기 (수강후기 게시판 전체보기, 게시글 입력)

이전글 https://amongthestar.tistory.com/150 JSP 개인프로젝트-영어 학습 사이트 만들기 (강의목록 전체보기, 상세보기) 이전글 (관리자 기능) https://amongthestar.tistory.com/149 JSP 개인프로젝트-영어 학..

amongthestar.tistory.com


지금까지 courseDetail.jsp 내에서 $.ajax을 통해 수강후기 전체글을 가져오고, 글쓰기 폼에서 후기등록 버튼을 눌렀을때 boardList로 이동하는 것까지 보았다.

 

오늘 포스팅할 내용은 수강후기 게시판에서 제목을 눌렀을 때 보이는 수강후기 글 상세보기 및 수정, 삭제와 그 밑에 달리는 댓글 입력하고 삭제하는 기능 구현이다.

 

 

제목을 누르면 boardDetail로 이동하여 다음과 같은 화면이 보인다. 댓글이 달려있다.

 


수강후기 전체 글의 껍데기인 listResult.jsp의 다음 코드에 의해 제목을 누르면 상세페이지로 이동한다.

<td><a href="/Tutoring/board/boardDetail?num=${board.num}">${board.subject}</a></td>

 


WBoardDetailAction.java

(수강후기 상세페이지 서블릿. 경로는 "/Tutoring/board/boardDetail"이다.)

package com.wboard.action;

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.wmember.model.WBoardDAO;
import com.wmember.model.WBoardDTO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		int num=Integer.parseInt(request.getParameter("num"));
		WBoardDAO dao=WBoardDAO.getInstance();
		WBoardDTO dto=dao.boardView(num);
		request.setAttribute("dto", dto);
		RequestDispatcher rd=request.getRequestDispatcher("detail.jsp");
		rd.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);
	}

}

 

파라미터 값으로 넘어온 num을 인자로 하여 WBoardDAO의 boardView메소드를 수행하고, dto객체를 dto이름으로 담아서 detail.jsp로 이동한다.

 

 


<WBoardDAO의 boardView메소드>

//게시물 상세보기
	public WBoardDTO boardView (int num) {
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		WBoardDTO dto=null;
		try {
			con=getConnection();
			st=con.createStatement();
			st.execute("update wboard set readcount = readcount+1 where num ="+num);
			String sql = "SELECT * FROM wboard WHERE num="+num;
			rs=st.executeQuery(sql);
			if(rs.next()) {
				dto=new WBoardDTO();
				dto.setNum(rs.getInt("num"));
				dto.setContent(rs.getString("content"));
				dto.setReadcount(rs.getInt("readcount"));
				dto.setReg_date(rs.getString("reg_date"));
				dto.setSubject(rs.getString("subject"));
				dto.setUserid(rs.getString("userid"));
				dto.setClassnum(rs.getInt("classnum"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return dto;
	}

 

수강후기 글을 클릭할 때마다 조회수 (readcount)가 1씩 증가하도록 했다.


detail.jsp

수강후기 상세글 jsp이다. 

수강후기 상세보기와 댓글 입력, 댓글 목록 영역으로 이루어져있다.

 

<div class="container">
<!-- 액션처리를 위한 값들 -->
<input type="hidden" id="num" name="num" value="${dto.num}"> <!-- 수강후기 게시글 번호 -->
<input type="hidden" id="classnum" name="classnum" value="${dto.classnum}">
<c:set var="classnum" value="${dto.classnum}" />
<!-- 수강 후기 글보기-->
<div><a href="/Tutoring/class/CourseDetail?num=${dto.classnum}"><b></b> 뒤로가기</a></div>
<br/>
	  <h5>수강후기</h5>
	  <br/>
	  <table class="table table-bordered table-sm">
	  <tr>
	 	<td style="width: 15%; background-color: #f8f9fa; text-align: center">글번호</td>
	 	<td style="width: 40%;">${dto.num}</td>
	 	<td style="width: 30%; background-color: #f8f9fa; text-align: center">조회수</td>
	 	<td style="width: 15%; text-align: right;">${dto.readcount}</td>
	  </tr>
	  <tr>
	 	<td style="background-color: #f8f9fa; text-align: center;">작성자</td>
	 	<td>${dto.userid}</td>
	 	<td style="background-color: #f8f9fa; text-align: center;">작성일</td>
	 	<td style="text-align: right">${dto.reg_date}</td>
	  </tr>
	  <tr>
	 	<td style="background-color: #f8f9fa; text-align: center">제목</td>
	 	<td colspan="3">${dto.subject}</td>
	  </tr>
	  <tr style="height: 150px">
	 	<td style="background-color: #f8f9fa; vertical-align: middle; text-align: center">글 내용</td>
	 	<td colspan="3">${dto.content}</td>
	  </tr>
	</table>
<!-- 수강후기 글보기 끝 -->
<!-- 수정, 삭제 버튼 보이기 -->
<c:set var="loginUserid" value="${sessionScope.userid}" />
<c:set var="userid" value="${dto.userid}" />
<c:if test="${loginUserid eq userid}">
		<div align="center" id="button">
			<input type="button" id="upBoard" name="upBoard" value="수정 " class="btn btn-info btn-sm" onclick="location.href='boardview?num=${dto.num}'"> 
			<input type="button" id="delBtn" name="delBtn" value="삭제" class="btn btn-danger btn-sm" onclick="javascript:fdelete(${dto.num}, ${dto.classnum})">
		</div> 
		<br/>
</c:if>
<!-- 수정, 삭제 버튼 보이기 끝-->
<!-- 댓글 리스트 영역 -->
	<div id="commentResult">
	</div>
<!-- 댓글 리스트 영역 끝-->
<!-- 댓글 달기 영역-->
	<div id="commentDiv" align="center">
		<textarea rows="2" cols="20" id="msg" name="msg" class="table table-bordered table-sm"></textarea>
<c:if test="${not empty sessionScope.userid}">
		<input type="button" id="commentBtn" name="commentBtn" value="댓글 " class="btn btn-info btn-sm">
</c:if>
	</div>
	<br/>
<!-- 댓글 달기 영역 끝 -->
</div>

자신이 쓴 글일 경우
다른이가 쓴 글일 경우

  • 현재 로그인한 userid와 글의 userid가 같으면 수정, 삭제 버튼이 보이도록 <c:set>과 <c:if>문으로 처리했다.
  • 댓글입력 버튼 또한 로그인을 하지 않으면 아예 보이지 않게 설정했다. 
  • 수강 후기 글을 클릭하자마자 댓글 리스트를 불러오도록 $.getJSON으로 처리했다.
$(document).ready(function(){
	//문서 열자마자 댓글 리스트를 불러옴
	$.getJSON("/Tutoring/board/commentList", 
				{num:$("#num").val()}, 
				function(d){
					var htmlStr="<table class='table table-striped'>";
					$.each(d.carr, function(key, val){ 
						htmlStr+="<tr>";
						htmlStr+="<th style='width:10%;'>"+val.userid+"</th>";
						htmlStr+="<td style='width:60%;'>"+val.msg+"</td>";
						htmlStr+="<td style='width:20%;'>"+val.reg_date+"</td>";
						
						if(val.userid == '${sessionScope.userid}'){
							htmlStr+="<td style='width:10%;'><a href='javascript:cdelete("+val.cnum+","+val.bnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";
						}else{
							htmlStr+="<td></td>";
						}
						
						htmlStr+="</tr>";
					})
						htmlStr+="</table>";
						$("#commentResult").html(htmlStr);
				}
	)

 

commentList 서블릿에서 JSONObject과 JSONArray클래스를 이용하여 최종적으로 JSONObject 객체에 저장된 데이터를 $.each로 뿌린다. 


CommentDTO.java

package com.wmember.model;

public class CommentDTO {
	private int cnum;
	private String userid;
	private String msg;
	private String reg_date;
	private int bnum;
	public int getCnum() {
		return cnum;
	}
	public void setCnum(int cnum) {
		this.cnum = cnum;
	}
	public String getUserid() {
		return userid == null ? "" : userid.trim();
	}
	public void setUserid(String userid) {
		this.userid = userid;
	}
	public String getMsg() {
		return msg == null ? "" : msg.trim();
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	public String getReg_date() {
		return reg_date == null ? "" : reg_date.trim();
	}
	public void setReg_date(String reg_date) {
		this.reg_date = reg_date;
	}
	public int getBnum() {
		return bnum;
	}
	public void setBnum(int bnum) {
		this.bnum = bnum;
	}
}

 


CommentListAction.java

(댓글 리스트 실행하는 서블릿. 경로는 "/Tutoring/board/commentList"이다.)

 

package com.wboard.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

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 org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.wmember.model.CommentDTO;
import com.wmember.model.WBoardDAO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		int bnum=Integer.parseInt(request.getParameter("num"));
		WBoardDAO dao=WBoardDAO.getInstance();
		ArrayList<CommentDTO> arr=dao.commentList(bnum);
		//arr를 json형태로 리턴
		JSONObject mainObj=new JSONObject();
		JSONArray jarr=new JSONArray();
		
		for(CommentDTO cd:arr) {
			JSONObject obj=new JSONObject();
			obj.put("bnum", cd.getBnum());
			obj.put("cnum", cd.getCnum());
			obj.put("msg", cd.getMsg());
			obj.put("userid", cd.getUserid());
			obj.put("reg_date", cd.getReg_date());
			jarr.add(obj);
		}
		mainObj.put("carr", jarr);
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(mainObj.toString());
	
	}

	/**
	 * @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);
	}

}

 

  • 파라미터 값으로 받아온 수강후기 글번호(num)를 bnum 변수에 저장하고, 그것을 인자로 하여 WBoardDAO.java의 commentList메소드를 수행한다.
  • 불러온 곳으로 다시 값을 들고 가야하므로 JSONObject과 JSONArray클래스를 활용한다. 

 

<WBoardDAO.java의 commentList메소드>

 

//코멘트 리스트 commentList
	public ArrayList<CommentDTO> commentList(int bnum){
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		ArrayList<CommentDTO> arr=new ArrayList<CommentDTO>();
		try {
			con=getConnection();
			String sql="select * from wcomment_board where bnum="+bnum+ "order by cnum desc";
			st=con.createStatement();
			rs=st.executeQuery(sql);
			while(rs.next()) {
				CommentDTO comment=new CommentDTO();
				comment.setBnum(rs.getInt("bnum"));
				comment.setCnum(rs.getInt("cnum"));
				comment.setMsg(rs.getString("msg"));
				comment.setReg_date(rs.getString("reg_date"));
				comment.setUserid(rs.getString("userid"));
				arr.add(comment);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return arr;
	}

 


이로써 게시글 상세보기 및 댓글 전체 목록 (comment list)를 출력할 수 있다.

 

 

자신이 쓴 게시글일 경우 삭제하고 싶으면 삭제 버튼을 누르면 된다.

 

<input type="button" id="delBtn" name="delBtn" value="삭제" class="btn btn-danger btn-sm" onclick="javascript:fdelete(${dto.num}, ${dto.classnum})">

삭제 버튼에 onclick을 달아 자바스크립트 함수를 호출했다.

confrim 창에서 확인을 누르면 삭제 메소드를 호출하는 서블릿으로 이동한다.

//게시글 삭제 함수
function fdelete(num, classnum){
	if(confirm("게시물을 삭제 하시겠습니까?")){
		location.href="delete?num=${dto.num}&classnum=${dto.classnum}";
	}
}

 


WBoardDeleteAction.java

(삭제 메소드를 호출하는 서블릿. 경로는 "/Tutoring/board/delete"이다.)

 

package com.wboard.action;

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.wmember.model.WBoardDAO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		int num=Integer.parseInt(request.getParameter("num"));
		int classnum=Integer.parseInt(request.getParameter("classnum"));
		WBoardDAO dao=WBoardDAO.getInstance();
		dao.boardDel(num);
		response.sendRedirect("/Tutoring/class/CourseDetail?num="+classnum);
	}

	/**
	 * @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);
	}

}

 

게시글 삭제 후에는 강의번호를 달고 다시 강의 상세정보 페이지로 이동한다.


<WBoardDAO.java의 boardDel메소드>

 

//게시글 삭제
	public void boardDel(int num) {
		Connection con=null;
		Statement st=null;
		try {
			con=getConnection();
			st=con.createStatement();
			String sql="delete from WBoard where num="+num;
			st.executeUpdate(sql);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, null);
		}
	}

 


 

그렇다면 자신이 쓴 게시글을 어떻게 수정할 수 있을까? 앞서 글의 userid와 현재 로그인한 userid가 동일한 경우에만 수정버튼, 삭제버튼이 보이도록 했다.

 

<!-- 수정, 삭제 버튼 보이기 -->
<c:set var="loginUserid" value="${sessionScope.userid}" />
<c:set var="userid" value="${dto.userid}" />
<c:if test="${loginUserid eq userid}">
		<div align="center" id="button">
			<input type="button" id="upBoard" name="upBoard" value="수정 " class="btn btn-info btn-sm" onclick="location.href='boardview?num=${dto.num}'"> 
			<input type="button" id="delBtn" name="delBtn" value="삭제" class="btn btn-danger btn-sm" onclick="javascript:fdelete(${dto.num}, ${dto.classnum})">
		</div> 
		<br/>
</c:if>
<!-- 수정, 삭제 버튼 보이기 끝-->

 

수정 버튼을 누르면 onclick location에 의해 boardview로 num값을 달고 간다. num은 이 게시글의 번호이다. (WBoardDTO의 num)

 

지금은 게시글을 그냥 볼 수 있는 화면이고, 수정할 수 있도록 폼 양식이 살아있는 화면으로 바뀌어야한다.

 


WBoardViewAction.java

(게시글을 수정할 수 있는 화면으로 넘기는 서블릿. 경로는 "/Tutoring/board/boardview" 이다.)

 

package com.wboard.action;

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.wmember.model.WBoardDAO;
import com.wmember.model.WBoardDTO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		int num=Integer.parseInt(request.getParameter("num"));
		WBoardDAO dao=WBoardDAO.getInstance();
		WBoardDTO dto=dao.boardView(num);
		request.setAttribute("dto", dto);
		RequestDispatcher rd=request.getRequestDispatcher("updateForm.jsp");
		rd.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);
	}

}

 

  • 파라미터 값으로 받아온 num을 인자로하여 WBoardDAO.java의 boardView 메소드를 수행한다.
  • dto객체를 dto이름에 담고 updateForm.jsp로 이동한다.

 

 


<WBoardDAO.java의 boardView 메소드>

  • 앞서 나온 메소드와 동일하다. 두 개의 서블릿에서 동일한 메소드를 거쳐 다른 출력화면으로 가는 것이다.
  • listResult.jsp(수강후기 전체 목록)의 제목 클릭->boardDetail(WBoardDetailAction.java)->WBoardDAO의 boardView 메소드->detail.jsp
  • detail.jsp의 수정버튼 클릭->boardView(WBoardViewAction.java)->WBoardDAO의 boardView 메소드->updateForm.jsp
//게시물 상세보기
	public WBoardDTO boardView (int num) {
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		WBoardDTO dto=null;
		
		try {
			con=getConnection();
			st=con.createStatement();
			st.execute("update wboard set readcount = readcount+1 where num ="+num);
			String sql = "SELECT * FROM wboard WHERE num="+num;
			rs=st.executeQuery(sql);
			if(rs.next()) {
				dto=new WBoardDTO();
				dto.setNum(rs.getInt("num"));
				dto.setContent(rs.getString("content"));
				dto.setReadcount(rs.getInt("readcount"));
				dto.setReg_date(rs.getString("reg_date"));
				dto.setSubject(rs.getString("subject"));
				dto.setUserid(rs.getString("userid"));
				dto.setClassnum(rs.getInt("classnum"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return dto;
	}

 


updateForm.jsp

수강후기글을 수정할 수 있는 화면

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="/include/header.jsp" %>    
<script>
//취소 함수
function back(){
	if(confirm("나가겠습니까? 변경사항은 저장되지 않습니다.")){
		location.href="/Tutoring/board/boardDetail?num=${dto.num}";
	}
}
</script>
<form action="/Tutoring/board/boardUpdate" method="post" id="wFrm">
<div class="container">
			<br/><br/>
			  <!-- 수강후기 등록하고자 하는 강의 번호 -->
			  <input type="hidden" id="classnum" name="classnum" value="${dto.classnum}">
			  
			  <!-- 게시글 번호 -->
			  <input type="hidden" id="num" name="num" value="${dto.num}">
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			  	  <span class="input-group-text">작성자</span></div>
			      <input type="text" class="form-control" id="userid" name="userid" readonly="readonly" value="${dto.userid}">
			  </div>
			  <br/>
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			      <span class="input-group-text">제목</span></div>
			      <input type="text" class="form-control" id="subject" name="subject" value="${dto.subject}">
			  </div>
			  <br/>
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			      <span class="input-group-text">내용</span></div>
			      <textarea rows="5" cols="20" class="form-control" id="content" name="content">${dto.content}</textarea>
			  </div>
			  
			  <div class="button" align="center">
			 	  <input type="reset" class="btn btn-gray" value="취소" onclick="javascript:back()">
			 	  <input type="submit" class="btn btn-primary" value="수정">
			  </div>
			  <br/>
			</form>
</div>
<%@ include file="/include/footer.jsp" %>

자신이 쓴 글의 수정버튼을 누르면 밑의 이미지처럼 updateForm.jsp 화면으로 이동한다.
updateForm.jsp 폼 양식 안에서 자신이 쓴 글을 수정할 수 있다. 

  • boardView 메소드를 거쳐 dto이름으로 저장된 dto 객체를 폼 양식 안에서 출력한다.
  • 수정버튼을 누르면 수정할 수 있는 서블릿으로 이동한다.

WBoardUpdateAction.java

(수정할 수 있는 구현체를 연결하는 서블릿. 경로는 "/Tutoring/board/boardUpdate"이다.)

 

 package com.wboard.action;

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.wmember.model.WBoardDAO;
import com.wmember.model.WBoardDTO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher rd=request.getRequestDispatcher("updateForm.jsp");
		rd.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		WBoardDTO board=new WBoardDTO();
		board.setNum(Integer.parseInt(request.getParameter("num")));
		board.setContent(request.getParameter("content"));
		board.setSubject(request.getParameter("subject"));
		board.setUserid(request.getParameter("userid"));

		int num=Integer.parseInt(request.getParameter("num"));
		WBoardDAO dao=WBoardDAO.getInstance();
		dao.boardUpdate(board);
		response.sendRedirect("/Tutoring/board/boardDetail?num="+num);
	}

}

 

  • 파라미터 값으로 받아온 게시글 번호, 내용, 제목, 아이디를 board객체에 저장한 후 이를 인자로 하여 WBoardDAO.java의 boardUpdate 메소드를 호출한다.
  • 게시글 수정 후에는 수강후기 상세보기 페이지로 다시 이동한다.

 


<WBoardDAO.java의 boardUpdate 메소드>

 

//게시물정보 수정
	public int boardUpdate(WBoardDTO vo) {
		Connection con=null;
		PreparedStatement ps=null;
		int flag=0;
		try {
			con=getConnection();
			String sql="update WBoard set subject=?, content=?, reg_date=sysdate where num=?";
			ps=con.prepareStatement(sql);
			ps.setString(1, vo.getSubject());
			ps.setString(2, vo.getContent());
			ps.setInt(3, vo.getNum());
			flag=ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps);
		}
		return flag;
	}

 

 


지금까지의 진행과정:

1. 게시판 목록에서 제목을 클릭하여 게시글 상세보기

2. 댓글목록을 보기

3. 게시글 삭제하기

4. 게시글 수정버튼을 눌러서 수정할 수 있는 화면으로 이동 -> 수정하기

 

 

앞에서 댓글목록을 부르는 것은 했다.

 

그렇다면 댓글은 어떻게 입력할까?

수강후기글 상세보기 페이지인 detail.jsp에서 로그인되어 있을 경우에만 댓글 버튼이 보이도록 처리했다.

<!-- 댓글 달기 영역-->
	<div id="commentDiv" align="center">
		<textarea rows="2" cols="20" id="msg" name="msg" class="table table-bordered table-sm"></textarea>
<c:if test="${not empty sessionScope.userid}">
		<input type="button" id="commentBtn" name="commentBtn" value="댓글 " class="btn btn-info btn-sm">
</c:if>
	</div>
	<br/>
<!-- 댓글 달기 영역 끝 -->

 

자바스크립트 함수에서 댓글 버튼을 눌렀을 경우 ajax 함수를 통해 commentInsert 서블릿으로 이동한다.

//댓글 입력 버튼
	$("#commentBtn").on("click", function(){
		if($("#msg").val()==""){
			alert("댓글을 작성해주세요");
			$("#msg").focus();
			return false;
		}else{
			$.ajax({
				type: "get",
				url: "commentInsert",
				data: {"msg":$("#msg").val(), "num":$("#num").val()},
				success: function(d){
						var htmlStr="<table class='table table-striped'>";
						d=JSON.parse(d);
						$.each(d.carr, function(key, val){ 
							
							htmlStr+="<tr>";
							htmlStr+="<th>"+val.userid+"</th>";
							htmlStr+="<td>"+val.msg+"</td>";
							htmlStr+="<td>"+val.reg_date+"</td>";
							
							if(val.userid == '${sessionScope.userid}'){
								htmlStr+="<td style='width:10%;'><a href='a href='javascript:cdelete("+val.cnum+","+val.bnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";
							}else{
								htmlStr+="<td></td>";
							}
							htmlStr+="</tr>";
						})
							htmlStr+="</table>";
							$("#commentResult").html(htmlStr);
				},
				error: function(e){
					alert("error:"+e);
				}
			})//ajax
		}
	})//commentBtn

 

commentInsert를 거쳐 돌아온 데이터는 JSON 형태로 파싱시켜 $.each로 값을 뿌린다.


WCommentInsertAction.java

(댓글 입력 처리 서블릿. 경로는 "/Tutoring/board/commentInsert"이다.)

 

package com.wboard.action;

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;
import javax.servlet.http.HttpSession;

import com.wmember.model.CommentDTO;
import com.wmember.model.WBoardDAO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String msg=request.getParameter("msg");
		int bnum=Integer.parseInt(request.getParameter("num"));
		HttpSession session=request.getSession();
		String userid=(String)session.getAttribute("userid");

		CommentDTO comment=new CommentDTO();
		comment.setBnum(bnum);
		comment.setMsg(msg);
		comment.setUserid(userid);
		WBoardDAO dao=WBoardDAO.getInstance();
		dao.commentInsert(comment);
		//commentList ArrayList에 담아 json으로 리턴
		response.sendRedirect("commentList?num="+bnum);

	}

	/**
	 * @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);
	}

}

 

댓글을 입력하고 나면 commentList 페이지로 게시글 번호를 달고 이동한다.

 

 


<WBoardDAO.java의 commentInsert 메소드>

 

//코멘트 추가 commentInsert
	public void commentInsert(CommentDTO comment) {
		Connection con=null;
		PreparedStatement ps=null;
		
		try {
			con=getConnection();
			String sql="insert into wcomment_board(cnum, userid, msg, reg_date, bnum) "
					+ "values(wcomment_board_seq.nextval,?,?,sysdate,?)";
			ps=con.prepareStatement(sql);
			ps.setString(1, comment.getUserid());
			ps.setString(2, comment.getMsg());
			ps.setInt(3, comment.getBnum());
			ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps);
		}
	}

댓글도 게시글과 마찬가지로 자신이 쓴 댓글이면 삭제 아이콘이 나타난다.

댓글 삭제또한 자바스크립트 함수 링크를 달아서 처리한다.

 

//댓글 삭제 함수
function cdelete(cnum, bnum){
	if(confirm("댓글을 삭제 하시겠습니까?")){
		$.getJSON("/Tutoring/board/cdelete", 
				{"cnum":cnum,"bnum":bnum}, 
				function(d){
					var htmlStr="<table class='table table-striped'>";
					$.each(d.carr, function(key, val){ 
						htmlStr+="<tr>";
						htmlStr+="<th style='width:10%;'>"+val.userid+"</th>";
						htmlStr+="<td style='width:60%;'>"+val.msg+"</td>";
						htmlStr+="<td style='width:20%;'>"+val.reg_date+"</td>";
						
						if(val.userid == '${sessionScope.userid}'){
							htmlStr+="<td style='width:10%;'><a href='javascript:cdelete("+val.cnum+","+val.bnum+")'><img src='/Tutoring/img/delete.png' style='height:20px; width:20px;'></a></td>";
						}else{
							htmlStr+="<td></td>";
						}
						
						htmlStr+="</tr>";
					})
						htmlStr+="</table>";
						$("#commentResult").html(htmlStr);
				}
	)
	}
}

 


CommentDeleteAction.java

(댓글 삭제 처리 서블릿. 경로는 "/Tutoring/board/cdelete"이다.)

 

package com.wboard.action;

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.wmember.model.WBoardDAO;

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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		int cnum=Integer.parseInt(request.getParameter("cnum"));
		int bnum=Integer.parseInt(request.getParameter("bnum"));
		WBoardDAO dao=WBoardDAO.getInstance();
		dao.commentDel(cnum);
		response.sendRedirect("/Tutoring/board/commentList?num="+bnum);
	}

	/**
	 * @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);
	}

}

 

삭제후에는 게시글번호를 달고 다시 commentList로 이동한다.

 


<WBoardDAO.java의 commentDel 메소드>

 

//댓글 삭제
	public void commentDel(int cnum) {
		Connection con=null;
		Statement st=null;
		try {
			con=getConnection();
			st=con.createStatement();
			String sql="delete from WComment_Board where cnum="+cnum;
			st.executeUpdate(sql);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, null);
		}
	}

 


https://github.com/kkj0712/JspProject_Tutoring

 

kkj0712/JspProject_Tutoring

Contribute to kkj0712/JspProject_Tutoring development by creating an account on GitHub.

github.com

 

이전글

https://amongthestar.tistory.com/150

 

JSP 개인프로젝트-영어 학습 사이트 만들기 (강의목록 전체보기, 상세보기)

이전글 (관리자 기능) https://amongthestar.tistory.com/149 JSP 개인프로젝트-영어 학습 사이트 만들기 (관리자 기능) 이전글 (로그인, 회원가입) https://amongthestar.tistory.com/148 JSP 개인프로젝트-영어..

amongthestar.tistory.com


이번에 포스팅할 내용은 수강후기 게시판 전체보기와 게시글 입력이다.

게시글 상세보기 및 수정 삭제, 댓글 입력 삭제는 다음 포스팅에 게시할 예정이다.

 

지금까지 로직 진행은 다음과 같다.

1. 메인 화면에서 세번째 탭에 해당하는 "과정"을 클릭하면 과정 전체목록이 카드 형식으로 보인다.

WClassCourseList.java -> courseList.jsp 로 이동

2. 카드 하나를 클릭하면 해당하는 과정의 상세내용을 볼 수 있다.

WClassCourseDetail.java -> courseDetail.jsp 로 이동

3. 과정의 상세내용 하단에 수강후기 게시판을 볼 수 있다.

 


수강후기 DB관련 DTO (WBoardDTO.java)

package com.wmember.model;

public class WBoardDTO {
	private int num;
	private String userid;
	private String subject;
	private String content;
	private String reg_date;
	private int readcount;
	private int classnum;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getUserid() {
		return userid == null ? "" : userid.trim();
	}
	public void setUserid(String userid) {
		this.userid = userid;
	}
	public String getSubject() {
		return subject == null ? "" : subject.trim();
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getContent() {
		return content == null ? "" : content.trim();
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getReg_date() {
		return reg_date == null ? "" : reg_date.trim();
	}
	public void setReg_date(String reg_date) {
		this.reg_date = reg_date;
	}
	public int getReadcount() {
		return readcount;
	}
	public void setReadcount(int readcount) {
		this.readcount = readcount;
	}
	public int getClassnum() {
		return classnum;
	}
	public void setClassnum(int classnum) {
		this.classnum = classnum;
	}
}

 


courseDetail.jsp

 

게시판 영역이다. 검색영역, 글쓰기 버튼, 수강후기 게시판영역으로 이루어져있다.

<!-- 게시판 -->
	<div class="board">
		<br/>
		
		<!-- 검색 시작-->
		<div align="right" id="searchDiv">
		<form name="search" id="search">
			<select name="field" id="field">
				<option value="userid">작성자</option>
				<option value="subject">제목</option>
			</select>
			<input type="text" name="word" id="word">
			<input type="button" value="찾기" id="btnSearch" class="btn btn-outline-secondary btn-sm">
			<a href="#coll"  id="writeBtn" class="btn btn-outline-dark btn-sm" data-toggle="collapse">글쓰기</a>
		</form>
		</div>
		<!-- 검색 끝-->
		
		<!-- 수강후기 게시판 -->
		<div id="result" align="center"></div>
		
		<!-- 글쓰기 폼 영역 -->
		  <div id="coll" class="collapse">
		   <form action="/Tutoring/board/boardinsert" method="post" id="wFrm">
			<br/><br/>
			  <!-- 수강후기 등록하고자 하는 강의 번호 -->
			  <input type="hidden" id="classnum" name="classnum" value="${dto.classnum}">
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			      <span class="input-group-text">강의명</span></div>
			      <input type="text" class="form-control" id="classname" name="classname" readonly="readonly" value="${dto.classname}">
			  	  <div class="input-group-prepend"><span class="input-group-text">작성자</span></div>
			      <input type="text" class="form-control" id="userid" name="userid" readonly="readonly" value="${sessionScope.userid}">
			  </div>
			  <br/>
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			      <span class="input-group-text">제목</span></div>
			      <input type="text" class="form-control" id="subject" name="subject">
			  </div>
			  <br/>
			  
			  <div class="input-group mb-3"><div class="input-group-prepend">
			      <span class="input-group-text">내용</span></div>
			      <textarea rows="5" cols="20" class="form-control" id="content" name="content"></textarea>
			  </div>
			  
			  <div class="button">
			 	  <input type="reset" class="btn btn-gray" value="취소">
			 	  <input type="button" class="btn btn-primary" id="send" value="후기등록">
			  </div>
			</form>
		  </div>
		  <!-- 글쓰기 폼 영역  끝-->
	</div>
<!-- 게시판 끝-->

 

수강후기 게시판 영역은 div태그만 있고 내용이 없다. 테이블 태그는 보이지 않는다. 어떻게 구현할까?

페이지가 로드되자 마자 수강후기 리스트를 불러오도록 자바스크립트 함수를 기입한다.

<script>
$(document).ready(function(){
	getData(1, "", "", ${dto.classnum}); //페이지 로드 시 수강후기 리스트 보기
//전체보기 함수
function getData(pageNum, field, word, classnum){
	$.get("/Tutoring/board/boardlist", 
			{"pageNum":pageNum, "field":field, "word":word, "classnum":classnum},
			function(d){
			$("#result").html(d);
	})
}//getData
//검색버튼 클릭
	$("#btnSearch").on("click", function(){
		getData(1, $("#field").val(), $("#word").val(), $("#classnum").val());
	})//btnSearch
  • $.get 함수로 "/Tutoring/board/boardlist"로 이동하고 들고온 값을 result div영역에 뿌린다.

 


WBoardListAction.java

(수강후기 게시판 전체 목록을 가져오는 서블릿. 경로는  "/Tutoring/board/boardlist"이다.)

package com.wboard.action;

import java.io.IOException;
import java.util.ArrayList;

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.wmember.model.PageUtil;
import com.wmember.model.WBoardDAO;
import com.wmember.model.WBoardDTO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		WBoardDAO dao=WBoardDAO.getInstance();
		
		String pageNum=request.getParameter("pageNum")==null? "1":request.getParameter("pageNum");
		int currentPage=Integer.parseInt(pageNum);
		int pageSize=5;
		int startRow=(currentPage-1)*pageSize+1;
		int endRow=currentPage*pageSize;
				
		int count=0;
		String field=request.getParameter("field")==null?"":request.getParameter("field");
		String word=request.getParameter("word")==null?"":request.getParameter("word");
		
		//어떤 강의인지 강의 번호를 가져오기
		String classNumber=request.getParameter("classnum");
		int classnum=Integer.parseInt(classNumber);
		
		//수강후기 개수 출력
		count=dao.getCount(field, word,classnum);
		
		//총페이지 수
		int totPage=(count/pageSize)+(count%pageSize==0?0:1);
		int pageBlock=3;
		int startPage=((currentPage-1)/pageBlock)*pageBlock+1;
		int endPage=startPage+pageBlock-1;
		if(endPage>totPage) endPage=totPage;
		
		PageUtil pu=new PageUtil();
		pu.setCurrentPage(currentPage);
		pu.setEndPage(endPage);
		pu.setPageBlock(pageBlock);
		pu.setStartPage(startPage);
		pu.setTotPage(totPage);
		pu.setField(field);
		pu.setWord(word);
		pu.setClassnum(classnum);
		
		ArrayList<WBoardDTO> arr=null;
		if(word.equals("")) {
			arr=dao.boardList(startRow, endRow, classnum);
		}else {
			arr=dao.boardList(field, word, startRow, endRow, classnum);
		}
		
		int rowNo=count-((currentPage-1)*pageSize); //매 페이지의 시작번호
		
		request.setAttribute("rowNo", rowNo);
		request.setAttribute("pu", pu);
		request.setAttribute("board", arr);
		request.setAttribute("count", count);
		
		RequestDispatcher rd=request.getRequestDispatcher("listResult.jsp");
		rd.forward(request, response);
	}

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

}

 

관리자 페이지에서 강의목록을 내보냈던 것과 마찬가지로 페이징, 전체 게시글 수, 게시글 목록을 request 객체를 이용해 listResult.jsp로 내보낸다. 

 

 


 

PageUtil.java 내용은 앞서 관리자 기능에 대해 소개한 포스팅에 나와있다.

 


<WBoard.java의 boardList 메소드>(검색이 아닐때)

 

//검색 아닌 전체보기
	public ArrayList<WBoardDTO> boardList(int startRow, int endRow, int classnum) {
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		ArrayList<WBoardDTO>arr=new ArrayList<WBoardDTO>();
		
		try {
			con=getConnection();
			StringBuilder sb=new StringBuilder();
			sb.append(" select * from");
			sb.append(" (select aa.*, rownum rn from");
			sb.append(" (select * from WBoard where classnum="+classnum);
			sb.append(" order by num desc) aa");
			sb.append(" where rownum<=?) where rn>=?");
			ps=con.prepareStatement(sb.toString());
			ps.setInt(1, endRow);
			ps.setInt(2, startRow);
			rs=ps.executeQuery();
			while(rs.next()) {
				WBoardDTO dto=new WBoardDTO();
				dto.setNum(rs.getInt("num"));
				dto.setContent(rs.getString("content"));
				dto.setReadcount(rs.getInt("readcount"));
				dto.setReg_date(rs.getString("reg_date"));
				dto.setSubject(rs.getString("subject"));
				dto.setUserid(rs.getString("userid"));
				dto.setClassnum(rs.getInt("classnum"));
				arr.add(dto);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps, rs);
		}
		return arr;
	}

 

더보기

이때 SQL문이 헷갈려서 고생을 했다.. (좀 막혔던 부분들을 생각해보면 다 전체목록 보기에 관한 기능 구현에 관해서다..)

지금까지 전체 목록을 볼때는 검색한 결과인지 아닌지만 가르면 됐는데, 지금의 수강후기 게시판은 "특정 강의에 대한" 수강후기라는 단서가 붙는다.

 

그래서 처음엔 바깥에 select를 한번 더 감싸고 where classnum=강의번호; 라고 조건절을 줬고 그 select문 안에서 rn을 미리 부여해놓고 5에서 10사이, 10에서 15사이 이런식으로 골라냈었다. 당연히 1페이지에는 2개, 2페이지에는 5개 이렇게 오류가 날 수 밖에 없었다. (사실 오류가 아니고 당연한 결과다.) 

 

하지만 강의 페이지별로 수강후기 DB가 따로 있는게 아니고 전체 수강후기 DB에서 강의번호 별로 골라낸다.

 

따라서 바깥 select를 지우고, rownum where 절이 아닌 select * from wboard 뒤에 where classnum이라는 조건절을 추가해야한다. 즉 미리 classnum을 골라내고 rn을 계산해야하는 것이다.


<WBoard.java의 boardList 메소드>(검색일때)

 

//검색 전체보기
	public ArrayList<WBoardDTO> boardList(String field, String word, int startRow, int endRow, int classnum) {
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		ArrayList<WBoardDTO>arr=new ArrayList<WBoardDTO>();
		
		try {
			con=getConnection();
			StringBuilder sb=new StringBuilder();
			sb.append(" select * from");
			sb.append(" (select aa.*, rownum rn from");
			sb.append(" (select * from WBoard where classnum="+classnum);
			sb.append(" and upper ("+field+") like upper ('%"+word+"%')");
			sb.append(" order by num desc) aa");
			sb.append(" where rownum<=?) where rn>=?");
			ps=con.prepareStatement(sb.toString());
			ps.setInt(1, endRow);
			ps.setInt(2, startRow);
			rs=ps.executeQuery();
			while(rs.next()) {
				WBoardDTO dto=new WBoardDTO();
				dto.setNum(rs.getInt("num"));
				dto.setContent(rs.getString("content"));
				dto.setReadcount(rs.getInt("readcount"));
				dto.setReg_date(rs.getString("reg_date"));
				dto.setSubject(rs.getString("subject"));
				dto.setUserid(rs.getString("userid"));
				dto.setClassnum(rs.getInt("classnum"));
				arr.add(dto);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps, rs);
		}
		return arr;
	}

 


<WBoard.java의 getCount 메소드>

 

//게시물수 출력
	public int getCount(String field, String word, int classnum) {
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		int count=0;
		String sql="";
		
		try {
			con=getConnection();
			st=con.createStatement();
			if(word.equals("")) {
				sql="select count(*) from WBoard where classnum="+classnum;
			}else {
				sql="select count(*) from WBoard where upper ("+field+") like upper ('%"+word+"%') and classnum="+classnum;
			}
			rs=st.executeQuery(sql);
			if(rs.next()) {
				count=rs.getInt(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, st, rs);
		}
		return count;
	}

listResult.jsp

WBoardListAction.java에서 내보내진 값을 board란 이름에 담아서 뿌린다. 페이징 영역도 포함하고 있다.

그런데 courseDetail.jsp->WBoardListAction.java->listResult.jsp로 이동된 것이므로 $.get의 콜백함수에 의해 이 값들이 courseDetail.jap의 result div에 뿌려지게 된다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<body>
<h5 style="text-align: left"><span id="cntSpan">수강후기(${count}</span>)</h5>
<table class="table table-hover table-bordered table-sm">
	<thead>
		<tr>
			<th style="width: 8%">글번호</th>
			<th style="width: 13%">작성자</th>
			<th>제목</th>
			<th style="width: 8%">작성일</th>
			<th style="width: 7%">조회수</th>
		</tr>
	</thead>
	<tbody>
		<c:forEach items="${board}" var="board" varStatus="st">
		<tr>
			<td>${rowNo-st.index}</td>
			<td>${board.userid}</td>
			<td><a href="/Tutoring/board/boardDetail?num=${board.num}">${board.subject}</a></td>
			<td>${board.reg_date}</td>
			<td>${board.readcount}</td>
		</tr>
		</c:forEach>
	</tbody>
</table>
<div align="center">
	<c:if test="${pu.startPage>pu.pageBlock}"> <!-- 이전 -->
		<a href="javascript:getData(${pu.startPage-pu.pageBlock},'${pu.field}','${pu.word}', ${pu.classnum})">[이전]</a>
	</c:if>
	<c:forEach begin="${pu.startPage}" end="${pu.endPage}" var="i"><!-- 페이지 출력 -->
		<c:if test="${i==pu.currentPage}"> <!-- 현재 페이지 -->
			<c:out value="${i}"/>
		</c:if>
		<c:if test="${i!=pu.currentPage}"> <!-- 현재 페이지 아닌 경우 링크 부여-->
			<a href="javascript:getData(${i},'${pu.field}','${pu.word}', ${pu.classnum})">${i}</a>
		</c:if>
	</c:forEach>
	<c:if test="${pu.endPage<pu.totPage}"> <!-- 다음-->
		<a href="javascript:getData(${pu.endPage+1},'${pu.field}','${pu.word}', ${pu.classnum})">[다음]</a>
	</c:if>
</div>
</body>
</html>

 


다음은 수강후기 글쓰기에 대한 내용이다.

지금까지는 로그인 없이 볼 수 있는 내용들이었지만 수강후기를 쓰려고 하면 로그인을 해야한다.

글쓰기 버튼을 누르면 숨어있던 글쓰기 폼이 나타난다. 부트스트랩의 collapse 클래스를 이용했다.

courseDetail.jsp 내에 글쓰기 폼이 있으므로 후기등록 버튼을 눌렀을때 실행되는 자바스크립트 함수도 이곳에 적어준다.

 

 

courseDetail.jsp 내의 글쓰기 폼 영역

 

//후기등록 버튼 클릭
	$("#send").click(function(){ //후기등록 버튼 클릭
         if(${sessionScope.userid==null}){
              alert("로그인 필요");
              location.href="/Tutoring/member/login";
         }else{
	       	 	var classnum=$("#classnum").val();
				var userid=$("#userid").val();
				var content=$("#content").val();
				var subject=$("#subject").val();
				var postString="classnum="+classnum+"&userid="+userid+"&content="+content+"&subject="+subject;
	            $.ajax({
	                  type:    "post",
	                  url :    "/Tutoring/board/boardinsert",
	                  data:    postString,
	                  success:function(d){
	                	   alert("후기가 등록되었습니다!");
	                	   $("#result").html(d);
	                       document.getElementById("wFrm").reset();
	                  },
	                  beforeSend: showRequest, //빈칸 확인
	                  error: function(e){
	                       alert("error:"+e);
	                  }
	            })//ajax
         }
     })//send
}); //document ready
//빈칸확인 함수
function showRequest(){
	if($("#subject").val()==""){
		alert("제목을 입력하세요");
		$("#subject").focus();
		return false;
	}
	if($("#content").val()==""){
		alert("내용을 입력하세요");
		$("#content").focus();
		return false;
	}
	return true;
}

 

로그인을 하지 않았을 경우 alert창을 띄우고 login화면으로 넘어간다.

로그인을 한 경우 $.ajax을 이용하여 비동기방식으로 수강후기가 입력되며, 새로고침을 하지 않아도 수강후기 화면이 업데이트 된다. 

 


WBoardInsertAction.java

($.ajax를 통해 넘어온 수강후기 입력 서블릿. 경로는 "/Tutoring/board/boardinsert"이다.)

 

package com.wboard.action;

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.wmember.model.WBoardDAO;
import com.wmember.model.WBoardDTO;


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

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher rd=request.getRequestDispatcher("courseDetail.jsp");
		rd.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		WBoardDTO board=new WBoardDTO();
		board.setClassnum(Integer.parseInt(request.getParameter("classnum")));
		board.setUserid(request.getParameter("userid"));
		board.setSubject(request.getParameter("subject"));
		board.setContent(request.getParameter("content"));
		WBoardDAO dao=WBoardDAO.getInstance();
		
		int classNumber=Integer.parseInt(request.getParameter("classnum"));
		int flag=0;
		flag=dao.boardInsert(board);

		if(flag==1){
			response.sendRedirect("/Tutoring/class/CourseDetail?num="+classNumber);
		}
	}
}

 

WBoardDAO.java의 boardInsert메소드를 수행하여 수강후기가 입력되었으면 return된 flag 값을 받아오고 1일 경우 다시 CourseDetail로 넘어간다. 수강후기가 해당되는 강의 상세보기로 넘어가므로 num값을 미리 받아와야한다.

 

 


<WBoardDAO.java의 boardInsert메소드>

 

//디비셋팅
	private static WBoardDAO instance=new WBoardDAO();
	public static WBoardDAO getInstance() {
		return instance;
	}
	private Connection getConnection() throws Exception{
		Context initCtx=new InitialContext();
		Context envCtx=(Context) initCtx.lookup("java:comp/env");
		DataSource ds=(DataSource) envCtx.lookup("jdbc/wiser");
		return ds.getConnection();
	}
	
	//게시물등록
	public int boardInsert(WBoardDTO vo) {
		Connection con=null;
		PreparedStatement ps=null;
		int flag=0;
		
		try {
			con=getConnection();
			String sql="INSERT INTO WBoard(num, userid, subject, content, reg_date, "
					+ "readcount, classnum)"
					+ "VALUES(WBoard_seq.nextval,?,?,?,sysdate,0,?)";
			ps=con.prepareStatement(sql);
			ps.setString(1, vo.getUserid());
			ps.setString(2, vo.getSubject());
			ps.setString(3, vo.getContent());
			ps.setInt(4, vo.getClassnum());
			flag=ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeConnection(con, ps);
		}
		return flag;
	}
    
    //닫기 closeConnection
	private void closeConnection(Connection con, PreparedStatement ps) {
		try {
			if(ps!=null) ps.close();
			if(con!=null) con.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
	}
	private void closeConnection(Connection con, Statement st, ResultSet rs) {
		try {
			if(st!=null) st.close();
			if(con!=null) con.close();
			if(rs!=null) rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
	}

 

courseDetail의 $.ajax으로 다시 돌아가면 result영역에 수강후기 게시판이 업데이트되어 나타난다. 


게시글 상세보기 및 수정 삭제, 댓글과 관련된 포스팅은 다음에 하겠다.

 

https://github.com/kkj0712/JspProject_Tutoring

 

kkj0712/JspProject_Tutoring

Contribute to kkj0712/JspProject_Tutoring development by creating an account on GitHub.

github.com

 

+ Recent posts