점프 투 스프링부트 추가기능 구현 - 조회수 수정

박철현·2023년 7월 26일
0

점프투스프링부트

목록 보기
2/14
  • 기존글 : 점프투스프링부트 추가기능 구현 - 조회수(수정 전 버전)

  • 문제 : 게시글 목록에서 글 이동하면 조회수가 증가하지만, 사용자가
    /detail/id 형태로 접속하면 증가가 안됨 -> Ajax 요청을 안보내니깐

  • 해결 : detail.html에 Ajax 메서드 구현, Controller 메서드 2개 나눈거 다시 1개로 변경

    • detail.html : html로드 시 함수 바로 실행되도록 하여 Ajax 보내기
    • JQuery Dom 조작 메서드 이용
      • replaceWith() : 아이디 해당 요소 전체 변경
      • html() : 자식 요소 전체 변경
 <script th:inline="javascript">

        window.onload = function () {
            checkQuestionRead(); // html 로드 시 바로 Ajax 요청
        };

        // 로컬스토리지에 해당 게시글 읽은적이 있는지 검사
        function checkIdInLocalStorage(id) {
            const visitedPosts = JSON.parse(localStorage.getItem("visitedPosts") || "[]");
            return visitedPosts.includes(id);
        }

        // 로컬스토리지에 방문 게시글 번호 추가
        // null 일 경우 []값이 들어가고, push로 id넣고 새로 세팅(맨 처음)
        function addIdToLocalStorage(id) {
            const visitedPosts = JSON.parse(localStorage.getItem("visitedPosts") || "[]");
            visitedPosts.push(id);
            localStorage.setItem("visitedPosts", JSON.stringify(visitedPosts));
        }

        const checkQuestionRead = () => {
            const questionId = [[${question.id}]];

            // 방문 내역 검사
            const isVisited = checkIdInLocalStorage(questionId);

            // 방문하지 않았을 때만 추가하고 조회수 증가하도록
            // true인 경우는 조건 제외함(요청 안보내도 되니)
            if (!isVisited) {
                addIdToLocalStorage(questionId);
                $.ajax({
                    // 요청방식: get
                    type: "get",
                    url: "/question/detail/" + questionId,
                    data: {
                        "isVisited" : false
                    },
                    success: function (fragment) {
                        $('#questionDetail').html(fragment);
                    },
                    error: function (err) {
                        console.log("요청 실패", err);
                    }
                });
            }
        }
    </script>
  • questionController.java
@GetMapping("/detail/{id}")
	public String detail(Model model, @PathVariable Integer id, @RequestParam(required = false) Boolean isVisited, AnswerForm answerForm, HttpServletRequest request) {
		Question question = questionService.getQuestion(id);

		// 방문한 적이 없을때만 조회수 증가
		if (isVisited != null && !isVisited) {
			questionService.updateQuestionView(question);
		}

		model.addAttribute("question", question);

		// 요청에 AJAX 헤더가 있는 경우 부분 페이지 반환
		if (Ut.AjaxUtils.isAjaxRequest(request)) {
			return "question/question_detail :: #questionDetail";
		}

		return "question/question_detail";
	}
  • Ajax 요청일때만 #으로 id에 해당하는 뷰를 전달 (타임리프 뷰 리졸버)
  • Ut.java
    • static 이유 : 객체 생성 안하고자
    • 왜 Ut안에 넣었나? 추가기능 하다보면 추가 클래스 발생 가능성 있으므로
 public class Ut {
	public static class AjaxUtils {
		public static boolean isAjaxRequest(HttpServletRequest request) {
        	// Ajax 요청인지 검사
			String header = request.getHeader("X-Requested-With");
			return "XMLHttpRequest".equals(header);
		}
	}
}

  • 결국 찐막 수정!
    • 위 수정 본에서, Controller 메서드 2개로 나눠서 increaseHit 메서드 추가
@GetMapping("/increase")
	@ResponseBody
	public String increaseHit(Integer questionId, @RequestParam(required = false) Boolean isVisited) {
		Question question = questionService.getQuestion(questionId);

		// 방문한 적이 없을때만 조회수 증가
		if (isVisited != null && !isVisited) {
			questionService.updateQuestionView(question);
		}

		return Integer.toString(question.getView());
	}
  const checkQuestionRead = () => {
            const questionId = [[${question.id}]];

            // 방문 내역 검사
            const isVisited = checkIdInLocalStorage(questionId);

            // 방문하지 않았을 때만 추가하고 조회수 증가하도록
            // true인 경우는 조건 제외함(요청 안보내도 되니)
            if (!isVisited) {
                addIdToLocalStorage(questionId);
                $.ajax({
                    // 요청방식: get
                    type: "get",
                    url: "/question/increase",
                    data: {
                        "questionId" : questionId,
                        "isVisited" : isVisited
                    },
                    success: function (fragment) {
                        $('#questionView').text(fragment);
                    },
                    error: function (err) {
                        console.log("요청 실패", err);
                    }
                });
            }
  • 별도 컨트롤러 메서드를 두고, 조회수 부분의 text만 변경하도록 수정

  • 불필요하게 다른 부분까지 다 변경하는 부분이 없어져서 좋은듯

  • 최종코드보러가기

profile
비슷한 어려움을 겪는 누군가에게 도움이 되길

0개의 댓글