JSP & Servlet

15. GET요청과 쿼리 스트링

출력방법
사용자입력이라는 것은 요청할때 입력이 이루어진다. 요청과 입력은 뗄레야 뗄수가없다.
요청할때 전달하는 값을 우리가 어떻게 받을 것인지가 중요하다.
사용자 요청에 가장 기본적인것은 GET요청이다.
기본적으로 웹이라는 것은 클라이언트가 웹브라우저로 요청을 한다. 문서를 요청한다.
logcalhost/hello -> get
logcalhost/hello?cnt=3 -> get ?를쓰고 키값에 해당되는 값을 전달할수있다.
이것을 쿼리 스트링이라고 한다. 예를들어 커피를 시키는데 샷추가해주세요 같은 것이다.
추가적으로 옵션을 읽어서 옵션에 맞는 웹페이지를 제공해야한다.
전달하지않으면 100번 아니면 3번
이전까진 response출력도구만 사용했지만 이번에는 request입력도구 사용하기
request의 getParameter()메소드 사용
int cnt = Integer.parseInt(request.getParameter("cnt"));
무조건 문자열로 받기때문에 정수로 쓰고싶다면 타입변환 해줘야한다.

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();

    int cnt = Integer.parseInt(request.getParameter("cnt"));

    for (int i = 0 ; i< cnt ; i++) {
        out.println((i+1) + ": 안녕 Servlet!!<br >");
    }
}

16. 기본값 사용하기

입력값이 만약 전달이 안되면 오류가 생긴다. 그래서 기본값이 필요하다.
4가지 경우가 있다.
logcalhost/hello/?cnt=3 -> "3"
logcalhost/hello/?cnt= -> " "
logcalhost/hello/? -> null
logcalhost/hello -> null
각각에 기본값을 넣어줘야함.

String cnt\_ = request.getParameter("cnt");  
int cnt = 100; //null일경우에는 100  
if (cnt\_ != null && !cnt\_.equals("")) { //null이 아니거나 공백일경우  
cnt = Integer.parseInt(cnt\_);  
}

그런데 사용자가 주소창에다가 요청을 한다? 그럴일이 없다.
하이퍼링크에 넣어줘보자

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    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!!<br >");
    }}

17. 사용자 입력을 통한 get요청

이전에는 하이퍼링크에 고정된값이엇지만 get 요청을 할때 값을 사용자가 입력할 수 있도록 해보자.
사용자가 입력할 수 있는 입력 폼을 준비해야한다.
name="cnt" 입력하고 클릭 -? get hello?cnt=3 -> hello문서생성 ->응답
html에 사용자 폼태그를 만들어줘야함.
from안에 사용자 요청을 하는 인풋과 요청을 전달하는 submit버튼이 필요하다.
action에 매핑주소를 적어준다.
submit누르면 hi에게 요청이간다 브라우저가 이 액션명을보고 url을 작성하고 name에 키값으로 쿼리스트림을 만들어주게 되어 요청이된다.

18. 입력할 내용이 많은 경우에는 POST요청

입력값이 많은 경우가 있다.
주문할때 옵션이 많다면 다 기억하기 힘들다.
여러가지 주문 -> post ->요청처리
게시물을 입력하거나 업무로 많이 할수있을경우 한번에 get으로 불가능하다.
처음에는 입력폼을 받기 위한 get요청을 하고 결과를 다시 post한다.

<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Insert title here</title>
    <form action = "notice-reg">
        <div>
            <label>제목:</label><input name="title" type="text">
        </div>
        <div>
            <label>내용:</label>
            <textarea name="content"></textarea>
        </div>
        <div>
            <input type = "submit" value="등록"/>
        </div>
</head>
<body>
</body>
</html>

제목을 입력받는 공간, 내용을 입력받는 공간이 있다.
이것에 대한 서블릿이 필요하게 된다. notice-reg서블릿을 작성해주자.

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    request.setCharacterEncoding("UTF-8");
    PrintWriter out = response.getWriter();

    String title = request.getParameter("title");
    String content = request.getParameter("content");

    out.println(title);
    out.println(content);}

개발자도구를 보면 어떻게 내용이 들어왔는지 알 수 있다.


폼데이터 보기

19. 한글입력문제

