Spring 프레임워크의 이해 – day3 자바지기
첫째 날 둘째 날 셋째 날 개발 환경 세팅 Spring 기본 Spring MVC 사용자 관리 시스템 개발 (실습) Spring DI Spring AOP Spring JDBC & Transaction Spring Test
모델 1
모델 2 - MVC
Controller(또는 Action) 사용자 입력 데이터 추출 입력 데이터에 대한 유효성 체크(Java Script를 이용할 경우 JSP(View)에서도 가능) 입력 데이터를 비즈니스 Layer로 전달하기 위한 변환 작업 비즈니스 Layer와 Interface 비즈니스 Layer에서 발생한 에러 처리 비즈니스 Layer에서 반환된 데이터를 View에 전달
모델 1 B R O W S E 1. Request JSP 2. Response
모델 2 B R O W S E (Controller) Servlet (View) JSP 1. Request 2. Response 3. Request (View) JSP 4. Response
데모 및 실습 모델 2 기반의 초간단 프레임워크 svn://www.javajigi.net/javajigi id : anonymous pwd : 없음 model2 프로젝트 checkout pom.xml 오른쪽 클릭 maven build.. eclipse:clean eclipse:eclipse를 통한 프로젝트 생성
Spring MVC
2 3 1 4 5 6 HandlerMapping 요청 DispatcherServlet Controller ModelAndView 1 4 5 ViewResolver 6 View
web.xml 설정 <servlet> <servlet-name>action</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <url-pattern>*.do</url-pattern> </servlet-mapping> <url-pattern>*.html</url-pattern>
=> 서블릿 이름-servlet.xml Spring 설정 파일 => 서블릿 이름-servlet.xml <servlet> <servlet-name>action</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> WEB-INF/action-servlet.xml
Controller
Controller Interface public interface Controller { ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response) throws Exception; }
HelloWorldController 실습 HelloWorldController public class HelloWorldController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { return new ModelAndView("hello", "message", "Hello World!! Welcome to Page!!"); } action-servlet.xml <bean id="helloController“ class="net.javajigi.web.HelloWorldController" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <entry key="/hello.do" value-ref="helloController"/> </map> </property> </bean>
2 3 1 4 5 6 SimpleUrlHandlerMapping “hello” /hello.do DispatcherServlet HelloWorldController ModelAndView 1 4 “hello”, “message” 5 InternalResourceViewResolver 6 /WEB-INF/jsp/hello.jsp
UrlFilenameViewController = No Model 데이터 정적인 페이지
org.springframework.web.servlet.mvc.UrlFilenameViewController 실습 org.springframework.web.servlet.mvc.UrlFilenameViewController action-servlet.xml <bean id="staticViewController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" /> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <entry key="/**/*.html" value-ref="staticViewController"/> </map> </property> </bean>
MultiActionController DispatchAction of Struts = DispatchAction of Struts Action of Webwork
= 1 : 1 ListAction InsertAction UpdateAction ViewAction DeleteAction List.do B R O W S E ListAction Insert.do InsertAction Update.do UpdateAction View.do ViewAction Delete.do DeleteAction = 1 : 1 URL : Action
단점 URL이 추가될 때마다 Action(Controller)를 추가해야함. Action(Controller)가 추가될 때마다 설정 파일에 Action 정보 추가 하나의 URL이 추가될 때마다 추가되어야 하는 부분이 많아짐으로서 생산성 저하. Action(Controller)의 숫자가 많아질수록 유지보수의 어려움. 너무도 복잡한 설정 파일로 인해 유지보수의 어려움.
= N : 1 SampleAction URL : Action B R O W S E List.do Insert.do Update.do View.do Delete.do = N : 1 URL : Action
실습 - MultiActionController UserController public class UserController extends MultiActionController { public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws Exception { List<User> userList = userService.findUserList(); ModelAndView mav = new ModelAndView(); mav.addObject("users", userList); return mav; } public ModelAndView edit(HttpServletRequest request, HttpServletResponse response) User user = new User(); bind(request, user); userService.updateUser(user); return new ModelAndView("redirect:/user/list.do");
URL Mapping : InternalPathMethodNameResolver 설정 파일에 아무 것도 설정되어 있지 않을 경우 InternalPathMethodNameResolver가 Default URL에 포함되어 있는 Method 이름을 실행한다. http://localhost:8080/user/edit.do => UserController의 edit() 메써드 호출 일반적으로 가장 많이 사용한다.
URL Mapping : ParameterMethodNameResolver action-servlet.xml <property name="methodNameResolver"> <bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> <property name="paramName" value="method"/> </bean> </property> URL을 통하여 전달되는 인자 이름을 통하여 실행하는 메써드 결정 http://localhost:8080/user.do?method=edit => UserController의 edit() 메써드 호출
URL Mapping : PropertiesMethodNameResolver action-servlet.xml <bean id="propsResolver" class="org....mvc.multiaction.PropertiesMethodNameResolver"> <property name="mappings"> <value> /user/modify.do=edit /user/list.do=list /user/remove.do=delete </value> </property> </bean> 요청 URL과 실행 메써드를 Mapping한다. Properties 파일을 통하여 관리하는 것도 가능하다. http://localhost:8080/user/modify.do => UserController의 edit() 메써드 호출
기존 방식
SimpleFormController
데모 사용자, 게시물 관리 svn://www.javajigi.net/javajigi id : anonymous pwd : 없음 sfw07 프로젝트 checkout pom.xml 오른쪽 클릭 maven build.. eclipse:clean eclipse:eclipse를 통한 프로젝트 생성
Spring MVC의 Interceptor public interface HandlerInterceptor { boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) void afterCompletion( Exception ex) }
실습 - SignonInterceptor public class SignonInterceptor extends HandlerInterceptorAdapter { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User userSession = (User) WebUtils.getSessionAttribute(request, "user"); if (userSession == null) { String url = request.getServletPath(); String query = request.getQueryString(); ModelAndView modelAndView = new ModelAndView("redirect:/signon/login.html"); if (query != null) { modelAndView.addObject("signonForwardAction", url+"?"+query); } else { modelAndView.addObject("signonForwardAction", url); throw new ModelAndViewDefiningException(modelAndView); return true;
실습 - SignonInterceptor action-servlet.xml <bean id="signonInterceptor" class="net.javajigi.user.web.SignonInterceptor"/> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="signonInterceptor"/> </list> </property> <property name="urlMap"> <map> <entry key="/user/*.do" value-ref="userController"/> <entry key="/signon/logout.do" value-ref="signonController"/> </map> </bean>
HandlerMapping
BeanNameUrlHandlerMapping <bean name="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean name="/menu.do" class="net.javajigi.common.web.MenuController" /> <bean name="/changelocale.do" class="net.javajigi.common.web.SessionLocaleController" /> URL과 Controller 설정을 한 곳에서 할 수 있다. 다양한 Interceptor 설정을 하는 것이 힘들다.
SimpleUrlHandlerMapping <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <entry key="/**/*.html" value-ref="staticViewController"/> <entry key="/user/addForm.do" value-ref="userController"/> <entry key="/user/add.do" value-ref="userController"/> <entry key="/signon/login.do" value-ref="signonController"/> <entry key="/hello.do" value-ref="helloController"/> </map> </property> </bean> 다양한 Interceptor 설정을 하는 것이 가능하다. URL 설정과 Controller 설정이 분리되어 있다.
ControllerClassNameHandlerMapping <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" /> <bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator" /> HelloWorldController => helloworld.do HelloWorldController.hello => helloworld/hello.do
DefaultAnnotationHandlerMapping <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <context:component-scan base-package="net.javajigi"/> @Controller public class UserController { @RequestMapping("/user/list.do") public ModelMap listHandler() { List<User> userList = userService.findUserList(); return new ModelMap("users", userList); }
여러 개의 HandlerMapping 사용 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" p:order="1"> <property name="urlMap"> <map> <entry key="/**/*.html"> <ref local="staticViewController" /> </entry> </map> </property> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="2"/> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" p:order="3" />
ViewResolver
ViewResolver
InternalResourceViewResolver <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
VelocityViewResolver <bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath"> <value>/WEB-INF/vm/</value> </property> <property name="velocityProperties"> <props> <prop key="input.encoding">utf-8</prop> <prop key="output.encoding">utf-8</prop> <prop key="file.resource.loader.cache">false</prop> </props> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="requestContextAttribute" value="rc" /> <property name="cache" value="false" /> <property name="suffix" value=".vm" /> <property name="contentType"> <value>text/html; charset=utf-8</value>
XmlViewResolver views.xml <bean class="org.springframework.web.servlet.view.XmlViewResolver" p:location="/WEB-INF/views.xml" /> views.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...> <bean name="xmlView" class="net.javajigi.user.web.coc.XMLUserView" /> <bean name="excelView" class="net.javajigi.user.web.coc.ExcelUserView" /> </beans>
ResourceBundleViewResolver <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:basename="views" /> views.properties xmlView.class=net.javajigi.user.web.coc.XMLUserView excelView.class=net.javajigi.user.web.coc.ExcelUserView
여러 개의 ViewResolver 사용하기 <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:basename="views" p:order="1"/> <bean class="org.springframework.web.servlet.view.XmlViewResolver" p:location="/WEB-INF/views.xml" p:order="2"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" p:order="3"/>
redirect or forward return new ModelAndView("redirect:/user/list.do"); return new ModelAndView(“forward:/user/list.do");
View
실습 XMLUserView.java views.properties public class XMLUserView extends AbstractView { protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { List<User> users = (List<User>)model.get("users"); StringBuffer sb = new StringBuffer(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); .... response.setContentType("text/xml;charset=utf-8"); response.setHeader("Cache-Control", "no-cache"); response.getWriter().write(sb.toString()); } views.properties xmlView.class=net.javajigi.user.web.coc.XMLUserView
실습 ExcelUserView.java views.properties public class ExcelUserView extends AbstractJExcelView { protected void buildExcelDocument(Map model, WritableWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { List<User> users = (List<User>)model.get("users"); WritableSheet sheet = workbook.createSheet("User List", workbook.getNumberOfSheets()); sheet.addCell(new Label(0, 0, "User ID")); sheet.addCell(new Label(1, 0, "Name")); sheet.addCell(new Label(2, 0, "Email")); for (int i=0; i < users.size(); i++) { User user = (User) users.get(i); sheet.addCell(new Label(0, i+1, user.getUserId())); sheet.addCell(new Label(1, i+1, user.getName())); sheet.addCell(new Label(2, i+1, user.getEmail())); } views.properties excelView.class=net.javajigi.user.web.coc.ExcelUserView
Locale Resolver
AcceptHeaderLocaleResolver : Default <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
CookieLocaleResolver <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> <property name="cookieName" value="clientlanguage"/> <property name="cookieMaxAge" value="100000"> </bean>
SessionLocaleResolver <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
LocaleChangeInterceptor <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" /> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="siteLanguage"/> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="localeChangeInterceptor"/> <ref bean="signonInterceptor"/> </list> </property> .... </bean>
ThemeResolver
ResourceBundleThemeSource theme.properties gobal.css=/css/global.css user.css=/css/user.css list.jsp <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <html> <head> <link rel=stylesheet href="<spring:theme code="gobal.css"/>" type="text/css"> <link rel=stylesheet href="<spring:theme code="user.css"/>" type="text/css"> </head> <body> ... </body> </html>
ThemeResolver action-servlet.xml <bean id="themesource" class="org.springframework.ui.context.support.ResourceBundleThemeSource"/> <bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver" p:defaultThemeName="theme"/>
ExceptionResolver
dataAccessFailure => 논리적인 View 이름 SimpleMappingExceptionResolver <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop> <prop key="org.springframework.transaction.TransactionException">dataAccessFailure</prop> </props> </property> </bean> dataAccessFailure => 논리적인 View 이름
MultipartResolver
데모 게시판 파일 업로드 svn://www.javajigi.net/javajigi id : anonymous pwd : 없음 sfw07 프로젝트 checkout pom.xml 오른쪽 클릭 maven build.. eclipse:clean eclipse:eclipse를 통한 프로젝트 생성
첫째 날 둘째 날 셋째 날 개발 환경 세팅 Spring 기본 Spring MVC 사용자 관리 시스템 개발 (실습) Spring DI Spring AOP Spring JDBC & Transaction Spring Test
절차적 프로그래밍 OOP AOP
다음 문제의 정답은? 1 11 12 1121 122111 112213 ???????
사고의 전환
요구사항!! MessageRenderer, MessageProvider의 모든 메써드 시작과 종료시 “MethodName 시작”, “MethodName 종료”라는 Logging 메시지를 출력한다.
요구사항 변경!! MessageRenderer, MessageProvider의 모든 메써드 시작과 종료시 “MethodName Start”, “MethodName End”라는 Logging 메시지를 출력한다.
요구사항 변경!! 메써드로 전달되는 인자를 Logging 메시지로 출력한다. MessageRenderer, MessageProvider의 모든 메써드 시작과 종료시 “MethodName Start”, “MethodName End”라는 Logging 메시지를 출력한다. 메써드로 전달되는 인자를 Logging 메시지로 출력한다.
삽질의 연속
실습 요구사항!! DAO 클래스의 메써드 실행속도가 500ms이 넘을 경우 Warning 메시지를 출력한다.
실습 - ProfilingAspect @Aspect public class ProfilingAspect { private static Log log = LogFactory.getLog(LoggingAspect25.class); @Pointcut("execution(* net.javajigi..dao..*(..))") public void daoPointcut() { } @Around ("net.javajigi.aop.ProfilingAspect.daoPointcut()") public Object profiling(ProceedingJoinPoint pjp) throws Throwable { StopWatch stopWatch = new StopWatch(); stopWatch.start("Dao Profiling"); Object returnValue = pjp.proceed(); stopWatch.stop(); if( stopWatch.getLastTaskTimeMillis() > 500 ) { if (log.isWarnEnabled()) { String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); log.warn(targetClassName + "." + targetMethodName + " execute : "); log.warn(stopWatch.prettyPrint()); return returnValue;
실습 – applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ....> <aop:aspectj-autoproxy /> <bean id="profilingAspect" class="net.javajigi.aop.ProfilingAspect"/> </beans>
Join point 프로그램이 실행되는 중 식별할 수 있는 Point. 예를 들어 메써드의 실행, Exception Handling 등이 포함된다.
Advice Join Point에서 Aspect에 의하여 실행되는 Action을 의미 예를 들어 Profiling Aspect일 경우 Join Point에서 Profiling 하는 것을 의미한다.
Pointcut Join Point들을 선택하는 규칙을 정의하는 것. Weaving Rule을 정의하는 것
Target Object 애플리케이션의 핵심 비즈니스 로직을 구현하고 있는 Object Aspect에 의하여 Advice가 적용되는 Object
Aspect 하나의 Crosscutting Concern을 Aspect로 정의 가능 Advice와 Pointcut이 결합되어 Aspect가 된다. 예를 들어 Transaction, Security등이 하나의 Aspect가 된다.
Weaving Advcie, Pointcut, Target Object로 분리된 것을 하나로 결합하는 것을 의미 Weaving 작업을 지원하는 Tool(AspectJ, Spring AOP)을 Weaver라 지칭
Advice
Advice 의 종류 Before advice : Join Point 전에 실행되는 Advice. Around advice : Join Point 전, 후에 실행되는 Advice. After returning advice : Joint Point 완료된 후에 실행되는 Advice After throwing advice : Exception Throwing이 될 때 실행되는 Advice After (finally) advice : After returning advice, After throwing advice 모든 경우에 실행
Before Advice applicationContext.xml public void beforeLog(JoinPoint pjp) throws Throwable { String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); if (log.isDebugEnabled()) { log.debug(targetClassName + "." + targetMethodName + " 시작!"); Object[] args = pjp.getArgs(); for (int i = 0; i < args.length; i++) { log.debug("arg[" + i + "] : " + args[i]); } applicationContext.xml <beans> <bean id="loggingAdvice" class="net.javajigi.aop.LoggingAdvice25"/> <aop:config> <aop:aspect id="loggingAspect" ref="loggingAdvice"> <aop:pointcut id="logPointcut" expression="execution(* net.javajigi.di..*(..))"/> <aop:before pointcut-ref="logPointcut" method="beforeLog"/> </aop:aspect> </aop:config> </beans>
Around Advice applicationContext.xml public Object logOperations(ProceedingJoinPoint pjp) throws Throwable { String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); if (log.isDebugEnabled()) { log.debug(targetClassName + "." + targetMethodName + " 시작!"); Object[] args = pjp.getArgs(); for (int i = 0; i < args.length; i++) { log.debug("arg[" + i + "] : " + args[i]); } Object returnValue = pjp.proceed(); log.debug(targetClassName + "." + targetMethodName + " 종료!"); return returnValue; applicationContext.xml <beans> <bean id="loggingAdvice" class="net.javajigi.aop.LoggingAdvice25"/> <aop:config> <aop:aspect id="loggingAspect" ref="loggingAdvice"> <aop:pointcut id="logPointcut" expression="execution(* net.javajigi.di..*(..))"/> <aop:around pointcut-ref="logPointcut" method="logOperations"/> </aop:aspect> </aop:config> </beans>
After Returing Advice applicationContext.xml public void afterReturningLog(JoinPoint pjp, Object returnValue) throws Throwable { String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); if (log.isDebugEnabled()) { log.debug("Return Value : " + returnValue); log.debug(targetClassName + "." + targetMethodName + " 종료!"); } applicationContext.xml <beans> <bean id="loggingAdvice" class="net.javajigi.aop.LoggingAdvice25"/> <aop:config> <aop:aspect id="loggingAspect" ref="loggingAdvice"> <aop:pointcut id="logPointcut" expression="execution(* net.javajigi.di..*(..))"/> <aop:after-returning pointcut-ref="logPointcut" method="afterReturningLog" returning="returnValue"/> </aop:aspect> </aop:config> </beans>
After Throwing Advice applicationContext.xml public void afterThrowingLog(JoinPoint pjp, Throwable ex) throws Throwable{ String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); if (log.isDebugEnabled()) { log.debug(targetClassName + "." + targetMethodName + " Exception !"); log.debug("Exception Message : " + ex.getMessage()); } applicationContext.xml <beans> <bean id="loggingAdvice" class="net.javajigi.aop.LoggingAdvice25"/> <aop:config> <aop:aspect id="loggingAspect" ref="loggingAdvice"> <aop:pointcut id="logPointcut" expression="execution(* net.javajigi.di..*(..))"/> <aop:after-throwing pointcut-ref="logPointcut" method="afterThrowingLog" throwing="ex"/> </aop:aspect> </aop:config> </beans>
After Advice applicationContext.xml public void after(JoinPoint pjp) throws Throwable{ String targetClassName = pjp.getTarget().getClass().getName(); String targetMethodName = pjp.getSignature().getName(); if (log.isDebugEnabled()) { log.debug(targetClassName + "." + targetMethodName + " 종료!"); } applicationContext.xml <beans> <bean id="loggingAdvice" class="net.javajigi.aop.LoggingAdvice25"/> <aop:config> <aop:aspect id="loggingAspect" ref="loggingAdvice"> <aop:pointcut id="logPointcut" expression="execution(* net.javajigi.di..*(..))"/> <aop:after pointcut-ref="logPointcut" method="after"/> </aop:aspect> </aop:config> </beans>
Pointcut
Pointcut의 종류 – Spring 1.x StaticMethodMatcherPointcut DynamicMethodMatcherPointcut Perl5RegexpMethodPointcut JdkRegexpMethodPointcut NameMatchMethodPointcut ComposablePointcut ControlFlowPointcut
Pointcut의 종류 – Spring 2.x execution within this target args
Pointcut의 종류 – Spring 2.x @target @args @within @annotation bean(id or bean name) &&, ||, !
Pointcut의 예제 – Spring 2.x execution(* com.xyz.service.AccountService.*(..)) within(com.xyz.service.*) this(com.xyz.service.AccountService) @target(org.springframework.transaction.annotation.Transactional) @within(org.springframework.transaction.annotation.Transactional) @args(com.xyz.security.Classified) bean(*Service)
데모 – AOP를 이용한 권한 관리 @Permission(value = PermissionType.ADMINISTRATOR) public int removeUser(String userId) { int result = userDao.delete(userId); if (logger.isDebugEnabled()) { logger.debug("Removed " + userId + " in User System!!"); } return result; <aop:config> <aop:pointcut id="securityOperation" expression="execution(* net.javajigi..service..*(..)) and @annotation(permission)" /> <aop:aspect ref="securityAdvice"> <aop:before pointcut-ref="securityOperation" method="checkPermission" /> </aop:aspect> </aop:config> <bean id="securityAdvice" class="net.javajigi.security.PermissionAdvice" />
데모 – AOP를 이용한 권한 관리 public class PermissionAdvice { private static Log log = LogFactory.getLog(PermissionAdvice.class); public void checkPermission(Permission permission) throws PermissionException { PermissionType type = permission.value(); if (log.isDebugEnabled()) { log.debug("Permission Value : " + type); } if (type == PermissionType.ADMINISTRATOR ) { User user = UserContext.getUser(); if (!user.isAdmin()) { throw new PermissionException(user.getUserId());
Thank you.