728x90
반응형

Spring MVC 패턴 시작하기 / 프로젝트 생성 / 파일 구조

 

스프링 MVC 패턴으로 프로젝트를 생성하는 방법입니다.

 

 

New - Spring Legacy Project 를 클릭합니다.

 

 

Spring MVC Project를 선택하고 Next를 클릭합니다.

 

 

HomeController 파일이 들어갈 패키지의 이름을 정하고 finish를 클릭합니다.

 

이름1.이름2.이름3의 형태로 점을 두번 적어서 패키지 이름을 작성하시면 됩니다.

 

아래 사진은 위에 서술한 방법을 따라서 생성된 다른 프로젝트입니다.

 

스프링 MVC 프로젝트의 구조는 사진과 같습니다.

 

webapp안의 views 폴더 안에 화면에 관한 jsp 파일들이 들어갑니다.

 

 

스프링 MVC 프로젝트 요청 처리 순서

 

 

사진 출처 : http://terasolunaorg.github.io/guideline/1.0.1.RELEASE/en/Overview/SpringMVCOverview.html#id2

 

사진 속의 보라색 영역은 개발자가 구현하는 부분이다.

 

파란색은 스프링 프레임워크에서 제공한다.

 

초록색은 스프링 프레임워크에서 제공하거나 개발자가 구현한다.

 

클라이언트의 요청 이후에 위치한 Filter는 Encoding 을 하기도 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<filter>
        <filter-name>encodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>        
    </filter-mapping>
cs

 

Filter를 거친 요청은 DispatcherServlet으로 전송된다.

 

DispatcherServlet은 HandlerMapping을 통해서 요청에 해당하는 적절한 Controller를 찾게 된다.

 

HandlerMapping은 클라이언트의 요청 url을 어떤 controller가 처리할지를 결정한다. 그리고 그것을 DispatcherServlet에 전달한다.

 

DispatcherServlet은 실행할 Controller 정보를 HandlerAdapter에 전달한다.

 

HandlerAdapter는 해당 Controller를 호출하게 된다.

 

Controller는 Service를 호출해서 클라이언트의 요청을 처리한다.

 

Service에서는 DAO 를 통해서 DB 작업을 수행한다.

 

Controller는 작업을 처리한 후 그 결과를 Model 에 담고 View의 이름을 HandlerAdapter에게 전달하게 된다.

 

ViewResolver는 Commander의 처리 결과를 보여줄 View를 결정한다.

 

DispatcherServlet : 클라이언트의 요청을 전달 받고. Controller에게 클라이언트의 요청을 전달하고, Controller가 반환한 결과 값을 View에게 전달하여 알맞은 응답을 생성하도록 한다.

 

클라이언트의 요청은 스프링의 DispatcherServlet클래스로 보내지게 됩니다.

 

 



출처: http://fors.tistory.com/307 [fors]

728x90
반응형

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

Spring DI 란  (0) 2018.08.29
Spring 프레임워크 란  (0) 2018.08.29
web.xml 설정추가  (0) 2013.09.24
spring-security xml 설정  (0) 2013.09.24
Spring Security란?  (0) 2013.09.24
728x90
반응형

어떤 @Service 어노테이션을 쓰는 비지니스 로직이 있는 객체에서 

나의 경우에는 Map을 초기화 해놓고 싶었다. 


그러니까 소스로 예를 들면,


@Service

public class test {

   public Map<String, Object> map;  // 이거 초기화 세팅을 어디서...?


    public void foo() {

        map.get("key");

    }

}


저 map을 초기화 해놓고 foo() 메소드에서 쓰고싶은데

어떻게 하면 좋을까?




예전에는 bean 설정에서 init-method 설정을 통해 초기화해주는 메소드에서 구현하면 되었다.

아래와 같이 initData 메소드에서 세팅하면 된다.


<bean name="testService" class="com.test.TestService" init-method="initData" />




근데 어노테이션으로 간단히 하려면.

아래와 같이 사용하면 된다.


@Service

public class test {

   public Map<String, Object> map; 

    

    @Autowired private AaaObject aaaObj;


    @PostConstruct

    public void init() {

        map = new HashMap<String, Object>();

        map.put("aaa", aaaObj);

    }


    public void foo() {

        map.get("key");

    }

}