한글이 전달되는 것을 서버에서 받지 못하는 문제 서버에서 출력하면서 한글이 깨진건지? 전달할때 깨진건지 알아야한다.
그러나 이전에 출력에 대해서는 한글 문제를 해결했기 때문에 전달할때 문제가 발생한 것이라고 할 수 있다.
UTF-8는 멀티바이트 문자이다. 문자 하나당 영문자 1바이트 한글 중 일 2바이트

입력 UTF-8 -> POST -> URL Ecoding할때 2바이트씩 했지만 웹서버에서 읽을때 2바이트를 1바이트씩 ISO-8859-1로 읽음
읽을때 "UTF-8"로 읽어달라
request.setCharacterEncoding("UTF-8")라고 써줘야한다.
만약 이게 귀찮으면?
톰캣 환경설정의 서버.XML 커넥터에 코딩방식을 UTF-8로 바꿔버리기

그런데 톰캣서버는 여러개의 서비스를 돌리기때문에 보통 마음대로 바꾸지 않는다.
그래서 서버에서 인코딩이 필요하면 그 서버에서만 한다.

20. 서블릿 필터

웹서버 <-> WAS ->request servlet container
서블릿을 실행하면 메모리상에 존재하게 되는데 이공간을 servlet container라고한다.
여기에 담아두고 다시 웹서버에 보내준다.
request.setCharacterEncoding("UTF-8");을했엇는데 우리는 한글을 사용하니까 압력받을때는 무조건해줘야한다.
그러면 귀찮으니 서버.XML을 바꾸면? 위에서 언급햇듯이 다른 서버들도 영향을 받으니 안고치는게 낫다.
그러나 서블릿마다 작업하는 것은 귀찮으니 요청과 응답사이에 Filter를 만들어줘서 먼저실행이 된후 서블릿이 실행
그리고 filter가 다시 응답을 보낼때 실행할지 안할지를 정해주고 보내준다.
또한 인증이나 권한이 있는지 권한을 줄까말까의 일도 하게 된다.
이것을 한번만 설정하게 되면 다른 서블릿들에도 영향을 받게할 수 있다.
사전과 사후에 필요한 처리가 있다면은 filter를 이용해서 할 수 있게 되는 것이다.

filter패키지를 따로 만들고 CharacterEncoingFilter 클래스를 생성해준다.
만들때 인터페이스 filter를 구현하도록 넣어준다.

이 필터를 만들고나면 설정만하면 자동으로 작동한다. 톰캣이 처음실행할때, 요청이 올때마다 출력된다.

web.xml을 가서 설정해줘야한다. 서블릿을 매핑하듯이 만들어주면된다.

<filter>
    <filter-name>CharacterEncoingFilter</filter-name>
    <filter-class>com.newlecture.filter.CharacterEncoingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterEncoingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

특정 url만 작성할수도 있고 모든거에 적용하려면 저렇게 표시해준다.
설정이 끝나고 무조건 뭔가 요청하게 되면 이것이 실행이된다.

@WebFilter("/*")
public class CharacterEncoingFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    //System.out.println("before filter");
    request.setCharacterEncoding("UTF-8");
    chain.doFilter(request, response);
    //System.out.println("after filter");}}

System.out.println("before filter");
chain.doFilter(request, response);
System.out.println("after filter");
요청이 오면 흐름을 넘기는 거임. 사전검사를 하면 위에것을 하고 사후검사를 하고 아래것을 출력해줌.
서블릿이 실행되기전이면 위에적고 실행후에 응답할대 필요하면 아래에 작성해줌.

이것또한 web.xml을 설정하는 것이아니라 어노테이션으로 설정할 수도잇다.
@WebFilter("/*")
설정방법이 매우 쉬워지고 불필요한 작업을 줄일 수있다.

21. 학습과제(사용자 입력을 통한 계산요청)

연산을 하던 처리를 하던 해주기
숫자 두개를 입력받아 전달하게 하기
1.폼달라고 하기 2.숫자입력해서 계산하기 3.add문서 덧셈의 결과를 주기
이전에 강의에서 폼을 만들때 method를 안넣었는데 이번에 넣으셔서 찾아보았다.
<form action = "add" method="post">
https://www.w3schools.com/tags/ref_httpmethods.asp
https://velog.io/@ye050425/html-form-%EC%A0%95%EB%A6%AC
기본 method는 get이고 서버주소창에 컨텐츠가 다보이게 된다.
http://localhost:8080/notice-reg?title=1&content=1
post는 한번에 보내는거라 그렇지 않고 그냥 서블릿 이름만 보이게된다.
http://localhost:8080/add

