// Spring MVC 3.2.x + iBatis // log4j추가 //Oracle 11g


denodo1-spring-module.zip


AOP (Aspect Oriented Programming)

전통적인 객체지향 기술의 설계 방법으로는 독립적인 모듈화가 불가능한 트랜잭션 경계설정과

같은 부가기능을 어떻게 모듈화 할 것인가를 연구해온 사람들은, 이 부가기능 모듈화 작업은 기존의 객체지향 설계 패러다임과는 구분되는 새로운 특성이 있다고 생각했다.


그래서 이런 부가기능 모듈을 객체지향 기술에서 주로 사용하는 오브젝트와는 다르게 특별한 이름으로 부르기 시작했다.


그것이 바로 애스펙트 (aspect) 이다.


애스펙트란 그 자체로 애플리케이션의 핵심기능을 담고 있지는 않지만, 애플리케이션을 구성하는 중요한 한 가지 요소이고, 핵심기능에 부가되어 의미를 갖는 특별한 모듈을 가리킨다.


2차원적인 평면 구조에서는 어떤 설계 기법을 동원해도 해결 할 수 없었던 것을, 3차원의 다면체 구조로 가져가면서 각각 성격이 다른 부가기능은 다른 면에 존재하도록 만들었다.


이렇게 독립된 측면에 존재하는 애스펙트로 분리한 덕에 핵심기능은 순수하게 그 기능을 담은 코드로만 존재하고 독립적으로 살펴볼 수 있도록 구분된 면에 존재하게 된 것이다.


이렇게 애플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스펙트라는 독특한 모듈로 만들어서 설계하고 개발하는 방법을 애스펙트 지향 프로그래밍(Aspect Oriented Programming) 또는 약자로 AOP 라고 부른다.

- 프록시 패턴

부가기능을 통해 핵심기능을 이용하게 되는것.

부가기능 코드에서는 핵심기능으로 요청을 위임해주는 과정에서 자신이 가진 부가적인 기능을 적용

해줄 수 있다. 비즈니스 로직 코드에 트랜잭션 기능을 부여해주는 것이 바로 대표적인 경우이다.


이렇게 마치 자신이 클라이언트가 사용하려고 하는 실제 대상인 것처럼 위장해서 클라이언트의 요청을 받아주는 것을 대리자, 대리인과 같은 역할을 한다고 해서 프록시(Proxy) 라고 부른다.


그리고 프록시를 통해 최종적으로 요청을 위임받아 처리하는 실제 오브젝트를 타깃(target) 또는

실체(real subject)라고 부른다.


프록시는 사용 목적에 따라 두 가지로 구분 할 수 있다.

첫째는 클라이언트가 타깃에 접근하는 방법을 제어하기 위해서다.

두번째는 타깃에 부가적인 기능을 부여해주기 위해서다.



- 데코레이터 패턴

데코레이터 패턴은 타깃에 부가적인 기능을 런타임 시 다이내믹하게 부여해주기 위해 프록시를

사용하는 패턴을 말한다.


다이내믹하게 기능을 부가한다는 의미는 컴파일 시점, 즉 코드상에서는 어떤 방법과 순서로 프록시와 타깃이 연결되어 사용되는지 정해져 있지 않다는 뜻이다.


이 패턴의 이름이 데코레이터라고 불리는 이유는 마치 제품이나 케잌 등을 여러 겹으로 포장하고 그 위에 장식을 붙이는 것처럼 실제 내용물은 동일하지만 부가적인 효과를 부여해줄 수 있기 때문이다.


따라서 데코레이터 패턴에서는 프록시가 꼭 한 개로 제한되지 않는다.

프록시가 직접 타깃을 사용하도록 고정시킬 필요도 없다. 그저 프록시가 여러개라면 순서를 정해서 단계적으로 위임하는 구조로 만들면 된다.


예를 들어, 소스코드를 출력하는 기능을 가진 핵심기능이 있다고 생각해보자.


이 클래스에 데코레이터 개념을 부여해서 타깃과 같은 인터페이스를 구현하는 프록시를 만들 수 있다. 예를 들어 소스코드에 라인넘버를 붙여준다거나, 문법에 따라 색을 변경해주거나, 특정 폭으로 소스를 잘라주거나, 페이지를 표시해주는 등의 부가적인 기능을 각각 프록시로 만들어주고 런타임 시에 이를 적절한 순서로 조합해서 사용하면 된다.



'Server Enterprise > Doc' 카테고리의 다른 글

[HashMap] 다중 리스트 데이터 담기  (0) 2014.02.18
[AOP] 애스펙트 지향 프로그래밍  (0) 2014.01.24
[Templet & Callback] 패턴  (0) 2014.01.24
[JSPF] Jsp Include 방식의 차이와 JSPF 설명  (0) 2013.10.30
URI Encoding  (0) 2013.02.17

- 템플릿

템플릿(template)은 어떤 목적을 위해 미리 만들어둔 모양이 있는 틀을 가리킨다.

프로그래밍에서는 고정된 틀 안에 바꿀 수 있는 부분을 넣어서 사용하는 경우에 템플릿이라고 부른다.


