728x90
반응형
 

// NoticeController.java // 공지사항 리스트

package controllers.customer;

 

public class NoticeController implements Controller { // 스프링이 제공 (Controller)

 

    private NoticeDao noticeDao;

 

    public void setNoticeDao(NoticeDao noticeDao// setter

        this.noticeDao = noticeDao;

    }

 

    @Override

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

        throws Exception {

        String _page = request.getParameter("pg");

        String _field = request.getParameter("f");

        String _query = request.getParameter("q");

 

        int page = 1;

        String field = "TITLE";

        String query = "%%"

 

        if(_page == null && _page.equals(""))            page = Integer.parseInt(_page);

        if(_field == null && _field.equals(""))               field = _field;

        if(_query == null && _query.equals(""))          query = _query;

 

        List<Notice> list = noticeDao.getNotices(page, field, query); // 페이지번호검색항목검색어    

        ModelAndView mv = new ModelAndView("notice.jsp");

        mv.addObject("listData", list);

 

        return mv;

    }

}

 

 

실행 호출 notice.tst?pg={param.pg}&f={param.f}&q={param.q}

실행 결과 공지사항 리스트 정보 (listData)

 

- 코드 설명 -

 * NoticeDao 클래스 인스턴스를 별도로 생성. (기존 예제에서는 handleRequest 함수 이내에서 처리함)
 * Setter 함수도 생성.

 * 이전의 고전적인 JSP 방식에서는 DB처리를 위한 noticeDao 클래스를 만들어 그 인스턴스 객체를 사용하여 작업하였지만, 여전히, 객체를 생성, 호출하는 부분이 분리되지 않음. 매번 만들어야 함. 또한 함수 내에 있는 NoticeDao는 빈(Bean) 객체로 생성할 수도 없고, XML에서 접근 불가. XML을 활용하면 noticeDao의 생성과 초기화, 디펜던시 등을 분리하여 관리할 수 있음. DB등의 정보가 변경되어도 XML파일만 수정.

 

// NoticeDetailController.java // 공지사항 상세 내용

package controllers.customer;

 

public class NoticeDetailController implements Controller { // 스프링이 제공 (Controller)

 

    private NoticeDao noticeDao;

 

    public void setNoticeDao(NoticeDao noticeDao// setter

        this.noticeDao = noticeDao;

    }

 

    @Override

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

        throws Exception {

 

        String seq = request.getParameter("seq");

        Notice notice = noticeDao.getNotice(seq);

 

        ModelAndView mv = new ModelAndView("noticeDetail.jsp");

        mv.addObject("noticeData", notice);

 

        return mv;

    }

}

 

 

실행 호출 noticeDetail.tst?pg={param.pg}&f={param.f}&q={param.q}

실행 결과 noticeData 객체를 페이지에 전달하여 적절한 내용을 출력함.

 

 

// dispatcher-servlet.xml (객체를 생성해주고, 주입(Injection)함.)

<bean name="noticeDaoclass="dao.NoticeDao">

 

// 빈 객체 생성하고 값(레퍼런스)를 주입.

// setNoticeDao() 호출을 통한 값(레퍼런스배정 (value or ref )

<bean name="customer/notice.tstclass="controllers.customer.NoticeController">

    <property name="noticeDaoref="noticeDao"></property>

</bean>

 

<bean name="customer/noticeDetail.tstclass="controllers.customer.NoticeDetailController">

    <property name="noticeDaoref="noticeDao"></property>

</bean>

 

 * XML에서 noticeDao 객체를 각 빈(Bean) noticeController와 NoticeDetailController에 생성하고, 주입.

 

 

// noticeDetail.jsp // 공지사항 상세 정보 표시 페이지

<div id=notice-article-detail">

    <dl class="article-detail-row">

        <dt class="article-detail-title">제목</dt>

        <dd class="article-detail-data">

            ${notice.title}

        </dd>

    </dl>  

 <dl class="article-detail-row">

        <dt class="article-detail-title">작성일</dt>

        <dd class="article-detail-data">

            ${notice.regDate}

        </dd>

    </dl>  

    …