22. 과제 체크

1.보낼때 '문자열'로 보내게되니 숫자로 변환해주기
2.혼자만의 해결할만한 시간을 가져보았느냐
를 보기 위해 주어진 과제이다.
서블릿을 만들때 그냥 클래스를 만드는 게아니라 servlet을 생성하는 방법도 있다.
어노테이션을 추가할 수 있고 알아서 메소드 오버라이딩도 해준다.
사용자 입력 할때 빈문자열이 올수도 있으니 기본값을 제공해주자.

<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Insert title here</title>
    <form action = "add" method="post">
        <div>
            <label>x:</label>
            <input name="x" type="text" />
        </div>
        <div>
            <label>y:</label>
            <input name="y" type="text" />
        </div>
        <div>
            <input type = "submit" value="덧셈"/>
        </div>
        <div>
            결과 : 0
        </div>

</head>
<body>
</body>
</html>

@WebServlet("/add")
public class Add extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();

    /*
    int x = Integer.parseInt( request.getParameter("x"));
    int y = Integer.parseInt( request.getParameter("y"));

    out.println("덧셈 결과: " +  (x + y) );
    */

    String x_ = request.getParameter("x");
    String y_ = request.getParameter("y");

    int x = 0;
    int y = 0;

    if(!x_.equals("")) {
        x =Integer.parseInt(x_);
    }
    if(!y_.equals("")) {
        y =Integer.parseInt(y_);
    }

    int result = x + y;
    //response.getWriter().printf("result is %d\n", result);
    response.getWriter().println("덧셈 결과: " + result);
}}

23. 여러개의 submit 버튼 사용하기

간단한계산기프로그램을 여러개의 submit로 여러개의 처리를 하기
덧셈과 뺄셈을 모두 가능하게 하고싶다. 그런데 전달되는 덧셈과 뺄셈을 어떻게 식별을 하나?
먼저 버튼을 두개 만들어준다. 그런데 이것을 어떻게 식별할 것인가?
개발자 도구로 각 버튼을 눌렀을 때 처리 되는 것을 보자
<input type = "submit" name="operator" value="덧셈"/>
<input type = "submit" name="operator" value="뺄셈"/>
버튼에 이름을 추가해주고 개발자도구에서 보면 어떤 버튼이 눌렸는지 구분이 되게된다.

<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Insert title here</title>
    <form action = "calc" method="post">
        <div>
            <label>x:</label>
            <input name="x" type="text" />
        </div>
        <div>
            <label>y:</label>
            <input name="y" type="text" />
        </div>
        <div>
            <input type = "submit" name="operator" value="덧셈"/>
            <input type = "submit" name="operator" value="뺄셈"/>
        </div>
        <div>
            결과 : 0
        </div>

</head>
<body>
</body>
</html>

@WebServlet("/calc")
public class Calc extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();

    String x_ = request.getParameter("x");
    String y_ = request.getParameter("y");
    String op = request.getParameter("operator");

    int x = 0;
    int y = 0;

    if(!x_.equals("")) {
        x =Integer.parseInt(x_);
    }
    if(!y_.equals("")) {
        y =Integer.parseInt(y_);
    }

    int result = 0;
    if(op.equals("덧셈")) {
        result = x + y;
    }
    if(op.equals("뺄셈")) {
        result = x - y;
    }
    //response.getWriter().printf("result is %d\n", result);
    response.getWriter().println("결과: " + result);
}}

String op = request.getParameter("operator");의 값을 입력받고
값에 따라 연산을 다르게 해주자.
submit이 두개가 잇어도 선택적으로 처리할수 있게 되엇다.

24.입력데이터 배열로 받기

사용자로부터 값을 입력받을때 배열의 형태로 받을 수있다.
입력값을 전달받기 위해 각각에다가 이름을 주고 받아왔다.
그러나 각각 줄 수 없는 경우가 있다.
입력박스를 동적으로 추가하는 경우도 있다. 칸이모자라면 하나씩 추가해서 입력하는것
입력박스가 같은 이름으로 각각 만들어지는 것이다.
식별자 별로 각각받게되면 반복되는 일이 여러번 발생하게 된다.
만약 1억개 값을 받게되면 1억개 코드 작성해야함.
같은 이름으로 보내면 배열로 가게된다. 서블릿에선 배열로 꺼내서 반복문으로 읽으면 된다.
String[] num = request.getParameterValues("num");
여러개의 값을 받으니 Values가 추가되고 배열로 받는다는 점이 이전과 다르다.
그리고 반복문으로 읽어준다.

