[Spring Boot 게시판] 16일차

김정현·2022년 10월 18일
0

SPRINGBOOT게시판

목록 보기
15/36

1. Rq 객체 생성을 스프링이 하도록(빈으로 등록)

1) Rq 객체

    @Component
    @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
        public class Rq {
            @Getter
            private boolean isLogined;
            @Getter
                  ~~~ 생략 ~~~~
        public Rq(HttpServletRequest req, HttpServletResponse resp, MemberService memberService) {
                  ~~~ 생략 ~~~~	
            this.loginedMemberId = loginedMemberId;
            this.loginedMember = loginedMember;
            this.req.setAttribute("rq", this);
        }
  • Rq객체를 빈으로 등록하기위해 @Component 어노테이션을 사용
  • @ComponentScan을 통해 @Component어노테이션이 붙은 클래스를 빈으로 등록
  • 기존에는 BeforeActionInterceptor 인터셉터에서 new연산자를 통해 Rq객체를 생성하여 request.setAttribute("rq", rq) 하여 Rq객체를 사용 하였다.
  • 하지만 빈으로 등록했기 때문에 @Autowired를 통해 의존성 주입이 가능하다.
  • this.req.setAttribute("rq", this) Rq객체 자신을 HttpServletRequest객체에 setAttribute를 하여 사용

2) Rq객체 주입

    @Component
    public class NeedLoginInterceptor implements HandlerInterceptor {
        @Autowired
        private Rq rq;    
    @Controller
    public class UsrArticleController {
        @Autowired
        private Rq rq;
  • 빈으로 등록된 rq객체를 주입하여 사용

3) Rq객체 빈등록시 문제 발생에 대한 해결

만약 usr/article/write 요청이 오면

  • NeedLoginInterceptor(인터셉터)에서 rq객체를 주입받는다.

  • 이때 생성과 함께 주입이 되고 Rq객체는 생성시 Rq객체 자신을HttpServletRequest객체에 setAttribute한다.

  • 그리고 컨트롤러로 연결이되고 컨트롤러에서도 rq객체를 주입받는데 이때 rq객체는 빈으로 등록되면 싱글톤패턴이므로

  • 두 레퍼런스가 하나의 동일한 인스턴스를 사용한다.

  • usr/article/write.jsp파일로 이동 HttpServletRequest객체에 setAttribute했기때문에 jsp에서 rq객체를 사용가능

하지만 usr/home/main 요청이 오면

  • NeedLoginInterceptor(인터셉터)에서 rq객체를 주입받고 HttpServletRequest객체에 setAttribute한다.

  • NeedLoginInterceptor(인터셉터)는 아래코드에서 추가한 uri패턴에서만 인터셉터가 적용되는데

  • 	registry.addInterceptor(needLoginInterceptor).addPathPatterns("/usr/article/write")
    				.addPathPatterns("/usr/article/doWrite").addPathPatterns("/usr/article/modify")
    				.addPathPatterns("/usr/article/doModify").addPathPatterns("/usr/article/doDelete");}
  • rq객체는 usr/home/main 로 요청시 NeedLoginInterceptor가 적용되지않아 rq객체는 생성되지않는다.

  • rq객체가 생성되지 않는다면 jsp에서 rq객체를 사용할수 없다.

  • 이를 해결하기 위해 아래코드에서 BeforeActionInterceptor ( .addPathPatterns("/**") )에서 rq객체를 주입받고 있다.

  •     @Component
        public class BeforeActionInterceptor implements HandlerInterceptor {
            @Autowired
            private Rq rq;
            @Override
            public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
                    rq.initOnBeforeActionInterceptor();
                return HandlerInterceptor.super.preHandle(req, resp, handler);
            }
  • 하지만 @Autowired를 했음에도 rq객체가 사용되지 않는다면 어플리케이션 실행시 rq객체는 주입받지 않는것으로 보인다.

  • rq.initOnBeforeActionInterceptor()메소드를 실행함으로써 rq객체를 주입받는것으로 보인다.

