JSP & Servlet

40.JSP시작하기 Jasper를 이용한 서블릿 프로그래밍

자바를 이용해서 웹개발을 할때 서블릿이라는 것을 이용해서 프로그램을 만들었는데 제스퍼라는 도움을 통해 서블릿을 좀 더 쉽게 개발하는 방법을 배우고자 한다.
이것이 바로 JSP프로그램이다.
간단한 문자열을 보내면 어렵지 않지만 HTML출력이 많은 결과 페이지는 어렵다. 이전처럼 한줄한줄 출력하면 매우 귀찮다.
Calculator참조
add.jsp 확장자만 jsp로 바꾸면된다. html코드들을 출력할 것으로 인식하고 출력하게 된다.
그런데 과연 이것들이 서블릿으로 언제 바꿔지나? 이게 요구될때 만들어진다. jsp파일은 jsp파일자체가 url이된다.
calc3.html을 calculator.jsp로 변경하였다.

재스퍼를 사용하면 요청할때마다 다시 만들어준다. 서블릿에 변경이 있으면 그것을 다시 컴파일하기 위해 서버를 재시작했었는데 굳이 그럴필요가 없다.
그냥 새로고침만 하면된다.
우리가 컨트로 f11로 시작했을때 왼쪽에 보이는 webapp의 파일을 열어주는 것같지만 그것이아니다.
이것들은 개발할때 사용하는 개발디렉토리이고 톰캣의 홈디렉토리로 옮겨지게 된다.
사용하고있는게 실제 사용하는것과 섞이면 안되니 별도의 이클립스가 관리하는 별도의 운영을 위한 서비스 운영을 위한 사본을 만든다. 개발할때 사용하는 임시 개발디렉토리이다.
workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\ROOT\org\apache\jsp
워크스페이스에가면 제스퍼가 만들어놓은 컴파일된 jsp파일을 볼 수 있다.

만약 int x = 3; int y = 4;처럼 변수를 선언하고싶은데 그냥 작성하면 출력표시가 들어간다.
그럼 이것들을 그대로 사용하고싶다면 어떻게 해야하나? 여기서 사용되는게 바로 코드블록이다.
<%
int x = 3;
int y = 4;
%>
이런식으로 작성하면 출력할 것이아니라 서블릿안에 자바코드를 넣고싶은 것이라는 것을 나타내는것이다.
재스퍼가 만든것을 직접 건들면 안되고 재스퍼가 올바르게 일할 수 있도록 jsp파일만 만져야한다.

41. JSP의 코드블록

재스퍼로 서블릿코드를 간접적으로 만들었다. 왜 그랫나? 문서를 출력할때 단순히 출력하는게아니라 방대한 HTML을 출력하는 것은 단순반복적이고 불편하기 때문이다.
출력문자사이에 자바 코드를 끼워넣는 방법을 배워보자.
사진참조
코드블록을 작성하면 서비스 메소드 블록에 들어가게 됨
1.코드블록의 종류1 : 출력코드
환영합니다. -> out.write("환영합니다.");
2.코드블록의 종류2 : 코드블록
<% y =x+3; %> -? y =x+3;
3.코드블록의 종류3 : 코드블록2
y의값은: y 라고할때 출력하고자하는 것이 문자열 + 자바코드라면
y의 값은: <% out.print(y) %> 코드블럭을 만들고 값을 꺼내는 코드를 적어주면된다.
이것이 재스퍼를 만나면
out.write("y의 값은: "); out.print(y);가 될것이다.
그런데 이것은 불편하다
y의 값은: <%=y%> 아까와 같은 내용이 추가가 된다.
4.코드블록의 종류4 : 선언부(Declaration)
<%
public int sum(int a, int b)
{
return a + b;
}
%>
메소드를 만들고 싶을때 코드블록을 만들면 에러가 난다.
왜? 이 메소드가 서비스 메소드에 들어가기때문임.
메소드안에 메소드를 정의할 수 없어서 구문 에러가 발생한다.
그렇다면 멤버 메소드를 만들고 싶은데 그럼 어떻게 해주나?
<%! %> !를 추가해주면 멤버에 들어가게 된다.
5.코드블록의 종류5 : 초기설정을 위한 Page 지시자
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding = "UTF-8" %>
이것들은 일반적으로 페이지 지시자라고 한다. 키 =값 으로 작성되는데 페이지를 어떠한 형태의 인코딩 컨텐트 타입이 무엇인지를 지시하는 것이다.
이 지시블록이 필요한 이유가 뭘까? 서블릿에서 프로그램만들때 출력하는데 우리가 UTF-8로하고 이것을 인코딩하는 것을 브라우저에게 지시했던 기억이있다.
과거에는 우리가 작성했던 코드를 코드블록안에 넣어서 처리했엇다.
<%
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
%>
그런데 이런것이 문제가 없어야하는데 애석하게도 에러가 발생하게 된다.
java.lang.illegalStateException: getOutputStream() has already been called for this response
이미 출력이 진행된다음 설정하는 것이 잘못된다. 이것들이 먼저 출력이 안되기때문이다.
페이지 지시자는 어떠한 코드보다도 설정이 먼저 진행되기 때문에 이것을 사용해야 된다.

