1. 개요 (from 전자정부표준프레임워크)

 

Spring MVC Framework의 유일한 Front Controller인 DispatcherServlet은 spring MVC의 핵심요소이다.

DispatcherServlet은 Controller로 향하는 모든 웹요청의 진입점이며, 웹요청을 처리하며 결과 데이터를 Client에게 응답한다.

 

web.xml에 DispatcherServlet 설정하기

Spring MVC Framework을 사용하기 위해서는 web.xml에 DispatcherServlet을 설정하고, DispatcherServlet이 WebApplicationContext를 생성할수 있도록 빈(Bean) 정보가 있는 파일들도 설정해주어야 한다. 

 

1-1 MVC1, MVC2 패턴의 종말

DispatcherServlet 사용으로 기존 MVC1과 MVC2패턴은 쓰이지 않는다.

 

2. 기본설정

web.xml에 아래와 같이 DispatcherServlet이 자동으로 설정된다.

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

클라이언트가 해당 어플리케이션에 접근하면 접근한 URL 요청을 DispatcherServlet 이 가로챈다.

이렇게 요청을 가로챌 수 있는 이유는 web.xml 에 등록된 DispatcherServlet  <url-pattern>이 ‘/’ 와 같이 해당 어플을 통과하는 모든 URL로 등록했기 때문이다.

특정 URL 만 적용하고 싶다면 <url-pattern> 의 내용을 바꿔주어 범위를 변경시켜주면 된다.

 

3. HandlerMapping

  • Dispatcher가 받은 요청은 HandlerMapping으로 넘어간다. 그리고 이 요청을 처리할 수 있는 Controller를 찾게 된다.
  • Controller부터는 개발된 애플리케이션 영역이다. DB 연동 등 로직 처리가 이루어지고 view로 넘어간 후에 최종적으로 DispatcherServlet를 거쳐 클라이언트에 리턴된다.

 

4. Spring MVC 핵심 구성 요소 (1)

① DispatcherSevlet 은 모든 연결을 담당하며, 웹 브라우저에서 요청이 들어오면 

② 그 요청을 처리하기 위해 HandlerMapping 객체에게 컨트롤러 검색을 요청한다.

    HandlerMapping은 클라이언트의 요청 경로를 이용해서 이를 처리할 컨트롤러 객체를 찾아서 DispatcherServlet 에 리턴한다.  

ex) root-context.xml 속

	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
 		<property name="url" value="jdbc:mysql://172.16.0.150:3306/btctrade?characterEncoding=UTF-8"></property> 
		<property name="username" value="btckorea"></property> 
		<property name="password" value="road0ds!32"></property> 
		
	</bean>

 

③  DispatcherServlet 은 @Controller 어노테이션을 이용해서 구현한 컨트롤러, 스프링 2.5까지 사용됐던 Controller 인터페이스를 구현한 컨트롤러, 특수 목적으로 사용되는 HttpRequestHandler 인터페이스를 구현한 클래스를 동일한 방식으로 실행하고 처리하기 위해 HandlerAdapter 객체에게 요청 처리를 위임한다.

④ HandlerAdapter 객체는 컨트롤러의 알맞은 메소드를 호출해서 요청을 처리하고,

⑤ 반환 받은 결과를 

⑥ ModelAndView 객체에 담아서 DispatcherServlet 에 리턴한다.

⑦ ModelAndView 객체를 반환 받은 DispatcherServlet 은 ViewResolver 객체를 이용해서 결과를 보여줄 뷰를 검색한다.

    ViewResolver 객체는 ModelAndView 객체에 담긴 뷰 이름을 이용해서 View 객체를 찾거나 생성해서 리턴한다.

    ViewResolver 는 매번 새로운 View 객체를 생성해서 DispatcherServlet에 리턴한다.

⑧ DispatcherServlet 은 ViewResolver 가 리턴한 View 객체에게 응답 결과 생성을 요청한다.

⑨ JSP를 사용하는 경우, View 객체는 JSP를 실행함으로서 브라우저에게 전송할 응답 결과를 생성한다.

    ModelAndView 의 Model 객체에 담겨 있는 데이터가 응답 결과에 필요하면 Model 에서 데이터를 꺼내 JSP 에서 사용할 수 있다.

 

 

클라이언트의 요청을 실제로 처리하는 것은 컨트롤러이고, 

DispatcherServlet 은 클라이언트의 요청을 전달 받는 창구 역할을 한다.

DispatcherServlet 에게 어떤 컨트롤러가 요청을 처리하는가는 중요하지 않으며, 

