제2 외국어 영역2012.08.17 14:57

문제의 시작은 그거였다.. (스프링 프레임웍 기반.)


컨트럴에서 로직을 처리하고 redirect를 한다.

그런데 redirect 한 곳에서 무언가의 데이터를 받고 싶다.. 


그럴땐 어떻게 하나?


쉽게는 그냥 url에다가 querystring 만들어서 넘겨주면 된다.

근데.... querystring에 넘거어가는 값을 숨기고  싶다.. 샹.. 어케해야하나?


대충 생각해보면 세션 스콥에 올린다음에 다음 엑션에서 꺼내쓰면 된다. 

근데.. 꺼내고 지우고 이작업을 있던 없던.. 무조건 해줘야 한다.. 


근데 졸라 불편하다.. -.-; 코드도 지저분해주고 .. 


뭐 그래서 낮에 그냥 세션스토어라는 녀석을 만들어서 이쪽에 넣고 담고 .. flush 특성처럼 만들었다.. 

근데 먼가 좀 예매모호하다.

일반 Bean에서 session을 가져 오기 위해서 해야 하는 코드가.. 


ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession(true);


이렇게 꺼내면 된다.. 

근데 좀 엉뚱한 곳에서 호출 하면 (정확히 sitemesh 의 decorator에서..) 


Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.


매우 친절하게 이러한 에러를 쳐 밷어 주신다..  췟;; 안써.. 


이래서 스프링 전문가님 백기선님이랑 수다를 떨었다.. 그러다가 백기선님이 몇개 링크를 던졌다.. 3.1MVC핵심 기능이라면서.. 



근데 저 문서를 봐도 어떻게 해야 하는지 잘 모르겠더라.. 

그래서 RedirectAttributes.java 파일을 깠다.. (소스는 대충이렇다..) 거기 봣더니 설명이 잘되어 있다..ㅋㅋ
그래서 했다.. ㅋㅋ
잘된다..ㅋㅋㅋ




	@RequestMapping("/info/test")
	public String tests(RedirectAttributes redirectAttributes) {
		redirectAttributes.addFlashAttribute("isNewUser", true);
		return "redirect:/";
	}

이러면 받는 컨트럴러의 model 객체에 알아서 담아준다.. ㅋ 스프링 만세 ㅋㅋ 

Posted by is윤군
제2 외국어 영역2012.04.04 13:16

일단 완전 넘사벽이라고 말해주고 싶다.

물론 코신이라면 상관없는 이야기지만. 

누군가가 한다면 말리고 싶다. 시간이 많다면 재미는 있겠지만 그렇게 유쾌하지는 않은듯.

참고로.. 저3가지에 나처럼 초자인 사람에게 해당하는 이야기이다;; 


시간되면 코드는 정리해서 github에 ㅋㅋ 


================ 

시큐리티 통합은 그럭저럭 할만함으로 변경.

Posted by is윤군
제2 외국어 영역2012.03.29 09:05

최근 springframework3.1(이하 spring) 로 프로젝을 시작했다.

뭐 몇년만에 고향에 돌아온 기분이라고 해야하나?

그동안 간간히 사용은 하고 있었지만.. 초딩들이 사용하는 것처럼 그냥 예전에 습득한 기술들 그냥 되색임 하는 정도였지.. 

제대로 사용하지는 않았다.


뭐 지금은 어느덧 PHP개발자가 되어 있는 나에게 JAVA따윈 귀찮은 녀석이었을 뿐이니까;

암튼 사설이 길어졌;; 


오늘 하고 싶은 이야기는 머냐면.. 

왜 그런거 있잖아.. 서버에 config 같은거 jsp에서 쓰고 싶을때.. 

config는 xml이나 properties 같은걸로 욜라 설정 다 빼놓고.. 

jsp에선 막 <% 컨피그.load('xxxxx'); blah blah~ %>  막 이렇게 꺼내고 싶진는 안단말이지.


그럼 jsp el 태그로 꺼낸다고 쳤을때.. 

어케 하면 잘 설정해줄수 있을까? 

