1. 시작하기
Spring
Framework3.2 게시판 2단계 : 지금까지 구현한 게시판의 기본 기능에 Spring AOP를 적용하여 충고(Advice)를
적용하자.
onj.board.dao.SpringBoardDAO.java의
insert, update, delete등 DML문장 실행시 로그를 남기기
2. Loging을 위한 테이블 생성
create table boardlog02
(
method
varchar2(50),
sql
varchar2(1000),
ilsi
date
);
3. BoardDAO.java , BoardDAOImple.java
package com.board.dao;
import java.util.List;
import java.util.Map;
import
org.springframework.dao.DataAccessException;
import com.board.model.BoardDTO;
import com.board.model.CommentDTO;
public interface BoardDAO {
// 전체 게시글 수
public int boardCount(Map<String,
Object>searchMap)throws DataAccessException;
// 게시판 리스트
public List<BoardDTO> boardList(Map<String,
Object>searchMap) throws DataAccessException;
// 게시물 본문 미리보기
public String preView(String seq)throws
DataAccessException;
// 게시글 조회수 1씩증가
public int updateReadCount(String seq)throws
DataAccessException;
// 게시글 상세보기
public BoardDTO readContent(String seq)throws
DataAccessException;
// 코멘트 저장
public int insertComment(CommentDTO
commentDTO)throws DataAccessException;
// 코멘트 조회
public List<CommentDTO> ListComment(String
seq)throws DataAccessException;
// 게시글 입력
public int insertBoard(BoardDTO boardDTO)throws
DataAccessException;
// 글 수정
public int updateBoard(BoardDTO boardDTO)throws
DataAccessException;
// 게시글 삭제
public int deleteBoard(BoardDTO boardDTO)throws
DataAccessException;
// 코멘트 전체 삭제
public int AllDeleteComment(String seq)throws
DataAccessException;
// 답글 달기
public int replyBoard(BoardDTO boardDTO)throws
DataAccessException;
//
SQL리턴용
public String
getSql()throws DataAccessException;
}
------------------------------------------------------------------------------------------
package com.board.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.dao.DataAccessException;
import
org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.jdbc.core.RowMapper;
import
org.springframework.stereotype.Component;
import com.board.model.BoardDTO;
import com.board.model.CommentDTO;
@Component("boardDAO")
public class BoardDAOImple implements BoardDAO
{
@Autowired
private DataSource dataSource;
public JdbcTemplate getTemplate(){return new
JdbcTemplate(dataSource);}
private String sql
="";
// 게시글 수
public int boardCount(Map<String,
Object>searchMap)throws DataAccessException{
int count = 0;
if(searchMap.get("boardListSearchText") == null ||
searchMap.get("boardListSearchText").equals("")){
sql = "select count(*) from
board02";
count =
getTemplate().queryForObject(sql,
Integer.class
);
}else{
String boardListSelect = (String)
searchMap.get("boardListSelect");
String boardListSearchText = (String)
searchMap.get("boardListSearchText");
sql = "select count(*) from board02
where "+boardListSelect+" like
'%"+boardListSearchText+"%'";
count =
getTemplate().queryForObject(sql,Integer.class);
}
return count;
}
// 게시판 리스트
public List<BoardDTO> boardList(Map<String,
Object>searchMap) throws DataAccessException {
List<BoardDTO> boardList =
null;
Object[] obj;
if(searchMap.get("boardListSearchText") == null ||
searchMap.get("boardListSearchText").equals("")){
sql = "select * from
("
+ " select ROWNUM r,seq ,name,title
,TO_CHAR(regdate,'YYYY/MM/DD')as regdate, readcount,"
+ " reply, reply_step, reply_level
"
+ " from "
+ " (select * from board02 "
+ " order by reply desc, reply_step
asc"
+ " )"
+ " )"
+ " where r BETWEEN ? AND ?";
obj = new Object[]
{searchMap.get("startRow"),searchMap.get("endRow")};
}else{
String boardListSelect = (String)
searchMap.get("boardListSelect");
String boardListSearchText = (String)
searchMap.get("boardListSearchText");
sql = "select * from
("
+ " select ROWNUM r,seq ,name,title
,TO_CHAR(regdate,'YYYY/MM/DD')as regdate, readcount, "
+ " reply, reply_step, reply_level
"
+ " from "
+ " (select * from board02 "
+ " where "
+ " "+boardListSelect+" like
'%"+boardListSearchText+"%'"
+ " order by reply desc, reply_step
asc"
+ " )"
+ " )"
+ " where r BETWEEN ? AND ?";
obj = new Object[]
{searchMap.get("startRow"),searchMap.get("endRow")};
}
boardList =
getTemplate().query(sql,
obj,
new
RowMapper<BoardDTO>(){
public BoardDTO mapRow(ResultSet rs, int
rowNum)throws SQLException{
BoardDTO boardDTO = new
BoardDTO(rs.getString("seq"),
rs.getString("name"),
rs.getString("title"),
rs.getString("regdate"),
rs.getInt("readcount"),
rs.getInt("reply_step"),
rs.getInt("reply_level")
);
return boardDTO;
}
});
return boardList;
}
// 게시물 본문내용 미리보기
public String preView(String seq) throws
DataAccessException{
sql = "select content from board02 where
seq = ?";
String preContent = "";
Object obj[] = {seq};
preContent =
getTemplate().queryForObject(sql,obj,String.class);
return preContent;
}
// 게시글 조회수 1씩증가
public int updateReadCount(String seq)throws
DataAccessException{
sql
= " update board02 set
readcount = nvl(readcount,0)+1 where seq = ?";
Object[] obj = {seq};
return
getTemplate().update(sql,obj);
}
// 게시글 상세보기
public BoardDTO readContent(String seq)throws
DataAccessException{
// 조회수 1증가 메소드 호출
this.updateReadCount(seq);
sql
= "select * from board02
where seq = ?";
Object[] obj = {seq};
BoardDTO boardDTO =
getTemplate().queryForObject(sql,
obj,
new RowMapper<BoardDTO>()
{
public BoardDTO mapRow(ResultSet rs,int
rowNum)throws SQLException {
BoardDTO boardDTO = new
BoardDTO();
boardDTO.setSeq(rs.getString("seq"));
boardDTO.setName(rs.getString("name"));
boardDTO.setPasswd(rs.getString("passwd"));
boardDTO.setTitle(rs.getString("title"));
boardDTO.setContent(rs.getString("content"));
boardDTO.setFilename(rs.getString("filename"));
boardDTO.setRegdate(rs.getString("regdate"));
boardDTO.setReadcount(rs.getInt("readcount"));
boardDTO.setReply(rs.getString("reply"));
boardDTO.setReply_step(rs.getInt("reply_step"));
boardDTO.setReply_level(rs.getInt("reply_level"));
return boardDTO;
}
});
return boardDTO;
}
// 코멘트 저장
public int insertComment(CommentDTO commentDTO)
throws DataAccessException {
sql = "insert into comment_t02
values(sequence_comment_seq.nextval,?,?,?)";
Object[] obj =
{commentDTO.getComment_name(),commentDTO.getComment_comm(),commentDTO.getSeq()};
return getTemplate().update(sql,
obj);
}
// 코멘트 조회
public List<CommentDTO> ListComment(String
seq) throws DataAccessException {
sql = "select * from comment_t02 where
seq = ? order by comment_seq desc";
Object[] obj = {seq};
List<CommentDTO> list =
getTemplate().query(sql,
obj,
new
RowMapper<CommentDTO>(){
public CommentDTO mapRow(ResultSet rs,int
rowNum)throws SQLException {
CommentDTO commentDTO = new
CommentDTO();
commentDTO.setComment_seq(rs.getString("comment_seq"));
commentDTO.setComment_name(rs.getString("comment_name"));
commentDTO.setComment_comm(rs.getString("comment_comm"));
commentDTO.setSeq(rs.getString("seq"));
return commentDTO;
}
});
return list;
}
// 게시글 입력
public int insertBoard(BoardDTO boardDTO)throws
DataAccessException{
sql = "insert into board02
values(sequence_board_seq.nextval,?,?,?,?,?,sysdate,0,sequence_board_seq.currval,0,0)";
Object[] obj = {boardDTO.getName(),
boardDTO.getPasswd(), boardDTO.getTitle(),boardDTO.getContent(),
boardDTO.getFilename()};
return getTemplate().update(sql,
obj);
}
// 글 수정
public int updateBoard(BoardDTO boardDTO)throws
DataAccessException{
sql = "update board02 set name = ?
,title = ?,content = ? where seq = ?";
Object[] obj = {
boardDTO.getName(),
boardDTO.getTitle(),
boardDTO.getContent(),
boardDTO.getSeq()
};
return
getTemplate().update(sql,obj);
}
// 게시글 삭제
public int deleteBoard(BoardDTO boardDTO)throws
DataAccessException{
// reply_revel이 0이면 본글 이고, 1이상이면
답변글
if(boardDTO.getReply_level() ==
0){
sql = "delete from board02 where reply =
?";
}else{
sql
= "delete from board02
where seq = ?";
}
Object[] obj =
{boardDTO.getSeq()};
// 코멘트 전체 삭제
this.AllDeleteComment(boardDTO.getSeq());
return
getTemplate().update(sql,obj);
}
// 코멘트 전체 삭제
public int AllDeleteComment(String seq)throws
DataAccessException{
sql = "delete from comment_t02 where seq
= ?";
Object[] obj = {seq};
return
getTemplate().update(sql,obj);
}
// 답글 달기
public int replyBoard(BoardDTO boardDTO)throws
DataAccessException{
// 현재 답변을 단 게시물 보다 더 높은 스텝의 게시물이 잇다면 스텝을 하나씩
상승시킴.
sql ="update board02 set reply_step =
reply_step + 1 "
+ "where reply = ? and reply_step >
?";
Object[] obj1
={boardDTO.getReply(),boardDTO.getReply_step()};
getTemplate().update(sql, obj1);
// reply_step과 reply_level을 1씩 증가시킨 후 내용을
저장
String sql = "insert into board02
values(sequence_board_seq.nextval,?,?,?,?,?,sysdate,0,?,?,?)";
Object[] obj2
={boardDTO.getName(),boardDTO.getPasswd(),boardDTO.getTitle(),boardDTO.getContent(),boardDTO.getFilename(),
boardDTO.getReply(),boardDTO.getReply_step()+1,boardDTO.getReply_level()+1};
return getTemplate().update(sql,
obj2);
}
//
SQL리턴용
public String
getSql()throws DataAccessException{
return
sql;
}
}
4. com.board.aop.LoggingDAO.java ,
com.board.aopLoggingImple.java
package com.board.aop;
import org.springframework.dao.DataAccessException;
import com.board.model.BoardLogDTO;
public interface LoggingDAO {
// 로그용 테이블에 로그 저장
public int
writeLog(BoardLogDTO boardLogDTO)throws DataAccessException;
}
------------------------------------------------------------------------------------------
package com.board.aop;
import javax.sql.DataSource;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.stereotype.Component;
@Component("loggingDAO")
public class LoggingDAOImple implements
LoggingDAO{
@Autowired
private DataSource dataSource;
public JdbcTemplate getTemplate(){return new
JdbcTemplate(dataSource);}
// 로그용 테이블에 로그
저장
public int writeLog(String methodName, String
dml){
String sql = "insert into boardlog02(method,
sql,ilsi) values(?,?,sysdate)";
Object[] obj = {methodName,dml};
return getTemplate().update(sql, obj);
}
}
5.
com.board.aop.LoggingAspect.java 생성
package com.board.aop;
import
org.aspectj.lang.JoinPoint;
import
org.aspectj.lang.annotation.AfterReturning;
import
org.aspectj.lang.annotation.Aspect;
import
org.springframework.beans.factory.annotation.Autowired;
import com.board.dao.BoardDAO;
@Aspect
public class LoggingAspect {
@Autowired
private LoggingDAO loggingDAO;
@Autowired
private BoardDAO boardDAO;
// 사후충고(반드시 정상 리턴 후
호출
// BoardDAOImple의 모든 메소드중
파라미터가 1개 있는 메소드가 충고받을 포인트 컷이됨.
// getSql()만 메소드 파라미타가 없어
충고 적용 안됨.
@AfterReturning(pointcut="execution(*
com.board.dao.BoardDAOImple.*(*))", returning="result")
public void logAfterReturning(JoinPoint
joinPoint){
System.out.println("<<<<<<<<<<
DAO 로깅 충고 실행");
loggingDAO.writeLog(joinPoint.getSignature().getName(),
boardDAO.getSql());
}
}
6. /WEB-INF/ spring / appServlet /
root-context.xml
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--
aop -->
<aop:aspectj-autoproxy/>
<context:component-scan
base-package="com.board.aop"/>
<bean id="myLogger"
class="com.board.aop.LoggingAspect"/>
<!-- 파일 업로드 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize"
value="90000000"/>
<property name="defaultEncoding"
value="utf-8"/>
</bean>
<!-- Root Context: defines shared resources
visible to all other web components -->
<context:component-scan
base-package="com.board.dao"/>
<context:component-scan
base-package="com.board.service"/>
<context:component-scan
base-package="com.board.util"/>
</beans>
오라클자바커뮤니티교육센터, 개발자전문교육, 개인80%환급
www.oraclejavacommunity.com
평일주간(9:30~18:10) 개강
(6/30)[기업100%환급]PL/SQL,ORACLE HINT,TUNING[개강확정]
(6/30)[기업100%환급]안드로이드개발자과정[개강확정]
(6/30)[기업100%환급]SQL기초에서 Schema Object까지[개강확정]
(7/07)[기업100%환급]C#4.0,WinForm,ADO.NET프로그래밍
(7/07)[기업100%환급]Spring ,MyBatis,Hibernate실무과정[개강확정]
(7/07)[기업100%환급]자바기초에서 JDBC, Servlet/JSP까지
(7/07)[채용예정교육]오라클자바개발잘하는신입뽑기프로젝트,교육전취업확정
평일야간(19:00~21:50) 개강
(6/26)SQL초보에서실전전문가까지[개강확정]
(7/01)안드로이드개발자과정[개강확정]
(7/01)닷넷(C#,Network,ADO.NET,ASP.NET)마스터과정
(7/02)Spring3.X, MyBatis, Hibernate실무과정[개강확정]
(7/02)자바웹(JSP,Spring,MyBatis,XPlatform)프로젝트과정
(7/02)JAVA,Network&WEB&Framework(자바기초에서웹스프링까지)
(7/03)웹퍼블리싱 마스터
(7/15)MyBatis3.X, Hibernate4.X ORM실무과정
(7/22)자바기초에서JSP,Ajax,jQuery,Spring3.2,MyBatis까지
주말(10:00~17:50) 개강
(6/28)Spring3.X, MyBatis, Hibernate실무과정[개강확정]
(6/28)안드로이드개발자과정
(6/29)자바기초에서JSP,Ajax,jQuery,Spring3.2,MyBatis까지[개강확정]
(7/05)SQL초보에서 Schema Object까지
(7/12)자바웹(JSP,Spring,MyBatis,XPlatform)프로젝트과정
(7/12)MyBatis3.X, Hibernate4.X ORM실무과정
(7/12)개발자를위한PLSQL,SQL튜닝,힌트
(7/12)실무예제로 배워보는 jQuery(개발자/디자이너를위한)
(7/13)C#,ASP.NET마스터
주말저녁(18:30~22:20) 개강
(6/28)JAVA,Network&WEB&Framework
(6/28)SQL기초에서실무까지
www.oraclejavacommunity.com
평일주간(9:30~18:10) 개강
(6/30)[기업100%환급]PL/SQL,ORACLE HINT,TUNING[개강확정]
(6/30)[기업100%환급]안드로이드개발자과정[개강확정]
(6/30)[기업100%환급]SQL기초에서 Schema Object까지[개강확정]
(7/07)[기업100%환급]C#4.0,WinForm,ADO.NET프로그래밍
(7/07)[기업100%환급]Spring ,MyBatis,Hibernate실무과정[개강확정]
(7/07)[기업100%환급]자바기초에서 JDBC, Servlet/JSP까지
(7/07)[채용예정교육]오라클자바개발잘하는신입뽑기프로젝트,교육전취업확정
평일야간(19:00~21:50) 개강
(6/26)SQL초보에서실전전문가까지[개강확정]
(7/01)안드로이드개발자과정[개강확정]
(7/01)닷넷(C#,Network,ADO.NET,ASP.NET)마스터과정
(7/02)Spring3.X, MyBatis, Hibernate실무과정[개강확정]
(7/02)자바웹(JSP,Spring,MyBatis,XPlatform)프로젝트과정
(7/02)JAVA,Network&WEB&Framework(자바기초에서웹스프링까지)
(7/03)웹퍼블리싱 마스터
(7/15)MyBatis3.X, Hibernate4.X ORM실무과정
(7/22)자바기초에서JSP,Ajax,jQuery,Spring3.2,MyBatis까지
주말(10:00~17:50) 개강
(6/28)Spring3.X, MyBatis, Hibernate실무과정[개강확정]
(6/28)안드로이드개발자과정
(6/29)자바기초에서JSP,Ajax,jQuery,Spring3.2,MyBatis까지[개강확정]
(7/05)SQL초보에서 Schema Object까지
(7/12)자바웹(JSP,Spring,MyBatis,XPlatform)프로젝트과정
(7/12)MyBatis3.X, Hibernate4.X ORM실무과정
(7/12)개발자를위한PLSQL,SQL튜닝,힌트
(7/12)실무예제로 배워보는 jQuery(개발자/디자이너를위한)
(7/13)C#,ASP.NET마스터
주말저녁(18:30~22:20) 개강
(6/28)JAVA,Network&WEB&Framework
(6/28)SQL기초에서실무까지
댓글 없음:
댓글 쓰기