카테고리 없음

190708_Day TomCat 설정, Servelet

용진용진 2019. 7. 9. 10:39

190708_Day Day TomCat 설정, Servelet

Preference에서

General에서 Workspace에서

d왼쪽 Text file encoding을 UTF-8로 바꿈

web탭에있는 애들(CSS,HTML,JSP)도 다 UTF-8로!


<톰캣서버 환경설정>

  1. 시스템 JAVA_HOME 설정 확인

  2. apache-tomcat 서버 설치

    http://tomcat.apache.org

    jdk8과 톰캣8이 가장 호환이 잘 되니 이걸로 간다!

    core가 가장 핵심이니 코어로 간다!

    보통 윈도우는 zip 리눅스는 tar

    zip파일과 installer가 있는데 굳이 zip 쓰는 이유는 서버 여러개 생성 가능해서


압축풀면

bin 에는 멸령어들(서버시작, 정지 등)

conf 환경설정 파일들 (server.xml web.xml context.xml)

logs 에는 서버 실행중 기록파일 기록함 (log.txt)

temp는 임시폴더

webapps는 웹 어플리케이션들, 중요한 폴더 (HTML, JAVA, JSP)

work는 개발자가 작성한 jsp 맵핑되는 servlet파일(.java .class) 를 생성하는 곳, 시스템테이블이랑 비슷, readonly, 자바코드 생성해주는 곳


cmd에서 startup.bat 실행시키면 Tomcat뜨면서 에러 발생함.

BindException도 발생하는데 웹서버를 돌리기 위해서는 포트넘버 하나를 가져가게 되는데 그것이 8080, 근데 오라클에서 리스닝 상태라 이미 쓰고 있어서 에러가 발생하는 것.

conf폴더에 포트넘버 바꾸는것이 있어!, 환경설정 모아둔 폴더

여기서 server.xml 에서 8080을 8282로 바꾸어보자!


이클립스에 플러그인 설치~! (필히 필요한건 아니지만 편리하다!)

https://sourceforge.net/projects/tomcatplugin/files/

여기서 zip파일 다운받기!

plugins폴더에

net.sf.eclipse.tomcat_9.1.4.jar 복사

복사한 jar파일을 내가 사용하는 이클립스 폴더 내에 plugins폴더에 붙여넣기 후 재시작

톰캣 메뉴 생김

Preferences 에서도 Tomcat 항목이 생겼다!

서버 버젼 8.x로 맞추고

Tomcat Home도 apache-tomcat-8.5.42 로 맞추고

context files로 어플라이!

그리고 Advances에서도 apache-tomcat-8.5.42

JVM setting에서도 체크 don't run Tomcat is debug mode

이후 Tomcat Project생성! Open perspective 뜨면 아니오~!

bin과 src는 헷갈릴거 같아서 지웠!


TomTest 프로젝트에서 jsp file 생성

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> 하이 톰캣서비스 ~ ! </title>
</head>
<body>
<!-- hello.jsp -->
    <font color="blue" size="15"> 톰캣 Plug-In을 통한 프로젝트 생성!</font>
</body>
</html>

http://192.168.0.87:8282/TomTest/hello.jsp 로 실행!


< Java Application>

  • 한개의 main()메소드를 가지고 독립적으로 실행하는 자바클래스

< Java Web Application>

  • 브라우저에서 실행되는 자바클래스 (Servlet/JSP)
  • 서블릿과 JSP를 실행하기 위해서는 web Application Server가 필요

<서블릿> javax.servlet.Servlet

  • 자바 플랫폼에서 컴포넌트를 기반으로 한 웹 애플리케이션을 개발할 때 사용
  • 스레드를 기반으로 하므로 웹 애플리케이션 운영에 효율적
  • 자바를 기반으로 하므로 자바 API를 모두 사용할 수 있다
  • 운영체제나 하드웨어에 영향을 받지 않으므로 한번 개발된 애플리케이션은 다양한 서버환경에서도 실행이 가능
  • 웹애플리케이션에서 효율적인 자료 공유 방법을 제공
  • JSP는 서블릿을 기반으로 한 기술

<웹 애플리케이션 개발 시 서블릿을 사용하면 좋은 점>

  • 콘텐츠와 비즈니스 로직을 분리 할 수 있다.
  • 컨트롤러와 뷰의 역할 분담으로 인해 웹 디자이너와 개발자 간의 원활한 작업이 가능
  • 유지보수가 수월
  • 기능확장이 용이

<서블릿 클래스의 상속관계>

javax.servlet.Servlet(인터페이스)

​ |

javax.servlet.GenericServlet(클래스)

​ |

javax.servlet.http.HttpServlet(클래스)