42. JSP의 내장객체 간단히 알아보기

코드블록의 내장객체
int page = 3; 하면 Duplicate local variable page 에러가 발생한다.
나는 이 이름을 사용하지 않았는데 중복된다고 나온다? 왜일까
간과하지 말아야할 것은 이 코드블록 외에 코드가 있다는 것이다. 내가 모르는 코드가 있다는 것이다.
재스퍼가 서비스함수를 만들며 자기가 필요해서 만든 변수가 있다.
객체 형식을 가지고있는 변수들이다. 이것들은 다 내장객체이다.


이것들을 우리가 알고 있어야한다. 또한 우리가 JSP를 만들때 이것들을 활용할 수 있어야 한다.
대표적으로 request response같은 입력도구와 출력도구
application session 객체
페이지 내에서 어플리케이션 세션처럼 임시로 데이터를 저장할 수있는 pageContext 객체가있다.
위의 것들은 전역적으로 사용한다면 이것은 페이지 내에서 임시적으로 사용한다.
config out page객체를 참조하는 것들이잇다.

42.1 내장객체 HttpServletRequest 입력도구를 많이 사용해왔는데 사용하는 메소드는 다음과 같다.


사용자 전달한 파라미터 입력 등 쿠키얻기 메소드얻기 세션얻기 등등
사용자가 요청한 ip를 얻을때 getRemoteAddr()등도잇다. 헤더정보등도 얻을 수있다.

42.2 내장객체 HttpServletResponse 출력도구 도 많이 사용했다.


헤더 설정, 컨텍트 형식설정, url인코딩, 상태값 넣기 등이 있다.

42.3 내장객체 out javax.servlet.jsp.JspWriter


출력하거나 그럴때 사용하는데 직접 사용할일은 적다. 재스퍼가 알아서 해주기때문임.

42.4 내장객체 session


getAttribute(attr) / setAttribute(name,attr)등 값을 설정하거나 얻어내기
저장되는 시간들을 허용하기
removeAttribute(name)을 사용해서 세션에 설정한 속성값을 삭제하는 것들은 중요하다.
하나하나 외우는 것보다는 이런게 있었음을 알고 있기

42.5 내장객체 applcation : ServletContext


서블릿들이 사용하고 있는 문맥(context) 서블릿들이 사용하는 것을 얻어낼 수 있는 것
값을 설정하거나 값을 얻기 등등

43. JSP로 만드는 Hello 서블릿

