본문 바로가기

Spring/Servlet

뉴렉처 서블릿

Tomcat 수동실행 : bin - startup.exe
브라우저에서 localhost:포트번호/파일이름


HOME(=WebContent)
/WEB-INF/classes/여기에 .class(컴파일된)파일이 있어야 찾을 수 있음
그러나 실제로 웹문서를 요청할 때는 WEB-INF에 접근할 수 없음, 서버쪽(WAS,  TOMCAT)에서만 사용 가능
즉 비공개영역이기 때문에 설정 관련된 파일을 저장하기도 함

URL과 실제 클래스 파일을 매핑해야함
web.xml파일

<servlet> <!--실제 파일-->
	<servlet-name>na</servlet-name>
	<servlet-class>com.newlecture/Nana</servlet-class> <!--패키지명이 있다면 같이써줌-->
</servlet>
<servlet-mapping> <!--사용자에게 제공하는 url-->
	<servlet-name>na</servlet-name>
	<url-pattern>/hello</url-pattern> <!--실제 파일이 없으면 was가 매핑정보를 찾아서 반환-->
</servlet-mapping>



출력
1. 서버로 출력 -->단순 매핑으로는 서버 콘솔에만 출력됨
2. 웹(클라이언트)에게 출력

서블릿 : 입출력을 웹으로 할 수 있음
- 요청도구 request
- 출력,응답도구 response
- 입출력의 기본 : Stream
- Byte(OutStream)가 아닌 문자열을 출력하기 위해서 PrintStream
- 버퍼가 다 차지 않아도 바로 flush하도록 하는 것(출력) : true 옵션


OutputStream os = response.getOutputStream();
 PrintStream out = new PrintStream(os, true)
out.println("클라이언트에 출력됨");
하지만 실제로 문자열 출력하기 위해서는 


printWriter out =response.getWriter();로 바로 씀 os부터해서 변환할 필요X

 

@WebServlet("/요청명")


Ctrl+F11 RUN : Run on Server에서 서버 설정 후 톰캣으로 배포된 문서 열림

같은 포트번호를 동시에 사용하면 에러 뜰 것. 하나를 닫거나 포트번호를 바꾸거나

context명 지우도록 프로젝트명 바꾸기 : 우클릭 후 web project settings  들어가서 '/'만 입력

 

자바 파일은 Java resources - src폴더안에 패키지 나눠 넣음

 

매핑 방법

1.WEB-INF/web.xml

2.Annotation이용(권장)

web.xml에서 설정해줘야함

<web-app 설정에서 ~~~~ metadata-complete="false">

true라면 모든 설정을 web.xml에서 한다는 뜻이기 때문에

클래스 내부에서 하려면 false로 바꾼다

 

 


톰캣의 기본 인코딩 방식 ISO-8859-1

한글인식 지원 안함 2바이트씩 혹은 멀티바이트로 보내야 하는데 1바이트씩 보내서 한글 깨짐response.setCharacterEncoding("utf-8"); 보내는 방식 따로 지정

response.setContentType("text/html; charset=utf-8"); 클라이언트에서 읽을 방식 또한 지정


GET 요청

http://localhost/hello?cnt=3

요청을 하면서 옵션 질의 (Query String) 전달

옵션에 맞는 문서를 만들어줌

무조건 문자열로 전달됨

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

 

<form action="매핑값"> //hi(보여주고싶은 문서명인데, 매핑)

<input type="text" name="cnt">

 

 


utf-8로 기본설정 바꾸기 Window-Preferences - Web - JSP, HTML, CSS 모두 utf-8로 바꿈

 


POST요청방식

보안 & 입력할 내용이 많을 때 장문은 쿼리스트링으로 전달하지 않는 게 좋음

 

POST방식 사용

url아닌 개발자도구의 network에서 확인 가능

url로 보내는 get요청과 달리 주소창이 아닌 문서 body안에 넣어 전달된 것

 


