51일차

JSP 점점 자바코드가 없는 것을 만들고 있다.
JSP에는 HTML만남기면 자바코드는 어디로 가야하나? 서블릿으로 가야한다.
그래서 패턴이 나온다.
일하는 곳, 보여주는 곳을 분리하는 패턴이 나온다. 책 518P
MVC패턴이 나온다.
실제 업무 처리하는 코드와 화면에 보여주기 위한 코드를 분리하는 것이다.
DB에서 값 꺼내오기 등등 비지니스 로직을 따로 뺀다..
지금까지 배운 것은 보여주기 위한 view를 배운 것이다.

view에게 이걸 보여줘 하는게 모델이다 모델을 request의 attribute를 쓸것이다.
서블릿이 다른 서블릿한테 일시킬때 request를 보내면 같은 request를 쓰는 것이다.
모델을 담아서 보내주는 것이다.

이과정을 쉽게 만드는것을 스프링 MVC인것이다.
서블릿만 사용하면 좀 불편하다.

17. 서블릿

서블릿은 HttpServlet을 상속받는다.
우리가 만든것은 톰캣위에서 돌아가기 때문에 톰캣이 안전하게 실행시키기 위해 상속받고 있다.
톰캣은 HttpServlet의 메소드를 상속받고 잇다는게 보장되어 재정의된 것을 실행시킨다.

doGet doPost doPut doDelete등의 메소드를 가지고 있다.
http요청은 get방식 post방식으로 나뉘는데 각각 요청에 따라 실행된다.
실제로 이 메소드를 재정의해서 사용하게 된다.

get방식 요청을 받으면 서블릿의 doGet메소드가 실행되게 된다.
주소로 요청을 해야하는데 주소를 어떻게 요청해야하냐면 어노테이션에서 지정된 url로 요청하면된다.

http://localhost:8080/JSP2023/Servlet01
ip:포트번호/contextpath/서블릿이름으로 요청하게 된다.

@WebServlet("/Servlet01")
public class Servlet01 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet01() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get요청 받음");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

17.1 서블릿 foward

서블릿이 받고 jsp로 포워드 시키는 것이다. 포워드 시킬때 모델에 붙여서 보내는 것이다.
클라이언트 입장에서는 첫 요청할때 주소만 나오기때문에 jsp가 일한지 모른다.

request.getRequestDispatcher(view).forward(request, response);

사용문구처럼 알고 잇어야한다.
첫요청을 받은 후 서블릿이 일한 후 view로 포워드 하게 된다.
하지만 클라이언트는 첫 요청이 하나의 요청이기 때문에 jsp가 일했다는 것을 알지 못한다.

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    System.out.println("서블릿 03 일함");
    //비즈니스 로직처리

    //모델에 값 담기(request attribute)

    // view로 포워딩
    String view = "/ch17/lecture/view01.jsp";
    request.getRequestDispatcher(view).forward(request, response);;
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>여기는 view01.jsp</h1>
</body>
</html>

17.2 서블릿 foward연습

서블릿이름 Servlet04
요청경로 /lec/sample04
서블릿하는일 /ch17/lecture/view02.jsp로 포워드

@WebServlet("/lec/sample04")
public class Servlet04 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet04() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("4번 서블릿 일함");

        // /ch17/lecture/view01.jsp
        RequestDispatcher dis = request.getRequestDispatcher("/ch17/lecture/view02.jsp");
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

17.3 request setatrribute

서블릿은 session, request로 foward할 수 있다.
session은 스레드 safe하지 않아서 request를 위주로 사용하는 것이 좋다.
우리가 만든 서블릿은 같은경로로 여러개 요청이 된다.
서블릿객체는 하나 만들어지고 여러스레드에서 각각 호출하게 된다.
여러 스레드에서 각각의 reqeust를 가지고 있지만 여러스레드의 세션은 같을 수도 있다.

view로 포워드할때 doGet메소드가 가지고 있는 request와 response를 그대로 건네준다.
그래서 view에서 같은 request를 사용하게 된다.
우리가 반복적으로 했던 것이 jsp에서 attribute를 꺼내는 것이었다.
jsp에서는 EL로 꺼내서 사용하면된다.
jsp는 이제 거의 받은 데이터를 보여주는 일만한다.

@WebServlet("/lec/sample05")
public class Servlet05 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet05() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 비즈니스 로직 실행

        // request attribute 추가 (모델에 데이터 담기)
        request.setAttribute("result", "일한 결과 데이터");

        // view로 포워드
        String view = "/ch17/lecture/view03.jsp";
        RequestDispatcher dis = request.getRequestDispatcher(view);
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}    

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>여기는 view03.jsp</h1>
    <p>보여줄 데이터: ${requestScope.result}</p>
    <p>보여줄 데이터: ${result}</p>