JSP는 HTML이라는 고정된 부분에 EL과 스크립릿이라는 변하는 부분을 넣은 일종의 템플릿 파일이다. 


템플릿 메소드 패턴은 고정된 틀의 로직을 가진 템플릿 메소드슈퍼클래스에 두고,

바뀌는 부분서브클래스의 메소드에 두는 구조로 이뤄진다.



- 콜백

콜백(callback)은 실행되는 것을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝트를 말한다.

파라미터로 전달되지만 값을 참조하기 위한 것이 아니라 특정 로직을 담은 메소드를 실행 시키기

위해 사용한다.


자바에선 메소드 자체를 파라미터로 전달할 방법은 없기 때문에 메소드가 담긴 오브젝트를 전달해야 한다. 그래서 펑셔널 오브젝트(functional object)라고도 한다.

http://beans9.tistory.com/103


http://antop.tistory.com/149

http://springmvc.egloos.com/429779

우선 아래 코드 부터 이해를 해야 한다

<jsp:include page="test.jsp" flush="true">

<%@ include file="파일의위치(url)" %>


선자는 compile이 끝난 결과물을 include 시키는 것이고,

후자는 page 전체가 compile 되기 이전에 소스코드를 먼저 include 후 compile 되는 것을 말한다.


이런경우 사용되어지는 대표적인 예가 공통변수를 사용하여 모든 페이지에 체크를 해야 하는 경우,


해당공통 변수를 include한 후 사용하면 된다.


JSPF란 그냥 후자처럼 사용하는 JSP를 JSPF 확장자로 선언한 뒤 web.xml에 선언하여 모든 JSP 페이지 내에 

자동으로 Include 되게 해주는 하나의 방법뿐이다.


예를들면


webConstraint.jspf >> 내용


<%page pageEncoding="UTF-8%>

<%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core"%>

...

...



들을 web.xml

<jsp-config>

<jsp-property-group>

<url-pattern>*.jsp</url-pattern>

<include-prelude>/web/jsp/common/webConstraint.jspf</include-prelude>

</jsp-property-group>

</jsp-config>


해서 사용 하면 된다

UserDaoTest.java (테스트용 클라이언트 Class)

package springbook.user;


@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = "/applicationContext.xml")

public class UserDaoTest {


/*

* ApplicationContext 객체를 사용하여 getBean을 이용하여 UserDao에 DI를 주입 할수도 있지만

* Autowired 를 통하여 바로 UserDao에 DI를 주입하는 방법을 통해 

* ApplicationContext 객체를 사용하지 않는 방법을 택했다.

* @Autowired 

* private ApplicationContext context;

*/


@Autowired

private UserDao dao;


private User user1;

private User user2;

private User user3;


@Before

public void setUp() {


/*

* Configuration File인 daoFactory.class 에서 userDao 라는 빈을 가지고 오고 그

* userDao 라는 빈은 UserDao Object를 반환한다.

*/

// this.dao = context.getBean("userDao", UserDao.class);


user1 = new User("SexyGuy", "김성민", "springman1");

user2 = new User("delay", "류민기", "springman2");

user3 = new User("postpone", "송준화", "springman3");


}


public static void main(String[] args) {

JUnitCore.main("springbook.user.UserDaoTest");

}


@Test

public void addAndGet() throws ClassNotFoundException, SQLException {


dao.deleteAll();

assertThat(dao.getCount(), is(0));


dao.deleteAll();

assertThat(dao.getCount(), is(0));


dao.add(user1);

dao.add(user2);

dao.add(user3);

assertThat(dao.getCount(), is(3));


User userget1 = dao.get(user1.getId());

assertThat(userget1.getName(), is(user1.getName()));

assertThat(userget1.getPassword(), is(user1.getPassword()));


User userget2 = dao.get(user2.getId());

assertThat(userget2.getName(), is(user2.getName()));

assertThat(userget2.getPassword(), is(user2.getPassword()));


User userget3 = dao.get(user3.getId());

assertThat(userget3.getName(), is(user3.getName()));

assertThat(userget3.getPassword(), is(user3.getPassword()));

}


@Test(expected = EmptyResultDataAccessException.class)

public void getUserFaiure() throws SQLException, ClassNotFoundException {


dao.deleteAll();

assertThat(dao.getCount(), is(0));


dao.get("unknown_id");

}

}


applicationContext.xml (@Configuration과 @Bean 환경설정 xml)

<beans>

<bean id="userDao" class="springbook.user.dao.UserDao">

<property name="dataSource" ref="dataSource" />

</bean>


<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">

<property name="driverClass" value="oracle.jdbc.OracleDriver" />

<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" />

<property name="username" value="scott" />

<property name="password" value="tiger" />

</bean>

</beans>


UserDao.java (의존성 주입을 당할 자바 빈 Class)
public class UserDao {
private DataSource dataSource;
private JdbcContext jdbcContext;
public void setDataSource(DataSource dataSource) {
this.jdbcContext = new JdbcContext();
this.jdbcContext.setDataSource(dataSource);
this.dataSource = dataSource;
}
public void deleteAll() throws SQLException  {
this.jdbcContext.executeSql("delete from users");
}

...

}


