공지사항 게시판
공지사항 게시판기능을 위해서는
목록과 상세페이지를 만들어야 한다.
회원 비회원 모두 조회할 수 있으며,
글쓰기는 관리자만 가능하다
![]() |
<< 이전포스팅에서 완료된 요청 | 이번포스팅에서 구현할 요청 >>
| 기능 | url요청 | 요청시 전달값 | 응답페이지 또는 url재요청 | |
| /web | index.jsp | |||
| 로그인요청 | /login.me | userId=?&userPwd=? | 실패시 | views/common/errorPage.jsp |
| 성공시 | /web url재요청=> index.jsp | |||
| 로그아웃요청 | /logout.me | /web url재요청=> index.jsp | ||
| 회원가입페이지 | /enrollForm.me | views/member/memberEnrollForm.jsp | ||
| 회원가입요청 | /insert.me | userId=? ... 등 | 실패시 | views/common/errorPage.jsp |
| 성공시 | /web url재요청 => index.jsp | |||
| 마이페이지요청 | /myPage.me | 로그인전 | /web url재요청 => index.jsp | |
| 로그인후 | views.member/myPage.jsp | |||
| 정보변경요청 |
/update.me |
userId=? ... 등 | 실패시 | view/common/errorPage.jsp |
| 성공시 | /myPage.me url재요청 | |||
| 비번변경요청 | /updatePwd.me | 성공/실패 | /myPage.me url재요청 | |
| 탈퇴요청 | /delete.me | 실패시 | /myPage.me url재요청 | |
| 성공시 | /web url재요청 | |||
| 공지사항 목록 | /list.no | views/notice/noticeListView.jsp | ||
| 공지사항글쓰기 | /enrollForm.no | views/noticeEnrollForm.jsp | ||
| 공지사항등록 | /insert.no | title=?&content=? | 실패시 | views/common/errorPage.jsp |
| 성공시 | /list.no url재요청 |
공지사항 목록 조회
회원 비회원 모두 조회할 수 있다.
STEP1) Notice.java
- 생성위치 : com.br.notice.model.vo
- 공지사항 게시판의 vo 클래스를 만든다.
- 공지사항 작성자를 담을 noticeWriter는 db에서는 number타입이지만(회원번호)
화면에 보여지는건 회원번호가 아닌 아이디 혹은 이름이다.
따라서 숫자와 문자열 둘다 담을 수 있는 String 타입으로 설정한다.
STEP2) menubar.jsp (수정)
- Home 버튼 클릭시 메인페이지 가도록 설정하기
- 공지사항 버튼을 클릭했을때 목록으로 이동하도록 서블릿 메핑값을 준다.
<a href="<%=contextPath%>">HOME</a>
<a href="<%=contextPath%>/list.no">공지사항</a>
STEP3) noticeListView.jsp
- 생성위치 : webProject/src/main/webapp/views/notice
- 공지사항 클릭시 뜨는 공지사항 목록 리스트를 설계한다.
- 상단에 menubar를 include지시어로 삽입한다.
STEP4) NoticeListController.java
- 생성위치 : com.br.notice.controller
서블릿/매핑값 list.no - 페이지 포워딩하는 용도의 서블릿
이때 DB로부터 조회된 공지사항에 대한 데이터가 필요
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1) 요청시 전달값 뽑기 >> 없으므로 생략
// 2) 요청 처리 (select)
ArrayList<Notice> list = new NoticeService().selectNoticeList();
// 3) 응답뷰 지정하여 포워딩 => views/notice/noticeListView.jsp
// 포워딩 시 응답뷰에 필요한 데이터는 request의 Attribute에 담으면 됨.
// DB에서 조회된 공지사항에 대한 데이터가 필요
// (조회 결과가 있든 없든 일단 데이터를 담아 페이지 이동)
request.setAttribute("list", list);
request.getRequestDispatcher("views/notice/noticeListView.jsp").forward(request, response);
}
STEP5) NoticeService.java
- 생성위치 : com.br.notice.model.service
- selectNoticeList() 작성
public ArrayList<Notice> selectNoticeList(){
Connection conn = getConnection();
ArrayList<Notice> list = new NoticeDao().selectNoticeList(conn);
close(conn);
return list;
}
STEP6) notice-mapper.xml
- 게시글을 조회해오는 sql문 작성
- 별칭을 지정하지 않으면 STATUS가 두개 컬럼에 있어서 ambiguausly 오류가 뜰것.
- 최신글이 위로 가도록하는 ORDER BY절 추가
<entry key="selectNoticeList">
SELECT
NOTICE_NO
, NOTICE_TITLE
, USER_ID
, COUNT
, CREATE_DATE
FROM NOTICE N
JOIN MEMBER ON (NOTICE_WRITER = USER_NO)
WHERE N.STATUS = 'Y'
ORDER
BY NOTICE_NO DESC;
<entry>
STEP) NoticeDao.java
- 생성위치 : com.br.notice.model.daoselectNoticeList
- 기본 생성자에 prop객체 생성하는 구문 추가
- selectNoticeList(conn) 메소드 작성
public NoticeDao() {
try {
prop.loadFromXML(new FileInputStream(NoticeDao.class.getResource("/db/sql/notice-mapper.xml").getPath()));
//그냥 load()가 아닌 loadFromXml()로 해야 오류없이 잘 읽어들여짐
} catch (IOException e) {
e.printStackTrace();
}
}
public ArrayList<Notice> selectNoticeList(Connection conn){
//select문 = ResultSet(여러행)
// ArrayList는 null로 초기화가 아닌 생성해두면 텅빈 리스트 생성
ArrayList<Notice> list = new ArrayList<>();
PreparedStatement pstmt = null;
ResultSet rset = null;
String sql = prop.getProperty("selectNoticeList") ;
try {
pstmt = conn.prepareStatement(sql);
//완성된 sql문으로 바로 실행
rset = pstmt.executeQuery();
while(rset.next()){
list.add(new Notice(rset.getInt("notice_no"),
.....
rset.getDate("create_date")));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rset);
close(pstmt);
}
return list;
}
STEP) noticeListView.jsp (수정)
- 데이터와 함께 포워딩을 받았으면, 최상단에에 전달받은 데이터를 뽑아놓는다.
- if문으로 조회 결과가 없으면 게시글없음 문구를 출력하고, 조회결과가 있다면 for문으로 데이터 수 만큼 목록이 만들어 지도록 코드를 구성한다
<%
ArrayList<Notice> list = (ArrayList<Notice>)request.getAttribute("list");
%>
.....
<table>
<tr>
<th>글번호</th>
<th width="400">글제목</th>
<th width="100">작성자</th>
<th>조회수</th>
<th width="100">작성일</th>
</tr>
<% if(list.isEmpty()) { %>
<!-- case1. 공지글이 없을 경우 -->
<tr>
<td colspan="5">존재하는 공지사항이 없습니다.</td>
</tr>
<%} else { %>
<!-- case2. 공지글이 있을 경우-->
<% for(Notice n : list) { %>
<tr>
<td><%= n.getNoticeNo() %></td>
<td><%= n.getNoticeTitle() %></td>
<td><%= n.getNoticeWriter() %></td>
<td><%= n.getCount() %></td>
<td><%= n.getCreateDate() %></td>
</tr>
<% } %>
<% } %>
</table>
공지사항 조회하기
관리자일때만 글쓰기 버튼이 보이게 해서 권한을 부여한다.
![]() |
STEP1) noticeListView.jsp (수정)
- 로그인한 사용자가 관리자일 경우 보일 div 안에 글쓰기 버튼을 넣는다
- session에 로그인한 회원정보인 loginUser 담겨있음(include된 menubar.jsp에 코드작성됨)
>> 해당 객체의 id필드가 관리자 아이디인 admin과 일치하는지 검사한다.
**이때, null검사 하지 않으면 오류가 뜸 (로그인 하지 않으면 loginUser는 null)
&&연산자는 앞의 조건이 false이면 뒤의 조건은 실행하지 않기때문에 해당 원리로 검사 - 버튼은 속성으로 href를 쓸 수 없어서 onclick= "location.href='요청할 url' " 구문을 사용해야한다.
>> 번거로우므로 a태그를 쓰고 부트스트랩을 활용해서 버튼모양을 만든다.
<% if(loginUser != null && loginUser.getUserId().equals("admin")) { %>
<a href="<%=contextPath%>/enrollForm.no" class="btn btn-secondary btn-sm">글작성</a>
<% } %>
STEP2) noticeEnrollForm.jsp
- 생성위치 : webProject/src/main/webapp/views/notice
- 게시글 작성하는 페이지를 구성한다.
- 클릭시 뒤로가게 만들기 : onclick="history.back();"
- 폼 제출 서블릿 : insert.no
<h2>공지사항 작성하기</h2>
<form action="<%=contextPath%>/insert.no" method="post" id="enroll-form">
제목 : <input type="text" name="title" required>
내용 : <textarea name="content" style="resize:none" id="" rows="10" required></textarea>
<button type="submit">등록하기</button>
<button type="reset">초기화</button>
<button type="button" onclick="history.back();">뒤로가기</button>
</form>
STEP3) NoticeEnrollFormController.java
- 생성위치 : com.br.notice.controller
서블릿/매핑값 enrollForm.no - 글쓰기 버튼을 눌렀을 때 글작성 페이지로 포워딩하는 용도
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 응답페이지 views/notice/noticeEnrollForm.jsp 포워딩
request.getRequestDispatcher("views/notice/noticeEnrollForm.jsp").forward(request, response);
}
STEP4) notice-mapper.xml(수정)
- 게시글을 삽입하는 sql문을 작성해보면 로그인한 회원의 번호가 필요하다는것을 알 수 있다.
INSERT
INTO NOTICE
(
NOTICE_NO
, NOTICE_TITLE
, NOTICE_CONTENT
, NOTICE_WRITER
)
VALUES
(
SEQ_NNO.NEXTVAL
, ?
, ?
, ?
)
STEP5) NoticeInsertController.java
- 생성위치 : com.br.notice.controller
서블릿/매핑값 insert.no - 사용자가 작성한 게시글을 넘겨받아 db에 삽입하는 요청처리를 하는 서블릿
- post방식이고 한글이 넘어올 수 있으므로 인코딩 해야한다
- 로그인한 회원 정보를 얻어내는 방법
1. input type="hidden"으로 애초에 요청시 숨겨서 전달하는 방법
2. session에 담겨있는 회원객체로부터 데이터 뽑기 (서블릿에서도 세션에 접근가능하다!)
>> getAttribute() 사용시 오브젝트타입 반환이므로 강제 형변환 후 getter 메소드 사용한다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String noticeTitle = request.getParameter("title");
String noticeContent = request.getParameter("content");
//로그인한 회원 번호 알아내기
HttpSession session = request.getSession();
int userNo = ((Member)session.getAttribute("loginUser")).getUserNo();
Notice n = new Notice();
n.setNoticeTitle(noticeTitle);
n.setNoticeContent(noticeContent);
//noticeWriter는 vo작성 당시 숫자가 아닌 문자열로 담기로 설계해놨었다.
//숫자>문자 변환 메소드 String.valueOf() 사용
n.setNoticeWriter(String.valueOf(userNo));
int result = new NoticeService().insertNotice(n);
if(result>0) {
// 성공 => 공지사항 목록페이지 띄우기(noticeListView.jsp)
// alert로 "성공적으로 공지사항 등록되었습니다."
session.setAttribute("alertMsg", "공지사항 등록에 성공했습니다");
//이미 등록해둔 url이 있으므로 포워딩 할 필요가 없이 url재요청을 한다.
response.sendRedirect(request.getContextPath() + "/list.no");
}else {
// 실패 => 에러페이지(errorPage.jsp)
// 에러문구 "공지사항 등록 실패"
request.setAttribute("errorMsg", "공지사항 등록에 실패했습니다.");
//포워딩을 한다.
request.getRequestDispatcher("/views/common/errorPage.jsp").forward(request,response);
}
}
STEP6) NoticeService.java (수정)
- insertNotice(n) 메소드 생성
public int insertNotice(Notice n) {
Connection conn = getConnection();
int result = new NoticeDao().insertNotice(conn, n);
if(result>0) {
commit(conn);
}else {
rollback(conn);
}
close(conn);
return result;
}
STEP7) NoticeDao.java (수정)
- insertNotice(conn, n) 메소드 생성
public int insertNotice(Connection conn, Notice n) {
int result = 0;
PreparedStatement pstmt = null;
String sql = prop.getProperty("insertNotice");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, n.getNoticeTitle());
pstmt.setString(2, n.getNoticeContent());
//문자열로 담았으니 숫자로 파싱해준다.
//pstmt.setInt(3, Integer.parseInt(n.getNoticeWriter()));
//사실 파싱 안해줘도 됨. 오라클은 자동형변환해줌
pstmt.setString(3, n.getNoticeWriter());
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}

'다양한 기술들 > 레거시 Web 실습' 카테고리의 다른 글
| [08] 게시판심화1 : 페이징처리 (1) | 2023.01.11 |
|---|---|
| [07] 게시판기초 : 상세조회, 수정, 삭제 (0) | 2023.01.09 |
| [05] 모달을 사용한 비밀번호변경 (0) | 2023.01.06 |
| [04] 회원정보변경 (0) | 2023.01.06 |
| [03] 마이페이지 (0) | 2023.01.05 |


댓글