오늘이라도

[Spring] 12. 웹사이트 만들기 ⑪ : 공지글 수정, 목록에서 첨부파일 다운로드, 페이징 밑작업 본문

취업성공패키지 SW 개발자 교육/Spring

[Spring] 12. 웹사이트 만들기 ⑪ : 공지글 수정, 목록에서 첨부파일 다운로드, 페이징 밑작업

upcake_ 2020. 7. 15. 09:26
반응형

https://github.com/upcake/Class_Examples

교육 중에 작성한 예제들은 깃허브에 올려두고 있습니다. 

gif 파일은 클릭해서 보는 것이 정확합니다.


 - 웹사이트 만들기 ⑪ : 공지글 수정, 목록에서 첨부파일 다운로드, 페이징 밑작업 -

▲작동 화면

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>modify JSP</title>
</head>
<body>
<h3>공지글 수정</h3>
<!-- 
 - 파일 첨부 시 form 반드시 갖고 있어야 할 속성 
	1. 반드시 method는 post이어야만 한다.
	2. enctype을 지정한다. ▶ enctype='multipart/form-data'
-->
<form action="update.no" method="post" enctype="multipart/form-data">
	<input type="hidden" name="id" value="${vo.id }"/>
	<input type="hidden" name="attach" />
	<table>
		<tr>
			<th class="w-px160">제목</th>
			<td><input class="need" type="text" name="title" value="${vo.title }"/></td>
		</tr>
		<tr>
			<th>내용</th>
			<td><textarea class="need" name="content">${vo.content }</textarea></td>
		</tr>
		<tr>
			<th>첨부 파일</th>
			<td class="left">
				<label>
					<input id="attach-file" type="file" name="file" />
					<img src="img/select.png" class="file-img" />
				</label>
				<span id="file-name">${vo.filename }</span>
				<span id="delete-file" style='display:${empty vo.filename ? "none" : "inline"}; color:red; margin-left:20px;'><i class="fas fa-times font-img"></i></span>
			</td>
		</tr>
	</table>
</form>
<div class="btnSet">
	<a class="btn-fill" onclick="if( necessary() ) { $('[name=attach]').val($('#file-name').text()); $('form').submit(); }">저장</a>
	<a class="btn-empty" href="detail.no?id=${vo.id }">취소</a>
	<!-- <a class="btn-empty" href="javascript:history.go(-1)">취소</a> -->
</div>

<!-- 실시간 갱신을 위해 getTime을 붙여준다 -->
<script type="text/javascript" src="js/need_check.js?v=<%=new java.util.Date().getTime() %>"></script>
<script type="text/javascript" src="js/file_attach.js"></script>
</body>
</html>

▲modify.jsp

 

/**
 * 입력 항목에 입력되어 있는지 여부를 반환하는 함수
 */
function necessary(){
	var need = true;
	$('.need').each(function(){
		if( $(this).val()=='' ){
			alert( '입력하세요!' );
			$(this).focus();
			need = false;
			return need;
		}
	});
	return need; 
}

//엔터를 누를 경우
$('[name=title]').on('keypress', function(e) {
	if(e.keyCode == 13) {
		if(necessary()) {$('form').submit(); }
		else {return false;}
	}
});

▲need_check.js

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>new JSP</title>
</head>
<body>
<h3>신규 공지 글</h3>
<!-- 
 - 파일 첨부 시 form 반드시 갖고 있어야 할 속성 
	1. 반드시 method는 post이어야만 한다.
	2. enctype을 지정한다. ▶ enctype='multipart/form-data'

-->
<form action="insert.no" method="post" enctype="multipart/form-data">
	<table>
		<tr>
			<th class="w-px160">제목</th>
			<td><input type="text" name="title" class="need"/></td>
		</tr>
		<tr>
			<th>작성자</th>
			<td>${login_info.name }</td>
		</tr>
		<tr>
			<th>내용</th>
			<td><textarea name="content" class="need"></textarea></td>
		</tr>
		<tr>
			<th>파일 첨부</th>
			<td class="left">
				<label>
					<input type="file" name="file" id="attach-file"/>
					<img src='img/select.png' class="file-img" />
				</label>
				<span id="file-name"></span>
				<span id="delete-file" style="color: red; margin-left: 20px;" ><i class="fas fa-times font-img"></i></span>
			</td>
		</tr>
	</table>