</body>
</html>

17.4 reqeust - 2

/lec/sample06으로 요청 오면 Servlet06의 doGet메소드 실행하고
res 이름의 request attribute 추가한 후 view04.jsp로 포워드하기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- /lec/sample06으로 요청 오면
    Servlet06의 doGet메소드 실행
    res 이름의 request attribute 추가
    이 jsp로 포워드 -->
    <h1>4번 jsp</h1>
    <h1>보여줄 데이터 : ${requestScope.res}</h1>
    <h1>보여줄 데이터 : ${res}</h1>
</body>
</html>

@WebServlet("/lec/sample06")
public class Servlet06 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet06() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("res", "👍👍👍👍👍👍👍👍");

        RequestDispatcher dis = request.getRequestDispatcher("/ch17/lecture/view04.jsp");
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

17.5 JSP 은닉

업무를 나누기로 결정했다.
요청은 서블릿이 받는다. 요청을 바로 jsp로 바로 보내도 되긴한다.
하지만 이런 패턴에서는 적절하지 않다. 건네주고 보여주는 역할만 하기 때문이다.
그래서 보여줄 데이터가 없기때문에 바로 요청하지 못하게 하고 싶다.
그래서 JSP를 숨기면 좋겠다.
지금까지 작성한것은 webapp에 작성햇는데 여기는 다보인다.
webapp안에는 META-INF와 WEB-INF폴더가 있는데 여기에는 밖에서 접근하지 못한다.
특히나 WEB-INF를 많이 사용한다. 그래서 JSP를 여기에 작성하도록 하자.

이 파일안에 넣으면 직접 jsp파일을 요청할때 직접 요청이 안된다.
무조건 서블릿을 통해서 요청해야만 데이터를 포워드받은 jsp가 보이게 된다.

@WebServlet("/lec/sample07")
public class Servlet07 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet07() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //business logic

        //add attribute
        request.setAttribute("result", List.of("java", "spring", "css"));

        //forward
        String view = "/WEB-INF/view/ch17/view05.jsp";
        RequestDispatcher dis = request.getRequestDispatcher(view);
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>5번 jsp</h1>
    <ul>
        <c:forEach items="${result }" var="item">
            <li>${item}</li>
        </c:forEach>
    </ul>
</body>
</html>

17.6 JSP 은닉 - 2 연습

/lec/sample08로 요청시 view06.jsp가 응답할 수 있도록 코드를 작성해보자.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- /lec/sample08로 요청시 이 jsp가 응답할 수 있도록  -->
    <h1>6번 jsp</h1>
    <ul>
        <c:forEach items="${mylist}" var="elem">
            <li>${elem}</li>
        </c:forEach>
    </ul>
</body>
</html>

@WebServlet("/lec/sample08")
public class Servlet08 extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Servlet08() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<String> list = new ArrayList<>();
        list.add("집에 가서 할일");
        list.add("도시락 통 꺼내 놓기");
        list.add("노트북 정리하기");
        list.add("취미 생활 하기");
        list.add("처 자기");

        request.setAttribute("mylist", list);

        String view = "/WEB-INF/view/ch17/view06.jsp";
        RequestDispatcher dis = request.getRequestDispatcher(view);
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

17.7 business logic

db에 값을 저장하거나 db의 값을 꺼내오거나
데이터를 만들거나 데이터를 읽거나 데이터를 수정하거나 등등
create read update delete
묶어서 crud라고 한다.

db와 연결을 안햇으니 흉내만 내보자. 이런일을 하는구나라고만 알고 코드자체는 알지 말자.
한줄로 간단하게 작성했지만 나중에 db에서 꺼내오면 길어질것이다.
db대신 세션에서 데이터를 가져와보도록 하자

세션에 넣어서 해서 복잡한 코드가 되어서 헷갈린다.
서블릿이 요청받아서 파라미터 읽어서 로직처리하고 attribute담아서 foward나 redirect해서 view에 데이터를 보내주는 역할을 한 것이다.

@WebServlet("/lec/sample09")
public class Servlet09 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //business logic
        // 데이터베이스에서 목록 가져오기
        //db대신 세션에서 가져오기
        HttpSession session = request.getSession();
        Object data = session.getAttribute("db");
        //List<String> players = List.of("서태웅", "강백호", "채치수");

        //add attribute
        request.setAttribute("players", data);

        //forward / redirect
        String view = "/WEB-INF/view/ch17/view07.jsp";
        RequestDispatcher dis = request.getRequestDispatcher(view);
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