처리 결과를 ModelAndView 타입의 객체로 전달 받을 수 있기만 하면 된다.

이 때, 사용할 컨트롤러를 찾고, 처리 결과를 ModelAndView 객체로 변환해 주는 객체가 HandlerAdapter 이다.

 

핸들러 객체의 실제 타입마다 그에 알맞은 HandlerMapping 과 HandlerAdapter 가 존재하기 때문에,

사용할 핸들러의 종류에 따라 해당 HandlerMapping 과 HandlerAdapter 를 스프링 빈으로 등록해 주어야 하는데,

스프링 설정 기능(<mvc:annotaion-driven>)을 사용하면 직접 등록하지 않아도 스프링이 알아서 처리해 준다.

 

요청을 처리할 컨트롤러를 찾기 때문에 ControllerMapping 이라는 이름이 어울리는데,

스프링 MVC 는 웹 요청을 처리할 수 있는 범용적인 프레임워크를 제공하고 있기 때문에,

클라이언트의 요청을 처리하는 객체가 컨트롤러가 아닐 수도 있다(HttpRequestHandler 등).

그래서 스프링 MVC 는 웹 요청을 실제로 처리하는 객체를 Handler 라고 표현하고 있다.

따라서 컨트롤러는 DispatcherServlet 입장에서 보면 한 종류의 핸들러 객체이다.

 

5. Spring MVC 핵심 구성 요소 (2) 설명2

  1. 클라이언트가 해당 어플리케이션에 접근하면 접근한 URL 요청을 DispatcherServlet 이 가로챕니다. 이렇게 요청을 가로챌 수 있는 이유는 web.xml 에 등록된 DispatcherServlet  <url-pattern>이 ‘/’ 와 같이 해당 어플을 통과하는 모든 URL로 등록했기 때문입니다. 특정 URL 만 적용하고 싶다면 <url-pattern> 의 내용을 바꿔주어 범위를 변경시켜주면 됩니다.

  2. 가로챈 정보를 HandlerMapping 에게 보내 해당 요청을 처리할 수 있는 Controller 를 찾아냅니다. (스프링은 기본적으로 5가지의 핸들러 매핑을 제공합니다.) 이 부분은 스프링의 디폴트 전략에 의해 BeanNameUrlHandlerMapping DefaultAnnotationHandlerMapping 이 기본으로 Spring MVC에 탑재되있기 때문에 특별한 경우가 아니면 따로 설정할 필요가 없습니다.

  3. 핸들러 매핑이 해당 요청을 처리할 컨트롤러를 찾아냈다면 요청을 컨트롤러에 보내줍니다. 컨트롤러는 사용자가 직접 구현해주는 부분입니다. @MVC는 매우 다양한 코딩방식과 직관적이고 편리한 컨트롤러 작성방법을 제공하므로 이 부분에 대해서는 차후 심층적인 분석으로 자신에게 알맞는 전략을 선정해야합니다.

  4. 해당 요청을 처리한 후에 컨트롤러는 요청을 응답받을 View 의 이름을 리턴하게 됩니다. ( 물론 다른 핸들러 매핑 전략을 이용한다면 응답 과정이 다를 수도 있습니다. ) 그 때 이 이름을 ViewResolver 가 먼저 받아 해당하는 View가 존재하는지 검색합니다.

  5. 컨트롤러에서 보내온 View 이름을 토대로 처리 View 를 검샙합니다.

  6. 해당 View가 있다면 처리결과를 View에 보낸 후 7. 이 결과를 다시 DispatcherServlet 에 보낸 후 8. DispatcherServlet 은 최종 결과를 클라이언트에 전송합니다.

 

자원의 분리

  • ’/’ 요청에 대한 모든 처리를 DispatcherServlet 이 담당한다면, 비어플리케이션 자원 (js, css …)에 대해서도 컨트롤러를 찾아 해매는 에러가 발생할 수 있다.
  • 그에 따라 Spring 은 자원을 분리할 수 있는 기능을 추가 시켜놓았다.
  • 이와 같은 처리는 preference의 Deplyment Assembly에 가면 확인 가능하다.

 

servlet-context.xml 파일 안

<resources mapping="/resources/-*" location="/resources/" />

  • <mvc:resources> 는 디스패처 서블릿이 해당 요청을 컨트롤러에서 찾지 못했을 때 2차적으로 위의 설정된 경로를 검색하여 해당 자원을 찾아내게 하는 것입니다.
  • 어플리케이션 자원과 비어플리케이션 자원( js, css …)을 분리하여 resources 폴더에서 따로 관리 가능하도록 한 것 입니다.