<서블릿의 생명주기 메소드> ★★★ Life Cycle

  1. init() 메소드

    서블릿 로딩시 실행되는 메소드

    서블릿 초기화에 관련된 메소드

    생성자라고 보면 됨

  1. service() 메소드

    웹브라우저에서 서비스(화면출력)하는 메소드

    클라이언트 요청에 따리 doGet()이나, doPost() 메소드로 분기

    사용자 요청 처리는 request(요청객체, client, 아이객체, 때쟁이, 브라우저)로

    ​ 응답 처리는 response(응답객체, server, 엄마객체, 톰캣)로 처리함

  1. destroy() 메소드

    컨테이너로부터 서블릿 종료요청이 있을때

    서블릿 종료직전에 해야 할 작업을 명시할 때 사용

    대부분의 경우 컨테이너가 종료될 때 실행된다.

    ​ 아파치 톰캣 => 서블릿 컨테이너! (서버, 실행기)


MyServlet.java

package t0708;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet{
  //서블릿 : 한개의 웹페이지 화면을 구성!!

   @Override
   public void init() throws ServletException {
      System.out.println("init()");
   }

   @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       System.out.println("service()");
       //서블릿 서비스 메소드 == 웹브라우저 서비스!! ==> HTML 서비스
       //request:클라이언트(사용자, 브라우저), response : 서버를 각각 의미

       // (한글)문자집합 설정
       response.setContentType("text/html;charset=UTF-8");
       // text/html => MIME형식
       // 입력:text 출력:html => out.print() 메소드를 통해 전달되는 text를 브라우저에게 html해석하시오!
       //text:plane; text:xml; 이런식으로 형식을 줄 수 있다!

       PrintWriter out = response.getWriter();
       //PrintWriter out ==> 브라우저 출력 객체를 의미함.
       //out.print("HTML코드(텍스트)");

       out.print("<html><head><title></title></head>");
       out.print("<body><h3>ServletTest</h3></hr>");
       for (int i = 0; i < 10; i++) {
           if(i%2==0)
           out.println("<b><font color = red>용진</font></b><br>");
           if(i%2==1)
            out.println("<b><font color = blue>진주</font></b><br>");
    }
       out.print("</body></html>");
    }

    @Override
    public void destroy() {
       System.out.println("destroy()");
    }

}

<서블릿 실행 방법>

  1. http://192.168.0.87:8282/TomTest/servlet/t0708.MyServlet

    그런데 이렇게 쓰면 해킹같은 문제가 발생할 수 있음.(보안상 문제)

    최근 버전부터는 그래서 주소를 적나라하게 쓰는걸 막음.

  2. WEB-INF/web.xml에 작성된 서블릿 클래스를 등록

    권장이 아닌 강요 하고 있음!

    등록과 함께 서블릿에 대한 가상의 경로를 매핑시켜서 호출.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd ">
    <!--서블릿 클래스 등록 -->
    <servlet>
        <servlet-name>my</servlet-name>
        <servlet-class>t0708.MyServlet</servlet-class>
    </servlet>

    <!--가상의 경로 설정 -->
    <servlet-mapping>
        <servlet-name>my</servlet-name>
        <url-pattern>/yongjinju/my</url-pattern> 
        <!-- url-pattern 엘리먼트 내의 맨 앞의  '/'는 (컨텍스트)루트를 의미 
            예) /yongjinju
            ===> http://localhost:828/Tomtest/yongjinju
        -->

    </servlet-mapping>

    <!-- 카운트 서블릿 등록 -->
    <servlet>
        <servlet-name> cnt2 </servlet-name>
        <servlet-class>t0708.CountServlet2</servlet-class>

    </servlet>

      <!-- 카운트 서블릿에 매핑할 가상경로 정의 -->
  <servlet-mapping>
     <servlet-name>cnt2</servlet-name>
     <url-pattern>/cnt2</url-pattern>
  </servlet-mapping>

</web-app>

xml하나를 만든다, Create XML file from an XML schema file!

XML catalog entry에서 web-app_3_0.xsd

javaee 선택하고 Edit으로 Prefix로 javaee 삭제(복잡해보여서)

CountServlet.java

