레이블이 JDK인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JDK인 게시물을 표시합니다. 모든 게시물 표시

2013년 8월 6일 화요일

[오라클자바닷넷교육강좌]웹애플리케이션에서의 로깅 , Web Application Logging

웹애플리케이션에서의 로깅 

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  



로그를 남겨 프로그램을 디버깅 하는 일은 대단히 중요한 일입니다. 웹 애플리케이션에서의 로깅은 크게 시스템 로깅과 애플리케이션 로깅으로 나누어 볼 수 있는데 시스템 로깅은 사용자의 데이터 보다 애플리케이션의 내부적인 동작에 대한 기록 입니다. 예를 들면 컨테이너가 시작했을 때의 시스템적인 오류 정보 등을 기록하는 것들이 해당 되며 애플리케이션의 로그는 사용자가 로그인을 하는 경우 인증을 한 정보 등을 기록하는 것이 해당 됩니다.

시스템의 오류는 error로 표현되는 반면에 애플리케이션의 에러는 info로 정의가 가능합니다.

--------------------------------------
서블릿 컨테이너를 이용한 로깅
--------------------------------------

서블릿의 스펙에서 개발자들이 컨테이너의 로그 파일에 이벤트 정보를 로깅 할 수 있도록 지원 합니다. 로그파일의 이름이나 위치는 어떤 컨테이너를 사용 하느냐에 따라 다르지만 기록이 된다는 것은 사실 입니다.

java.servlet.ServletContext는 로그를 남기기 위한 두개의 메소드를 제공 합니다.

ppublic void log(Stirng msg);
public void log(String msg, Throwable throwable);

아래는 이 메소드를 Struts의 Action에서 사용 한 예입니다.

[이전의 DB를 이용한 인증 예제의 LoginAction 입니다.]

//로그를 남기자.
                StringBuffer buf = new StringBuffer("LoginAction : User --> ");
                buf.append(id + " logged in session");
                servlet.log(buf.toString());

위의 소스 코딩에 위해 Tomcat의 Console창에 다음과 같은 기록이 남습니다…

정보: action: LoginAction : User --> jcleelogged in session



------------------------
필터사용
-----------------------

필터는 서블릿2.3에 새로 추가된 기능 입니다. 서블릿의 필터를 이용하면 HTTP요청과 응답객체의 Contents를 검사 할 수 있으며 정적인 Contents뿐 아니라 동적인 Contents에 대해서도 필터기능을 이용하는 것이 가능 합니다.

필터링 기능을 이용하여 아래와 같은 일들이 가능 합니다.

- 클라이언트의 요청이 도달하기 전에 웹 리소스에 대해 접근 가능 합니다.
- 클라이언트의 요청이 리소스에 도달하기 전 요청을 처리 할 수 있습니다.
- 요청헤더나 데이터에 대한 수정이 가능
- 응답헤더나 데이터에 대한 수정 가능
- 어떤 리소스를 수행 한 후 리소스에 대한 메소드 호출을 가로챌 수 있습니다.

이 필터 기능을 로깅만을 위해 쓰기에는 아까운 면도 있지만 시스템에서 사용자의 행위를 추적하기에는 적합한 기술 입니다. 필터를 이용해 암호화, URL 및 기타정보에 대한 캐시, 인증,XML Contents를 변환하기 위한 XSLT 변환 등 다양한 일들을 할 수 있습니다.

필터를 생성 하기 위해서는 세 단계를 거쳐야 합니다.

1.        javax.servlt.Filter 인터페이스를 구현하는 자바 클래스를 만듭니다.
2.        web.xml에 filter 요소를 선언 합니다.
3.        웹애플리케이션의 리소스와 함께 filter class를 packaging 합니다.

Javax.servlet.Filter 인터페이스를 구현하는 클래스에서 반드시 구현해야 하는 세가지 메소드는 다음과 같습니다.

public void init(FilterConfig filterConfig) throws ServletException;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
public void destroy( );

[필터 예]


import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletContext;
import javax.servlet.ServletResponse;
import javax.servlet.ServletException;

public class LoggingFilter implements Filter{
        public final static String LOG_FILE_PARAM = "Login.log";
        private FilterConfig filterConfig = null;
        private ServletContext servletContext = null;

        public void init( FilterConfig config ) throws        ServletException {
                // Initialize any neccessary resources here
                this.filterConfig = config;
                this.servletContext = config.getServletContext( );

                // You can get access to initialization parameters from        web.xml
                // although this example doesn't really use it
                String logFileName = config.getInitParameter( LOG_FILE_PARAM );

                // You can log messages to the servlet log like this
                log( "Logging to file " + logFileName );

                // Maybe initialize a third-party logging framework        like log4j
        }