필터를 사용해 한글 인코딩

한글은 2byte사용됨

따라서 요청을 받는 페이지에서 request.setCharacterEncoding("utf-8");을 지정하거나

Server.xml 에서 <Connector 옵션값 중 하나로 URLEncoding="utf-8"/>로 바꿔야함

그러나 톰캣 서버 설정은 일반적으로 건드리지 않기 때문에, 서블릿안에서 설정하는 것이 권장됨 (1번 방법)

 

chain.doFilter(request, response)으로 흐름제어

 

방법1 web.xml 파일 수정

 

방법2 Filter파일에 어노테이션 추가

 

 

과제1

덧셈 결과 찍기 (.html파일은 강의에서 하라는대로)

서블릿 클래스를 만들 때 new - servlet - 매핑이름 바꾸기 -  service만 체크

 


submit버튼 여러개 만들기

개발자도구 - Network (clear한 상태에서 반응 보기) - 문서 안 headers정보 최하단 Form data - View source

 

인풋 태그의 type은 submit, name은 같은 값 value는 다른 값

ex. <input type="sumbit" name="operator" value="add">

      <input type="sumbit" name="operator" value="subtrack">

- 개발자 도구를 확인해보면 operator : add 로 value값을 가지고 오는 것 확인 가능

- getParameter("operator")해서 해당 값이 "add"일 때와 "subtrack"일 때로 나누어 조건문 작성

if(op.equals("add")) result = x+y;
else result = x-y;

response.getWriter().printf("result is %d\n", result);

 


name을 같은 값으로 주면 배열로 들어감 > String[] num = request.getParameterValues("num");

* for문안에 변수를 선언한다고 해서,

반복적으로 변수선언하기 때문에 좋지 않다고 생각할 수 있는데 실제로는 이렇게 지역변수로 선언하는 편이 나음

int result=0;

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

 

 


상태 유지를 위한 5가지 방법

1. application

서블릿 context : 서블릿들의 공유 저장소, 어플리케이션 저장소, 누구나 쓸 수 있음

ServletContext application  = request.getServletContext();

application.setAttribute("name", value[변수]);

 

 

//단순 더하기 빼기 연산 (뒤로가기를 통해 +[-], = 연산해야함)

calc2.html
input 태그 3개 type= submit | value = {+, -, =}


Calc2.java

protected void service(HttpServletRequest request, HttpServletResponse response){
  ServeletContext application = request.getServletContext(); 

  response.setCharacterEncoding("utf-8");
  response.setContentType("text/html; charset=utf-8");
  
  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("operator");
      int result = 0;

      if(operator.equals("+"))
          result = x+y;
      else
          result x-y;
      response.getWriter().printf("result is %d\n", result);
   } else{
   		application.setAttribute("value", v);
        application.setAttribute("op", op);
}

*application : 모든 서블릿이 전역적으로 쓸 수 있음  | 사용자 요청을 처리하다가 다른 서블릿에 전달하고 싶을 때 공동 저장공간

 


 

 

2. session

HttpSession session = request.getSession();

session.setAttribute(), getAttribute();

*session : 사용자가 전역적으로 쓸 수 있음, 브라우저마다 다른 사용자로 인식함(같은 브라우저는 같은 세션)

 같은 브라우저, 여러 창은 하나의 프로세스를 나눠가지는 스레드의 개념으로 열림

 

cf. 처음 사이트를 이용할 때 세션 정보가 없기 때문에 Application에서 처리했다가

     세션 정보가 생기는 순간 그 다음부터는 세션 정보를 이용같은 브라우저는 같은 SID를 가지는데, 브라우저를 끄면 사라짐

개발자도구 - Network - Headers - Cookie 에서 SessionID를 가지고 가고 있다는 것을 확인할 수 있음

