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 ]
- 글 쓰기(add.jsp), 글 보기(list.jsp), 로그인, 로그아웃 구현하기
@Controller
public class CodeController {
@Autowired
private CodeDAO dao;
// 홈 화면
@RequestMapping(value = "/index.action", method = { RequestMethod.GET })
public String index (HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
return "index";
}
// 로그인
@RequestMapping(value = "/signin.action", method = { RequestMethod.POST })
public void signin (HttpServletRequest req,
HttpServletResponse resp,
HttpSession session,
String pw) {
// 1. 데이터 가져오기(pw)
// 2. DB 작업 > select
String id = dao.signin(pw);
// 3. 인증 티켓 발급
if (id != null) {
session.setAttribute("id", id); // 인증 티켓 발급(로그인)
}
// 4. 결과 처리
try {
resp.sendRedirect("/code/index.action");
} catch (IOException e) {
e.printStackTrace();
}
}
// 로그아웃
@RequestMapping(value = "/signout.action", method = { RequestMethod.GET })
public void signout (HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
session.removeAttribute("id"); // 인증 티켓 제거(로그아웃)
try {
resp.sendRedirect("/code/index.action");
} catch (IOException e) {
e.printStackTrace();
}
}
// 글 보기
@RequestMapping(value = "/list.action", method = { RequestMethod.GET })
public String list (HttpServletRequest req,
HttpServletResponse resp,
HttpSession session,
String lseq) {
List<CodeDTO> list = dao.list(lseq);
for (CodeDTO dto : list) {
// 게시물 1개 > 글 번호 조건 > SQL > 언어 목록
List<CodeLanguageDTO> llist = dao.llist(dto.getSeq());
dto.setLlist(llist);
}
req.setAttribute("list", list);
return "list";
}
// 글 쓰기
@RequestMapping(value = "/add.action", method = { RequestMethod.GET })
public String add (HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
List<CodeLanguageDTO> llist = dao.llistAll();
req.setAttribute("llist", llist);
return "add";
}
// 글 쓰기
@RequestMapping(value = "/addok.action", method = { RequestMethod.POST })
public void addok (HttpServletRequest req,
HttpServletResponse resp,
HttpSession session,
CodeDTO dto,
String lseq) {
// 1. 데이터 가져오기(subject, content, code, lseq)
// 2. DB 작업
// - 게시물 insert x 1
// - 언어(링크) insert x N > lseq
dao.add(dto);
// 방금 작성한 게시물 번호 가져오기
String seq = dao.getSeq();
// 히든 태그로 넘겨받은 N개의 lseq(언어번호)
String[] temp = lseq.split(",");
CodeLanguageLinkDTO lldto = new CodeLanguageLinkDTO();
lldto.setCseq(seq);
for (String llseq : temp) {
// 선택한 언어 번호(llseq) + 방금 작성한 게시물 번호(seq)
lldto.setLseq(llseq);
dao.addLink(lldto);
}
try {
resp.sendRedirect("/code/list.action");
} catch (IOException e) {
e.printStackTrace();
}
}
}
[ Code.DAO ]
- 반환값이 1개일 때 selectOne 반환
- 반환값이 N개일 때 selectList 반환
@Repository
public class CodeDAO {
@Autowired
private SqlSessionTemplate template;
// 로그인 확인 작업
public String signin(String pw) {
return template.selectOne("code.signin", pw);
}
// 전체 글 보기 작업
public List<CodeDTO> list(String lseq) {
return template.selectList("code.list", lseq);
}
// 특정 언어 글 보기 작업
public List<CodeLanguageDTO> llist(String seq) {
return template.selectList("code.llist", seq);
}
// 모든 언어 글 보기 작업
public List<CodeLanguageDTO> llistAll() {
return template.selectList("code.llistAll");
}
// 글 쓰기 작업
public void add(CodeDTO dto) {
template.insert("code.add", dto);
}
// 방금 쓴 글 seq 가져오는 작업
public String getSeq() {
return template.selectOne("code.getSeq");
}
// 방금 쓴 글과 연결된 언어 추가
public void addLink(CodeLanguageLinkDTO lldto) {
template.insert("code.addLink", lldto);
}
}
[ DTO ]
- Code, CodeComment, CodeLanguage, CodeLanguageLink
// Code.DTO
@Data
public class CodeDTO {
private String seq;
private String subject;
private String content;
private String code;
private String regdate;
private List<CodeLanguageDTO> llist; // 현재 게시물에 관련된 언어 목록
}
// CodeComment.DTO
@Data
public class CodeCommentDTO {
private String seq;
private String content;
private String beginline;
private String endline;
private String regdate;
private String cseq;
}
// CodeLanguage.DTO
@Data
public class CodeLanguageDTO {
private String seq;
private String name;
private String langicon;
private String langclass;
private String color;
private String cseq; // outer join용
}
// CodeLanguageLink.DTO
@Data
public class CodeLanguageLinkDTO {
private String seq;
private String cseq;
private String lseq;
}
[ mapper ]
- com.test.code.mapper > code.xml
- 쿼리 작성
<mapper namespace="code">
<!-- 로그인 -->
<select id="signin" parameterType="String" resultType="String">
select id from tblCodeUser where id='hong' and pw=#{pw}
</select>
<!-- 게시물 -->
<select id="list" resultType="dto" parameterType="String">
<!-- select * from tblCode order by seq desc; -->
select * from tblCode c
<!-- MyBatis의 동적 쿼리이며 String은 예외발생이 있으므로 일종의 예약어인 언더바(_)를 붙인다. -->
<if test="_parameter != null">
inner join tblCodeLanguageLink cll
on c.seq = cll.cseq
where cll.lseq = #{ lseq }
</if>
order by c.seq desc
</select>
<!-- 특정 게시물에 관련된 언어 목록 -->
<select id="llist" parameterType="String" resultType="ldto">
select * from tblCodeLanguage cl
left outer join (select * from tblCodeLanguageLink where cseq = #{ seq }) cll
on cl.seq = cll.lseq
order by cl.seq asc
</select>
<!-- 모든 언어 -->
<select id="llistAll" resultType="ldto">
select * from tblCodeLanguage order by seq asc
</select>
<!-- 글 쓰기 -->
<insert id="add" parameterType="dto">
insert into tblCode (seq, subject, content, code, regdate)
values (seqCode.nextVal, #{ subject }, #{ content }, #{ code }, default)
</insert>
<!-- 방금 쓴 글의 번호 -->
<select id="getSeq" resultType="String">
select max(seq) from tblCode
</select>
<!-- 방금 쓴글과 연결된 언어 추가 -->
<insert id="addLink" parameterType="cldto">
insert into tblCodeLanguageLink (seq, cseq, lseq)
values (seqCodeLanguageLink.nextVal, #{ cseq }, #{ lseq })
</insert>
</mapper>
[ index.jsp ]
- 홈 페이지
- 로그인/로그아웃 및 코드 게시판으로 이동하는 기능을 수행 한다.
<!-- 로그인 안했을 때 -->
<c:if test="${ empty id }">
<form method="POST" action="/code/signin.action">
<!-- 전송할때 text하나면 submit 안만들어도됨.(엔터만 치면됨) -->
<input type="password" name="pw" class="form-control" required autofocus placeholder="passoword">
</form>
</c:if>
<!-- 로그인 했을 때 -->
<c:if test="${ not empty id }">
<!-- 코드 게시판 이동 -->
<div onclick="location.href='/code/list.action';" class="signed">signed. Code</div>
<!-- 로그아웃 -->
<div onclick="location.href='/code/signout.action';" class="signed">sign out.</div>
</c:if>
[ add.jsp ]
- 글 쓰기 페이지
- 글 제목, 코드 설명 내용, 코드 내용, javascript로 적용한 코드 내용 언어 설정을 할 수 있다.
<form method="POST" action="/code/addok.action">
<table class="table table-bordered table-add">
<tr>
<td><input type="text" name="subject" class="form-control" required placeholder="Subject" autocomplete="off"></td>
</tr>
<tr>
<td><textarea name="content" class="form-control" required placeholder="Description"></textarea></td>
</tr>
<tr>
<td>
<div class="language">
<c:forEach items="${llist}" var="ldto">
<i class="${ldto.langclass} ${ldto.langicon} icon off"
title="${ldto.name}"
data-toggle="tooltip"
data-placement="bottom"
data-language="${ldto.name.toLowerCase()}"
data-lseq="${ldto.seq}"></i>
</c:forEach>
</div>
</td>
</tr>
<tr>
<td><textarea name="code" class="form-control" required placeholder="Code"></textarea></td>
</tr>
</table>
<div class="btns">
<button type="button" class="btn btn-default" onclick="location.href='/code/list.action';">Back</button>
<button type="submit" class="btn btn-primary">Create Code</button>
</div>
<input type="hidden" name="lseq">
</form>
<script src='/code/resources/js/add.js'></script>
[ list.jsp ]
- 글 리스트 페이지
- 해당 글을 클릭하면 상세페이지로 이동한다.
- 코드 언어 아이콘을 클릭하면 해당 언어와 관련된 언어 리스트 목록을 확인 할 수 있다.
<c:forEach items="${list}" var="dto">
<div class="item">
<div class="language">
<c:forEach items="${ dto.llist }" var="ldto">
<!-- 관련 언어 O -->
<c:if test="${ not empty ldto.cseq }">
<i class="${ ldto.langclass} ${ldto.langicon } icon"
title="${ ldto.name }"
data-toggle="tooltip"
data-placement="bottom"
data-language="${ldto.name.toLowerCase() }"
onclick="location.href='/code/list.action?lseq=${ ldto.seq }';"></i>
</c:if>
<!-- 관련 언어 X -->
<c:if test="${ empty ldto.cseq }">
<i class="empty-icon icon"></i>
</c:if>
</c:forEach>
</div>
<div class="desc" onclick="location.href='/code/view.action';">
<h4>${ dto.subject }</h4>
<div class="ellipsis">${ dto.content }</div>
</div>
</div>
</c:forEach>
<div class="btns">
<button type="button" class="btn btn-default" onclick="location.href='/code/list.action';">All Code</button>
<button type="button" class="btn btn-primary" onclick="location.href='/code/add.action';">Add Code</button>
</div>
<script src='/code/resources/js/list.js'></script>
[ 구현 화면 ]
MEMO>
# 일반 게시판 CRUD 구현이 아닌, 코드 작성과 설명을 작성하는 게시판 구현은 처음하다니 보니 낯설어서 많이 헷갈렸다. 다시 복습할 것
# 오늘은 쓰기, 보기 구현을 했으니 내일은 상세 보기 구현!!
# 마지막 프로젝트 + 취업 준비로 많이 어수선 하지만 유종의 미를 거둘 수 있게 노력하기!
728x90
반응형
'교육 > Spring' 카테고리의 다른 글
Spring 개발자 수업 102일차 - 웹 소켓(Web Socket)을 이용한 채팅 구현하기 (10) | 2021.08.22 |
---|---|
Spring 개발자 수업 101일차 - 코드 게시판 만들기(상세 보기, 댓글 작성) (0) | 2021.08.19 |
Spring 개발자 수업 99일차 - AOP 적용한 게시판 만들기 (0) | 2021.08.17 |
Spring 개발자 수업 98일차(2) - 타일즈(Tiles) (0) | 2021.08.13 |
Spring 개발자 수업 98일차(1) - MyBatis(SELECT) (0) | 2021.08.13 |
댓글