jsp페이지에 일하는 방법을 배웠으니 초간단 페이지를 만들어보자.
처음 만들엇던 nana.java를 이용해서 만들어보자
nana.jsp를 만드는데 이것이 url이름으로 매핑되기때문에 소문자로 이름을 만들어주는 것이 좋다.
jsp라는 것이 html으르 출력하는 것이기때문에 기본적인 틀은 알아서 추가가된다.
<% for (int i = 0 ; i< 10 ; i++) {%>
안녕 Servlet!!<br >
<%}%>
전체를 담는게 안이라 줄을 나눠서 중괄호도 코드블록에 담아준다.
<%
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
String cnt_ = request.getParameter("cnt");
int cnt = 100;
if (cnt_ != null && !cnt_.equals("")) {
cnt = Integer.parseInt(cnt_);
}
for (int i = 0 ; i< cnt ; i++) {
out.println((i+1) + ": 안녕 Servlet!!
");
}
%>

원래대로라면 이런식으로 다 작성해야하지만 out은 이미 재스퍼에서 사용하고 있고
utf-8로 변환하는 과정은 페이지 지시자에서 설정을 했기때문에 필요없다.
이렇게 만들면? 우리는 코드블록만 책임지면 되서 출력이 많은 경우 많은 도움을 받을 수 있을 것이다.
장점도 많지만 요즘 단점이 더많아진다. 요즘 경향은 jsp사용을 정말 출력에 필요한 템플릿페이지로만 사용한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%    
String cnt_ = request.getParameter("cnt");
int cnt = 100;
if (cnt_ != null && !cnt_.equals("")) {
    cnt = Integer.parseInt(cnt_);
}
String[] result = new String[cnt];
for (int i = 0 ; i< result.length ; i++) {
    result[i] = "안녕 Servlet!!";
}
%> 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%=result %><br >
</body>
</html>

44. 스파게티 코드를 만드는 JSP

JSP를 만드는 방법은 정말 다양해서 이를 단순하게 만들수도 복잡하게 만들 수 도있다.
복잡하게 만들면 스파게티 코드이다. 이게 문제가 되는 이유를 알아보도록하자.

코드들을 나눠서 만들었을때 자바코드들만 모아서 볼 수가 없다. 어떤블록이 어디서 오류가 낫는지 어떤 블록들이 단일화되있는지 알기 어렵다.
관심있는 코드와 관심없는 코드가 섞여있으면 작업하기 매우 힘들다.
이런 코드를 지양하고 바람직하게 만들어야하고 그럴라면 얘들이 모여있어야 한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    int num = 0;
%>     

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<%
String num_ = request.getParameter("n");
if(num_ != null && !num_.equals("")){
    num = Integer.parseInt(num_);
}
%>
<body>
    <%if(num%2 != 0){%> 
    홀수입니다.
    <%}
    else
    {%> 
    짝수입니다.
    <%}%>
</body>
</html>

45. JSP MVC model1

스파게티 코드가 만들어지면 작업을 할때 매우 힘들다.
잘못만들면 코드블록이 복잡해지는 문제가 발생하게 된다.
코드블록이 흩어져있다. 이걸 간단하게 하는것이 MVC model1방식이다.
블록을 최소하하자는 것이다. 가능하면 코드들을 위에 몰아 넣고 밑에는 출력코드만 모아 놓기
업무로직은 윗 코드에서 보고 출력고치려면 밑단에서 보자는 것이다.
이 코드들을 한곳에 모으고싶다.


if문들이 위로올라갔다.
출력하기 위한 것을 변수에 넣었다.
이전 조건문에서는 출력을 제어했다면 이 모델에서는 데이터를 제어하는 것이다.
출력할 데이터를 만들고 출력할때는 쉽게 꽃아 넣는것임.
이렇게하면 코드들이 한곳에 모일수있고 코드블록이 줄어들 수있다.
앞으로 프로그램을 만들때 모델1처럼 만드는게 좋다. 데이터를 제어하는 것이 중요하다.
입력과 제어를 담당 : Controler[자바코드]
출력을 담당 : View[html코드]
출력데이터 : Model
->이래서 MVC 모델1이다. 자바코드와 출력코드를 최대한 분리하고 Model변수를 적절히 사용하는 것이다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    int num = 0;

    String num_ = request.getParameter("n");
    if(num_ != null && !num_.equals("")){
    num = Integer.parseInt(num_);
    }

    String result;

    if(num%2 != 0){
        result = "홀수";
    } else {
        result = "짝수";
    }
%> 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>

<body>
    <%=result%>입니다.
</body>
</html>

46. JSP MVC model1을 model2방식으로

model1 : 컨트롤러와 뷰가 물리적으로 분리되지 않은 방식. 페이지 1개에 작성을 했었다.
model2 : 컨트롤러와 뷰가 물리적으로 분리된 방식 View단만 사용자 요청에따라 서블릿으로 만들어지니 서블릿으로 만드는게 훨씬 줄어든다.
model2 는 Dispatcher를 집중화 하기 전의 모델
model2를 더발전시키면 다음과 같아진다.
컨트롤단에서 뷰를 연결하기 위해 포워딩하는 방법이 사용된다. 둘다 서블릿 서블릿에서 서블릿으로 연결하도록 이어지는게 포워딩이라는 것이다. 이 포워딩을 Dispatcher로한다.
그런데 페이지가 추가가되면 컨트롤러-뷰가 하나씩 추가되고 이것들이 각각 Dispatcher로 포워딩하게 되면 Dispatcher이 여러개 있는 것이 중복되는 것이므로 비효율적으로 보인다.
그래서 뷰와 소통하는 서블릿은 Dispatcher를 하나만두고 일반적인 업무로직인 Controller들은 별도의 POJO클래스 일반클래스로 만들어서 사용자 요청이 들어오면 Dispatcher가 적절한 컨트롤러를 작성하도록

이번에는 물리적으로 분리만 해보도록한다.
request.setAttribute("result", result);
redirect
현재작업과 관련없는 새로운요청
forward
현재작업한 내용을 이어갈수있도록 공유하는 것
RequestDispatcher dispatcher = request.getRequestDispatcher("spag3.jsp");
dispatcher.forward(request, response);
현재작업햇던 내용들을 답고있다면 jsp 서블릿에 이어지면 jsp에서 사용하는 request와 response가 이 서블릿의 것이다.
jsp에서 꺼내서 사용할수도있고 이용하면 포워드 새로요청하면 리디렉트
둘사이에 포워드하는 것은 request를 사용한다.

실행은 무조건 컨트롤러에서 한다.
데이터를 컨트롤러가 만들기때문임 뷰는 그냥 껍데기일뿐이다.
자바코드를 모두 몰아내기위해서는 EL을 배우면된다 다음시간에 배운다.

@WebServlet("/spag")
public class Spag extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    int num = 0;
    String num_ = request.getParameter("n");
    if(num_ != null && !num_.equals("")){
    num = Integer.parseInt(num_);
    }
    String result;

    if(num%2 != 0){
        result = "홀수";
    } else {
        result = "짝수";
    }

    request.setAttribute("result", result);
    //redirect
    //현재작업과 관련없는 새로운요청
    //forward
    //현재작업한 내용을 이어갈수있도록 공유하는 것
    RequestDispatcher dispatcher = request.getRequestDispatcher("spag3.jsp");
    dispatcher.forward(request, response);
    //현재작업햇던 내용들을 답고있다면 jsp 서블릿에 이어지면 jsp에서 사용하는 request와 response가 이 서블릿의 것이다.
    //jsp에서 꺼내서 사용할수도있고 이용하면 포워드 새로요청하면 리디렉트
    //둘사이에 포워드하는 것은 request를 사용한다.
    }}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<%