void setAttribute
(String name, Ojbect value)
Object getAttribute
(String name)
void invalidate() boolean isNew()
지정된 이름으로 객체 설정 지정한 이름의 객체 반환 세션에서 사용되는 객체 해제 세션이 새로 생성되었는지 확인
void setMaxInactiveInterval (int interval) Long getCreationTime() Long getLastAccessedTime()
세션 타임아웃을 정수(초)로 설정 (Default:30분) 세션 시작 시간 반환
1970/1/1 기준 밀리초
마지막 요청 시간 반환
밀리초

3. cookie

브라우저(클라이언트)에 저장하는 값

getCookies(), addCookie()

쿠키 저장 쿠키 읽기
Cookie cookie = new Cookie("c", String.valueOf(result);
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
String _c="";
if(cookies!=null)
   for(Cookie cooke: cookies)
         if("c".equals(cookie.getName()))
              _c = cookie.getValue();

// 쿠키는 배열로 넘어오기 때문에
조금 번거롭더라고 원하는 쿠키 값을 찾기 위해서 반복문 필요
쿠키의 URL 설정
쿠키의 이름 충돌, 비효율적 사용을 막기 위해 URL과 관련된 서블릿에게만 전달되도록함
setPath("/"); //root로 지정, 어떤 경로로든 전달
setPath("/Calc2"); //Calc에 올때만 쿠키 전달
쿠키는 브라우저가 닫혀도 유효하다 [설정시]
디스크에 외부 파일로 저장
지정하지 않으면 브라우저가 닫히면 사라짐
setMaxAge(60*30); //30분으로 만료시점 지정
setMaxAge(24*60*60); //하루로 지정
 
calc2.html
input 태그 3개 type= submit | value = {+, -, =}


Calc2.java

protected void service(HttpServletRequest request, HttpServletResponse response){
	Cookie[] cookies = request.getCookies();
    response.setCharacterEncoding("utf-8");
    response.setContentType("text/html; charset=utf-8");
  
  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 = 0;
    for(Cookie c : cookies){
      if(c.getName().equals("value")){
          x = Integer.parseInt(c.getValue());
          break;
      }
    int y = v;
    String operator="";
    for(Cookie c : cookies){
      if(c.getName().equals("op")){
          operator = c.getValue();
          break;
      }
      
      int result = 0;

      if(operator.equals("+"))
          result = x+y;
      else
          result x-y;
      response.getWriter().printf("result is %d\n", result);
   } else{
	Cookie valueCookie = new Cookie("value", String.valueOf(v)); //쿠키는 반드시 문자열로만 보낼 수 있음 v는 정수형이라 형변환
	Cookie opCookie = new Cookie("op", op);
    valueCookie.setPath("/calc2"); //calc2로 지정해야만 쿠키가 전달됨
    response.addCookie(valueCookie);
    response.addCookie(opCookie);
    //쿠키는 response의 header에 심어져서 전달됨
}

단 쿠키는 브라우저 설정에 따라 쿠키 저장을 허용하지 않을 수도 있음

 

cf.

Response Headers = 서버가 클라이언트에게 돌려주는 헤더

Request Headers : 요청헤더에서 쿠키를 가져가고 있다는 걸 알 수 있음

 

  사용범위 생명주기 저장위치
Application 전역범위에서 사용하는 저장 공간 WAS가 시작해서 종료할 때까지 WAS 서버의 메모리
Session 세션 범위에서 사용하는 저장 공간
(특정 사용자)
세션이 시작해서 종료할 때까지 WAS서버의 메모리
Cookie WEB Browser별 지정한
path범주 공간 (특정URL)
"notice.jsp"에서만 사용한다면 쿠키
Browser에 전달한 시간부터
만료시간까지 (브라우저 닫아도 유효)
저장 기간이 길다면 무조건 쿠키 사용
Web Browser의 메모리 또는 파일

 

4. hidden input

5. querystring


Redirect

response.sendRedirect();

페이지 요청