1. boolean startsWith(String str)

특정 값이 인자로 받은 해당 접두사와 일치하는 경우 true, 일치하지 않은 경우 false를 리턴하는 메소드 

 

 

* <=> boolean endsWith(String str)

 

2. boolean indexOf()

 

 

3. charAt()

'BackEnd > Java' 카테고리의 다른 글

람다식과 함수형 프로그래밍 (Java 8.0 이상)  (0) 2017.02.09
자바 기본 정리  (0) 2017.02.09
Java :: Reflection 리플렉션  (0) 2016.12.18
Java :: Exception 예외처리  (0) 2016.12.15
Servlet :: ServletContext vs ServletConfig  (0) 2016.11.22

1. 정의

객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법

형은 알고 있지만 형변환을 할 수 없는 상태에서 객체의 메소드를 호출할 수 있음


자바에서는 클래스의 정보를 분석하기 위한 도구로 Class 클래스를 제공해주고 있는데, .class의 등록 정보 클래스, 바이트 코드의 등록 정보 클래스로 표현할 수 있다.


Class 클래스는 java.lang 패키지 소속의 클래스이며 Method, Field, Constructor는 java.lang.reflect 패키지에 존재한다.

그렇기 때문에 자바의 리플렉션 기법을 사용하기 위해서는 무조건 java.lang.reflect 패키지를 import 한 후에 사용해야 한다.



2. 정적 바인딩

컴파일시 이미 컴파일러가 Data 클래스를 알고 있는 상태(class path가 지정된 곳에 클래스 자체가 존재해야 함)

컴파일 시점에 이미 로딩되어 있음 (ex. new 연산자)

다운 캐스팅도 가능하고 마음대로 Data라는 형을 사용할 수 있음


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.example;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
public class ShowClassInfoMain {
    public static void main(String[] args) {
//      Integer 클래스 데이터 타입을 Class 클래스 데이터 타입 c로 값 복사
//      Integer 클래스는 java.lnag 패키지 소속이기 때문에 자동 import
        Class c = Integer.class;
        
//      클래스, 생성자, 메소드, 필드명 객체 주소 알아내기(여러개일 수 있으므로 배열로 받는다)
        Class[] iface = c.getInterfaces();
        Constructor [] ctor = c.getConstructors();
        Method [] m = c.getMethods();
        Field[] f = c.getFields();
        
//      Integer 클래스 타입인 c를 Class타입인 temp로 값 복사함
        Class temp = c;
        
//      temp와 temp.getSuperClass. 상위 클래스의 값이 null이 아닌 경우 무한 반복
//      (상위 클래스들을 모두 역으로 추적하기 위해 while문 사용함)
//      => 상위 클래스 : Number, Object (콘솔 창에 출력되는 결과)
        while ( (temp = temp.getSuperclass()) != null) {
            System.out.println(temp);
        }
        
        System.out.println();
        
//      Integer 클래스 데이터 타입인 인터페이스 배열들 출력하는 for문
        for (int i = 0; i < iface.length; i++) {
            System.out.println("interface[" + i + "] = " + iface[i]);
        }
        
        System.out.println();
        
//      Integer 클래스 데이터 타입인 생성자 배열들 출력하는 for문
        for (int i = 0; i < ctor.length; i++) {
            System.out.println("Constructor[" + i + "] = " + ctor[i]);
        }
        
        System.out.println();
        
//      Integer 클래스 데이터 타입인 메소드 배열들 출력하는 for문
        for (int i = 0; i < m.length; i++) {
            System.out.println("Methoid[" + i + "] = " + m[i]);
        }
        
        System.out.println();
        
//      Integer 클래스 데이터 타입인 필드 배열들 출력하는 for문
        for (int i = 0; i < f.length; i++) {
            System.out.println("Field[" + i + "] = " + f[i]);
        }
    }
}
cs

<클래스 정보 출력하는 예제>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example;
 
//정적 바인딩을 이용해 다운 캐스팅 하는 클래스
public class Data {
    public void sayHello() {
        System.out.println("Hello World!");
    }
}
 
package com.example;
 