pageContext.setAttribute("result","hello");
%>

<body>
    <%=request.getAttribute("result")%>입니다.
</body>
</html>

47. EL(Expression Language)

JSP를 MVC를 만들려고할때 중요한 표기언어이다.
Controller request.setAttribute("cnt",30); -> View request.getAttribute("cnt")
그러나 View에서는 자바코드를 사용하지 않는게 MVC구현하는데 가장 좋은 방법이다.
이 값을 EL로 표기할 수 있다. ${cnt} 그 값을 꺼내서 출력까지 해준다.
저장소에서 값을 꺼내기 위해 복잡한 로직 사용x $ { } 에 넣기
좀더 복잡한데이터
List list = new ArrayList(){"1", "test"};
request.setAttribute("list", list);
-> ((List))request.getAttrilibute("list")).get(0)
무조건 객체로 뽑아주기때문에 get을 못쓴다. 그래서 List로 강제 타입변환도 해줘야한다.
${list[0]} 배열처럼 꺼낸다.
Map n = new HashMap("title", "제목");
request.setAttribute("n", n);
-> ((Map) request.getAttribute("n")).get("title")
-> ${n.title}

48. EL의 데이터 저장소

#{cnt} request라는 저장소에 담겨잇따. 사실 여기서만 검색하는 것은 아니다.
1.페이지 2.request 3.session 4.application에서 꺼내 사용할 수 있다.
request는 포워드를 통해 두개의 서블릿이 값을 공유할때 사용하는 저장소
페이지 JSP내에서 재스퍼가 만들어낸 객체 중 페이지 컨테스트 페이지내에서 사용할 수 잇는 서블릿객체들을 모아놓은것
이런애들이 페이지단위로 저장소 역할이 필요하면 저장소 역할을 할 수있는 객체
<%
pageContext.setAttribute("aa","hello");
%>
이것을 또 el을 사용해서 읽을 수 있다.
궁금한점 키워드를 가지고 값을 꺼내야한다. 4개의 객체에다가 우연치않게 같은 이름으로 넣엇을 경우 어떤 저장소에 있는걸 꺼내고 오나?
우선순위가 있다. page->request->session->appication순서이다.


