본문 바로가기

Servlet&JSP 프로그래밍

뉴렉처[Servlet/JSP] 강의 복습 75강~84강

75강 - getNoticeList의 JDBC 코드 구현하기

데이터 서비스를 해주는 Service 덕분에 Controller에서의 코드가 간결화 되고, Controller는 사용자의 입력과 출력만

신경 쓰면 된다.

즉, Controller에서 사용자의 요청이 들어왔을때 무엇을 필요로 하는지 캐치하고 해당 Service에 필요로 하는 데이터를 요청해서 받음으로써 데이터를 View로 출력해준다.

 

* 테이블의 속성(field)을 sql문의 값을 세팅하려면 물음표로 세팅할 수 없고 값을 직접 넣어주는 식으로 

select * from notice where " + field + " like ? order by regdate desc 으로 해야한다.

 

왜 물음표를 넣을 수 없나요?

==> 물음표로 값을 넣으면 field가 sql문으로 들어갈때 'field로 들어가기 때문이다. (문자열 값으로 인식)

ex) select * from notice where 'field' like %'A'% order by regdate desc; 

위와 같은 결과로 들어가버린다.

 

76강 - NoticeService 클래스 완성하기

77강 - 목록 페이지에서 검색 추가하기

Controller의 역할은 사용자의 요청을 받아 처리후 다시 View단으로 출력하는 것이다.

 

* list.jsp에서 사용자는 Controller에 요청할때 name의 속성값은 key이며 그에 따른 제목의 value는 title안에 있고

작성자의 value는 writerId에 있다.

<select name="f">
    <option  value="title">제목</option>
    <option  value="writerId">작성자</option>
</select> 

<label class="hidden">검색어</label>
<input type="text" name="q" value=""/>

 

제목을 통해서 검색을 Controller에 요청할때 전달되는 url의 예
==> list?f=title&q=HelloWorld

 

Controller에서는 

String field = request.getParameter("f"); // 사용자로부터 요청한 검색 조건 값이 들어있다.(제목 or 작성자)

String query = request.getParameter("q"); // 사용자로부터 요청한 검색 키워드 값이 들어있다.

위와 같이 해줌으로써 클라이언트롭터 넘어온 요청 값을 받는다.

 

여기서 잠깐!! 문제점 발생!!!

 

문제1. 검색할때 검색어가 유지 안됨

param.q는 url값에 http://localhost:8080/notice/list?f=title&q=JDBC

파라미터로 넘어온 q를 가져오는 속성이다. 따라서 value에 ${param.q} 해줌으로써 검색했던 값을 그대로 넣어준다.

=> <input type="text" name="q" value="${param.q}" />

 

문제2. 검색 키워드를 "제목"이 아닌 "작성자"로 설정했을때 문제 발생

=> why? oracle 컬럼명은 writer_id 이고 list.jsp에서는 writerId 로 되어있기에 현재 서로 불일치한 상황

따라서 list.jsp의 value값에서 writer_id로 변경해주어 해결

 

문제3. "작성자"로 검색을 요청시 결과 페이지에 다시 "제목"으로 돌아가있는 문제 발생

=> param값과 <option>태그의 selected 속성을 이용한다.

파라미터로 넘어온 f(param.f)이 title이면 해당 option태그를 selected 해주고,

writer_id이면 해당 option태그를 selected 해주면 된다. (삼항연산자 이용)

ex.

<select name="f">
    <option ${(param.f == "title") ? "selected":""} value="title">제목</option>
    <option ${(param.f == "writer_id") ? "selected":""}  value="writer_id">작성자</option>
</select>

 

78강 - 목록에서 페이징 구현하기

Controller 에 사용자가 요청한 page값을 받는 page변수를 만들어준다.

(주의!! page는 int 이지만 String으로 받아야한다.)

-> why? 만약 요청받은 값이 없어서 null이 올 수 있는데 int는 null값을 받을 수 없기 때문에 오류가 발생한다.

따라서 null도 받아 줄 수 있는 String 으로 변수타입을 사용한다.

[list.jsp]

<ul class="-list- center">
   <c:forEach var="i" begin="0" end="4"> 
   <li>

        <a class="-text- orange bold" href="?p=${startNum+i}&f=${param.f}&q=${param.q}" >${startNum+i} </a>         </li>
   </c:forEach>
</ul>

 

[Controller]
String page_ = request.getParameter("p"); // 사용자가 요청한 페이지 값이 들어있다.

 

문제점 발생!!!

페이지 2를 눌렀을때 page값은 넘어가지만 field와 query 값은 빈문자열로 전달되고 있다.

넘어온 값이 빈문자열이니까 조건 검사에서 field_ != null 과 query_ != null 을 통과하고 그대로 빈문자열을 쓰는 상황!

=> field와 query값이 ""(빈문자열)로 들어가고 service 클래스 내부에서 의도치않는 쿼리문을 생성하게 된다.

따라서 조건식을 한번 더 세부적으로 만들어주어야한다.(빈문자열이 아니어야한다는 조건을 추가)

 

String field_ = request.getParameter("f");

String query_ = request.getParameter("q");

String page_ = request.getParameter("p");

 

