2013년 7월 19일 금요일

eclipse javascript 문법 에러

JQuery.js 파일들이나 JQuery.ui.js 파일 같은 것들을 폴더에 추가해두면 올바른 문법이 아니라면서 에러 표시가 나는 경우가 있다. Properties -> JavaScript -> Include Path -> Source에 가서 Excluded 에 Edit 을 눌러서 **/jquery*.* 등록한다.

2013년 7월 15일 월요일

spring-security url 예제


 

   


1 : 최상위 디렉토리는 권한상관없이 접속 가능 (루트 url)
2 : /login url 은 권한상관없이 접속 가능
3 : 아래 /** 는 user 와 admin 에게만 열어놓았으므로 권한이 없을때 이미지 표시가 안될 수가 있기 때문에 설정
    spring-servlet.xml 에서 설정한 디폴트서블릿보다 spring-security가 우선하기 때문에 따로 설정해야 한다.
4 : /admin/ 하위 디렉토리는 admin 권한에게만 오픈
5 : 그외 모든 디렉토리는 user와 admin에게 오픈한다.

3번 처럼 설정하기 싫다면

< security:http pattern="/resources/**" security="none" / >

이놈을 추가해라

mime-mapping 에 대해...

톰캣 같은 WAS 를 사용할때 정적인 리소스는 보통 브라우져에서 바로 접근이 가능하다.
보통은 다운로드 받기위해 접근 하는 경우가 많은데 
기본적으로 톰캣에 등록되있지 않은 확장자를 가진 파일에 접근할때 브라우져에서는 바로
해석을 하려고 한다. 그에 대한 설정이다

web.xml 에 넣으면 된다.

    js
    text/javascript
 

    css
    text/css

하지만 위에 대한 것은 기본적으로 등록이 되어있으므로 큰 의미는 없다

추가등록정보

  • 엑셀 97-2003 통합문서 (*.xls):application/vnd.ms-excel
  • 엑셀 통합문서 (2007 이상 *.xlsx):application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • ZIP 파일 (*.zip):application/zip
  • TAR 파일 (*.tar):application/x-bzip
  • 워드 97-2003 문서 (*.doc):application/msword
  • 워드 문서 (2007 이상 *.docx):application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • PDF 파일 (*.pdf):application/pdf
  • 한글 (*.hwp):application/x-hwp

2013년 7월 9일 화요일

ajax 인코딩 관련

기본적으로 ajax 는 utf-8 로 통신하게 되어있기 때문에 한글을 보내거나 받을 경우
그에 맞는 인코딩 설정을 해주어야 한다.
단, json 객체로 보내게 되면 굳이 인코딩을 할필요는 없다.
json 객체를 전송할때는

contentType : "application/json",

json 객체를 받을때는

dataType : "json",

을 명시해주면 된다. 하지만 일반 text일 경우에는
추가로 설정이 필요하다.

전송할때

contentType:"application/x-www-form-urlencoded; charset=UTF-8",

추가해주고 받을때는 

별도의 설정은 필요없다.

컨트롤러단에서 @ResponseBody 사용시
@RequestMapping(value = "/test/encoding5", method = RequestMethod.GET, produces="text/plain; charset=UTF-8")
설정해주고 @ResponseBody 미사용시

response.setCharacterEncoding("utf-8");

이 구문을 추가해준다.

@RequestBody, @ResponseBody

소스부터..
var data = {usr_id : "jack" , usr_pw : "jack", usr_name : "jack"};
     
$.ajax({
 url : "/contextPath/test/json",
 method : "POST", 
 contentType : "application/json",
 data : JSON.stringify(data),           
 success : function() {
  alert("전송 성공");
 },
 error : function(XHR, textStatus, errorThrown) {
       
     alert("Error: " + textStatus);      
     alert("Error: " + errorThrown);

 }
});
위와 같이 json 객체를 JSON.stringify 를 이용하여 문자열로 변환후 전송하려 할때 spring에서를 어떻게 받아야 할까?
@RequestMapping(value = "/test/json", method = RequestMethod.POST, consumes="application/json")
public void ajax_sendJSON(@RequestBody Map< String, Object> data, HttpServletResponse response) {  
    
 logger.info("ajax_sendJSON\n"+data);   
  
 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        //응답 없음
}
위와 같이 받으면 된다. 만약에 json객체가 [] 로 된 배열형태라면
List< Map< String,Object>> 로 받으면 된다.

json객체를 내보낼때도 마찬가지다.
@ResponseBody
@RequestMapping(value = "/test/json", method = RequestMethod.GET, produces="application/json")
public List< Map< String, Object>> ajax_receiveJSON() {
  
 logger.info("ajax_receiveJSON");
  
 List< Map< String, Object>> list = new ArrayList< Map< String, Object>>();
  
 for(int i=0 ; i<3 ; i++) {
   
  Map< String, Object> map = new HashMap< String, Object>();
   
  map.put("id", "id"+i);
  map.put("name", "name"+i);
   
  list.add(map);
 }
  
 return list;    
} 
위와 같이 리턴해주면 json형태로 손쉽게 받을 수 있다.
$.ajax({
 url : "/contextPath/test/json",
 method : "GET",  
 dataType:"JSON",
 success : function(json) {
       
   alert(JSON.stringify(json));       
       
 },
 error : function(XHR, textStatus, errorThrown) {
       
     alert("Error: " + textStatus);      
     alert("Error: " + errorThrown);

 }
});
받는 것도 위 처럼 받으면 된다
매우 좋은 기능이지만 그냥 사용 할 수는 없다. pom.xml 에서 다음을 추가하면 된다.

 org.codehaus.jackson
 jackson-core-asl
 1.9.12


 org.codehaus.jackson
 jackson-mapper-asl
 1.9.12

그리고 전에 글에 servlet-context.xml 에서 처럼 json 관련 
bean을 추가해주면 된다.

ibatis 설정 및 간단한 구현

기본적으로 몇가지 jar들이 필요한대 그 목록은 다음과 같다.

1. ojdbc14 (oracle jdbc 라이브러리)
2. spring-orm (ibatis와 jdbc를 연결해주는 역할)
3. ibatis-sqlmap (ibatis 의 sqlmap 라이브러리)

Spring Template Project 를 사용하여 프로젝트를 생성했다면
기본적으로 maven이 포함되어 있다. pom.xml 을 수정하여 쉽게 추가가 가능하다.

참고로 Spring Template Project로 프로젝트 생성시 추가 작업으로는
Spring Library 추가 Server Library 추가가 있다.



com.oracle
    ojdbc14
    10.2.0.4.0

	


    org.springframework
    spring-orm
    ${org.springframework-version}


    org.apache.ibatis
    ibatis-sqlmap
    2.3.4.726

귀찮으면 위에꺼 가져가 쓰면 된다.
이제 몇가지 설정 파일이 필요한데 위치는 WEB-INF 밑에 classes 안에 자유롭게 배치해도 된다. 
classes 가 classpath 임.

data-context.xml 이름은 상관없다.


	   					   
	
	
		
		
		
		
	
	
	
		  
	
	      
	
	


sqlMapConfig.xml 이건 이름이 정해져있다.


		

	
        
		

usr.xml 쿼리가 들어가는 파일


		

        
	
	
	
	
	
	
	
		INSERT INTO usr(usr_uid, usr_id, usr_pw, usr_name, usr_enabled, usr_authority, usr_regdate, usr_upddate)
					VALUES
					(usr_seq.nextval, #usr_id#, #usr_pw#, #usr_name#, '1', 'ROLE_USER', sysdate, sysdate)
		
	

dao 구현
@Repository
public class UsrDao extends SqlMapClientDaoSupport {
	
	@Resource(name = "sqlMapClient") 
    public void setSuperSqlMapClient(SqlMapClient sqlMapClient){
		
        super.setSqlMapClient(sqlMapClient);
        
    } 
	
	public UsrVo selectOne(String usr_uid){
		
		return (UsrVo)getSqlMapClientTemplate().queryForObject("usr.selectOne", usr_uid);
		
	}
	
	public List selectAll(){
		
		return getSqlMapClientTemplate().queryForList("usr.selectAll");
		
	}
	
	public void insert(UsrVo usrVo) {
		
		getSqlMapClientTemplate().insert("usr.insert", usrVo);
		
	}
}
service 구현
@Service
public class UsrService {

	@Autowired
	private UsrDao usrDao;
	
	private static final Logger logger = LoggerFactory.getLogger(UsrService.class);
	
	public void getUsrList(Model model) {
		
		model.addAttribute("usrList", usrDao.selectAll());
		
	}
	
	public boolean checkUsrIdDup(String usr_id) {
		
			
		return usrDao.checkUsrIdDup(usr_id);		
		
	}
	
	public UsrVo findUsrDetail(String usr_uid) {
		
		return usrDao.selectOne(usr_uid);		
		
	}
	
	public void submitUsrJoin(UsrVo usrVo) {
		
		usrDao.insert(usrVo);		
		
	}
}

jQuery RESTful 요청

회원 목록

위와 같은 form 이 있을 경우 jquery를 이용하여 RESTful방식으로 요청하는 법.

$(".detailHandler").click(function() {		
					
	var usr_uid = $(this).attr("usr_uid");
	$("input[name=_method]").val("get");
	$("form")
		.attr("method","post")
		.attr("action","/contextPath/admin/usr/"+usr_uid+") 
		.submit();
});	
form 내부에 _method 이름으로 된 요소가 있을 경우 web.xml에서 HiddenHttpMethodFilter 필터를 설정했다면 
위와 같은 방법으로 spring에서도 delete,get,put,post 메소드를 사용 할 수 있다.

onclick 속성을 사용하지 않을 경우에 버튼 태그안에 임의의 속성을 주어 데이터를 저장하게 할 수 있다.
또한 contextPath는  태그를 사용하여 대체 가능하다.

중복 ID 체크


회원가입시 중복체크 쿼리. 
입력된 아이디와 기존 회원 테이블을 조인시켜 
입력된 아이디에 대한 정보가 null인지 아닌지 구분함.
dao 클래스에서 java.lang.Boolean 형식으로 받을 수 있다.
이후,

@ResponseBody 
@RequestMapping(value = "/usr/join_check", method = RequestMethod.POST)
public boolean usr_join_check(@RequestParam String usr_id) {
		
	logger.info("usr_join_check ajax\nusr_id : ["+usr_id+"]");
		
	return usrService.checkUsrIdDup(usr_id);		
}	
컨트롤러 단에서 @ResponseBody 를 이용하여 리턴해준다.

2013년 7월 8일 월요일

url pattern / or /*

 
  appServlet
  /*.do
 
옛날은 위와 같이 매핑해주는 것이 보통이었다. 이렇게 하면 .do 로 끝나는 url 은 쉽게 스프링 서블릿을 
타게 할 수가 있다. 하지만 요즘은 RESTful 스타일을 선호한다. 
예를 들면 

http://localhost:8080/myapp/user/10 (user 수정,탈퇴,보기)
http://localhost:8080/myapp/user (user의 회원가입)
http://localhost:8080/myapp/admin/user/10 (user의 수정,삭제,보기,추가)

이런 식의 url 들이다.

이런 식의 url 을 구현하려면 
 
  appServlet
  /*
 
pattern을 이런식으로 변경해야 한다.그렇지만 static한 js,css,html 파일등의 요청과 .jsp 에 대한 요청도 스프링 서블릿이 작동하여
404 페이지를 보게 된다. 그래서 한가지 해결책으로 urlrewrite 를 사용했다. pattern 은 그대로 두고

  ^/world.jsp?country=([a-z]+)&city=([a-z]+)$
  /world/$1/$2

이와 같이 설정한다.
정규식을 사용하여 

/world.jsp?country=korea&city=seoul 을
/world/korea/seoul

로 변경되는 식이다.

이런 방법도 있지만 web.xml 과 spring 설정을 조작하여 해결하는 방법도 있다.
 
  appServlet
  /
 
이와 같이 설정하고

위 구문을 spring-servlet.xml 에 추가하면 된다.
필터를 통과못한 url 을 잡아서 톰캣 기본 서블릿에 넘겨주는 역할을 한다. pattern을 / 로 설정했기때문에
위 구문이 없으면 톰캣 기본 서블릿은 동작을 하지 못하기 때문이다.

한마디로 /* 는 모든 요청을 자기가 처리하겠다 이고, / 는 모든 요청은 받지만 처리 못하는 것은 넘기겠다 라는 뜻이다.

web.xml 설정




 
 
  contextConfigLocation
  
   /WEB-INF/spring/root-context.xml
   /WEB-INF/spring/appServlet/spring-security.xml
   
  
 
 
 
 
  org.springframework.web.context.ContextLoaderListener
 

 
 
  appServlet
  org.springframework.web.servlet.DispatcherServlet
  
   contextConfigLocation
   /WEB-INF/spring/appServlet/servlet-context.xml
  
  1
  
 
  appServlet
  /
 
 
  
 
     httpMethodFilter
     org.springframework.web.filter.HiddenHttpMethodFilter
 
     
 
     httpMethodFilter
     /*
 
 
 
 
  springSecurityFilterChain
  org.springframework.web.filter.DelegatingFilterProxy  
  
 
  springSecurityFilterChain
  /*
  
 
 
 
  springCharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
     encoding
     UTF-8
    
    
     forceEncoding
     true
    
 
 
 
  springCharacterEncodingFilter
     /*
 
 

spring-security.xml 기본 설정



 
  
 
 
  
 
  
    
 
  
  
  
        
  
    
  
  
  
  
     
  
     
 
 
 
  
  
  
  
 
 
 
 
 
 
  
 
   
 

위의 설정만으로도 기본적인 로그인 인증 기능은 사용 할 수 있다.
위의 설정에서는 로그인 페이지가 따로 커스텀 되어있는데 몇가지 유의할점이 있다면
암호 기억하기
위와 같이 url명과 아이디와 비밀번호의 name을 설정해야 한다.
또한 인증정보와 권한정보는 session에 저장되는데 

<%@ page session="true" %>

이걸 사용하지 않아도 session에 접근할 수 있다.

<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>



권한 등급 : 사용자
아이디 : []
권한 등급 : 관리자
아이디 : []
권한 등급 : 손님
아이디 : []
로그인 해주세요
위와 같이 사용한다. 또한 로그인 실패시 그에 관한 정보는

 
로그인 실패
위의 변수에 들어있다.

spring-servlet.xml 기본 설정


 


 
 
  
  
 
 

 
 
 
 
 
 
 
 
 
 
 
  
 
  
   
        
   
  
  

 
  
 
 
 
  
  
 



Validator 모듈



var Validator = {
		
		validateElement : function(formName, elName) {
			
			var el = $("form[name="+formName+"] *[name="+elName+"]");			
				
			var classGroup = el.attr("class");	
				
			if(classGroup) {
						
				var classes = classGroup.split(" ");
				var comment = el.attr("comment");
				
				for(var i=0 ; i< classes.length ; i++) {
					
					var className = classes[i];
					
					if(Validator[className]) {					
						
						var msg = Validator[className](el.val());
						
						if(msg) {	
							
							Validator._handleError(msg, comment);	
							return false;
								
						}							
					}
				}
			}
			
			return true;				
		},
		
		validateForm : function(formName) {
			
			var result = true;
			
			$("form[name="+formName+"] *").each(function() {				
				
				var classGroup = $(this).attr("class");	
				
				if(classGroup) {
						
					var classes = classGroup.split(" ");
					var comment = $(this).attr("comment");
					
					for(var i=0 ; i < classes.length ; i++) {
						
						var className = classes[i];
						
						if(Validator[className]) {					
							
							var msg = Validator[className]($(this).val());
							
							if(msg) {	
								
								Validator._handleError(msg, comment);
								result = false;
								return false;
								
							}
							 
						}
						
					}
				}
			});
			
			return result;			
		},
		
		_handleError : function(msg, comment) {
			
			alert(comment+" 는(은) "+msg);
			
		},
		
		trim : function(str)
		{
			var count = str.length;
			var len = count;
			var st = 0;

			while ((st < len) && (str.charAt(st) <= ' '))
			{
				st++;
			}
			while ((st < len) && (str.charAt(len - 1) <= ' '))
			{
				len--;
			}
			return ((st > 0) || (len < count)) ? str.substring(st, len) : str ;
		},
		
		"required" : function(value) {
			
			if(!Validator.trim(value).length) {
				
				return "필수 입력 사항입니다";
				
			}			
		},
		
		"alpha-lower" : function(value) {			
			
			var pattern = new RegExp("^[a-z]{6,18}$");			
			
			if(!pattern.exec(Validator.trim(value))) {
				
				return "소문자만 입력 가능합니다 (6~18 글자)";
				
			}			
		},
		
		"alpha-upper" : function(value) {
			
			var pattern = new RegExp("^[A-Z]{6,18}$");			
			
			if(!pattern.exec(Validator.trim(value))) {
				
				return "대문자만 입력 가능합니다 (6~18 글자)";
				
			}			
		},
		
		"email" : function(value) {
			
			var pattern = new RegExp("^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$");
			
			if(!pattern.exec(Validator.trim(value))) {
				
				return "이메일 형식에 맞지 않습니다";
			}
		},
		
		"mobile" : function(value) {
			
			var pattern = new RegExp("^01([0-9])-([0-9]{3,4})-([0-9]{4,4})$");
			
			if(!pattern.exec(Validator.trim(value))) {
				
				return "핸드폰 번호 형식에 맞지 않습니다";
			}				
		}
};






유효성 검사 모듈.. 
사용법은 유효성검사가 필요한 엘리먼트에 class 추가 후
script 에서 validateForm 또는 validateElement 호출하면 된다.