'클래스'에 해당되는 글 3건

multipart 클래스 사용 예제



<!-- http://servlets.com/cos/ 접속 -> cos-26Dec2008.zip 파일 다운로드 (파일은 바뀔 수 있음) -->


<!-- WEB-INF -> lib 폴더에 추가 -->


<!-- fileSelect.jsp -->


<?xml version="1.0" encoding="EUC-KR" ?>

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR" />

<title>파일 업로드예제 폼</title>

</head>

<body>

<h2>파일을 업로드예제를 시작 합니다.</h2>

<form action="upPro.jsp" name="fileUp" method="post" enctype="multipart/form-data">

<table border="1">

<tr>

<td>작성자 : </td>

     <td><input type="text" name="user" /></td>

</tr>

<tr>

<td>제     목 : </td>

     <td><input type="text" name="title" /></td>

</tr>

<tr>

<td>파     일 : </td>

     <td><input type="file" name="uploadFile" /></td>

</tr>

<tr>

<td colspan="2" align="center">

         <input type="submit" value="전송" />

     </td>

</tr>

</table>

</form>

</body>

</html>




<!-- fileupload.jsp -->


<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>

<%@ page import="com.oreilly.servlet.*, com.oreilly.servlet.multipart.*" %>

<%@ page import="java.io.*, java.util.*" %>

<%

// 먼저 파일이 저장될 서버의 실제 폴더 경로를 구합니다.. ServletContext 객체를 이용합니다.

String realFolder = "";

// webApps 상의 폴더명입니다.. 이 폴더에 해당하는 실제 경로를 찾아서  realFolder 로 매핑시킵니다.

String saveFolder = "fileSave";

String charset = "euc-kr";

int maxSize = 1024 * 1024 * 1024;


realFolder = this.getServletContext().getRealPath(saveFolder);

out.println("실제 경로는 다음과 같은 위치 입니다. : " + realFolder);


try {

// 이제부터 multipartRequest 객체를 이용해서 파일을 업로드 합니다.

MultipartRequest multi = null;

multi = new MultipartRequest(request, realFolder, maxSize, charset, new DefaultFileRenamePolicy());

// 이상으로 파일 업로드 끝입니다.


//이제부터 Form에서 전송되는 파라미터 확인 해 봅니다.

Enumeration<String> params = multi.getParameterNames();

while (params.hasMoreElements()) {

String name = params.nextElement();

String value = multi.getParameter(name);

out.println("<br />" + name + " : " + value + "<br />");

}


out.println("<hr color='red' />");

out.println("업로드 된 파일의 정보 입니다.");


Enumeration files = multi.getFileNames();


while (files.hasMoreElements()) {

String name = (String)files.nextElement();

String fileName = multi.getFilesystemName(name);

String originName = multi.getOriginalFileName(name);

String type = multi.getContentType(name);


// 전송된 파일의 실제 속성을 열여봅니다.

File file = multi.getFile(name);


out.println("파라미터의 이름 : " + name + "<br />");

out.println("실제 파일 이름 : " + originName + "<br />");

out.println("저장된 파일 이름 : " + fileName + "<br />");

out.println("파일타입 : " + type + "<br />");


if (file != null) {

out.println("크기 : " + file.length());

out.println("<br />");

}

}

} catch (Exception e) {

e.printStackTrace();

}

%>

'JAVA' 카테고리의 다른 글

multipart 파일체크  (4) 2019.04.09
multipart 파라미터 받기  (0) 2019.02.28
multipart 케스팅  (0) 2019.02.28
multipart 리졸버  (0) 2019.02.28
method 동적 호출  (0) 2019.02.27
블로그 이미지

마크제이콥스

초보 개발자의 이슈및 공부 내용 정리 블로그 입니다.

,

Class.forName 사용하기


JAVA.LANG.CLASS클래스


클래스의 정보를 얻기위한 클래스 

즉, 클래스의 정보를 얻어오는 클래스입니다.


forName() : 물리적인 클래스 파일명을 인자로 넣어주면 이에 해당하는 클래스를 반환해줍니다.