</form>
<div class="btnSet">
	<a class="btn-fill" onclick="if(necessary()) $('form').submit()">저장</a>
	<a class="btn-empty" href="list.no">취소</a>
</div>

<!-- 실시간 갱신을 위해 getTime을 붙여준다 -->
<script type="text/javascript" src="js/need_check.js?v=<%=new java.util.Date().getTime() %>"></script>
<script type="text/javascript" src="js/file_attach.js"></script>
</body>
</html>

▲new.jsp

 

package com.hanul.iot;

import java.io.File;
import java.util.HashMap;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import common.CommonService;
import member.MemberServiceImpl;
import member.MemberVO;
import notice.NoticePage;
import notice.NoticeServiceImpl;
import notice.NoticeVO;

@Controller
public class NoticeController {
	@Autowired private NoticeServiceImpl service;
	@Autowired private MemberServiceImpl member;
	@Autowired private CommonService common;
	@Autowired private NoticePage page;
	
	//공지사항 목록화면 요청//////////////////////////////////////////////////////
	@RequestMapping("/list.no")
	public String list(Model model, HttpSession session, @RequestParam(defaultValue = "1") int curPage) {
		//공지사항 클릭 하면 admin으로 자동 로그인
		HashMap<String, String> map = new HashMap<String, String>();
		//HashMap : 데이터를 담을 자료 구조
		map.put("id", "admin");
		map.put("pw", "1234");
		session.setAttribute("login_info", member.member_login(map));
		session.setAttribute("category", "no");
		//DB에서 공지 글 목록을 조회해와 목록 화면에 출력
		page.setCurPage(curPage);
		model.addAttribute("page", service.notice_list(page));
		
		return "notice/list";
	}
	
	//신규 공지 글 작성 화면 요청//////////////////////////////////////////////////////
	@RequestMapping("/new.no")
	public String notice() {
		return "notice/new";
	}
	
	//신규 공지 글 저장 처리 요청//////////////////////////////////////////////////////
	@RequestMapping("/insert.no")
	public String insert(MultipartFile file, NoticeVO vo, HttpSession session) {
		//첨부한 파일을 서버 시스템에 업로드하는 처리
		if( !file.isEmpty() ) {
			vo.setFilepath(common.upload("notice", file, session));
			vo.setFilename(file.getOriginalFilename());
		}
		
		vo.setWriter( ((MemberVO) session.getAttribute("login_info")).getId() );
		//화면에서 입력한 정보를 DB에 저장한 후
		service.notice_insert(vo);
		//목록 화면으로 연결
		return "redirect:list.no";
	}
	
	//공지글 상세 화면 요청//////////////////////////////////////////////////////
	@RequestMapping("/detail.no")
	public String detail(int id, Model model) {
		//선택한 공지글에 대한 조회수 증가 처리
		service.notice_read(id);
		
		//선택한 공지글 정보를 DB에서 조회해와 상세 화면에 출력
		model.addAttribute("vo", service.notice_detail(id));
		model.addAttribute("crlf", "\r\n");
		
		return "notice/detail";
	} //detail()
	
	//첨부파일 다운로드 요청//////////////////////////////////////////////////////
	@ResponseBody @RequestMapping("/download.no")
	public void download(int id, HttpSession session, HttpServletResponse response) {
		NoticeVO vo = service.notice_detail(id);
		common.download(vo.getFilename(), vo.getFilepath(), session, response);
	} //download()
	
	//공지글 삭제 처리 요청//////////////////////////////////////////////////////
	@RequestMapping("/delete.no")
	public String delete(int id, HttpSession session) {
		//선택한 공지글에 첨부된 파일이 있다면 서버의 물리적 영역에서 해당 파일도 삭제한다
		NoticeVO vo = service.notice_detail(id);
		if(vo.getFilepath() != null) {
			File file = new File(session.getServletContext().getRealPath("resources") + vo.getFilepath());
			if( file.exists() ) { file.delete(); }
		}
		
		//선택한 공지글을 DB에서 삭제한 후 목록 화면으로 연결
		service.notice_delete(id);
		
		return "redirect:list.no";
	} //delete()
	