        public void doFilter( ServletRequest request,ServletResponse response,FilterChain filterChain )       
                              throws IOException, ServletException {
                // Log a message here using the request data
                log( "doFilter called on LoggingFilter" );

                // All request and response headers are available to the filter
                log( "Request received from " +        request.getRemoteHost( ) );

                // Call the next filter in the chain
                filterChain.doFilter( request, response );
        }

        public void destroy( ){
                // Remove any resources to the logging framework here
                log( "LoggingFilter destroyed" );
        }

        protected void log( String message ) {
                getServletContext( ).log("LoggingFilter: " + message );
        }

        protected ServletContext getServletContext( ){
                return this.servletContext;
        }
}


[web.xml]

<filter>
                <filter-name>MyLoggingFilter</filter-name>
                <filter-class>LoggingFilter</filter-class>
                <init-param>
                        <param-name>log_file_name</param-name>
                        <param-value>log.out</param-value>
                </init-param>
        </filter>

        <filter-mapping>
                <filter-name>MyLoggingFilter</filter-name>
                <servlet-name>MyExampleServlet</servlet-name>
        </filter-mapping>

        <filter-mapping>
                <filter-name>MyLoggingFilter</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>



다음은 필터 기능을 이용하여 스트럿츠에서 한글 문제를 해결 한 경우 입니다.

[SetCharacterEncodingFilter.java]

package filters;


import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;



public class SetCharacterEncodingFilter implements Filter {

    protected String encoding = null;

    protected FilterConfig filterConfig = null;


    /**
    * Should a character encoding specified by the client be ignored?
    */
    protected boolean ignore = true;


    public void destroy() {

        this.encoding = null;
        this.filterConfig = null;

    }


    public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain)
        throws IOException, ServletException {

        // Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }

        // Pass control on to the next filter
        chain.doFilter(request, response);

    }

    public void init(FilterConfig filterConfig) throws ServletException {

        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;

    }


    protected String selectEncoding(ServletRequest request) {

        return (this.encoding);

    }
}


[web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>

<!-- Example filter to set character encoding on each request -->
<filter>
 <filter-name>Set Character Encoding</filter-name>
 <filter-class>filters.SetCharacterEncodingFilter</filter-class>
 <init-param>
  <param-name>encoding</param-name>
  <param-value>EUC-KR</param-value>
 </init-param>
</filter>

<!-- Define filter mappings for the defined filters -->
<filter-mapping>
 <filter-name>Set Character Encoding</filter-name>
 <servlet-name>action</servlet-name>
</filter-mapping>

    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
       
        <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>3</param-value>
        </init-param>
        <init-param>
            <param-name>detail</param-name>
            <param-value>3</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
   
    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
 
</web-app> 

2013년 8월 2일 금요일

JAVA RandomAccessFile (자바 랜덤파일처리)

임의의 바이트, 텍스트등을 파일내 임의의 위치에 쓸수 있도록 허락
InputStream이나 OutputStream의 서브 클래스는 아니지만 파일의 읽기, 쓰기를 위한 독립적인 메소드를 제공한다. 


 오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 

length() : 파일의 길이 
getFilePointer() : 현재 포인터의 위치 
seek() : 포인터 위치 설정 
readBoolean(), readByte(),readChar(), readShort(), readLong(), readInt(), readFloat(),readDouble(), readLine(), readUTF() : 해당타입의 데이터 읽기 
writeBoolean(), writeByte(),writeChar(), writeShort(), writeLong(), writeInt(), writeFloat(), writeDouble(), writeUTF() : 해당타입의 데이터 쓰기 
close() : 파일 닫기 



import java.io.*; class RandomTest { public static void main(String[] args) throws IOException {      RandomAccessFile raf=new 
                            RandomAccessFile("test.txt","rw");      raf.seek(raf.length());      raf.writeUTF("The end");      raf.close(); } }



----------------
메모장 –  예제
----------------
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class NotePad extends Frame implements ActionListener {
TextArea text = null;
String filename = null;

public NotePad(String title) {
    super(title); // set title
    MenuBar menuBar=new MenuBar();
    Menu fileMenu = new Menu("File");
    menuBar.add(fileMenu);
    MenuItem openItem = new MenuItem("Open...", new MenuShortcut('O'));
    openItem.setActionCommand("Open"); // for getActionCommand
    openItem.addActionListener(this);
    fileMenu.add(openItem);


    MenuItem saveItem = new MenuItem("Save", new MenuShortcut('S'));
    saveItem.setActionCommand("Save"); // for getActionCommand
    saveItem.addActionListener(this);
    fileMenu.add(saveItem);
    MenuItem saveasItem = new MenuItem("Save As...", new MenuShortcut('V'));
    saveasItem.setActionCommand("SaveAs"); // for getActionCommand
    saveasItem.addActionListener(this);
    fileMenu.add(saveasItem);
    fileMenu.addSeparator();
    MenuItem exitItem = new MenuItem("Exit", new MenuShortcut('X'));
    exitItem.setActionCommand("Exit"); // for getActionCommand
    exitItem.addActionListener(this);
    fileMenu.add(exitItem);
    setMenuBar(menuBar);
    text = new TextArea();   


    add(text, "Center");
    addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent we) {
            dispose();
            System.exit(0);
        }
    });
    setSize(500, 400);    setVisible(true);
}
public static void main(String args[]) throws Exception {
    new NotePad("Simple NotePad...");
}
public void actionPerformed(ActionEvent e) {
    String cmd=e.getActionCommand();
    if (cmd.equals("Exit"))
        System.exit(0);
    else if (cmd.equals("Open")) {
        FileDialog dialog=new FileDialog(this, "Text File Open", FileDialog.LOAD);
        dialog.show(); // file dialog is modal
        String filename=dialog.getFile();


      if (filename != null) {
            String directory=dialog.getDirectory();
            if (directory != null)
                filename=directory+filename;
            loadFile(filename);
        }
    }
    else if (cmd.equals("Save")) {
        if (this.filename != null) saveFile(this.filename);
        else {
            FileDialog dialog=new FileDialog(this, "Text File Save", FileDialog.SAVE);
            dialog.show(); // file dialog is modal
            String filename=dialog.getFile();
            if (filename != null) {
                String directory=dialog.getDirectory();
                if (directory != null)
                    filename=directory+filename;
                saveFile(filename);
            }
        }
    }


else if (cmd.equals("SaveAs")) {
        FileDialog dialog=new FileDialog(this, "Text File Save", FileDialog.SAVE);
        dialog.show(); // file dialog is modal
        String filename=dialog.getFile();
        if (filename != null) {
            String directory=dialog.getDirectory();
            if (directory != null)
                filename=directory+filename;
            saveFile(filename);
        }
    }
}