public class StaticBindingMain {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//      정적 바인딩으로 Data 클래스를 사용함
//      정적 바인딩 : 개발자가 .class 파일을 직접 로딩한 후 Class 클래스를 이용하여 객체를 생성하면
//                    JVM이 그 다음 작업을 해주는 것
//      1단계 > .class : 개발자가 .class 파일을 직접 로딩하여 Class 클래스에 값 복사함
        Class c = Data.class;
//      2단계 > newInstance() : Class 클래스 이용하여 객체를 직접 생성하는 메소드
//                         (정적 바인딩을 직접 하기 위해)
        Object obj = c.newInstance();
        
//      정적 바인딩으로 Data 클래스를 사용함
//      (Data 라는 해당 클래스가 프로젝트 안에 실제로 존재해야 함)
        Data d = (Data) obj;
        Class c2 = d.getClass();
        
//      정적 바인딩으로 Data 클래스를 사용함
        Data d2 = (Data) c2.newInstance();
        
        System.out.println(d);
        System.out.println(d2);
        
        d.sayHello();
        d2.sayHello();
    }
}
cs

<정적 바인딩 예제>



3. 동적 바인딩

일반적으로 말하는 리플렉션의 기법

런타임(실행) 시점에 로딩되기 때문에 컴파일 시에는 해당 클래스가 없어도 됨

프로그램이 실행되고 난 뒤 동적으로 위치를 명시하고, 해당 클래스( .class) 를 로딩하여 객체를 만들고 메소드를 호출함

해당 클래스가 바로 존재하지 않아도 클래스의 위치와 이름만 알면 찾을 수 있음 (ex. Class.forName(String str))


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.example;
 
public class DynamicData {
    public void sayHello() {
        System.out.println("안녕하세요!");
    }
    
    public void goodBye() {
        System.out.println("안녕히계세요!");
    }
}
 
package com.example;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
 
public class DynamicDataClassMain {
    public static void main(String[] args) throws IOException, InstantiationException, 
                                                    IllegalAccessException, ClassNotFoundException {
        System.out.println("다운로드중 ...");
        
//      웹 서버에 존재하는 파일에 연결된 스트림을 생성하는 방법
        URL url = new URL("http://www.jabook.org/DynamicData.class");
        InputStream is = url.openStream();
        
//      스트림을 통해 읽은 데이터를 저장하기 위해 파일 출력 스트림 생성
        FileOutputStream fos = new FileOutputStream("DynamicData.class");
        
        int i;
        
//      입력 & 출력 스트림이 생성되었을 시 반복
        while ( (i = is.read()) != -1) {
            fos.write(i);
            
            System.out.println("|");
        }
        
//      열어놨던 입출력 스트림들은 반드시 닫아줘야 함
        fos.close();
        is.close();
        
        System.out.println("\n 다운로드 완료 ...");
        
//      클래스의 이름 자체를 컴파일 타임에 사용할 수 없기 떄문에 문자열 형태로 클래스의 이름을 사용
//      Class.forName(String str)이 호출되는 그 순간 클래스를 로딩하겠다는 의미
//      매개변수가 String 형인 이유 : 해당 클래스가 컴파일시 없기 때문
        Class c = Class.forName("DynamicData");
        
//      동적으로 생성된 Class 정보를 이용해서 객체 생성
        Object obj = c.newInstance();
        
        System.out.println(obj);
        
        /*
         * 정적 바인딩과 동적 바인딩의 차이
         * - 다운 캐스팅의 유무 (동적 바인딩 : X, 정적 바인딩 : O)
         * - 이유 : 동적 바인딩은 컴파일시 해당 클래스의 이름을 사용할 수 없기 때문임
         *             (매개변수로 클래스 이름을 넣는게 아니라 위치만 넣으니까)
         *             동적 바인딩은 멤버 메소드를 호출할 수 없다
         * 
         *     (중요) => 이 때, java.lang.Reflection 패키지의 Class 클래스를 이용하여
         *            다운캐스팅 할 수 없는 객체여도 모든 작업을 할 수 있게 지원해줌 (ex. getContstructors())
         */           
    }
}
cs

<동적 바인딩 예제>

'BackEnd > Java' 카테고리의 다른 글

