본문 바로가기
교육/Spring

Spring 개발자 수업 101일차 - 코드 게시판 만들기(상세 보기, 댓글 작성)

by yhyuk 2021. 8. 19.
728x90
반응형

코드 게시판 만들기(상세 보기, 댓글 작성)

[ 구현 목표 ]

- 글 리스트 목록에서 항목을 선택하여 클릭하면 상세 페이지로 이동한다.

- 상세페이지에서 코드를 드래그 형식으로 선택하여 댓글형식으로 코드 설명을 작성할 수 있다.

오른쪽: 상세페이지 / 왼쪽: 댓글 형식인 라인 별 코드 설명

 

[ 설정 ]

스프링을 이용한 코드 게시판 만들기
    - Spring MVC Project + MyBatis + Log4j + AOP + Tiles
    - 게시판(+소스 코드 첨부) 

1. pom.xml
    - java, spring 버전 변경(1.11, 4.3.8)
    - jar(lombok, jdbc, mybatis, log4j, tiles)

2. web.xml
    - 확장자 설정(*.action)
    - POST 인코딩 필터(UTF-8)

3. root-context.xml
    - myBatis 설정
        > mapper 설정: com.test.code.mapper > code.xml
        > xml 설정: WEB-INF > myBatis.xml 
    - log4j 설정
        > <bean>태그 추가
        > log4j.xml 수정

4. servlet-context.xml
    - tiles 설정(tiles.xml)
    - AOP 설정(aop태그 추가)

5. 파일 생성
    - Java파일(com.test.code)
        > CodeController.java       : 컨트롤러
        > CodeDAO.java              : DAO
        > CodeDTO.java              : 게시판
        > CodeLanguageDTO.java      : 카테고리
        > CodeLanguageLinkDTO.java  : 게시판 <-> 카테고리
        > CodeCommentDTO.java       : 댓글
    - jsp파일(views)
        > add.jsp    : 글 쓰기
        > list.jsp   : 글 리스트
        > view.jsp   : 글 상세
        > index.jsp  : 홈 화면

6. tiles 적용
    - views > layout > template.jsp

 

[ CodeController.java ]

- 상세페이지(view), 코드 설명(addcomment) 구현하기

@Controller
public class CodeController {
	
	@Autowired
	private CodeDAO dao;
    
