- 공지사항 작성(+확인), 전체선택, 삭제
- 없는 아이디여도 에러 안나게
- 인터셉터(관리자레벨이 아니면 접근 ㄴㄴ)
✨인터셉터, 관리자 접근
NoticeInterceptor
public class NoticeInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
MemberDto loginUser = (MemberDto) request.getSession().getAttribute("loginUser");
if("admin".equals(loginUser.getUserId())) {
return true;
}else {
request.setAttribute("msg", "관리자 계정이 아닙니다.");
request.getRequestDispatcher("/WEB-INF/views/error/errorPage.jsp").forward(request, response);
return false;
}
}
}
ErrorProcessor
@ControllerAdvice(annotations = Controller.class)
@Slf4j
public class ErrorProcessor {
@ExceptionHandler(Exception.class)
public String errorProcess(Exception e) {
log.error(e.toString());
log.error(e.getMessage());
e.printStackTrace();
return "error/exception";
}
}
ErrorPage.jsp
<body>
<%@ include file="/WEB-INF/views/common/header.jsp" %>
<h1>에러페이지~~</h1>
<h2 id="msg">${msg}</h2>
<script type="text/javascript">
console.log(document.getElementById('msg').innerText);
alert(document.getElementById('msg').innerText);
window.location.href = "${root}";
</script>
</body>
servlet-context.xml
<interceptors>
<interceptor>
<mapping path="/notice/**"/>
<exclude-mapping path="/notice/list/**"/>
<beans:bean class="com.kh.app999.interceptor.NoticeInterceptor"></beans:bean>
</interceptor>
</interceptors>
페이징
PageVo
C,S,D
MemberServiceImpl
@Service
@Slf4j
@Transactional
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberDao dao;
@Autowired
private PasswordEncoder pe;
@Override
public int join(MemberDto dto, HttpServletRequest req) throws Exception{
int no = dao.getMemberSeq();
dto.setUserNo(no);
dto.setUserPwd(pe.encode(dto.getUserPwd()));
log.info(dto.toString());
int result = dao.insertMember(dto);
MultipartFile f = dto.getF();
if(!f.isEmpty()) {
String changeName = System.currentTimeMillis()+"_"+f.getOriginalFilename();
dto.setChangeName(changeName);
System.out.println("===============");
System.out.println(f.getOriginalFilename());
System.out.println(f.getSize());
System.out.println(f.getContentType());
System.out.println("===============");
String path = req.getServletContext().getRealPath("/resources/upload/profile/");
File file = new File(path+ changeName);
f.transferTo(file);
dao.uploadProfile(dto);
}
return result;
}
@Override
public MemberDto login(MemberDto dto) throws Exception {
MemberDto dbUser = dao.getMember(dto);
if(dbUser == null) {
return null;
}
if(pe.matches(dto.getUserPwd(), dbUser.getUserPwd())) {
return dbUser;
}else {
return null;
}
}
@Override
public MemberDto editMember(MemberDto dto) throws Exception {
if(dto.getUserPwd().length()>0) {
dto.setUserPwd(pe.encode(dto.getUserPwd()));
}
int result = dao.updateMember(dto);
MemberDto m = null;
if(result > 0) {
m = dao.getMember(dto);
}
return m;
}
}
NoticeController
@Controller
@RequestMapping("notice")
@Slf4j
public class NoticeController {
@Autowired
private NoticeService service;
@GetMapping(value = "/list")
public String list(Model model) throws Exception {
List<NoticeVo> list = service.getNoticeList();
model.addAttribute("list", list);
return "notice/list";
}
@GetMapping("write")
public String write() {
return "notice/write";
}
@PostMapping("write")
public String write(NoticeVo vo, HttpServletRequest req) throws Exception {
System.out.println(vo);
int result = service.write(vo);
if(result>0) {
return "redirect:/notice/list";
}else {
req.setAttribute("msg", "공지사항 작성 실패");
return "error/errorPage";
}
}
@PostMapping("delete")
@ResponseBody
public String delete(String str) throws Exception {
System.out.println(str);
System.out.println(str.length()/2);
int result = service.deleteNotice(str);
log.warn("선택한 row 개수 : {}", result);
if(result == str.length()/2) {
return "ok";
}else {
return "fail_" + result;
}
}
}
NoticeService 인페
public interface NoticeService {
int write(NoticeVo vo) throws Exception;
List<NoticeVo> getNoticeList() throws Exception;
int deleteNotice(String str) throws Exception;
}
NoticeServiceImpl
@Service
public class NoticeServiceImpl implements NoticeService{
@Autowired
private NoticeDao dao;
@Override
public int write(NoticeVo vo) throws Exception {
return dao.write(vo);
}
@Override
public List<NoticeVo> getNoticeList() throws Exception {
return dao.getNoticeList();
}
@Override
public int deleteNotice(String str) throws Exception {
String[] delArr = str.split(",");
return dao.deleteNotice(delArr);
}
}
NoticeDao 인페
public interface NoticeDao {
int write(NoticeVo vo) throws Exception;
List<NoticeVo> getNoticeList() throws Exception;
int deleteNotice(String[] delArr) throws Exception;
}
NoticeDaoImpl
@Repository
public class NoticeDaoImpl implements NoticeDao{
@Autowired
private SqlSession sqlSession;
@Override
public int write(NoticeVo vo) throws Exception {
return sqlSession.insert("notice.insertNotice", vo);
}
@Override
public List<NoticeVo> getNoticeList() throws Exception {
return sqlSession.selectList("notice.getNoticeList");
}
@Override
public int deleteNotice(String[] delArr) throws Exception {
return sqlSession.update("notice.deleteNotice", delArr);
}
}
NoticeVo
@Data
public class NoticeVo {
private long no;
private String title;
private String content;
private long writer;
private Date writeDate;
private Date editDate;
private String del;
private String userNick;
}
디비
notice-mapper.xml
<mapper namespace="notice">
<insert id="insertNotice" parameterType="noticeVo">
INSERT INTO NOTICE
(
NO
,TITLE
,CONTENT
,WRITER
)
VALUES
(
NOTICE_SEQ.NEXTVAL
,#{title}
,#{content}
,#{writer}
)
</insert>
<select id="getNoticeList" resultType="noticeVo">
SELECT *
FROM NOTICE n
JOIN MEMBER m ON(n.WRITER = m.USER_NO)
WHERE DEL = 'N'
ORDER BY NO
</select>
<update id="deleteNotice" >
UPDATE NOTICE
SET
DEL = 'Y'
WHERE NO IN
<foreach collection="array" item="n" open="(" close=")" separator=",">
#{n}
</foreach>
</update>
</mapper>
NOTICE
DROP TABLE NOTICE CASCADE CONSTRAINTS;
CREATE TABLE NOTICE(
NO NUMBER PRIMARY KEY
,TITLE VARCHAR2(100)
,CONTENT VARCHAR2(4000)
,WRITER NUMBER
,WRITE_DATE DATE DEFAULT SYSDATE
,EDIT_DATE DATE NULL
,DEL CHAR(1) DEFAULT('N')
,CONSTRAINT NOTICE_FK FOREIGN KEY(WRITER) REFERENCES MEMBER(USER_NO) ON DELETE CASCADE
);
DROP SEQUENCE NOTICE_SEQ;
CREATE SEQUENCE NOTICE_SEQ NOCACHE NOCYCLE;
SELECT * FROM NOTICE;
mybatis-config.xml
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="autoMappingBehavior" value="FULL"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
<typeAliases>
<typeAlias type="com.kh.app999.member.entity.MemberDto" alias="memberDto"/>
<typeAlias type="com.kh.app999.notice.vo.NoticeVo" alias="noticeVo"/>
</typeAliases>
</configuration>
뷰
notice/list.jsp
<body>
<%@ include file="/WEB-INF/views/common/header.jsp" %>
<div id="div-main">
<div style="text-align:center;">
<h1>공지사항</h1>
</div>
<table border="1" style="margin:auto;">
<thead>
<tr>
<th><input type="checkbox" id="allCheck"></th>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성시간</th>
</tr>
</thead>
<tbody>
<c:forEach items="${list}" var="n">
<tr>
<td><input type="checkbox" class="checkbox-del" value="${n.no}"></td>
<td>${n.no}</td>
<td>${n.title}</td>
<td>${n.userNick}</td>
<td>${n.writeDate}</td>
</tr>
</c:forEach>
</tbody>
</table>
<a href="${root}/notice/write">공지 작성</a>
<button onclick="del();">삭제하기</button>
</div>
<script type="text/javascript">
let allCheck = document.querySelector('thead input[type=checkbox]');
let delArr = document.getElementsByClassName('checkbox-del');
allCheck.onchange = function(e){
console.log(this.checked);
if(this.checked){
for(let i=0; i<delArr.length; i++){
delArr[i].checked = true;
}
}else{
for(let i=0; i<delArr.length; i++){
delArr[i].checked = false;
}
}
}
function del() {
let delArr = document.getElementsByClassName('checkbox-del');
let result = "";
for(let i = 0; i<delArr.length; i++){
let t = delArr[i];
if(t.checked){
console.log(t.value);
result += t.value + ',';
}
}
$.ajax({
url : "${root}/notice/delete",
data : {"str" : result},
type : "post",
success : function(data){
console.log(data);
},
error : function(error){
console.log(error)
},
complete : function(){
window.location.reload();
}
});
}
</script>
</body>
notice/write.jsp
<body>
<%@ include file="/WEB-INF/views/common/header.jsp" %>
<div id="div-main">
<div style="text-align:center;">
<h1>공지사항 작성하기</h1>
</div>
<form action="" method="post" style="text-align:center;" onsubmit="return writeCheck();">
제목 : <input type="text" name="title"><br>
작성자 : <input type = "text" value="${loginUser.userNick}" readonly="readonly"/> <br>
<input type = "hidden" name = "writer" value="${loginUser.userNo}"/> <br>
내용 : <br> <textarea rows="30" cols="100" name = "content"></textarea> <br>
<input type = "submit" value = "공지사항 작성" />
</form>
</div>
<script type="text/javascript">
function writeCheck(){
return confirm("작성하시겠습니까?");
}
</script>
</body>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="root" value="${pageContext.request.contextPath}"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" href="${root}/resources/css/common/header.css">
<div id="div-header">
<table border="1">
<tr>
<td>빈칸</td>
<td colspan="2"><a href="${root}"><img width="100%" height="50px" src="${pageContext.request.contextPath}/resources/imgs/qr.png"></a></td>
<c:if test="${empty loginUser}">
<td>빈칸</td>
</c:if>
<c:if test="${not empty loginUser}">
<td><a href="${root}/member/mypage"><img src="${root}/resources/upload/profile/${loginUser.changeName}"></a></td>
</c:if>
</tr>
<tr>
<td><a href="${root}/notice/list">공지사항</a></td>
<td>메뉴2</td>
<td>메뉴3</td>
<c:if test="${empty loginUser}">
<td>
<a href="${root}/member/login">로그인</a><br>
<a href="${root}/member/join">회원가입</a>
</td>
</c:if>
<c:if test="${not empty loginUser}">
<td>
${loginUser.userNick}님 환영합니다!<br>
<a href="${root}/member/logout">로그아웃</a>
</td>
</c:if>
</tr>
</table>
</div>
home.jsp
<body>
<%@ include file="/WEB-INF/views/common/header.jsp" %>
<script type="text/javascript" src="${root}/resources/js/home.js"></script>
<div id="div-main">
<h1>홈페이지</h1>
</div>
</body>
js 분리