이럴때 사용하는게 pageScope, requestScope, sessionScope, applicationScope으로 특정 저장소에서만 꺼내올 수있다.
${sessionScope.cnt} 이건 객체가 아니라 그냥 한정사임.
el표기는 사실 4대 저장소 이외에도 사용할 수 있는 객체가잇다.
보통 파라미터를 컨트롤러에서 얻는데 때에 따라 파라미터를 뷰단에서 얻을때도 있다.
${param.cnt} ${header.host} ${header["host"]}
header에 -같은게 들어가면 그냥 불러올수 없어서 []에 담아야한다.
header는 개발자도구 켜서 보기 accept는 브라우저 할때 내가 읽을 수있는 페이지타입등을 보여줌
pageContext 페이지 단위의 컨텍스트 저장소
<%=pageContext.getRequest().getMethod()%>
${pageContext.request.method}
객체를 사용하지만 메소드가 아닌것처럼 사용함.

@WebServlet("/spag")
public class Spag extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    int num = 0;
    String num_ = request.getParameter("n");
    if(num_ != null && !num_.equals("")){
    num = Integer.parseInt(num_);
    }
    String result;

    if(num%2 != 0){
        result = "홀수";
    } else {
        result = "짝수";
    }

    String[] names = {"newlec", "dragon"};
    request.setAttribute("names", names);

    Map<String, Object> notice = new HashMap<>();
    notice.put("id", 1);
    notice.put("title","el은좋아요");
    request.setAttribute("notice", notice);

    request.setAttribute("result", result);
    //forward
    RequestDispatcher dispatcher = request.getRequestDispatcher("spag3.jsp");
    dispatcher.forward(request, response);
    }}

 <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<%
pageContext.setAttribute("result","hello");
%>

<body>
    <%=request.getAttribute("result")%>입니다.
    <%-- ${result} <br > --%>
    ${requestScope.result} <br >
    ${names[0]} <br >
    ${notice.title} <br >
    ${result}<br >
    <%--${param.n}<br >--%>
    <%-- ${param.n gt 3}<br > --%>
    <%-- ${empty param.n?'값이비어있습니다.':param.n}<br > --%>
    ${param.n/2}<br >
    ${header.accept}

