Servlet
21. 학습과제(사용자 입력을 통한 계산 요청)
서블릿하면서 출력 입력방법 배웠다. 연산을해서 사용자에게 돌려줄 수 있게 되었다.
초간단으로 연습할 수 있는 과제
1.add.html에서 입력할 수 있는 폼
2.계산버튼 누르면 post
3.서버쪽에서는 계산해서 덧셈결과 돌려주기
22. 과제풀이(사용자 입력을 통한 계산 요청)
1.보낼때 '문자열'로 보내게되니 숫자로 변환해주기
2.혼자만의 해결할만한 시간을 가져보았느냐
를 보기 위해 주어진 과제이다.
사용자 입력 할때 빈문자열이 올수도 있으니 기본값을 제공해주자.
@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();
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_);
}
out.println("result is : " + (x + y));
}
}23. 여러 개의 Submit 버튼 사용하기
간단한계산기프로그램을 여러개의 submit로 여러개의 처리를 하기
덧셈과 뺄셈을 모두 가능하게 하고싶다. 그런데 전달되는 덧셈과 뺄셈을 어떻게 식별을 하나?
먼저 버튼을 두개 만들어준다. 그런데 이것을 어떻게 식별할 것인가?
개발자 도구로 각 버튼을 눌렀을 때 처리 되는 것을 보자
<input type = "submit" name="operator" value="덧셈"/>
<input type = "submit" name="operator" value="뺄셈"/>
버튼에 이름을 추가해주고 개발자도구에서 보면 어떤 버튼이 눌렸는지 구분이 되게된다.
String op = request.getParameter("operator");의 값을 입력받고
값에 따라 연산을 다르게 해주면된다.
submit이 두개가 잇어도 선택적으로 처리할수 있다.
@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;
} else if (op.equals("뺄셈")) {
result = x - y;
}
out.println("result is : " + result);
}
}24. 입력 데이터 배열로 받기
사용자로부터 값을 입력받을때 배열의 형태로 받을 수 있다.
입력값을 전달받기 위해 각각에다가 이름을 주고 받아왔다.
그러나 인풋 박스에 이름을 각각부여할 수 없는 경우도 있다.
고정되어 있지 않고 입력박스를 동적으로 추가하는 경우도 있다.
칸이 모자라면 하나씩 추가하는 버튼이 가끔 있다.
입력박스가 같은 이름으로 각각 만들어지는 것이다.
식별자 별로 각각받게되면 반복되는 일이 여러번 발생하게 된다.
만약 1억개 값을 받게되면 1억개 코드 작성해야한다.
그래서 같은 이름으로 값을 받을 수 있다.
<input type="text" name="num" />
<input type="text" name="num" />
<input type="text" name="num" />
<input type="text" name="num" />같은 이름으로 보내면 배열로 가게된다.
서블릿에선 배열로 꺼내서 반복문으로 읽으면 된다.
String[] num = request.getParameterValues("num");
여러개의 값을 받으니 Values가 추가되고 배열로 받는다는 점이 이전과 다르다.
그리고 반복문으로 읽어준다.
@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[] nums = request.getParameterValues("num");
int result = 0;
for (int i = 0; i < nums.length; i++) {
int num = Integer.parseInt(nums[i]);
result += num;
}
out.println("result is : " + result);
}
}25. 상태 유지의 필요성
웹이라는 것은 어플리케이션이 조각나있는것이다.
서블릿이라는 것도 서버프로그램이 조각으로 나누어져 있다는 것이다.
그러다 보니 전역변수같은 개념이 필요한데 전역변수라는 개념을 가지고 있지않은 조각난 애플리케이션사이에서
전역변수처럼 서블릿들 사이에서 값을 유지해야하는 것이 필요하게 되는데 이것을 어떻게 처리해야할까?
현실적으로 풀을 만들어보자면 입력박스가 여러개인것이아니라 박스는 하나이고
첫번째 값을 하나 전송하고 전송하는 주체를 입력하고 일단 세이브 그리고 입력을 하고 계산해야한다.
그런데 첫번째 입력한 값이 어디에 가잇을까?
예를들어 원래 우리가 덧셈 버튼을 누르면 서버프로그램은 잠깐 올라왓다가 사라지게 된다.
그래서 이값을 받아서 이 값을 어딘가에다가 저장을 해줘야한다.
그래서 계산버튼을 눌럿을때 다시깨어난 서블릿이 앞전의 값을 가져와서 계산을 해야한다.
서블릿 간에 값을 저장하는 타입캡슐같은 이런게 없다. 이것을 어떻게 해야할것인가?
우리는 application seccsion cookie세가지 도구, 객체를 사용한다.
어딘가에 담아두었다가 다음에 쓰도록 담아두는 것이다.
서블릿이 살아낫다 죽엇다 하는 것 이 데이터를 사라지지 않고 남아잇게하는 것이다.
때에따라 hidden input과 querystring도 있다.
이 세가지 도구를 사용할 것이다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="calc" method="post">
<div>
<input type="text" name="v" />
</div>
<div>
<input type="submit" name="operator" value="+" />
<input type="submit" name="operator" value="-" />
<input type="submit" name="operator" value="=" />
</div>
<div>
결과 : 0
</div>
</form>
</body>
</html>계산기와 비슷한 형태가 생겨난다.
서버에서는 값과 연산자를 받고 저장하고
다시 원래 페이지로 돌아가고 다시 값과 연산자를 받고 이전 연산자와 계산을 한다.
26. Application 객체와 그것을 사용한 상태 값 저장
상태들 저장하는 객체 중 Application에 대해서 배워보고자 한다.
원래는 1번서블릿 요청시 일하고 메모리에서 사라진다.
이런 특성으로 1번이처리햇던결과를 2번이 이어받아 실행하는 것이 불가능하다.
그들만의 데이터를 이어받아 저장하는 것이 중요한데 서블릿 Context(문맥)라고 한다.
흔히 Application을 만들다보면 사용되는 api중 context를 가지고 있는것이 많다.
어떻게보면 책갈피라는 것을 떠올릴수잇는네 책을 이어갈수잇도록 하나의 상태값을 표시하는 역할을 한다.
context가 문맥을 이어갈수잇도록 저장소 역할을 하는 것이다.
A가 결과물을 저장하면 B가 이 결과물로 결과를 만드는 상태 저장공간이라고 보면된다.
웹 어플리케이션 저장소를 사용하려면 다음과 같이 작성해야한다.
ServletContext application = request.getServletContext();
이 application에는 두가지 저장 일반적으로 사용되는 컬렉션이라고 생각하면된다.
application.setAttribute("value", v);
맵에서 저장햇듯이 키, 값을 넣어주자.
이렇게하면 두고 꺼내서 쓸수가 있다.
op에 따라서 저장, 계산 등을 할수있다.
x 저장소에 담긴내용 y 지금 사용자가 전달한 밸류값을 y라고 해보자.
값을 담는작업말고 꺼내는 작업은 getAttribute하면된다.
int x = (Integer) application.getAttribute("value");
Object로 값을 반환하기 때문에 강제변환해줘야한다.
사용자가 입력할때 순서
1.값을 전달한다.
2.=이 아니라면 저장한다.
3.=이 눌리면 값들을 꺼낸다.
@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();
ServletContext application = request.getServletContext();
String v_ = request.getParameter("v");
String op = request.getParameter("operator");
int v = 0;
if (!v_.equals("")) {
v = Integer.parseInt(v_);
}
// 계산
if (op.equals("=")) {
int x = (Integer) application.getAttribute("value");
int y = v;
String operator = (String) application.getAttribute("op");
int result = 0;
if (operator.equals("+")) {
result = x + y;
} else if (operator.equals("-")) {
result = x - y;
}
out.printf("result is: %d", result);
} else {
// 값저장
application.setAttribute("value", v);
application.setAttribute("op", op);
}
}
}그러나 흰화면 나오고 뒤로돌아가고 흰화면나오고 뒤로돌아가고 밖에 안된다.
사실 이 실습이 appication객체를 이용하는데 적절하지는 않다. 사용방법만 배우고자 한것이다.
저장소를 사용하기 위한 적절한 시기와 적절한 방법을 알아볼 필요가 있다.
27. Session 객체로 상태 값 저장하기(그리고 Application 객체와의 차이점)
위에서 사용한 코드가 Session을 사용해도 똑같다.
HttpSession Session = request.getSession();으로 만들고 위에서 Session으로만 바꾼다.
사용방법은 application과 같다. session은 application처럼 상태를 저장하는 공간이다.
코드도 비슷하고 사용법도 같은데 차이점이 무엇일까?
application객체는 웹 어플리케이션 전역에서 쓸수잇다.
session객체는 session 범주에서쓸수있다.
즉 session은 현재 접속한 사용자를 위한 공간이다.
사용자별로 공간이 달라질 수있다. 세션마다 현재접속자마다 공간이 달라진다는 뜻이다.
브라우저가 달라지면 다른 사용자로 인식을 하는데 세션이 달라지니 다른 사람이 입력했던 것은 값이 없어진다.
크롬브라우저를 똑같이 하나 더 열엇을때 같은 세션으로 인식하는가 다른 세션으로 인식하는가?
-> 이것은 같은 세션으로 인식한다.
같은 컴퓨터에서 같은 브라우저를 여러 개를 띄워도 하나의 프로세스를 스레드로 받기때문에 프로세스를 공유하는 같은 사용자로 인식하게 된다.
28. WAS가 현재사용자(Session)을 구분하는 방식
그렇다면 웹서버는 사용자를 구분, 식별할까?
우리는 브라우저를 통해서 서버에 요청을 하게 된다.
브라우저 ->요청 -> 서버 다른서블릿에게 전달하고 싶은 내용을 어딘가에 저장하는데 이것이 application 공간이다.
이것을 개인별로 사용자마다 저장할수 잇는 session공간이 잇다.
서블릿 실행요청이 왓을때 사용자가 SID를 전달하게 되는데 처음에는 SID가 없다.
그래서 새로운 사용자에게는 session이 존재하지 않는다.
session은 사용자가 SID를 가지고 있어야한다.
그래서 처음에는 SID가 없어서 application만 가능하다. 돌아갈때 SID를 제공하고 session이 제공되게 된다.
다음 또 요청을 하면 SID를 참조해서 session에 값이 저장된다.
SID가 WAS에 의해 발급되고 이것을 이용자가 가지고 있다가 session을 이용하게 되는것이다.
브라우저를 바꾸거나 끄면 다시 초기화된다.
물론 물리적으로는 사용자가 다른 브라우저를 띄워서 갈 수 있다. 웹서버는 이것을 같은 사용자로 보지 않는다.
개발자도구의 네트워크를 보면 서버에 요청할때마다 식별자를 가지고 가는 것을 볼 수 있다.
브라우저를 사용하지 않고 간단한 툴로 누군가의 세션아이디를 복사해서 요청하면 같은 사용자로 인식하게 된다.
그래서 웹서버에서는 다양한 방식으로 세션아이디를 제공하기도한다.
여러 다른 조합을 통해서 사용자를 식별하기도 한다.
그러면 웹이라는 특성상 사용자가 요청을 계속할 것이다.
그럼 서버는 계속 세션을 유지하나 아니면 정리를 할까?
그렇다면 언제 정리할까?
그래서 session은 여러가지 추가적인 기능을 가지고 있다.
void invalidate()하면 다 지운다.
그래서 session은 시간이 중요해서 타임아웃을 사용한다.
사용자 요청후 요청이 또 안오면 시간을 두고 삭제한다. 기본시간은 30분이다.
개별적으로 타임아웃을 설정할 수 있다.
'기초단계 > JSP&Servlet' 카테고리의 다른 글
| 2023.03.20 JSP (0) | 2023.03.20 |
|---|---|
| 2023.03.19 Servlet (0) | 2023.03.20 |
| 2023.03.15 Servlet (1) | 2023.03.15 |
| 2023.03.14 Servlet (0) | 2023.03.15 |
| 2023.01.06 JSP & Servlet (0) | 2023.01.07 |