String field = "title";

if(field_ != null && !field_.equals("")) {

field = field_;

}

 

String query = "";

if(query_ != null && !query_.equals("")) {

query = query_;

}

 

int page = 1;

if(page_ != null && !page_.equals("")) {

page = Integer.parseInt(page_);

}

 

79강 - Pager에서 현재 페이지 번호 처리

* 해당 페이지의 위치를 우측하단에 표시해주는 작업

<div><span class="text-orange text-strong">${(empty param.p)?1:param.p }</span> / 1 pages</div>

==> empty연산자를 통해서 파라미터 p의 값이 null 이거나 빈문자열일때 1로 그 외는 넘어오는 페이지의 값을 나타나게 삼항연산자로 설정함

 

* 현재 보고있는 페이지의 번호를 알 수 있게 처리해주는 작업

<ul class="-list- center">
   <c:forEach var="i" begin="0" end="4"> 
      <li>
            <a class="-text- ${(param.p==(startNum+i))? 'orange':'' } bold"

                href="?p=${startNum+i}&f=${param.f}&q=${param.q}"> ${startNum+i} </a>
      </li>
   </c:forEach>
</ul>

==> 파라미터로 넘어오는 p와 forEach작업을 할때 표시하는 숫자와 같을때 orange색으로 하이라이트를 준다.

 

그런데 확인 결과 처음 페이지를  등장시킬때 1에 대한 하이라이트가 안나타난다.

why? 처음 페이지를 등장시킬때 파라미터 p의 값이 없기 때문이다.

 

따라서 이전에 설정한 page변수를 가져다 쓴다. (<c:set var="page" value="${(empty param.p)?1:param.p}"/>)

<ul class="-list- center">
   <c:forEach var="i" begin="0" end="4"> 
      <li>
            <a class="-text- ${(page==(startNum+i))? 'orange':'' } bold" href=

                 "?p=${startNum+i}&f=${param.f}&q=${param.q}">${startNum+i} </a>
      </li>
   </c:forEach>
</ul>

 

80강 - Pager에서 마지막 번호 처리하기

게시판에서 해당 게시물이 없는데도 하단의 Pager에 번호가 붙어져있다.

이 문제점을 해결하기 위해서 게시물이 있는 곳까지의 페이지 번호가 나타나게 할 것 이다.

KeyPoint!! 마지막 Pager 번호가 몇번인가?

 

총 게시물이 100개 이면 100/10을 해서 10개의 Pager을 만들면 되지만,

만약 총 게시물이 102개이면 11개의 Pager을 만들어 주어야한다.

==> 10.2 --> 11 로 만들어줘야하기 때문에 반올림을 해주는 Math함수를 사용!!

소수점이 있다면 값을 올려주는 Math.ceil(10.2) ---> 11.0 (반대로 Math.floor(10.2) ---> 10.0)

 

그런데 값이 11.0이 됨으로 뒤에 소수점을 잘라주는 함수를 써야한다.

맨위에서 JSTL을 추가한다. <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

* ${fn:substringBefore(11.0, '.')} 설명

==> 11.0의 값에서 .(점)이 발견되면 앞에 것만 가져와 달라.

 

최종 소스 

<c:set var="lastNum" value="${fn:substringBefore(Math.ceil(count/10), '.') }"/>

 

페이지 번호가 출력되는 것도 if문을 추가해서 lastNum보다 작거나 같을때까지만 Pager번호가 생성될 수 있게 조건문을 추가한다.

<ul class="-list- center">
   <c:forEach var="i" begin="0" end="4"> 
      <c:if test="${(startNum+i) <= lastNum}">
          <li>  <a class="-text- ${(page==(startNum+i))? 'orange':'' } bold"

                   href="p=${startNum+i}&f=${param.f}&q=${param.q}">${startNum+i} </a>

          </li>

      </c:if>
   </c:forEach>
</ul>


81강 - 자세한 페이지 수정하기

82강 - 목록에 댓글 수를 포함하려면?

83강 - 목록에 댓글 수를 포함하기 위한 쿼리문제

select n.id, n.title, n.writer_id, n.regdate, n.hit, n.files, COUNT(C.ID) cmt_count from notice N
left join "COMMENT" C on n.id = c.notice_id
group by n.id, n.title, n.writer_id, n.regdate, n.hit, n.files
order by N.regdate desc;  

 

84강 - 목록의 댓글 수를 위한 View 생성하기

[1. notic_view 라는 view 생성]
create view notice_view 
as 
select n.id, n.title, n.writer_id, n.regdate, n.hit, n.files, COUNT(C.ID) cmt_count from notice N
left join "COMMENT" C on n.id = c.notice_id
group by n.id, n.title, n.writer_id, n.regdate, n.hit, n.files;

[2.생성한 view 대입]
select * from ( 
    select rownum num, n.*
    from ( select * from notice_view where title like '%%' order by regdate desc ) n
) where num between 1 and 10;

 

 

 

 

 

 



[출처]

뉴렉쳐 
www.youtube.com/watch?v=u6-D8CJbsmo&list=PLq8wAnVUcTFVOtENMsujSgtv2TOsMy8zd&index=14