728x90
반응형

14) AOP with Annotation(애노테이션)

 

* 애노테이션(Annotation) & 오토와이어링(Autowiring)

 

 - 하나의 컨트롤러(Controller)와 하나의 페이지를 매핑하는 것은 작업도 번거롭고, 관리도 힘듬.

   그렇다면 하나의 함수에 하나의 URL을 어떻게 매핑할것인가?

  -> 애노테이션(Annotation)을 사용하자!

 

 - 그럼 애노테이션은 무엇인가??

  -> 주석(Comments) 단순한 주석?

  -> 컴파일러를 거친 후에도 코드에 남아있는 특수한 주석!!

 

 애노테이션은 특수한 주석으로 자체적으로 어떠한 기능을 수행하는 것은 아니지만, 애노테이션이 가리키는 지시어(정보)를 기반으로 컴파일러는 애노테이션이 적용된 클래스 또는 매서드, 프로퍼트 등에 적절한 기능을 부여한다.

 

  -> 애노테이션은 @(골뱅이) 로 주석을 시작하며, 클래스, 매서드, 변수 등에 적용됨.

 

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

<context:component-scan base-package=“controller”></context:component-scan>

<bean name=“noticeDao” class=“dao.NoticeDao”> // Autowired 어노테이션을 통해서 자동 매핑됨.

 

// CustomerController.java

package controllers;

 

@Controller

@RequestMapper(“/customer/*”)

public class CustomerController {

 

    private NoticeDao noticeDao;

 

    @Autowired

    public void setNoticeDao(NoticeDao noticeDao) {

        this.noticeDao = noticeDao;

    }

 

    @RequestMapping(“notice.oz”)

    public String notices(String pg, String f, String q, Model model) throws ClassNotFoundException {

        int page = 1;

        String field = “TITLE”;

        String query = “%%”

 

        if(pg == null && pg.equals(“”))            page = Integer.parseInt(pg);

        if(f == null && f.equals(“”))                 field = _field;

        if(q == null && q.equals(“”))               query = _query;

 

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

        mv.addObject(“listData”, list);

 

        return “notice.jsp“; // VIEW로 사용되는 페이지 문자열(String)

    }

 

    @RequestMapping(“noticeDetail.oz”) // 게시물 상세 내용 보기

    public String noticeDetail(String seq, Model model) throws ClassNotFoundException {

        Notice notice = noticeDao.getNotice(seq);

        model.addAttribute(“notice”, notice);

        return “noticeDetail.jsp“;
    }

 

    @RequestMapping(“noticeReg.oz”) // 게시물 등록

    public String noticeReg(Notice n /* String title, String content */) throws ClassNotFoundException {

       

        /* Notice n = new Notice();

        n.setTitle(title);

        n.setContent(content); */

        noticeDao.insert(n);

        return “redirect:notice.oz“;
    }

 

    @RequestMapping(“noticeEdit.oz”) // 게시물 수정

    public String noticeEdit(Notice n /* String title, String content */) throws ClassNotFoundException {

       

        /* Notice n = new Notice();

        n.setTitle(title);

        n.setContent(content); */

        noticeDao.update(n);       

        return “redirect:noticeDetail.oz?seq=“ + n.getSeq();
    }

}

 

 - 코드 설명 -

 

 * Context:component-scan : Controller 패키지에서 URL-메쏘드 매핑된 정보를 자동으로 검색(Auto-Scan)함. 단 Controller 애노테이션된 클래스에서 해당 메서드를 찾음. 위에서 /customer/notice.oz 서브 URL이 호출되면 notices 메서드가 수행됨.

(기존 XML 방식에서는 특정 페이지의 URL과 컨트롤러를 하나씩 배정했지만, context:component-scan을 통해서는 사용자로부터 URL이 입력된 경우 @Controller 애노테이션을 가지고 있는 클래스 내부의 RequestMapping 정보를 자동으로 스캔하여 처리 함수를 찾아 연결하여 줌.)

 

 * @RequestMapping – 표시된 URL에 해당 메서드를 매핑 (지정된 URL요청이 들어오면 해당 메서드를 실행함)


 * 그런데! XML을 사용하지 않으므로 URL-Controller 맵핑 정보(빈(Bean) 객체) 자체가 XML 파일에서 사라지게 되는데 이렇게 되면 빈(Bean) 객체를 생성하고, 프로퍼티(AOP관련 포함) 값을 세팅해줄 수가 없음.

 -> 이 문제는 @Autowired 애노테이션을 통해 해결! 

 -> component-scan을 사용하는 경우 빈(Bean)객체를 세팅하고 값을 할당해 줄 수 없지만, @Autowired를 사용하여 자동으로 객체와 변수를 연결 및 설정해 줌.

 * 메서드에서 반환하는 모델이 있다면 메서드 내에 파라메터 Model model을 선언만 해주면 됨. 해당 Model 객체가 생성되어 참조가 자동으로 됨.

[ 동일한 페이지를 다르게 처리 ]
@RequestMapping(value={“/customer/noticeReg.oz”}, method=RequestMethod.GET)
@RequestMapping(value={“/customer/noticeReg.oz”}, method=RequestMethod.POST)

 

[ 매핑된 컨트롤러의 함수가 처리하는 JSP페이지와는 다른 페이지로 결과를 넘길때 ]
return “redirect:notice.oz” // redirect 처리

 

 * Request로부터 넘어오는 인자는 1:1로 함수 매개변수로 대입 가능. 더 나아가 Request를 통해서 넘어오는 개별 어트리뷰트(Attribute) 인자의 이름(변수명)이 처리 함수의 매개 변수 레퍼런스 클래스의 인스턴스(속성 값)의 이름(변수 명)과 동일하다면 이를 자동으로 맵핑(대입)하여 줌.

 



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

728x90
반응형

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

Dependency Injection (의존성 주입)이란?  (0) 2018.08.29
Spring MVC 프로세스  (0) 2018.08.29
Spring AOP with XML  (0) 2018.08.29
Spring MVC jsp jstl  (0) 2018.08.29
Spring MVC Model2  (0) 2018.08.29
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

+ Recent posts