HttpSession을 이용한 Session 관리방법
- Client의 상태값을 서버측에 저장하여 Session 관리
- javax.servlet.http.HttpSession 객체를 이용하여 관리

 

 

HttpSession은 로그인 처리할 때 유용하게 쓰인다. 이것의 동작은 세션 쿠키를 통해 이루어진다. 서버는 접속한 브라우저에게 고유한 세션쿠키를 전달하고, 매번 브라우저에서 서버를 호출할 때 세션 쿠키를 가지고 다니기 때문에, 이를 마치 열쇠처럼 사용해서 필요한 데이터를 보관한다.

 

session을 이용하는 방식의 핵심은 HttpSession을 이용해서 객체를 보관할 수 있다는 점이다. 사용자는 항상 열쇠에 해당하는 세션쿠키를 가지고 접근하고, 서버의 내부에 상자가 필요한 객체를 보관하기 때문에 안전하다는 장점을 가지고 있다.

 

session에 보관된 객체는 JSP에서 EL을 이용해서 자동으로 추적하는 방식을 사용한다. 예를 들면 ${name}은 page > request > session > application 순서대로 원하는 데이터를 검색한다. 따라서 JSP를 개발하는 개발자는 자신이 사용하는 변수가 request에 존재하는 것인지, session에 존재하는 것인지 고민하지 않아도 된다.

 

 

장점 ?
- 관리할 수 있는 상태값(Client Data)의 종류나 크기나 개수의 제한이 없음
- 서버에 저장되므로 cooie에 비해 보안상 유리

단점 ?
- 서버에 부담을 줌

 

 

////////////////////////////////////////////

 

HttpSession의 주요 메서드

 

 메소드 이름

리턴 타입 

설명 

getAttribute(String name) 

 java.lang.Object

 세션 속성명이 name인 속성의 값을 Object 타입으로 리턴한다. 해당 되는 속성명이 없을 경우에는 null 값을 리턴한다.

getAttributeNames() 

java.util.Enumeration 

 세션 속성의 이름들을 Enumeration 객체 타입으로 리턴한다.

getCreationTime() 

long 

1970년 1월 1일 0시 0초를 기준으로 하여 현재 세션이 생성된 시간까지 경과한 시간을 계산하여 1/1000초 값으로 리턴한다. 

getId() 

java.lang.String 

세션에 할당된 고유 식별자를 String 타입으로 리턴한다. 

getMaxInactiveInterval()

int 

현재 생성된 세션을 유지하기 위해 설정된 세션 유지시간을 int형으로 리턴한다.

invalidate() 

void 

현재 생성된 세션을 무효화 시킨다.

소멸

removeAttribute(String.name)

void 

세션 속성명이 name인 속성을 제거한다. 

setAttribute(String name, Object value)

void 

세션 속성명이 name인 속성에 속성값으로 value를 할당한다. 

setMaxInactiveInterval(int interval) 

void 

세션을 유지하기 위한 세션 유지시간을 초 단위로 설정한다. 즉, Client가 Second 만큼 동안 요청이 들어오지 않으면 Session을 소멸

 

 

 

Enumeration: 

Enumeration 인터페이스는 객체들의 집합(Vector)에서 각각의 객체들을 한순간에 하나씩 처리할 수 있는 메소드를 제공하는 켈렉션이다.

 

[JAVA] Vector 클래스 정리

 

인터페이스이므로, 직접 new 연산자를 이용하여 객체를 생성할 수 없으며, Enumeration 인터페이스에 선언된 메소드는 그 인터페이스를 사용하는 클래스로 구현해서 사용해야만 한다.

 

* Enumeration 인터페이스 메소드

 

Enumeration 메소드 

설명 

boolean hasMoreElements() 

 Vector로 부터 생성된 Enumeration의 요소가 있으면 true, 아니면 false 반환

Object nextElement() 

 Enumeration 내의 다음 요소를 반환한다. 

 

Enumeration 객체는 new 연산자로 생성할 수 없으며, Vector를 이용하여 생성할 수 있다.

Vector 클래스의 elements() 라는 메소드는 객체의 모든 요소들을 Enumeration 객체로 반환한다.

 

//////////////////////////////

 

getSession(), getSession(true)는 null 체크없이 바로 getAttribute()를 사용해도 무방하지만, getSession(false)는 null을 리턴할수 있기 때문에 null체크를 해야 한다.

스프링 유용한 단축키

 

1. 자동 완성 기능

키: crtl+space

 

명령어를 어느정도 입력한 뒤 crtl+space를 누르면 추천 명령어가 뜬다.

 