</body>
</html>

49. EL의 연산자


[] .
()
not ! empty
* / div % mod
+ -
< > <= >= lt(less than) gt(greater than) le ge
== != eq ne
&& and
|| or
? :
굳이 연산자를 lt gt이런걸 사용해야할까? html이 기본적으로 꺽은쇠를 가지고 있어서 안에다가 <>등을 사용하는 것은 오류를 유발할 수 있다.
쓸수없는 환경에서는 왠만하면 영어로 된거로 사용하자
${empty param.n} null이든 빈문자열이든 true로옴
${param.n == null || param.n == ""}
${empty param.n?'값이비어있습니다.':param.n} 3항연산자로 필요하면 값 나타내기
${param.n/2}<br > 1.5 문자열/2했는데 정수/ 정수 로해서 dobule값으로 나옴.

50. JSP 수업용 프로젝트 준비하기

사용자홈페이지
관리자페이지
회원가입 공지사항등록 공지사항조회
공지관리에 대한 기본적인 방식 배우기
db사용할것임.

51. JSP를 이용한 자바 웹프로그래밍 시작하기

1.JSP로 만드는 이유 2. JSP이용하는 방법
1.JSP로 만드는 이유
출력내용이 정적인것을직접 작성해줘야한다. 비효율적이니 재스퍼로 사용해서 필요한 코드만 하는게 좋다.
JSP파일에 코드블록을 적절하게 넣어서 잘 사용할 수 있느냐가 JSP이용하는 방법이다.
확장자는 JSP지만 결국만드는것은 서블릿이다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
페이지 지시자 꼭넣어주자
db로 데이터를 가져올 것임.

52. JDBC를 이용해 글 목록 구현하기

String sql = "SELECT * FROM NOITCE";
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/orcl", "java", "oracle");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
jsp파일에서 임포트하는방법 컨트롤 스페이스 눌러서 골라주면된다.
라이브러리를 같이 배포해야하니 WEB-INF lib에 같이 담아서 포함시켜줘야한다.
https://webstone.tistory.com/56
preparedStatement vs Statment 차이 내가 배웠던거랑 여기서 처음보는 것 차이
Statement는 executeQuery() 나 executeUpdate() 를 실행하는 시점에 파라미터로 SQL문을 전달
SQL문을 수행하는 과정에서 매번 컴파일을 하기 때문에 Prepared Statement에 비해 효율성이 떨어진다 .
값을 채우려면 전자 그냥 보여주기만 할거면 후자 사용 그냥 Statement는 실행용도로만 사용하는것.

<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
String url = "jdbc:oracle:thin:@localhost:1521/orcl";
String sql = "SELECT * FROM NOTICE";
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection( url, "java", "oracle");
//Statement st = con.createStatement();
PreparedStatement st = con.prepareStatement(sql);
ResultSet rs = st.executeQuery();
%>

<tbody>
  <%while(rs.next()) {%>        
   <tr>
    <td><%=rs.getInt("ID")%></td>
    <td class="title indent text-align-left"><a href="detail?id=<%=rs.getInt("ID")%>"><%= rs.getString("TITLE")%></a></td>
       <td><%=rs.getString("WRITER_ID")%></td>
       <td>
    <%=rs.getDate("REGDATE")%>    
    </td>
    <td><%=rs.getInt("HIT")%></td>
    </tr>
    <%} %>        
</tbody>

53. 자세한 페이지 구현하기