@PostConstruct 어노테이션을 설정해놓은 init 메소드는 WAS가 띄워질 때 실행된다. 



저 위에 예제에서 보면, AAAObject는 오토와이어링이 되어있는데,

과연 map에 들어있는 객체는 스프링에서 객체 생성을 해주었을까? 


PostConstruct의 메소드를 실행하기전에 오토와이어링으로 인해서 객체가 잘 생성 되었는가?

아니면 오토와이어링이 되기 전에 PostConstruct가 실행되었는가.. 



정답은 '잘 생성이 되어있다.'

autowired가 먼저 된 후 init 메소드가 실행된다~



출처: http://marobiana.tistory.com/105 [Take Action]

728x90
반응형

'Web Programming > java-jsp' 카테고리의 다른 글

java 예외 try catch finally  (0) 2018.08.29
JAVA Method 클래스  (0) 2018.08.29
[자바][Java] DecimalFormat 클래스  (0) 2018.08.28
JSONP를 이용하여 Cross Domain 해결  (0) 2015.12.29
도움이 되는 사이트들  (0) 2015.10.21
728x90
반응형

DecimalFormat이란... 10진수의 값을

원하는 포멧으로 변형해 주는 클래스를 말합니다.
DecimalFormat 클래스는 객체를 생성할 때 new 연산자를 사용합니다.
format 메소드를 사용해서 특정 패턴으로 값을 포맷할 수 있습니다.

 



패턴 형식은 '0'과 '#'을 사용 해서 지정합니다.
예를들면, '00.###', '0.#', '000.##'등으로 패턴을 지정할 수 있습니다.
'0' 은 표시한 자리수만큼의 값을 최소한으로 표시해야한다는 것이며,

#은 표시한 소수점자리수만큼 반올림하여 표시해야한다는 것입니다.

 



예를들어 12.3456789의 경우에 아래와 같습니다.
'00.###' = 12.346
'0.#' = 12.3 
'000.##' : 012.35

 

해당 패턴을 지정하여 DecimalFormat을 사용하는 방법은 아래와 같습니다.
DecimalFormat fmt=new DecimalFormat("00.###");
String decimal= fmt.format(12.3456789);
위와 같이 사용하면 decimal에는 12.346이 반환되죠.

 



DecimalFormat의 패턴을 변경하려 할 때는

void applyPattern(String pattern)를 사용합니다.
fmt.applyPattern("000.###")으로 변경하면

이후에는 변경된 Pattern이 포맷으로 적용됩니다.

 

다음 예제를 보면


 

 

실행결과

 


Decimal 패턴의 형식은 "0"과 "#" 외에도 여러 종류가 더 있습니다.
더 자세한 내용은 Java API DOC을 참고 하세요.

728x90
반응형
728x90
반응형


 IT Blog - https://moon9342.github.io/

728x90
반응형

'Web Programming > Angular - TypeScript' 카테고리의 다른 글

앵귤러JS (AngularJS) 란?  (0) 2018.08.29
Angular Component LifeCycle  (0) 2018.08.28
Angular Pipe  (0) 2018.08.28
Angular Directive  (0) 2018.08.28
Angular Material Table Event  (0) 2018.08.28
728x90
반응형

Component Lifecycle

이번 포스트에서는 Angular의 Lifecycle에 대해서 알아보겠습니다. 다른 Framework과 마찬가지로 Angular 역시 여러 단계의 lifecycle을 관리합니다. Component와 Directive가 이 lifecycle의 영향을 받게 되며 각 lifecycle마다 제공되는 hook method를 이용하여 특정 작업을 처리할 수 있습니다.

이런 hook method는 interface형태로 우리에게 제공됩니다. Component 혹은 Directive class가 이 interface를 구현하고 그 안의 특정 method를 overriding하는 식으로 hook method를 이용할 수 있습니다.

Component를 대상으로 객체가 생성되고 소멸되기까지 호출되는 hook method를 순서대로 나열하면 다음과 같습니다. Directive는 View를 가지고 있지 않기 때문에 ngAfter로 시작되는 hook method는 호출되지 않습니다.

  • constructor
  • ngOnChanges
  • ngOnInit
  • ngDoCheck
  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterViewInit
  • ngAfterViewChecked
  • ngOnDestroy