JdbcContext.java (템플릿과 콜백 패턴을 써서 만든 Class)

public class JdbcContext {

private DataSource dataSource;

public void setDataSource(DataSource dataSource) {

this.dataSource = dataSource;

}


public void workWithStatementStrategy (StatementStrategy stmt) throws SQLException {

Connection c = null;

PreparedStatement ps = null;


try {

c = dataSource.getConnection();


ps = stmt.makePreparedStatement(c);


ps.executeUpdate();

} catch (SQLException e) {

throw e;

} finally {

if (ps != null) { try { ps.close(); } catch (SQLException e) {} }

if (c != null) { try { c.close(); } catch (SQLException e) {} }

}

}

public void executeSql(final String query) throws SQLException {

workWithStatementStrategy( new StatementStrategy() {

@Override

public PreparedStatement makePreparedStatement(Connection c) throws SQLException {

return c.prepareStatement(query);

}

}); 

}

}


StatementStrategy.java (전략 패턴을 써야 함으로 인한 Interface)

public interface StatementStrategy {

PreparedStatement makePreparedStatement(Connection c) throws SQLException;

}

Class.forName("oracle.jdbc.OracleDriver");

Connection c = DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");



요거임.


loginAction.xml 

<struts>

<package name="login" extends="struts-default">

<action name="joinForm">

<result name="success">/jh/jsp/login/joinForm.jsp</result>

</action>

<action name="join" class="jh.login.action.UserJoinAction">

<result name="success" type="redirect">/list.do</result>

</action>


<action name="login" class="jh.login.action.UserLoginAction" method="login">

<result name="success" type="redirect">/list.do</result>

<result name="input">/jh/jsp/error/error.jsp</result>

</action>

<action name="loginForm">

<result name="success" type="dispatcher">/jh/jsp/login/loginForm.jsp</result>

</action>

<action name="logout" class="jh.login.action.UserLoginAction" method="logout">

<result name="success" type="redirect">/loginForm.do</result>

</action>

 

</package>

</struts>



UserLoginAction.java

public class UserLoginAction extends ActionSupport implements SessionAware {


private LoginVO vo = new LoginVO(); 

private LoginBO bo = new LoginBO();

private String userid;

private String passwd;

private String result;

SessionMap<String,Object> session;

String errMsg;

public String login() throws Exception{

vo.setUserid(userid);

vo.setPasswd(passwd);

/* [ Board 2013 ] 2013.07.12 이재희 : id,pw db에서 찾아 그 결과 값을 담는다. */

result = bo.login(vo);

if(result!=null){ /* [ Board 2013 ] 2013.07.12 이재희 : id,pw 존재하고 일치한다면 */

session.put("userid", userid); // 세션에 userid 저장

return SUCCESS;

}else{

/* [ Board 2013 ] 2013.07.12 이재희 : 인증이 잘못되어 있을 경우 result값을 다르게 주어서 다른 페이지(view)로 이동시킨다. */

            addFieldError("err.msg", "잘못된 로그인입니다"); // struts 태그 error 태그의 메시지값을 담는다.

            return INPUT;

}

}

public String logout() throws Exception{

session.remove("userid");

return SUCCESS;

}



/**

* @Method Name  : setSession

* @작성일     : 2013. 7. 10. 

* @작성자     : 이재희

* @param    :

* @Method 설명 :

*/

public void setSession(Map<String, Object> session) {

this.session = (SessionMap<String,Object>) session;

}



/**

* @return the userid

*/

public String getUserid() {

return userid;

}



/**

* @param userid the userid to set

*/

public void setUserid(String userid) {

this.userid = userid;

}



/**

* @return the passwd

*/

public String getPasswd() {

return passwd;

}



/**

* @param passwd the passwd to set

*/

public void setPasswd(String passwd) {

this.passwd = passwd;

}


}



loginForm.jsp

<form name="UserLoginForm" method="post" action="/login.do">

<table width="100%" border="0" cellspacing="0" cellpadding="1">

<tr>

<td colspan="2" id="td0">아이디 비밀번호</td>

</tr>

<tr>

<td id="td1"><input type="text" name="userid" id="tx1"

maxlength="12" /></td>

</tr>

<tr>

<td id="td1"><input type="password" name="passwd" id="tx1"

maxlength="16" /></td>

</tr>

<tr>

<td id="td11"><a id="bt_login" class="a_default" href="#"

onclick="FormSubmit( UserLoginForm );">Login</a> <a id="bt_login"

class="a_default" href="/joinForm.do">Join</a></td>

</tr>

</table>

</form>



loginok.jsp

<s:if test="#session.userid != null">

<%=session.getAttribute("userid")%> 님 안녕하세요.

<a href="/logout.do">로그아웃</a>

</s:if>

<s:else>

<script type='text/javascript'>

<!--

alert("로그인 바랍니다.");

setTimeout("location.href=' " + window.location.href + "/loginForm.do'",500);

//-->

</script>

</s:else>

+ Recent posts