2012년 3월 14일 수요일

[tomcat] 한글 깨짐 현상

1. Get방식 해결 방안 - URIEncoding="euc-kr"추가


server.xml
---------------------------------------------------------------------------
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="euc-kr" />


<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="euc-kr"/>
--------------------------------------------------------------------------- 





2. Post방식 해결 방안 - servlet filter 사용하기


파일명 : SetCharacterEncodingFilter.java
--------------------------------------------------------------------------- 

package filter;


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;


public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
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 {
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
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(war로 묶일 web.xml, 톰캣 web.xml이 아니다)

--------------------------------------------------------------------------- 

<?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="WebApp_ID" version="2.5">
  <display-name>recruit</display-name>
  <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>
  <filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>euc-kr</param-value>
</init-param>
 </filter>


 <filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
 </filter-mapping>


</web-app>
--------------------------------------------------------------------------- 


2012년 3월 13일 화요일

[Toad] 단축키


테이블 정보 상세보기
F4 : Table, View, Proc, Funct, Package DESC(테이블명 위에 커서를 두고 F4)


자동완성
Ctrl+. : Table Completion (매칭되는 테이블목록 출력)
Ctrl+T : Columns Dropdown (해당테이블의 컬럼목록 표시)


SQL문 실행
F5 : SQL Editor내의 모든 SQL문 실행
Ctrl+Enter : 현재 커서의 SQL문 실행
F9 : SQL문 실행 후 Grid에 출력


히스토리(과거 수행SQL문 조회)
F8 : 과거에 실행한SQL HISTORY 목록
Alt+Up : History UP
Alt+Down : History DOWN


텍스트 대/소문자 변환
CTRL+L : 텍스트를 소문자로
CTRL+U : 텍스트를 대문자로


주석처리
Ctrl+B : 주석처리
Ctrl+Shift+B : 주석해제


편집 창 전환(이동)
F6 : SQL Editor와 결과창간의 이동
F2 : SQL Editor창 전체화면 전환
Shift+F2 : Grid Output창 전체화면 전환


기타 단축키
F7 : 화면을 모두 CLEAR
Ctrl+Shift+F : 쿼리문을 보기좋게 정렬
Ctrl+F9 : SQL Validate (SQL문을 수행하지 않음)

2012년 3월 12일 월요일

[Eclipse] JAD decompile 사용하기

1. jad.exe, net.sf.jadclipse_3.3.0.jar 다운받기
jad - jad.exe
http://www.varaneckas.com/jad


jadclipse - net.sf.jadclipse_x.x.x.jar 
http://jadclipse.sourceforge.net/wiki/index.php/Main_Page




2. jad.exe는 eclipse 폴더로 이동(eclipse 실행 아이콘 있는 폴더)




3. jadclipse는 eclipse plugin 폴더로 이동(eclipse/plugins 폴더)




4. Eclipse 실행




5. Window →  General  →  Editors  →  File Associations에서 *.class선택 후, JadClipse Class File Viewer(default) 선택(필자는 기본으로 이렇게 설정이 되어있었으나 혹시 모르는 상황이 있을 수 있으니 우선 memo)




6. Window  →  Preference  →  Java  →  JadClipse에서 Ignore existing source에 check

[tomcat] servlet invoker 사용하기

1. web.xml 에서 아래 부분 주석 해제
------------------------------------------------------------------------------
    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>invoker</servlet-name>
        <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
------------------------------------------------------------------------------



2. context.xml에서 <Context>태그 부분 수정
------------------------------------------------------------------------------
<Context reloadable="true" privileged="true"> 
------------------------------------------------------------------------------



** tomcat7.0부터는 servlet3.0을 사용하는 이유로 invoker 기능이 사라졌다.
그래서 찾아보니 그렇게 할 수 있는 java를 만들어 listener로 추가 하는 방법을 구현한 외국분의 사이트를 발견
http://blogs.nologin.es/rickyepoderi/index.php?/archives/44-Tomcat-7-and-the-Invoker-Servlet.html

방법을 정리하자면..
1. InvokerLoadListener.java를 Download
2. web.xml 수정(여기서 말하는 web.xml은 war파일로 묶일 곳의 web.xml, tomcat/conf에 있는 web.xml이 아니다!)

-----------------------------------------------------------------------------

<listener>
        <listener-class>
            sample.invoker.ctxlistener.InvokerLoadListener
        </listener-class>
    </listener>

    <context-param>
        <param-name>invoker.packages</param-name>
        <param-value>
            sample.invoker.servlet,
            sample.invoker.other,
            sample.invoker.another
        </param-value>
        <description>List of packages to check for servlets (comma separated)</description>
    </context-param>
-----------------------------------------------------------------------------
고쳐질 web.xml에 대해서 간단한 설명

listener로 지정한 sample.invoker.ctxlistener.InvokerLoadListener
- 당연히 sample.invoker.ctxlistener패키지에 InvokerLoadListener.java를 넣으라는 것
<param-value>안에는 servlet이 들어가 있는 package를 넣을 것(한 개가 아니고 여러개라면 위처럼 ,를 이용해서 구분하자)



블로거의 단점!
왜!! 첨부가 안되는 것이냐.....
혹시나 나중에 링크가 작동안 할 때를 대비한 InvokerLoadListener.java
-----------------------------------------------------------------------------
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sample.invoker.ctxlistener;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import org.apache.catalina.ContainerServlet;

/**
 *
 * http://snippets.dzone.com/posts/show/4831
 * 
 * @author ricky
 */
public class InvokerLoadListener implements ServletContextListener {

    /**
     * Invoker parameter that defines the packages to search servlets.
     * Comma separated list of packages
     */
    public static final String PACKAGES_PARAMETER = "invoker.packages";
    
    /**
     * Invoker parameter to setup the mapping name. By default is "/servlet/"
     */
    public static final String INVOKER_PREFIX_PARAMETER = "invoker.prefix";

    /**
     * Scans all classes accessible from the context class loader which 
     * belong to the given package and subpackages.
     * 
     * @param packageName
     * @return The list of classes found
     */
    private Set<Class> getClasses(String packageName) {
        Set<Class> classes = new HashSet<Class>();
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            String path = packageName.replace('.', '/');
            Enumeration<URL> resources = classLoader.getResources(path);
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();
                if (resource.getProtocol().equals("jar")) {
                    // inside a jar => read the jar files and check
                    findClassesJar(resource, path, classes);
                } else if (resource.getProtocol().equals("file")) {
                    // read subdirectories and find
                    findClassesFile(new File(resource.getFile()), packageName, classes);
                } else {
                    System.err.println("Unknown protocol connection: " + resource);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classes;
    }

    /**
     * Reads a jar file and checks all the classes inside it with the package
     * name specified.
     * 
     * @param resource The resource url
     * @param path
     * @param classes
     * @return 
     */
    private Set<Class> findClassesJar(URL resource, String path, Set<Class> classes) {
        JarURLConnection jarConn = null;
        JarFile jar = null;
        try {
            jarConn = (JarURLConnection) resource.openConnection();
            jar = jarConn.getJarFile();
            Enumeration<JarEntry> e = jar.entries();
            while (e.hasMoreElements()) {
                JarEntry entry = e.nextElement();
                if ((entry.getName().startsWith(path + "/")
                        || entry.getName().startsWith(path + "."))
                        && entry.getName().endsWith(".class")) {
                    String name = entry.getName().replace('/', '.');
                    name = name.substring(0, name.length() - 6);
                    checkClass(name, classes);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                jar.close();
            } catch (IOException e) {
            }
        }
        return classes;
    }

    /**
     * Recursive method used to find all classes in a given file (file
     * or directory).
     *
     * @param file   The base directory
     * @param packageName The package name for classes found inside the base directory
     * @ classes The list of classes
     * @return The same classes
     * @throws ClassNotFoundException
     */
    private Set<Class> findClassesFile(File file, String packageName, Set<Class> classes) {
        if (file.isFile() && file.getName().endsWith(".class")) {
            //classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
            checkClass(packageName.substring(0, packageName.length() - 6), classes);
        } else {
            File[] files = file.listFiles();
            for (File f : files) {
                findClassesFile(f, packageName + "." + f.getName(), classes);
            }
        }
        return classes;
    }

    private Set<Class> checkClass(String name, Set<Class> classes) {
        try {
            Class clazz = Class.forName(name);
            if (HttpServlet.class.isAssignableFrom(clazz)
                    && ContainerServlet.class.isAssignableFrom(clazz)) {
                classes.add(clazz);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return classes;
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized(ServletContextEvent e)");
        ServletContext sc = sce.getServletContext();
        String list = sc.getInitParameter(PACKAGES_PARAMETER);
        String prefix = sc.getInitParameter(INVOKER_PREFIX_PARAMETER);
        if (prefix == null) {
            prefix = "/servlet/";
        }
        if (list != null) {
            String[] packages = list.split(",");
            for (int i = 0; i < packages.length; i++) {
                String packageName = packages[i].trim();
                if (packageName.length() > 0) {
                    System.out.println("Checking package: " + packageName);
                    // load classes under servlet.invoker
                    Set<Class> classes = getClasses(packageName);
                    System.out.println("size: " + classes.size());
                    for (Class clazz : classes) {
                        String mapping = prefix + clazz.getName();
                        System.out.println("Adding '" + clazz.getName() + "' in mapping '" + mapping + "'");
                        ServletRegistration sr = sc.addServlet(clazz.getName(), clazz.getName());
                        sr.addMapping(mapping);
                    }
                }
            }
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed(ServletContextEvent e)");
    }
}
-----------------------------------------------------------------------------





[tomcat] war파일 GUI를 이용해서 deploy하기

1. localhost:8080에서 Tomcat Manager로 이동


2. ID/PASSWORD 입력


톰캣 설치 시, 사용자에 대한 설정은 하지 않는다.
manager GUI를 사용하기 위해서는 tomcat-users.xml에서 해당 내용 주석 제거 후, bold 글씨체 추가


Ex) username과 password를 admin으로 설정한다고 했을 때
--------------------------------------------------------------------------------

  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <role rolename="manager-gui"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="admin" password="admin" roles="tomcat,role1,manager-gui"/>
  <user username="role1" password="tomcat" roles="role1"/>

--------------------------------------------------------------------------------


3. Deploy에서 Context Path (required) 지정 후, war파일 올리기

2012년 3월 11일 일요일

[tomcat] startup.bat 사용하기 및 윈도우 서비스 등록

항상 이클립스에서만 환경 구성해서 미리 마련된 곳에 올리다 보니 startup.bat 실행하는 것도 어렵다..;

1. tomcat install

2. 환경변수 등록

CATALINA_HOME        D:\Util\tomcat6.0
JAVA_HOME               C:\Program Files\Java\jdk1.6.0_30
(JDK1.5가 Path에 full_name으로 잡혀있었지만, JDK1.6을 사용해야 하는지라 JAVA_HOME은 1.6으로 setting) 

참고로, 환경변수를 잡아주지 않으면 이런 에러가 발생
-------------------------------------------------------------------------------------------------------------
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined  
At least one of these environment variable is needed to run this program      
-------------------------------------------------------------------------------------------------------------

3. CATALINA_HOME/bin으로 이동 후 startup.bat 실행(실행 안 되면 reboot)

4. http://localhost:8080/ 에서 고양이 page로 확인


* 서비스 등록
CATALINA_HOME/bin으로 이동 후 service install

2012년 3월 1일 목요일

Apache + Tomcat + ssl연동

* IBM HTTP Server 7.0 + (Tomcat4.1.40, Tomcat6.0) 연동

1. Apache Download

2. Tomcat Download

3. mod_jk.so Download (tomcat과 Apache를 연동시킬 때 필요한 파일 묶음)
http://mirror.apache-kr.org//tomcat/tomcat-connectors/jk/binaries/windows/ 


apache version에 맞춰서 해야한다.
tomcat-connectors-1.2.32-windows-i386-httpd-2.2.x.zip 

IHS7.0은 Apache 2.2.x version이라 2.0.x version을 사용했을 때 LoadModule을 할 수 없었다.




4. 받은 파일 압축 푼 후 HTTPServer/modules 밑에 mod_jk.so을 복사한다.


5. HTTPServer/conf/httpd.conf 편집
LoadModule jk_module modules/mod_jk.so
include conf/mod_jk.conf

내용추가

6. HTTPServer/conf에 mod_jk.conf 파일 추가
ajp13의 application 시작 root
   http://localhost:7777/jQueryTest/
ajp14의 application 시작 root
   http://localhost:8080/ttttttttt/

JkWorkersFile "C:/IBM/HTTPServer/conf/workers.properties"
JkLogFile "D:/eclipse/tomcat6.0/logs/mod_jk.log"
JkLogLevel error
JkAutoAlias "D:/eclipse/tomcat6.0/webapps"
JkMount /ttttttttt/* ajp14
JkUnmount /ttttttttt/*.php ajp14
JkMount /jQueryTest/* ajp13
JkUnmount /jQueryTest/*.php ajp13
<Directory "D:/eclipse/tomcat6.0/webapps">
 Options Indexes FollowSymLinks
 allow from all
</Directory>


7. HTTPServer/conf에 workers.properties 파일 추가
ajp13 = TOMCAT6.0
ajp14 = TOMCAT4.1


worker.ajp.13.port, worker.ajp.14.port는 해당 TOMCAT server.xml에서 맞춰줄 것
tomcat을 2개 돌릴 때 default 설정으로 돌리면 port가 충돌나면서 start가 되지 않는다.
이를 피하기 위해 server.xml에 들어가 기본 설정을 바꿔줘야 한다.
필자는 하나는 default, 하나는 시작 숫자를 7로 바꿔주었다.



workers.tomcat_home="D:/eclipse/tomcat6.0"
workers.java_home="C:/Program Files/Java/jdk1.6.0_30"
ps=/

worker.list=ajp12, ajp13, ajp14
worker.ajp12.port=8007
worker.ajp12.host=localhost
worker.ajp12.type=ajp12
worker.ajp12.lbfactor=1

worker.ajp13.port=7009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1


worker.ajp14.port=8009
worker.ajp14.host=localhost
worker.ajp14.type=ajp13
worker.ajp14.lbfactor=1

worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=ajp12, ajp13, ajp14
worker.inprocess.type=jni
worker.inprocess.class_path=(workers.tomcathome)(ps)lib(ps)tomcat.jarworker.inprocess.cmdline=startworker.inprocess.stdout=(workers.tomcat_home)(ps)logs(ps)inprocess.stdout
worker.inprocess.stderr=(workers.tomcathome)(ps)logs$(ps)inprocess.stder


8. ssl 연동

SSL관련된 주석 제거 후 SSL 가능하나 https로 진입 후 어디로 가야할지 JkMount 이용해 지정


LoadModule ibm_ssl_module modules/mod_ibm_ssl.so
Listen 0.0.0.0:443
## IPv6 support:
#Listen [::]:443
<VirtualHost *:443>
JkMount /jQueryTest/* ajp13
JkUnmount /jQueryTest/*.php ajp13


SSLEnable
SSLProtocolDisable SSLv2
</VirtualHost>
KeyFile C:/IBM/HTTPServer/ssl/key.kdb
SSLDisable