</div>

 

 

 

 

이러한 AOP 구현에 있어서 XML 방식의 문제점.
 * XML에 URL 수만큼 Bean객체를 생성하여 객체 값을 설정 해야하는 어려움이 있음.

 * 문제가 되는 이유는 Controller 클래스에는 URL에 매핑되는 오버라이드(Override)된 handleRequest 함수가 하나씩만 배정되어 있음.
 * URL에 반응하는 Controller가 함수 하나 하나마다 매번 캡슐(java 페이지) 생성해야 하므로, 코드 작성의 어려움이 있음. 즉 소스 페이지(JSP, XML, JAVA 등)가 여러 곳에 산재하게 됨. -> 웹 서비스 규모에 따른 너무 많은 개체 수 관리.



출처: http://ooz.co.kr/224?category=818548 [이러쿵저러쿵]

728x90
반응형

'Web Programming > spring' 카테고리의 다른 글

Spring MVC 프로세스  (0) 2018.08.29
Spring AOP with Annotation  (0) 2018.08.29
Spring MVC jsp jstl  (0) 2018.08.29
Spring MVC Model2  (0) 2018.08.29
Spring 빈 후처리기  (0) 2018.08.29
728x90
반응형

12. 스프링 프레임워크 기본 강좌 (12) - 스프링MVC (고전적인 JSP 코딩)

 

* 스프링 MVC 샘플 코드를 보기 이전에 고전적인 JSP 코딩 방식을 보도록 하겠습니다.

 

// NoticeController.java (1단계 DB 제어 클래스를 통한 DB데이터 가져오기)

package controllers.customer;

public class NoticeController implements Controller { // 스프링이 제공 (Controller)

 

    @Override

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

        throws Exception {

 

        String _page = request.getParameter("pg");

        String _field = request.getParameter("f");

        String _query = request.getParameter("q");

 

        int page = 0;

        String field = "TITLE";

        String query = "%%"

 

        if(_page == null && _page.equals(""))            page = Integer.parseInt(_page);

        if(_field == null && _field.equals(""))               field = _field;

        if(_query == null && _query.equals(""))          query = _query;

 

        NoticeDao dao = new NoticeDao();

        List<Notice> list = dao.getNotices(page, field, query); // 페이지번호검색항목검색어

       

        ModelAndView mv = new ModelAndView("notice.jsp");

        mv.addObject("listData", list);

 

        return mv;

    }

}

 

실행 호출 notice.tst?pg={param.pg}&f={param.f}&q={param.q}

 

 - 코드 설명 -

 * NoticeDao 클래스는 DB 커넥션 개체를 생성하고, DB와 연결하며, 쿼리를 통해 데이터를 가져오는 작업을 처리하여 주는 클래스.
 * AOP개념이라고 볼 수 있는데 NoticeDao 를 통해서 DB 개체 생성, 접속, 쿼리 실행, 종료 등에 대한 처리를 위임한 클래스 개체를 만들어 사용.

 * Controller Interface 구현
 * Controller의 handleRequest 함수 구현 (XML에 매핑된 함수임)

 

// notice.jsp

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

<table>

<tbody>

<c:forEach var="n" items="${listData}">

    <tr>

        <td class="seq">${n.seq}</td> // n.getSeq();

        <td class="title"><href="noticeDetail.tst?seq=${n.seq}">${n.title}</td>

        <td class="writer">${n.writer}</td>

        <td class="writer">${n.regDate}</td>

        <td class="writer">${n.hit}</td>

   </tr>

</c:forEach>

</tbody>

</table>

 

* 참고로 JSP페이지에 스크립트릿, 표현식, HTML 등의 코드가 섞이게 되면 가독성이 떨어지게 되는데, 보다 가독성을 높이기 위한 언어 및 태그를 표현언어(EL, Expression Language) / JSTL 코드를 사용.

 

* ${n.seq} 는 실제 n.getSeq() 함수를 호출하는 것이며, 이 setter 함수는 이미 정의되어 있어야 함.
* EL은 $와 {}를 사용하여 값을 표현

