Spring TIL - 커뮤니티 게시판(1)

Jieun·2023년 5월 1일
0

📝 커뮤니티 게시판 목록 조회, interceptor 공부 후 자습
#230501

boardList.jsp
Header.jsp

📌 콘솔창에 sql문 로그 찍는 설정하기

1. 메이븐 홈페이지가서 검색창에 Log4jdbc 쳐서 아래처럼 뜨면 클릭

2. 버전 0.2.7 선택하여 아래 Maven 코드 긁어오기

<!-- https://mvnrepository.com/artifact/org.lazyluke/log4jdbc-remix -->
<dependency>
    <groupId>org.lazyluke</groupId>
    <artifactId>log4jdbc-remix</artifactId>
    <version>0.2.7</version>
</dependency>

3. 위 메이븐 코드 복사해서 pomm.xml 안에 4개 밑에 써주기

4. root-context.xml안에 id값 dataSource ➡️ RealDataSource라고 수정하기

5. root-context.xml dbcp bean등록 구문 밑에 아래코드 복붙하기

<!-- 
	log4j를 이용한 SQL 로그 출력용 bean 생성
	
	* realDataSource를 이용해서 SQL 수행 내용, 결과를 출력하는 역할
	-> realDataSource를 대체하는 역할
-->
	 <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
	 	<constructor-arg ref="realDataSource" />

6. log4j.xml 내용 제일 하단 Root Logger 위에 아래 코드 복붙하기

<!-- SQL 로그 출력 -->
	<logger name="java.sql.Connection">
		<level value="debug" />
		<appender-ref ref="sql-console" />
	</logger>

	<logger name="java.sql.Statement">
		<level value="debug" />
		<appender-ref ref="sql-console" />
	</logger>

	<logger name="java.sql.PreparedStatement">
		<level value="debug" />
		<appender-ref ref="sql-console" />
	</logger>

	<logger name="java.sql.ResultSet">
		<level value="debug" />
		<appender-ref ref="sql-console" />
	</logger>

	<logger name="jdbc.sqlonly" additivity="false">
		<level value="INFO" />
		<appender-ref ref="sql-console" />
	</logger>

	<logger name="jdbc.resultsettable" additivity="false">
		<level value="INFO" />
		<appender-ref ref="sql-console" />
	</logger>

7. 서버돌려서 콘솔창에 아래처럼 나오면 성공!


📌 DB테이블 설정 맞추기

community_final_sql 파일 참고해서 필요한부분 설정하기


게시판 기능 구현할 파일들 만들기
edu.kh.comm.board.model.vo

  • Pagination
  • Board
  • BoardImage
  • BoardDetail
  • Boardtype

edu.kh.comm.board.controller

  • BoardController

edu.kh.comm.board.model.service;

  • BoardService (인터페이스)
  • BoardServiceImpl (클래스)

edu.kh.comm.board.model.dao

  • BoardDAO

edu.kh.comm.common.interceptor

  • BoardTypeInterceptor(클래스)

board-mapper.xml


interceptor

요청이 Dispatcher Servlet에서 Controller에 도달하기 전 또는 후에
요청/응답 객체(req, resp)를 가로채서 사용할 수 있는 객체

spring - appServlet - survlet-context.xml 닫는 beans태그 바로 위에 interceptor 구문 적기

<!-- interceptors : 인터셉터를 모아둔 태그 -->
	<interceptors>
		
		<interceptor>
		
		<!-- 가로챌 요청의 패턴을 지정 -->
		<mapping path="/**"/>
		
		<!-- 인터셉터 역할을 수행할 클래스를 찾아서 bean 등록 -->
		<beans:bean id="boardTypeInterceptor"
                    class="edu.kh.comm.common.interceptor.BoardTypeInterceptor"/>
		<!--id = "이름"  class="패키지명.클래스명" -->
		</interceptor>
	</interceptors>

인터셉터가 요청을 가로채는 시기