자바 기본 정리  (0) 2017.02.09
Java :: startsWith() vs indexOf() vs charAt()  (0) 2016.12.26
Java :: Exception 예외처리  (0) 2016.12.15
Servlet :: ServletContext vs ServletConfig  (0) 2016.11.22
Java :: Abstract vs Interface  (0) 2016.10.28

1. 정의

디렉토리의 기본 웹 페이지

디렉토리를 방문 했을 때 그 디렉토리에 맞는 기본 화면을 제공하기 때문에 웰컴 파일이라 함

url을 파일명이 아닌 디렉토리명으로 받았을 경우, 기본적으로 불러올 파일명을 지정해야 함



2. 특징

여러 개의 welcome 파일을 등록시 디렉토리에서 웰컴 파일을 찾을 때 태그에 선언된 위 > 아래 순서대로 조회하여 먼저 찾은 순대로 클라이언트로 보냄

둘 다 없을 시, 디렉토리 내의 모든 파일을 보여주거나 404 에러를 내보내기도 함



3. 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
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"
version="3.0">
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
 
</web-app>
cs



* 이러한 welcome-file-list 태그는 Tomcat 내의 기본 web.xml인 %CATALINA_HOME%/conf/web.xml 에도 존재하고, 프로젝트의 web.xml 두 곳에 모두 존재하나 프로젝트 내의 web.xml의 순위가 더 높음

1. java.lang.Trowable

ㄱ. Error : 프로그램 실행 중 일어날 수 있는 치명적인 오류. 복구 불가능

ㄴ. Exception : 에러보다 비교적 경미한 오류. 프로그램의 비정상적 중단을 막을 수 있음

a. RuntimeException

b. Exception

 

 

2. RuntimeException

코드 논리의 오류. 컴파일시 체크되지 않고, 실행 도중 예외 발생시 비정상적으로 종료됨

코드를 수정하여 예외 발생을 막을 수 있음

대부분의 런타임 예외는 실행 중 조건의 문제보다는 코드의 논리적인 오류의 경우에 의해 발생함

 

1
2
3
4
5
6
7
8
9
10
11
package spms.test;
 
public class TestMain {
    public static void main(String[] args) {
        int x = 10;
        int y = 0;
        int z = x / y; //0으로 나눈 값이기 때문에 논리적 오류가 발생함
        
        System.out.println("debug> z : " + z);
    }
}
cs

  

3. Exception

실행 도중 필요한 리소스 파일이 없거나, 사용 매체의 문제 등으로 발생하는 예기치 못한 예외들

자바는 try ~ catch 문으로 예외 처리를 해야만 컴파일을 성공시킨다

 

try문에서 예외 발생시 JVM(Java Virtual Machine)은 그 예외가 어떤 것인지 분석하고 그 예외를 담을 수 있는 객체를 만들어서 참조함

=> catch 문은 try문에서 발생한 예외 객체를 인자로 받아와 catch문 내에서 사용

 

* Exception과 Error를 구분하는 기준 : JVM의 겉과 속

ㄱ. 겉 : Exception

ㄴ. 속 : Error

 

* try ~ catch 문에 return이 있다 하더라도 finally문은 반드시 실행된다

* 런타임 예외가 아닌 Exception일 경우 컴파일러는 에러를 발생시킨다

* 한 개의 try문에서 여러 개의 예외가 발생할 시에는 여러 개의 catch를 사용한다

=> 첫 번째 catch문에서 예외의 최상위인 Exception 매개변수를 받게 되면, 두 번째 catch문 부터는 받을 예외가 없어 컴파일 에러가 발생하게 됨

 

* 자바 7.0부터 지원하는 다중 catch 방식

A와 B Exception이 발생했을 때, 동일한 문구를 출력해야 함에도 불구하고 각각의 catch를 써야 함 => 중복 발생

 

1
2
3
4
5
6
7
8
9
    try {
            //예외 발생
        } catch (AException e) {
            System.out.println("예외 발생!");
        } catch (BException e) {
            System.out.println("예외 발생!");
        } catch (CException e) {
            e.printStackTrace();
        }
cs

<중복 예외를 처리하던 기존 자바 코드>

 

1
2
3
4
5
6
7
    try {
            //예외 발생
        } catch (AException || BException e) {
            System.out.println("예외 발생!");
        } catch (CException e) {
            e.printStackTrace();
        }