참고 : JSTL – JSP Standard Tag Library
 - jsp 페이지에 스크립트릿과 표현식, html 코드등이 뒤섞이면 가독성이 낮아지게 되는데, 이때 태그 형태인 el과 jstl이나 커스텀태그를 사용하면 스크립트릿을 사용하는 것보다 가독성을 높일 수 있음. 표현언어(el)같은 경우는 톰캣 라이브러리에 기본적으로 포함되어 배포되기 때문에 별도로 라이브러리를 추가해주지 않아도 되지만, jstl같은 경우는 함께 제공되지 않기 때문에 따로 라이브러리를 추가해야 함.



출처: http://ooz.co.kr/223?category=818548 [이러쿵저러쿵]

728x90
반응형

'Web Programming > spring' 카테고리의 다른 글

Spring AOP with Annotation  (0) 2018.08.29
Spring AOP with XML  (0) 2018.08.29
Spring MVC Model2  (0) 2018.08.29
Spring 빈 후처리기  (0) 2018.08.29
Spring 포인트컷 조인포인트  (0) 2018.08.29
728x90
반응형

스프링 MVC (Model2)

 

* Front Controller : URL매핑을 담당. (어떠한 컨트롤러가 어떤 URL을 쓸것인가에 대한 설정 파일 포함) - 설정 파일을 통해서 적절한 컨트롤러를 호출. (Front Part : Servlet (DispatcherServlet.class))

* Controller : 화면 단에서 보여줄 데이터들을 미리 만들어 놓는 것. 그 데이터는 모델(Model)이라 함.
* Model : 데이터


Model, Controller, Front Controller, View 를 잘 구조화하는 것이 MVC 모델을 제어하고 있는 라이브러리가 할 역할.

 

[스프링 MVC의 개념도] 

 

 

[예제 코드]

 

// web.xml

<servlet>

    <servlet-name>dispatcher</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

</servlet>

<servlet-mapping>

    <servlet-name>dispatcher</servlet-name>

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

</server-mapping>

 

// dispatcher-servlet.xml // 어떤 URL을 어떤 클래스에 매핑할 것인가?

<bean name="customer/notice.ozclass="controllers.customer.NoticeController"></bean>

 

// NoticeController.java

package controllers.customer;

public class NoticeController implements Controller { // 스프링이 제공 (Controller)

    @Override

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

         throws Exception  {

        ModelAndView mv = new ModelAndView("notice.jsp");

        mv.addObject("test", "hello");

        return mv;

    }

}

 

// notice.jsp

<div id="main"><h2>테스트 값 : ${test}</h2></div>

 

 

 

// 실행 및 결과

URL Call : localhost/customer/notice.oz   => 화면 출력 : hello

 

* 예지 코드는 게시판 MVC(스프링 MVC – 서블릿 DispatcherServlet)로 공지사항 리스트를 관리하고, 특정 번호의 공지사항을 열람하기 위한 공지사항 페이지를 구현. (스프링의 MVC의 개념을 설명하는데에 있어서 게시물 등록, 수정, 삭제 처리 함수는 크게 다른게 없으므로 생략.)

 

ModelAndView : Controller의 처리결과를 보여줄 View와 View에서 사용할 값을 전달하는 클래스.
ModelAndView의 mv 오브젝트는 web.xml에서 설정했었던 DispatcherServlet이 받아서 처리함.

${test} : 표현 언어 (JAVA 레벨(서버)의 변수를 Front(클라이언트)에 출력하기 위한 표현 언어)

 

 

[WEB.XML 이란?]

* Web Application 의 환경 파일(Deployment Description)

- XML 형식(XML Schema)의 파일로써, WEB-INF 폴더에 위치
- <web-app> 태그로 시작하고 종료하는 문서로써 web.xml 이 정의 된 Web Application의 동작과 관련된 다양한 환경 정보를 태그 기반으로 설정하는 파일.
- Servlet 2.3 까지 DTD 파일, 2.4 부터 XML Schema 파일 형태로 변경.

 

