'분류 전체보기'에 해당되는 글 223건

  1. 2011.11.18 jQuery 로 메뉴 접었다~ 펼쳤다~ 구현하기 39
  2. 2011.11.17 이클립스(eclipse) 실행시 Java was started but returned exit code=13 에러가 날때 4
  3. 2011.11.16 제우스 + 스프링 프로젝트 디플로이시 java.lang.IllegalStateException: Unable to locate the default servlet for serving static content 이 발생할때 4
  4. 2011.11.16 재귀함수(Recursive funtion)을 이용한 특정 폴더 아래의 모든 파일정보 읽어서 출력하기
  5. 2011.11.16 JAVA/JSP SQL Injection 해킹 방지를 위한 코딩 5

jQuery 로 메뉴 접었다~ 펼쳤다~ 구현하기



jQuery 를 이용하면 드럽게 복잡해질 자바스크립트가 매우매우매우매우매우 심플해 진다. 간단한 몇 라인의 코딩만으로 쉽게 간지나는 것을 맨들 수 있다.

고것을 설명하기 위해 접었다 펼쳐졌다 하는 간단한 메뉴를 만들어 보았다. 본인이 디자이너가 아닌 관계로 화면은 쫌 그지같지만 css 만 적용시키면 쓸만한 있어 보이는 메뉴를 바로 맨들 수 있다.

대충 요렇게 하는 것이다 라고 설명을 하는 것이니 디자인 과감히 생략한다.

우선 처음으로 맨들어볼 메뉴는 요렇다.( 클릭하면 접었다 펼쳐졌다 접었다 펼쳐졌다 함 )

요런 모양을 맨들기 위한 html 마크업은 요렇게~ html 태그에 onclick=""; 어쩌고 하는 지저분한 자바스크립트 하나 안들어간 순결하고 *(-_-)* 깔끔한 마크업이다.
<div>
	<ul>
		<li class="menu">
			<a><img src="" alt="상위메뉴이미지1"/></a>
			<ul class="hide">
				<li>메뉴1-1</li>
				<li>메뉴1-2</li>
				<li>메뉴1-3</li>
				<li>메뉴1-4</li>
				<li>메뉴1-5</li>
				<li>메뉴1-6</li>
			</ul>
		</li>

		<li class="menu">
			<a><img src="" alt="상위메뉴이미지2"/></a>
			<ul class="hide">
				<li>메뉴2-1</li>
				<li>메뉴2-2</li>
				<li>메뉴2-3</li>
				<li>메뉴2-4</li>
				<li>메뉴2-5</li>
				<li>메뉴2-6</li>
			</ul>
		</li>
	</ul>
</div>


스타일은 요정도로만
<style>
	.menu a{cursor:pointer;}
	.menu .hide{display:none;}
</style>


중요한 jQuery 를 이용한 자바스크립 소스 부분이다. 심플스럽기 서울역에 그지없다. 주석을 빼면 3~4줄 정도밖에 안된다. 아주 짧으면서도 의미가 쏙쏙 들어오는!
<script>
	// html dom 이 다 로딩된 후 실행된다.
	$(document).ready(function(){
		// memu 클래스 바로 하위에 있는 a 태그를 클릭했을때
		$(".menu>a").click(function(){
			// 현재 클릭한 태그가 a 이기 때문에
			// a 옆의 태그중 ul 태그에 hide 클래스 태그를 넣던지 빼던지 한다.
			$(this).next("ul").toggleClass("hide");
		});
	});
</script>




그냥 뿟뿟 나타났다 사라지는게 허접스럽게 느껴진다면 여기서 한단계 더 나아가

클릭했을때 보드랍게 슬라이딩 되면서 나타났다 사라지는 것을 맨들어 보자. 마크업과 스타일은 손댈필요 없이 자바스크립만 요래 살짝 바꿔 주면 된다.
<script>
	// html dom 이 다 로딩된 후 실행된다.
	$(document).ready(function(){
		// menu 클래스 바로 하위에 있는 a 태그를 클릭했을때
		$(".menu>a").click(function(){
			var submenu = $(this).next("ul");

			// submenu 가 화면상에 보일때는 위로 보드랍게 접고 아니면 아래로 보드랍게 펼치기
			if( submenu.is(":visible") ){
				submenu.slideUp();
			}else{
				submenu.slideDown();
			}
		});
	});