간단하게 Project를 하나 생성해서 각 lifecycle단계에서 해당 hook method가 호출되는지 확인하는 식으로 진행하시면 됩니다.


 constructor

Component 혹은 Directive가 생성될 때 호출됩니다. 사실 constructor는 Angular의 lifecycle의 단계에 포함될 내용은 아닙니다.

TypeScript에서는 일반적으로 constructor에서 초기화를 진행합니다. 하지만 Angular에서 사용하는 속성의 초기화는 ngOnInit에서 하는것이 좋습니다.


 ngOnChanges

@Input을 이용해 부모 Component가 자식 Component에게 데이터를 전달할 수 있습니다. ngOnChanges는 부모 Component에서 자식 Component로 데이터가 binding 될 때 혹은 변경되었을 때 호출됩니다. 따라서 @Input을 사용하지 않으면 호출되지 않습니다.

정확하게는 부모 Component로부터 자식 Component에게 전달하는 primitive 값이 변경되거나 혹은 참조하는 객체의 reference가 변경되어야 호출됩니다. 즉, 참조하는 객체의 property가 변경되는 경우에는 ngOnChanges가 호출되지 않는다는 것 기억하셔야 합니다.

@Input을 이용한 값의 binding은 생성자가 호출된 후에 일어납니다. 즉, 생성자에서 @Input을 이용해 binding한 값을 출력하면 undefined가 출력되게 됩니다. 간단한 이벤트 처리를 통해 @Input으로 전달되는 값을 변경해보면 값이 변경될 때마다 ngOnChanges hook method가 호출되는걸 확인할 수 있습니다.

ngOnChanges hook method의 인자로 SimpleChanges 객체를 하나 받을 수 있습니다. 해당 객체를 이용하면 변경되기 이전값과 이후값등을 알 수 있습니다.

import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {

  @Input() myInput: string;

  constructor() {
    console.log(`Constructor 호출!! => myInput : ${this.myInput}`);
  }

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log(`ngOnChanges 호출!! => myInput : ${this.myInput}`);
    console.log(simpleChanges.myInput.previousValue);
    console.log(simpleChanges.myInput.currentValue);
  }

  ngOnInit() {
  }

}

 ngOnInit

ngOnInit는 ngOnChanges가 호출된 이후에 모든 속성에 대한 초기화가 완료된 시점에 딱 한번만 호출됩니다. 즉, class가 가지고 있는 속성과 @Input을 통해 값을 내려받은 속성이 모두 초기화가 된 이후에 호출됩니다. 결국 Component의 속성 참조는 ngOnInit hook method이후에 참조하는 것이 좋습니다.

결국 생성자는 Service의 Injection같은 사항을 처리하고 속성에 대한 초기화는 ngOnInit에서 처리하시는게 좋다는 말입니다.

import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {

  @Input() myInput: string;
  myString = 'Hello';

  constructor() {
    console.log(`Constructor 호출!! => myInput : ${this.myInput}`);
    console.log(`Constructor 호출!! => myString : ${this.myString}`);
  }

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log(`ngOnChanges 호출!! => myInput : ${this.myInput}`);
    console.log(simpleChanges.myInput.previousValue);
    console.log(simpleChanges.myInput.currentValue);
  }

  ngOnInit() {
    console.log(`ngOnInit 호출!! => myInput : ${this.myInput}`);
    console.log(`ngOnInit 호출!! => myString : ${this.myString}`);
  }

}

 ngDoCheck

ngOnInit hook method가 호출된 이후에 호출됩니다. Component에서 발생하는 모든 상태변화에 반응하여 호출되어지는 hook method로 Angular의 Changes Detection이 상태변화를 감지하면 자동으로 호출되게 됩니다. 한가지 주의하셔야 할 점은 ngOnChanges와는 다르게 primitive값의 변경, reference 객체의 변경, reference객체의 속성변경에 대한 모든 변경에 대해 해당 hook mehtod가 호출된다는 점입니다. 심지에 이전값과 같은 값이 assign되었음에도 호출됩니다. 따라서 ngDoCheck을 많이 사용하게 되면 그만큼 성능이 저하될 수 있습니다.

import {Component, DoCheck, Input, 
        OnChanges, OnInit, SimpleChanges} from '@angular/core';