	//공지글 수정 화면 요청//////////////////////////////////////////////////////
	@RequestMapping("/modify.no")
	public String modify(int id, Model model) {
		//선택한 공지글 정보를 DB에서 조회해와 수정화면에 출력
		model.addAttribute("vo", service.notice_detail(id));
		return "notice/modify";
	} //modify()
	
	//공지글 수정 처리 요청//////////////////////////////////////////////////////
	@RequestMapping("/update.no")
	public String update(NoticeVO vo, MultipartFile file, HttpSession session, String attach) {
		//원래 공지글의 첨부 파일 관련 정보를 조회
		NoticeVO notice = service.notice_detail(vo.getId());
		String uuid = session.getServletContext().getRealPath("resources") + notice.getFilepath();
		
		//파일을 첨부한 경우 - 없었는데 첨부 / 있던 파일을 바꿔서 첨부
		if(!file.isEmpty()) {
			vo.setFilename(file.getOriginalFilename());
			vo.setFilepath(common.upload("notice", file, session));
			
			//원래 있던 첨부 파일은 서버에서 삭제
			if( notice.getFilename() != null ) {
				File f = new File(uuid);
				if ( f.exists() ) { f.delete(); }
			}
			
		} else {
			//원래 있던 첨부 파일을 삭제됐거나 원래부터 첨부 파일이 없었던 경우
			if(attach.isEmpty()) {
				//원래 있던 첨부 파일은 서버에서 삭제
				if( notice.getFilename() != null ) {
					File f = new File(uuid);
					if ( f.exists() ) { f.delete(); }
				}
				
			//원래 있던 첨부 파일을 그대로 사용하는 경우
			} else {
				vo.setFilename(notice.getFilename());
				vo.setFilepath(notice.getFilepath());
			}
			
		}
		
		//화면에서 변경한 정보를 DB에 저장한 후 상세 화면으로 연결
		service.notice_update(vo);
		
		return "redirect:detail.no?id=" + vo.getId();
	} //update()
} //class

▲NoticeController.java

 

package notice;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class NoticeServiceImpl implements NoticeService {
	@Autowired private NoticeDAO dao;
	
	@Override
	public void notice_insert(NoticeVO vo) {
		dao.notice_insert(vo);
	}

	@Override
	public List<NoticeVO> notice_list() {
		return dao.notice_list();
	}

	@Override
	public NoticeVO notice_detail(int id) {
		return dao.notice_detail(id);
	}

	@Override
	public void notice_update(NoticeVO vo) {
		dao.notice_update(vo);
	}

	@Override
	public void notice_delete(int id) {
		dao.notice_delete(id);
	}

	@Override
	public void notice_read(int id) {
		dao.notice_read(id);
	}

	@Override
	public NoticePage notice_list(NoticePage page) {
		return dao.notice_list(page);
	}
}

▲NoticeServiceImpl.java

 

package notice;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class NoticeDAO implements NoticeService {
	@Autowired private SqlSession sql;
	
	@Override
	public void notice_insert(NoticeVO vo) {
		sql.insert("notice.mapper.insert", vo);
	}

	@Override
	public List<NoticeVO> notice_list() {
		return sql.selectList("notice.mapper.list");
	}

	@Override
	public NoticeVO notice_detail(int id) {
		return sql.selectOne("notice.mapper.detail",id);
	}

	@Override
	public void notice_update(NoticeVO vo) {
		sql.update("notice.mapper.update", vo);
	}

	@Override
	public void notice_delete(int id) {
		sql.delete("notice.mapper.delete", id);
	}

	@Override
	public void notice_read(int id) {
		sql.update("notice.mapper.read", id);
	}

	@Override
	public NoticePage notice_list(NoticePage page) {
		page.setTotalList((Integer) sql.selectOne("notice.mapper.totalList"));
		page.setList(sql.selectList("notice.mapper.list", page));
		
		return page;
	}
}

