Programming/스프링(spring) - Enterprise

스프링(spring)/ +더하기 4(1:1게시판 시스템)

esoog Polaris 2023. 8. 7. 14:33

1. 1:1채팅 아이디어를 변용해서 1:1 게시판 시스템을 만들어보고자 한다.

게시물 리스트를 받아오는데, 해당 주제에서 글을 쓴 본인 아이디로 접속 시에는

1:1게시판 버튼이 안보이게 일단 설정, jsp파일에 링크를 연결시켜준다.

 

<c:if test="${list.nick!=member.id}">
    <a href="/board/debate?idx=${list.idx}&sender=${member.id}">대결</a>
</c:if>

*debate라는 jsp에 ?쿼리로,

해당 데이터를 넘겨줘서 get페이지로 사용하겠다.

 

 

 

 

2. 그 먼저 1:1게시판의 특징을 데이터 모델링 해서 Controller 단에서 url과 데이터 처리 로직을 매핑시켜 준다.

주제 관련 게시물A의 1:1 논쟁 게시판 클릭 > 게시물A의 내용과 논쟁 요청자(보낸이) user가 작성한 게시글 데이터 내용 

 

// 1:1 논쟁 게시판 시스템
	@RequestMapping(value = "/debate", method = RequestMethod.GET)
	public void getDebate(@RequestParam("idx") int idx, @RequestParam("sender") String sender, Model model)
			throws Exception {
		// 그러니까 기존 주제 최초 발언 게시글 데이터
		List<BoardVO> originList = null;
		originList = service.originList(idx);
		model.addAttribute("originList", originList);

		List<BoardVO> debate = null;
		debate = service.debate(idx, sender);
		model.addAttribute("debate", debate);
	}

	@RequestMapping(value = "/debate", method = RequestMethod.POST)
	public String postDebate(BoardVO vo) throws Exception {
		service.debateWrite(vo);
		service.linked(vo);
		return "redirect:/board/debate?idx=" + vo.getIdx() + "&sender=" + vo.getSender();
	}

* idx는 게시글 고유 번호라서 게시글 데이터 찾는 데 사용.(originList 으로 설정했다. 최초 논쟁 게시물 출발 데이터)

sender는 1:1 요청 보낸이를 참조해서 1:1 논쟁 게시판 데이터 베이스를 따로 형성.(이후 보낸이와 연결된 데이터 관리)

*POST의 debateWrite와 linked 함수를 사용해서 데이터 매칭.

 

 

 

 

3. 데이터 모델링 작업 처리를 위해 매퍼 파일 먼저.

수정 및 추가 해준다. debate 논쟁과 linked 매칭의 새로운 데이터 테이블 생성 후, 로직을 만들어 준다. 조금 복잡해 진다...

(이전에, 새로운 데이터 테이블 생성 후, 데이터 컬럼 객체들의 게터와 세터 작업이 먼저다.)

 