첨에는 ContextLoaderListener같은거 구현해서 처음 로딩할 때 servletContext에다가 쳐 넣을까? 했었고.

담에는 spring의 viewResolvers의 setAttributeMap 을 통해서 request의 attribute에다가 넣을까 했었고.

그리고 두번째 방법으로 넣어서 .. 

jsp에서 ${config.url} (사실 이렇게 호출하면 엿된다. 왜일까? 1초만 생각해보면 알 문제이다-.-; 난 한 20분 걸린듯..ㅋ)

이런식의 el로 꺼낼수 있다. ${app['config.url']} 이렇게 말이지. 

이런식?;



암튼.. 

근데 .. 이렇게 한지 한 10분이 지났나.. spring reference를 보다가 갑자기 spring eval이 보였고.. 

처음 spring eval 기능이 튀져나왔을 봤던 기억이 세록 떠오르며.... 

아 삽질했구나 생각이 들었다.. 

그냥 이렇게 하면 아까 두번째 한 attributeMap에 넣는 설정 부분은 그냥 지우고.. 

바로 설정에 접근할수 있다..





역시 사람은 머리가 나쁘면 시간 버리고 고생한다..

삽질했던 기억을 더듬으면서... 

간만에 포스팅.

그리고 쓰잘때기 없던 나의 삽질에 시간을 빌려준 . whiteshiparawn 두 행님께 감사를 ..ㅎㅎ 


Posted by is윤군
제2 외국어 영역2011.05.24 15:05
내 생각은 그렇다.. 

간지용으로 정규식을 쓰는 것 보단..  정규식 아닌 녀석으로 문제를 해결 할 수 있다면.. 
그녀석으로 하는게.. 더 괜춘하다는 것; 

그렇다고 정규식으로 한줄이면 끝나는데 정규식 안 쓰려구 100줄 만들라는 이야기가 아니라.. ㅡ.ㅡ;
둘다 한 줄이면 정규식 말고 다른 녀석을 쓰는게 속도 측면에선 귿이라는 것!
 
Posted by is윤군
TAG 잡설
제2 외국어 영역2011.05.17 18:59
ie에서 filter 을 이용하면 opacity를 거시기 할 수 있다.. 
but.. 그 filter가 먹히는 대상의 height (width는 테스트 안해봤음.. -.-;;) 4096이상이면 
filter가 안먹는다...

난 왜 안되나 싶었더니.. ;;   이런 버그가 있었다!! 젠장.. 

무튼 귀찮아서 많이 찾아보지는 않았지만 딱히 해결책은 없어보이고 ..
그냥 트릭으로 해결하는 수밖에 없었다... 
 