syso 입력한 후 Ctrl + Space 하면 System.out.println(); 으로 바뀐다.

try 입력한 후 Ctrl + Space 하면 try-catch 문이 완성된다.

for 입력한 후 Ctrl + Space 하면 여러가지 for 문을 완성할 수 있다.

 

2. 주석 기능

키: crtl+shift+C

 

선택한 뒤 crtl+shift+c를 누르면 알아서 /* */ 또는 <!-- --> 등으로 주석 처리 해줌

 

3. 코드 찾기 기능

키: crtl+H

 

파일 안에 쓰여진 코드를 찾을 수 있다.

보통 file search로 한다.

 

4. 파일 찾기 기능

키: crtl+shft+R

 

프로젝트 안의 파일들을 찾을 수 있다.

 

5. 에러 내용 확인

키: F2

 

컴파일 에러기호에 커서를 갖져다가 이 키를 누르면 에러의 원인에 대한 힌트를 제공한다.

 

6. 한줄 삭제

키: crtl+D

 

7. 하이어라키창 띄우기 (인터페이스 구현 클래스간 이동시 편리)

키: crtl+T

 

8. 메소드나 필드 이동하기

키: crtl+O

 

9. 자동 import

키: crtl+shift+O

 

10. 디버그

키: F11

※ 자주 쓰이는 어노테이션

 

@ModelAttribute

- view에서 전달해주는 파라미터를 클래스(VO/DTO)의 멤버 변수로 binding 해주는 애노테이션

바인딩 기준은 <input name="id" /> 처럼 어떤 태그의 name값이 해당 클래스의 멤버 변수명과 일치해야하고 set메서드명도 일치해야한다.

 

ex)

class Person{

String id;

public void setId(String id){ this.id = id;}

}

 

 

@RequestMapping

- URL을 컨트롤러의 메서드와 매핑할 때 사용하는 스프링 프레임워크의 어노테이션이다.

클래스나 메서드 선언부에 @RequestMapping과 함께 URL을 명시하여 사용한다. URL외에도 HTTP 요청 메서드나 헤더값에 따라 매핑되도록 -0=옵션을 제공한다. 메서드 레벨에서 정의한 @RequestMapping은 타입 레벨에서 정의된 @RequestMapping의 옵션을 상속받는다.

 

참고로, 메서드 내에서 viewName을 별도로 설정하지 않으면 @RequestMapping의 path로 설정한 URL이 그대로 viewName으로 설정된다.

 

 

@Configuration

- Configuration을 클래스에 적용하고 @Bean을 해당 클래스의 메소드에 적용하면 @Autowired로 빈을 부를 수 있다.

 

 

@Resource

- @Autowired와 마찬가지로 빈 객체를 주입해주는데 차이점은 Autowired는 타입으로, Resource는 이름으로 연결해준다.

 

@Controller

- spring MVC의 Controller 클래스 선언을 단순화시켜준다. 스프링 컨트롤러, 서블릿을 상속할 필요가 없으며,   @Controller로 등록된 클래스 파일에 대한 bean을 자동으로 생성해준다.

Controller로 사용하고자 하는 클래스에 @Controller 어노테이션을 명시하면 component-scan으로 자동 등록된다.

 

 

@Repository

일반적으로 DAO에 사용되며 DB Exception을 DataAccessException으로 변환한다.

 


※ 그 외 어노테이션

 

@ResponseBody

- view가 아닌 JSON 형식의 값을 응답할 때 사용하는 애노테이션으로 문자열을 리턴하면 그 값을 http response header가 아닌 response body에 들어간다.

만약 객체를 return하는 경우 JACKSON 라이브러리에 의해 문자열로 변환되어 전송된다.

context에 설정된 resolver를 무시한다고 보면된다. (viewResolver)

 

 

@RequestBody

- 요청이 온 데이터(JSON이나 XML형식)를 바로 클래스나 model로 매핑하기 위한 애노테이션

 


@RequestParam

- @PathVariable과 비슷하다. request의 parameter에서 가져오는 것이다. 메소드의 파라미터에 사용됨

 

단일 파라미터 변환

private ModelAndView request_TEST(@RequestParam("test") int num,
@RequestParam("test2") String str)){
        //위처럼 하나이상의 타입을 적용할수 있습니다. 스프링에서 지원하는 변환기에서 지원되는 모든타입을 변환가능합니다.
        //RequestParam은 하나이상 파라미터에서 사용가능합니다.
    }

하지만 단점이 있다.

위처럼 사용하게 된다면 만약에 넘어오는 requestParam중에

@RequestParam 지정한 키값이 존재하지 않다면