클래스를 조사하기 위한 클래스입니다.

변수로 클래스를 만들때 Class.forName 은 유용하게 쓰인다.


예제소스 (물리적인 WhitePerson 클래스를 인스턴스한다.)


try{

Class c = Class.forName("poly.WhitePerson");

// 로딩단계(클래스조사),메모리에 올라오지는 않음(newInstance()해줘야함)

Person p=(WhitePerson)c.newInstance();

// newInstance() 반환형이 Object형이므로 다운캐스팅한다.

}catch(ClassNotFoundException e1){

//클래스를 찾지못했을 경우에 대한 예외사항 

System.out.println("클래스가 존재하지 않습니다.");

}catch(InstantiationException e2){

//인스턴스(new)실패시에 대한 예외사항

System.out.println("메모리에 올릴수 없습니다.");

}catch(IllegalAccessException e3){

//파일접근에 대한 예외사항 

System.out.println("클래스파일 접근 오류입니다.");

}


종합예제 소스

물리적(폴더)에 있는 클래스 (WhitePerson/BlackPerson/YellowPerson)

를 입력받아 해당클래스를 로딩&생성하여 속성(color 변수)에 대한 값을 출력!!!!!

 

[1] 사용자가 입력한 문자열에 해당하는 클래스를 얻어옵니다.

[2] 얻어온 클래스를 메모리에 올린후 

[3] 해당 메서드를 실행합니다.


1. package classtest;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import poly.*;


public class ClassApp extends JFrame implements ActionListener{

private JPanel p;

private JLabel la;

private JTextField txt1, txt2;

private JButton bt;


public ClassApp(){

p=new JPanel();

la=new JLabel("생성할 클래스 입력");

txt1=new JTextField(15);

txt2=new JTextField(15);

bt=new JButton("생성");

p.add(txt1);

p.add(bt);

p.add(txt2);

add(p);

bt.addActionListener(this);

setSize(200,150);

setVisible(true);

}


public void actionPerformed(ActionEvent ae){

String className = txt1.getText();


try{

Class c=Class.forName(className);

// 로딩단계(클래스조사), 메모리에 올라오지는 않음

Person p = (Person)c.newInstance();

txt2.setText(p.getColor());

}catch(ClassNotFoundException e1) {

//클래스를 찾지못했을 경우에 대한 예외사항

txt2.setText("클래스가 없습니다.");

}catch(InstantiationException e2){

// 인스턴스(new)실패시에 대한 예외사항

txt2.setText("인스턴스를 생성할수 없습니다.");

}catch(IllegalAccessException e3){

//파일접근에 대한 예외사항

txt2.setText("엑세스 할수 없습니다.");

}

}


public static void main(String[] args){

new ClassApp();

}

}


Class.forName()ClassLoader.loadClass() 차이점


일단 Class.forName() 메서드는 인자가 한 개 짜리인 것과 세 개 짜리인 것이 있습니다.


static Class<?>     forName(String className)

          Returns the Class object associated with the class or interface with the given string name.



static Class<?>     forName(String name, boolean initialize, ClassLoader loader)

          Returns the Class object associated with the class or interface with the given string name, using the given class loader.


1. 클래스를 로딩할 때 사용되는 클래스로더 차이


인자가 한개 짜리인 forName(String) 메서드는 클래스를 로딩할 때 사용하는 클래스로더가 저 코드를 실행하는 클래스로더가 됩니다. 하지만 ClassLoader.loadClass()를 사용하면 당연히 자기 자신을 사용해서 클래스 로딩을 실행하게 되죠. 

(그렇다고 해서 반드시 해당 클래스로더가 읽어온다는 보장은 없죠. 그 부모가 읽어올 수도 있고 클래스 패스에 없을 수도 있고 암튼 여기서 로딩한다는 건 로딩을 시도한다고 보시기 바랍니다.)


하지만 Class.forName(String, boolean, ClassLoader)를 사용하면 클래스 로더를 지정해 줄 수 있습니다.



2. 초기화