	@RequestMapping(value = "/view.action", method = { RequestMethod.GET })
	public String view (HttpServletRequest req, 
						HttpServletResponse resp, 
						HttpSession session,
						String seq) {
		
		//1. 데이터 가져오기(seq)
		//2. DB 작업 > select
		//3. DTO 전달 + JSP(tiles definition) 호출
		
		CodeDTO dto = dao.get(seq);
		
		// 글내용 개행문자 처리
		dto.setContent(dto.getContent().replace("\n", "<br>"));
		
		dto.setCode(dto.getCode().replace("&", "&amp;"));
		
		// 코드 탭문자 처리
		dto.setCode(dto.getCode().replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"));
		
		// 코드 마크업 문자 처리
		//	- 이 작업을 안한다면.. 위에서 탭문자 처리한 &nbsp 및 코드내용을 
		//    HTML이 알아서 해석해버림
		dto.setCode(dto.getCode().replace("<", "&lt;"));
		dto.setCode(dto.getCode().replace(">", "&gt;"));
		
		// 언어 가져오기
		List<CodeLanguageDTO> llist = dao.llist(seq);
		
		// 7개의 언어 DTO중에서 cseq가 not null인 항목만 남기고 나머지는 삭제
		// 방법1
		/*
		List<CodeLanguageDTO> llist2 = new ArrayList<CodeLanguageDTO>();
		
		for (CodeLanguageDTO d : llist) {
			if (d.getCseq() != null) {
				llist2.add(d);
			}
		}
		*/
		
		// 방법2. 스트림 사용
		llist = llist.stream()
					 .filter(ldto -> ldto.getCseq() != null)
					 .collect(Collectors.toList());
		
		// 댓글 목록 가져오기
		List<CodeCommentDTO> clist = dao.clist(seq);
		
		// 댓글 내용 개행 문자 처리
		for (CodeCommentDTO cdto : clist) {
			cdto.setContent(cdto.getContent().replace("\n", "<br>"));
		}		
		
		req.setAttribute("dto", dto);
		req.setAttribute("llist", llist);
		req.setAttribute("clist", clist);

		return "view";
	}
	
	@RequestMapping(value = "/addcomment.action", method = { RequestMethod.POST })
	public void addcomment (HttpServletRequest req, 
							HttpServletResponse resp, 
							HttpSession session,
							CodeCommentDTO dto) {
		
		// 1. 데이터 가져오기
		
		// 2. DB 작업
		dao.addComment(dto);
		
		// 3. view.action으로 돌아가기
		try {
			resp.sendRedirect("/code/view.action?seq=" + dto.getCseq());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}



}

 

[ CodeDAO.java ]

- 반환값이 1개일 때 selectOne 반환

- 반환값이 N개일 때 selectList 반환

@Repository
public class CodeDAO {

	@Autowired
	private SqlSessionTemplate template;

	public CodeDTO get(String seq) {
		return template.selectOne("code.get", seq);
	}

	public void addComment(CodeCommentDTO dto) {
		template.insert("code.addComment", dto);
	}

	public List<CodeCommentDTO> clist(String seq) {
		return template.selectList("code.clist", seq);
	}

}

 

[ mapper ]

- com.test.code.mapper > code.xml

- 쿼리 작성

<mapper namespace="code">

	<!-- 글보기 -->
	<select id="get" parameterType="String" resultType="dto">
		select * from tblCode where seq = #{seq}
	</select>
	
	<!-- 댓글 쓰기 -->
	<insert id="addComment" parameterType="cdto">
		insert into tblCodeComment (seq, content, beginline, endline, regdate, cseq)
			values (seqCodeComment.nextVal, #{content}, #{beginline}, #{endline}, default, #{cseq})
	</insert>
	
	<!-- 댓글 목록 -->
	<select id="clist" parameterType="String" resultType="cdto">
		select * from tblCodeComment where cseq = #{seq} order by beginline asc
	</select>

</mapper>

 

[ view.jsp ]

- 글 상세 페이지

- 코드 제목, 내용, 설명을 확인 할 수 있다.

- 해당 코드 라인을 선택하고 드래그하면 댓글을 작성할 수 있다. (JavaScript)

<div class="panel panel-default">
    <div class="panel-heading">${dto.subject}</div>
    <div class="panel-body">${dto.content}</div>
    <div class="regdate">${dto.regdate}</div>
</div>

<div class="code">
	
	<c:forEach items="${dto.code.lines().toArray()}" var="line" varStatus="status">
		<div class="line"><span class="line-number"><fmt:formatNumber value="${status.count}" minIntegerDigits="3" />: </span>${line}</div>
	</c:forEach>
	
   	<div>
   		<!-- 컨트롤러에서 미리 조건문을 해서 jsp에 넘기기 -->
   		<c:forEach items="${llist}" var="ldto" varStatus="status">
   			<i class="${ldto.langclass} category" 
   			   style="color: ${ldto.color}; 
   			   		  right: ${((llist.size() - 1) * 55 + 20) - (status.index * 55 + 10)}px;"></i>    			
   		</c:forEach> 
    		
	</div>

	<!-- 댓글 작성 -->
	<div class="commentForm">
      	<form method="POST" action="/code/addcomment.action">
                <textarea name="content" class="form-control content" required placeholder="1. Submit(Ctrl+Enter)
2. Cancel(ESC)"></textarea>
				<input type="hidden" name="cseq" value="${dto.seq}"> <!-- 현재 보고있는 글번호(부모글) -->
				<input type="hidden" name="beginline"> <!-- 선택한 코드 시작 라인 번호 -->
				<input type="hidden" name="endline"> <!-- 선택한 코드 끝 라인 번호 -->
		</form>
	</div>
</div>

<div class="list">
	<c:forEach items="${clist}" var="cdto">
   	<div class="listitem" data-begin="${cdto.beginline}" data-end="${cdto.endline}">
       	<span class="line-number">
       		<fmt:formatNumber value="${cdto.beginline+1}" minIntegerDigits="3" />: </span>
       ${cdto.content}
   </div>
   </c:forEach>
</div>

<div class="list selected-list"></div>

<div class="btns">
    <button type="button" class="btn btn-default" onclick="location.href='/code/list.action';">Back</button>
</div>


<script src='/code/resources/js/view.js'></script>

 

[ 구현 화면 ]

view.action


MEMO>

# 개행문자를 처리할때 Windows, Mac, Unix(Linux) 각각 다르다.
           1. Windows: \r\n
           2. Mac: \r
           3. Unix(Linux): \n

# 일반 게시판이 아닌 코드 게시판 구현으로 안에 들어가는 주 내용(content)가 코드이므로 HTML이 해석을 못하게 하려면 마크업 문자 처리를 따로 해야한다. (탭 처리 등..)

# 이전에 배웠던 스트림을 여기서 썼는데 많이 편리한거 같다.

 

728x90
반응형

댓글