2. 게시글 작성시 게시판 선택 구현

1) write.jsp

     <tr>
        <td>게시판 선택</td>
        <td>
          <select required name="boardId" class="select select-bordered">
            <option disabled>게시판을 선택해주세요</option>
            <option value="1">공지사항</option>
            <option value="2">자유게시판</option>
          </select>
        </td>
     </tr>
	<tr>
	    <td>제목</td>
		<td><input required="required" type="text" ~~생략~~ /></td>						
	</tr>
  • select 태그를 사용하여 게시판선택 (boardId)
  • input태그required 속성을 붙여주면 해당 반드시 입력해야한다.
  • 입력하지 않으면 입력하라는 메세지창이 보여진다.
  • option 태그에 disabled 속성 붙여주면 해당 옵션을 선택할수 없다.(비활성화)

2) 게시글 작성 쿼리문 수정

	<insert id="writeArticle">
		INSERT INTO article
		SET regDate = NOW(),
		updateDate =
		NOW(),
		memberId = #{loginedMemberId},
		title = #{title},
		`body`= #{body},
		boardId = #{boardId}
	</insert>
  • 게시글 작성시 게시글에 boardId 를 추가하여 DB에 저장

3. 게시글 리스트 페이징(파라미터 처리)

1) ArticleController showList메소드

      @RequestMapping("/usr/article/list")
        public String showList(Model model, @RequestParam(defaultValue = "1") int boardId, 
                               @RequestParam(defaultValue = "1") int page) {
            Board board = boardService.getBoardById(boardId);

            if (board == null) {
                return rq.jsHistoryBackOnView("존재하지 않는 게시판 입니다.");
            }
            int itemsInApage = 10;
            List<Article> articles = articleService.getForPrintArticles(rq.getLoginedMemberId(), boardId, page, itemsInApage);
  • @RequestParam 어노테이션을 사용해 필수 파라미터를 받게 하고
  • defaultValue속성으로 기본값을 지정
  • itemsInApage는 페이지당 보여줄 게시물의 수

2) ArticleService

	public List<Article> getForPrintArticles(int actorId, int boardId, int page, int itemsInApage) {
		int limitStart = (page -1) * itemsInApage;
		int limitTake = itemsInApage;
		
		List<Article> articles = articleRepository.getForPrintArticles(boardId, limitStart, limitTake);
		for (Article article : articles) {
			updateForPrintData(actorId, article);
		}
		return articles;
	}
  • limitStart : 2페이지라면 11부터 20까지의 게시물을 가져와야한다. 쿼리문(LIMIT)을 작성하기위한 변수
  • limitTake : 페이지당 가져올 게시물의 수, 쿼리문(LIMIT)을 작성하기위한 변수

3) ArticleRepository.xml

	<select id="getForPrintArticles" resultType="Article">
		SELECT A.* , M.nickname AS extra__writer 
		FROM article AS A
		INNER JOIN `member` AS M
		ON A.memberId = M.id
		WHERE 1
		<if test="boardId != 0">
		AND boardId = #{boardId}
		</if>
		ORDER BY A.id DESC
		<if test="limitTake != -1">
		LIMIT #{limitStart}, #{limitTake}
		</if>
	</select>
  • articleService에서 전달받은 limitStart,limitTake를 통해 쿼리문을 작성하여 가져올 게시물을 선택

@RequestParam

  • http요청 파라미터를 메서드의 파라미터로 전달받을 때 사용

  • 적용된 파라미터가 String이 아닐 경우 자동으로 타입변환

  • @RequestParam 어노테이션이 적용된 파라미터는 기본적으로 필수 파라미터required 속성 값 이용)

  • 필수 파라미터에대한 요청 파라미터가 없을 경우 에러 발생

  • defaultValue 속성을 이용하여 파라미터가 없을 경우 기본값을 설정

0개의 댓글