BadRequest로 http 4** 에러가 발생한다.

 

 

2. 이를 방지하기 위하여 필수적이지 않도록 

그리고 존재하지 않다면 DefaultValue를 지정할수 있다.

private ModelAndView request_TEST(@RequestParam(value="test", required=false, defaultValue= "0") int num,
                                                   @RequestParam("test2") String str)){
        //required=false로 지정하면 해당 키값이 존재하지 않다고 해서 BadRequest가 발생하지 않게 됩니다.
                //그리고 존재하지 않다면 num변수에 default로 0이 들어가게됩니다.
}

 

 

3. RequestParam을 map에 지정하여 사용하기.

private ModelAndView request_TEST(@RequestParam HashMap<string,string> paramMap)){
        String data = paramMap.get("testParam");
    }
</string,string>

 

위의 예시처럼 map을 통해서도 파라미터를 컨트롤 할수 있습니다.

대규모의 파라미터를 받는데 map을 사용하기엔 편하지만

개발한 이외의 사람들이 유지보수하기에는 어려운 점이 있습니다.

그래서 주로 "커맨드패턴"인 데이터커맨드를 만들서 사용하는데요.

 

링크는 아래

https://heavenly-appear.tistory.com/44

 

 

@JsonProperty

- Jackson 라이브러리를 참조하는 어노테이션이다.

getter/setter 의 이름을 property 와 다른 이름을 사용할 수 있도록 설정한다. Database 를 자바 클래스로 매핑하는데 DB의 컬럼명이 알기 어려울 경우등에 유용하게 사용할 수 있다.

 

다음과 같은 테이블이 있을 경우

CREATE TABLE Users (
  u INT NOT NULL,
  a INT NOT NULL,
  e VARCHAR(80) NOT NULL
);

 

다음과 같이 JsonProperty 를 사용하면 DB 의 컬럼명을 변경하지 않아도 가독성을 높일 수 있다.

public class User
{
    @JsonProperty("userId");
    public Integer u;
  
    @JsonProperty("age");
    public Integer a;
  
    @JsonProperty("email");
    public String e;
}

 

json 으로 변환된 결과

{
    "userId": 1,
    "age": 13,
    "email": "user@host.com"
}

이외에 @JsonIgnoreProperties, @JsonInclude 등이 있다.

 

Jackson 라이브러리에 관한 자세한 내용:

https://www.lesstif.com/pages/viewpage.action?pageId=24445183#JavaJsonlibraryjackson%EC%82%AC%EC%9A%A9%EB%B2%95-%EA%B0%9C%EC%9A%94

 

 

@CrossOrigin

- CORS 보안상의 문제로 브라우저에서 리소스를 현재 origin에서 다른 곳으로의 AJAX요청을 방지하는 것이다.

@RequestMapping이 있는 곳에 사용하면 해당 요청은 타 도메인에서 온 ajax요청을 처리해준다.

@CrossOrigin(origins = "http://jeong-pro.tistory.com", maxAge = 3600)

-> 기본 도메인이 http://jeong-pro.tistory.com 인 곳에서 온 ajax요청만 받아주겠다.

 

 

@CachePut

- 캐시를 업데이트하기 위해서 메서드를 항상 실행하게 강제하는 애노테이션

해당 애노테이션이 있으면 메서드호출을 항상한다. 그러므로 @Cacheable과 상충되어 같이 사용하면 안된다.

 

 

@Lazy

- 지연로딩을 지원한다.

 @Component나 @Bean 애노티에션과 같이 쓰는데 클래스가 로드될 때 스프링에서 바로 bean등록을 마치는 것이 아니 라 실제로 사용될 때 로딩이 이뤄지게 하는 방법이다.

 

 

@Scheduled

- 스프링 스케줄러이다. Unix의 cron처럼 특정시간 혹은 몇분 혹은 몇시간마다 동작하는 스케쥴러를 구현한다.

 

...더보기

사용 예시)

 @Scheduled(fixedDelay=1000)
    public void TestScheduler(){
        System.out.println("스케줄링 테스트");
    }

3가지 밸류가 존재한다.

cron은 CronTab에서의 설정과 같이 cron="0/10 * * * * ?" 과 같은 설정이 가능하고

fixedDelay은 이전에 실행된 Task의 종료시간으로 부터 정의된 시간만큼 지난 후 Task를 실행한다.(밀리세컨드 단위)

fixedRate은 이전에 실행된 Task의 시작시간으로 부터 정의된 시간만큼 지난 후 Task를 실행한다.(밀리세컨드 단위)

 

 

 

 

 

+ Recent posts