이클립스 HTTP 500에러 (Message Unable to compile class for JSP)

Back-End/Problems 2019. 5. 10. 11:48

-에러코드-


 

  Type Exception Report

  Message Unable to compile class for JSP:

  Description The server encountered an unexpected condition that prevented it from fulfilling the request.

  Exception
  org.apache.jasper.JasperException: Unable to compile class for JSP: 



서버에서 클래스를 인식하지 못해 발생하는 에러 (문법에 이상이 없어도 가끔 발생한다고 함)

인터넷에서 방법을 찾아봤지만 되지않아 서버를 삭제하고 다시 셋팅해서 실행해보았는데 실행이 되었다.

:

19.05.10 JSP 게시판 BoardInfo 게시글 보기 (46강)

Back-End/JSP 2019. 5. 10. 11:45

전체 게시글 보기BoardList.jsp

글보기

BoardDAO-

getOneBoard( )

하나의 게시글 보기

BoardInfo.jsp


 

답글 쓰기

BoardReWriteForm.jsp


 글 수정하기

BoardUpdateForm.jsp

 글 삭제하기

BoardDeleteForm.jsp 



-노란색 표시한 부분까지 구현-


BoardWriteForm.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
36
37
38
39
40
41
42
43
44
45
46
47
48
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<center>
<h2> 게시글 쓰기 </h2> 
 
<form action="BoardWriteProc.jsp" method="post">
<table width = "600" border="1" bordercolor = "gray" bgcolor = "skyblue"> <!-- bordercolor는 선색깔 지정 -->
    <tr height = "40">
        <td align = "center" width = "150"> 작성자 </td> <!-- ref는 데이터베이스에서 처리하기 때문에 따로 받지 않는다. -->
        <td width = "450"> <input type = "text" name = "writer" size = "60"></td> 
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 제목 </td>
        <td width = "450"> <input type = "text" name = "subject" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 이메일 </td>
        <td width = "450"> <input type = "text" name = "email" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 비밀번호 </td>
        <td width = "450"> <input type = "password" name = "password" size = "61"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 글내용 </td>
        <td width = "450"><textarea rows = "10" cols = "50" name = "content"></textarea></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" colspan = "2">
            <input type = "submit" value = "글쓰기"> &nbsp;&nbsp;
            <input type = "reset" value = "다시작성"> &nbsp;&nbsp;
            <button onclick = "location.href='BoardList.jsp'">전체 게시글 보기</button> <!-- 클릭하면 BoardList.jsp페이지로 넘어가는 버튼-->
        </td>
    </tr>
</table>
</form>
</center>
</body>
</html>
 
cs



BoardWriteProc.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
36
37
38
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
    <% 
    request.setCharacterEncoding("EUC-KR"); //한글깨짐 방지 문자셋 설정
%>
    <!-- 빈파일에서 게시글 작성한 데이터를 한번에 읽어들임 -->
    <!-- use빈을 사용하여 자바빈을 사용, id는 빈클래스를 지칭하는 참조 변수명 -->
    <!-- 빈파일에 있는 값들을 받는다. -->
    <!-- 빈파일에 없는 값들은 null로 들어온다 null값으로 들어온 것들은 데이터베이스에서 들어올 값들이니 걱정x -->
 
    <jsp:useBean id="boardbean" class="model.BoardBean">
        <jsp:setProperty name="boardbean" property="*" />
    </jsp:useBean>
 
    <%
    //데이터베이스 쪽으로 빈클래스를 넘겨줌
    BoardDAO bdao = new BoardDAO();
    
    //데이터 저장 메소드를 호출
    bdao.insertBoard(boardbean);
    
    //게시글 저장후 전체 게시글 보기
    response.sendRedirect("BoardList.jsp");
 
%>
 
 
 
 
</body>
</html>
 
cs




BoardList.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<%@page import="java.util.Vector"%>
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
<%
 
    //전체 게시글의 내용을 jsp쪽으로 가져와야함
    //길이를 정확히 알 수 없기 때문에 가변길이인 벡터로 받는다.
    BoardDAO bdao = new BoardDAO();
 
    //전체게시글을 리턴 받아주는 소스 (나중엔 개수가 많아지므로 다시 수정할 예정)
    Vector<BoardBean> vec = bdao.getAllBoard();
    
%>
<center>
<h2> 전체 게시글 보기 </h2>
<table width = "700" border = "1" bgcolor = "skyblue">
    <tr height = "40">
        <td width = "50" align = "center"> 번호 </td>
        <td width = "320" align = "center"> 제목 </td>
        <td width = "100" align = "center"> 작성자 </td>
        <td width = "150" align = "center"> 작성일 </td>
        <td width = "80" align = "center"> 조회수 </td>
    </tr>