private void loadFile(String filename) {
    BufferedReader in = null; 
    text.setText("");

    try {
        in = new BufferedReader(new FileReader(filename),1024); 
        String string=null;


      while ((string=in.readLine()) != null) {  text.append(string+'\n');    }
        in.close();
    } 
    catch (IOException ie) {System.err.println("File Read Error : "+ie.getMessage()); }
    setTitle("FileName:"+filename);
    this.filename=filename;
}
private void saveFile(String filename) {
    BufferedWriter out = null; 
    try {
        out = new BufferedWriter(new FileWriter(filename));
      String string=text.getText();
        out.write(string); 
      out.close();
  }
    catch(IOException e) { System.err.println("File Read Error : "+e.getMessage()); }
    setTitle("FileName:"+filename);
    this.filename=filename;
}
}

2013년 7월 28일 일요일

(오라클자바개발자실무교육,오엔제이프로그래밍실무교육센터)JAVA Nateive Thread/Green Thread 선점형/비선점형

Sun의 JDK 1.2/1.3에는 JIT(just-In-time) 기술이 도입되어 loading 시점에  바이트코드를 실제 기계에서 수행되는 코드로 바꾼 후 실행하게 함으로써 상당한 성능 향상을 가져왔다 
네이티브와 그린 쓰레드는 자바에서 사용되는 쓰레드의 실제 구현상의 차이를 나타내는 것이다. 쓰레드를 자바 가상 기계 내에서 처리하는 것이 그린 쓰레드이고, 커널의 쓰레드 지원 기능을 이용하는 것이 네이티브 쓰레드이다.


  오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)




비선점형(Non-preemptive)멀티태스킹 :운영체제가 제어권을 가지고 있지 않고 응용 프로그램이 제어권을 가지고 있는 것으로 응용 프로그램이 제어권을 운영체제로 돌려주지 않고 중앙 처리 장치를 독점하면 컴퓨터가 다운되는 현상이 생길 수 있다.(Win3.1, MacOS)

선점형(preemptive) 멀티태스킹 : 운영체제가 제어권을 응용 프로그램에게 부여하는 것으로 응용 프로그램이 제어권을 독점하는 것을 방지하여 안정적인 작업 환경을 지원하는 체제이다.(Win95/98, WinNT, Unix)