1. restful을 적용하여 게시판을 구현을 완성하시오.(URL 설계 포함)
1-1. 게시판 리스트 불러오기
// Controller 객체
@GetMapping("/board")
public ModelAndView list(ModelAndView mav) {
mav.setViewName("rest/rest_list");
mav.addObject("list", boardService.getList());
return mav;
}
// Service 인터페이스
public List<BoardVO> getList();
// 인터페이스 구현 객체
@Override
public List<BoardVO> getList() {
log.info("getList()");
return mapper.getList();
}
// BoardMapper 객체
public List<BoardVO> getList();
<!-- SQL 구현부 -->
<select id="getList" resultType="edu.bit.ex.board.vo.BoardVO">
<![CDATA[
SELECT bId, bName, bTitle, bContent, bDate, bHit, bGroup, bStep, bIndent
FROM mvc_board order by bGroup desc, bStep asc
]]>
</select>
<!-- 페이지 구현부 -->
<%@ 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" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Rest List</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function (){
$('.a-delete').click(function(event){
// 이벤트를 취소할 때 동작을 멈춘다.
event.preventDefault();
console.log("ajax 호출전");
// <a>의 parent(<td>)의 parent 즉, <tr>를 지칭한다.(클로저)
/*
어떻게 제이쿼리는 this가 <a>인 것을 알고있을까?
: a 태그내 .a-delete 클릭 이벤트가 발생 되었으므로!
: $('.a-delete').click(function(event)
*/
var trObj = $(this).parent().parent();
$.ajax({
// AJAX의 타입(삭제)
type : 'DELETE',
// <a>의(this) 속성(href)을 가져온다.(attr)
url : $(this).attr("href"),
// 캐시를 false 설정하여 페이지가 새로 고쳐질때
// 데이터를 남기지 않는다(?)
cache : false,
success: function(result){
console.log(result);
if(result=="SUCCESS"){
// trObj 변수를 삭제한다.(게시글 삭제)
$(trObj).remove();
console.log("REMOVED!")
}
},
error:function(e){
console.log(e);
}
})
});
});
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<tr>
<th>번호</th>
<th>이름</th>
<th>제목</th>
<th>날짜</th>
<th>조회수</th>
<th>삭제</th>
</tr>
<c:forEach items="${list}" var="dto">
<tr>
<td>${dto.bId}</td>
<td>${dto.bName}</td>
<td>
<c:forEach begin="1" end="${dto.bIndent}">[Re]</c:forEach>
<a href="${pageContext.request.contextPath}/restful/board/${dto.bId}">${dto.bTitle}</a></td>
<td><fmt:formatDate value="${dto.bDate}" pattern="YYYY-MM-DD"/></td>
<td>${dto.bHit}</td>
<td><a class="a-delete" href="${pageContext.request.contextPath}/restful/board/${dto.bId}">삭제</a></td>
</tr>
</c:forEach>
<tr>
<th>번호</th>
<th>이름</th>
<th>제목</th>
<th>날짜</th>
<th>조회수</th>
<th>삭제</th>
</tr>
<tr>
<td colspan="6"><a href="${pageContext.request.contextPath}/restful/write">글쓰기</a></th>
</tr>
</table>
</body>
</html>
1-2. 작성글 삭제
// Controller 객체
@DeleteMapping("/board/{bId}")
public ResponseEntity<String> rest_delete(BoardVO boardVO, Model model) {
ResponseEntity<String> entity = null;
log.info("rest_delete..");
try {
boardService.remove(boardVO.getbId());
// 삭제가 성공하면 상태메시지 저장
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
// 댓글 삭제가 실패하면 BAD_REQUEST를 리턴
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
// 삭제 처리 HTTP 상태 메시지 리턴
return entity;
}
// Service 인터페이스
public int remove(int bId);
// 인터페이스 구현 객체
@Override
public int remove(int bId) {
log.info("remove..........");
return mapper.ajaxDelete(bId);
}
// BoardMapper 객체
public int ajaxDelete(int bId);
<!-- SQL 구현부 -->
<delete id="ajaxDelete">
<![CDATA[
delete from mvc_board where bId = #{bId}
]]>
</delete>
<!-- 페이지 구현부 -->
<%@ 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" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Rest List</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function (){
$('.a-delete').click(function(event){
// 이벤트를 취소할 때 동작을 멈춘다.
event.preventDefault();
console.log("ajax 호출전");
// <a>의 parent(<td>)의 parent 즉, <tr>를 지칭한다.(클로저)
/*
어떻게 제이쿼리는 this가 <a>인 것을 알고있을까?
: a 태그내 .a-delete 클릭 이벤트가 발생 되었으므로!
: $('.a-delete').click(function(event)
*/
var trObj = $(this).parent().parent();
$.ajax({
// AJAX의 타입(삭제)
type : 'DELETE',
// <a>의(this) 속성(href)을 가져온다.(attr)
url : $(this).attr("href"),
// 캐시를 false 설정하여 페이지가 새로 고쳐질때
// 데이터를 남기지 않는다(?)
cache : false,
success: function(result){
console.log(result);
if(result=="SUCCESS"){
// trObj 변수를 삭제한다.(게시글 삭제)
$(trObj).remove();
console.log("REMOVED!")
}
},
error:function(e){
console.log(e);
}
})
});
});
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<tr>
<th>번호</th>
<th>이름</th>
<th>제목</th>
<th>날짜</th>
<th>조회수</th>
<th>삭제</th>
</tr>
<c:forEach items="${list}" var="dto">
<tr>
<td>${dto.bId}</td>
<td>${dto.bName}</td>
<td>
<c:forEach begin="1" end="${dto.bIndent}">[Re]</c:forEach>
<a href="${pageContext.request.contextPath}/restful/board/${dto.bId}">${dto.bTitle}</a></td>
<td><fmt:formatDate value="${dto.bDate}" pattern="YYYY-MM-DD"/></td>
<td>${dto.bHit}</td>
<td><a class="a-delete" href="${pageContext.request.contextPath}/restful/board/${dto.bId}">삭제</a></td>
</tr>
</c:forEach>
<tr>
<th>번호</th>
<th>이름</th>
<th>제목</th>
<th>날짜</th>
<th>조회수</th>
<th>삭제</th>
</tr>
<tr>
<td colspan="6"><a href="${pageContext.request.contextPath}/restful/write">글쓰기</a></th>
</tr>
</table>
</body>
</html>
1-3. 작성글 불러오기
// Controller 객체
@GetMapping("/board/{bId}")
public ModelAndView rest_content_view(BoardVO boardVO, ModelAndView mav) {
log.info("rest_content_view");
mav.setViewName("rest/content_view");
mav.addObject("content_view", boardService.getBoard(boardVO.getbId()));
return mav;
}
// Service 인터페이스
public BoardVO getBoard(int getbId);
// 인터페이스 구현 객체
@Transactional
@Override
public BoardVO getBoard(int bno) {
mapper.upHit(bno);
log.info("getBoard()");
return mapper.read(bno);
}
// BoardMapper 객체
public BoardVO read(int bno);
public void upHit(int bno);
<!-- SQL 구현부 -->
<select id="read" resultType="edu.bit.ex.board.vo.BoardVO">
<![CDATA[
select * from mvc_board where bId = #{bno}
]]>
</select>
<update id="upHit">
<![CDATA[
update mvc_board set bHit = bHit+1 where bId = #{bId}
]]>
</update>
<!-- 페이지 구현부 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Content View</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#updateForm").submit(function(event){
event.preventDefault();
var bId = $("#bId").val();
var bName = $("#bName").val();
var bTitle = $("#bTitle").val();
var bContent = $("#bContent").val();
console.log(bName);
console.log(bTitle);
console.log(bContent);
console.log($(this).attr("action"));
var form = {
bId: bId,
bName: bName,
bContent: bContent,
bTitle: bTitle
};
$.ajax({
type : "PUT",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8', // 인코딩 데이터 변환
data: JSON.stringify(form), // 보안 문제 해결을 위해 stringify 메소드를 사용
success: function (result) {
if(result == "SUCCESS"){
// update가 완료되었으면 리스트 페이지로 이동
$(location).attr('href', '${pageContext.request.contextPath}/restful/board/')
}
},
error: function (e) {
console.log(e);
}
})
}); // end submit()
}); // end ready()
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<form id="updateForm" action="${pageContext.request.contextPath}/restful/board/${content_view.bId}" method="post">
<input type="hidden" id="bId" value="${content_view.bId}">
<tr>
<td> 번호 </td>
<td> ${content_view.bId} </td>
</tr>
<tr>
<td> 조회수 </td>
<td> ${content_view.bHit} </td>
</tr>
<tr>
<td> 이름 </td>
<td> <input type="text" id="bName" value="${content_view.bName}"></td>
</tr>
<tr>
<td> 제목 </td>
<td> <input type="text" id="bTitle" value="${content_view.bTitle}"></td>
</tr>
<tr>
<td> 내용 </td>
<td> <textarea rows="10" id="bContent" >${content_view.bContent}</textarea></td>
</tr>
<tr >
<td colspan="2">
<input type="submit" value="수정">
<a href="${pageContext.request.contextPath}/restful/board">목록보기</a>
<a href="#">삭제</a>
<a href="${pageContext.request.contextPath}/restful/board/reply/${content_view.bId}">답변</a>
</td>
</tr>
</form>
</table>
</body>
</html>
1-4. 작성글 수정하기
// Controller 객체
@PutMapping("/board/{bId}")
public ResponseEntity<String> rest_update(@RequestBody BoardVO boardVO, ModelAndView modelAndView) {
ResponseEntity<String> entity = null;
log.info("rest_update..");
try {
boardService.modifyBoard(boardVO);
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return entity;
}
// Service 인터페이스
public void modifyBoard(BoardVO boardVO);
// 인터페이스 구현 객체
@Override
public void modifyBoard(BoardVO boardVO) {
mapper.modify(boardVO);
log.info("modifyBoard()");
}
// BoardMapper 객체
public void modify(BoardVO boardVO);
<!-- SQL 구현부 -->
<update id="modify">
<![CDATA[
update mvc_board set bName = #{bName}, bTitle = #{bTitle}, bContent = #{bContent} where bId = #{bId}
]]>
</update>
<!-- 페이지 구현부 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Content View</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#updateForm").submit(function(event){
event.preventDefault();
var bId = $("#bId").val();
var bName = $("#bName").val();
var bTitle = $("#bTitle").val();
var bContent = $("#bContent").val();
console.log(bName);
console.log(bTitle);
console.log(bContent);
console.log($(this).attr("action"));
var form = {
bId: bId,
bName: bName,
bContent: bContent,
bTitle: bTitle
};
$.ajax({
type : "PUT",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8', // 인코딩 데이터 변환
data: JSON.stringify(form), // 보안 문제 해결을 위해 stringify 메소드를 사용
success: function (result) {
if(result == "SUCCESS"){
// update가 완료되었으면 리스트 페이지로 이동
$(location).attr('href', '${pageContext.request.contextPath}/restful/board/')
}
},
error: function (e) {
console.log(e);
}
})
}); // end submit()
}); // end ready()
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<form id="updateForm" action="${pageContext.request.contextPath}/restful/board/${content_view.bId}" method="post">
<input type="hidden" id="bId" value="${content_view.bId}">
<tr>
<td> 번호 </td>
<td> ${content_view.bId} </td>
</tr>
<tr>
<td> 조회수 </td>
<td> ${content_view.bHit} </td>
</tr>
<tr>
<td> 이름 </td>
<td> <input type="text" id="bName" value="${content_view.bName}"></td>
</tr>
<tr>
<td> 제목 </td>
<td> <input type="text" id="bTitle" value="${content_view.bTitle}"></td>
</tr>
<tr>
<td> 내용 </td>
<td> <textarea rows="10" id="bContent" >${content_view.bContent}</textarea></td>
</tr>
<tr >
<td colspan="2">
<input type="submit" value="수정">
<a href="${pageContext.request.contextPath}/restful/board">목록보기</a>
<a href="#">삭제</a>
<a href="${pageContext.request.contextPath}/restful/board/reply/${content_view.bId}">답변</a>
</td>
</tr>
</form>
</table>
</body>
</html>
1-5. 작성글 답변하기
// Controller 객체
@GetMapping("/board/reply/{bId}")
public ModelAndView rest_reply_view(BoardVO boardVO, ModelAndView mav) {
log.info("rest_reply_view");
mav.setViewName("rest/reply_view");
mav.addObject("reply_view", boardService.getReply(boardVO.getbId()));
return mav;
}
@PutMapping("/board/reply/{bId}")
public ResponseEntity<String> rest_reply(@RequestBody BoardVO boardVO, ModelAndView modelAndView) {
ResponseEntity<String> entity = null;
log.info("rest_reply..");
try {
boardService.replyBoard(boardVO);
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return entity;
}
// Service 인터페이스
public BoardVO getReply(int getbId);
public void replyBoard(BoardVO boardVO);
// 인터페이스 구현 객체
@Override
public BoardVO getReply(int bno) {
log.info("getBoard()");
return mapper.readReply(bno);
}
@Transactional
@Override
public void replyBoard(BoardVO boardVO) {
mapper.reply(boardVO);
mapper.replyShape(boardVO);
log.info("replyBoard()");
}
// BoardMapper 객체
public BoardVO readReply(int bno);
public void reply(BoardVO boardVO);
public void replyShape(BoardVO boardVO);
<!-- SQL 구현부 -->
<select id="readReply" resultType="edu.bit.ex.board.vo.BoardVO">
<![CDATA[
select * from mvc_board where bId = #{bno}
]]>
</select>
<insert id="reply" >
<![CDATA[
insert into mvc_board (bId, bName, bTitle, bContent, bGroup, bStep, bIndent) values (mvc_board_seq.nextval, #{bName}, #{bTitle}, #{bContent}, #{bGroup}, #{bStep}+1, #{bIndent}+1)
]]>
</insert>
<update id="replyShape" >
<![CDATA[
update mvc_board set bStep = bStep + 1 where bGroup = #{bGroup}
]]>
</update>
<!-- 페이지 구현부 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Reply View</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#modifyForm").submit(function(event){
event.preventDefault();
var bId = $("#bId").val();
var bGroup = $("#bGroup").val();
var bStep = $("#bStep").val();
var bIndent = $("#bIndent").val();
var bName = $("#bName").val();
var bTitle = $("#bTitle").val();
var bContent = $("#bContent").val();
console.log(bId);
console.log(bGroup);
console.log(bStep);
console.log(bIndent);
console.log(bName);
console.log(bTitle);
console.log(bContent);
console.log($(this).attr("action"));
var form = {
bId: bId,
bGroup: bGroup,
bStep: bStep,
bIndent: bIndent,
bName: bName,
bTitle: bTitle,
bContent: bContent
};
$.ajax({
type : "PUT",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8',
data: JSON.stringify(form),
success: function (result) {
if(result == "SUCCESS"){
$(location).attr('href', '${pageContext.request.contextPath}/restful/board/')
}
},
error: function (e) {
console.log(e);
}
})
});
});
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<form id="modifyForm" action="${pageContext.request.contextPath}/restful/board/reply/${reply_view.bId}" method="post">
<input type="hidden" id="bId" name="bId" value="${reply_view.bId}">
<input type="hidden" id="bGroup" name="bGroup" value="${reply_view.bGroup}">
<input type="hidden" id="bStep" name="bStep" value="${reply_view.bStep}">
<input type="hidden" id="bIndent" name="bIndent" value="${reply_view.bIndent}">
<tr>
<td>번호</td>
<td>${reply_view.bId}</td>
</tr>
<tr>
<td>조회수</td>
<td>${reply_view.bHit}</td>
</tr>
<tr>
<td>이름</td>
<td><input type="text" id="bName" name="bName" value="${reply_view.bName}"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" id="bTitle" name="bTitle" value="${reply_view.bTitle}"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea cols="20" id="bContent" rows="10" name="bContent">${reply_view.bContent}</textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="답변">
<a href="${pageContext.request.contextPath}/restful/board">목록</a>
</td>
</tr>
</form>
</table>
</body>
</html>
1-6. 글 작성하기
// Controller 객체
@GetMapping("/board/write")
public ModelAndView rest_write_view(BoardVO boardVO, ModelAndView mav) {
log.info("rest_write_view");
mav.setViewName("rest/write_view");
return mav;
}
@PutMapping("/board/write")
public ResponseEntity<String> write_view(@RequestBody BoardVO boardVO, ModelAndView modelAndView) {
ResponseEntity<String> entity = null;
log.info("write_view..");
try {
boardService.writeBoard(boardVO);
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return entity;
}
// Service 인터페이스
public void writeBoard(BoardVO boardVO);
// 인터페이스 구현 객체
@Override
public void writeBoard(BoardVO boardVO) {
mapper.insert(boardVO);
log.info("writeBoard()");
}
// BoardMapper 객체
public void insert(BoardVO boardVO);
<!-- SQL 구현부 -->
<insert id="insert">
<![CDATA[
insert into mvc_board (bId, bName, bTitle, bContent, bHit, bGroup, bStep, bIndent) values (mvc_board_seq.nextval, #{bName}, #{bTitle}, #{bContent}, 0, mvc_board_seq.currval, 0, 0)
]]>
</insert>
<!-- 페이지 구현부 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Write View</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#writeForm").submit(function(event){
event.preventDefault();
var bName = $("#bName").val();
var bTitle = $("#bTitle").val();
var bContent = $("#bContent").val();
console.log(bName);
console.log(bTitle);
console.log(bContent);
console.log($(this).attr("action"));
var form = {
bName: bName,
bTitle: bTitle,
bContent: bContent
};
$.ajax({
type : "PUT",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8',
data: JSON.stringify(form),
success: function (result) {
if(result == "SUCCESS"){
$(location).attr('href', '${pageContext.request.contextPath}/restful/board/')
}
},
error: function (e) {
console.log(e);
}
})
});
});
</script>
</head>
<body>
<table width="500" cellpadding="0" cellspacing="0" border="1">
<form id="writeForm" action="${pageContext.request.contextPath}/restful/board/write" method="post">
<tr>
<td>이름</td>
<td><input type="text" id="bName" name="bName" size="50"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" id="bTitle" name="bTitle" size="50"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea cols="20" rows="10" id="bContent" name="bContent"></textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="입력">
<a href="${pageContext.request.contextPath}/restful/board">목록</a>
</td>
</tr>
</form>
</table>
</body>
</html>
2. 부트스트랩으로 로그인 화면구현후 interceptor 적용하여 로그인한 유저에게만 게시판이 보이도록 하시오.
2-1. 소스코드(Controller 객체)
package edu.bit.ex.board.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import edu.bit.ex.board.service.LoginService;
import edu.bit.ex.board.vo.UserVO;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Log4j
@AllArgsConstructor
@Controller
public class LoginController {
private LoginService loginService;
// 루트 페이지 매핑(home 컨트롤러 매핑 구현 주석처리 할 것
@GetMapping("/")
public String home() {
log.info("home...");
return "log/login";
}
// 로그인 페이지
@PostMapping("/login")
public String login(HttpServletRequest req, RedirectAttributes rttr) {
log.info("post login..");
String id = req.getParameter("id");
String pw = req.getParameter("pw");
// Session 처리를 위한 Session 객체 HttpServletRequest 안에 있음.
HttpSession session = req.getSession();
UserVO user = loginService.loginUser(id, pw);
if (user == null) {
session.setAttribute("user", null);
/*
* Spring3 에서 제공하는 RedirectAttributes를 사용하면 redirect post 구현이 가능하다.
* 하지만 일회성이라 새로고침하면 날라가는 데이터이므로 사용목적에 따라서 판단 후 사용한다.
*/
rttr.addFlashAttribute("msg", false);
} else {
session.setAttribute("user", user);
}
return "redirect:/";
}
// 로그아웃
@RequestMapping(value = "/logout")
public String logout(HttpSession session) throws Exception {
log.info("/member/logout");
session.invalidate();
return "redirect:/";
}
}
2-2. 소스코드(Interceptor 객체)
package edu.bit.ex.board.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import edu.bit.ex.board.vo.UserVO;
import lombok.extern.log4j.Log4j;
@Log4j
public class BoardInterceptor extends HandlerInterceptorAdapter {
// preHandle() : 컨트롤러보다 먼저 수행되는 메서드
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle 실행");
// session 객체를 가져옴
HttpSession session = request.getSession();
// login처리를 담당하는 사용자 정보를 담고 있는 객체를 가져옴
UserVO user = (UserVO) session.getAttribute("user");
if (user == null) {
log.info("user가 null");
// 로그인이 안되어 있는 상태이므로 로그인 폼으로 다시 돌려보냄(redirect)
response.sendRedirect(request.getContextPath());
return false; // 더이상 컨트롤러 요청으로 가지 않도록 false로 반환함
}
// preHandle의 return은 컨트롤러 요청 uri로 가도 되냐 안되냐를 허가하는 의미임
// 따라서 true로하면 컨트롤러 uri로 가게 됨.
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
System.out.println("postHandle 실행");
}
}
2-3. 소스코드(LoginService 인터페이스 및 객체)
// 로그인 인터페이스
package edu.bit.ex.board.service;
import edu.bit.ex.board.vo.UserVO;
public interface LoginService {
public UserVO loginUser(String id, String pw);
}
// 로그인 서비스 객체
package edu.bit.ex.board.service;
import org.springframework.stereotype.Service;
import edu.bit.ex.board.mapper.LoginMapper;
import edu.bit.ex.board.vo.UserVO;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
public class LoginServiceImpl implements LoginService {
LoginMapper loginMapper;
@Override
public UserVO loginUser(String id, String pw) {
return loginMapper.logInUser(id, pw);
}
}
2-4. 소스코드(LoginMapper 객체)
package edu.bit.ex.board.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import edu.bit.ex.board.vo.UserVO;
//@Mapper // root-context내 my-batis 매퍼 경로 지정이 없을시 사용
@Mapper
public interface LoginMapper {
// 지정할 변수가 2개 이상인 경우 파라미터를 설정한다.
@Select("select * from users where username = #{username} and password = #{password}")
public UserVO logInUser(@Param("username") String username, @Param("password") String password);
}
2-5. 소스코드(login 페이지)
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="/docs/4.0/assets/img/favicons/favicon.ico">
<title>Login Page</title>
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/sign-in/">
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- Custom styles for this template -->
<link href="<c:url value="/resources/css/signin.css"/>" rel="stylesheet">
</head>
<body>
<c:if test="${user == null}">
<form class="form-signin" role="form" method="post" autocomplete="off" action="${pageContext.request.contextPath}/login">
<a href="https://github.com/roqhdehd502">
<center>
<img class="mb-4" src="https://avatars.githubusercontent.com/u/47406388?s=460&u=be5c94a9effdfe887c56be3dec5ca29e224e83ce&v=4" alt="" width="72" height="72">
</center>
</a>
<h1 class="h3 mb-3 font-weight-normal"><center>아이디와 비밀번호를<br>입력해주세요.</center></h1>
<!--<p>
<label for="userId">아이디</label>
<input type="text" id="userId" name="id" />
</p>-->
<label for="inputEmail" class="sr-only">아이디</label>
<input type="text" id="inputId" class="form-control" placeholder="아이디" name="id" required autofocus>
<!--<p>
<label for="userPass">패스워드</label>
<input type="password" id="userPass" name="pw"/>
</p>-->
<label for="inputPassword" class="sr-only">패스워드</label>
<input type="password" id="inputPassword" class="form-control" placeholder="패스워드" name="pw" required>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 입력사항 기억
</label>
</div>
<!--<p><button type="submit">로그인</button></p>
<p><a href="/member/register">회원가입</a></p> -->
<button class="btn btn-lg btn-primary btn-block" type="submit">로그인</button>
<p class="mt-5 mb-3 text-muted"><center>2021©All rights reserved by <a href="https://getbootstrap.com/">getbootstrap</a>.<br><br>
Designed and built with all the love in the world by the Bootstrap team with the help of our contributors.<br>
Currently v5.0.0-beta1. Code licensed MIT, docs CC BY 3.0.<br>
</center></p>
</form>
</c:if>
<c:if test="${msg == false}">
<p style="color:#f00;">로그인에 실패했습니다. 아이디 또는 패스워드를 다시 입력해주십시오.</p>
</c:if>
<c:if test="${user != null}">
<p>${user.username}님 환영합니다.</p>
<!-- <a href="member/modify">회원정보 수정</a>, <a href="member/withdrawal">회원탈퇴</a><br/> -->
<a href="${pageContext.request.contextPath}/board/list">게시판 리스트</a><br>
<a href="${pageContext.request.contextPath}/logout">로그아웃</a>
</c:if>
</body>
</html>
2-6. 구현화면
3. interceptor의 개념에 대하여 설명하시오.
: 단어상 ‘가로채다(intercept)‘의 의미를 가진 인터셉터는 서버 페이지에서 입력 데이터 정보를 보내 클라이언트에게 응답을 하기 전, 서버 측 세션 내용을 중간에 가져와 유효성 검증을 하는 기능이다. Spring에서는 HandlerInterceptorAdapter 객체를 상속하여 구현한다.
public class BoardInterceptor extends HandlerInterceptorAdapter {
// preHandle() : 컨트롤러보다 먼저 수행되는 메서드
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle 실행");
// session 객체를 가져옴
HttpSession session = request.getSession();
// login처리를 담당하는 사용자 정보를 담고 있는 객체를 가져옴
UserVO user = (UserVO) session.getAttribute("user");
if (user == null) {
log.info("user가 null");
// 로그인이 안되어 있는 상태이므로 로그인 폼으로 다시 돌려보냄(redirect)
response.sendRedirect(request.getContextPath());
return false; // 더이상 컨트롤러 요청으로 가지 않도록 false로 반환함
}
// preHandle의 return은 컨트롤러 요청 uri로 가도 되냐 안되냐를 허가하는 의미임
// 따라서 true로하면 컨트롤러 uri로 가게 됨.
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
System.out.println("postHandle 실행");
}
}
4. 부트스트랩이란?
: HTML, CSS, JS 태그 및 스크립트의 성능 향상 및 기능 확장성을 둔 프론트엔드 프레임워크(Front-End Framework)이다. 부트스트랩이 가진 특성은 동적 웹 페이지(Dynamic Web Page)를 구축할 수 있어 PC외에도 스마트폰 및 태블릿 등 다양한 플랫폼에 디자인을 적용할 수 있다.
'WebDev > 본과정' 카테고리의 다른 글
Spring Security (0) | 2021.05.17 |
---|---|
목표 지향 프로그래밍 (0) | 2021.05.17 |
Spring의 트랜잭션과 rollback 및 commit (0) | 2021.05.17 |
RESTful (0) | 2021.05.17 |
AJAX와 JSON (0) | 2021.05.17 |
최근댓글