</script>

 바꾼결과( 클릭해 보셈 )



그렇다면 마지막으로 클릭했을때의 기능은 남겨두고 마우스가 오버되면 메뉴가 자동으로 펼쳐지게 맨들어 보자. 자바스크립트를 살짝 요래 수정하면 된다.
<script>
	$(document).ready(function(){
		$(".menu>a").click(function(){
			var submenu = $(this).next("ul");

			// submenu 가 화면상에 보일때는 위로 보드랍게 접고 아니면 아래로 보드랍게 펼치기
			if( submenu.is(":visible") ){
				submenu.slideUp();
			}else{
				submenu.slideDown();
			}
		}).mouseover(function(){
			$(this).next("ul").slideDown();
		});
	});
</script>

 바꾼결과( 마우스를 올려 보셈 )




진짜 진짜 마지막으로,

맨처음 뜰때 부터 두번째 메뉴가 펼쳐진 상태로 뜨게 하고 싶다면? 간단하게 두번째 서브메뉴 ul 에 지정된 hide 클래스를 지우면 되지만,

자바스크립트적인 방법으로는 요렇게 하면 된다.
<script>
	$(document).ready(function(){
		$(".menu>a").click(function(){
			var submenu = $(this).next("ul");

			// submenu 가 화면상에 보일때는 위로 보드랍게 접고 아니면 아래로 보드랍게 펼치기
			if( submenu.is(":visible") ){
				submenu.slideUp();
			}else{
				submenu.slideDown();
			}
		}).mouseover(function(){
			$(this).next("ul").slideDown();
		});


		// menu class 중에 두번째 있는 menu 의 하위에 있는 a태그에 클릭 이벤트를 발생시킨다.
		$(".menu:eq(1)>a").click();
	});
</script>


이클립스(eclipse) 실행시 Java was started but returned exit code=13 에러가 날때

램을 4기가로 업그레이드 하면서 4기가 램을 모두 활용하기 위함과 동시에 깔쌈하고 쾌적한 윈도우로 다시 돌아가기 위해 64bit 윈도우7을 설치했다.

다 설치한다음에 쓸 후로그램들을 이것저것 다 설치하고

흥미진진한 개발의 세계로 발을 다시 살포시 디밀기 위해 JDK 도 64bit 버전으로 뿟 설치했다.




이클립스도 새로 받아서 하면 좋겠지만 훌러그인들을 다시 설치하는게 시간도 많이 걸리고 귀찮기도 해서 전에 쓰던 이클립을 그대로 쓰기로 했다.
(※ 이클립은 포맷하기 전에 압축해서 백업해 뒀다가 다시 압축만 풀어주면 전에 쓰던 이클립을 고대로 쓸 수 있다.)

이클립을 실행하려고 따블클릭을 했는데 실행이 안된다. Java was started but returned exit code=13 에러와 함께.


 왜 그런가 했더만, 이유는 JDK는 64bit 버전을 설치했는데 이클립은 32bit용 버전이였기 때문이다.

64bit용 이클립을 새로 받아서 압축풀고 실행을 했더니 실행이 잘된다. 다시 훌러그인들을 설치해야 하지만 -_-;



아무튼 Java was started but returned exit code=13  에러가 뜰때는 JDK 에 맞는 이클립 32bit용 혹은 64bit용을 새로 받아야 한다~~~ 


제우스 + 스프링 프로젝트 디플로이시 java.lang.IllegalStateException: Unable to locate the default servlet for serving static content 이 발생할때


개발환경으로 Jetty 를 써가며 개발하다 실제 서버인 JEUS 에 프로젝트를 디플로이 할려고 했는데

java.lang.IllegalStateException: Unable to locate the default servlet for serving static content. Please set the 'defaultServletName' property explicitly.

어쩌고 하는 에러가 났다.




쪽~~~ 찾아보니 에러가 나는 이유는 "/" 경로를 처리하기 위해 등록했던 스프링 설정파일 중의 <mvc:default-servlet-handler/> 요 설정 때문이였다.




원래 <mvc:default-servlet-handler/> 설정할때 <mvc:default-servlet-handler default-servlet-name="디폴트서블릿 이름"/> 요런식으로 WAS 의 디폴트 서블릿 이름을 설정해 줘야 하는데,

tomcat, resin, weblogic, websphere 같은 외국에서 맨든 was 들은 <mvc:default-servlet-handler/> 요렇게 편리하게 설정할수 있도록

스프링 개발자가 주요 was 에 대해 처리를 해줘서, 굳이 디폴트 서블릿 이름을 안적어 줘도 됬었던 것이다.




아무튼 Jeus 에서 에러를 해결하기 위해서는 Jeus 에서 쓰는 디폴트 서블릿 이름인 WorkerServlet 을
<mvc:default-servlet-handler default-servlet-name="WorkerServlet"/>

요래 설정해 주면 해결할 수 있다.





※ 디폴트 서블릿 이름을 알려면 ?
각 was 설치 디렉토리 아래쪽으로 설정 파일들 모아 놓은데 보면 web.xml 파일이 있다. 예를 들어 톰캣 같은 경우는 톰캣설치디렉토리/conf/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-name>default</servlet-name> 에서 default 가 디폴트 서블릿 이름이다.





※ was 별 default servlet name
Tomcat : default
Resin : resin-file
Weblogic :  FileServlet
WebSphere : SimpleFileServlet
jetty : default
jboss : default
jeus : WorkerServlet



재귀함수(Recursive funtion)을 이용한 특정 폴더 아래의 모든 파일정보 읽어서 출력하기


왠지 도움이 될것 같다면 추천을 *(-_-)*


이런건 학교 뎅길때 숙제로 많이 하던것이다.

복잡해 보이는 문제도 이빠이 작은 부분으로 쪼개서 생각하고 고걸 recursive funtion 화 시키면 쉽게! 심플하게! 문제를 해결할 수 있다.



요 문제의 경우, 작게 쪼개서 생각할만한 부분은

어떤 디렉토리가 있으면 그 디렉토리 안에 있는 디렉토리들과 파일들을 출력할래염!!! 이다.

디렉토리의 디렉토리 안에 있는 또 다른디렉토리와 또 그 많은 파일을의 출력에 대해서는 생각하지 않는다.

어떤 디렉토리가 있으면 그 디렉토리 안에 있는 디렉토리들과 파일들을 출력할래염!!!에 대해서 recursive function 을 맹글면 된다.



어렴풋이 생각나는 학창시절의 배움을 더듬어 보면 그냥 쌩으로 for 문을 써서 하는게 속도면에서는 훨씬 빠르다.(그런데 코드는 훨씬 복잡해질것이다.)

하지만 요즘 컴퓨터는 그때의 컴퓨터가 아니다. 나는 컴퓨터를 믿는다. *(-_-)*



성능이 매우매우매우매우매우 중요할 때에는 recursive function 을 쓰면 안되겠지만 그럴 경우가 아니면야 가독성 있는 코딩을 할 수 있는 방법이 훨씬 좋다고 생각한다.




잡소리는 고만하고, source!
package com.tistory.stove99;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileListExporter {
	private StringBuffer sb = new StringBuffer();
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

	String targetDir; // 리스팅할 대상 디렉토리
	File outputFile;  // 결과를 출력할 파일

	public FileListExporter(String targetDir, File outputFile) {
		this.targetDir = targetDir;
		this.outputFile = outputFile;
	}

	public void export() {
		// StringBuffer 로 파일정보 싹 읽어 들이기
		traversDir(new File(targetDir), 0);

		// 파일로 출력
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(outputFile);
			pw.append(sb);
			pw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (pw != null)
				pw.close();
		}
	}

	// recursive funtion
	private void traversDir(File dir, final int level) {
		dir.listFiles(new FileFilter() {

			public boolean accept(File file) {
				String modified = sdf.format(new Date(file.lastModified()));

				// 탭처리 해서 트리처럼 보이게 하기
				for (int idx = 0; idx < level; idx++) sb.append("\t");

				if (file.isDirectory()) {
					sb.append(String.format("%-35s <dir> %s", file.getName(), modified))
						.append("\r\n");
					traversDir(file, level + 1);
				} else {
					sb.append(String.format("%-35s %d %s", file.getName(), file.length(), modified))
						.append("\r\n");
				}

				return false;
			}

		});
	}

	// test
	public static void main(String[] args) {
		new FileListExporter("C:\\Program Files", new File("c:\\list.txt")).export();
		System.out.println("export end");
	}
}


파일 출력하는것 때문에 코드가 약간 길어지긴 했는데 딱 보면 코드가 그렇게 길지도 않다. 요런 짧으면서도 이해가 뽓 잘되는 코드를 맹글수 있다는게 recursive funtion의 매력인것 같다 *(-_-)*

요걸 뽓 실행해 보면 C 드라이브에 요런 list.txt 파일이 생성된다.


 

JAVA/JSP SQL Injection 해킹 방지를 위한 코딩


SQL Injection 은 사용자가 요상한 문자열을 입력해서 쿼리를 요상하게 바꿔 버려서 아무 아이디로나 로그인이 훅 되버린다던지 하는 쪼금은 싱거운 해킹방법중의 하나라고 나는 알고 있다.


뭐 예를들어 아이디 비번을 입력하고 로그인 할때

아이디로  
admin' OR '1'='1 요런걸 입력하고 로그인을 했을때 admin 으로 싹 로그인 되 버리는 어처구니 없는 일이 발생하는 것이 SQL Injection 처리를 쪽바로 해주지 않았을때 일어나는 참혹한 일이다.


SQL Injection 이 발생하는 전형적인 코드는 다음과 같다.
String userid=request.getParameter("userid");
String password=request.getParameter("password");

....
....

Statement stmt = conn.createStatement();
ResultSet rs = 
   stmt.executeQuery("select count(*) as cnt from member where userid='"+userid+"' and password='"+password+"'");

....
....



위 코드처럼 사용자 정보를 받아서 쿼리를 실행하고 실행결과가 1 이면 로그인 시켜주는 코드가 있다.

그런데 사용자가 아디디로 admin' OR '1'='1  을 입력하고 비밀번호로 abcd 를 입력한 후 로그인 시켜주셈~ 이라고 하면 우째될까?

위 코드대로라면  select count(*) from member where userid='amdin' OR '1'='1' and password = 'abcd'   이 쿼리가 실행되 버린다 -_-;;;

무섭다. 만약 사용자 테이블에 userid 가 admin 이라는 레코드가 있다면 admin 으로 로그인 되버리는 것이다. 

이런 어처구니 없는일이 놀랍게도 몇몇 허접한 사이트에서는 더러 통하는데도 있다 . -_-



아무튼 헛소리는 고만하고 본론으로 들어가서 SQL Injection 을 방지하려면 우째해야 될까? 

Statement 대신  PreparedStatement 를 쓰면 된다. 요렇게.
....
....

PreparedStatement stmt = conn.prepareStatement("select count(*) from member where userid=? and password=?");
stmt.setString(1, userid);
stmt.setString(2, password);

ResultSet rs = stmt.executeQuery();

....
....



PreparedStatement 만 쓰면 해결된다고 해서 또 요렇게는 쓰지 말길 -.-;
PreparedStatement stmt = 
   conn.prepareStatement("select count(*) from member where userid='" + userid + "'" and password='" + password + "'");



※ 하이버네이트는 한번도 안써봐서 잘 모르겠는데 mybatis 나 ibatis 같은 경우는 무난하게 #{xxxx} 요런것만 썼다면 SQL Injection 이 방지된다.

그런데 WHERE 절에 ${xxxx} 이렇게 있다면 다시 한번 생각해 보기 바란다.

${xxxx} 이거는 문자열 더하는것과 똑같기 때문에 위험하다. ${xxxx} 요런건 ORDER BY 절 같은데만 사용하자.


prev 1 ··· 22 23 24 25 26 27 28 ··· 45 next