▲NoticeDAO.java

 

<?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="notice.mapper" >
	<select id="list" resultType="notice.NoticeVO">
		SELECT * 
		FROM (SELECT ROWNUM no, n.* 
				FROM (SELECT * FROM notice ORDER BY root, step DESC) n
				ORDER BY no DESC) n 
		WHERE no BETWEEN #{beginList} and #{endList}				
		
	</select>

	<select id="totalList" resultType="integer">
		SELECT COUNT(*) FROM notice
	</select>
	
	<insert id="insert">	
		INSERT INTO notice (id, root, title, content, writer, filename, filepath)
		VALUES (seq_notice.nextval, seq_notice.currval, #{title }, #{content }, #{writer }, #{filename, jdbcType=VARCHAR }, #{filepath, jdbcType=VARCHAR }) 
	</insert>
	
	<select id="detail" resultType="notice.NoticeVO">
		SELECT n.*, (SELECT name FROM member m WHERE m.id = n.writer) name FROM notice n WHERE id=#{id }
	</select>
	<!-- jdbcType=VARCHAR 속성을 넣으면 null값이 허용된다. -->
	
	<update id="read">
		UPDATE notice SET readcnt = readcnt + 1 WHERE id=#{id}
	</update>
	
	<delete id="delete">
		DELETE FROM notice WHERE id=#{id }
	</delete>
	
	<update id="update">
		UPDATE notice set title = #{title }, content = #{content }, filename = #{filename, jdbcType=VARCHAR }, filepath = #{filepath, jdbcType=VARCHAR }
		WHERE id=#{id }
	</update>
	
	<insert id="reply_insert">
		<!-- 원글의 step보다 더 큰 step을 가진 글이 있다면 그 글들의 step을 먼저 +1 한다. -->
		<![CDATA[
			{CALL DECLARE BEGIN
				UPDATE notice SET step = step + 1
				WHERE root = #{root } AND step > #{step };
				
				INSERT INTO notice (id, root, title, content , writer, step, indent, filename, filepath)
				VALUES (seq_notice.NEXTVAL, #{root }, #{title }, #{content }, #{writer }, #{step } + 1, #{indent } + 1, #{filename, jdbcType=VARCHAR }, #{filepath, jdbcType=VARCHAR });
			END}
		]]>
	</insert>

</mapper>

▲notice-mapper.xml

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>list JSP</title>
</head>
<body>
<h3>공지사항</h3>

<div id="list-top">
	<div>
		<ul>
			<core:if test="${login_info.admin eq 'Y' }">
				<li><a class="btn-fill" href="new.no">글쓰기</a></li>
			</core:if>
		</ul>
	</div>
</div>

<table>
	<tr>
		<th class="w-px60">번호</th>
		<th>제목</th>
		<th class="w-px100">작성자</th>
		<th class="w-px120">작성일자</th>
		<th class="w-px60">첨부파일</th>
	</tr>
	<core:forEach items="${page.list }" var="vo">
		<tr>
			<td>${vo.no }</td>
			<td class="left"><a href="detail.no?id=${vo.id }" >${vo.title }</a></td>
			<td>${vo.name }</td>
			<td>${vo.writedate }</td>
			<td>
				<core:if test="${!empty vo.filename }">
					<a href="download.no?id=${vo.id }">
						<img title="${vo.filename }" class="file-img" src="img/attach.png" />
					</a>
				</core:if>
			</td>
		</tr>
	</core:forEach>
</table>
</body>
</html>

▲list.jsp

 

--테이블 생성
CREATE TABLE customer (
	id		NUMBER CONSTRAINT customer_id_pk PRIMARY KEY,
	name	VARCHAR2(50) NOT NULL,
	gender	VARCHAR2(3) NOT NULL,
	email	VARCHAR2(50),
	phone	VARCHAR2(13)
);

--시퀀스 생성
CREATE SEQUENCE seq_customer START WITH 1 INCREMENT BY 1;

--레코드 삽입
INSERT INTO customer(id, name, gender)
VALUES (seq_customer.NEXTVAL, '홍길동', '남');

INSERT INTO customer(name, gender)
VALUES ('심청', '여');

--트리거(trigger) 설정
CREATE OR REPLACE TRIGGER trg_customer
    BEFORE INSERT ON customer   --커스터머 테이블에 인서트가 되기전에
    FOR EACH ROW    --모든 행에 대하여
BEGIN   --시작한다
    SELECT seq_customer.NEXTVAL INTO :new.id FROM dual;  --시퀀스의 데이터를 담고있는 테이블은 없으므로 더미 테이블(dual)에서 조회한다.
END;    
/       --끝 슬래쉬까지 써줘야한다


drop trigger trg_customer;
CREATE OR REPLACE TRIGGER trg_customer
    BEFORE INSERT ON customer 
    FOR EACH ROW 
BEGIN 
    SELECT seq_customer.NEXTVAL INTO :new.id FROM dual; 
END;    
/

--조회
SELECT * FROM customer;

--커밋
COMMIT;



--20/07/02==================================================================
--회원 관리 테이블
CREATE TABLE member(
    irum    VARCHAR2(20)    NOT NULL,
    id      VARCHAR2(20)    CONSTRAINT member_id_pk PRIMARY KEY,
    pw      VARCHAR2(20)    NOT NULL,
    age     NUMBER,
    gender  VARCHAR2(3)     NOT NULL,
    birth   DATE,
    post    VARCHAR2(7),
    addr    VARCHAR2(50),
    email   VARCHAR2(50)    NOT NULL,   --유니크가 들어간다 생각하고 NOT NULL만 지정
    tel     VARCHAR2(20),
    admin   VARCHAR2(1)     DEFAULT 'N'
);

--기존에 있던 member 테이블 수정
ALTER TABLE member
ADD(
    gender  VARCHAR2(3) DEFAULT '남' NOT NULL,
    birth   DATE,
    post    VARCHAR2(7),
    email   VARCHAR2(50),
    admin   VARCHAR2(1) default 'N'
);

UPDATE MEMBER SET email = id || '@naver.com';

ALTER TABLE member
MODIFY (irum NOT NULL, pw NOT NULL, email NOT NULL);

ALTER TABLE member RENAME COLUMN irum TO name;

ALTER TABLE member ADD CONSTRAINT member_id_pk PRIMARY KEY(id);

--관리자 회원 정보 저장
INSERT INTO member(name, id, pw, age, gender, email, admin)
VALUES ('관리자', 'admin', '1234', 25, '남', 'admin@admin.com', 'Y');

SELECT * FROM member;

--20/07/10======================================================================
CREATE TABLE notice(
    id          NUMBER CONSTRAINT notice_id_pk PRIMARY KEY,
    title       VARCHAR2(300) NOT NULL,
    content     VARCHAR2(4000) NOT NULL,
    writer      VARCHAR2(20) NOT NULL,
    writedate   DATE DEFAULT SYSDATE,
    readcnt     NUMBER DEFAULT 0,
    filename    VARCHAR2(300),
    filepath    VARCHAR2(300)
);

CREATE SEQUENCE seq_notice
START WITH 1 INCREMENT BY 1;

CREATE OR REPLACE TRIGGER trg_notice
    BEFORE INSERT ON notice
    FOR EACH ROW
BEGIN
    SELECT seq_notice.NEXTVAL INTO:NEW.id FROM dual;
END;
/

SELECT * FROM notice;

INSERT INTO notice(title, content, writer)
VALUES ('공지 글 테스트', '테스트 공지 글 입니다.', 'admin');

COMMIT;

--20/07/15================================================
--테이블에 공지글 항목 추가
INSERT INTO notice(title, content ,writer, writedate, filepath, filename)
SELECT title, content, writer, writedate, filepath, filename FROM notice;

COMMIT;

▲table.sql

 

package common;

public class PageVO {
	private int pageList = 10; //페이지당 목록수
	private int blockPage = 10; //블럭당 페이지수
	private int totalList; //총목록수
	private int totalPage; //총페이지수
	//157 페이지 = 총목록수/페이지당 목록수 + 나머지가 있으면+1
	private int totalBlock; //총블럭수
	//16 블럭 = 총페이지수/블럭당 페이지수 + 나머지가 있으면+1
	private int curPage; //현재페이지번호
	private int beginList, endList; //현재페이지의 시작/끝 목록번호
	private int beginPage, endPage; //현재블럭의 시작/끝 페이지번호
	
	public int getPageList() {
		return pageList;
	}
	public void setPageList(int pageList) {
		this.pageList = pageList;
	}
	public int getBlockPage() {
		return blockPage;
	}
	public void setBlockPage(int blockPage) {
		this.blockPage = blockPage;
	}
	public int getTotalList() {
		return totalList;
	}
	public void setTotalList(int totalList) {
		this.totalList = totalList;
		
		//총페이지수=총목록수/페이지당보여질목록수
		//576/10 --> 57 ..6 -> 58페이지
		totalPage = totalList / pageList;
		if( totalList % pageList >0 ) ++totalPage;
		
		//총블럭수=총페이지수/블럭당보여질페이지수
		//58/10 --> 5..8 -> 6블럭
		totalBlock = totalPage / blockPage;
		
		//시작/끝 목록번호
		//끝목록번호: 576, 566, 556, 
		endList = totalList - (curPage-1) * pageList;
		//시작목록번호: 567, 557, 547, 
		//= 끝목록번호 - (페이지당보여질목록수-1) 
		beginList = endList - (pageList-1);
		
		//현재 블럭번호 
		curBlock = curPage / blockPage;
		if( curPage % blockPage > 0 ) ++curBlock;
		//시작/끝 페이지번호
		//끝페이지번호: 10, 20, 30, ...
		endPage = curBlock * blockPage;
		//시작페이지번호 : 1, 11, 21, ...
		beginPage = endList - (blockPage-1);
		
		//2048건 ▶ 1페이지 : 2048 ~ 2039, 1 ~ 10
		//			205페이지 : 8 ~ 1, 51 ~ 58
		//끝 페이지 번호가 총 페이지 번호보다 크면 총 페이지 번호가 끝 페이지 번호이다.
		if(endPage > totalPage) {endPage = totalPage; }
	}
	private int curBlock; //현재블럭번호 
	
	public int getCurBlock() {
		return curBlock;
	}
	public void setCurBlock(int curBlock) {
		this.curBlock = curBlock;
	}
	public int getTotalPage() {
		return totalPage;
	}
	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}
	public int getTotalBlock() {
		return totalBlock;
	}
	public void setTotalBlock(int totalBlock) {
		this.totalBlock = totalBlock;
	}
	public int getCurPage() {
		return curPage;
	}
	public void setCurPage(int curPage) {
		this.curPage = curPage;
	}
	public int getBeginList() {
		return beginList;
	}
	public void setBeginList(int beginList) {
		this.beginList = beginList;
	}
	public int getEndList() {
		return endList;
	}
	public void setEndList(int endList) {
		this.endList = endList;
	}
	public int getBeginPage() {
		return beginPage;
	}
	public void setBeginPage(int beginPage) {
		this.beginPage = beginPage;
	}
	public int getEndPage() {
		return endPage;
	}
	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}
}

▲PageVO.java

 

package notice;

import java.util.List;

import org.springframework.stereotype.Component;

import common.PageVO;

@Component
public class NoticePage extends PageVO {
	private List<NoticeVO> list;

	public List<NoticeVO> getList() {
		return list;
	}

	public void setList(List<NoticeVO> list) {
		this.list = list;
	}
	
	
}

▲NoticePage.java

 

package notice;

import java.util.List;

public interface NoticeService {
	//CRUD : Create, Read, Update, Delete
	void notice_insert(NoticeVO vo);	//공지글 저장
	List<NoticeVO> notice_list();	//공지글 목록 조회
	NoticePage notice_list(NoticePage page);	//페이지 처리 된 공지글 목록 조회
	NoticeVO notice_detail(int id); //공지글 상세 조회
	void notice_update(NoticeVO vo); //공지글 변경 저장
	void notice_delete(int id); //공지글 삭제
	void notice_read(int id); //조회수 증가 처리
}

▲NoticeService.java

반응형