Posted by is윤군
TAG IE버그
제2 외국어 영역2011.04.21 20:38
이녀석은 기본 코드 일부.  
autoGrowTextArea : {
      node : undefined,
      pairTextAreaNode : undefined,
      prevText : '',
      webWorker : undefined,
      maxHeight : 0,
      rejectCount : 0,
      workingDelayTime : 0,
      waitingDelayTime : 10000,
      isKeyDownEvent : false,
      isPossible : true,
      init : function(options){
        var _self = this;
        if(Y.UA.gecko){
          _self.webWorker = new Looah.looahWebWorker.init({jsName:'/js/looah-autogrow-worker',
                                                           onmessage : function(e){
                                                             var delayTime = e.data.delayTime;
                                                             if(e.data.workType === 'working'){
                                                              if(_self.rejectCount > 150){
                                                                delayTime = _self.waitingDelayTime;
                                                              }
                                                              if(_self.rejectCount === 151){
                                                                _self.isKeyDownEvent = true;
                                                                _self.pairTextAreaNode.on('keydown',function(){
                                                                  _self.webWorker.command({workType:'working',delayTime:_self.workingDelayTime});
                                                                },_self);
                                                              }
                                                              _self.update();
                                                              if(_self.rejectCount === 0){
                                                                delayTime = _self.workingDelayTime;
                                                                if(_self.isKeyDownEvent){
                                                                  _self.isKeyDownEvent = false;
                                                                  Y.Event.purgeElement(_self.pairTextAreaNode._node, false, 'keydown');
                                                                }
                                                              }
                                                            }
                                                            _self.webWorker.command({workType:e.data.workType,delayTime:delayTime});
                                                           }
                                                        });  
        }
        _self.maxHeight = options.maxHeight;
        if (Y.UA.gecko && !_self.webWorker) {
          _self.isPossible = false;
        }else{
          _self.node = Y.one('body').appendChild('
bestofbest
').set('id',options.id); } return _self; }, getNode : function(){ return this.node; }, setPairTextAreaNode : function(taNode){ var _self = this, delayObject, updateFn = function(e,delayTime){ if(delayTime !== 0){ if(delayObject){ delayObject.cancel(); } delayObject = Y.later((e.type === 'cut'?50:100), _self, _self.update); }else{ _self.update(); } }, updateFnForGecko = function(e,options){ if(options.workType === 'working'){ _self.rejectCount = 0; _self.workingDelayTime = options.delayTime; _self.update(); } _self.webWorker.command({workType:options.workType,delayTime:options.delayTime}); }; if(!_self.isPossible){ taNode.setStyle('overflow','auto').setAttribute('rows',6); return _self; } _self.pairTextAreaNode = taNode; if(!Y.UA.gecko){ _self.pairTextAreaNode.on('focus',updateFn,null,0); _self.pairTextAreaNode.on('keyup',updateFn,null,0); _self.pairTextAreaNode.on('change',updateFn, null,0); _self.pairTextAreaNode._node.oncut = updateFn; _self.pairTextAreaNode._node.onpaste = updateFn; }else{ _self.pairTextAreaNode.on('focus',updateFnForGecko,null,{workType:'working',delayTime:100}); _self.pairTextAreaNode.on('blur', updateFnForGecko, null,{workType:'sleeping',delayTime:3600000}); } _self.node.setWidth(this.pairTextAreaNode.getWidth()); return _self; }, update : function(){ var currentText = this.pairTextAreaNode.getValue(); if(currentText === this.prevText || !this.isPossible){ this.rejectCount++; return this; } this.rejectCount = 0; this.node.set('innerHTML',currentText+'bestofbest'); if(this.node.getHeight() < this.maxHeight){ if(this.pairTextAreaNode.getStyle('overflow') === 'auto'){ this.pairTextAreaNode.setStyle('overflow','hidden'); } this.pairTextAreaNode.setHeight(this.node.getHeight()); }else{ this.pairTextAreaNode.setStyles({overflow:'auto',height:this.maxHeight}); } this.prevText = currentText; return this; }, getHeight : function(){ return this.node.getHeight(); }, destroy : function(){ if(this.webWorker){ this.webWorker.stop(); } this.node.remove(); } }, looahWebWorker : { worker : undefined, state : 'stop', init: function(options){ if (!!window.Worker) { if(this.worker){ this.worker.terminate(); } this.worker = new Worker(Looah.getJsLocation(options.jsName)); this.worker.onmessage = options.onmessage; } return this; }, command : function(msg){ this.state = msg.workType; this.worker.postMessage(msg);
return this; }, stop : function(){ this.state = 'stop'; this.worker.postMessage({workType:this.state}); this.worker.terminate();
return this; } },
아래 녀석은 웹워커 녀석. 사실 이녀석은 별거 없다. ㅋ
var timeoutObject,
    sendPostMessage = function(msg){
     postMessage(msg);
    };

onmessage = function (e) {
  if(timeoutObject){
    clearTimeout(timeoutObject);
  }
	if(e.data.workType !== 'stop'){
	  timeoutObject = setTimeout(function(){sendPostMessage(e.data);},e.data.delayTime);
	}
};

전반 적인 삽질 이야기.. 
일단 가장 삽질은.. FF때문이다.. 개발좀 해봤다는 사람들 다들 아는 사실이지만..
FF에서 한글을 칠때.. key이벤트가 한번만 실행된다;; 그래서 많은 트릭들이 나와 있고~ ;; 

이것도 뭐 비슷한 맥락이지만 그냥 웹워커를 한번 써보려고 worker를 이용해서 돌려 보았다.. 
그래서 FF에서 worker지원 안하는 버전에선.. 그냥 일반 textarea로 나온다..  

looahWebWorker 이 녀석은.. 그 머냐.. looah에서 사용하는 공통으로 사용하려고 만들어 보았는데..
사실 아직 쓰이는데는 없다.. 그냥 만들어 놓은 거구..

대충 설명 들어가면.. 일단 안보이는 맨 구석에 div하나를 숨겨 놓는다..
그리고 textarea에서 친 내용을 실시간으로 div에다가 넣어주시고 그 녀석의 height를 가지고 와서 textarea
높이를 변경해주는 것이다.. 

만들다 보면 이것저것 생각할게 많다.. ; cut&paste할때.. 마우스로 할때 .. 등등.. 자질 구리하게 신경써줘야 하는 것도 많고..
완벽하게 만들려고 한다면 과연 할 수 있을까 의문 스럽기도 하고..

그리고 css에서도 해줘야 할 게 있고.. ;;
아참 이녀석은 무한대로 자라지 않는다... 다만 maxHeight까지만 자랄 뿐.. ;;

혹시나 이런 삽질 놀이에 관심 있는 사람은 코드 컨셉만 참조 하면 될듯..
한국에서 YUI를 쓰는 사이트가 있을지 모르겠지만.. 충분히 jQuery같은걸로 컨버팅 한다던가.. 사실 js프레임웍이 중요한게 아니잖아욤!?!  아님 이녀석 뭐야 이러고 잊어 버리시면 된다.. ㅋ 그건 댁들이 알아서;; 판단하시고.. 데모나 css같은건..
http://www.looah.com  에 가서 직접 확인해보시길.. ;; 

사실 이것저것 정리해서 블로깅 하기가 귀찮으니;; 쿨럭;  아 가장 중요한건.. 
아직 배포 되지 않은 코드다.. 아마  몇일 안에 push할 것 같은데..  이런 잼있는 삽질 말고 다른 힘든 삽질한다고 ;; 
많이 바뻐서 코드 반영이 느려지고 있다 ㅡ.ㅡ; 

FF에서 최소한 리소스를 적게 써보려고 삽질해서 코드가 좀 더럽다; 다음 코드 베큠 돌릴때 다시금 정리 해야징;; 지금은 바쁘니 ㅡ.ㅡ; 아참 bestofbest라는 문구는 .. 좀더 빨리 자라도록 심어둔 영양제 같은 녀석이다.


js는 잼있다니까.. 쩝;; 
다음번엔.. jslint 검사후 YUI compressor를 이용해서 압축하는  자동화 이야기를 포스팅 해볼까 생각만 중이다..;; 

아참.. 참고로 YUI를 사용하고 있지만 난 전혀 Yahoo랑 상관없는 놈이다..;;  난 그냥 Looah개발자다;;
회사 코드 막 블로깅 하고... 이러다가 "Yoon's fired!!" ;;이러는거 아냐;; 쿨럭; 어차피 js는 초딩도 볼 수 있으니;; pass 하겠습니다;;


update ===== 2011.4.27
ie에서 좀 븅신처럼 동작한다 ㅡㅡ;
그래서 path를 했는데... ;; 다시 올리려니 귀찮네;;  
Posted by is윤군
제2 외국어 영역2011.04.16 10:31

$(document).ready(function(){
	var amIworking = false,
	    mainCfg ={
			cardNubmers : [1,2,3,4,5,6,7,8],
			widthBoxCount : 4,
			heightBoxCount : 4,
			eachBoxWidth : 84,
			eachBoxHeight : 104
		},
		firstFaceUpCardNumber = -1,
		faceUpCardIdxs = [],
		totalBoxCount = (mainCfg.widthBoxCount*mainCfg.heightBoxCount),
		blackBox = {},
		triedCount = 0,
		totalScore = 0,
		initGame = function(){
			var cardSets = arraySuffle(mainCfg.cardNubmers);
			cardSets = $.merge(cardSets,arraySuffle(cardSets.slice()));
			
			$('#card-part li').each(function(idx,item){
				$(item).css({'left': (Math.floor(idx % mainCfg.widthBoxCount) * mainCfg.eachBoxWidth),
						     'top' : (Math.floor(idx / mainCfg.heightBoxCount) * mainCfg.eachBoxHeight)
						    });	
			});
			
			for(var i = 0; i < totalBoxCount;i++){
				blackBox[i] = {};
				blackBox[i].cardNubmer = cardSets[i];
				blackBox[i].isRemove = false;
			}
			faceUpCardIdxs = [];
			amIworking = false;
			firstFaceUpCardNumber = -1;
			triedCount = 0;
			totalScore = 0;
			resetCardFaceDown();
			$('#entry-box').focus();
		},
		movingBox = function(currentIdx, direction){
			if(currentIdx === undefined){
				return false;
			}
			currentIdx = parseInt(currentIdx,10);
			var nextIdx = 0,
			    leftLimtIdx = 0,
				lastIdx = totalBoxCount-1;
			
			switch (direction) {
				case 37: //left
					nextIdx = currentIdx-1;
					if(leftLimtIdx > nextIdx){
						nextIdx = lastIdx;	
					}
					break;
				case 38: //up
					if(currentIdx === leftLimtIdx){
						nextIdx = lastIdx;
					}else{
						nextIdx = currentIdx-mainCfg.heightBoxCount;
						if(0 > nextIdx){
							nextIdx = lastIdx + nextIdx;
						}						
					}
					break;
				case 39: //right
					nextIdx = currentIdx+1;
					if(lastIdx < nextIdx){
						nextIdx = leftLimtIdx;	
					}
					break;
				case 40: //down
					if(currentIdx === lastIdx){
						nextIdx = leftLimtIdx;
					}else{
						nextIdx = currentIdx+mainCfg.heightBoxCount;
						if(lastIdx < nextIdx){
							nextIdx = nextIdx - lastIdx;
						}
					}
					break;
			}
			if(blackBox[nextIdx].isRemove){
				movingBox(nextIdx,direction);
			}else{
				seleteBox(nextIdx);
			}
		},
		
		toggleCard = function(){
			var selectedCard = $('#card-part li.selected'),
			    idx = parseInt(selectedCard.attr('data-idx'),10),
			    secondFaceUpCardNumber;
			if(faceUpCardIdxs.length > 0){
				if($.inArray(idx,faceUpCardIdxs) === 0){
					amIworking = false;
					return false;
				}else{
					triedCount++;
					secondFaceUpCardNumber = blackBox[selectedCard.attr('data-idx')].cardNubmer;
					selectedCard.attr('data-num',secondFaceUpCardNumber);
					if(firstFaceUpCardNumber === secondFaceUpCardNumber){
						blackBox[faceUpCardIdxs[0]].isRemove = true;
						blackBox[idx].isRemove = true;
						$('#card-part li[data-idx="'+faceUpCardIdxs[0]+'"]').remove();
						$('#card-part li[data-idx="'+idx+'"]').remove();
						faceUpCardIdxs = [];
						totalScore++;
						amIfinished(idx);
						amIworking = false;
					}else{
						if(totalScore > 0){
							totalScore--; 
						}
						setTimeout(function(){
							resetCardFaceDown(faceUpCardIdxs[0]);
							resetCardFaceDown(idx);
							faceUpCardIdxs = [];
							amIworking = false;
						},500);
					}
				}
			}else{
				firstFaceUpCardNumber = blackBox[selectedCard.attr('data-idx')].cardNubmer;
				selectedCard.attr('data-num',firstFaceUpCardNumber);
				faceUpCardIdxs[0] = idx;
				amIworking = false; 
			}
		},
		
		arraySuffle = function(arr){
	      var s = [];
	      while (arr.length){
	        s.push(arr.splice(Math.random() * arr.length, 1));
	      }
	      while (s.length){
	        arr.push(s.pop()[0]);
	      }
	      return arr;
	    },
		
		resetCardFaceDown = function(idx){
			if(idx !== undefined){
				$('#card-part li[data-idx="'+idx+'"]').attr('data-num',0);
			}else{
				for(var i = 0 ; i < totalBoxCount ; i++){
					$('#card-part li[data-idx="'+i+'"]').attr('data-num',0);
				}
				seleteBox(0);
			}
		},
		amIfinished = function(currentIdx){
			var firstAliveBoxIdx;
			$.each(blackBox,function(idx,item){
				if(!item.isRemove){
				  if(firstAliveBoxIdx === undefined || currentIdx < idx){
						firstAliveBoxIdx = idx;
						if(currentIdx < idx ){
							return false;
						}
					}
				}
			});
			if(firstAliveBoxIdx === undefined){
				alert('triedCount ==>'+triedCount+'\n totalScore ==>'+totalScore);
				initGame();
			}else{
				seleteBox(firstAliveBoxIdx);
			}
		},
		seleteBox = function(idx){
			$('#card-part li.selected').removeClass('selected');
			$('#card-part li[data-idx="'+idx+'"]').addClass('selected');
		};
	
	$('#entry-box').keydown(function(e){
		if(e.keyCode === 37|| 
		   e.keyCode === 38||
		   e.keyCode === 39||
		   e.keyCode === 40 
		  ){
		  	if(amIworking){
				return false;
			}
			e.preventDefault();
			amIworking = true;
			movingBox($('#card-part li.selected').attr('data-idx'),e.keyCode);
			amIworking = false;
		}else if(e.keyCode === 13){
			if(amIworking){
				return false;
			}
			e.preventDefault();
			amIworking = true;
			toggleCard();
		}
	});
	
	initGame();
});
생각없이 발로 만든 코드.. ;; 머 하는 녀석인가?;
Posted by is윤군
제2 외국어 영역2011.04.11 07:16

var jsonObject = {yoon : '삽질맨' , isyoon : '간지마쵸맨' };


이런 데이터가 있을때!!! 
급 yoon:삽질맨을 지우고 싶다..

그럴땐.

delete jsonObject['yoon']; or
delete jsonObject.yoon;  해주면

 jsonObject =>>>  {isyoon : '간지마쵸맨' }
이렇게만 된다.

 
그냥 적어봤다 ㅡ.ㅡ;;
개인적으론 object속성에 접근 할때 [] 이것보단 . 요넘을 선호한다.. 왜냐면 배열녀석이랑 썩일 수도 있거든!!


이상!! 
Posted by is윤군
제2 외국어 영역2010.12.10 19:33
여차 저차 해서 springframework RestTemplate사용한다고 깝치다가 삽질만 했네 ㅡㅡ; anyway...

<property name="messageConverters">

            <list>

                <bean class="org.springframework.http.converter.FormHttpMessageConverter">

                <property name="charset">

                <bean class="java.nio.charset.Charset" factory-method="forName">

                <constructor-arg value="UTF-8"/>

                </bean>

                </property>

                </bean>

                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>

            </list>

        </property>


코드 플러그인이라도 설치하던가;;; 
아우 ~ 구찮아서 정렬은 패쓰~~~;; 

여기에 핵은... FormHttpMessageConverter 이놈의 기본 Charset 가 .. ㅡ.ㅡ ISO-8859-1 
이놈이다 ~ 그러니 UTF-8로 바까주시고 사용하셈~

잠들기전에 해결해서 ~ 그나마 다행;; 
꿈속에서 코딩할 뻔했;; 
Posted by is윤군
제2 외국어 영역2010.11.22 12:02

자바에서 ISO-8601 형식의 주차 구하기.!!

Calendar cal = new GregorianCalendar();

cal.setFirstDayOfWeek(Calendar.MONDAY);

cal.setMinimalDaysInFirstWeek(4);


흠냥. 

php 랑 달라서 @.@;; 쿨럭. 냠냠 간만에 기술 블로깅질... 
스프링 배치 끝나면 한번 블로깅질 해야겠다.. 

삽질하는 많은 개발자를 위해 ㅠㅠ 
Posted by is윤군