<%
    for(int i = 0; i<vec.size(); i++)
    {
        BoardBean bean = vec.get(i); //벡터에 저장되어있는 bean클래스를 하나씩 추출
    
%>
    <tr height = "40">
        <td width = "50" align = "center"> <%=i+1%> </td> <!-- 숫자가 하나씩 올라가게 하기위해서 i+1을 해준다 -->
                                                            <!-- getNum()을 쓰면 순서가 복잡해지기 때문 -->
        <td width = "320" align = "center"> <a href = "BoardInfo.jsp?num=<%=bean.getNum()%>"> 
        <%=bean.getSubject()%></a>    </td>
        <td width = "320" align = "center"> <a href = "test.jsp?num=<%=bean.getNum()%>"> 
        <%=bean.getSubject()%></a>    </td>
        <!-- BoardInfo.jsp파일(정보를 확인하기 위한파일)에 Num값을 넘겨준다 --> 
        <td width = "100" align = "center"> <%=bean.getWriter() %></td>
        <td width = "150" align = "center"> <%=bean.getReg_date() %></td>
        <td width = "80" align = "center"> <%=bean.getReadcount() %> </td>
    </tr>
    <%%>
    <tr height = "40">
        <td align = "center" colspan = "5"><!-- 버튼을 클릭하면 BoardWriteForm.jsp파일로 넘어간다.-->
        <input type = "button" value = "글쓰기" onclick="location.href='BoardWriteForm.jsp'"></td>
        </tr>
        
        
        
</table>
</center>
</body>
</html>
 
 
cs




BoardInfo.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<%@page import="model.BoardBean"%>
<%@page import="model.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<%
    int num = Integer.parseInt(request.getParameter("num").trim()); //리스트 파일에서 넘겨준  num값을 받는다. num이 테이블의 기본키이기 때문에 num으로 정보를 확인할수 있기 때문
    //공백제거후 정수형으로 바뀜 (정수형으로 바꾸면 숫자를 넣기가 쉽기 때문에)
    
    //데이터베이스 접근
    BoardDAO bdao = new BoardDAO();
    //boardbean 타입으로 하나의 게시글을 리턴 받는다.
    BoardBean bean = bdao.getOneBoard(num);
    
%>
<center>
<h2> 게시글 보기 </h2> <!-- 빈클레스가 가지고있는 값들을 뿌려준다. -->
<table width = "600" border = "1" bgcolor = "skyblue">
    <tr height"40">
        <td align = "center" width = "120">글 번호 </td>
        <td align="center" width = "180"> <%=bean.getNum() %>
        <td align = "center" width = "120">조회수 </td>
        <td align="center" width = "180"> <%=bean.getReadcount() %></td>
        </tr>
        
        <tr height"40">
        <td align = "center" width = "120">작성자 </td>
        <td align="center" width = "180"> <%=bean.getWriter() %>
        <td align = "center" width = "120">작성일 </td>
        <td align="center" width = "180"> <%=bean.getReg_date() %></td>
        </tr>
        
        <tr height"40">
        <td align = "center" width = "120" colspan = "2">이메일 </td>
        <td align="center" width = "180" colspan = "2"> <%=bean.getEmail() %></td>
        </tr>
        
        <tr height"40">
        <td align = "center" width = "120">제목 </td>
        <td align="center" colspan = "3"> <%=bean.getSubject() %></td>
        </tr>
        
        <tr height"80">
        <td align = "center" width = "120">글 내용 </td>
        <td align="center" colspan = "3"> <%=bean.getContent() %></td>
        </tr>
        
        <tr height"40">
        <td align="center" colspan = "4">
        <input type = "button" value = "답글쓰기" 
        onclick = "location.href='BoardReWriteForm.jsp?num=<%=bean.getNum()%>&ref=<%=bean.getRef()%>&re_step=<%=bean.getRe_step()%>&re_Level<%=bean.getRe_level()%>'"> 
        <!-- 부모글의 ref, revel, num값을 다 알고 있어야된다.(리플달기이기 때문) -->
        <!-- 위에처럼 num값만 넘겨서 할수도 있다.
        int num = Integer.parseInt(request.getParameter("num").trim());
        BoardDAO bdao = new BoardDAO();
        BoardBean bean = bdao.getOneBoard(num); -->
        <input type = "button" value = "수정하기" onclick = "location.href = 'BoardUpdateForm.jsp?num=<%=bean.getNum()%>'">
        <input type = "button" value = "삭제하기" onclick = "location.href = 'BoardDeleteForm.jsp?num=<%=bean.getNum()%>'">
        <input type = "button" value = "목록보기" onclick = "location.href = 'BoardList.jsp?num=<%=bean.getNum()%>'">
        
        
        
        
</table>
</center>
</body>
</html>
cs



BoardBean.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package model;
 
public class BoardBean { //빈클래스 생성
    
    private int num;
    private String email;
    private String subject;
    private String password;
    private String reg_date;
    private String writer;
    private int ref;
    private int re_step;
    private int re_level;
    private int readcount;
    private String content;
    
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getReg_date() {
        return reg_date;
    }
    public void setReg_date(String reg_date) {
        this.reg_date = reg_date;
    }
    public String getWriter() {
        return writer;
    }
    public void setWriter(String writer) {
        this.writer = writer;
    }
    public int getRef() {
        return ref;
    }
    public void setRef(int ref) {
        this.ref = ref;
    }
    public int getRe_step() {
        return re_step;
    }
    public void setRe_step(int re_step) {
        this.re_step = re_step;
    }
    public int getRe_level() {
        return re_level;
    }
    public void setRe_level(int re_level) {
        this.re_level = re_level;
    }
    public int getReadcount() {
        return readcount;
    }
    public void setReadcount(int readcount) {
        this.readcount = readcount;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    
    
}
 
cs



BoardDAO.java(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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package model;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;
 
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.naming.Context;
 
public class BoardDAO {
 
    // 데이터베이스에 연결하기 위한 설정
    Connection con;
    PreparedStatement pstmt;
    ResultSet rs;
 
    // 데이터베이스의 커넥션들을 사용하도록 설정하는 메소드
    public void getCon() {
 
        try { // 데이터베이스에 접속할때는 예외처리를 해주어야한다.
 
            Context initctx = new InitialContext(); // 외부에서 데이터를 읽어들어야 하기 때문에 Context 객체 생성
            // 톰캣 서버에 정보를 담아놓은 곳으로 이동함
            Context envctx = (Context) initctx.lookup("java:comp/env"); // lookup메소드를 이용해서 자료를 읽어오는 코드
            DataSource ds = (DataSource) envctx.lookup("jdbc/pool"); // datasource 객체를 선언 , 오브젝트 타입이기 때문에 타입변환을 한다.
 
            con = ds.getConnection(); // 데이터 소스를 기준으로 커넥션을 연결함
        } catch (Exception e) {
            e.printStackTrace(); // 어느부분이 잘못되었는지 알려주는 예외처리
        }
    }
 
    // 하나의 새로운 게시글이 넘어와서 저장되는 메소드
    public void insertBoard(BoardBean bean) {
        getCon();
        // 빈클래스에 넘어오지 않았던 데이터들을 초기화 해주어야 한다.
 
        int ref = 0// 글그룹을 의미한다, 쿼리를 실행시켜서 가장 큰 ref값을 가져온후 +1을 더해주면 된다.
        int re_step = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
        int re_level = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
 
        try {
 
            // 가장큰 ref값을 읽어오는 쿼리 준비함 (새로운 글은 ref가 가장크기 때문)
            String refsql = "select max(ref) from board"// board테이블로부터 가장큰 ref를 검색
            // 쿼리를 실행할 객체
            pstmt = con.prepareStatement(refsql);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
            if (rs.next()) { // 쿼리(rs)가 결과값이 있다면 실행하는 구문
                ref = rs.getInt(1+ 1// 최대값에 1을 더해서 글그룹을 설정. 새로운글은 ref숫자가 하나씩 올라가야 하기 때문
            }
 
            // 실제로 게시글 전체값을 테이블에 저장
            String sql = "insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)"// ?가 아니라 시퀀스를 사용해
                                                                                                    // 시퀀스에 이미 들어가있는값의
                                                                                                    // 다음값을 자동으로 매핑해서
                                                                                                    // 넣어준다.
            pstmt = con.prepareStatement(sql);
            // ?에 값을 매핑한다. //0은 카운트값이기때문 0을 넣어주었다
            pstmt.setString(1, bean.getWriter());
            pstmt.setString(2, bean.getEmail());
            pstmt.setString(3, bean.getSubject());
            pstmt.setString(4, bean.getPassword());
            pstmt.setInt(5, ref);
            pstmt.setInt(6, re_step);
            pstmt.setInt(7, re_level);
            pstmt.setString(8, bean.getContent());
 
            // 쿼리를 실행하시오.
            pstmt.executeUpdate();
            // 자원 반납
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    //모든 게시글을 리턴해주는 메소드 작성
    public Vector<BoardBean> getAllBoard()
    {
        //리턴할 객체 선언
        Vector<BoardBean> v = new Vector<>();
        
        getCon();
        
        
        try {
            //쿼리 준비
            String sql = "select * from board order by ref desc, re_step asc "//게시판 글을 내림차순으로 정렬하기 위한 sql코드
            //쿼리를 실행할 객체 선언
            pstmt = con.prepareStatement(sql);
            //쿼리 실행후 결과 저장
            rs = pstmt.executeQuery();
            //데이터 개수가 몇개인지 모르기에 반복문을 이용하여 데이터를 추출
            while(rs.next()) 
            {
                //데이터를 패키징 시키기(가방 = Boardbean 클래스를 이용) 패키지 안에 넣는다는 의미
                BoardBean bean = new BoardBean();
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); //reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
            
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
                //패키징한 데이터를 벡터에 저장
                v.add(bean);
            }
            
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return v;
    }
    
    //하나의 게시글을 리턴하는 메소드
    public BoardBean getOneBoard(int num) 
    {
        //리턴타입 선언(객체 생성)
        BoardBean bean = new BoardBean();
        getCon();
        try {
            
            //조회수 증가 쿼리
            String readsql = "update board set readcount = readcount+1 where num=?"//읽은 게시글의 조회수를 늘리기 위한 sql문
            pstmt = con.prepareStatement(readsql);
            pstmt.setInt(1, num);
            pstmt.execute();
            
            
            //쿼리 준비
            String sql = "select * from board where num=?";
            //쿼리 실행 객체
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1,num);
            //쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
            
            if(rs.next())
            {
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); //reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
                
            }
            
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return bean;
    }
    
}
 
cs




:

데이터베이스 접속 오류 (The Network Adapter could not establish the connection)

Back-End/Problems 2019. 5. 10. 09:54

java.sql.SQLException: Cannot create PoolableConnectionFactory (IO 오류: The Network Adapter could not establish the connection)



위와 같이 접속에러가 발생하게 되면

제어판 \ 모든 제어판 항목 \ 관리 도구 \ 서비스에 들어가면 











OracleXETNSListener의 상태가 시작이 안되고 있는 것을 확인할 수 있다.

수동으로 서비스 시작을 누르면 해결이 된다.




출처

https://m.blog.naver.com/PostView.nhn?blogId=syh_22&logNo=220627456918&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

:

19.05.09 계층형 게시판 (게시물 쓰기 구현)-책

Back-End/JSP 2019. 5. 9. 23:54

-계층형 게시판의 전체적인 구조-

 

브라우저 <-> jsp 파일 <-> 자바&빈즈 <-> 데이터베이스

(<->는 요청과 응답)

 

 

 

-소스파일 목록-

 

JSP

 * list.jsp (리스트 페이지)

 * post.jsp (쓰기 페이지)

 * read.jsp (읽기 페이지)

 * download.jsp (첨부파일 다운로드 페이지)

 * delete.jsp (삭제 페이지)

 * update.jsp (수정 페이지)

 * reply.jsp (답변 페이지)

서블릿

 

 * BoardPostServlet.java (쓰기 처리 서블릿)

 * BoardUpdatetServlet.java (수정 처리 서블릿)

 * BoardReplyServlet.java (답변 처리 서블릿)

 

기타 파일

 * style.css (스타일 시트 파일)

자바와 빈즈 

 

 1. BoardBean.java (게시판 자바 빈즈)

 2. BoardMgr.java (게시판 SQL문 처리 자바 파일)

 3. DBConnectionMgr.java (데이터베이스 연결 Connectionpool 자바 파일)

 4. UtilMgr.java (유틸 자바 파일)

 

 (컴파일 순서 : 1 -> 2 -> 3 -> 4)

 

 

 

 

-테이블 설계-

 

 칼럼명

데이터타입 

 

설명

 

num

 int(11)

 게시물의 유일성을 보장하는 게시번호를 저장하는 칼럼입니다.

 num값은 유일한 값 이므로 주키(primary key)와 자동적으로 증가하는

 auto_increment 속성으로 지정하였음

name

 varchar(20)

 게시물의 작성자 이름을 저장하는 칼럼입니다

subject

 varchar(50) 

 게시물의 제목을 저장하는 칼럼입니다. 

content 

 text 

 게시물의 본문 내용을 저장하는 칼럼입니다. 

pos 

 smallint(7) unsigned

 게시물의 상대적인 위치 값을 저장하여 화면에 순서대로 뿌려주는 

 역할을 담당하는 칼럼 입니다. 

ref 

 smallint(7)

 게시물이 답변 글일 경우 소속된 부모 글을 가리키는 번호를 저장하는 칼럼 입니다.

depth 

 smallint(7) unsigned

 게시물이 작성된 날짜를 저장하는 칼럼입니다.

regdate 

 date

 회원의 주소를 저장하는 칼럼입니다.

pass

 varchar(15) 

 게시물 작성자의 패스워드를 저장하는 칼럼입니다.

ip 

 varchar(15) 

 게시물을 저장할 때 작성자의 IP주소를 저장하는 칼럼입니다.

count 

 smallint(7) unsigned 

 게시물의 조회수를 저장하는 칼럼입니다.

filename 

 varchar(30) 

 업로드 된 파일의 이름을 저장하는 칼럼입니다.

filesize

 int(11) 

 업로드 된 파일의 크기를 저장하는 칼럼입니다.

 

 

 

  AUTO-IN CREMENT

 

  mysql에서 정수형으로 선언된 칼럼의 값이 한 행이 입력될 때 마다 자동적으로 증가하여 저장이 되는 속성입니다.

  기본값은 초기 값이 1이고 증가 값도 1입니다.

  AUTO_INCREMENT 속성으로 지정된 테이블은 INSERT 문에서 칼럼을 지정하지 않아도 자동으로 입력됩니다. (카운트되는 속성에 사용)

 

 

 

-mysql 테이블 생성-

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE tblBoard(
num INT(11NOT NULL AUTO_INCREMENT,
name VARCHAR(20),
subject VARCHAR(50),
content TEXT,
pos SMALLINT(7UNSIGNED,
ref SMALLINT(7),
depth SMALLINT(7UNSIGNED,
regdate DATE,
pass VARCHAR(15),
ip VARCHAR(15),
COUNT SMALLINT(7UNSIGNED,
filename VARCHAR(30),
filesize INT(11),
PRIMARY KEY(num)
);
cs

 

 

한글 깨짐 방지를 위한 문자셋 수정추가함

1
2
ALTER TABLE tblBoard
COLLATE UTF8_GENERAL_CI;
cs

 

 

 

-게시판의 쓰기, 읽기, 삭제 기능 구현-

 

 쓰기

   1. post.jsp 페이지에서 게시물을 입력하고,

   2. BoardPostServlet.java 서블릿에서 데이터베이스에 저장되는 부분을 처리함

   3. 게시물의 저장이 완료되면 자동적으로 게시판 읽기 기능을 담당하는 list.jsp 페이지로 이동

 읽기

   4. list.jsp 페이지에서 게시물의 제목을 클릭하면 게시판 읽기 기능을 담당하는 read.jsp 페이지로 이동

 삭제

   5. read.jsp 페이지에서 삭제를 클릭하여 delete.jsp 페이지로 이동하면 게시물의 비밀번호 입력란이 나오는데

      입력한 비밀번호가 일치하면 데이터베이스에 저장되어 있는 게시물을 삭제되고 list.jsp 페이지로 이동

      하지만, 일치하지 않으면 다시 비밀번호를 물어본다.

 

 

 

 

  -enctype 속성-

 

  <form> 태그의 속성인 method, action, enctype 등은 입력받은 데이터를 어떻게 처리할 것인지 세부적으로 설정하는데 사용된다.

  method는 전송 방식, action은 전송 목적지, enctype는 전송되는 데이터 형식을 설정한다.

 

  enctype 속성은 다음 세가지의 값으로 지정될 수 있다.

 

 

  1. application/www-form-urlencoded

 

  디폴트 값이다. enctype을 따로 설정하지 않으면 이 값이 설정된다.

  폼데이터는 서버로 전송되기 전에 URL-Encode 된다.

 

  2. multipart/form-data

 

  파일이나 이미지를 서버로 전송할 경우 이 방식을 사용한다.

  그렇게 하지 않으면 웹 서버로 데이터를 넘길때 파일의 경로명만 전송되고 파일 내용이 전송되지 않기 때문이다.

  그리고 이때 메소드는 post 값으로 지정해줘야 한다.

 

  3. text/plain

 

  이 형식은 인코딩을 하지 않은 문자 상태로 전송한다. 

 

 

 

 

게시물 쓰기 기능 구현

 

 

post.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>JSP Board</title>
<link href="style.css" rel="stylesheet" type="text/css">
<!-- 게시글 입력창 디자인 설정 -->
</head>
<body bgcolor="#FFFFCC">
    <div align="center">
        <br />
        <br />
        <table width="600" cellpadding="3">
            <tr>
                <td bgcolor="84F399" height="25" align="center">글쓰기</td>
            </tr>
        </table>
        <form name="postFrm" method="post" action="boardPost"
            enctype="multipart/form-data">
            <!-- 서블릿 BoardPostServlet의 매핑으로 설정된 boardPost 호출 -->
            <table width="600" cellpadding="3" align="center">
                <!-- cellpadding는 셀과 글의 사이 간격을 지정 -->
                <tr>
                    <td align=center>
                        <table align="center">
                            <tr>
                                <td width="20%">성 명</td>
                                <td width="80%"><input name="name" size="10" maxlength="8"></td>
                                <!-- 성명안에 들어갈수 있는 문자의 길이를 8칸으로 한다. -->
                            </tr>
 
                            <tr>
                                <td>제 목</td>
                                <td><input name="subject" size="50" maxlength="30"></td>
                                <!-- 제목안에 들어갈수 있는 문자의 길이를 30칸으로 한다. -->
                            </tr>
 
                            <tr>
                                <td>내 용</td>
                                <td><textarea name="content" rows="10" cols="50"></textarea></td>
                            </tr>
 
                            <tr>
                                <td>비밀 번호</td>
                                <td><input type="password" name="pass" size="15"
                                    maxlength="30"></td>
                            </tr>
 
                            <tr>
                                <td>파일 찾기</td>
                                <td><input type="file" name="filename" size="50"
                                    maxlength="50"></td>
                            </tr>
                            <!-- file는 파일 불러오기 창을 띄우는 기능을 제공한다.-->
                            <tr>
                                <td>내용 타입</td>
                                <!-- 내용의 타입을 HTML과 TEXT를 선택할수 있도록 만들어준다. -->
                                <td>HTML<input type=radio name="contentType" value="HTTP">&nbsp;&nbsp;&nbsp;
                                    TEXT<input type=radio name="contentType" value="TEXT" checked>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="2"><hr /></td>
                            </tr>
                            <tr>
                                <td colspan="2">
                                    <!-- 하단에 다른페이지로 넘어갈 버튼들을 만든다. --> <input type="submit"
                                    value="등록"> <input type="reset" value="다시쓰기"> <input
                                    type="button" value="리스트"
                                    onClick="javascript:location.href='list.jsp'">
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
            <input type="hidden" name="ip" value="<%=request.getRemoteAddr()%>">
            <!-- 게시물을 등록한 사용자의 ip주소를 가져온다. -->
        </form>
    </div>
</body>
</html>
cs

 

 

BoardPostServlet.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
package ch15;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
                                        //게시물 쓰기 처리 서블릿
@WebServlet("/ch15/boardPost")//서블릿을 사용하기 위한 맵핑 이름을 선언한다.
public class BoardPostServlet extends HttpServlet{//HttpServlet를 상속받음
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{//post.jsp에서 form의 method가 post이기 때문에 서블릿의

                                                        doPost를 호출

        request.setCharacterEncoding("EUC-KR"); //post.jsp 에서 입력받은 문자열의 한글 인코딩 설정
        BoardMgr bMgr = new BoardMgr(); //문자를 입력하기 위해 BoardMgr 객체를 생성하고 insert메소드를 호출
        bMgr.insertBoard(request);
        response.sendRedirect("list.jsp"); //tblBoard 테이블에 저장후에 list.jsp 페이지로 응답한다.    
    }
}
 

cs

 

 

 

-------미완성-----

:

19.05.09 JSP 게시판 - 전체 게시글 보기 구현 (~동영상 45강)

Back-End/JSP 2019. 5. 9. 20:49

전체 게시글 보기 구현

글쓰기 (BoardWriteForm.jsp) --> 글쓰기처리 (BoardWriteProc.jsp) --> 글쓰기 저장 (BoardDAO) --> 전체게시글 보기 (BoardList.jsp)

 

 

BoardWriteForm.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
36
37
38
39
40
41
42
43
44
45
46
47
48
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<center>
<h2> 게시글 쓰기 </h2> 
 
<form action="BoardWriteProc.jsp" method="post">
<table width = "600" border="1" bordercolor = "gray" bgcolor = "skyblue"> <!-- bordercolor는 선색깔 지정 -->
    <tr height = "40">
        <td align = "center" width = "150"> 작성자 </td> <!-- ref는 데이터베이스에서 처리하기 때문에 따로 받지 않는다. -->
        <td width = "450"> <input type = "text" name = "writer" size = "60"></td> 
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 제목 </td>
        <td width = "450"> <input type = "text" name = "subject" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 이메일 </td>
        <td width = "450"> <input type = "text" name = "email" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 비밀번호 </td>
        <td width = "450"> <input type = "password" name = "password" size = "61"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 글내용 </td>
        <td width = "450"><textarea rows = "10" cols = "50" name = "content"></textarea></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" colspan = "2">
            <input type = "submit" value = "글쓰기"> &nbsp;&nbsp;
            <input type = "reset" value = "다시작성"> &nbsp;&nbsp;
            <button onclick = "location.href='BoardList.jsp'">전체 게시글 보기</button> <!-- 클릭하면 BoardList.jsp페이지로 넘어가는 버튼-->
        </td>
    </tr>
</table>
</form>
</center>
</body>
</html>
 
cs

 

 

BoardWriteProc.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
36
37
38
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
    <% 
    request.setCharacterEncoding("EUC-KR"); //한글깨짐 방지 문자셋 설정
%>
    <!-- 빈파일에서 게시글 작성한 데이터를 한번에 읽어들임 -->
    <!-- use빈을 사용하여 자바빈을 사용, id는 빈클래스를 지칭하는 참조 변수명 -->
    <!-- 빈파일에 있는 값들을 받는다. -->
    <!-- 빈파일에 없는 값들은 null로 들어온다 null값으로 들어온 것들은 데이터베이스에서 들어올 값들이니 걱정x -->
 
    <jsp:useBean id="boardbean" class="model.BoardBean">
        <jsp:setProperty name="boardbean" property="*" />
    </jsp:useBean>
 
    <%
    //데이터베이스 쪽으로 빈클래스를 넘겨줌
    BoardDAO bdao = new BoardDAO();
    
    //데이터 저장 메소드를 호출
    bdao.insertBoard(boardbean);
    
    //게시글 저장후 전체 게시글 보기
    response.sendRedirect("BoardList.jsp");
 
%>
 
 
 
 
</body>
</html>
 
cs

 

BoardBean.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package model;
 
public class BoardBean { //빈클래스 생성
    
    private int num;
    private String email;
    private String subject;
    private String password;
    private String reg_date;
    private String writer;
    private int ref;
    private int re_step;
    private int re_level;
    private int readcount;
    private String content;
    
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getReg_date() {
        return reg_date;
    }
    public void setReg_date(String reg_date) {
        this.reg_date = reg_date;
    }
    public String getWriter() {
        return writer;
    }
    public void setWriter(String writer) {
        this.writer = writer;
    }
    public int getRef() {
        return ref;
    }
    public void setRef(int ref) {
        this.ref = ref;
    }
    public int getRe_step() {
        return re_step;
    }
    public void setRe_step(int re_step) {
        this.re_step = re_step;
    }
    public int getRe_level() {
        return re_level;
    }
    public void setRe_level(int re_level) {
        this.re_level = re_level;
    }
    public int getReadcount() {
        return readcount;
    }
    public void setReadcount(int readcount) {
        this.readcount = readcount;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    
    
}
 
cs

 

BoardDAO.java(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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package model;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;
 
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.naming.Context;
 
public class BoardDAO {
 
    // 데이터베이스에 연결하기 위한 설정
    Connection con;
    PreparedStatement pstmt;
    ResultSet rs;
 
    // 데이터베이스의 커넥션들을 사용하도록 설정하는 메소드
    public void getCon() {
 
        try { // 데이터베이스에 접속할때는 예외처리를 해주어야한다.
 
            Context initctx = new InitialContext(); // 외부에서 데이터를 읽어들어야 하기 때문에 Context 객체 생성
            // 톰캣 서버에 정보를 담아놓은 곳으로 이동함
            Context envctx = (Context) initctx.lookup("java:comp/env"); // lookup메소드를 이용해서 자료를 읽어오는 코드
            DataSource ds = (DataSource) envctx.lookup("jdbc/pool"); // datasource 객체를 선언 , 오브젝트 타입이기 때문에 타입변환을 한다.
 
            con = ds.getConnection(); // 데이터 소스를 기준으로 커넥션을 연결함
        } catch (Exception e) {
            e.printStackTrace(); // 어느부분이 잘못되었는지 알려주는 예외처리
        }
    }
 
    // 하나의 새로운 게시글이 넘어와서 저장되는 메소드
    public void insertBoard(BoardBean bean) {
        getCon();
        // 빈클래스에 넘어오지 않았던 데이터들을 초기화 해주어야 한다.
 
        int ref = 0// 글그룹을 의미한다, 쿼리를 실행시켜서 가장 큰 ref값을 가져온후 +1을 더해주면 된다.
        int re_step = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
        int re_level = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
 
        try {
 
            // 가장큰 ref값을 읽어오는 쿼리 준비함 (새로운 글은 ref가 가장크기 때문)
            String refsql = "select max(ref) from board"// board테이블로부터 가장큰 ref를 검색
            // 쿼리를 실행할 객체
            pstmt = con.prepareStatement(refsql);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
            if (rs.next()) { // 쿼리(rs)가 결과값이 있다면 실행하는 구문
                ref = rs.getInt(1+ 1// 최대값에 1을 더해서 글그룹을 설정. 새로운글은 ref숫자가 하나씩 올라가야 하기 때문
            }
 
            // 실제로 게시글 전체값을 테이블에 저장
            String sql = "insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)"// ?가 아니라 시퀀스를 사용해
                                                                                                    // 시퀀스에 이미 들어가있는값의
                                                                                                    // 다음값을 자동으로 매핑해서
                                                                                                    // 넣어준다.
            pstmt = con.prepareStatement(sql);
            // ?에 값을 매핑한다. //0은 카운트값이기때문 0을 넣어주었다
            pstmt.setString(1, bean.getWriter());
            pstmt.setString(2, bean.getEmail());
            pstmt.setString(3, bean.getSubject());
            pstmt.setString(4, bean.getPassword());
            pstmt.setInt(5, ref);
            pstmt.setInt(6, re_step);
            pstmt.setInt(7, re_level);
            pstmt.setString(8, bean.getContent());
 
            // 쿼리를 실행하시오.
            pstmt.executeUpdate();
            // 자원 반납
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    //모든 게시글을 리턴해주는 메소드 작성
    public Vector<BoardBean> getAllBoard()
    {
        //리턴할 객체 선언
        Vector<BoardBean> v = new Vector<>();
        
        getCon();
        
        
        try {
            //쿼리 준비
            String sql = "select * from board order by ref desc, re_step asc "//게시판 글을 내림차순으로 정렬하기 위한 sql코드
            //쿼리를 실행할 객체 선언
            pstmt = con.prepareStatement(sql);
            //쿼리 실행후 결과 저장
            rs = pstmt.executeQuery();
            //데이터 개수가 몇개인지 모르기에 반복문을 이용하여 데이터를 추출
            while(rs.next()) 
            {
                //데이터를 패키징 시키기(가방 = Boardbean 클래스를 이용) 패키지 안에 넣는다는 의미
                BoardBean bean = new BoardBean();
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); //reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
            
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
                //패키징한 데이터를 벡터에 저장
                v.add(bean);
            }
            
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return v;
    }
}
 
cs

 

BoardList.jsp(게시글 리스트)

 
  cs

 

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
<%@page import="java.util.Vector"%>
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
<%
 
    //전체 게시글의 내용을 jsp쪽으로 가져와야함
    //길이를 정확히 알 수 없기 때문에 가변길이인 벡터로 받는다.
    BoardDAO bdao = new BoardDAO();
 
    //전체게시글을 리턴 받아주는 소스 (나중엔 개수가 많아지므로 다시 수정할 예정)
    Vector<BoardBean> vec = bdao.getAllBoard();
    
%>
<center>
<h2> 전체 게시글 보기 </h2>
<table width = "700" border = "1" bgcolor = "skyblue">
    <tr height = "40">
        <td width = "50" align = "center"> 번호 </td>
        <td width = "320" align = "center"> 제목 </td>
        <td width = "100" align = "center"> 작성자 </td>
        <td width = "150" align = "center"> 작성일 </td>
        <td width = "80" align = "center"> 조회수 </td>
    </tr>
<%
    for(int i = 0; i<vec.size(); i++)
    {
        BoardBean bean = vec.get(i); //벡터에 저장되어있는 bean클래스를 하나씩 추출
    
%>
    <tr height = "40">
        <td width = "50" align = "center"> <%=i+1%> </td> <!-- 숫자가 하나씩 올라가게 하기위해서 i+1을 해준다 -->
                                                            <!-- getNum()을 쓰면 순서가 복잡해지기 때문 -->
        <td width = "320" align = "center"> <a href = "BoardInfo.jsp?num=<%=bean.getNum()%>"> 
        <%=bean.getSubject()%></a>    </td>
        <!-- BoardInfo.jsp파일(정보를 확인하기 위한파일)에 Num값을 넘겨준다 --> 
        <td width = "100" align = "center"> <%=bean.getWriter() %></td>
        <td width = "150" align = "center"> <%=bean.getReg_date() %></td>
        <td width = "80" align = "center"> <%=bean.getReadcount() %> </td>
    </tr>
    <%%>
    <tr height = "40">
        <td align = "center" colspan = "5"><!-- 버튼을 클릭하면 BoardWriteForm.jsp파일로 넘어간다.-->
        <input type = "button" value = "글쓰기" onclick="location.href='BoardWriteForm.jsp'"></td>
        </tr>
        
        
        
</table>
</center>
</body>
</html>
cs

 

 

 

 

:

오라클 한글 깨짐 문제 해결

Back-End/Problems 2019. 5. 8. 22:45

 

페이지 문자셋을 설정할 때 문자셋을 전부다 통일해줘야 DB로 자료를 보낼때 한글이 깨지지 않는다.

 

(EUC-KR로 할꺼면 전부다 EUC-KR로 하고, UTF-8로 할꺼면 모든 페이지의 문자셋을 UTF-8로 해주어야 한다.)

 

 

 

 

 

출처

https://androphil.tistory.com/11

:

19.05.08 JSP 게시판 - 시스템 구조 및 게시판 만들기 (~동영상 43강)

Back-End/JSP 2019. 5. 8. 22:15

 

-게시판의 구조 (글읽기 옆에 답변형 추가됨)-



-테이블 구조(총 11개의 컬럼을 만들어 데이터를 저장)-

글 그룹 : 글을 묶어놓은 그룹

글 스텝 : 글의 단계 (ex - 글의 답변의 답변, 글의 답변 같은 단계별로 넘어가는 글)

글 레벨 : 글을 보여주는 순서 (ex-최신순서대로 보여줄지.)


컬럼명

설명

비고

Num 

글번호

자동증가 int

Writer

글쓴이 

String 

Email

이메일 

String 

Subject

글제목 

String 

Password

글 비밀번호 

String 

Reg_date

글 작성날짜 

Date 

Ref

글 그룹 

Int 

Re_step

글 스텝

Int 

Re_level

글 레벨 

Int 

Readcount

조회수 

Int 

Content 

글내용 

String 



예시)


글번호

글제목

ref

Re_step 

Re_level 

베스킨라빈스 

1

1

[re] 난 나뚜르

1

2

3

            [re] 나뚜르 나도 

1

3

4

   [re] 베스킨좋아 

1

2

2



실제 작성시 정렬되는 순서

글번호

글제목

ref

Re_step 

Re_level 

1

베스킨라빈스 

1

1

           [re]베스킨좋아

           [re]난 나뚜르 

               [re] 나뚜르 나도


 

[게시글 쓰기] 작성 순서


글쓰기 > 글쓰기 처리 > 글쓰기 저장 > 전체게시글 보기

 

 


-예제 및 출력 결과-

 

(글쓰기 저장까지 구현됨)

글쓰기 (BoardWriteForm.jsp) --> 글쓰기처리 (BoardWriteProc.jsp) --> 글쓰기 저장 (BoardDAO) --> 전체게시글 보기 (BoardList.jsp)


1.데이터베이스 테이블, 시퀀스 (게시판관련된 숫자를 자동으로 생성하기 위해) 만들기

 

 

 

 

 

 

2. server.xml파일 수정 (커넥션풀 사용할수있도록) - (마지막부분)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->
 
        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log" suffix=".txt"/>
 
      <Context docBase="ch11" path="/ch11" reloadable="true" source="org.eclipse.jst.jee.server:ch11"/><Context docBase="ch14" path="/ch14" reloadable="true" source="org.eclipse.jst.jee.server:ch14"/><Context docBase="Board" path="/Board" reloadable="true" source="org.eclipse.jst.jee.server:Board">
          <Resource auth = "Container" driverClassName = "oracle.jdbc.driver.OracleDriver" loginTimeout = "10" maxWait = "5000" name = "jdbc/pool" password = "123456" type = "javax.sql.DataSource" url = "jdbc:oracle:thin:@localhost:1521:xe" username = "system"/> 
      </Context>//데이터베이스를 사용하기 위한 커넥션 풀 코드 추가 및 수정, 바로 위쪽 줄 (org.eclipse.jst.jee.server:Board"/> /제거
      </Host>
    </Engine>
  </Service>
</Server>
cs




3. 페이지 작성

 

BoardWriteForm.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
36
37
38
39
40
41
42
43
44
45
46
47
48
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<center>
<h2> 게시글 쓰기 </h2> 
 
<form action="BoardWriteProc.jsp" method="post">
<table width = "600" border="1" bordercolor = "gray" bgcolor = "skyblue"> <!-- bordercolor는 선색깔 지정 -->
    <tr height = "40">
        <td align = "center" width = "150"> 작성자 </td> <!-- ref는 데이터베이스에서 처리하기 때문에 따로 받지 않는다. -->
        <td width = "450"> <input type = "text" name = "writer" size = "60"></td> 
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 제목 </td>
        <td width = "450"> <input type = "text" name = "subject" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 이메일 </td>
        <td width = "450"> <input type = "text" name = "email" size = "60"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 비밀번호 </td>
        <td width = "450"> <input type = "password" name = "password" size = "61"></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" width = "150"> 글내용 </td>
        <td width = "450"><textarea rows = "10" cols = "50" name = "content"></textarea></td>
    </tr>
    
    <tr height = "40">
        <td align = "center" colspan = "2">
            <input type = "submit" value = "글쓰기"> &nbsp;&nbsp;
            <input type = "reset" value = "다시작성"> &nbsp;&nbsp;
            <button onclick = "location.href='BoardList.jsp'">전체 게시글 보기</button> <!-- 클릭하면 BoardList.jsp페이지로 넘어가는 버튼-->
        </td>
    </tr>
</table>
</form>
</center>
</body>
</html>
 
cs

 

 

BoardWriteProc.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
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
    <% 
    request.setCharacterEncoding("EUC-KR"); //한글깨짐 방지 문자셋 설정
%>
    <!-- 빈파일에서 게시글 작성한 데이터를 한번에 읽어들임 -->
    <!-- use빈을 사용하여 자바빈을 사용, id는 빈클래스를 지칭하는 참조 변수명 -->
    <!-- 빈파일에 있는 값들을 받는다. -->
    <!-- 빈파일에 없는 값들은 null로 들어온다 null값으로 들어온 것들은 데이터베이스에서 들어올 값들이니 걱정x -->
 
    <jsp:useBean id="boardbean" class="model.BoardBean">
        <jsp:setProperty name="boardbean" property="*" />
    </jsp:useBean>
 
    <%
    //데이터베이스 쪽으로 빈클래스를 넘겨줌
    BoardDAO bdao = new BoardDAO();
    
    //데이터 저장 메소드를 호출
    bdao.insertBoard(boardbean);
 
%>
 
 
 
 
</body>
</html>
 
cs

 

 

BoardDAO.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package model;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.naming.Context;
 
public class BoardDAO {
 
    // 데이터베이스에 연결하기 위한 설정
    Connection con;
    PreparedStatement pstmt;
    ResultSet rs;
 
    // 데이터베이스의 커넥션풀들을 사용하도록 설정하는 메소드
    public void getCon() {
 
        try { // 데이터베이스에 접속할때는 예외처리를 해주어야한다.
 
            Context initctx = new InitialContext(); // 외부에서 데이터를 읽어들어야 하기 때문에 Context 객체 생성
            // 톰캣 서버에 정보를 담아놓은 곳으로 이동함
            Context envctx = (Context) initctx.lookup("java:comp/env"); // lookup메소드를 이용해서 자료를 읽어오는 코드
            DataSource ds = (DataSource) envctx.lookup("jdbc/pool"); // datasource 객체를 선언 , 오브젝트 타입이기 때문에 타입변환을 한다.

           

            //Resource 이름을 매개값으로 주어 DataResource 객체를 리턴
   
            //외부에서 데이터를 읽어들이는 Context 객체를 생성
            //그 객체의 lookup 메소드로 톰캣서버 정보를 읽어들이고
            //톰캣 서버정보를 읽어들인 객체의 lookup 메소드 리소스이름을 매개값으로 주어
            //데이터소스객체 (커넥션풀 사용할때 쓰기로한 객체)를 얻는다.
            //(커넥션풀)데이터소스를 이용하여 접속

            

 
            con = ds.getConnection(); // 데이터 소스를 기준으로 커넥션을 연결함
        } catch (Exception e) {
            e.printStackTrace(); // 어느부분이 잘못되었는지 알려주는 예외처리
        }
    }
 
    // 하나의 새로운 게시글이 넘어와서 저장되는 메소드
    public void insertBoard(BoardBean bean) {
        getCon();
        // 빈클래스에 넘어오지 않았던 데이터들을 초기화 해주어야 한다.
 
        int ref = 0// 글그룹을 의미한다, 쿼리를 실행시켜서 가장 큰 ref값을 가져온후 +1을 더해주면 된다.
        int re_step = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
        int re_level = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
 
        try {
 
            // 가장큰 ref값을 읽어오는 쿼리 준비함 (새로운 글은 ref가 가장크기 때문)
            String refsql = "select max(ref) from board"// board테이블로부터 가장큰 ref를 검색
            // 쿼리를 실행할 객체
            pstmt = con.prepareStatement(refsql);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
            if (rs.next()) { // 쿼리(rs)가 결과값이 있다면 실행하는 구문
                ref = rs.getInt(1+ 1// 최대값에 1을 더해서 글그룹을 설정. 새로운글은 ref숫자가 하나씩 올라가야 하기 때문
            }
 
            // 실제로 게시글 전체값을 테이블에 저장
            String sql = "insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)"// ?가 아니라 시퀀스를 사용해
                                                                                                    // 시퀀스에 이미 들어가있는값의
                                                                                                    // 다음값을 자동으로 매핑해서
                                                                                                    // 넣어준다.
            pstmt = con.prepareStatement(sql);
            // ?에 값을 매핑한다. //0은 카운트값이기때문 0을 넣어주었다
            pstmt.setString(1, bean.getWriter());
            pstmt.setString(2, bean.getEmail());
            pstmt.setString(3, bean.getSubject());
            pstmt.setString(4, bean.getPassword());
            pstmt.setInt(5, ref);
            pstmt.setInt(6, re_step);
            pstmt.setInt(7, re_level);
            pstmt.setString(8, bean.getContent());
 
            // 쿼리를 실행하시오.
            pstmt.executeUpdate();
            // 자원 반납
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
cs

 

 

BoardBean.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package model;
 
public class BoardBean { //빈클래스 생성
    
    private int num;
    private String email;
    private String subject;
    private String password;
    private String reg_date;
    private String writer;
    private int ref;
    private int re_step;
    private int re_lever;
    private int readcount;
    private String content;
    
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getReg_date() {
        return reg_date;
    }
    public void setReg_date(String reg_date) {
        this.reg_date = reg_date;
    }
    public String getWriter() {
        return writer;
    }
    public void setWriter(String writer) {
        this.writer = writer;
    }
    public int getRef() {
        return ref;
    }
    public void setRef(int ref) {
        this.ref = ref;
    }
    public int getRe_step() {
        return re_step;
    }
    public void setRe_step(int re_step) {
        this.re_step = re_step;
    }
    public int getRe_lever() {
        return re_lever;
    }
    public void setRe_lever(int re_lever) {
        this.re_lever = re_lever;
    }
    public int getReadcount() {
        return readcount;
    }
    public void setReadcount(int readcount) {
        this.readcount = readcount;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    
}
 
cs

 

 

:

useBean HTTP 500에러

Back-End/Problems 2019. 5. 8. 18:09

-오류 내용-

심각: Servlet.service() for servlet [jsp] in context with path [/Board2] threw exception [/TestProc.jsp (line: [11], column: [0]) 

The value for the useBean class attribute [model.TestBean] is invalid.] with root cause
org.apache.jasper.JasperException: /TestProc.jsp (line: [11], column: [0]) The value for the useBean class attribute [model.TestBean] is invalid.



해결법 : 서버 삭제후 다시 만들어서 실행함

: