Spring MVC Controller
스프링 MVC
- MVC를 이용한 Controller 의 특징
- HttpServletRequest, HttpServletResopnse 를 거의 사용할 필요없이 기능 구현
- 다양한 타입의 파라미터 처리, 다양한 타입의 리턴 타입 사용 가능
- GET,POST 전송 박식에 대한 처리를 어노테이션으로 처리 가능
- 상속/인터페이스 방식 대신 어노테이션으로도 필요 설정 가능
- 스프링 MVC 는 어노테이션을 중심으로 구성되기때문에 어노테이션의 의미에 대해 주의깊게 학습할것.
@Controller, @RequestMapping
@Controller
@RequestMapping("/sample/*")
public class SampleController {
@RequestMapping("/aaa")
public void aaa() {
log.info("aaa...............");
}
}
//servlet-context.xml
<context:component-scan base-package="org.zerock.controller" />
- @Controller
- Controller 역할을 수행한다고 명시
- Bean 으로 등록
- @Component 의 구체화 된 어노테이션
- @RequestMapping
- 현재 클래스의 모든 메소드들의 기본적인 URL 경로 (/지정경로/모든경로)
- 클래스의 선언과 메소드 선언에 사용 가능함.
@RequestMapping 의 변화
@Controller
@RequestMapping(value = "/sample/*", method = {RequestMethod.GET, RequestMethod.POST})
@Log4j
public class SampleController {
@GetMapping("/mapping")
public void aaa() {
log.info("aaa...............");
}
}
- method 속성을 추가가능함(Get, Post)
- GET,POST 모두 지원해야하는 경우 배열로 처리해 지정 가능함.
- 스프링 4.3 부터는 @GetMapping, @PostMapping 처럼 축약형표현으로 사용가능함.
@Controller의 파라미터 수집
@Controller 작성 시 가장 편리한 기능은 파라미터가 자동으로 수집되는 기능임.
//SampleDTO
@Data
public class SampleDTO {
private String name;
private int age;
}
//SampleController 에 추가
@GetMapping("/ex01")
public String ex01(SampleDTO dto) {
log.info(dto);
return "ex01";
}
- @GetMapping 이 사용되어 필요한 파라미터 뒤 값 입력 후 호출 시 로그에 출력되는걸 볼수있음.
- 자동으로 타입변환처리함.
파라미터의 수집과 변환
@GetMapping("/ex02")
public String ex02(@RequestParam("name") String name, @RequestParam("age") int age) {
log.info("name = " + name);
log.info("age = " +age);
return "ex02";
}
@GetMapping("/ex03")
public String ex03(@RequestParam("ids")ArrayList<?> ids ) { //또는 String[] 사용
log.info("ids = " + ids);
return "ex03";
}
-
@RequestParam 은 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른경우에 유용하게 사용됨.
-
파라미터가 여러개 전달될 경우 ArrayList<> 를 사용
- 파라미터의 타입은 실제적인 클래스 타입을 지정함.
객체 리스트
- 여러 객체 타입의 파라미터를 처리해야할 시 사용
// 객체를 담을 리스트 클래스 추가
@Data
public class SampleDTOList {
private List<SampleDTO> list;
public SampleDTOList() {
list = new ArrayList<>();
}
}
// 테스트
@GetMapping("/ex05")
public String ex05(SampleDTOList list) {
log.info("list =" + list);
return "list";
}
@InitBinder
파라미터의 수집을 다른용어로 binding 이라 함. 변환이 가능한 데이터는 자동으로 변환되지만 경우에 따라 파라미터를 변환해 처리해야하는 경우 사용하는 어노테이션.(‘2020-12-12’ 와 같이 문자열로 받은 데이터값)
@Data
public class TodoDTO {
private String title;
private Date date;
}
@DateTimeFormat
@InitBinder 를 이용할수도 있지만 파라미터로 사용되는 인스턴스 변수에 @DateTimeFormat 을 이용해도 변환 가능
@Data
public class TodoDTO {
private String title;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
}
- 위와같이 변환 시 @InitBinder 어노테이션 사용 안해도 됨.
Model 데이터 전달자
- Model 객체는 JSP에 데이터를 담아 전달하는 역할임.
- 파라미터에 Model 타입이 지정된 경우 Model 타입의 객체를 만든뒤 주입함.
- request.setAttribute()와 유사한 역할을 함.
@ModelAttribute
//SampleController.java
@GetMapping("/ex07")
public void ex07(SampleDTO dto, @ModelAttribute("page") int page) {
log.info(dto);
log.info(page);
}
// jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>sampleDTO ${sampleDTO }</h2>
<h2>page ${page }</h2>
</body>
</html>
- 강제로 전달받은 파라미터를 Model 에 담아서 전달하도록 할 때 사용하는 어노테이션
- 타입에 관계없이 무조건 Model 에 담아서 전달됨.
- 파라미터로 전달된 데이터를 다시 화면에 사용할때 사용함.
- @ModelAttribute 사용 시 value 를 지정할것.
@RedirectAttributes
//Serlvet redirect 방식
response.sendRedirect("/home?name=aaa&age=10");
//Spring MVC 방식
rttr.addFlashAttribute("name", "AAA");
rttr.addFlashAttribute("age",10);
- 일회성으로 데이터를 전달하는 용도로 사용됨.
- response.sendRedirect()를 사용할때와 동일한 용도
Controller 리턴 타입
- Controller 의 메소드가 사용할 수 있는 타입
타입 | 용도 |
---|---|
String | jsp 를 이용하는 경우 jsp 파일의 경로와 파일이름을 나타내기 위해 사용 |
void | 호출하는 URL 과 동일한 이름의 jsp를 의미 |
VO, DTO | 주로 JSON 타입의 데이터를 만들어 반환하는 용도로 사용 |
ResponseEntity | response 할 때 Http 헤더 정보와 내용을 가공하는 용도로 사용 |
Model, ModelAndView | Model 로 데이터를 반환하거나 화면까지 같이 지정하는 경우에 사용 |
HttpHeaders | 응답에 내용없이 Http 헤더 메시지만 전달하는 용도 |
@GetMapping("/ex08")
private void ex08() {
}
- void
- 리해당 URL 의 경로를 그대로 jsp 파일의 이름으로 사용하게됨.
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
- String
- 상황에 따라 다른 화면을 보여줄 필요가 있을경우 사용(if~else 와 같은 처리가 필요한 상황)
- String 타입은 JSP 파일의 이름을 의미함.
- String 타입에는 특별한 키워드를 붙여 사용가능함.
- redirect : 리다이렉트 방식으로 처리하는경우
- forward : 포워드 방식으로 처리하는 경우
@GetMapping("/ex09")
public @ResponseBody SampleDTO ex09() {
log.info("//ex09");
SampleDTO dto = new SampleDTO();
dto.setAge(10);
dto.setName("AAA");
return dto;
}
- 객체 타입
- JSON 데이터를 만들어내는 용도로 사용함.
//pom.xml 라이브러리 추가
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
@GetMapping("/ex10")
public ResponseEntity<String> ex10(){
log.info("ex10------------");
String msg = "{\"name\": \"홍길동\"}";
HttpHeaders header = new HttpHeaders();
header.add("Content-Type", "application/json;charset=UTF-8");
return new ResponseEntity<String>(msg, header, HttpStatus.OK);
}
- ResponseEntity 타입
- 원하는 헤더 정보나 데이터를 전달 가능함.
// pom.xml 라이브러리 추가
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
//servlet-context.xml
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="defaultEncoding" value="utf-8" />
<beans:property name="maxUploadSize" value="104857560" />
<beans:property name="maxUploadSizePerFile" value="2097152" />
<beans:property name="uploadTempDir" value="file:/C:/upload/tmp" />
<beans:property name="maxInMemorySize" value="10485756" />
</beans:bean>
//controller
@GetMapping("/upload")
private void upload() {
log.info("upload...........");
}
//jsp
<form action="/sample/uploadPost" method="post" enctype="multipart/form-data">
<div>
<input type="file" name="files" />
</div>
<div>
<input type="submit" />
</div>
</form>
//controller
@PostMapping("/uploadPost")
private void uploadPost(ArrayList<MultipartFile> files) {
log.info(files);
files.forEach(f -> {
log.info("--------------");
log.info(f.getOriginalFilename());
log.info(f.getSize());
log.info("--------------");
});
}
- 파일 업로드 처리
- servlet-context.xml 설정
- java 이용시
@Bean(name = "multipartResolver")
public CommonsMultipartResolver getResolver() throws Exception{
CommonsMultipartResolver res = new CommonsMultipartResolver();
res.setMaxUploadSize(1024 * 1024 * 10);
res.setMaxUploadSizePerFile(1024 * 1024 * 2);
res.setMaxInMemorySize(1024 * 1024);
res.setUploadTempDir(new FileSystemResource("C:\\upload\\tmp"));
res.setDefaultEncoding("utf-8");
return res;
}
Controller Exception 처리
- 스프링 MVC 에서 예외상황 처리방법
- @ExceptionHandler 와 @ControllerAdvice 를 이용한 처리
- @ResponseEntity 를 이용하는 메시지 구성
- @ControllerAdvice
AOP(Aspect-Oriented-Programming)을 이용하는 방식(AOP란 공통적인 관심사를 분리 하자는 개념)
@ControllerAdvice
@Log4j
public class CommonExceptionAdvice {
@ExceptionHandler(Exception.class)
public String ex(Exception ex, Model model) {
log.error("에러" + ex.getMessage());
model.addAttribute("exception",ex);
log.error(model);
return "error_page";
}
}
- @ControllerAdvice 는 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 존재임을 명시하는 용도로 사용
- @ExceptionHandler 는 해당 메소드가 () 들어가는 예외 타입을 처리하는다는것을 의미