cs

<자바 7.0부터 지원하는 다중 catch 방식>

 

 

4. Finally

* finally를 가장 잘 활용하는 사례 : IOStream / DB Connection

ㄱ. IO (Input Output) Stream

가비지 컬렉션의 대상이 아닌 것 (가비지 컬렉션 : 자바의 JVM에서 모든 객체를 자동으로 소멸시켜주는 기능)

=> IO Stream 객체들은 개발자가 직접 닫아줘야 함

 

* IO Stream 객체 생성 후, 사용 중 에러가 발생하여 프로그램을 종료시 가비지 컬렉터의 대상이 아니기 때문에 메모리 누수의 원인이 될 수 있음

=> finally 블록을 꼭 추가하고 블록 안에서 IO Stream 객체를 소멸시키는 코드를 넣어야 함

 

 

5. Throw

DB 서버를 연결시 DB 서버에서 접속했다가 사용을 끝내면 자동 접속 종료를 기다리기 전에 편의상 미리 닫아주는 것이 효율적일 때가 있음. 그럴 때 사용

ㄱ. throw : 개발자가 필요에 의해 강제로 발생시키는 예외 코드

메소드 내에서 상위 블럭으로 예외를 던짐

억지로 에러를 발생시킬 때에도 사용하지만, 현재 메소드 에러를 처리한 후 상위 메소드에 여러 정보를 줌으로서 상위 메소드에도 에러가 발생했다는 것을 감지할 수 있음

throw 에약어 뒤에 java.lang.Throwable 클래스를 상속 받은 자식 클래스의 객체를 지정해야 함

 

1
2
3
4
5
6
7
8
9
try {
        //예외를 처리하는 객체 메모리 생성
        Exception e = new Exception(" ");
            
        //JVM이 예외를 감지하도록 고의로 이벤트를 발생시킴
        throw e;
    } catch (Exception e) {
        //예외처리 코드
    }
cs

 

ㄴ. throws : 현재 메소드에서 상위 메소드로 예외를 던짐

첫 번째 메소드에서 예외 발생시 예외를 처리해버리면 그 후의 메소드들은 예외가 발생되었는지조차 모르기 때문에 자바에서는 throws 키워드를 사용함

예외를 자신이 처리하지 않고, 자신을 호출하는 메소드에게 책임을 전가함

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void test1() throws Exception {
    //예외를 발생시키는 코드
}
        
void test2() throws Exception {
            
}
        
void test3() {
    try {
        test2();
    }
    catch (Exception e) {
    //예외를 처리하는 코드
    }
}
cs

 

 

* 메소드 오버라이딩시 throws 예외처리

- 예외를 던지지 않거나

- 부모메소드보다 작거나 같은 범위에서 예외처리를 해야 함

(부모 메소드가 예외처리 되지 않은 상태인 경우 오버라이딩 된 메소드도 예외 처리를 할 수 없음)


'BackEnd > Java' 카테고리의 다른 글

Java :: startsWith() vs indexOf() vs charAt()  (0) 2016.12.26
Java :: Reflection 리플렉션  (0) 2016.12.18
Servlet :: ServletContext vs ServletConfig  (0) 2016.11.22
Java :: Abstract vs Interface  (0) 2016.10.28
Java :: 간단한 JDBC 예제  (0) 2016.10.18

오라클에서는 mysql처럼 limit가 없기 때문에 Rownum을 사용해야 한다.

ex) mysql에서 20개 가져오기
SELECT * FROM 테이블 LIMIT 20;

ex) 오라클에서 20개 가져오기
SELECT * FROM 테이블 WHERE ROWNUM >= 1 AND ROWNUM <= 20;

ex) 오라클에서 시작과 끝사이의 검색된 결과 20개 가져오기
SELECT * FROM 테이블 WHERE ROWNUM >= 1 AND ROWNUM <= 20 AND 컬럼 BETWEEN 시작 AND 끝;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Servlet 2.2
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app />
 
 
Servlet 2.3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app />
 
 
Servlet 2.4
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="servlet-2_4" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
 
 
Servlet 2.5
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="servlet-2_5" version="2.5">
</web-app>
 
 
Servlet 3.0
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
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"
version="3.0">
</web-app>
cs