- WEB.XML 파일의 구성 내용
 1) ServletContext의 초기 파라미터
 2) Session의 유효시간 설정
 3) Servlet/JSP에 대한 정의
 4) Servlet/JSP 매핑
 5) Mime Type 매핑
 6) Welcome File list
 7) Error Pages 처리
 8) Listen/Filter 설정
 9) 보안



출처: http://ooz.co.kr/219?category=818548 [이러쿵저러쿵]

728x90
반응형

'Web Programming > spring' 카테고리의 다른 글

Spring AOP with XML  (0) 2018.08.29
Spring MVC jsp jstl  (0) 2018.08.29
Spring 빈 후처리기  (0) 2018.08.29
Spring 포인트컷 조인포인트  (0) 2018.08.29
Spring Advice  (0) 2018.08.29
728x90
반응형

* 빈 후처리기(Bean Post Processor)란?

 

 - 빈(Bean)의 설정을 후처리(postprocessing)함으로써 빈의 생명 주기와 빈 팩토리의 생명주기에 관여.
 - 빈의 초기화 되기 전, 초기화 된 후 2개의 기회를 제공.
 - 빈 프로퍼티의 유효성 검사 등에 사용.
 - 다른 초기화 메소드인 afterPropertiesSet()과 init-method가 호출되기 직전과 직후에 호출되어짐.

public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(Object bean, String name) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String name) trhows BeansException;

    ...

 

 

package com.sample;

public class Foo implements BeanPostProcessor {

    public void method1() {

        // 어떠한 작업..

    }

    Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {

        // 초기화 되기 전 처리

    }

    Object postProcessAfterInitialization(Object bean, String name) throws BeansException; {

        // 초기화 된 후 처리

    }

 

Resource resource = new FileSystemResource("beans.xml");

BeanFactory factory = new XmlBeanFactory(resource);

BeanPostProcess foo = new Foo();

Factory.addBeanPostProcessor(fool);

 

 // beans.xml 개체

<bean id="fooclass="com.sample.Foo/>

 

Bean Factory를 IoC Container 로 사용하는 경우에는 단순히 addBeanPostProcessor() 메서드를 이용하여 프로그램 방식으로만 빈 후처리기(Bean Post Processor)를 등록함.

 

* 빈 후처리 과정 (Process of Bean Postprocessing)

 1) 빈 객체(Bean Instance) 생성 (생성자(Constructor) 또는 팩토리 메서드(Factory Method) 사용).

 2) 빈 프로퍼티(Bean Property)에 값과 빈 레퍼런스 설정.

 3) Aware Interface에 정의된 Setter 메서드 호출

 4) 빈 인스턴스(Bean Instance)를 각 빈 후처리기(Bean Post Processor)의 postProcessBeforeInitialization() 에 전달.

 5) 초기화 Callback 메서드 호출

 6) 빈 인스턴스(Bean Instance)를 각 빈 후처리기(Bean Post Processor)의 postProcessAfterInitialization() 에 전달.

 7) 빈 사용 준비 완료

 8) 컨테이너 종료 후, 소멸(Destructor) Callback 메서드 호출

 

[BeanFactory 인터페이스]

 - 빈 객체를 관리하고 각 빈 객체 간의 의존 관계를 설정해주는 기능 제공.

 - 가장 단순한 컨테이너.

[XmlBeanFactory 클래스]

 - 외부 자원으로부터 설정 정보를 읽어 와 빈 객체를 생성하는 클래스

 

덧붙여!

스프링의 빈 객체는 기본적으로 싱글톤(Singleton)으로 생성되는데, 그 이유는 사용자의 요청이 있을 때마다 애플리케이션 로직까지 모두 포함하고 있는 오브젝트를 매번 생성하는 것은 비효율 적이기 때문. 하나의 빈 객체(Bean Object)에 동시에 여러 스레드가 접근할 수 있기 때문에 상태 값을 인스턴스 변수에 저장해 두고 사용할 수 없음. 따라서 싱글톤의 필드에는 의존 관계에 있는 빈에 대한 참조(Reference)나 읽기 전용(Read-Only) 값만을 저장해 두고, 실제 오브젝트의 변화 상태를 저장하느 인스턴스 변수는 두지 않음. 애플리케이션 로직을 포함하고 있는 오브젝트는 대부분 싱글톤 빈(Singleton Bean)으로 만들면 충분함.

 