db에있는 데이터를 가져다가 목록페이지를 구현했다. 초기버전을 구현해봣다.
구현할 내용은 자세한 페이지이다. 자게한 페이지라는 것은 들어가면 내용이 나오도록하는 것임.
detail.html에 만들것임.
바람직한 코드를 만드는 것을 배우고자한다.
주의할점1.목록을 클릭해서 넘어갓을때 detail.jsp?쿼리값 id에따라서 달라진다.
id값을 전달하지 않으면 보여줄게 없어서 오류가 날것임 이값을 어떻게 심을수 잇을가?
제목 하이퍼링크에 추가함. <a href="detail.jsp?id=<%=rs.getInt("ID")%>">
=값뒤에는 ID값이 오도록 해주기

<%
int id = Integer.parseInt(request.getParameter("id"));

String url = "jdbc:oracle:thin:@localhost:1521/orcl";
String sql = "SELECT * FROM NOTICE WHERE ID=?";
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection( url, "java", "oracle");
PreparedStatement st = con.prepareStatement(sql);
st.setInt(1, id);
ResultSet rs = st.executeQuery();
rs.next();
%>

<tbody>
<tr>
<th>제목</th>
    <td class="text-align-left text-indent text-strong text-orange" colspan="3"><%= rs.getString("TITLE") %></td>
</tr>
<tr>
    <th>작성일</th>
    <td class="text-align-left text-indent" colspan="3"><%= rs.getDate("REGDATE") %></td>
</tr>
<tr>
    <th>작성자</th>
    <td><%= rs.getString("WRITER_ID") %></td>
    <th>조회수</th>
    <td><%= rs.getInt("HIT") %></td>
</tr>
<tr>
    <th>첨부파일</th>
    <td colspan="3"><%= rs.getString("FILES") %></td>
</tr>
<tr class="content">
    <td colspan="4"><%= rs.getString("CONTENT") %></td>
</tr>
</tbody>

54. 자세한페이지 MVC model1으로 변경하기

지금 작성한것은 일명 스파게티 코드이다.
한번꼬이면 전부다 하나씩 찾아봐야하기때문에 유지보수가 어렵다.
코드에서 꽃아놓을 수있는 최소한의 변수만 남겨놓으면된다.
화면 밑단에서 사용할 변수인 model을 만들고 넣어준다.

<%
int id = Integer.parseInt(request.getParameter("id"));

String url = "jdbc:oracle:thin:@localhost:1521/orcl";
String sql = "SELECT * FROM NOTICE WHERE ID=?";
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection( url, "java", "oracle");
PreparedStatement st = con.prepareStatement(sql);
st.setInt(1, id);
ResultSet rs = st.executeQuery();

rs.next();
String title = rs.getString("TITLE");
Date regdate = rs.getDate("REGDATE") ;
String writerId= rs.getString("WRITER_ID");
int hit = rs.getInt("HIT") ;
String files = rs.getString("FILES");
String content = rs.getString("CONTENT") ;


rs.close();
st.close();
con.close();
%>

 <table class="table">
    <tbody>
        <tr>
            <th>제목</th>
            <td class="text-align-left text-indent text-strong text-orange" colspan="3"><%= title %></td>
        </tr>
        <tr>
            <th>작성일</th>
            <td class="text-align-left text-indent" colspan="3"><%= regdate %></td>
        </tr>
        <tr>
            <th>작성자</th>
            <td><%= writerId %></td>
            <th>조회수</th>
            <td><%= hit %></td>
        </tr>
        <tr>
            <th>첨부파일</th>
            <td colspan="3"><%= files %></td>
        </tr>
        <tr class="content">
            <td colspan="4"><%= content %></td>
        </tr>
    </tbody>
</table>

55. 자세한페이지 MVC model2로 변경하기

아예물리적으로 나누기
입력처리(Contril)(서블릿) - model - 문서츌력(View)(JSP)
나눠서 만들면 개별적으로 유지관리가 가능, 협업도 가능 재사용시 각각 재사용가능하다.
실행면에서도 jsp는 컴파일 하는과정을 해야하는데 굉장히 커다란 덩치인데 줄일 수 있다. 실행성능에 영향
이 model이 가능한것은 pageContext / request / session /application
중에서 뒤에 3가지이다. 제일적합한것은 범위가 가장좁은 request이다.
입력도구인데 입력도구에다가 저장소로도 사용할 수 있다.