@WebServlet("/lec/sample10")
public class Servlet10 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String view = "/WEB-INF/view/ch17/view08.jsp";
        RequestDispatcher dis = request.getRequestDispatcher(view);
        dis.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("포스트 요청 받음");

        //request파라미터 값 꺼내기
        String name = request.getParameter("name");

        //business logic
        //db에 이름추가 (session으로 간단히 흉내)
        HttpSession session = request.getSession();
        Object o = session.getAttribute("db");
        if (o == null) {
            o = new ArrayList<String>();
            session.setAttribute("db", o);
        }
        List<String> list = (List<String>) o;
        list.add(name);

        //add attribute

        //forward / redirect
        String location = request.getContextPath() + "/lec/sample09";
        response.sendRedirect(location);
    }
}

17.7 business logic- 2

수정 삭제하는 기능을 추가해보자.
수정을 하기 위해서는 list의 index를 받을 필요가 있다.
js코드로 목록을 누르면 input박스의 value에 이름이 들어가게 해주자.
index도 같이 hidden으로 전달되게 하자.
name은 수정버튼을 누를때 이름으로 바뀌고 index는 hidden으로 가니그대로 전달이된다.
각 파라미터를 받고 list.set을 하면 수정이 되게 된다.

<div>
    <c:url value="/lec/sample11"  var="updateUrl"/>
</div>    
<h1>선수 이름 수정</h1>
<form action="${updateUrl}" method="post">
    <input type="hidden" name="index" id="input2" />
    <input type="text" id="input1" name="name" />
    <input type="submit" value="수정" />
</form>

<script>
    $("li").click(function () {
        const name = $(this).text();
        const index = $("li").index(this);
        $("#input1").val(name);
        $("#input2").val(index);
    });
</script>

@WebServlet("/lec/sample11")
public class Servlet11 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // request파라미터 값 꺼내기
        String name = request.getParameter("name");
        String index_ = request.getParameter("index");
        int index = Integer.parseInt(index_);

        // business logic
        // db에 이름수정 (session으로 간단히 흉내)
        HttpSession session = request.getSession();
        List<String> db  = (List<String>) session.getAttribute("db");
        db.set(index, name);

        // add attribute

        // forward / redirect
        String location = request.getContextPath() + "/lec/sample09";
        response.sendRedirect(location);
    }
}

17.8 business logic- 3

삭제하는 기능 추가해보자.
이전과 같은 방식으로 index를 얻어오자.
이름은 파라미터로 받을 필요가 없지만 보여주기 위해서 설정하자.
강의 듣기 이전 혼자서 풀어보았다.
서블릿은 재사용을 위해 기능별로 나눠야한다. 여러일을 처리하지 않도록 주의하자.
강의에서는 다음주에 할 예정

@WebServlet("/lec/sample12")
public class Servlet12 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // request파라미터 값 꺼내기
        String index_ = request.getParameter("index");
        int index = Integer.parseInt(index_);

        // business logic
        // db에 이름수정 (session으로 간단히 흉내)
        HttpSession session = request.getSession();
        List<String> db  = (List<String>) session.getAttribute("db");
        db.remove(index);

        // add attribute

        // forward / redirect
        String location = request.getContextPath() + "/lec/sample09";
        response.sendRedirect(location);
    }
}

2023.04.07

WEB-INF에 은닉하면 왜 안보이는지 잘 이해를 못햇엇는데 이해를 하게 되었다.
서브릿을 통해서 VIEW페이지를 불러오는 것을 이해하게 되었다.
뉴렉처 강의때 서블릿으로가서 요청하는게 귀찮아서 페이크 폴더를 만들었던게 기억난다.
서블릿매핑과 jsp이름을 비슷하게 지어서 헷갈리게 이해햇던 것 같다.

뜬금없이 aws 배포를 배우게 되었다.
나중에 실제 사용할때 따로 또 알아보도록 하자.
1년후에 빌린 서버 유료되니 그전에 끊도록하자 주의하자!
2023.04.07 영상보면서 복습
가상컴퓨터 설정 나중에 보기

가상컴퓨터에 톰캣 10.0인데 월요일에 10.1버전으로 바꿀예정이다.
+ 서블릿 지우는 기능 올려서 서비스 해보기
월요일에 남은것 하고 스프링하면서 jdbc할 예정이다.

그래도 독학하는 부분은 jsp마무리하고 스프링 기본부터 같이 보면서 공부하는게 나을 듯..!
정신 바짝 차려야할 것 같다. 갑자기 진도가 매우 빨라진 느낌이다.

'국비 > JSP' 카테고리의 다른 글

2023.04.10 52일차 JSP  (0) 2023.04.10
2023.04.07 51일차 JSP - 2  (0) 2023.04.07
2023.04.06 50일차 JSP  (0) 2023.04.06
2023.04.05 49일차 JSP  (0) 2023.04.05
2023.04.04 48일차 JSP  (5) 2023.04.04

+ Recent posts