본문 바로가기
ICIA 수업일지

2021.10.15 수업일지(Spring Framework, Fileupload, interceptor)

by 주성씨 2021. 10. 15.

- 어제 프로젝트에서 최신상품, 베스트상품 슬라이더로 이용할 쿼리문을 작성하겠다.

/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를 테스트해보겠다.

인기 상품 json 확인

 

신상품 json 확인

 

 

- 이제 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">&lt</button>
		&nbsp;&nbsp;
		<button id="next">&gt</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);
	}
}

 

DB 연결 확인

 

 

- 이제 컨트롤러를 생성하겠다.

/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);
	})
...

 

alert 확인

 

 

- 삭제 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();
			}
		})
	})
...

 

댓글 delete 확인

 

 

- 로그인 페이지를 만들겠다.

/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

user table 확인

 

- 회원관리를 위한 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>

 

유효성 체크 및 data return 확인

- 아래 스크립 추가

...
			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

경로 확인

 

check 확인

 

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:/";
	}

 

로그아웃시 쿠키 삭제 확인