DD를 조작하여 서블릿에 정보를 전달하기 위한 용도의 인터페이스

 

1. ServletContext

하나의 context (application 범위) 내에서 다른 서블릿 간에 공유가 가능한 데이터

 

a. getServletContext()

ㄱ. jsp에서 사용할 시 : context를 받아오는 용도로 사용
              (ex. ServletContext context = getServletContext(); )
ㄴ. MVC(model2)에서 사용할 시 : Controller의 인터페이스(서블릿의 인터페이스 - GenericServlet)을 받아 사용하게 됨
                                         웹 어플리케이션의 절대 경로를 구하는 servletContext()를 구할 수 있음
                                         (ex. String realFolder = context.getRealPath("upload")


b. request.getSerlvetContext() vs request.getSession().getServletContext() 차이
     session이든 request든 간에 하나의 ServletContext 범위 안에서(하나의 웹 어플리케이션 영역)에 있음
     => 같은 ServletContext를 리턴하기 때문에 실질적인 둘의 차이는 없다


c. 서버의 물리적 경로 구하기
    - 현재 서비스가 돌아가고 있는 서버의 웹서비스 디렉토리 물리 경로를 구할시 사용 (파일 업로드시)

ㄱ. 업로드 디렉토리가 웹서비스 디렉토리 하위에 위치한 경우
    ( ex. request.getSession().getServletContext().getRealPath("/") )
        - 업로드 url : http://localhost\upload
        - 업로드 디렉토리 물리적 경로 : C:\Web\WebContents\upload\
        - 웹서비스 경로 : C:\Web\WebContents\
            - 가장 일반적 방법. 현재 서비스가 돌아가고 있는 서블릿의 경로를 가져옴.
            - 파일 업로드 위치가 실제 업로드 디렉토리 물리적 경로와 같이 서블릿 구동 경로 안에 있는 디렉토리에 포함되어 있을 경우 사용          
 ㄴ. 업로드 디렉토리가 별도 존재 => Tomcat 등의 Context로 추가한 경우
     ( ex. request.getSession().getServletContext().getContext("/upload").getPath("") )
        - 업로드 url : http://localhost\upload
        - 업로드 디렉토리 물리적 경로 : D:\upload\
        -  웹서비스 경로 : C:\Web\WebContents\
            - 업로드 디렉토리가 물리적으로 웹서비스 디렉토리에 포함되지 않고 별도로 존재함
            - 해당 디렉토리는 WAS 상에서 Context 등을 통해 별도로 추가된 경우 사용
 ㄷ. Properties 파일에 실제 저장될 물리적 경로 기입한 경우
        - 최근 가장 많이 사용하는 방법
        - WAS에 따라 처리하는 방식이 조금씩 다르기 때문에 편의성을 위해 사용

 

* ReadOnly : DD에서 config는 <servlet> 내에 있었지만, 개념적으로 Context가 더 상위이기 때문에 위치도 <servlet>보다

  위여야 함

  <coxntext-param>~</context-param> 에서 가져올 땐 getInitParam() 메소드를 사용함

  ReadWrite : getAttribute(), setAttribute() 메소드를 사용하여 특정 scope 조정하여 데이터 공유 가능


 

2. ServletConfig

해당 서블릿에서 사용함

하나의 서블릿에 관련된 초기화 파라미터

=> 주로 그 서블릿의 초기화 파라미터 값들을 설정하고 저장할 수 있음 (파라미터 초기화 : DD 사용)

 

'BackEnd > Java' 카테고리의 다른 글

Java :: Reflection 리플렉션  (0) 2016.12.18
Java :: Exception 예외처리  (0) 2016.12.15
Java :: Abstract vs Interface  (0) 2016.10.28
Java :: 간단한 JDBC 예제  (0) 2016.10.18
Java :: 스레드(Thread)  (0) 2016.10.12

웹 어플리케이션 프로젝트를 분석하다가 다음과 같은 오류가 계속 발생했다.



javax.naming.NamingException: Could not load resource factory class [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory]

라는 오류가 발생하였고 인터넷을 검색하던 중 오류를 해결할 수 있게 되었다.

실제로 현재 톰캣8.5 버전을 사용하고 있는데,


1
2
3
4
5
6
7
8
9
10
11
12
 <Context>
     <Resource name="jdbc/OracleDB" 
         auth="Container"
         type="javax.sql.DataSource" 
         username="dbid23geb" 
         password="dbpass23geb"
         driverClassName="oracle.jdbc.OracleDriver"
         factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
         url="jdbc:oracle:thin:@localhost:1521:XE"
         maxActive="500" 
         maxIdle="100"/>  
 </Context>
cs


Context Resource factory 요소를 다음과 같이 사용하고 있었다.

factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"

톰캣8.0 이상을 사용하는 경우에는 factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory" 로 바꿔줘야 한다.

톰캣7.0 이하일 경우 dpcp, 톰캣8.0 이상일 경우에는 dbcp2로 사용하면 된다.

1. 정의

web.xml 에서 서블릿 설정시 들어가는 숫자

해당 서블릿의 init() 메소드가 호출되는 시기와 순서를 정하는 것


보통의 서블릿은 반드시 '해당 서블릿'에 최초 요청이 들어올 때에만 해당 인스턴스화 초기 설정을 하게 되는데, 시간이 너무 오래 걸리기 때문에 Context의 웹 애플리케이션이 톰캣에 의해 인식되는 시점에 서블릿이 초기화 되도록 설정하는 것

(애노테이션이나 web.xml에 설정한 이름으로 서블릿을 호출하기 전에, 미리 톰캣 시작될 때 해당 서블릿을 호출하는 기술)



2. 방법

음수 : 톰캣 실행시 자동으로 서블릿이 호출되지 않고 load-on-startup을 설정하지 않은 서블릿과 동일해짐(일반 서블릿)

양수 : 0에 가까울수록 먼저 초기화됨. 같은 숫자가 mapping되었을 경우 먼저 작성된 서블릿부터 초기화됨



3. 예시
    1) web.xml 에 mapping하는 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
 
    <display-name>Customer Support Application</display-name>
 
    <servlet>
        <servlet-name>TicketServlet</servlet-name>
        <servlet-class>/tickets</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