Class.forName(String) 메서드를 사용하면 곧바로 클래스의 static 초기화 블럭과 static 멤버 변수의 값을 초기화 합니다. 하지만 ClassLoader.loadClass()를 사용하면 해당 클래스를 처음으로 사용하기 전까지 초기화가 지연됩니다.

이것 역시 Class.forName(String, boolean, ClassLoader)의 두번째 인자값을 이용하여 조절할 수 있습니다.


- 클래스 초기화 에러

만약 Class.forName(String)을 사용해서 로딩할 때 static 영역에서 에러가 난다면 해당 클래스는 다시 로딩할 수가 없습니다. 특정 클래스로더가 일단 로딩한 클래스는 다시 로딩할 수가 없죠. 

그래서 NoClassDefinitionFound 에러가 날 수도 있습니다.

이때는 해당 클래스로더 인스턴스를 버리고 새로 만들어야 하는데 그럴 때를 대비해 인자 세개짜리 forName을 쓰라는군요.

결국 forName()으로 클래스를 로딩할 떄는 별 개의 클래스로더를 쓰라는건데 그렇게 단순해 보이지가 않는데 클래스로더를 지정해 둔다고 해봤자. 보통 App CL로 읽어올테고 그럼 App CL 인스턴스를 버리라고?? 그건 좀..

forName으로 읽어올 클래스를 클래스패스를 가지고 있으면서 parent로 위임하지도 않는 CL을 이용해서 forName으로 읽은 경우라면 뭐 괜찮을지도 모르겠습니다. 어쨋거나 직접 통제가 가능한 클래스로더를 사용해야 겠네요.

'JAVA' 카테고리의 다른 글

[JAVA] ClassLoader  (0) 2017.10.30
[JAVA]classes 위치 가져오기  (0) 2017.10.30
[JAVA] class 클래스 로딩  (0) 2017.10.30
[JAVA] class 동적로딩  (0) 2017.10.30
[JAVA] class path에서 resource 찾기  (0) 2017.10.30
블로그 이미지

마크제이콥스

초보 개발자의 이슈및 공부 내용 정리 블로그 입니다.

,

[JAVA] class 클래스 로딩

JAVA 2017. 10. 30. 13:31

class 클래스 로딩


CLASSPATH에 없는 클래스 로딩


java.lang.reflect를 이용하면 우리가 원하는 클래스에 대한 invoke가 가능하다는 것은 알고 있을 것이다.

하지만 classpath에 등록안되어진 클래스들에 대해서는 어떻게 할 것인가?

일일이 사용자에게 클래스 패스를 설정하게 할수만은 없는 일 입니다.

보통의 엔진들을 보게 되면 install되어진 디렉토리의 위치만을 세팅하도록 하고 있다.

set JAVA_HOME 이라던지

set ANT_HOME 이라던지

쉘스크립트에 의하여 그러한 것들을 정의하여 java process를 띄우곤 하는데 그러면 내가 ant.jar등을 등록하지 않았음에도 불구하고 해당 애플리케이션들이 잘 작동하는 이유는 무엇일까요?

그건은 바로 ClassLoader에 숨겨져 있습니다.


아래에서 보여지는 샘플코드는 classpath 프로퍼티에 등록이 되어지지 않은 클래스들에 대한 조작을 할 것입니다. 

그렇게 함으로서 우리들이 만든 애플리케이션이 별다른 클래스로딩 정책 없이도 작동이 될수 있습니다.

그러려면 또한 잘 알아야 하는것이 reflection API가 있습니다.


이 부분에서는 그러한 것을 생략하고 URLClassLoader를 이용하여 디렉토리나 jar파일을 등록하여 가져오는 방법을 설명하도록 하겠습니다.


ClassLoader클래스는 이미 1.0API부터 존재했으며 URLClassLoader1.2에 새롭게 추가된 클래스이다.


우리가 사용하는 파일시스템이 URL이란 이름하에 조작이 될 수 있다는 것을 우선 명심해주시기 바랍니다.


이유는 file:// 이란 URI를 사용하기 때문이다.