<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Insert title here</title>
    <form action = "add2" method="post">
        <div>
            <input name="num" type="text" />
            <input name="num" type="text" />
            <input name="num" type="text" />
            <input name="num" type="text" />
        </div>
        <div>
            <input type = "submit" value="덧셈"/>
        </div>
        <div>
            결과 : 0
        </div>
</head>
<body>
</body>
</html>

@WebServlet("/add2")
public class Add2 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();

    String[] num_ = request.getParameterValues("num");


    int result = 0;
    for (int i = 0 ; i < num_.length; i++) {
        int num = Integer.parseInt(num_[i]);
        result += num;

    }
    //response.getWriter().printf("result is %d\n", result);
    response.getWriter().println("덧셈 결과: " + result);
}}

25. 상태 유지를 필요로하는 경우와 구현의 어려움

웹이라는 것은 어플리케이션이 조각나있다.
서블릿이라는 것도 서버프로그램이 조각으로 나누어져 있다는 것이다.
그러다 보니 전역변수같은 개념이 필요한데 전역변수라는 개념을 가지고 있지않은 조각난 애플리케이션사이에서
전역변수처럼 서블릿들 사이에서 값을 유지해야하는 것이 필요하게 되는데 이것을 어떻게 처리하게 될것인가?
현실적으로 풀을 만들어보자면 입력박스가 여러개인것이아니라 박스는 하나이고
첫번째 값을 하나 전송하고 전송하는 주체를 입력하고 일단 세이브 그리고 입력을 하고 계산해야한다.
그런데 첫번째 입력한 값이 어디에 가잇을까? 원래 우리가 버튼을 누르면 서버프로그램은 잠깐 올라왓다가 사라지게 된다.
받아서 이 값을 어딘가에다가 저장을 해줘야한다. 그래서 계산버튼을 눌럿을때 다시깨어난 서블릿이
앞전의 값을 가져와서 계산을 해야한다. 이것을 어떻게 해야할것인가?
그래서 우리는 application seccsion cookie세가지 객체를 사용한다.
어딘가에 담아두었다가 다음에 쓰도록 담아두는 것임 이게 사라지지 않고 남아잇는것임
때에따라 hidden input과 querystring도 있다.
이 세가지 도구를 사용할 것이다.

calc2 html만듬

계산기와 비슷한 형태가 생겨난다.
서버에서는 값과 연산자를 받고 다시 원래 페이지로 돌아가고 다시 값과 연산자를 받고 이전 연산자와 계산을 한다.

<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Insert title here</title>
    <form action = "calc2" method="post">
        <div>
            <label>입력:</label>
            <input name="v" type="text" />
        </div>
        <div>
            <input type = "submit" name="operator" value="+"/>
            <input type = "submit" name="operator" value="-"/>
            <input type = "submit" name="operator" value="="/>
        </div>
        <div>
            결과 : 0
        </div>

</head>
<body>
</body>
</html>

@WebServlet("/calc2")
public class Calc2 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();

    String x_ = request.getParameter("x");
    String y_ = request.getParameter("y");
    String op = request.getParameter("operator");

    int x = 0;
    int y = 0;

    if(!x_.equals("")) {
        x =Integer.parseInt(x_);
    }
    if(!y_.equals("")) {
        y =Integer.parseInt(y_);
    }

    int result = 0;
    if(op.equals("덧셈")) {
        result = x + y;
    }
    if(op.equals("뺄셈")) {
        result = x - y;
    }
    //response.getWriter().printf("result is %d\n", result);
    response.getWriter().println("결과: " + result);
    }}

2022.12.30 후기

2일차인것을 확인하기 위해서 파일을 새로 만들어서 진행하였는데 톰캣서버가 안켜지는 오류가 발생햇다.
복사해서 만들고 @WebServlet("/hi") 이부분, 서블릿 매핑하는 이름을 똑같게 만들어놔서 그런 오류가 발생하게 된것이엇다.
점점 새로운 것을 배워나가는 점이 즐겁다.
중요한것은 꺾이지 않는 마음

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

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

+ Recent posts