필요한것 1.흐름전이 2.데이터 모델로 보내기
서블릿에서 서블릿으로 전이
//redirect
현재작업과 관련없는 새로운요청
//forward
현재작업한 내용을 이어갈수있도록 공유하는 것
현재작업햇던 내용들을 답고있다면 jsp 서블릿에 이어지면 jsp에서 사용하는 request와 response가 이 서블릿의 것이다.
jsp에서 꺼내서 사용할수도있고 이용하면 포워드 새로요청하면 리디렉트
둘사이에 포워드하는 것은 request를 사용한다.
list에서여는데 매핑을 햇으니 그냥 detail로 열어야함.
<a href="detail?id=<%=rs.getInt("ID")%>">

현장에선 이걸 자주 쓴다. 익숙해질 필요가 있다.

@WebServlet("/notice/detail")
public class NoticeDetailController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {    
        int id = Integer.parseInt(request.getParameter("id"));

        String url = "jdbc:oracle:thin:@localhost:1521/orcl";
        String sql = "SELECT * FROM NOTICE WHERE ID=?";
        Class.forName("oracle.jdbc.OracleDriver");
        Connection con = DriverManager.getConnection( url, "java", "oracle");
        PreparedStatement st = con.prepareStatement(sql);
        st.setInt(1, id);
        ResultSet rs = st.executeQuery();

        rs.next();
        String title = rs.getString("TITLE");
        Date regdate = rs.getDate("REGDATE") ;
        String writerId= rs.getString("WRITER_ID");
        int hit = rs.getInt("HIT") ;
        String files = rs.getString("FILES");
        String content = rs.getString("CONTENT") ;

        request.setAttribute("title", title);
        request.setAttribute("writerId", writerId);
        request.setAttribute("regdate", regdate);
        request.setAttribute("hit", hit);
        request.setAttribute("files", files);
        request.setAttribute("content", content);

        RequestDispatcher dispatcher = request.getRequestDispatcher("/notice/detail.jsp");
        dispatcher.forward(request, response);

        rs.close();
        st.close();
        con.close();
    } catch (Exception e){
        e.getStackTrace();
    }}}

<tr>
    <th>제목</th>
    <td class="text-align-left text-indent text-strong text-orange" colspan="3"><%= request.getAttribute("title") %></td>
</tr>
<tr>
    <th>작성일</th>
    <td class="text-align-left text-indent" colspan="3"><%= request.getAttribute("regdate") %>
    </td>
</tr>
<tr>
    <th>작성자</th>
    <td><%= request.getAttribute("writerId") %></td>
    <th>조회수</th>
    <td><%= request.getAttribute("hit") %></td>
</tr>
<tr>
    <th>첨부파일</th>
    <td colspan="3"><%= request.getAttribute("files") %></td>
</tr>
    <tr class="content">
    <td colspan="4"><%= request.getAttribute("content") %></td>
</tr>

2023.01.02 후기

JSP를 이용해서 홈페이지를 구현한다.
HTML은 이미 짜져있는 것이지만 자바를 공부할때 만들었던 게시판 기능을 이용해서 만들어서 맥락 상으로 비슷해서 어렵지는 않았다.
MVC가 무엇인지 왜 사용하는지를 잘 배울 수 있어서 좋았다.
중요한 것은 꺾이지 않는 마음!

'기초단계 > JSP&Servlet' 카테고리의 다른 글

2023.01.04 JSP & Servlet  (0) 2023.01.05
2023.01.03 JSP & Servlet  (1) 2023.01.03
2022.12.31 JSP & Servlet  (0) 2022.12.31
2022.12.30 JSP & Servlet  (0) 2022.12.30
2022.12.29 JSP & Servlet  (0) 2022.12.30

+ Recent posts