Programming/Spring MVC

핸들러 메소드 - 2 (스프링 MVC - 6)

흠냐아뤼 2020. 3. 26. 17:47
728x90

 

1. @SessionAttributes

- 모델 정보를 HTTP 세션에 저장해주는 애노테이션

- 이 애노테이션에 설정한 이름에 해당하는 모델 정보를 자동으로 세션에 넣어준다.

- @ModelAttribute는 세션에 있는 데이터도 바인딩한다.

- 여러 화면에서 사용해야 하는 객체를 공유할 때 사용함

   ex) 회원 가입을 여러 창에 나누어서 할 때

- SessionStatus를 사용해서 세션 처리 완료를 알려줄 수 있다. (폼 처리가 끝나고 세션을 비울 때 사용)

 

 

2. @SessionAttribute

- 해당 컨트롤러 안에서 동작하는 @SessionAttributes와는 다르게 쓰임 

  -> @SessionAttribute는 컨트롤러 밖 (인터셉터 또는 필터 등)에서 만들어 준 세션 데이터에 접근할 때 사용함

- HTTP 세션에 들어있는 값 참조할 때 사용

 

 

세션을 사용해서 여러 폼에 걸쳐 데이터를 나눠 입력 받고 저장하기 (@SessionAttributes)

- 이벤트 이름 입력 -> 이벤트 아이디 입력 -> 이벤트 목록

 

사용자 최초 접근 시간을 핸들러 인터셉터로 구현하기 (@SessionAttribute)

 

1) 컨트롤러 작성

@Controller
@SessionAttributes("event")
public class SampleController {

    private List<Event> eventList = new ArrayList<>();

    @GetMapping("/events/form/name")
    public String eventsFormName(Model model) {
        model.addAttribute("event", new Event());
        return "/events/form-name";
    }

    @PostMapping("/events/form/name")
    public String eventsFromNameSumit(@Valid @ModelAttribute Event event,
                                      BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            return "events/form-name";
        }
        return "redirect:/events/form/id";
    }

    @GetMapping("/events/form/id")
    public String eventsFormId(@ModelAttribute Event event,
                               Model model) {
        model.addAttribute(event);
        return "/events/form-id";
    }

    @PostMapping("/events/form/id")
    public String eventFormIdSubmit(@Valid @ModelAttribute Event event,
                                    BindingResult bindingResult,
                                    SessionStatus sessionStatus) {
        if(bindingResult.hasErrors()){
            return "/events/form-id";
        }

        // Store to Database
        eventList.add(event);
        sessionStatus.setComplete();
        return "redirect:/events/list";
    }

    @GetMapping("/events/list")
    public String showEvents(Model model, @SessionAttribute LocalDateTime visitTime) {
        System.out.println(visitTime);

        // Select from database
        model.addAttribute(eventList);
        return "/events/list";
    }
}

 

2) 핸들러 인터셉터 작성 및 등록(등록은 생략)

public class VisitTimeInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        final HttpSession session = request.getSession();
        if(session.getAttribute("visitTime") == null) {
            session.setAttribute("visitTime", LocalDateTime.now());
        }

        return true;
    }

}

 

 

3. RedirectAttributes

- 리다이렉트 할 때 기본적으로 Model에 들어있는 primitive type 데이터는 URI 쿼리 매개변수에 추가된다.

   스프링 부트에서는 이 기능이 기본적으로 비활성화 되어 있다. (프로퍼티 추가하여 활성화)

- 원하는 값만 리다이렉트 할 때 전달하고 싶다면 RedirectAttributes에 명시적으로 추가 가능 

- 리다이렉트 요청을 처리하는 곳에서 @RequestParam, @ModelAttribute (세션 사용 시 이름 같으면 안됨)로 받을 수 있음

- Event와 같은 객체 전달 불가능

 

 

4. Flash Attributes

- 주로 리다이렉트시에 데이터를 전달할 때 사용한다.

- 데이터가 URI에 노출되지 않는다

- 임의의 객체를 저장할 수 있다.

 

리다이렉트 하기 전에 데이터를 HTTP 세션에 저장하고 리다이렉트 요청을 처리 한 다음 그 즉시 제거한다.

redirectAttributes.addFlashAttribute(event);

 

리다이렉트를 받는 핸들러는 Model로 위의 객체를 받을 수 있음.

 

 

5. MultipartFile

- 파일 업로드 시 사용하는 메소드 아규먼트

- MultipartResolver 빈이 설정 되어 있어야 사용할 수 있다 (스프링 부트 자동 설정이 해줌)

- POST multipart/form-data 요청에 들어있는 파일 참조 가능

- List<MultipartFile> 아규먼트로 여러 파일을 참조할 수 있다.

 

1) 업로드 및 업로드 확인 페이지 작성

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
    <div th:if="${message}">
        <h2 th:text="${message}">msg</h2>
    </div>

    <form method="POST" enctype="multipart/form-data" action="#" th:action="@{/file}">
        <input type="file" name="file"></input>
        <input type="submit" value="UPLOAD"></input>
    </form>
</body>
</html>

 

2) FileController 작성

@Controller
public class FileController {

    @GetMapping("/file")
    public String fileForm(Model model) {
        return "/files/index";
    }

    @PostMapping("/file")
    public String fileUpload(@RequestParam MultipartFile file,
                             RedirectAttributes redirectAttributes) {

        /*
        	save
            local, cloud..에 저장
        */

        String message = file.getOriginalFilename() + " is Uploaded";
        redirectAttributes.addFlashAttribute("message", message);
        return "redirect:/file";
    }
}

 

 

6. 파일 다운로드

 

파일 리소스 읽어오는 방법

- 스프링 ResourceLoader 사용하기

 

파일의 종류(미디어 타입) 알아내는 방법

- 티카 의존성 추가 후 사용

 

ResponseEntity

- 응답 상태 코드

- 응답 헤더

- 응답 본문

 

@Controller
public class FileController {

    @Autowired
    ResourceLoader resourceLoader;

    @GetMapping("/file/{filename}")
    public ResponseEntity<Resource> fileDownload(@PathVariable String filename) throws IOException {
        Resource resource = resourceLoader.getResource("classpath:" + filename);
        File file = resource.getFile();

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + resource.getFilename() + "\"")
                .header(HttpHeaders.CONTENT_TYPE, "text/plain")
                .header(HttpHeaders.CONTENT_LENGTH, file.length() + "")
                .body(resource);
    }

}

 

 

7. @RequestBody & HttpEntity

 

@ReqeustBody

- 요청 본문(body)에 들어있는 데이터를 HttpMessageConverter를 통해 변환한 객체로 받아올 수 있음

- @Valid, @Validated 사용해서 검증 할 수 있음

- BindingResult 사용 가능 (바인딩 예외 발생 시 예외를 발생시키지 않고, 코드로 처리할 수 있음)

 

HttpEntity

- @RequestBody와 비슷하지만 추가적으로 요청 헤더 정보를 사용할 수 있다.

 

 

8. @ResponseBody & ResponseEntity

 

@ResponseBody

- 데이터를 HttpMessageConverter를 사용해 응답 본문 메시지로 보낼 때 사용함

- @RestController 사용 시 자동으로 모든 핸들러 메소드에 적용됨

 

ResponseEntity

- 응답 헤더 상태 코드 본문을 직접 다루고 싶은 경우에 사용함

 

 

-@JsonView, PushBuilder는 따로 공부할 것!

 

 

 

 

인프런 백기선님 '스프링 MVC’ 강의를 듣고 정리한 내용입니다.
728x90