1. preHandle (전처리) : 컨트롤러 수행 전

2. postHandle (후처리) : 컨트롤러 수행 후 ( 컨트롤러 수행 결과 참조 가능)

3. afterCompletion(View 단 처리 후) : 보통은 자원 반환 ( close() )을 수행

단, 비동기 요청(java 내부 쓰레드 요청)은 가로채지 않음. (ajax같은 비동기요청은 아님)



⭐⭐ 인터셉터 클래스 만들기

  • 인터셉터 클래스 만들고 이름 뒤에 implements HadlerInterceptor 써주기
  • 오버라이드 3개 해주기
    (alt + shift + s 눌러서 override/implement method 클릭하면 자동생성)

package edu.kh.comm.common.interceptor;

import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import edu.kh.comm.board.model.service.BoardService;
import edu.kh.comm.board.model.vo.BoardType;

public class BoardTypeInterceptor implements HandlerInterceptor {
	
	

	
	private Logger logger = LoggerFactory.getLogger(BoardTypeInterceptor.class);
	
	//BoardService 의존성 주입 받기 (DI)
	@Autowired
	private BoardService boardService;
	

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		// logger.info("전처리 수행");
		
		// application scope에 "boardTypeList(키값이름, setAttribute해서 쓰는)"가 없을 경우
		// 이를 조회하는 Service 호출 후 결과를 세팅
		
		// application scope 객체 얻어오기
		ServletContext application = request.getServletContext();
		
		// application scope에 "boardTypeList"가 없을 경우
		if ( application.getAttribute("boardTypeList") == null ) {
			
			List<BoardType> boardTypeList = boardService.selectBoardType();
			
			application.setAttribute("boardTypeList", boardTypeList);
		}
	
		return HandlerInterceptor.super.preHandle(request, response, handler);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		logger.info("후처리 수행");
		
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
		logger.info("View단 처리 완료 후 수행");

		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}
	
}

@PathVariable("value")

  • URL 경로에 포함되어 있는 값을 변수로 사용할 수 있게하는 역할
    ➡️자동으로 request scope에 등록됨 ➡️ jsp에서 ${value} EL 작성 가능
  • PathVariable : 요청 자원을 식별하는 경우
  • QueryString : 정렬, 검색등의 필터링 옵션
<< BoardController >>

@Controller
@RequestMapping("/board")
public class BoardController {
	
	@Autowired
	private BoardService service;
	
	
	// 게시글 목록 조회
	@GetMapping("/list/{boardCode}")
	public String boardList(@PathVariable("boardCode") int boardCode,
							@RequestParam(value="cp", required = false, defaultValue = "1") int cp,
							Model model
							/* @RequestParam Map<String, Object> paramMap */) { 		
		
		// 게시글 목록 조회 서비스 호출
		// 1) 게시판 이름 조회 -> 인터셉터로 application에 올려둔 boardTypeList 쓸 수 있을 듯?
		// 2) 페이지네이션 객체 생성(listCount)
		// 3) 게시글 목록 조회
		
		Map<String, Object> map = null;
		
		map = service.selectBoardList(cp, boardCode);
		
		model.addAttribute("map", map);
		
		return "board/boardList";
	}

RowBounds 객체 (Mybatis)

전체 조회 결과에서 몇 개의 행을 건너 뛰고 (offset) 그 다음 몇개의 행만 조회할 것인지 지정

<< BoardDAO >>

public List<Board> selectBoardList(Pagination pagination, int boardCode) {

		int offset = (pagination.getCurrentPage() -1 ) * pagination.getLimit();
		
		RowBounds rowBounds = new RowBounds(offset, pagination.getLimit());
		
		return sqlSession.selectList("boardMapper.selectBoardList", boardCode, rowBounds);

	}
profile
👩‍💼👩‍💼➡️➡️➡️👩‍💻👩‍💻 생산자의 삶을 살기 위해 개발공부중

0개의 댓글