JSP파일 직접 접근 방지

웹으로 접속하는 사용자가 .do가 아닌 .jsp로 접근할 가능성도 있다. .jsp로 직접 접근을 하지 못하게 막기 위해서는 web.xml에 <security-constraint> 코드를 추가하면 된다.

 

[경로: src/main/webapp/WEB-INF/web.xml]

1
2
3
4
5
6
7
8
9
10
11
12
<security-constraint>
  <web-resource-collection>
      <web-resource-name>Prevent JSP</web-resource-name>
      <description>Prevent JSP</description>
      <url-pattern>*.jsp</url-pattern> <!-- 제약을 걸 자원 -->
      <http-method>GET</http-method> <!-- 제약을 걸 HTTP 메서드 -->
      <http-method>POST</http-method><!-- 제약을 걸 HTTP 메서드 -->
  </web-resource-collection>
  <auth-constraint>
      <role-name></role-name>
  </auth-constraint>
</security-constraint>
cs

 

URL에 http://localhost:9090/MyMVC/index.jsp라고 쳐서 들어가면 HTTP Status 403 - Access to the requested resource has been denied 에러가 뜬다. 즉, 접근할 수 없도록 서버에서 차단한 것이다.


properties 파일

여러 JSP파일을 호출할 때 서브 컨트롤러를 매핑해주는 파일

[경로: src/main/webapp/WEB-INF/command.properties]

1
2
3
4
5
6
7
8
# comment
# key=value
/index.do=common.controller.IndexAction
#board
/board/input.do=board.controller.BoardWriteFormAction
/board/insert.do=board.controller.BoardInsertAction
/board/list.do=board.controller.BoardListAction
/board/view.do=board.controller.BoardViewAction
cs

만약 웹에서 http://localhost:9090/MyMVC/board/input.do를 입력하면 BoardWriteFormAction 서브 컨트롤러가 작동한다.

 


게시판 글쓰기 페이지

  • 서브 컨트롤러: BoardWriteFormAction
  • JSP: src/main/webapp/board/input.jsp

[경로: src/main/java/board.controller/BoardWriteFormAction.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
public class BoardWriteFormAction extends AbstractAction {
 
    @Override
    public void execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
        
        //뷰페이지 지정
        this.setViewName("/board/input.jsp");
        //이동방식 지정
        this.setRedirect(false); //forward이동
    }
 
}
 
cs

 

[경로: src/main/webapp/board/input.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=UTF-8"
    pageEncoding="UTF-8"%>
 
<!-- content -->
<div class="container">
    <h1>MVC Board</h1>
    <br><br>
    <form name="bbsF" method="post" action="insert.do">
        <table border="1">
            <tr>
                <th width="20%">글제목</th>
                <td width="80%">
                    <input type="text" name="title" id="title" placeholder="Title" required>
                </td>
            </tr>
            <tr>
                <th>작성자</th>
                <td>
                    <input type="text" name="name" id="name" placeholder="Name" required>
                </td>
            </tr>
            <tr>
                <th>글내용</th>
                <td>
                    <textarea name="content" id="content" placeholder="Content" rows="7" cols="60"></textarea>
                </td>
            </tr>
            <tr>
                <th>비밀번호</th>
                <td>
                    <input type="password" name="passwd" id="passwd" placeholder="Password" required>
                </td>
            </tr>
            <tr>
                <th>첨부파일</th>
                <td>
                    <input type="file" name="fileName" id="fileName">
                </td>
            </tr>
            <tr>
                <td colspan="2" style="text-align:center">
                    <button>글쓰기</button>
                    <button type="reset">다시쓰기</button>
                </td>
            </tr>
        </table>
    </form>
</div>
cs

http://localhost:9090/MyMVC/board/input.do

 


게시판 글쓰기 구현

  • 서브 컨트롤러: BoardInsertAction
  • JSP: message.jsp

[경로: src/main/java/board.controller/BoardInsertAction.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
public class BoardInsertAction extends AbstractAction {
 
    @Override
    public void execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
        //1. 사용자가 입력한 값 받기
        String title = req.getParameter("title");
        String name = req.getParameter("name");
        String content = req.getParameter("content");
        String passwd = req.getParameter("passwd");
        
        //첨부파일명, 파일크기 받기 => 나중에
        String fileName = null;
        long fileSize = 0;
        
        //2. 유효성 체크
        if(title==null || name==null || passwd==null || title.trim().isBlank()
                || name.trim().isBlank() || passwd.trim().isBlank()) {
            this.setRedirect(true); //redirect이동
            this.setViewName("input.do");//input.do로 redirect이동
            return;
        }
        //3. 1번에서 받은 값 BoardVO객체에 담기
        BoardVO vo = new BoardVO(0, name, passwd, title, content, null0, fileName, fileSize);
        //4. BoardDAO 생성 후 insertBoard() 호출
        BoardDAO dao = new BoardDAO();
        int n = dao.insertBoard(vo);
        //5. 그 결과 메시지, 이동경로 설정해서 req에 저장하기
        String msg = (n>0)? "글 등록 완료":"글 등록 실패";
        String loc = (n>0)? "list.do":"javascript:history.back()";
        
        //request에 msg와 loc 저장 => message.jsp에서 꺼내야 함
        req.setAttribute("msg", msg);
        req.setAttribute("loc", loc);
        
        //뷰페이지 지정
        this.setViewName("/board/message.jsp");
        //이동방식 지정
        this.setRedirect(false); //forward이동
    }
 
}
cs

 

[경로: src/main/webapp/board/message.jsp]

1
2
3
4
5
6
7
8
9
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<script type="text/javascript">
    alert('${msg}');
    /* requestScope.msg ==> request에서 찾는다.
    sessionScope.msg ==> 세션에서 찾는다.
    생략 가능 */
    location.href = '${loc}';
</script>
cs

 


게시판 글쓰기 DB연동

1) SQL문