하지만, 하나의 빈 설정으로 여러 개의 오브젝트를 만들어서 사용하는 경우도 발생하게 되는데, 이 때는 싱글톤이 아닌 빈을 생성해야 함. 싱글톤이 아닌 빈은 프로토타입 빈(ProtoType Bean)과 스코프 빈(Scope Bean)이 있다.

 



출처: http://ooz.co.kr/217?category=818548 [이러쿵저러쿵]

728x90
반응형

'Web Programming > spring' 카테고리의 다른 글

Spring MVC jsp jstl  (0) 2018.08.29
Spring MVC Model2  (0) 2018.08.29
Spring 포인트컷 조인포인트  (0) 2018.08.29
Spring Advice  (0) 2018.08.29
Spring 디자인 패턴  (0) 2018.08.29
728x90
반응형

스프링 AOP (Aspect Oriented Programming)

 

포인트 컷 & 조인포인트

 

 - 위빙 (Weaving) : 보조업무가 프록시(Proxy)를 통해서 주 업무에 주입되는 것. 즉, 타깃 객체에 애스펙트를 적용해서 새로운 프록시 객체를 생성하는 절차.
 - 조인포인트 (Joint Point) : 위빙하게 되는 함수. 그 지점.

 - 포인트 컷 (PointCuts) : 객체의 특정 함수만 조인포인트 역할을 하도록 하는 것. 

 

 

* 이전 포스팅에서의 스프링 AOP 는 특정 객체(클래스)를 대상으로 타깃(Target)을 설정하였는데, 그렇기 때문에 프록시 적용이 해당 객체 단위 전체에 적용이 됨. 즉 타깃에 속한 모든 조인포인트에 보조 업무(Proxy Class)가 적용됨. 하지만, 포인트 컷을 활용하면 특정 클래스의 특정 함수에만 보조 업무를 삽입할 수 있음.

 

 

* 예제 코드

 

<bean id="cal" class="aoptest.TestCalculator"></bean>

<bean id="logPrintAroundAdvice" class="aoptest.LogPrintAroundAdvice"/>

<bean id="logPrintBeforeAdvice" class="aoptest.LogPrintBeforeAdvice"/>

<bean id="logPrintAfterReturningAdvice" class="aoptest.LogPrintAfterReturningAdvice"/>

<bean id="logPrintAfterThrowingAdvice" class="aoptest.LogPrintAfterThrowingAdvice"/>

 

<bean id="namePointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">

<proporty name="mappedNames">

         <list>

              <value>add</value>

              <value>subtract</value>

          </list>

     </property>

</bean>

 

<bean id="nameAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">

      <property name="pointcut" ref="namePointcut"></property>

      <property name="advice" ref="logPrintAroundAdvice"></property>

</bean>

 

<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="cal"></property>

    <property name="interceptorNames">

        <list>

            <value>nameAdvisor</value>

            /* <value>logPrintAroundAdvice</value>

            <value>logPrintBeforAdvice</value>

            <value>logPrintAfterReturningAdvice</value>

            <value>logPrintAfterThrowingAdvice</value> */

        </list>

    </property>

</bean> 

 

 - 코드 설명 -

 

1)  특정 함수(add, subtract) 만 조인포인트 함수가 되도 록 포인트 컷 지정.
2) 특정 포인트 컷에 특정 어드바이스(핸들러) 지정.

 

어드바이저 = 포인트 컷 + 어드바이스


 

3) 특정 어드바이스(Advice) 대신 어드바이저(Advisor) 지정 가능.

 

