- 어제 프로젝트에서 최신상품, 베스트상품 슬라이더로 이용할 쿼리문을 작성하겠다.
/ex08/src/main/resources/mapper/ProductMapper.xml
<select resultType="hashmap" id="best">
select * from tbl_product
order by viewcnt desc
limit 0,10
</select>
<select resultType="hashmap" id="new">
select * from tbl_product
order by pcode desc
limit 0,10
</select>
/ex08/src/main/java/com/example/mapper/ProductDAO.java
...
public List<HashMap<String, Object>> bestProduct();
public List<HashMap<String, Object>> newProduct();
}
/ex08/src/main/java/com/example/mapper/ProductDAOImpl.java
...
@Override
public List<HashMap<String, Object>> bestProduct() {
return session.selectList(namespace+".best");
}
@Override
public List<HashMap<String, Object>> newProduct() {
return session.selectList(namespace+".new");
}
}
- 이제 메서드를 호출하기 위해서 컨트롤러를 이용한다.
/ex08/src/main/java/com/example/controller/ProductController.java
...
// 파일 저장 루트 지정
@Resource(name = "uploadPath")
private String path;
// best product
@RequestMapping("/best.json")
@ResponseBody
public List<HashMap<String, Object>> bestProduct(){
return pdao.bestProduct();
}
// brandnew product
@RequestMapping("/new.json")
@ResponseBody
public List<HashMap<String, Object>> newProduct(){
return pdao.newProduct();
}
...
- 이제 컨트롤러에 있는 restAPI를 테스트해보겠다.
- 이제 best 상품과 new 상품을 출력할 페이지를 만들도록 하겠다.
/ex08/src/main/webapp/WEB-INF/views/best.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
<style>
#slider {
position: relative;
overflow: hidden;
width: 550px;
height: 150px;
}
#items {
position: absolute;
width: 1100px;
overflow: hidden;
margin-left: -110px;
}
#items .item {
width: 100px;
float: left;
margin-left: 10px;
height: 150px
}
#items .item img {
width: 100px;
}
</style>
</head>
<body>
<div id="slider">
<div id="items"></div>
<script id="temp1" type="text/x-handlebars-template">
{{#each .}}
<div class="item">
<img src="/display?fileName={{image}}"/>
</div>
{{/each}}
</script>
</div>
<div style="width: 550px; text-align: center; margin-top: 10px;">
<button id="prev"><</button>
<button id="next">></button>
</div>
</body>
<script>
//item생성 후 items에 추가
$.ajax({
type : "get",
url : "/best.json",
dataType : "json",
success : function(data) {
var temp = Handlebars.compile($("#temp1").html());
$("#items").html(temp(data));
}
});
//슬라이드 반복 실행
var repeat = setInterval(function() {
$('#next').click();
}, 2500);
$('#next').on('click', function() {
clearInterval(repeat); //슬라이드 반복 중지
$('#items .item:first').animate({
marginLeft : -110
}, 300, function() {
$(this).appendTo($('#items')).css({
marginLeft : 10
});
});
repeat = setInterval(function() {
$('#next').click();
}, 2500); //슬라이드 반복 실행
});
$('#prev').on('click', function() {
clearInterval(repeat); //슬라이드 반복 중지
$('#items .item:first').animate({
marginLeft : 110
}, 300, function() {
$(this).before($('#items .item:last')).css({
marginLeft : 10
});
});
repeat = setInterval(function() {
$('#next').click();
}, 2500); //슬라이드 반복 실행
});
</script>
<html>
- 해당 페이지를 list.jsp에 출력하도록 하겠다.
/ex08/src/main/webapp/WEB-INF/views/list.jsp
...
</style>
<h1>[BEST 상품]</h1>
<div style="margin-left:200px">
<jsp:include page="best.jsp"></jsp:include>
</div>
<h1>[상품 목록]</h1>
...
- 오늘은 새로운 프로젝트에 인터셉터를 이용해 로그인까지 해보겠다.
- ex09 프로젝트를 생성하고 아래 VO, 컨트롤러, page를 생성하겠다.
/ex09/src/main/java/com/example/domain/BoardVO.java
package com.example.domain;
import java.util.Arrays;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
public class BoardVO {
private int bno;
private String title;
private String content;
private String writer;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Seoul")
private Date regdate;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Seoul")
private Date updatedate;
private int viewcount;
private int replycount;
private String[] files;
private int attachcount;
/ex09/src/main/java/com/example/domain/ReplyVO.java
package com.example.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
public class ReplyVO {
private int rno;
private int bno;
private String reply;
private String replyer;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Seoul")
private Date replydate;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Seoul")
private Date updatedate;
/ex09/src/main/java/com/example/controller/HomeController.java
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
model.addAttribute("pageName", "list.jsp");
return "home";
}
}
/ex09/src/main/webapp/WEB-INF/views/home.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>이주성 커뮤니티</title>
<link rel="stylesheet" href="/resources/home.css" />
<script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
</head>
<body>
<div id="page">
<div id="header">
<a href="/" title="홈으로"><img src="/resources/back.png" width=960 /></a>
</div>
<div id="center">
<div id="menu">
<a href="/insert" title="글쓰기">글쓰기</a>
</div>
<div id="content">
<jsp:include page="${pageName}"></jsp:include>
</div>
</div>
<div id="footer">
<h3>Copyright H&S. All rights Reserved.</h3>
</div>
</div>
</body>
</html>
/ex09/src/main/webapp/WEB-INF/views/home.jsp
/ex09/src/main/webapp/WEB-INF/views/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[게시판 관리]</h1>
- 이제 목록을 만들기 위해 mapper 생성
/ex09/src/main/resources/mapper/BoardMapper.xml
<?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="com.example.mapper.BoardMapper">
<!-- list -->
<select id="list" resultType="com.example.domain.BoardVO">
select * from tbl_board
order by bno desc
limit #{pageStart},#{perPageNum}
</select>
<!-- read -->
<select resultType="com.example.domain.BoardVO" id="read">
select * from tbl_board
where bno=#{bno}
</select>
<!-- insert -->
<insert id="insert">
insert into tbl_board(title,content,writer)
values(#{title},#{content},#{writer})
</insert>
</mapper>
/ex09/src/main/java/com/example/mapper/BoardDAO.java
package com.example.mapper;
import java.util.List;
import com.example.domain.BoardVO;
import com.example.domain.Criteria;
public interface BoardDAO {
public List<BoardVO> list(Criteria cri);
public BoardVO read(int bno);
public void insert(BoardVO vo);
}
/ex09/src/main/java/com/example/mapper/BoardDAOImpl.java
package com.example.mapper;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.domain.BoardVO;
import com.example.domain.Criteria;
@Repository
public class BoardDAOImpl implements BoardDAO{
@Autowired
SqlSession session;
String namespace="com.example.mapper.BoardMapper";
@Override
public List<BoardVO> list(Criteria cri) {
return session.selectList(namespace+".list", cri);
}
@Override
public BoardVO read(int bno) {
return session.selectOne(namespace+".read", bno);
}
@Override
public void insert(BoardVO vo) {
session.insert(namespace+".insert", vo);
}
}
- junit으로 test먼저 하겠다.
/ex09/src/test/java/com/example/controller/MysqlTest.java
package com.example.controller;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.example.domain.Criteria;
import com.example.mapper.BoardDAO;
import com.example.mapper.MysqlMapper;
@RunWith(SpringJUnit4ClassRunner.class) // 먼저 SpringJUnit4ClassRunner.class
// import한다.
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class MysqlTest {
// 자동으로 연결
@Autowired
private BoardDAO mapper;
// 연결해서 getTime을 테스트
@Test
public void getTime() {
Criteria cri = new Criteria();
cri.setPerPageNum(3);
mapper.list(cri);
}
}
- 이제 컨트롤러를 생성하겠다.
/ex09/src/main/java/com/example/controller/BoardController.java
package com.example.controller;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.domain.Criteria;
import com.example.domain.PageMaker;
import com.example.mapper.BoardDAO;
@Controller
public class BoardController {
@Autowired
BoardDAO bdao;
// list json data get
@RequestMapping("/list.json")
@ResponseBody
public HashMap<String, Object> listJSON(Criteria cri){
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("list", bdao.list(cri));
PageMaker pm = new PageMaker();
pm.setCri(cri);
pm.setTotalCount(120);
map.put("cri", cri);
map.put("pm", pm);
return map;
}
}
- 이제 해당 데이터를 list.jsp에 출력해주도록 하겠다.
/ex09/src/main/webapp/WEB-INF/views/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[게시판 관리]</h1>
<table id="tbl">
</table>
<script id="temp" type="text/x-handlebars-template">
{{#each list}}
<tr class="row" onClick="location.href='read?bno={{bno}}'">
<td width=50>{{bno}}</td>
<td width=300>{{title}}</td>
<td width=200>{{regdate}}</td>
<td width=100>{{writer}}</td>
</tr>
{{/each}}
</script>
<div id="pagination" class="pagination"></div>
<script src="/resources/pagination.js"></script>
<script>
var page = 1;
getList();
function getList() {
$.ajax({
type : 'get',
url : '/list.json',
dataType : 'json',
data : {
page : page
},
success : function(data) {
var temp = Handlebars.compile($('#temp').html());
$('#tbl').html(temp(data));
$('#pagination').html(getPagination(data));
}
})
}
$("#pagination").on('click', 'a', function(e) {
e.preventDefault();
page = $(this).attr("href");
getList();
})
</script>
- 이제 특정 행을 클릭하면 해당 데이터를 보여주는 page에 갈 수 있도록 하겠다.
/ex09/src/main/java/com/example/controller/BoardController.java
...
@Controller
public class BoardController {
@Autowired
BoardDAO bdao;
// read page con
@RequestMapping("/read")
public String read(int bno, Model model){
model.addAttribute("pageName","read.jsp");
model.addAttribute("vo",bdao.read(bno));
return "home";
}
...
/ex09/src/main/webapp/WEB-INF/views/read.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[게시글 정보]</h1>
<div>
<h1>${vo.bno}:${vo.title}</h1>
<h4 style="color:rgb(57, 109, 192)">${vo.writer}/${vo.regdate}</h4>
<hr />
<p>${vo.content}</p>
</div>
- 댓글(tbl_reply)을 작성할 수 있게 하겠다.
- 우선 mapper부터 작성하겠다.
/ex09/src/main/resources/mapper/ReplyMapper.xml
<?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="com.example.mapper.ReplyMapper">
<select id="list" resultType="com.example.domain.ReplyVO">
select * from tbl_reply
where bno=#{bno}
order by rno desc
limit #{cri.pageStart},#{cri.perPageNum}
</select>
</mapper>
/ex09/src/main/java/com/example/domain/ReplyDAO.java
package com.example.mapper;
import java.util.List;
import com.example.domain.Criteria;
import com.example.domain.ReplyVO;
public interface ReplyDAO {
public List<ReplyVO> list(int bno, Criteria cri);
}
/ex09/src/main/java/com/example/domain/ReplyDAOImpl.java
package com.example.mapper;
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.domain.Criteria;
import com.example.domain.ReplyVO;
@Repository
public class ReplyDAOImpl implements ReplyDAO {
@Autowired
SqlSession session;
String namespace = "com.example.mapper.ReplyMapper";
@Override
public List<ReplyVO> list(int bno, Criteria cri) {
HashMap<String, Object> map = new HashMap<>();
map.put("cri", cri);
map.put("bno", bno);
return session.selectList(namespace + ".list", map);
}
}
- 테스트해보겠다.
/ex09/src/test/java/com/example/controller/MysqlTest.java
package com.example.controller;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.example.domain.Criteria;
import com.example.mapper.BoardDAO;
import com.example.mapper.MysqlMapper;
import com.example.mapper.ReplyDAO;
@RunWith(SpringJUnit4ClassRunner.class) // 먼저 SpringJUnit4ClassRunner.class
// import한다.
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class MysqlTest {
// 자동으로 연결
@Autowired
private ReplyDAO mapper;
// 연결해서 getTime을 테스트
@Test
public void getTime() {
Criteria cri = new Criteria();
cri.setPerPageNum(3);
mapper.list(192,cri);
}
}
- 댓글을 위한 컨트롤러
/ex09/src/main/java/com/example/controller/ReplyController.java
package com.example.controller;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.domain.Criteria;
import com.example.domain.PageMaker;
import com.example.mapper.ReplyDAO;
@RestController
public class ReplyController {
@Autowired
ReplyDAO rdao;
@RequestMapping("/reply.json")
public HashMap<String, Object> list(int bno, Criteria cri){
HashMap<String, Object> map = new HashMap<String, Object>();
cri.setPerPageNum(5);
map.put("list", rdao.list(bno, cri));
// 페이지 목록
PageMaker pm = new PageMaker();
pm.setCri(cri);
pm.setTotalCount(120);
map.put("cri", cri);
map.put("pm", pm);
return map;
}
}
- 해당 데이터를 read.jsp에 출력해주겠다.
/ex09/src/main/webapp/WEB-INF/views/read.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[게시글 정보]</h1>
<style>
.box {
text-align: left;
margin-top: 10px;
padding: 10px;
border-bottom: 1px dotted gray;
}
.replyer {
font-weight: bold;
color: #396dc0;
margin-bottom: 5px;
}
.replydate {
text-align: right;
}
.replyBox {
padding: 10px;
width: 850px;
margin: 0px auto;
border: 1px dotted gray;
}
</style>
<div>
<h1>${vo.bno}:${vo.title}</h1>
<h4 style="color: rgb(57, 109, 192)">${vo.writer}/${vo.regdate}</h4>
<hr />
<p>${vo.content}</p>
</div>
<hr />
<h2>[댓글 목록]</h2>
<div id="replies"></div>
<script id="temp" type="text/x-handlebars-template">
{{#each list}}
<div class="box">
<div class="replyer">
<span>[{{rno}}]</span>
<span>{{replyer}}</span>
</div>
<div class="reply">
<span>{{reply}}</span>
</div>
<div class="replydate">
<span>{{replydate}}</span>
</div>
</div>
{{/each}}
</script>
<div id="pagination" class="pagination"></div>
<script src="/resources/pagination.js"></script>
<script>
var page = 1;
var bno = "${vo.bno}";
getList();
function getList() {
$.ajax({
type : 'get',
url : '/reply.json',
dataType : 'json',
data : {
page : page,
bno : bno
},
success : function(data) {
var temp = Handlebars.compile($('#temp').html());
$('#replies').html(temp(data));
$('#pagination').html(getPagination(data));
}
})
}
$("#pagination").on('click', 'a', function(e) {
e.preventDefault();
page = $(this).attr("href");
getList();
})
</script>
- 임의의 댓글 총 갯수가 아닌 실제 총 갯수를 구해보겠다.
/ex09/src/main/resources/mapper/ReplyMapper.xml
<select resultType="int" id="totalCount">
select count(*) from tbl_reply
where bno=#{bno}
</select>
</mapper>
/ex09/src/main/java/com/example/mapper/ReplyDAO.java
public int totalCount(int bno);
}
/ex09/src/main/java/com/example/mapper/ReplyDAOImpl.java
@Override
public int totalCount(int bno) {
return session.selectOne(namespace+".totalCount",bno);
}
}
/ex09/src/main/java/com/example/controller/ReplyController.java
@RequestMapping("/reply.json")
public HashMap<String, Object> list(int bno, Criteria cri){
HashMap<String, Object> map = new HashMap<String, Object>();
cri.setPerPageNum(5);
map.put("list", rdao.list(bno, cri));
// 페이지 목록
PageMaker pm = new PageMaker();
pm.setCri(cri);
pm.setTotalCount(rdao.totalCount(bno)); <<<<<<<<<<<<<<<<<<<<<<<
map.put("cri", cri);
map.put("pm", pm);
return map;
}
- 로그인한 유저만 글, 댓글 작성 및 본인이 작성한 글, 댓글을 삭제할 수 있도록 하겠다.
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
<hr />
<h2>[댓글 목록]</h2>
<div id="insert">
<textarea id="txtReply" cols="120" rows="5"></textarea>
<button id="btnInsert">댓글등록</button>
</div>
<hr />
...
...
<script>
var page = 1;
var bno = "${vo.bno}";
getList();
$('#btnInsert').on("click",function(){
var reply=$("#txtReply").val();
if(reply==""){
alert("내용을 입력하세요.");
$("#txtReply").focus();
return;
}
if(!confirm("댓글을 등록하시겠습니까?"))return;
})
...
- 댓글 입력을 위한 mapper id insert
/ex09/src/main/resources/mapper/ReplyMapper.xml
...
<insert id="insert">
insert into tbl_reply(bno,reply,replyer)
values(#{bno},#{reply},#{replyer});
</insert>
</mapper>
/ex09/src/main/java/com/example/mapper/ReplyDAO.java
public void insert(ReplyVO vo);
}
/ex09/src/main/java/com/example/mapper/ReplyDAOImpl.java
@Override
public void insert(ReplyVO vo) {
session.insert(namespace+".insert",vo);
}
}
/ex09/src/main/java/com/example/controller/ReplyController.java
...
@RestController
public class ReplyController {
@Autowired
ReplyDAO rdao;
// reply insert
@RequestMapping(value="/reply/insert",method=RequestMethod.POST)
public void insert(ReplyVO vo){
rdao.insert(vo);
}
...
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
<script>
var page = 1;
var bno = "${vo.bno}";
getList();
$('#btnInsert').on("click", function() {
var reply = $("#txtReply").val();
if (reply == "") {
alert("내용을 입력하세요.");
$("#txtReply").focus();
return;
}
if (!confirm("댓글을 등록하시겠습니까?"))
return;
$.ajax({
type : 'post',
url : '/reply/insert',
data : {
bno : bno,
replyer : "user02",
reply : reply
},
success:function(){
alert("등록되었습니다.");
$("#txtReply").val("");
getList();
}
})
})
...
- 글쓰기(board insert) 하겠다.
/ex09/src/main/java/com/example/controller/BoardController.java
@Controller
public class BoardController {
@Autowired
BoardDAO bdao;
// insert page move
@RequestMapping("/insert")
public String insert(Model model){
model.addAttribute("pageName","insert.jsp");
return "home";
}
/ex09/src/main/webapp/WEB-INF/views/insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[글쓰기]</h1>
<style>
input[type=text]{
width:100%;
margin-bottom: 10px;
}
textarea{
width:100%;
}
#btn{
margin: 10px;
}
#btn input{
background: rgb(57, 109, 192);
padding: 10px 5px 10px 5px;
color: white;
font-size: 25px;
}
</style>
<form action="insert" name="frm" method="post">
<input type="text" name="title"/>
<textarea name="content" cols="80" rows="10"></textarea>
<div id="btn">
<input type="submit" value="등록"/>
<input type="reset" value="취소"/>
</div>
</form>
/ex09/src/main/java/com/example/controller/BoardController.java
...
public class BoardController {
@Autowired
BoardDAO bdao;
// 게시글 입력
@RequestMapping(value="/insert",method=RequestMethod.POST)
public String insertPost(BoardVO vo){
vo.setWriter("user03");
bdao.insert(vo);
return "redirect:/";
}
...
- 특정 유저가 댓글을 삭제할 수 있도록 하겠다.
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
<script id="temp" type="text/x-handlebars-template">
{{#each list}}
<div class="box">
<div class="replyer">
<span>[{{rno}}]</span>
<span>{{replyer}}</span>
</div>
<div class="reply">
<span>{{reply}}</span>
</div>
<div class="replydate">
<span>{{replydate}}</span>
<a href="{{rno}}">삭제</a> <<<<<<<
</div>
</div>
{{/each}}
</script>
...
...
$("#replies").on('click','.box a',function(e){
e.preventDefault();
var rno = $(this).attr("href");
alert(rno);
})
...
- 삭제 mapper 를 작성하겠다.
/ex09/src/main/resources/mapper/ReplyMapper.xml
<delete id="delete">
delete from tbl_reply
where rno=#{rno}
</delete>
</mapper>
/ex09/src/main/java/com/example/mapper/ReplyDAO.java
public void delete(int rno);
}
/ex09/src/main/java/com/example/mapper/ReplyDAOImpl.java
@Override
public void delete(int rno) {
session.delete(namespace+".delete", rno);
}
}
/ex09/src/main/java/com/example/controller/ReplyController.java
...
@Autowired
ReplyDAO rdao;
// reply delete
@RequestMapping(value="/reply/delete",method=RequestMethod.POST)
public void delete(int rno){
rdao.delete(rno);
}
...
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
<script>
var page = 1;
var bno = "${vo.bno}";
getList();
$("#replies").on('click','.box a',function(e){
e.preventDefault();
var rno = $(this).attr("href");
if(!confirm("댓글을 삭제할까요?")) return;
$.ajax({
type:'post',
url:'/reply/delete',
data:{rno:rno},
success:function(){
alert("삭제되었습니다.");
getList();
}
})
})
...
- 로그인 페이지를 만들겠다.
/ex09/src/main/webapp/WEB-INF/views/home.jsp
...
<div id="menu">
<a href="/insert" title="글쓰기">글쓰기</a>
<a href="/login" title="로그인" style="float: right">로그인</a>
</div>
...
- 그 전에 테이블을 확인하겠다.
- go to mysql
- 회원관리를 위한 controller를 만들겠다.
/ex09/src/main/java/com/example/controller/UserController.java
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/login")
public String login(Model model){
model.addAttribute("pageName","login.jsp");
return "home";
}
}
/ex09/src/main/webapp/WEB-INF/views/login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>[로그인]</h1>
<style>
.loginBox{
width:300px;
margin: 0px auto;
padding: 10px;
}
input[type=text], input[type=password]{
width: 100%;
margin-bottom: 10px;
font-size: 15px;
}
input[type=submit]{
padding: 10px 20px 10px 20px;
background: rgb(57, 109, 192);
color: white;
}
</style>
<div class="loginBox">
<form action="post" name="frm">
<input type="text" name="uid" placeholder="ID"/>
<input type="password" name="upass" placeholder="PW" />
<input type="submit" value="LOGIN" />
</form>
</div>
- 회원관리를 위한 mapper를 생성하겠다.
/ex09/src/main/resources/mapper/UserMapper.xml
<?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="com.example.mapper.UserMapper">
<select id="login" resultType="com.example.domain.UserVO">
select * from tbl_user where uid=#{uid}
</select>
</mapper>
/ex09/src/main/java/com/example/domain/UserVO.java
package com.example.domain;
public class UserVO {
private String uid;
private String upass;
private String uname;
... getter, setter, tostring
/ex09/src/main/java/com/example/mapper/UserDAO.java
package com.example.mapper;
import com.example.domain.UserVO;
public interface UserDAO {
public UserVO login(String uid);
}
/ex09/src/main/java/com/example/mapper/UserDAOImpl.java
package com.example.mapper;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.domain.UserVO;
@Repository
public class UserDAOImpl implements UserDAO {
@Autowired
SqlSession session;
String namespace="com.example.mapper.UserMapper";
@Override
public UserVO login(String uid) {
return session.selectOne(namespace+".login",uid);
}
}
/ex09/src/main/java/com/example/controller/UserController.java
package com.example.controller;
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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.domain.UserVO;
import com.example.mapper.UserDAO;
@Controller
public class UserController {
@Autowired
UserDAO udao;
// user login check
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public int loginPost(String uid, String upass) {
int result = 0;
UserVO vo = udao.login(uid);
if (vo != null) {
if (upass.equals(vo.getUpass())) {
result = 1;
} else {
result = 2;
}
}
return result;
}
// user page con
@RequestMapping("/login")
public String login(Model model) {
model.addAttribute("pageName", "login.jsp");
return "home";
}
}
- login page 에서 submit시 uid, upass확인을 하겠다.
/ex09/src/main/webapp/WEB-INF/views/login.jsp
<script>
$(frm).on('submit',function(e){
e.preventDefault();
var uid=$(frm.uid).val();
var upass=$(frm.upass).val();
if(uid==""||upass==""){
alert("아이디와 비밀번호를 입력하세요.");
return;
}
if(!confirm("로그인 하시겠습니까?")) return;
$.ajax({
type:'post',
url:'/login',
data:{
uid:uid,
upass:upass
},
success:function(data){
alert(data);
}
})
})
</script>
- 아래 스크립 추가
...
success:function(data){
if(data==0){
alert("존재하지 않는 아이디입니다.")
}else if(data==2){
alert("비밀번호를 확인하세요.")
}else{
alert("로그인 합니다.")
location.href="/";
}
}
...
- 로그인한 uid를 session에 저장하겠다.
/ex09/src/main/java/com/example/controller/UserController.java
...
// user login check
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public int loginPost(String uid, String upass, HttpSession session) {
int result = 0;
UserVO vo = udao.login(uid);
if (vo != null) {
if (upass.equals(vo.getUpass())) {
session.setAttribute("uid", uid);
result = 1;
} else {
result = 2;
}
}
return result;
}
...
- 저장한 session을 이용해 home에서 login, logout의 여부를 확인하겠다.
/ex09/src/main/webapp/WEB-INF/views/home.jsp
...
<div id="menu">
<a href="/insert" title="글쓰기">글쓰기</a>
<c:if test="${uid==null}">
<a href="/login" title="로그인" style="float: right">로그인</a>
</c:if>
<c:if test="${uid!=null}">
<a href="/login" title="로그아웃" style="float: right">로그아웃</a>
<span>${uid}님</span>
</c:if>
</div>
...
- 로그아웃
/ex09/src/main/java/com/example/controller/UserController.java
...
// user logout
@RequestMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/";
}
...
/ex09/src/main/webapp/WEB-INF/views/home.jsp
...
<div id="menu">
<a href="/insert" title="글쓰기">글쓰기</a>
<c:if test="${uid==null}">
<a href="/login" title="로그인" style="float: right">로그인</a>
</c:if>
<c:if test="${uid!=null}">
<a href="/logout" title="로그아웃" style="float: right">로그아웃</a>
<span>${uid}님</span>
</c:if>
</div>
...
- 이제 글작성, 댓글작성 시 로그인한 uid를 이용해 사용할 수 있도록 하겠다.
1. 글작성
/ex09/src/main/java/com/example/controller/BoardController.java
// 게시글 입력
@RequestMapping(value="/insert",method=RequestMethod.POST)
public String insertPost(BoardVO vo){
bdao.insert(vo);
return "redirect:/";
}
/ex09/src/main/webapp/WEB-INF/views/insert.jsp
<form action="insert" name="frm" method="post">
<input type="text" name="writer" value="${uid}"/>
<input type="text" name="title" placeholder="제목"/>
<textarea name="content" cols="80" rows="10" placeholder="내용"></textarea>
<div id="btn">
<input type="submit" value="등록"/>
<input type="reset" value="취소"/>
</div>
</form>
2. 댓글작성
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
var uid = "${uid}"; <<<<<<<<<<<<<<<<<<<<<<<<<
$('#btnInsert').on("click", function() {
var reply = $("#txtReply").val();
if (reply == "") {
alert("내용을 입력하세요.");
$("#txtReply").focus();
return;
}
if (!confirm("댓글을 등록하시겠습니까?"))
return;
$.ajax({
type : 'post',
url : '/reply/insert',
data : {
bno : bno,
replyer : uid, <<<<<<<<<<<<<<<<<<<<<
reply : reply
},
success:function(){
alert("등록되었습니다.");
$("#txtReply").val("");
getList();
}
})
})
...
3. registerhelper를 이용해 로그인한 유저가 본인이 작성한 댓글만 삭제가 가능하도록 하겠다.
/ex09/src/main/webapp/WEB-INF/views/read.jsp
...
<script id="temp" type="text/x-handlebars-template">
{{#each list}}
<div class="box">
<div class="replyer">
<span>[{{rno}}]</span>
<span>{{replyer}}</span>
</div>
<div class="reply">
<span>{{reply}}</span>
</div>
<div class="replydate">
<span>{{replydate}}</span>
<a href="{{rno}}" style="display:{{printDel replyer}}">삭제</a>
</div>
</div>
{{/each}}
</script>
<script>
Handlebars.registerHelper("printDel", function(replyer) {
if (replyer != "${uid}") {
return "none";
}
})
</script>
...
- 댓글 작성을 하려면 로그인해야 하도록 하겠다. 이 기능은 interceptor를 이용하겠다.
- 인터셉터 패키지를 만든다.
/ex09/src/main/java/com/example/interceptor
/ex09/src/main/java/com/example/interceptor/LoginInterceptor.java
package com.example.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 로그인 여부 check
if(request.getSession().getAttribute("uid")==null){
response.sendRedirect("/login");
}
return super.preHandle(request, response, handler);
}
}
/ex09/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
....
<!-- interceptor 등록 -->
<beans:bean id="LoginInterceptor" class="com.example.interceptor.LoginInterceptor"/>
<interceptors>
<interceptor>
<mapping path="/insert"/>
<mapping path="/reply/insert"/>
<beans:ref bean="LoginInterceptor"></beans:ref>
</interceptor>
</interceptors>
</beans:beans>
- 글쓰기 page에 들어가서 login후 메인이 아닌 연속적으로 글쓰기 page에 들어갈 수 있도록 하겠다.
/ex09/src/main/java/com/example/interceptor/LoginInterceptor.java
package com.example.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 로그인 여부 check
if(request.getSession().getAttribute("uid")==null){
// /insert /read 까지만 가지고 오는 path
String path = request.getServletPath();
// path 이후의 경로 query로 설정
String query=request.getQueryString();
if(query==null||query.equals("")){
query="";
}else{
query="?"+query;
}
request.getSession().setAttribute("destination", path+query);
response.sendRedirect("/login");
}
return super.preHandle(request, response, handler);
}
}
/ex09/src/main/webapp/WEB-INF/views/login.jsp
...
success:function(data){
if(data==0){
alert("존재하지 않는 아이디입니다.")
}else if(data==2){
alert("비밀번호를 확인하세요.")
}else{
alert("로그인 합니다.")
var destination="${destination}";
location.href=destination;
}
}
...
- 댓글란 클릭시 로그인은 나중에 하겠다.
- 로그인시 로그인 상태 유지 여부를 물어보는 checkbox를 만들고 쿠키에 담아서 로그인 유지를 해보겠다.
/ex09/src/main/webapp/WEB-INF/views/login.jsp
...
<div class="loginBox">
<form action="post" name="frm">
<input type="text" name="uid" placeholder="ID"/>
<input type="password" name="upass" placeholder="PW" />
<div>
<input type="checkbox" name="chkLogin"/> 로그인 상태 유지
</div>
<input type="submit" value="LOGIN" />
</form>
</div>
<script>
$(frm).on('submit',function(e){
e.preventDefault();
var uid=$(frm.uid).val();
var upass=$(frm.upass).val();
var isLogin=$(frm.chkLogin).is(":checked")?true:false;
alert(isLogin);
if(uid==""||upass==""){
alert("아이디와 비밀번호를 입력하세요.");
return;
}
if(!confirm("로그인 하시겠습니까?")) return;
$.ajax({
type:'post',
url:'/login',
data:{
uid:uid,
upass:upass,
isLogin:isLogin
},
success:function(data){
if(data==0){
alert("존재하지 않는 아이디입니다.")
}else if(data==2){
alert("비밀번호를 확인하세요.")
}else{
alert("로그인 합니다.")
var destination="${destination}";
location.href=destination;
}
}
})
})
</script>
...
/ex09/src/main/java/com/example/controller/UserController.java
...
// user login check
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public int loginPost(String uid, String upass, HttpSession session, boolean isLogin, HttpServletResponse response) throws Exception {
int result = 0;
UserVO vo = udao.login(uid);
if (vo != null) {
if (upass.equals(vo.getUpass())) {
session.setAttribute("uid", uid);
if(isLogin){
Cookie cookie = new Cookie("uid", uid);
cookie.setPath("/");
cookie.setMaxAge(60 * 60 * 24 * 7);
response.addCookie(cookie);
}
result = 1;
} else {
result = 2;
}
}
return result;
}
...
- home에서 web의 cookie 유무 확인 후 로그인 유지
/ex09/src/main/java/com/example/controller/HomeController.java
package com.example.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.util.WebUtils;
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model, HttpServletRequest request) {
Cookie cookie = WebUtils.getCookie(request, "uid");
if(cookie!=null){
request.getSession().setAttribute("uid", cookie.getValue());
}
model.addAttribute("pageName", "list.jsp");
return "home";
}
}
- 로그아웃시 쿠키 초기화
/ex09/src/main/java/com/example/controller/UserController.java
// user logout
@RequestMapping("/logout")
public String logout(HttpSession session, HttpServletResponse response, HttpServletRequest request) {
session.invalidate();
Cookie cookie =WebUtils.getCookie(request, "uid");
if(cookie!=null){
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
return "redirect:/";
}
'ICIA 수업일지' 카테고리의 다른 글
2021.10.19 수업일지(Spring Framework, Interceptor, Google API) (0) | 2021.10.19 |
---|---|
2021.10.18 수업일지(Spring Framework, Interceptor) (0) | 2021.10.18 |
2021.10.14 수업일지(Spring Framework, Fileupload) (0) | 2021.10.14 |
2021.10.13 수업일지(Spring Framework, fileupload) (0) | 2021.10.13 |
2021.10.12 수업일지(Spring 연습, fileupload 방법 (0) | 2021.10.12 |