Spring-MVC : 1

김정훈·2021년 2월 24일
0

Spring

목록 보기
3/4
post-thumbnail

프로젝트 생성

  1. Spring Legacy Project를 선택
  2. Spring MVC Project를 선택
  3. 생성된 프로젝트의 pom.xml의 자바, 스프링 버전을 수정해준다.
  4. servlet 버전 또한 2.5 => 3.1.0 버전으로 수정해준다.
  5. maven의 컴파일 옵션도 1.6으로 되어있는데 1.8로 변경하고
    프로젝트의 Maven메뉴에서 update project를 클릭해서 업데이트 시켜준다.
  6. 프로젝트를 한 번 실행시켜주고, Tomcat의 Modules 메뉴로 들어가서,
    Path부분을 '/' 경로로 프로젝트가 실행될 수 있도록 처리한다.

프로젝트의 로딩 구조에 대해서.

web.xml : Tomcat구동과 관련된 설정
root-context.xml, servlet-context.xml : 이 2가지 파일은 스프링과 관련된 설정이다.

web.xml
context-param에는 root-context.xml의 경로가 설정되어 있다.
root-context.xml파일이 처리되면 root-context.xml 파일에 있는 Bean(객체) 설정들이 동작한다.
root-conext.xml에 정의된 객체들은 스프링의 영역 안에 생성되고, 객체들 간의 의존성을 처리한다.

ContextLoaderListener는 Spring컨테이너를 생성하고,
Spring은 모든 Servlet과 Filters 공유하는 역할을 한다고 한다.

root-context.xml의 beans graph에 있는 그림이다.
hotel, restaurant, chef의 의존성이 처리된다.

root-context.xml이 처리된 후 DispatcherServlet이라는 Servlet관련된 설정이 동작한다.
우선 이 그림을 한 번 살펴보고 가자.

DispatcherServlet의 동작방식

  1. 사용자의 요청(request)는 Front-Controller인 DispatcherServlet을 통해서 처리한다.
  2. HandlerMapping은 Request의 처리를 담당하는 Controller를 찾기 위해서 존재한다.
    HandlerMapping인터페이스를 구현한 여러 객체들 중 RequestMappingHandlerMapping 같은 경우는 개발자가 @RequestMapping어노테이션이 적용된 것을 기준으로 판단하게 된다.
    적절한 컨트롤러가 찾아졌다면 HandlerAdapter를 이용해서 해당 컨트롤러를 동작시킨다.
  3. Controller는 개발자가 작성하는 클래스로 실제 Request를 처리하는 로직을 작성한다.
    이 때 View에 전달해야 하는 데이터는 주로 Model이라는 객체에 담아서 전달한다.
    Controller는 다양한 타입의 결과를 반환하는데 이에 대한 처리는 viewResolver을 이용한다.
  4. ViewResolver는 Controller가 반환한 결과를 어떤 View를 통해서 처리하는 것이 좋을지 해석하는 역할을 한다.<지금은 이 정도만 하고 넘어가자.>
  5. View는 실제로 응답 보내야 하는 데이터를 Jsp등을 이용해서 생성하는 역할을 하게 된다.
    만들어진 응답은 DispatcherServlet을 통해서 전송된다.

DispatcherServlet * Front-Controller 패턴
모든 Request를 DispatcherServlet을 통하도록 설계되어 있고, 이런 방식이 Front-Controller패턴이다.
Front-Controller 패턴을 이용하는 경우에는 모든 Request의 처리에 대한 분배가 정해진 방식대로 동작한다.
이러한 특징으로 엄격한 구조를 만들어 낼 수 있다.


스프링MVC를 이용하는 경우 작성되는 Controller의 특징

  1. HttpServletRequest, HttpServletResponse 거의 사용할 필요 없이 필요한 기능 구현
  2. 다양한 타입의 파라미터 처리, 다양한 타입의 리턴 타입 사용 가능
  3. Get방식, Post방식 전송 방식에 대한 처리를 @어노테이션 처리 가능
  4. 상속, 인터페이스 방식 대신에 @어노테이션만으로 설정 가능

Controller

ExController에 @Controller라는 스프링MVC에서 사용하는 @어노테이션을 적용한다.
작성된 ExController클래스는 자동으로 스프링의 객체(Bean)으로 등록된다.
이 부분은 servlet-context.xml파일을 보면 확인할 수 있다.
이거는 servlet-context.xml의 일부인데,
com.xml.practice는 mvc프로젝트를 생성할 때 기본으로 생성되는 패키지이고, 이 패키지 안에 HomeController가 있다.
SpringMVC를 생성할 때 com.velog.io라는 패키지가 생성되고, 저 패키지 밑에는 HomeController가 생긴다.

root-context.xml, servlet-context.xml
이 두 개의 xml파일에서 모두 component-scan을 한다.
해당 패키지에 선언된 클래스들을 스캔하면서 스프링에서 객체(Bean) 설정에 사용되는,
@어노테이션들을 가진 클래스들을 파악하고 필요한 경우 이를 객체로 생성해서 관리한다.

클래스가 스프링에서 관리되면 클래스 옆에 그림과 같이 's'모양의 아이콘이 추가된다.