<!-- 고유 번호의 게시글 총 리스트 -->
	<select id="originList" resultType="com.project.model.BoardVO">
		select
		*
		from board
		WHERE
		idx=#{idx}
	</select>
    
    <!-- getDebate 1:1논쟁 게시판 데이터 따로 분리 -->
	<select id="getDebate" resultType="com.project.model.BoardVO">
		SELECT * FROM
		argument
		WHERE
		sender=#{sender} AND idx=#{idx}
		ORDER BY date DESC
	</select>
    
    // 논쟁 매치 작성
    <insert id="debateWrite"
		parameterType="com.project.model.BoardVO">
		insert into
		argument(idx,
		nick, text, receiver, sender)
		values(#{idx}, #{nick}, #{text},
		#{receiver}, #{sender} )
	</insert>
    
    <!-- 연결된 매치 별도 테이블 생성. 레코드 인서트 -->
	<insert id="linked" parameterType="com.project.model.BoardVO">
		INSERT INTO counter (idx,
		receiver, sender, channel)
		VALUES (#{idx}, #{receiver}, #{sender},
		CONCAT(#{idx}, #{sender},
		#{receiver}))
	</insert>
    
    <!-- 레코드 셀렉터 -->
    <select id="linkedSelect"
		parameterType="com.project.model.BoardVO"
		resultType="java.lang.Integer">
		SELECT COUNT(*) FROM
		counter
		WHERE
		channel=#{channel}
	</select>

 

 

 

 

 

4. 그럼 이제 DAO와 Service에 자연스럽게 아래코드 추가

 

public List<BoardVO> originList(int idx) throws Exception;
public List<BoardVO> debate(int idx, String sender) throws Exception;

public void debateWrite(BoardVO vo) throws Exception;
public boolean linked(BoardVO vo);

 

 

DAOImple파일에는

 

	public List<BoardVO> originList(int idx) throws Exception {
		HashMap<String, Object> data = new HashMap<>();
		data.put("idx", idx);
		return sql.selectList(namespace + ".originList", data);
	}
    
    @Override
	public List<BoardVO> debate(int idx, String sender) throws Exception {
		HashMap<String, Object> data = new HashMap<>();
		data.put("sender", sender);
		data.put("idx", idx);
		return sql.selectList(namespace + ".getDebate", data);
	}
    
    @Override
	public boolean linked(BoardVO vo) {
		String channel = vo.getIdx()+vo.getSender()+vo.getReceiver();
		int count = sql.selectOne(namespace + ".linkedSelect", channel);
		if(count>0) {	
			return false;
		}else {
		sql.insert(namespace + ".linked", vo);
		return true;}
	}
    
    // 1:1 논쟁 작성
	@Override
	public void debateWrite(BoardVO vo) throws Exception {
		sql.insert(namespace + ".debateWrite", vo);
	}

*linked 메서드가 조금 복잡하다. 중복을 걸러 사용하기위함.

 

 

ServiceImple에는

 

@Override
	public List<BoardVO> originList(int idx) throws Exception {
		return dao.originList(idx);
	}
    
@Override
	public List<BoardVO> debate(int idx, String sender) throws Exception {
		return dao.debate(idx, sender);
	}
    
 @Override
	public void debateWrite(BoardVO vo) throws Exception {
		dao.debateWrite(vo);
	}
    
    
 @Override
	public boolean linked(BoardVO vo) {
		return dao.linked(vo);
	}

 

 

 

 

 

5. 그럼 이제 마지막으로 JSP파일에서 모델을 사용해서 뷰를 완성

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
<link rel="stylesheet" href="../../resources/debate.css">
<!-- 합쳐지고 최소화된 최신 CSS -->
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- 부가적인 테마 -->
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">

<script
	src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<title>작성</title>
</head>
<body>

	<c:if test="${member == null}">
		<script>
			alert("로그인을 해야 작성이 가능합니다.");
			window.location.href = '/'; // 여기서 '/페이지'는 이동하고자 하는 페이지의 URL입니다.
		</script>
	</c:if>

	<div class="contentBox">
		<c:forEach items="${debate}" var="debate">
			<c:if test="${debate.nick==member.id}">
				<div class="originBox">
					<div>
						<fmt:formatDate value="${debate.date}"
							pattern="yyyy-MM-dd HH:mm:ss" />
					</div>
					<div>${debate.nick}</div>
					<div>${debate.text}</div>
					<div>${debate.hcount}</div>
				</div>
			</c:if>
			<c:if test="${debate.nick!=member.id}">
				<div class="newBox">
					<div>
						<fmt:formatDate value="${debate.date}"
							pattern="yyyy-MM-dd HH:mm:ss" />
					</div>
					<div>${debate.nick}</div>
					<div>${debate.text}</div>
					<div>${debate.hcount}</div>
				</div>
			</c:if>
		</c:forEach>
		<c:forEach items="${originList}" var="originList">
			<div class="userBox">
			<h1>최초 논점</h1>
				<div>
					<fmt:formatDate value="${originList.date}"
						pattern="yyyy-MM-dd HH:mm:ss" />
				</div>
				<div>${originList.nick}</div>
				<div>${originList.text}</div>
				<div>${originList.hcount}</div>
			</div>
			<c:set var="originListNick" value="${originList.nick}"></c:set>
			<c:set var="originListIdx" value="${originList.idx}"></c:set>
		</c:forEach>

	</div>

	<div class="postBox">
		<c:if test="${not empty originListIdx}">
			<form method="post">
				<input type="hidden" name="receiver" value="${originListNick}">
				<input type="hidden" name="nick" value="${member.id}"> <input
					type="hidden" name="idx" value="${originListIdx}">
				<div class="writer">
					<label>작성자</label> ${member.id} <br />
				</div>
				<div class="mb-3 content">
					<label>내용</label>
					<textarea class="form-control" id="tArea" rows="3" name="text"></textarea>
				</div>
				<button class="btn btn-info" type="submit" id="submit">작성</button>
			</form>
		</c:if>
	</div>

	<script type="text/javascript">
		// 최종 점검 로직
		$("#submit").on("click", function() {
			var email = $("#tArea").val().trim();
			if (email.length < 10) {
				alert("10자 이상의 내용을 입력해 주세요");
				$("#tArea").focus();
				return false;
			}
		});
	</script>
</body>
</html>

 

 

 

 

 

6. 1:1논쟁 게시판 페이지는 만들었으니, 이제는 최초 게시글 작성 유저에게 별도로 논쟁 목록을 표시해주도록 하면 된다.

로직상, user에 관련된 정보와 매칭을 시켜야 하므로 USER관련 작업을 한다. 

*마이페이지에서 하나의 페이지로 걸어주는게 좋을 듯해서 아래처럼 jsp파일을 추가.

 

<div class="nest">
	<a href="/account/nest?receiver=${member.id}">
        <button class="btn btn-info" id="nest">둥지</button>
    </a>
</div>

*nest는 '둥지'라는 의미로 1:1매칭을 모아놓은 단어로 사용했다.

*요청을 받은 receiver 데이터를 사용한다.

 

 

 

 

 

7. 그럼 Controller단,

 

// 둥지 목록
	@RequestMapping(value = "/account/nest", method = RequestMethod.GET)
	public void getNest(@RequestParam String receiver, Model model) throws Exception {
		List<BoardVO> nest = null;
		nest = userService.nest(receiver);
		model.addAttribute("nest", nest);
	}

 

 

 

 

 

8. 간단하게 DAO와 Service단에 아래 코드 추가

 

	public List<BoardVO> nest(String receiver) throws Exception;

 

 

DAOImpl파일에는 아래코드 추가

 

// 둥지 
    @Override
	public List<BoardVO> nest(String receiver) throws Exception {
		return sqlSession.selectList(namespace + ".nest", receiver);
	}

 

 

ServiceImpl파일에는 아래코드를

 

// 둥지 로직
	@Override
	public List<BoardVO> nest(String receiver) throws Exception {
		return userDAO.nest(receiver);

	}

 

 

 

 

 

9. 이제 매퍼로 데이터 쿼리문을 작성해준다. 본인이 쓴 게시물에 receiver 또는 sender에 자신 닉네임이 있는 것들을 가져온다면~

논쟁 테이블에서 

<!-- 둥지 셀렉트 -->
	<select id="nest" resultType="com.project.model.BoardVO">
		select idx, sender, receiver, COUNT(sender)
		AS countSender, COUNT(receiver) AS countReceiver
		from
		argument
		Where receiver=#{receiver} OR sender=#{receiver}
		GROUP BY receiver, sender, idx;
	</select>

* GROUP BY로 묶으면서 집게함수를 사용(전체 컬럼 선택 불가)

(데이터 쿼리문에서 셀렉트 객체는 VO파일에 생성되어 있어야 한다!. countSender와 countReceiver게터와 세터 준비)

 

 

 

 

 

10. 마지막으로 이제 JSP파일에서 모델을 사용해서 뷰를 완성시키기~

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>

<link rel="stylesheet" href="../../resources/nest.css">
<!-- 합쳐지고 최소화된 최신 CSS -->
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- 부가적인 테마 -->
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">

<script
	src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<title>Insert title here</title>
</head>
<body>

	<div class="received">
		<h1>요청 받음</h1>
		<c:forEach items="${nest}" var="nest">
			<c:if test="${nest.receiver==member.id}">
				<div class="oposite"
					onclick="location.href ='/board/debate?idx=${nest.idx}&sender=${nest.sender}';">
					<p>논객: ${nest.sender}</p>
					<p>대화 목록: ${nest.countSender}</p>
				</div>
			</c:if>
		</c:forEach>
	</div>

	<div class="sent">
		<h1>신청함</h1>
		<c:forEach items="${nest}" var="nest">
			<c:if test="${nest.sender==member.id}">
				<div class="oposite"
					onclick="location.href ='/board/debate?idx=${nest.idx}&sender=${nest.sender}';">
					<p>논객: ${nest.receiver}</p>
					<p>대화 목록: ${nest.countReceiver}</p>
				</div>
			</c:if>
		</c:forEach>
	</div>
</body>
</html>

 

반응형