[경로: src/main/webapp/board/mvc_board.sql]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DROP table mvc_board;
--단순형 게시판
CREATE table mvc_board(
    num NUMBER(8primary key--글번호
    name VARCHAR2(30not null--작성자
    passwd VARCHAR2(20not null--글 비밀번호
    title VARCHAR2(300not null--글제목
    content VARCHAR2(2000), --글내용
    wdate DATE default SYSDATE, --작성일
    readnum NUMBER(8default 0--조회수
    fileName VARCHAR2(500), --첨부파일명
    fileSize NUMBER(8--첨부파일 크기
);
 
DROP sequence mvc_board_seq;
 
CREATE sequence mvc_board_seq
START WITH 1
INCREMENT BY 1
NOCACHE;
cs

 

2) BoardVO 객체

[경로: src/main/java/board.model/BoardVO.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package board.model;
 
import java.sql.Date;
 
public class BoardVO {
    //멤버변수(property)
    private int num;
    private String name;
    private String passwd;
    private String title;
    private String content;
    private java.sql.Date wdate;
    private int readnum;//조회수
    private String fileName;//첨부파일명
    private long fileSize;//첨부파일 크기
    
    //기본생성자
    public BoardVO() {
        
    }
    
    //인자생성자
    public BoardVO(int num, String name, String passwd, String title, String content, Date wdate, int readnum,
            String fileName, long fileSize) {
        super();
        this.num = num;
        this.name = name;
        this.passwd = passwd;
        this.title = title;
        this.content = content;
        this.wdate = wdate;
        this.readnum = readnum;
        this.fileName = fileName;
        this.fileSize = fileSize;
    }
    
    //setter, getter
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPasswd() {
        return passwd;
    }
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public java.sql.Date getWdate() {
        return wdate;
    }
    public void setWdate(java.sql.Date wdate) {
        this.wdate = wdate;
    }
    public int getReadnum() {
        return readnum;
    }
    public void setReadnum(int readnum) {
        this.readnum = readnum;
    }
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public long getFileSize() {
        return fileSize;
    }
    public void setFileSize(long fileSize) {
        this.fileSize = fileSize;
    }
    
    //toString()
    @Override
    public String toString() {
        return "BoardVO [num=" + num + ", name=" + name + ", title=" + title + ", content=" + content + ", wdate="
                + wdate + ", readnum=" + readnum + ", fileName=" + fileName + ", fileSize=" + fileSize + "]";
    }
    
}
cs

 

3) BoardDAO

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 class BoardDAO {
    
    private DataSource ds;
    private Connection con;
    private PreparedStatement ps;
    private ResultSet rs;
    
    public BoardDAO() {
        try {
            Context ctx = new InitialContext();
            ds = (DataSource)ctx.lookup("java:comp/env/jdbc/myoracle");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            if(rs!=null) rs.close();
            if(ps!=null) ps.close();
            if(con!=null) con.close();            
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
cs

게시판 글목록 페이지

  • 서브 컨트롤러: BoardListAction
  • JSP: src/main/webapp/board/list.jsp

# 페이징 처리

  1. 총 게시글 수: totalCount
  2. 한 페이지에 보여줄 글의 개수: oneRecordPage (= 5로 하자)
  3. 페이지 수: pageCount
총 게시글 수(totalCount) 한 페이지에 보여줄 글의 개수
(oneRecordPage)
페이지 수(pageCount)
1, 2, 3, 4, 5 5 1
6, 7, 8, 9, 10 5 2
11, 12, 13, 14, 15 5 3
16, 17, 18, 19, 20 5 4
if(totalCount % oneRecordPage == 0){ //totalCount가 5, 10, 15, 20일 때
	pageCount = totalCount/oneRecordPage;
}else{
	pageCount = totalCount/oneRecordPage + 1;
}

==> 한 줄로 줄이면

pageCount = (totalCount - 1)/oneRecordPage + 1;

 

4. jsp에서 페이지 네비게이션 구현

링크 걸기 => 현재 보여줄 페이지 번호pageNum이라는 파라미터 값으로 전달한다.

[<a href="list.do?pageNum=2">  2 </a>]

 

5. BoardListAction(서브 컨트롤러)에서 pageNum 파라미터 값 받기

pageNum을 이용해서 DB에서 데이터를 끊어 가져오기 위한 연산 수행

--rownum을 활용한 페이징 처리
SELECT * FROM(
SELECT rownum rn, a.* FROM
(SELECT * FROM mvc_board ORDER BY num DESC) a)
WHERE rn BETWEEN 1 AND 5;
현재 보여줄 페이지 번호
(pageNum)
한 페이지에 보여줄 글의 개수
(oneRecordPage)
start end
1 5 1 5
2 5 6 10
3 5 11 15
4 5 16 20
int end = pageNum * oneRecordPage;
int start = end - (oneRecordPage - 1);

 


[경로: src/main/java/board.controller/BoardListAction.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
public class BoardListAction extends AbstractAction {
 
    @Override
    public void execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
        //0. pageNum 파라미터값 받기
        String pageNumStr = req.getParameter("pageNum");
        if(pageNumStr==null) {
            pageNumStr="1"//default 페이지를 1페이지로 지정
        }
        int pageNum = Integer.parseInt(pageNumStr.trim());
        if(pageNum<1) {
            pageNum = 1;
        }
        
        //BoardDAO 생성 listBoard() 호출
        BoardDAO dao = new BoardDAO();
        //1. 총 게시글 수 가져오기
        int totalCount = dao.getTotalCount();
        
        //2. 한 페이지당 보여줄 목록 개수 정하기 => 5개씩 보여주기
        int oneRecordPage = 5;
        
        //3. 총 페이지수 구하기
        int pageCount = (totalCount - 1)/oneRecordPage + 1;
        System.out.println("pageCount: " + pageCount);
       //4. jsp에서 페이지 네비게이션 출력 => 링크 ==> pageNum파라미터 전달
        if(pageNum > pageCount) {
            pageNum = pageCount; //마지막 페이지로 지정
       } //url에 pageNum을 직접 치고 들어오는 경우를 방지
        
//5. pageNum을 이용해서 DB에서 끊어올 범위 정하기
        int end = pageNum * oneRecordPage;
        int start = end - (oneRecordPage - 1);
        //6. 게시글 목록 가져오기
        List<BoardVO> boardList = dao.listBoard(start, end);
        
        //반환하는 List<BoardVO> 객체를 req에 저장
        req.setAttribute("boardAll", boardList);
        //페이지 관련된 각각의 숫자들을 req에 저장
        req.setAttribute("totalCount", totalCount);
        req.setAttribute("pageCount", pageCount);
        req.setAttribute("pageNum", pageNum);
        
        //뷰페이지 지정
        this.setViewName("list.jsp");
        //이동방식 지정
        this.setRedirect(false); //forward방식
    }
 
}
cs
 
 
 

 

[경로: src/main/webapp/board/list.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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!-- ---------------------------------------------------- -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!-- 제어문은 core태그에 모여 있음. 숫자, 날짜 format은 ftm태그에 있음- -->
 
<!-- content -->
<div class="container">
    <h1>MVC Board</h1>
    <br>
    [<a href="input.do">글쓰기</a>]
    <br><br>
    <table border="1">
        <tr>
            <th class="m1" width="10%">글번호</th>
            <th class="m1" width="40%">글제목</th>
            <th class="m1" width="20%">작성자</th>
            <th class="m1" width="20%">작성일</th>
            <th class="m1" width="10%">조회수</th>
        </tr>
        <!--  ----------------- empty: boardArr.size()==0 -->
    <c:if test="${boardAll==null || empty boardAll}">
        <tr>
            <td colspan="5">
                <b>데이터가 없습니다</b>
            </td>
        </tr>
    </c:if>
    <c:if test="${boardAll !=null && not empty boardAll}">
        <%--for(BoardVO board:boardAll){...}와 동일함 --%>
        <c:forEach var="board" items="${boardAll}">
        <tr>
            <td>${board.num}</td>
            <td>
                <a href="view.do?num=${board.num}">${board.title}</a>
            </td>
            <td>${board.name}</td>
            <td>
                <fmt:formatDate value="${board.wdate}" pattern="yyyy-MM-dd"/>
            </td>
            <td>${board.readnum}</td>
        </tr>
        </c:forEach>
    </c:if>            
                <!-- ---------------------- -->
        <tr>
            <td colspan="3" style="text-align:center">
                <!-- 페이지 네비게이션 -->
                <c:forEach var="i" begin="1" end="${pageCount}" step="1">
                [<a href="list.do?pageNum=${i}"
                <c:if test="${pageNum==i}">class='active'</c:if>> ${i} </a>]
                </c:forEach>
            </td>
            <td colspan="2" style="text-align:center">총 게시글 수
                <span style="color:red; font-weight:bold">${totalCount}</span>
            </td>
        </tr>
    </table>
</div>
cs

 

[경로: src/main/java/css/style.css] CSS에 추가 - class='active'인 요소를 빨간색으로 처리

1
2
3
4
.active{
    color:red;
    font-weight:bold;
}
cs

실행 결과

 


게시글 상세보기 처리

to be continued...

+ Recent posts