@RequestMapping

현재 클래스의 모든 메서드들의 기본적인 URL의 경로가 된다.

ex) TestController 클래스에,
@RequestMapping('/sample/*') 이렇게 경로를 지정했다고 하면
/sample/aaa
/sample/bbb
이 두 가지 경로 모두 AController에서 처리된다.

@Controller같은 경우 추가적인 속성을 지정할 수 없다.
@RequestMapping의 경우에는 몇 가지의 속성을 추가할 수 있다.

RequestMapping(value="/basic", method=RequestMethod.GET)
그런데 이제는 이 방법보다는
@GetMapping("/basic")
@PostMapping("/basic")으로 쓴다.

Get,Post방식 모두를 지원해야 하는 경우에는
@RequestMapping(value="/abc", method={RequestMethod.GET, RequestMethod.Post})

Controller의 파라미터 수집

예제를 위해서 SamDTO클래스를 생성해준다.

@Data
public class SamDTO{
	private String name;
    private int age;
}

Lombok의 @Data 어노테이션을 이용해서 getter/setter, equals(), toString()이 생성된다.

@Controller
@RequestMapping("/sample/*")
@Log4j
public class TestController{
	@GetMapping("/ex01")
        public String ex01(SamDTO dto){
				log.info(""+dto);               
                return "ex01";
       }
 }

AController의 메소드가 SamDTO를 파라미터로 사용하게 되면,
자동으로 SamDTO의 setter메소드가 동작하면서 파라미터를 수집하게 된다.

AController의 경로가 '/sample*' 이므로
그런데 ex01()메소드에 GetMapping이 설정되어 있다.
호출하는 경로는 sample/ex01이 된다.
필요한 파라미터를 URL뒤에 '?name=AAA&age=10' 같은 형태로 추가해서 호출을 해보면,
다음과 같은 로그가 찍힐 것이다.

INFO : packageName.AController-SamDTO(name=AAA, age=10)

파라미터의 수집과 변환

@Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식이다.
ex>위의 예제에서 보면 int타입으로 선언된 age(SamDTO)가 자동으로 숫자로 변화되는 것을 볼 수 있다.

@RequestParam
기본 자료형이나 문자열 등을 이용한다면 파라미터의 타입만을 맞게 선언해주는 방식을 사용할 수 있다.
ex02() 메서드는 파라미터에 @RequestParam 어노테이션을 사용해서 작성되었다.

@RequestParam은 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우 유용하다

@RequestParam을 사용한 경우이다.

@GetMapping("/ex02")
public String ex02(@RequestParam("name") String name,
	           @RequsetParam("age") int age){
               					log.info("name:"+name);
                                		log.info("age:"+age);
                                   		return "ex02";
                                        }

@RequestParam을 이용해서 List, Array배열 처리도 가능하다

@GetMapping("/ex02List")
public String ex02List( @RequestParam("ids")ArrayList<String> ids){

	log.info("ids: "+ids);
    	return "ex02List";

스프링은 파라미터의 타입을 보고 객체를 생성하므로,
파라미터의 타입은 List와 같은 인터페이스 타입이 아닌 실제적인 ArrayList와 같은 클래스 타입으로 지정한다.

이 코드의 경우네느 'ids'라는 이름의 파라미터가 여러 개 전달되더라도 ArrayList이 생성되어 자동으로 수집한다.

/sample/ex02List?ids=111&ids=222&ids=333 을 호출하면
INFO : 패키지.컨트롤러 - ids:{111,222,333}
이렇게 로그가 찍힌다.

다음으로 객체 자체를 List로 만들어서 처리해보자.
SamListDTO.java로 객체를 만들어주자.

@Data
public class SamListDTO{
  private List<SamDTO> list;
  
  public SamListDTO(){
  		list = new ArrayList<>();
  	}
  }

Controller.java

  @GetMapping("/ex02Bean")
  public String ex02Bean(SamListDTO list){
  	log.info("list dtos: "+list);
  	return "ex02Bean";
  }

테스트 URL 프로젝트경로/sample/ex02Bean?list[0].name=aaa&list[2].name=bbb
[] Tomcat버전에 따라서 이 부분에서 에러가 발생할 수 있다.
==> /sample/ex02Bean?list%5B0%5D.name=aaa 이렇게 호출해주면

INFO : 패키지.컨트롤러 - list dtos : SamListDTO(list=[SamDTO(name=aaa, age=0)
이렇게 로그가 찍히는 것을 확인할 수 있다.

@DateTimeFormat

파라미터로 사용되는 인스턴스 변수에 @DateTimeFormat을 적용해 타입 변환이 가능하다.

@Data
public class TodoDTO{
  private String title;
  
  @DateTimeFormat(pattern="yyyy/MM/dd")
  private Date dueDate;
}

Test URL : localhost:~/sample/ex03?title=testFile&dueDate=2018/01/01

INFO : package.Controller - todo: TodoDTO(title=testFile, dueDate=Mon Jan 01 00:00:00 KST 2018
이렇게 로그가 찍히는 것을 확인할 수 있다.

참고 : 코드로 배우는 스프링 웹 프로젝트

profile
WebDeveloper

0개의 댓글