아래에서는 특정한 티렉토리 안의 jar 파일에 대한 class loading샘플을 보여줍니다.


import java.io.*; 

import java.net.*; 


public class ClassLoading { 

public static void main(String [] args) throws Exception { 

   // Create a File object on the root of the directory containing the class file 

    File file = 

new File("D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar"); 

     

    try { 

      // Convert File to a URL 

      URL url = file.toURL();          

// file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar 

            URL[] urls = new URL[]{ url }; 

            System.out.println(urls); 

       

            // Create a new class loader with the directory 

            ClassLoader cl = new URLClassLoader(urls); 

            System.out.println(cl); 

       

            // Load in the class; Logger.class should be located in 

     // the directory file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar 

      

Class cls = cl.loadClass("org.apache.log4j.Logger"); 

            System.out.println(cls); 

     

    } catch (MalformedURLException e) { 

        e.printStackTrace(); 

    } catch (ClassNotFoundException e2) { 

          e2.printStackTrace(); 

    }

   

  }

}


위에서 보는 것처럼 디렉토리를 설정하거나 특정 jar 파일을 사용할 수 있도록 작성합니다.

특정파일이 가르키지 않으면 해당 디렉토리의 class파일들을 package형태로 참조하도록 할 수 있는데 해당 디렉토리에 대한 클래스 로딩 샘플을 아래와 같습니다.


import java.io.*; 

import java.net.*; 


public class ClassLoading {

//Create a File object on the root of the directory containing the class file

File file = 

new File("D:/_CVSDevelop/jca_hello_adapter/build/classes");


try {

// Convert File to a URL

URL url = file.toURL();

// file:/D:/_CVSDevelop/jca_hello_adapter/build

URL[] urls = new URL[]{ url };

System.out.println(urls);


// Create a new class loader with the directory 

ClassLoader cl = new URLClassLoader(urls);

System.out.println(cl);


// Load in the class; Test.class should be located in 

// the directory //file:/D:/_CVSDevelop/jca_hello_adapter/build/classes/com/b//ea/jca/test/Test 

Class cls = cl.loadClass("com.bea.jca.test.Test"); 

System.out.println(cls); 

}catch (MalformedURLException e){

e.printStackTrace(); 

}catch (ClassNotFoundException e2){

e2.printStackTrace();

}

}


위와 같은 경우에는 classpath의 root로 잡은 디렉토리를 기준의 package형태로 설정되 파일을 로딩하여 사용할수 있도록 한다.

이 이후의 코딩에는 class가 newInstance를 취한 후 method를 

invoking해야 하는 과정을 거치게 되는데 한 가지 주의할 점은 해당 클래스를 반드시 reflection API를 이용하여 호출해야 한다는 점이다.

대략 아래의 코드정도를 이용하여 main 메소드등을 호출하는 클래스를 작성할 수 있을 것이다.


public void invokeClass(String name, String[] args)

throws ClassNotFoundException, NoSuchMethodException,

InvocationTargetException

{

Class c = loadClass(name);

Method m = c.getMethod("main", new Class[] {args.getClass()});

m.setAccessible(true);

int mods = m.getModifiers(); 

if(m.getReturnType() != void.class || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)){

throw new NoSuchMethodException("main");

}

try {

m.invoke(null, new Object[] { args }); 

}catch (IllegalAccessException e) { 

// This should not happen, as we have disabled //access checks 

}

}


위와 같은 샘플을 이용하게 되면 서버측 프로그램에 대한 작성을 해볼 수 있는 좋은 기회가 아닐까 생각 됩니다.



'JAVA' 카테고리의 다른 글

[JAVA]classes 위치 가져오기  (0) 2017.10.30
[JAVA] Class.forName 사용하기  (0) 2017.10.30
[JAVA] class 동적로딩  (0) 2017.10.30
[JAVA] class path에서 resource 찾기  (0) 2017.10.30
[JAVA] cache function  (0) 2017.10.27
블로그 이미지

마크제이콥스

초보 개발자의 이슈및 공부 내용 정리 블로그 입니다.

,