package t0708;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CountServlet extends HttpServlet{
    int cnt;//=0;
    ArrayList<String> list;// 접속한 ip주소를 저장하는 용도


    @Override
    public void init() throws ServletException {
        list = new ArrayList<>(); //1회 실행
    }

    @Override
    protected void service(HttpServletRequest req, 
                           HttpServletResponse resp) throws ServletException, IOException {


       resp.setContentType("text/html;charset=UTF-8");
       //한글을 한개라도 사용하면 글자 깨짐을 방지하기 위해 '문자셋'설정을 해야 함.

       //req: 요청객체(브라우저,클라이언트), resp:응답객체(서버,출력)
       PrintWriter out = resp.getWriter();//out: 브라우저 출력객체
         //out.print("HTML텍스트");
         out.print("<html><head><title>ServletCount</title></head>");
         out.print("<body><h3>ServletCounter</h3><hr>");

      //동일 사용자(동일 브라우저접속)의 경우 ==> 조회 수를 1증가!!
         //req ==브라우저
         //HttpSession session = req.getSession(); //세션은 접속이다!!
         //if(session.isNew())

       String addr = req.getRemoteAddr();//접속한 클라이언트(브라우저)의 ip주소 얻기
           //addr ="192.168.0.90"
       System.out.println("접속클라이언트 ip주소["+addr+"]");  

         if(!list.contains(addr)) {//이미 접속한 ip가 아니라면, ip주소가 list에 포함되지 않았다면
             cnt++;
             list.add(addr);
         }

         out.print("조회수: "+  cnt  +"회</body></html>");

    }//service

}

이후 web.xml 에 서블릿 등록!

오라클 DB연결, 반드시 xe여야하는거 기억하기

counter.sql

--counter.sql

--카운트 값 저장
create table cnt
(
    cnt number
);

insert into cnt values (0);

select * from cnt;

create sequence cnt_seq;

--접속 ip 저장
create table addr
(
    addr varchar2(20)
);

drop table addr;

drop sequence cnt_seq;

counter.xml (아이바티스로)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd" >
<sqlMap namespace="count">
  <!-- counter.xml -->  
  <!-- ip저장 -->
  <insert id="insert" parameterClass="String">
      insert into addr values (#value#)
  </insert>

  <!-- 카운트값 변경 -->
  <update id="update" >
      update cnt set cnt=cnt_seq.nextval
  </update>

  <!-- 저장된 ip조회 -->
  <select id="select" parameterClass="String" resultClass="int">
      select count(*) from addr
      where addr=#value#
  </select>

  <select id="selectCnt" 
          resultClass="int">
       select cnt from cnt
  </select>
</sqlMap>

CountServlet2.java

package t0708;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.ibatis.sqlmap.client.SqlMapClient;

import iba.MySqlMapClient;

public class CountServlet2 extends HttpServlet{
    //접속한 클라이언트 ip주소와 조회수를 DB에 저장

    SqlMapClient smc;//용도? XML문서내의 sql호출

    @Override
    public void init() throws ServletException {
        smc = MySqlMapClient.getSqlMapInstance();
    }

    @Override
    protected void service(HttpServletRequest req, 
                           HttpServletResponse resp) throws ServletException, IOException {


       resp.setContentType("text/html;charset=UTF-8");
       //한글을 한개라도 사용하면 글자 깨짐을 방지하기 위해 '문자셋'설정을 해야 함.

       //req: 요청객체(브라우저,클라이언트), resp:응답객체(서버,출력)
       PrintWriter out = resp.getWriter();//out: 브라우저 출력객체
         //out.print("HTML텍스트");
         out.print("<html><head><title>ServletCount</title></head>");
         out.print("<body><h3>ServletCounter</h3><hr>");

       String addr = req.getRemoteAddr();//접속한 클라이언트(브라우저)의 ip주소 얻기
           //addr ="192.168.0.90" 
       System.out.println("접속클라이언트 ip주소["+addr+"]");  

       try {
  int count = (Integer)smc.queryForObject("count.select",addr);
           //count ==> 저장된 ip 존재 유무

           if(count == 0) {//저장ip가 존재하지 않는다면
                smc.insert("count.insert",addr);
                smc.update("count.update");
           }         
             out.print("조회수: "+  
                       smc.queryForObject("count.selectCnt").toString() 
                 +"회</body></html>");

       } catch (SQLException e) {
        e.printStackTrace();
       }

    }//service

}
궁금상자
Servlet JSP
JSP로 만들어도 실제 실행은 Servlet으로 실행됨

Servlet은 Java코드 안에 HTML 태그가 삽입된 .java코드
규약에 맞는 라이브러리나 클래스들을 상속, 구현하여 만든 클래스

JSP은 HTML을 코딩하기 불편, 어려워서 HTML내부에 Java코드를 삽입하는 방식, 인터페이스 구현이 힘든 Servlet의 비효율성을 개선?
서블릿 기반의 서버스크립트 기술!

Servlet은 자바코드로구현, 컴파일하고 배포해야 함 문자열 스크림 처리해야 함, 코드 수정시 다시 컴파일

JSP는 키워드 태그화로 쉬움, 자바코드는 <% %> 태그 안에 처리, HTML처럼 태그를 사용하여 자바코드도 사용 가능