스프링 웹 MVC-22.Flash Attributes, MultipartFile(핸들러 메소드)


핸들러 메소드 12부: Flash Attributes

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

  • 데이터가 URI에 노출되지 않는다.
  • 임의의 객체를 저장할 수 있다.
  • 보통 HTTP 세션을 사용한다.

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

RedirectAttributes를 통해 사용할 수 있다.

XPath

  • https://www.w3schools.com/xml/xpath_syntax.asp
  • https://www.freeformatter.com/xpath-tester.html#ad-output

사용방법

    @PostMapping(value = "/events/form/age")
    public String eventsFormAgeSubmit(@Validated @ModelAttribute Event event,
                                      BindingResult bindingResult,
                                      SessionStatus sessionStatus,
                                      RedirectAttributes attributes) {
        if(bindingResult.hasErrors()){
            return "/events/form-age";
        }
        sessionStatus.setComplete();
        attributes.addFlashAttribute("newEvent", event);
        // uri 경로 미노출
        // 임의의 객체 사용 가능 (event.class)
        return "redirect:/events/list";
    }

    @GetMapping("/events/list")
    public String getEvents(Model model, // 그냥 모델에 들어온다. (addFlashAttribute)
                            @SessionAttribute LocalDateTime visitTime){
        System.out.println(visitTime);

        Event event = new Event();
        event.setName("jaeuk");
        event.setAge(30);

        Event newEvent = (Event) model.asMap().get("newEvent"); // model에서 꺼냄

        List<Event> eventList = new ArrayList<>();
        eventList.add(event);
        eventList.add(newEvent);

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

테스트코드

    @Test
    public void getEvents() throws Exception{
        Event newEvent = new Event();
        newEvent.setName("my name is jaeuk");
        newEvent.setAge(27);

        mockMvc.perform(get("/events/list")
                .sessionAttr("visitTime", LocalDateTime.now())
                .flashAttr("newEvent", newEvent))
                    .andDo(print())
                    .andExpect(status().isOk())
                    // html 본문도 테스트 가능
                    // p 노드를 전부 셀렉트해서 p 노드가 2개 있는지 확인
                    .andExpect(xpath("//p").nodeCount(2));
    }

핸들러 메소드 13부: MultipartFile

MultipartFile

  • 파일 업로드시 사용하는 메소드 아규먼트
  • MultipartResolver 빈이 설정 되어 있어야 사용할 수 있다. (부트의 경우는 자동 설정 해 줌)
  • POST multipart/form-data 요청에 들어있는 파일을 참조할 수 있다.
  • List 아큐먼트로 여러 파일을 참조할 수도 있다.

파일 업로드 관련 스프링 부트 설정

  • MultipartAutoConfiguration
  • MultipartProperties

참고

  • https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-multipart-forms
  • https://spring.io/guides/gs/uploading-files/
spring.servlet.multipart.location=
spring.servlet.multipart.file-size-threshold=
... 설정가능

파일 업로드 폼

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>file upload form</title>
</head>
<body>

<div th:if="${message}">
    <h2 th:text="${message}"></h2>
</div>

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

파일 업로드 처리 핸들러

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

    @PostMapping("/file")
    public String fileUpload(@RequestParam MultipartFile file,
                             RedirectAttributes attributes){
        //save
        String message = file.getOriginalFilename() + "is uploaded";
        attributes.addFlashAttribute("message", message);
        return "redirect:/file";
    }

테스트

    @Test
    public void fileUploadTest() throws Exception{
        MockMultipartFile file = new MockMultipartFile(
                "file",
                "test.txt",
                "plain/text",
                "hello file".getBytes());


        this.mockMvc.perform(multipart("/file").file(file))
                .andDo(print())
                .andExpect(status().is3xxRedirection());
    }





© 2019. by jaeuk