interface IBook {
  btitle: string;
  bauthor: string;
}

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck {

  @Input() myInput: IBook;
  myString = 'Hello';

  constructor() {
    console.log(`Constructor 호출!! => myInput : ${this.myInput}`);
    console.log(`Constructor 호출!! => myString : ${this.myString}`);
  }

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log(`ngOnChanges 호출!! => myInput : ${this.myInput}`);
    console.log(simpleChanges.myInput.previousValue);
    console.log(simpleChanges.myInput.currentValue);
  }

  ngOnInit() {
    console.log(`ngOnInit 호출!! => myInput : ${this.myInput}`);
    console.log(`ngOnInit 호출!! => myString : ${this.myString}`);
  }

  ngDoCheck() {
    console.log(`ngDoCheck 호출!! => myInput : ${this.myInput}`);
    console.log(`ngDoCheck 호출!! => myString : ${this.myString}`);
  }
}

 ngAfterContentInit, ngAfterContentChecked

최초의 ngDoCheck hook method가 호출된 후에 한번만 호출되며 앞서 배운 ngContent directive를 이용해 부모 Component의 template 일부를 자식 Component에서 projection한 후 호출됩니다. 여기서 Content의 의미는 ngContent directive처럼 외부에서 Component View안으로 내용을 가져온 것을 지칭합니다. 이 hook method 이후에 Change Detection이 실행된 후 바로 따라서 ngAfterContentChecked hook method가 호출됩니다.


 ngAfterViewInit, ngAfterViewChecked

Component에 속한 모든 View와 ViewChild가 시작되고 나서 호출됩니다. 쉽게 생각하면 HTML이 모두 화면에 출력된 후 호출된다고 생각 하시면 됩니다. ngAfterViewChecked는 Component의 View에 대한 Change Detection이 실행되고 난 후 호출됩니다.


 ngOnDestroy

Component가 소멸하기 직전에 호출됩니다. 일반적으로 사용된 자원에 대한 해제 코드가 들어옵니다.

import {
  AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, 
  Component, DoCheck, Input, OnChanges, OnDestroy, OnInit,
  SimpleChanges
} from '@angular/core';

interface IBook {
  btitle: string;
  bauthor: string;
}

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck, AfterContentInit,
  AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {

  @Input() myInput: IBook;
  myString = 'Hello';

  constructor() {
    console.log(`Constructor 호출!! => myInput : ${this.myInput}`);
    console.log(`Constructor 호출!! => myString : ${this.myString}`);
  }

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log(`ngOnChanges 호출!! => myInput : ${this.myInput}`);
    console.log(simpleChanges.myInput.previousValue);
    console.log(simpleChanges.myInput.currentValue);
  }

  ngOnInit() {
    console.log(`ngOnInit 호출!! => myInput : ${this.myInput}`);
    console.log(`ngOnInit 호출!! => myString : ${this.myString}`);
  }

  ngDoCheck() {
    console.log(`ngDoCheck 호출!! => myInput : ${this.myInput}`);
    console.log(`ngDoCheck 호출!! => myString : ${this.myString}`);
  }

  ngAfterContentInit() {
    console.log(`ngAfterContentInit 호출!!`);
  }

  ngAfterContentChecked() {
    console.log(`ngAfterContentChecked 호출!!`);
  }

  ngAfterViewInit() {
    console.log(`ngAfterViewInit 호출!!`);
  }

  ngAfterViewChecked() {
    console.log(`ngAfterViewChecked 호출!!`);
  }

  ngOnDestroy() {
    console.log(`ngOnDestroy 호출!!`);
  }
}

이번 포스트는 Angular가 제어하는 Component와 Directive의 lifecycle에 대해서 살펴봤습니다. 어떤 시점에 어떤 hook method가 호출되는지 이해하고 Change Detection이 어느 시점에 호출되는지를 이해하시면 조금 더 Angular를 이해하는데 도움이 될 듯 합니다.

728x90
반응형

'Web Programming > Angular - TypeScript' 카테고리의 다른 글

앵귤러JS (AngularJS) 란?  (0) 2018.08.29
Angular 강좌 및 참고사이트  (0) 2018.08.28
Angular Pipe  (0) 2018.08.28
Angular Directive  (0) 2018.08.28
Angular Material Table Event  (0) 2018.08.28

+ Recent posts