</web-app>
cs


2) 애노테이션으로 mapping하는 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.wrox;
 
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
 
//loadOnStartup : tomcat 실행시 무조건 실행(서블릿 실행시가 아니라)
//                숫자가 0보다 크면 서버가 시작될 때 무조건 해당 서블릿을 초기화
//                (숫자가 0에 가까울 수록 먼저 초기화, 숫자 중복시 먼저 작성된 서블릿부터 초기화)
//                숫자가 음수일 경우 톰캣 호출시 서블릿이 호출되지 않고 그냥 보통의 서블릿으로 적용됨
//                web.xml에서 설정 가능
@WebServlet(name = "TicketServlet", urlPatterns = { "/tickets" }, loadOnStartup = 1)
public class TicketServlet extends HttpServlet {
 
    private static final long serialVersionUID = 1L;
 
cs


JVM의 일반적인 실행 영역은 Heap 영역이기 때문에 Heap 영역 메모리를 늘려 줌으로서 시스템 과부하를 막을 수 있다.


1. Eclipse 설치 폴더 > eclipse.ini


2. Heap 영역 시작 크기 수정

사진에서는 Heap 영역의 시작 크기가 Xms256m으로 되어 있다. 아래의 Xmx1024m은 Heap 영역의 최대 크기이다.


Heap 영역 최대 크기 >= Heap 영역 시작 크기이기 때문에 시작 크기를 키워주면 된다.

만약에 최대 크기가 작아지는 경우에는 Heap 영역 자체의 메모리 크기가 작아지는 것이기 때문에 더욱 더 쉽게 과부하에 걸릴 수 있다.



3. Eclipse > Window > Preferance > General > Show heap status

Show heap status 부분을 체크하고 Apply > OK 를 클릭한다.



5. 이클립스에서 Heap 영역 메모리 확인

이클립스의 Heap 영역의 메모리가 1024로 늘어난 것을 확인할 수 있으며, 사용 메모리가 늘어나 과부하가 걸릴 것 같으면 옆에 쓰레기통 모양의 아이콘을 눌러 가비지 컬렉터를 비워주면 된다.

+ Recent posts