전자정부개발프레임워크실행환경 2009 년 6 월 - 1 -
1. 개요 2. MVC 3. Internationalization 4. Ajax Support 5. Security 6. UI Adaptor - 2 -
1. 개요 - 실행환경화면처리레이어 (1/3) 화면처리레이어는업무프로그램과사용자간의 Interface 를담당하는 Layer 로서, 사용자화면구 성, 사용자입력정보검증등의기능을제공함 전자정부개발프레임워크실행환경 서비스그룹 Presentation Layer 설명 업무프로그램과사용자간의 Interface 를담당하는 Layer 로서, 사용자화면구성, 사용자입력정보검증등의기능을제공함 Layer Presentation Layer Logic Business Layer Persistence Integration Layer Business Logic Layer 업무프로그램의업무로직을담당하는 Layer 로서, 업무흐름제어, 에러처리등의기능을제공함 Persistence Layer 데이터베이스에대한연결및영속성처리, 선언적인트랜잭션관리를제공하는 Layer 임 Foundation Layer ( 공통기반레이어 ) Integration Layer 타시스템과의연동기능을제공하는 Layer 임 환경 서비스그룹 Foundation Layer ( 공통기반레이어 ) 실행환경의각 Layer 에서공통적으로사용하는공통기능을제공함 - 3 -
1. 개요 - 실행환경화면처리레이어 (2/3) 화면처리레이어는 MVC, Ajax Support 등총 5 개의서비스를제공함 실행환경 화면처리레이어 업무처리레이어 데이터처리레이어 연계통합레이어 MVC Internationalization Process Control DataSource Data Access Naming Service Ajax Support Security Exception Handling ORM TBD Transaction Integration Service UI Adaptor Web Service 공통기반레이어 AOP Cache Compress/Decompress Encryption/Decryption Excel File Handling File Upload/Download FTP Server Security ID Generation IoC Container Logging Mail Marshalling/Unmarshalling Object Pooling Property Resource Scheduling String Util XML Manipulation 실행환경서비스그룹서비스 - 4 -
1. 개요 - 실행환경화면처리레이어 화면처리레이어는 Spring MVC, Ajax Tags 등총 3 종의오픈소스 SW 를사용하고있음 서비스 오픈소스 SW 버전 MVC Spring 2.5 Ajax Support Ajax Tags 1.5 Internationalization Spring 2.5 Security Apache Commons Validator 1.3-5 -
2. MVC - 개요 (1/2) 서비스개요 MVC(Model-View-Controller) 패턴은코드를기능에따라 Model, View, Controller 3가지요소로분리한다. Model : 어플리케이션의데이터와비지니스로직을담는객체이다. View : Model의정보를사용자에게표시한다. 하나의 Model을다양한 View에서사용할수있다. Controller : Model과 View의중계역활을한다. 사용자의요청을받아 Model에변경된상태를반영하고, 응답을위한 View를선택한다. MVC 패턴은 UI 코드와비지니스코드를분리함으로써종속성을줄이고, 재사용성을높이고, 보다쉬운변경이가능하도록한다. MVC 패턴이 Web Framework에만사용되는단어는아니지만, 전자정부프레임워크에서 MVC 서비스 란 MVC 패턴을활용한 Web MVC Framework를의미한다. - 6 -
2. MVC - 개요 (1/2) 오픈소스 Web MVC Framework Spring MVC, Struts, Webwork 등이있다. 전자정부프레임워크에서는 Spring MVC를체택하였다. Framework내의특정클래스를상속하거나, 참조, 구현해야하는등의제약사항이비교적적다. IOC Contatiner가 Spring 이라면연계를위한추가설정없이 Spring MVC를사용할수있다. 오픈소스프로젝트가활성화 ( 꾸준한기능추가, 빠른 bug fix와 Q&A) 되어있으며로드맵이신뢰할만하다. 국내커뮤니티활성화정도, 관련참고문서나도서를쉽게구할수있다. Spring MVC DispatcherServlet, HandlerMapping, Controller, Interceptor, ViewResolver, View등각컴포넌트들의역할이명확하게분리된다. HandlerMapping, Controller, View등컴포넌트들에다양한인터페이스및구현클래스를제공한다. Controller(@MVC) 나폼클래스 ( 커맨드클래스 ) 작성시에특정클래스를상속받거나참조할필요없이 POJO 나 POJO-style 의클래스를작성함으로써비지니스로직에집중한코드를작성할수있다. 웹요청파라미터와커맨드클래스간에데이터매핑기능을제공한다. 데이터검증을할수있는, Validator와 Error 처리기능을제공한다. JSP Form을쉽게구성하도록 Tag를제공한다. - 7 -
2. MVC - Spring MVC Architecture(1/2) Spring MVC의핵심 Component DispatcherServlet Spring MVC Framework 의 Front Controller, 웹요청과응답의 Life Cycle 을주관한다. HandlerMapping 웹요청시해당 URL 을어떤 Controller 가처리할지결정한다. Controller 비지니스로직을수행하고결과데이터를 ModelAndView 에반영한다. ModelAndView Controller 가수행결과를반영하는 Model 데이터객체와이동할페이지정보 ( 또는 View 객체 ) 로이루어져있다. ViewResolver 어떤 View 를선택할지결정한다. View 결과데이터인 Model 객체를 display 한다. - 8 -
2. MVC - Spring MVC Architecture(2/2) Spring MVC 컴포넌트간의관계와흐름 Client의요청이들어오면 DispatchServlet이가장먼저요청을받는다. HandlerMapping이요청에해당하는 Controller를 return한다. Controller는비지니스로직을수행 ( 호출 ) 하고결과데이터를 ModelAndView에반영하여 return한다. ViewResolver는 view name을받아해당하는 View 객체를 return한다. View는 Model 객체를받아 rendering한다. - 9 -
Spring MVC 컴포넌트간의관계와흐름 HandlerMapping 이요청에해당하는 Controller 를 return 한다. Client 의요청이들어오면 DispatchServlet 이가장먼저요청을받는다. Controller 는비지니스로직을수행 ( 호출 ) 하고결과데이터를 ModelAndView 에반영하여 return 한다 View 는 Model 객체를받아 rendering 한다. ViewResolver 는 view name 을받아해당하는 View 객체를 return 한다. - 10 -
2. MVC - DispatcherServlet(1/3) DispatcherServlet Controller 로향하는모든웹요청의진입점이며, 웹요청을처리하며, 결과데이터를 Client 에게응답한다. Spring MVC 의웹요청 Life Cycle 을주관 - 11 -
2. MVC DispatcherServlet 상세. Spring MVC 의웹요청 Life Cycle 을주관하는 DispatcherServlet - 12 -
2. MVC DispatcherServlet(2/3) DispatcherServlet, ApplicationContext, WebApplicationContext 하나의빈설정파일에모든빈을등록할수도있지만, 아래와같이 Layer 별로빈파일을나누어등록하고 ApplicationContext, WebApplicationContext 사용하는것을권장. ApplicationContext : ContextLoaderListener에의해생성. persistance, service layer의빈 WebApplicationContext : DispatcherServlet에의해생성. presentation layer의빈 ContextLoaderListener는웹어플리케이션이시작되는시점에 ApplicationContext을만들고, 이 ApplicationContext의빈정보는모든 WebApplicationContext들이참조할수있다. - 13 -
2. MVC DispatcherServlet(3/3) web.xml 에 DispatcherServlet 설정하기 <!-- ApplicationContext 빈설정파일 --> <context-param> <param-name>contextconfiglocation</param-name> <param-value> /WEB-INF/config/service/easycompany-service.xml <!-- 서비스빈정의 --> /WEB-INF/config/service/easycompany-dao.xml <!--Dao 빈정의 --> </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.contextloaderlistener</listener-class> </listener> <!-- WebApplicationContext 빈설정파일 --> <servlet> <servlet-name>servlet</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> <param-name>contextconfiglocation</param-name> <param-value> /WEB-INF/config/easycompany-servlet.xml <!--web layer 관련빈선언 --> </param-value> </init-param> </servlet> <!-- WebApplicationContext 빈설정파일 --> <servlet> <servlet-name>webservice</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> <param-name>contextconfiglocation</param-name> <param-value> /WEB-INF/config/easycompany-webservice.xml </param-value> </init-param> </servlet> - 14 -
LAB 301-mvc LAB 301-mvc 실습 - 15 -
LAB 301-mvc Exercise 1-1-1. /hello.do 에동작하는 Controller 메소드만들기 @RequestMapping(value = "/hello.do") public String helloworld() { return getviewname(); Exercise 1-1-2. helloworld.jsp 만들기 ( 위치 : src\main\webapp\web-inf\jsp\hello ) <%@ page contenttype="text/html; charset=utf-8"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> </head> <body> <h1>hello 표준프레임워크 </h1> </body> </html> - 16 -
2. MVC @MVC(1/2) @MVC 어노테이션을이용한설정 : XML 기반으로설정하던정보들을어노테이션을사용해서정의한다. 유연해진메소드시그니쳐 : Controller 메소드의파라미터와리턴타입을좀더다양하게필요에따라선택할수있다. POJO-Style의 Controller : Controller 개발시에특정인터페이스를구현하거나특정클래스를상속해야할필요가없다. 하지만, 폼처리, 다중액션등기존의계층형 Controller가제공하던기능들을여전히쉽게구현할수있다. - 17 -
2. MVC @MVC(2/2) <context:component-scan/> 설정 @Component, @Service, @Repository, @Controller 가붙은클래스들을읽어들여 ApplicationContext, WebApplicationContext에빈정보를저장, 관리한다. @Controller만스캔하려면 <context:include-filter> 나 <context:exclude-filter> 를사용해야한다. <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation=http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/springcontext-2.5.xsd> <context:component-scan base-package="com.easycompany.controller.annotation"> <context:include-filter type="annotation" expression="org.springframework.stereotype.controller"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.service"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.repository"/> </context:component-scan> </beans> - 18 -
2. MVC HandlerMapping DefaultAnnotationHandlerMapping @MVC 개발을위한 HandlerMapping. 단 jdk1.5 이상의환경에서사용가능. @RequestMapping 에지정된 url 과해당 Controller 의메소드매핑 기본 HandlerMapping 이므로빈설정파일에별도로선언할필요없으나, 다른 HandlerMapping 과함께사용한다면선언해야 한다. SimpleUrlAnnotationHandlerMapping DefaultAnnotationHandlerMapping 은특정 url 에대해 interceptor 를적용할수없음. -> 확장 HandlerMapping DefaultAnnotationHandlerMapping 과함께사용. (order 프로퍼티를 SimpleUrlAnnotationHandlerMapping 에준다.) <bean id="selectannotaionmapper class="egovframework.rte.ptl.mvc.handler.simpleurlannotationhandlermapping p:order="1"> <property name="interceptors"> <list> <ref local="authenticinterceptor"/> </list> </property> <property name="urls"> <list> <value>/admin/*.do</value> <value>/user/userinfo.do</value> <value>/development/**/code*.do</value> </list> </property> </bean> <bean id="annotationmapper" class="org.springframework.web.servlet.mvc.annotation.defaultannotationhandlermapping p:order="2"/> - 19 -
2. MVC @Controller 관련어노테이션 (1/7) 관련어노테이션 @Controller 해당클래스가 Controller 임을나타내기위한어노테이션 @RequestMapping 요청에대해어떤 Controller, 어떤메소드가처리할지를맵핑하기위한어노테이션 @RequestParam Controller 메소드의파라미터와웹요청파라미터와맵핑하기위한어노테이션 @ModelAttribute Controller 메소드의파라미터나리턴값을 Model 객체와바인딩하기위한어노테이션 @SessionAttributes Model 객체를세션에저장하고사용하기위한어노테이션 @Controller @MVC 에서 Controller 를만들기위해서는작성한클래스에 @Controller 를붙여주면된다. 특정클래스를구현하거나상속할 필요가없다. import org.springframework.stereotype.controller; @Controller public class HelloController {... - 20 -
2. MVC @Controller 관련어노테이션 (2/7) @RequestMapping 요청에대해어떤 Controller, 어떤메소드가처리할지를맵핑하기위한어노테이션이다 관련속성 이름타입설명 value String[] URL 값으로맵핑조건을부여한다. @RequestMapping(value= /hello.do ) 또는 @RequestMapping(value={ /hello.do, /world.do ) 와같이표기하며, 기본값이기때문에 @RequestMapping( /hello.do ) 으로표기할수도있다. /mypath/*.do 와같이 Ant-Style의패턴매칭을이용할수도있다. method RequestM ethod[] HTTP Request 메소드값을맵핑조건으로부여한다. HTTP 요청메소드값이일치해야맵핑이이루어지게한다. @RequestMapping(method = RequestMethod.POST) 같은형식으로표기한다. 사용가능한메소드는 GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE 이다 params String[] HTTP Request 파라미터를맵핑조건으로부여한다. params= myparam=myvalue 이면 HTTP Request URL중에 myparam이라는파라미터가있어야하고값은 myvalue이어야맵핑한다. params= myparam 와같이파라미터이름만으로조건을부여할수도있고,!myParam 하면 myparam이라는파라미터가없는요청만을맵핑한다. @RequestMapping(params={ myparam1=myvalue, myparam2,!myparam3 ) 와같이조건을주었다면, HTTP Request에는파라미터 myparam1이 myvalue값을가지고있고, myparam2 파라미터가있어야하고, myparam3라는파라미터는없어야한다. - 21 -
2. MVC @Controller 관련어노테이션 (3/7) @RequestMapping 설정 @RequestMapping 은클래스단위 (type level) 나메소드단위 (method level) 로설정할수있다. type level /hello.do 요청이오면 HelloController의 hello 메소드가수행된다. type level에서 URL을정의하고 Controller에메소드가하나만있어도요청처리를담당할메소드위에 @RequestMapping 표기를해야제대로맵핑이된다. import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.requestmapping; @Controller @RequestMapping("/hello.do") public class HelloController { @RequestMapping public String hello(){... - 22 -
2. MVC @Controller 관련어노테이션 (4/7) method level /hello.do 요청이오면 hello 메소드, /helloform.do 요청은 GET 방식이면 helloget 메소드, POST 방식이면 hellopost 메소드가수행된다. import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.requestmethod; @Controller public class HelloController { @RequestMapping(value="/hello.do") public String hello(){... @RequestMapping(value="/helloForm.do", method = RequestMethod.GET) public String helloget(){... @RequestMapping(value="/helloForm.do", method = RequestMethod.POST) public String hellopost(){... - 23 -
2. MVC @Controller 관련어노테이션 (5/7) type + method level type level, method level 둘다설정할수도있는데, 이경우엔 type level에설정한 @RequestMapping의 value(url) 를 method level에서재정의할수없다. /hello.do 요청시에 GET 방식이면 helloget 메소드, POST 방식이면 hellopost 메소드가수행된다. @Controller @RequestMapping("/hello.do") public class HelloController { @RequestMapping(method = RequestMethod.GET) public String helloget(){... @RequestMapping(method = RequestMethod.POST) public String hellopost(){... - 24 -
2. MVC @Controller 관련어노테이션 (6/7) @RequestParam @RequestParam 은 Controller 메소드의파라미터와웹요청파라미터와맵핑하기위한어노테이션이다. 관련속성 이름타입설명 value String 파라미터이름 required boolean 해당파라미터가반드시필수인지여부. 기본값은 true 이다. 해당파라미터가 Request 객체안에없을때그냥 null값을바인드하고싶다면, 아래예제의 pageno 파라미터처럼 required=false로명시해야한다. name 파라미터는 required가 true이므로, 만일 name 파라미터가 null이면 org.springframework.web.bind.missingservletrequestparameterexception이발생한다. @Controller public class HelloController { @RequestMapping("/hello.do") public String hello(@requestparam("name") String name, @RequestParam(value="pageNo", required=false) String pageno){... - 25 -
2. MVC @Controller 관련어노테이션 (7/7) @ModelAttribute @ModelAttribute은 Controller에서 2가지방법으로사용된다. 1. Model 속성 (attribute) 과메소드파라미터의바인딩. 2. 입력폼에필요한참조데이터 (reference data) 작성. - SimpleFormContrller의 referencedata 메소드와유사한기능. 관련속성 이름타입설명 value String 바인드하려는 Model 속성이름. @SessionAttributes @SessionAttributes는 model attribute를 session에저장, 유지할때사용하는어노테이션이다. @SessionAttributes는클래스레벨 (type level) 에서선언할수있다. 관련속성 이름타입설명 value String[] session 에저장하려는 model attribute 의이름 required Class[] session 에저장하려는 model attribute 의타입 - 26 -
2. MVC @Controller 메소드시그니쳐 (1/2) @Controller 메소드시그니쳐 기존의계층형 Controller(SimpleFormController, MultiAction..) 에비해유연한메소드파라미터, 리턴값을갖는다. 메소드파라미터 Servlet API - ServletRequest, HttpServletRequest, HttpServletResponse, HttpSession 같은요청, 응답, 세션관련 Servlet API. org.springframework.web.context.request.webrequest, org.springframework.web.context.request.nativewebrequest java.util.locale java.io.inputstream / java.io.reader java.io.outputstream / java.io.writer @RequestParam - HTTP Request의파라미터와메소드의 argument를바인딩하기위해사용하는어노테이션. java.util.map / org.springframework.ui.model / org.springframework.ui.modelmap - 뷰에전달할모델데이터. Command/form 객체 - HTTP Request로전달된 parameter를바인딩한커맨드객체, @ModelAttribute을사용하면 alias를줄수있다. org.springframework.validation.errors / org.springframework.validation.bindingresult - 유효성검사후결과데이터를저장한객체. org.springframework.web.bind.support.sessionstatus - 세션폼처리시에해당세션을제거하기위해사용된다. - 27 -
2. MVC @Controller 메소드시그니쳐 (2/2) 메소드리턴타입 ModelAndView - 커맨드객체, @ModelAttribute 적용된메소드의리턴데이터가담긴 Model 객체와 View 정보가담겨있다. Model( 또는 ModelMap) - 커맨드객체, @ModelAttribute 적용된메소드의리턴데이터가 Model 객체에담겨있다. View 이름은 RequestToViewNameTranslator가 URL을이용하여결정한다. Map - 커맨드객체, @ModelAttribute 적용된메소드의리턴데이터가 Map 객체에담겨있으며, View 이름은역시 RequestToViewNameTranslator가결정한다 String - 리턴하는 String 값이곧 View 이름이된다. 커맨드객체, @ModelAttribute 적용된메소드의리턴데이터가 Model( 또는 ModelMap) 에담겨있다. 리턴할 Model( 또는 ModelMap) 객체가해당메소드의 argument에선언되어있어야한다 void - 메소드가 ServletResponse / HttpServletResponse등을사용하여직접응답을처리하는경우이다. View 이름은 RequestToViewNameTranslator가결정한다. - 28 -
2. MVC @MVC 예제 (1/3) @Controller 로폼처리구현하기 부서정보를수정하고저장하는폼페이지를 @Controller 로구현해보자. 메소드의이름은폼처리를담당하는 기존의 Form Controller 인 SimpleFormController 와의비교를위해기능별로동일하게지었다. 화면 & 시나리오 1. 파라미터부서번호의해당부서정보데이터를불러와입력폼을채운다. 2. 상위부서 (selectbox) 는부서정보데이터와는별도로, 상위부서에해당하는부서리스트데이터을구해서참조데이터로구성한다. 3. 사용자가데이터수정을끝내고저장버튼을누르면수정데이터로저장을담당하는서비스 (DB) 를호출한다. 4. 저장이성공하면부서리스트페이지로이동하고에러가있으면다시입력폼페이지로이동한다. - 29 -
2. MVC @MVC 예제 (2/3) Controller 작성하기 package com.easycompany.controller.annotation;... @Controller public class UpdateDepartmentController { @Autowired private DepartmentService departmentservice; // 상위부서 (selectbox) 는부서정보데이터와는별도로, 상위부서에해당하는부서리스트데이터을구해서참조데이터로구성한다. @ModelAttribute("deptInfoOneDepthCategory") public Map<String, String> referencedata() { Map<String, String> param = new HashMap<String, String>(); param.put("depth", "1"); return departmentservice.getdepartmentidnamelist(param); // 해당부서번호의부서정보데이터를불러와입력폼을채운다 @RequestMapping(value = "/updatedepartment.do", method = RequestMethod.GET) public String formbackingobject(@requestparam("deptid") String deptid, Model model) { Department department = departmentservice.getdepartmentinfobyid(deptid); model.addattribute("department", department); return "modifydepartment"; // 사용자가데이터수정을끝내고저장버튼을누르면수정데이터로저장을담당하는서비스 (DB) 를호출한다. // 저장이성공하면부서리스트페이지로이동하고에러가있으면다시입력폼페이지로이동한다. @RequestMapping(value = "/updatedepartment.do", method = RequestMethod.POST) public String onsubmit(@modelattribute("department") Department department) { try { departmentservice.updatedepartment(department); return "redirect:/departmentlist.do?depth=1"; catch (Exception e) { return "modifydepartment"; - 30 -
2. MVC @MVC 예제 (3/3) JSP 폼필드와모델데이터의편리한데이터바인딩을위해스프링폼태그를사용한다. commandname 에는 model attribute 를적어주면된다. department... <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>... <form:form commandname="department"> <table> <tr> <th> 부서번호 </th><td><c:out value="${department.deptid"/></td> </tr> <tr> <th> 부서이름 </th><td><form:input path="deptname" size="20"/></td> </tr> <tr> <th> 상위부서 </th> <td> <form:select path="superdeptid"> <option value=""> 상위부서를선택하세요.</option> <form:options items="${deptinfoonedepthcategory" /> </form:select> </td> </tr> <tr> <th> 설명 </th><td><form:textarea path="description" rows="10" cols="40"/></td> </tr> </table>... <input type="submit" value=" 저장 "/> <input type="button" value=" 리스트페이지 " onclick="location.href='/easycompany/departmentlist.do?depth=1'"/>... </form:form> - 31 -
LAB 301-mvc LAB 301-mvc 실습 - 32 -
LAB 301-mvc Exercise 1-2-1. mvc-servlet.xml 설정변경하기 : messagesource 활성화 <bean id="messagesource" class="org.springframework.context.support.resourcebundlemessagesource"> <property name="basenames"> <list> <value>messages.validation</value> <value>messages.label</value> </list> </property> </bean> Exercise 1-2-2. LoginController1.java 메소드추가하기 @RequestMapping(value = "/loginprocess1.do", method = RequestMethod.GET) public String loginformsetup() { return getformview(); @RequestMapping(value = "/loginprocess1.do", method = RequestMethod.POST) public String loginprocess(@modelattribute("login") LoginCommand logincommand) { return getsuccessview(); @ModelAttribute("loginTypes") protected List<LoginType> referencedata() throws Exception { List<LoginType> logintypes = new ArrayList<LoginType>(); logintypes.add(new LoginType("A", " 개인회원 ")); logintypes.add(new LoginType("B", " 기업회원 ")); logintypes.add(new LoginType("C", " 관리자 ")); return logintypes; @ModelAttribute("login") protected Object referencedata4login() throws Exception { return new LoginCommand(); - 33 -
LAB 301-mvc Exercise 1-2-3. LoginCommand.java 완성하기 private String id; private String password; private String logintype; public String getid() { return id; public void setid(string id) { this.id = id; public String getpassword() { return password; public void setpassword(string password) { this.password = password; public String getlogintype() { return logintype; public void setlogintype(string logintype) { this.logintype = logintype; - 34 -
2. MVC - 참고자료 Spring Framework API http://static.springframework.org/spring/docs/2.5.x/api/index.html The Spring Framework - Reference Documentation http://static.springframework.org/spring/docs/2.5.x/reference/spring-web.html - 35 -
3. Internationalization( 국제화 ) 개요 (1/8) 서비스개요 전자정부표준프레임워크에서는 Spring MVC 에서제공하는 LocaleResolver를이용한다. Spring MVC 는다국어를지원하기위하여아래와같은종류의 LocaleResolver 를제공하고있다. CookieLocaleResolver : 쿠키를이용한 locale정보사용 SessionLocaleResolver : 세션을이용한 locale정보사용 AcceptHeaderLocaleResolver : 클라이언트의브라우져에설정된 locale정보사용 * Bean 설정파일에정의하지않을경우 AcceptHeaderLocaleResolver 가 default 로적용된다. - 36 -
3. Internationalization( 국제화 ) 설명 (2/8) CookieLocaleResolver CookieLocaleResolver 를설정하는경우사용자의쿠키에설정된 Locale 을읽어들인다. Bean 설정정보 (xx-servlet.xml) <bean id="localeresolver" class="org.springframework.web.servlet.i18n.cookielocaleresolver" > <property name="cookiename" value="clientlanguage"/> <property name="cookiemaxage" value="100000"/> <property name="cookiepath" value="web/cookie"/> </bean> Property 속성 - 37 -
3. Internationalization( 국제화 ) 설명 (3/8) SessionLocaleResolver requst 가가지고있는 session 으로부터 locale 정보를가져온다. Bean 설정정보 (xx-servlet.xml) <bean id="localeresolver" class="org.springframework.web.servlet.i18n.sessionlocaleresolver" /> AcceptHeaderLocaleResolver 사용자의브라우저에서보내진 request 의헤더에 accept-language 부분에서 Locale 을읽어들인다. 사용자브 라우저의 Locale 을나타낸다. Bean 설정정보 (xx-servlet.xml) <bean id="localeresolver" class="org.springframework.web.servlet.i18n.acceptheaderlocaleresolver" /> - 38 -
3. Internationalization( 국제화 ) 설명 (4/8) 샘플예제 (SessionLocaleResolver ) Web Configuration Filter 설정 Web 을통해들어오는요청을 Charset UTF-8 적용 1. CharacterEncodingFilter 을이용하여 encoding 할수이도록아래와같이세팅 (Web.xml) <filter> <filter-name>encoding-filter</filter-name> <filter-class> org.springframework.web.filter.characterencodingfilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> - 39 -
3. Internationalization( 국제화 ) 설명 (5/8) Spring Configuration (xx-servlet.xml) 아래와같이 localeresover 와 localechangeinterceptor 를등록하고 Annotation 기반에서동작할수있도록 DefaultAnnotationHandlerMapping 에 interceptor 로등록을해준다. SessionLocaleResolver 를이용하여위와같이하였을경우 Locale 결정은 language Request Parameter 로넘기게된다. <bean id="localeresolver" class="org.springframework.web.servlet.i18n.sessionlocaleresolver" /> <!-- 쿠키를이용한 Locale 이용시 <bean id="localeresolver" class="org.springframework.web.servlet.i18n.cookielocaleresolver"/> --> <bean id="localechangeinterceptor" class="org.springframework.web.servlet.i18n.localechangeinterceptor"> <property name="paramname" value="language" /> </bean> <bean id="annotationmapper" class="org.springframework.web.servlet.mvc.annotation.defaultannotationhandlermapping"> <property name="interceptors"> <list> <ref bean="localechangeinterceptor" /> </list> </property> </bean> - 40 -
3. Internationalization( 국제화 ) 설명 (6/8) Message Source 설정 먼저다국어를지원해야하므로메시지를 MessageSource 로추출하여구현해야한다. 자세한 MessageSource 내용은 Resource 를참고하길바란다. messagesource는아래와같이설정하였다. <bean id="messagesource" class="org.springframework.context.support.resourcebundlemessagesource"> <property name="basenames"> <list> <value>classpath:/message/message</value> </list> </property> </bean> message properties 파일은아래와같다. locale 에따라 ko, en 으로구분하였다. message_ko.properties 파일 : view.category= 카테고리 message_en.properties 파일 : view.category=category - 41 -
3. Internationalization( 국제화 ) 설명 (7/8) JSP Spring Message Tag 이용 : <spring:message code="view.category" /> <%@ taglib prefix="spring" uri=http://www.springframework.org/tags %> <form:form commandname="message" >... <table border="1" cellspacing="0" class="boardlist" summary="list of Category"> <thead> <tr> <th scope="col">no.</th> <th scope="col"> <input name="checkall" type="checkbox" class="inputcheck" title="check All" onclick="javascript:fnccheckall();"/> </th> <th scope="col"><spring:message code="view.category" /> ID</th> <th scope="col"><spring:message code="view.category" /> 명 </th> <th scope="col"> 사용여부 </th> <th scope="col">description</th> <th scope="col"> 등록자 </th> </tr> </thead>... - 42 -
3. Internationalization( 국제화 ) 설명 (8/8) 결과 화면상으로해당페이지를실행해보면아래와같다. - 43 -
LAB 301-mvc LAB 301-mvc 실습 - 44 -
LAB 301-mvc Step 1-3-1.. mvc-servlet.xml 추가설정하기 <!-- [Exercise 1-3-3] mvc-servlet.xml 추가설정하기 : SessionLocaleResolver 를이용한 locale 설정 --> <!-- setting Locale --> <bean id="localechangeinterceptor" class="org.springframework.web.servlet.i18n.localechangeinterceptor" p:paramname="lang" /> <bean id="localeresolver" class="org.springframework.web.servlet.i18n.sessionlocaleresolver" /> <!-- Locale Interceptor 설정하기 --> <bean class="org.springframework.web.servlet.mvc.annotation.defaultannotationhandlermapping"> <property name="interceptors"> <list> <ref bean="localechangeinterceptor"/> </list> </property> </bean> Step 1-3-2. LoginController1.java 에 @SessionAttributes 설정하기 @Controller @SessionAttributes("login") public class LoginController2 { - 45 -
LAB 301-mvc Step 1-3-3. LoginController2.java 추가메소드작성하기 @RequestMapping(value = "/memberinfo.do") public ModelAndView memberinfo(httpsession httpsession) { ModelAndView mav = new ModelAndView("login/memberInfo"); if (httpsession.getattribute("login")!= null) mav.addobject("login", httpsession.getattribute("login")); return mav; @RequestMapping(value = "/loginout.do", method = RequestMethod.GET) public String logout(sessionstatus sessionstatus) { if (!sessionstatus.iscomplete()) sessionstatus.setcomplete(); return getformview(); @ModelAttribute("loginTypes") protected List<LoginType> referencedata() throws Exception { List<LoginType> logintypes = new ArrayList<LoginType>(); logintypes.add(new LoginType("A", " 개인회원 ")); logintypes.add(new LoginType("B", " 기업회원 ")); logintypes.add(new LoginType("C", " 관리자 ")); return logintypes; @ModelAttribute("login") protected Object referencedata4login() throws Exception { return new LoginCommand(); - 46 -
3. Internationalization( 국제화 ) 참고자료 The Spring Framework - Reference Documentation http://static.springframework.org/spring/docs/2.5.x/reference/ - 47 -
4. Ajax Support - 개요 Ajax Support 일반적으로 Ajax 기능은 javascript 언어로개발하나, server-side 구현에익숙한 J2EE 개발자들에게는쉽지않은작업이다. Ajax를이용해자주사용되는기능을 custom tag형태로제공한다. 오픈소스라이브러리인 AjaxTags를이용한다. - 48 -
LAB 302-ajax LAB 302-ajax 실습 - 49 -
LAB 302-ajax Step 2-1-1. AjaxSimpleController.java 에 simpleajax 메소드구현하기 @SuppressWarnings("unchecked") @RequestMapping(value = "/autocomplete.do") public ModelAndView simpleajax(@requestparam("keyword") String keyword) { ModelAndView mav = new ModelAndView(new AjaxSimpleView()); List keywordlist = search(keyword); StringBuffer sb = new StringBuffer(); sb.append(keywordlist.size()); sb.append(" "); for (int i = 0; i < keywordlist.size(); i++) { String key = (String) keywordlist.get(i); sb.append(key); if (i < keywordlist.size() - 1) { sb.append(","); log.debug(sb.tostring()); mav.addobject("ajaxsimple", sb.tostring()); return mav; Step 2-1-2. AjaxSimpleView.java 완성하기 writer.write((string) model.get("ajaxsimple")); - 50 -
4. Ajax Support -AjaxTags(1/2) AjaxTags AjaxTags 는 javascript 로 Ajax 기능을실행하지만, 이용하는개발자에게 JSP Tag Library 형태의 API 만을노출 시키고필요한값만을입력받음으로써쉽게 Ajax 기능을구현할수있도록한다. 시스템환경및필요라이브러리 JDK 1.5 Servlet container running Servlets 2.4+ and JSP 2.0+ (jsp-api 2.0,servlet-api 2.4) AjaxTags 라이브러리 - 51 -
4. Ajax Support -AjaxTags(2/2) 설치 AjaxTags 라이브러리를 download 한후 WEB-INF/lib 에위치시킨다. web.xml 설정. <servlet> <servlet-name>sourceloader</servlet-name> <servlet-class>net.sourceforge.ajaxtags.servlets.sourceloader</servlet-class> <init-param> <param-name>prefix</param-name> <param-value>/ajaxtags</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>sourceloader</servlet-name> <url-pattern>/ajaxtags/js/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>sourceloader</servlet-name> <url-pattern>/ajaxtags/img/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>sourceloader</servlet-name> <url-pattern>/ajaxtags/css/*</url-pattern> </servlet-mapping> - 52 -
4. Ajax Support - AjaxTags Reference & Usage AjaxTags Reference & Usage ajax:autocomplete 자동완성기능. 보통검색입력창에 prefix 문자를입력하면해당추천검색어를보여주는방식으로이용. ajax:select 하나의셀렉트박스에서값을변경하면다른셀렉트박스에연관된값으로리스트를구성. ajax:tabpanel 탭으로구성된페이지를새로고침없이보여줄때. 이외에도여러기능이있다. AjaxTags 의 Tag 레퍼런스및사용법은아래 AjaxTags 사이트에서확인할수있다. http://ajaxtags.sourceforge.net/usage.html - 53 -
4. Ajax Support - 예제 (1/5) ajax:autocomplete 기능구현하기 사원정보조회페이지에서, 조회조건중에하나인이름필드에자동완성기능 (autocomplete) 을적용해본다. 검색하려는이름을입력하기시작하면, 입력값에해당하는 prefix 를가진이름들이추천리스트로나온다. - 54 -
4. Ajax Support - 예제 (2/5) JSP 태그라이브러리선언 <%@ taglib prefix="ajax" ri="http://ajaxtags.sourceforge.net/tags/ajaxtags" %> 관련 Javascript, CSS 선언 <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/prototype.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/scriptaculous/scriptaculous.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/overlibmws/overlibmws.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/ajaxtags.js"></script> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/ajaxtags.css" /> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/displaytag.css" /> <ajax:autocomplete/> 사용 <ajax:autocomplete baseurl= ajax url" source= 입력필드이름 " target= 입력필드이름 " classname= CSS 클래스이름 " minimumcharacters= 최소입력값 " /> - 55 -
4. Ajax Support - 예제 (3/5) /easycompany/webapp/jsp/annotation/employeelist.jsp <%@ taglib prefix="ajax" uri="http://ajaxtags.sourceforge.net/tags/ajaxtags" %>... <!--Ajax Tags--> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/prototype.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/scriptaculous/scriptaculous.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/overlibmws/overlibmws.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/ajaxtags.js"></script> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/ajaxtags.css" /> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/displaytag.css" /> <form:form commandname="searchcriteria" action="/easycompany/employeelist.do"> <table width="50%" border="1"> <tr> <td> 사원번호 : <form:input path="searcheid"/> </td> <td> 부서번호 : <form:input path="searchdid"/> </td> <td> 이름 : <form:input path="searchname"/> </td> <td><input type="submit" value=" 검색 " onclick="this.disabled=true,this.form.submit();" /></td> </tr> </table> </form:form> <ajax:autocomplete baseurl="${pagecontext.request.contextpath/suggestname.do" source="searchname" target="searchname" classname="autocomplete" minimumcharacters="1" /> - 56 -
4. Ajax Support - 예제 (4/5) Controller 검색이름필드 serachname에입력된값으로추천이름리스트를받아온다. 결과데이터를 XML 형식으로변환하고, Model 데이터에담는다. 결과데이터 display를 AjaxXmlView가담당한다. JSP 페이지에프린트되는일반적인응답방식이아니므로, 응답처리를위한 View(AjaxXmlView) 를만들어야한다. package com.easycompany.controller.annotation;... import net.sourceforge.ajaxtags.xml.ajaxxmlbuilder; import com.easycompany.view.ajaxxmlview; @Controller public class AjaxController { @RequestMapping("/suggestName.do") protected ModelAndView suggestname(@requestparam("searchname") String searchname){ ModelAndView model = new ModelAndView(new AjaxXmlView()); List<String> namelist = employeeservice.getnamelistforsuggest(searchname); AjaxXmlBuilder ajaxxmlbuilder = new AjaxXmlBuilder(); for(string name:namelist){ ajaxxmlbuilder.additem(name, name, false); model.addobject("ajaxxml",ajaxxmlbuilder.tostring()); return model; - 57 -
4. Ajax Support - 예제 (5/5) View 결과데이터의형식을응답객체에설정한다. Controller 에서보낸 Model 객체의결과데이터를꺼내 write 한다. package com.easycompany.view; import java.io.printwriter; import java.util.map; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.springframework.web.servlet.view.abstractview; public class AjaxXmlView extends AbstractView { @Override protected void rendermergedoutputmodel(map model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setcontenttype("text/xml"); response.setheader("cache-control", "no-cache"); response.setcharacterencoding("utf-8"); PrintWriter writer = response.getwriter(); writer.write((string) model.get("ajaxxml")); writer.close(); - 58 -
4. Ajax Support - 추가예제 예제 (easycompany) 속의 AjaxTags ajax:autocomplete 사원리스트페이지 (/easycompany/employeelist.do) 에서이름검색. Controller : com.easycompany.controller.annotation. AjaxController suggestname 메소드 JSP : /easycompany/webapp/jsp/annotation/employeelist.jsp ajax:select 사원정보수정페이지 (/easycompany/updateemployee.do?employeeid= 사원아이디 ) 에서상위부서 select box 선택시하위부서 select box 데이터자동변환. Controller : com.easycompany.controller.annotation. AjaxController getdeptinfoforselecttag 메소드 JSP : /easycompany/webapp/jsp/annotation/modifyemployee.jsp ajax:tabpanel 부서리스트페이지 (/easycompany/departmentlist.do?depth=1) 에서상하위부서정보를탭처리. Controller : Controller 불필요. JSP : /easycompany/webapp/jsp/annotation/departmentlist.jsp - 59 -
LAB 302-ajax LAB 302-ajax 실습 - 60 -
LAB 302-ajax HsqlDB 를실행하여라.(lab302-ajax\db\runHsqlDB.cmd) Step 2-2-1. employeelist.jsp 에서 Ajax Tags Resource 를붙여준다. Line 16 <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/prototype.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/scriptaculous/scriptaculous.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/overlibmws/overlibmws.js"></script> <script type="text/javascript" src="<%=request.getcontextpath()%>/ajaxtags/js/ajaxtags.js"></script> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/ajaxtags.css" /> <link type="text/css" rel="stylesheet" href="<%=request.getcontextpath()%>/ajaxtags/css/displaytag.css" /> Step 2-2-2. employeelist.jsp 에서 Ajax Tags Script(AutoComplete 용 ) 를붙여준다. <ajax:autocomplete baseurl="suggestname.do" source="searchname" target="searchname" classname="autocomplete" minimumcharacters="1" /> Step 2-2-3. employeelist.jsp 에서 Ajax Tags Script(select 용 ) 를붙여준다. <ajax:select baseurl="autoselectdept.do" parameters="depth=2,superdeptid={superdeptid" source="superdeptid" target="departmentid" emptyoptionname="select model"/> - 61 -
LAB 302-ajax Step 2-2-4. employeeservice.getnamelistforsuggest 메소드를호출하여결과를가져온다. namelist = employeeservice.getnamelistforsuggest(searchname); Step 2-2-5. 호출하고보니 EmployeeServiceImpl 의메소드가완성되어있지않다. 따라서 EmployeeServiceImpl.java 를완성한다. EmployeeService Interface 를구현한다. public class EmployeeServiceImpl implements EmployeeService { Step 2-2-6. getnamelistforsuggest 메소드를구현한다.(comment 처리를지운다.) public List<String> getnamelistforsuggest(string nameprefix) { Step 2-2-7. employeedao 의 getnamelistforsuggest 메소드를이용하여검색한후결과를리턴한다. public List<String> getnamelistforsuggest(string nameprefix) { return employeedao.getnamelistforsuggest(nameprefix); - 62 -
4. Ajax Support - 참고자료 AjaxTags Web Site http://ajaxtags.sourceforge.net/index.html - 63 -
5. Security - 개요 Security 서비스 인증, 권한같은일반적인 ( 통상적인 ) 개념의 Security 서비스는 Spring Security를활용한공통기반레이어에서제공한다. 화면처리레이어의 Security 서비스는입력값유효성검증기능을제공한다. 입력값유효성검증 (validation) 을위한기능은 Valang, Jakarta Commons, Spring 등에서제공한다. 기반오픈소스로 Jakarta Commons Validator를선택. MVC 프레임워크인 Spring MVC와 Jakarta Commons Validator의연계와활용방안을제공한다. - 64 -
5. Security - Jakarta Commons Validator Jakarta Commons Validator Jakarta Commons Validator는필수값, 각종 primitive type(int,long,float ), 최대-최소길이, 이메일, 신용카드번호등의값체크등을할수있도록 Template이제공된다. Template은 Java 뿐아니라 Javascript로도제공되어 client-side, server-side의검증을함께할수있으며, Configuration과에러메시지를 client-side, server-side 별로따로하지않고한곳에같이쓰는관리상의장점이있다. - 65 -
5. Security - Spring+Commons Validator Spring Framework + Jakarta Commons Validator Struts에서는 Commons Validator를사용하기위한 org.apache.struts.validator.validatorplugin 같은플러그인클래스를제공하는데, Spring에서는 Spring Modules(https://springmodules.dev.java.net/) 프로젝트에서연계모듈을제공한다. 필요라이브러리 commons-validator : Ver 1.3.1 아래 4개의파일에대한 dependency가있다. 1. commons-beanutils : Ver 1.7.0 2. commons-digester : Ver 1.8 3. commons-logging : Ver 1.0.4 4. oro : Ver 2.0.8 spring modules : Ver 0.9 다운받고압축을풀어보면여러파일들이있으나여기서필요한건 spring-modules-validation.jar 뿐이다. 예제를보려면 \samples\sources\spring-modules-validation-commons-samples-src.zip도필요하다. 위에서언급한라이브러리들을설치한다. - 66 -
5. Security - DefaultValidatorFactory, DefaultBeanValidator DefaultValidatorFactory, DefaultBeanValidator 설정 DefaultValidatorFactory 프로퍼티 'validationconfiglocationsapache' 에정의된 Validation rule을기반으로 Commons Validator들의인스턴스를얻는다. DefaultBeanValidator DefaultBeanValidator는 org.springframework.validation.validator를 implements하고있지만, DefaultValidatorFactory가가져온 Commons Validator의인스턴스를이용해 validation을수행한다. Controller의 validation을수행할때이 DefaultBeanValidator를참조하면된다. 빈정의파일에아래와같이 DefaultValidatorFactory, DefaultBeanValidator 를선언한다. <!-- Integrated Apache Commons Validator by Spring Modules --> <bean id="beanvalidator" class="org.springmodules.validation.commons.defaultbeanvalidator"> <property name="validatorfactory" ref="validatorfactory"/> </bean> <bean id="validatorfactory" class="org.springmodules.validation.commons.defaultvalidatorfactory"> <property name="validationconfiglocations"> <list> <value>/web-inf/config/validator-rules.xml</value> <value>/web-inf/config/validator.xml</value> </list> </property> </bean> - 67 -
5. Security - validator-rules.xml validator-rules.xml 설정 validator-rules.xml 은 application 에서사용하는모든 validation rule 에대해정의하는파일이다. <validator> 태그를구성하는주요요소는아래와같다. name : validation rule(required,mask,integer,email ) classname : validation check 를수행하는클래스명 (org.springmodules.validation.commons.fieldchecks) method : validation check 를수행하는클래스의메소드명 (validaterequired,validatemask ) methodparams : validation check 를수행하는클래스의메소드의파라미터 msg : 에러메시지 key. (message 프로퍼티에서설정한다.) javascript : client-side validation 을위한자바스크립트코드 <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN" "http://jakarta.apache.org/commons/dtds/validator_1_0.dtd"> <form-validation> <global> <validator name="required" classname="org.springmodules.validation.commons.fieldchecks" method="validaterequired" methodparams="java.lang.object, org.apache.commons.validator.validatoraction, org.apache.commons.validator.field, org.springframework.validation.errors" msg="errors.required > <javascript><![cdata[... ]]> </javascript> </validator> </form-validation> - 68 -
5. Security - Validation Rule Validation Rule name(validation rule) FieldCheck 클래스 FieldCheck 메소드기능 required org.springmodules.validation.commons.fieldchecks validaterequired 필수값체크 minlength org.springmodules.validation.commons.fieldchecks validateminlength 최소길이체크 maxlength org.springmodules.validation.commons.fieldchecks validatemaxlength 최대길이체크 mask org.springmodules.validation.commons.fieldchecks validatemask 정규식체크 byte org.springmodules.validation.commons.fieldchecks validatebyte Byte형체크 short org.springmodules.validation.commons.fieldchecks validateshort Short형체크 integer org.springmodules.validation.commons.fieldchecks validateinteger Integer 형체크 long org.springmodules.validation.commons.fieldchecks validatelong Long 형체크 Spring Modules float org.springmodules.validation.commons.fieldchecks validatefloat Float형체크 double org.springmodules.validation.commons.fieldchecks validatedouble Double형체크 date org.springmodules.validation.commons.fieldchecks validatedate Date형체크 range org.springmodules.validation.commons.fieldchecks validateintrange 범위체크 intrange org.springmodules.validation.commons.fieldchecks validateintrange int형범위체크 floatrange org.springmodules.validation.commons.fieldchecks validatefloatrange Float형범위체크 creditcard org.springmodules.validation.commons.fieldchecks validatecreditcard 신용카드번호체크 email org.springmodules.validation.commons.fieldchecks validateemail 이메일체크 ihidnum egovframework.rte.ptl.mvc.validation.rtefieldchecks validateihidnum 주민등록번호체크 korean egovframework.rte.ptl.mvc.validation.rtefieldchecks validatekorean 한글체크 htmltag egovframework.rte.ptl.mvc.validation.rtefieldchecks validatehtmltag <,> 태그정보체크 egovframework - 69 -
5. Security - validator.xml(1/2) validator.xml 설정 validator.xml 은 validation rule 과 validation 할 Form 을매핑한다. form name 과 field property 의 name-rule 은 Server-side 와 Client-side 인경우에따라다르다. Server-side validation 의경우 form name 과 field property 는 validation 할폼클래스의이름, 필드가각각매핑된다.(camel case) 폼클래스가 Employee 면 employee, DepartmentForm 이면 departmentform 을 form name 으로지정한다. Client-side 의경우 form name 은 JSP 에서설정한 <validator:javascript formname= employee /> 태그의 formname 과매핑되고, field property 는각각의폼필드의이름과일치하면된다. 따라서, Server-side, Client-side 둘다수행하려면, JSP 의 <validator:javascript formname= employee /> 태그의 formname 은폼클래스의이름이되어야하고, JSP 의폼필 드들은폼클래스의필드와일치해야한다. - 70 -
5. Security - validator.xml(2/2) depends는해당필드에적용할 (validator-rules.xml에정의된 rule name) validator를의미한다. <arg key > 는메시지출력시파라미터를지정하는값이다. 아래와같이작성했다면, Employee 클래스의 name 필드에대해서필수값체크를, age 필드에대해서 integer 체크를, email 필드에대해선필수값과 email 유효값체크를하겠다는의미이다. <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN" http://jakarta.apache.org/commons/dtds/validator_1_1.dtd> <form-validation> <formset> <form name="employee"> <field property="name" depends="required,korean"> <arg0 key="employee.name" /> </field> <field property="age" depends="integer"> <arg0 key="employee.age" /> </field> <field property="email" depends="email,htmltag"> <arg0 key="employee.email" /> </field> <field property="ihidnum" depends="ihidnum"/> </form> </formset> </form-validation> - 71 -
5. Security - Server-Side Validation(1/4) Server-Side Validation Controller Server-Side Validation 을위해 Controller 에 validation 로직을추가. package com.easycompany.controller.annotation;... import org.springmodules.validation.commons.defaultbeanvalidator;... @Controller public class UpdateEmployeeController { @Autowired private DefaultBeanValidator beanvalidator;... @RequestMapping(value = "/updateemployee.do", method = RequestMethod.POST) public String updateemployee(@modelattribute("employee") Employee employee, BindingResult bindingresult, Model model) { beanvalidator.validate(employee, bindingresult); //validation 수행 if (bindingresult.haserrors()) { // 만일 validation 에러가있으면...... return "modifyemployee"; employeemanageservice.updateemployee(employee); return "changenotify"; - 72 -
5. Security - Server-Side Validation(2/4) JSP form submit을하면이름, 나이, 이메일등의입력값이 Employee 클래스에바인딩이되어서 Controller에전달이되고, Controller에 validation 수행로직이있으면 validator.xml 내용에따라 validation이이루어진다. 만일에러가발생하면 <form:error /> 에해당에러메시지를출력한다. <form:form commandname="employee"> <table> <tr> <th> 이름 </th><td><form:input path="name" size="20"/><form:errors path="name" /></td> </tr> <tr> <th> 비밀번호 </th><td><form:input path="password" size="10"/></td> </tr> <tr> <th> 나이 </th><td><form:input path="age" size="10"/><form:errors path="age" /></td> </tr> <tr> <th> 이메일 </th><td><form:input path="email" size="50"/><form:errors path="email" /></td> </tr> </table> <table width="80%" border="1"> <tr> <td><input type="submit"/> <input type="button" value="list" onclick="location.href='/easycompany/employeelist.do'"/> </td> </tr> </table> </form:form> - 73 -
5. Security - Server-Side Validation(3/4) 에러메시지등록 메시지파일 (message.properties) 에에러메시지를등록한다. validation 에러가발생하면 validator-rules.xml에서정의했던 msg값으로에러메시지의 key값을찾아해당하는메시지를출력해준다. 예를들어, email validation에서에러가발생하면 msg값이 errors.email 이므로, 유효하지않은이메일주소입니다. 라는에러메시지를 JSP에있는 <form:errors path= email /> 부분에출력하게된다. employee.name= 이름 employee.email= 이메일 employee.age= 나이 employee.password= 비밀번호 # -- validator errors -- errors.required={0 은필수입력값입니다. errors.minlength={0 은 {1 자이상입력해야합니다. errors.maxlength={0 은 {1 자이상입력할수없습니다. errors.invalid={0 은유효하지않은값입니다. errors.byte={0 은 byte타입이어야합니다. errors.short={0 은 short타입이어야합니다. errors.integer={0 은 integer 타입이어야합니다.... errors.email= 유효하지않은이메일주소입니다. - 74 -
5. Security - Server-Side Validation(4/4) TEST 이름필드에값을비우고 submit 하면, name 에필수값 (required) validation rule 이설정되어있으므로 아래와같이이름필드옆에에러메시지가출력된다. - 75 -
5. Security - Client-Side Validation(1/3) Client-Side Validation validator.jsp 추가 <%@ page language="java" contenttype="javascript/x-javascript" %> <%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> <validator:javascript dynamicjavascript="false" staticjavascript="true"/> /validator.do 로호출하도록 Controller 에서메소드를추가하고 requestmapping 한다. validator.jsp 를 http://localhost:8080/easycompany/validator.do 브라우져에서호출해보면, validator-rules.xml 에서정의한 javascript 함수들이다운로드되거나화면에 print 되는걸확인할수있다. validator.jsp 는 client-validation 을위해 validator-rules.xml 에서정의한 javascript 함수들을로딩한다. 따라서 client-validation 을할페이지에서는이 validator.jsp 를 <script type= text/javascript src= <c:url value= /validator.do /> ></script> 같이호출한다. JSP 설정 (taglib,javascript) 추가 client-validation 을위해서는해당 JSP 에아래와같은작업이추가되어야한다. commons-validator taglib 를선언한다. <%@ taglib prefix= validator uri= http://www.springmodules.org/tags/commons-validator %> 필요한자바스크립트함수를 generate 하기위한코드를추가한다. validation-rules.xml 에서선언한함수를불러오기위해, 위에서작성한 validator.jsp 를아래와같이호출한다. <script type= text/javascript src= <c:url value= /validator.do /> ></script> - 76 -
5. Security - Client-Side Validation(2/3) 위의자바스크립트함수를이용해필요한 validation 과메시지처리를위한자바스크립트를 generate 하기위한코드를추가 한다. formname 에는 validator.xml 에서정의한 form 의이름을써준다. <validator:javascript formname= employee staticjavascript= false xhtml= true cdata= false /> form submit 시에 validatevo 클래스명 () 함수를호출한다. onsubmit= return validateemployee(this) > 따라서앞의 server-side validation 에서작성한 modifyemployee.jsp 은아래와같이변경된다. <!-- commons-validator tag lib 선언 --> <%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> <!--for including generated Javascript Code(in validation-rules.xml)--> <script type="text/javascript" src="<c:url value="/validator.do"/>"></script> <!--for including generated JavascriptCode(validateEmployee(),formName:validator.xml 에서정의한 form 의이름 )--> <validator:javascript formname="employee" staticjavascript="false" xhtml="true" cdata="false"/> <script type="text/javascript"> function save(form){ if(!validateemployee(form)){ return; else{ form.submit(); </script> <form:form commandname="employee"> <!--<input type="submit"/>--> <input type="button" value="save" onclick="save(this.form)"/> <!-- client-validation 을위해바로 submit 하지않고먼저 validateemployee 함수를호출 --> <input type="button" value="list" onclick="location.href='/easycompany/employeelist.do'"/> </td></tr> </table> </form:form> - 77 -
5. Security - Client-Side Validation(3/3) TEST 이름필드의값을지우고저장버튼을누르면아래와같은 alert 메시지가보인다. - 78 -
5. Security - 참고자료 Spring Modules Reference Documentation v 0.9-79 -
6. UI Adaptor - 개요 서비스개요 전자정부표준프레임워크와 UI 솔루션 (Rich Internet Application) 연동. 보통 Web Framework 과 UI 솔루션과의연동을하는방법중가장많이사용하는방식은 Controller 역할을수행하는 Servlet 객체에서업무로직을호출전데이타를 DTO 형태로변화하여업무로직으로넘기는방식. 전자정부표준프레임워크에서는 Spring MVC Annotation 기반으로개발시메소드의파라미터로넘어오는객체가 request 객체가아닌업무용 DTO 클래스로넘어올수있도록가이드하는방식을선택. - 80 -
6. UI Adaptor- 설명 (1/8) 전자정부표준프레임워크의 UI Adaptor 구현시나리오 UI솔루션데이타에서 DTO로변환 1. AnnotationMethodHandlerAdapter 의 CustomRiaArgumentResolver 등록 CustomRiaArgumentResolver 2. UIAdaptor 구현 / 등록 UIAdaptorImpl Controller 메소드구현 BeanNameViewResolver 설정 RiaView 구현 RiaView 구현 / 등록 RiaView - 81 -
6. UI Adaptor- 설명 (2/8) UI 솔루션데이터에서 DTO 로변환 AnnotationMethodHandlerAdapter 의 CustomRiaArgumentResolver 등록 CustomRiaArgumentResolver WebArgumentResolver 의구현체인 CustomRiaArgumentResolver 는 uiadaptor 에세팅된 Adaptor 를실행해준다. <bean class="org.springframework.web.servlet.mvc.annotation.annotationmethodhandleradapter"> <property name="webbindinginitializer"> <bean class="egovframework.rte.fdl.web.common.egovbindinginitializer" /> </property> <property name="customargumentresolvers"> <list> <bean class="egovframework.rte.fdl.sale.web.customriaargumentresolver"> <property name="uiadaptor"> <list> <ref bean="riaadaptor" /> </list> </property> </bean> </list> </property> </bean> - 82 -
6. UI Adaptor- 설명 (3/8) CustomRiaArgumentResolver UiAdaptor 의구현체는아래와같다. 여기서는 Miplatform 의예를들어코드를작성하였다. UI 솔루션의객체에서 DTO 로데이타를옮기는역할은 convert 메소드에서수행한다. public class CustomRiaArgumentResolver implements WebArgumentResolver { private UiAdaptor[] uias; public void setuiadaptors(uiadaptor[] uias) { this.uias = uias; public Object resolveargument(methodparameter methodparameter, NativeWebRequest webrequest) throws Exception { Class<?> type = methodparameter.getparametertype(); Object uiobject = null; if (uias == null) return UNRESOLVED; // 여기서 Adapter 를찾는방법을필히물어볼것... for (UiAdaptor uia : uias) { if (type.equals(uia.getmodelname())) { HttpServletRequest request = (HttpServletRequest) webrequest.getnativerequest(); // uiobject = (UdDTO) uia.convert(request); uiobject = (Object) uia.convert(request); return uiobject; return UNRESOLVED; - 83 -
6. UI Adaptor- 설명 (4/8) UIAdaptor 구현 / 등록 UIAdaptorImpl (riaadaptor) convert(httpservletrequest request) 메소드구현 Public Object convert(httpservletrequest request) throws Exception { PlatformRequest platformrequest = null; try { platformrequest = new PlatformRequest(request, PlatformRequest.CHARSET_UTF8); platformrequest.receivedata(); catch (IOException ex) { ex.getstacktrace(); // throw new IOException("PlatformRequest error"); /* * TODO platformrequest 에서 VariableList 와 DatasetList 를뽑아결정된 Map * 형태 (example : ModelMap) 의객체에담아 Request 에다시담고 return true 로넘긴다. */ //CategoryVO dto = converte4in(platformrequest); //Class dto = Class.forName("egovframework.rte.fdl.sale.service.CategoryVO"); Object dto = converte4in(platformrequest, request); //request.setattribute("categoryvo", dto); return dto; - 84 -
6. UI Adaptor- 설명 (5/8) Controller 메소드구현 UdDTO 클래스는 CustomRiaArgumentResolver 에서만들어져 Controller 메소드의 parameter 형태로가져온 다. @Controller public class MiCategoryController {. @RequestMapping("/sale/miplatform.do") public ModelAndView selectcategorylist4mi(uddto midto, Model model) throws Exception { ModelAndView mav = new ModelAndView("miplatformView"); // 조회조건으로넣는다. Map<String, String> smp = new HashMap<String, String>(); try { List resultlist = categoryservice.selectcategorylist(smp); log.debug(" CategoryController START ======================"); mav.addobject("midto", resultlist); log.debug(" CategoryController End ======================"); catch (Exception ex) { mav.addobject("miresultcode", "-1"); mav.addobject("miresultmsg", ex.tostring()); log.info(ex.getstacktrace(), ex); return mav; - 85 -
6. UI Adaptor- 설명 (6/8) BeanNameViewResolver 설정 모델객체의이름이 miplatformview 이다. 이것은 Bean Name 을직접명시한것으로아래와같은설정 (BeanNameViewResolver) 이필요하다. <bean class="org.springframework.web.servlet.view.beannameviewresolver" p:order="0" /> <bean class="org.springframework.web.servlet.view.urlbasedviewresolver" p:order="1" p:viewclass="org.springframework.web.servlet.view.jstlview" p:prefix="/web-inf/jsp/" p:suffix=".jsp" /> <bean id="miplatformview" class="egovframework.rte.fdl.sale.web.miplatformmapview" /> - 86 -
6. UI Adaptor- 설명 (7/8) RiaView 구현 RiaView 구현 / 등록 miplatformview public class MiPlatformMapView extends AbstractView { @SuppressWarnings("unchecked") @Override protected void rendermergedoutputmodel(map model, HttpServletRequest request, HttpServletResponse response) throws Exception { PlatformData platformdata = new PlatformData(miVariableList, midatasetlist); if ((String) model.get("miresultcode")!= null) { this.setmiresultmessage((string) model.get("miresultcode"), (String) model.get("miresultmsg")); else { this.setmiresultmessage("0", "sucess~~"); // 데이터변환. try { new PlatformResponse(response, PlatformConstants.CHARSET_UTF8).sendData(platformData); catch (IOException ex) { if (log.iserrorenabled()) { log.error("exception occurred while writing xml to MiPlatform Stream.", ex); throw new Exception(); - 87 -
6. UI Adaptor- 설명 (8/8) 결과 - 88 -
6. UI Adaptor- 참고자료 The Spring Framework - Reference Documentation http://static.springframework.org/spring/docs/2.5.x/reference/ - 89 -
4. 업무처리레이어 1. 개요 2. Process Control 3. Exception Handling - 90 -
1. 개요 - 실행환경업무처리레이어 (1/3) 4. 업무처리레이어 업무처리레이어는업무프로그램의업무로직을담당하는 Layer 로서, 업무흐름제어, 에러처리등 의기능을제공함 전자정부개발프레임워크실행환경 서비스그룹 Presentation Layer 설명 업무프로그램과사용자간의 Interface 를담당하는 Layer 로서, 사용자화면구성, 사용자입력정보검증등의기능을제공함 Layer Presentation Layer Logic Business Layer Persistence Integration Layer Business Logic Layer 업무프로그램의업무로직을담당하는 Layer 로서, 업무흐름제어, 에러처리등의기능을제공함 Persistence Layer 데이터베이스에대한연결및영속성처리, 선언적인트랜잭션관리를제공하는 Layer 임 Foundation Layer ( 공통기반레이어 ) Integration Layer 타시스템과의연동기능을제공하는 Layer 임 환경 서비스그룹 Foundation Layer ( 공통기반레이어 ) 실행환경의각 Layer 에서공통적으로사용하는공통기능을제공함 - 91 -
1. 개요 - 실행환경업무처리레이어 (2/3) 4. 업무처리레이어 업무처리레이어는 Process Control, Exception Handling 등총 2 개의서비스를제공함 실행환경 화면처리레이어 업무처리레이어 데이터처리레이어 연계통합레이어 MVC Internationalization Process Control DataSource Data Access Naming Service Ajax Support Security Exception Handling ORM TBD Transaction Integration Service UI Adaptor Web Service 공통기반레이어 AOP Cache Compress/Decompress Encryption/Decryption Excel File Handling File Upload/Download FTP Server Security ID Generation IoC Container Logging Mail Marshalling/Unmarshalling Object Pooling Property Resource Scheduling String Util XML Manipulation 실행환경서비스그룹서비스 - 92 -
1. 개요 - 실행환경업무처리레이어 (3/3) 4. 업무처리레이어 업무처리레이어는 Spring Web Flow, Spring 등총 2 개의오픈소스 SW 를사용하고있음 서비스오픈소스 SW 버전 Process Control Web Flow 2.0 Exception Handling Spring 2.5-93 -
2. Process Control 개요 4. 업무처리레이어 서비스개요 Spring Web Flow(SWF) 는웹애플리케이션내페이지흐름 (flow) 의정의와수행에집중하는 Spring프레임워크웹스택의컴포넌트이다. Spring Web Flow는추상화의좀더높은레벨에존재하고 Struts, Spring MVC, Portlet MVC, 그리고 JSF와같은기본프레임워크내에서자족적인페이지흐름 (flow) 엔진 (page flow engine) 처럼통합된다. SWF는선언적이고높은이식성을가지며뛰어난관리능력을가지는형태로명시적으로애플리케이션의페이지흐름 (flow) 을획득하는기능을제공한다. - 94 -
2. Process Control - 설명 (1/9) 4. 업무처리레이어 Getting Started - Hello 프로젝트 화면시나리오 1 2-95 -
LAB 303-swf Demo Lab303-swf - 96 -
2. Process Control - 설명 (2/9) 4. 업무처리레이어 1 번 Hello 시나리오 Flow 정의 <?xml version="1.0" encoding="utf-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> </flow> <view-state id="hello"> <transition on="say" to="helloworld" /> </view-state> <view-state id="helloworld"> <transition on="return" to="return" /> </view-state> <end-state id="return" view="externalredirect:servletrelative:/start" /> - 97 -
2. Process Control - 설명 (3/9) 4. 업무처리레이어 2 번 Hello 시나리오 Flow 정의 <?xml version="1.0" encoding="utf-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> <on-start> <evaluate expression="helloservice.saymessage()" result="flowscope.message" /> </on-start> <view-state id="hello2" model="message"> <binder> <binding property="str" required="true" /> </binder> <transition on="proceed" to="actionhello" /> <transition on="return" to="return" /> </view-state> <action-state id="actionhello"> <evaluate expression="helloservice.addhello(message)" /> <transition on="yes" to="moredecision" /> <transition on="no" to="hello" /> </action-state> <decision-state id="moredecision"> <if test="helloservice.getdecision(message)" then="helloworld2" else="return" /> </decision-state> <view-state id="helloworld2"> <transition on="return" to="return" /> </view-state> <end-state id="return" view="externalredirect:servletrelative:/start" /> </flow> - 98 -
2. Process Control - 설명 (4/9) 4. 업무처리레이어 Flow Definition <?xml version="1.0" encoding="utf-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> </flow> <view-state id="hello"> <transition on="say" to="helloworld" /> </view-state> <view-state id="helloworld"> <transition on="return" to="return" /> </view-state> <end-state id="return" view="externalredirect:servletrelative:/start" /> view-state: Flow 중화면을보여주는 State 를정의하는구성요소 편의상 Flow 정의파일이있는디렉터리내에서 view-state id 와일치하는화면템플릿을맞추어보여주게된다. transition: State 내에서발생한이벤트를제어하는구성요소. 화면이동을일으킨다. end-state: Flow의결과를정의 - 99 -
2. Process Control - 설명 (5/9) 4. 업무처리레이어 decision state action-state 를대신해서편리하게 if/else 문법을사용해서이동하고자하는의사결정을해주는 decision-state 를사용한다. <decision-state id="moredecision"> <if test="helloservice.getdecision(message)" then="helloworld2" else="return" /> </decision-state> action-state 액션은대부분 POJO 의메소드를호출한다. action-state 와 decision-state 을호출했을때, 이들메소드가반환하는값은상태를전이하게해주는데사용할수있다. 전이가이벤트에의해서발생되기때문에, 우선메소드가반환하는값은반드시 Event 객체에매핑되야한다. <action-state id="actionhello"> <evaluate expression="helloservice.addhello(message)" /> <transition on="yes" to="moredecision" /> <transition on="no" to="hello" /> </action-state> - 100 -
2. Process Control - 설명 (6/9) 4. 업무처리레이어 환경설정 with Spring MVC - 101 -
2. Process Control - 설명 (7/9) 4. 업무처리레이어 webmvc-config.xml - 102 -
2. Process Control - 설명 (8/9) 4. 업무처리레이어 webflow-config.xml - 103 -
2. Process Control - 설명 (9/9) 4. 업무처리레이어 화면 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html> <head> <title>welcome to Spring Web Flow</title> </head> <body> <h1>welcome to Spring Web Flow</h1> <form:form id="start"> <input type="submit" name="_eventid_say" value="click to say hello!" /> </form:form> </body> </html> <view-state id="hello"> <transition on="say" to="helloworld" /> </view-state> <view-state id="helloworld"> <transition on="return" to="return" /> </view-state> transition 은화면에서발생한이벤트와매핑을할까? hello.jsp 소스를잠시보겠다. 코드에서보는봐와같이 form으로둘러싸인곳에해답은있다. <input type= submit name= _eventid_say. /> 에서 name 을보면 _eventid_say 로답을찾을수있다. _eventid 가답이다. say는 transition 의 on 과같음을확인할수있다. eventid 에정의된특정위치의문자열을가지고 transition 를분석한다. transition 에대한내용은 flow 정의에서자세히살펴보길바란다. eventid 가 say 를가지고 form 이전달되면 flow 정의에따라 transition 을찾고그에맞는 state 로넘어가게된다. 결과는별도의값을가지고보여주는화면이아닌단지아래와같은화면을보여주도록되어있다. - 104 -