TestCalculator : 주 업무(타깃) 클래스 (AOP처리가 필요한 클래스)
LogXXXAdvice : 어드바이스 클래스 (핸들러 클래스 – 주 업무 처리 이전, 이후 등 부가적인 업무를 처리할 클래스)
PointCut(mappedNames) : 주 클래스의 함수 중에 내가 어드바이스를 적용을 한정(포인트 컷 할)시킬 함수를 지정 (특정 함수에만  국한지어 적용)
Advisor(nameAdvisor) : 포인트컷과 어드바이스를 합친 어드바이저를 생성. 어드바이스 대신 어드바이저 사용가능.
Proxy : 타깃 클래스를 지정하고, 어드바이저(또는 어드바이스)를 적용할 것(interceptorNames)을 지정한 후, 대리 클래스 생성. ProxyFactoryBean을 통한 동적 프록시 생성.

참고로 어드바이저에는 여러 개의 어드바이스와 포인트 컷이 추가 될 수 있기 때문에 개별적으로 등록 시 어떤 어드바이스(부가기능)에 대해 어떤 포인트컷(메소드 선정)을 적용 할지 애매해진다. 그래서 어드바이스와 포인트 컷을 묶은 오브젝트를 어드바이저라고 부른다.

 

어드바이저 = 포인트컷(메소드 선정 알고리즘) + 어드바이스(부가 기능, 애스펙트의 한가지 형태)

 

  

<bean id="nameAdvisorclass="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

    <property name="pointcutref="namePointcut"></property>

    <proporty name="mappedNames">

         <list>

              <value>add</value>

              <value>substract</value>

          </list>

     </property>

     <property name="advice" ref="logPrintAroundAdvice"></property>

</bean>

 

 

// JAVA 정규식 표현을 활용한 포인트 컷 패턴 설정.  

<bean id="nameAdvisorclass="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

    <property name="pointcutref="namePointcut"></property>

    <proporty name="patterns">

         <list>

              <value>.*a.*</value>

              <value>.*b</value>

          </list>

     </property>

     <property name="advice" ref="logPrintAroundAdvice"></property>

</bean>

 

 

* mappedName : 적용시킬 함수를 지정.
* mappedNames : 적용시킬 함수들을 지정.

예제 클래스에는 2개의 함수(add, substract) 밖에 없지만, 함수가 상당히 많은 경우, 패턴을 사용하는 것이 더 효율적일 수 있다. 그룹핑을 통해 어떤 어드바이스(Advice)만 실행되게 할 것인지도 한정할 수도 있다.

[정규식 특수 문자 의미]

. : 어떠한 문자든 상관없다. (한개의 문자가 옴)
* : 임의의 문자가 0개 이상 올 수 있다. (한개 이상의 문자가 옴)

 

 

* 위빙, 조인포인트, 포인트컷을 다시 한 번 상기시키자면

위빙 : 크로스 컷팅 되어 있는 관심사(Concern)를 다시 결합하는 것.
조인포인트 : 위빙하는 함수들이 있는 곳 지점, 시점 (스프링에서는 메소드만을 조인 포인트로 사용함.)

포인트 컷 : 부가 기능 적용 대상 메서드 선정 방법. 내가 원하는 메서드만 골라서 조인포인트 역할을 하도록 함. (단, 포인트 컷을 통해 특정 타깃 함수와 어드바이스를 매 하나씩 연결해야 한다면 설정 파일의 용량도 커지고, 함수가 많아지게 되면 관리도 어려워질 수 있음.)

 

 * 스프링에서의  조인 포인트 특징!
  - 분리하고 도킹하는 것이 자유로움.
  - 조인포인트를 쓸 수 있는 것이 Method에 한정.

 



출처: http://ooz.co.kr/216?category=818548 [이러쿵저러쿵]

728x90
반응형

'Web Programming > spring' 카테고리의 다른 글

Spring MVC Model2  (0) 2018.08.29
Spring 빈 후처리기  (0) 2018.08.29
Spring Advice  (0) 2018.08.29
Spring 디자인 패턴  (0) 2018.08.29
Spring 동적 Proxy  (0) 2018.08.29

+ Recent posts