Spring | 06 스프링 MVC의 Controller 1/4 - 파라미터 수집

파과·2022년 9월 20일

스프링에서 관리되는 클래스는 아이콘 옆에 작게 s 표시가 추가된다.

org.zerock.controller 패키지에 SampleController 클래스를 만들자.

package org.zerock.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.log4j.Log4j;

@Controller
@RequestMapping("/sample/*")
@Log4j
public class SampleController {

	@RequestMapping("")
	public void basic() {
		log.info("basic........................");
	}
}

Log4j를 인식하지 못할 경우 pom.xml을 수정해주면 된다. 참고 : https://moon1226.tistory.com/93

@RequestMapping

@RequestMapping : method속성으로 GET, POST 방식을 구분해서 사용할 수 있다.
@GetMapping, @PostMapping으로 축약형을 쓸 수도 있다.

package org.zerock.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import lombok.extern.log4j.Log4j;

@Controller
@RequestMapping("/sample/*")
@Log4j
public class SampleController {

	@RequestMapping("")
	public void basic() {
		log.info("basic........................");
	}
	
	@RequestMapping(value="/basic", method= {RequestMethod.GET, RequestMethod.POST})
	public void basicGet() {
		log.info("basic get...............");
	}
	
	@GetMapping("/basicOnlyGet")
	public void basicGet2() {
		log.info("basic get only get..........");
	}
}

Controller의 파라미터 자동 수집

SampleDTO.java

package org.zerock.domain;

import lombok.Data;

@Data
public class SampleDTO {

	private String name;
	private int age;
}

@Data를 이용하면 getter/setter, equals(), toString()등의 메서드를 자동 생성해준다.

SampleController.java에 아래 코드 추가

@GetMapping("/ex01")
	public String ex01(SampleDTO dto) {
		log.info("" + dto);
		
		return "ex01";
	}

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

다음 주소로 호출해보자. (콘솔 로그에서 결과를 확인할 수 있다)
localhost:8080/sample/ex01?name=AAA&age=10

파라미터 수집과 변환

컨트롤러는 파라미터 타입에 따라 자동으로 변환시켜준다. 기본 자료형이나 문자열 등을 이용한다면 파라미터 타입만을 맞게 선언해주는 방식이 있다.

SampleController에 다음을 추가하자.

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

아까 호출했던 주소로 다시 호출하면 이전과 동일하게 데이터가 수집된다.

리스트, 배열 처리

동일한 이름의 파라미터가 여러 개 전달되는 경우 ArrayList<>등을 이용해 처리할 수 있다.

@GetMapping("/ex02List")
	public String ex02List(@RequestParam("ids")ArrayList<String> ids) {
		log.info("ids: " + ids);
		return "ex02List";
	}
}

localhost:8080/sample/ex02List?ids=111&ids=222&ids=333 을 호출해보자. 로그에 다음과 같이 출력된다.

배열의 경우는 다음처럼.

@GetMapping("/ex02Array")
	public String ex02Array(@RequestParam("ids") String[] ids) {
		log.info("array ids: " + Arrays.toString(ids));
		
		return "ex02Array";
	}

객체 리스트

SampleDTO와 같은 객체를 여러 개 전달받아서 처리하고 싶다면, SampleDTOList 클래스를 설계한다.

SampleDTOList.java

package org.zerock.domain;

import java.util.ArrayList;
import java.util.List;

import lombok.Data;

@Data
public class SampleDTOList {

	private List<SampleDTO> list;
	
	public SampleDTOList() {
		list = new ArrayList<>();
	}
}

SampleController.java

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

다음 URL을 전송해보자.
http://localhost:8080/sample/ex02Bean?list[0].name=aaa&list[2].name=bbb

톰캣이 [ ] 문자를 허용하지 않을 경우 각각 %5B%5D 로 변경해 사용한다.

http://localhost:8080/sample/ex02Bean?list%5B0%5D.name=aaa&list%5B2%5D.name=bbb

@InitBinder

파라미터의 수집을 다른 용어로는 binding바인딩이라고 한다.

파라미터를 바인딩할 때 @InitBinder가 자동으로 호출된다.
파라미터 타입을 변환할 때 이 @InitBinder를 이용한다.

TodoDTO 클래스를 작성하자.

package org.zerock.domain;

import java.util.Date;

import lombok.Data;

@Data
public class TodoDTO {

	private String title;
	private Date dueDate;
}

주의할 것은 dueDate의 타입이 java.util.Date이다.
사용자가 2018-01-01과 같이 들어오는 데이터를 변환하고자 하면 문제가 발생한다. InitBinder가 이를 처리해 줄 수 있다.

SampleController.java 수정

//...생략
@InitBinder
	public void initBinder(WebDataBinder binder	) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(dateFormat, false));
	}
//...생략
@GetMapping("/ex03")
	public String ex03(TodoDTO todo) {
		log.info("todo: " + todo);
		return "ex03";
	}

다음을 호출한다.

http://localhost:8080/sample/ex03?title=text&dueDate=2018-01-01

정상적으로 수집된다.

@DateTimeFormat

또는 DateTimeFormat을 적용해 날짜를 변환할 수도 있다.

package org.zerock.domain;

import java.util.Date;

import lombok.Data;

@Data
public class TodoDTO {

	private String title;

	@DateTimeFormat(pattern = "yyyy/MM/dd")
	private Date dueDate;
}

0개의 댓글