98일차 Spring return에 대해 / 파일 업로드 처리에 대해

쿠우·2022년 8월 19일
0

Controller 부분의 메서드에 리턴에 대해서

-return 부분은 곧 반환할 view
-void일 때 그리고 클래스 일 때 다양한 상황에 대한 예제

-void의 반환

	@GetMapping("/void")
	public void returnVoid() {
		log.trace("returnVoid() invoked.");
		// 뷰이름 => 곧, Request URI(= Base URI + Detail URI) 이다.
	}// return void

-String 타입의 반환

	@GetMapping("/string")
	public String returnString() {
		log.trace("returnVoid() invoked.");
		return "return/string"; // => WEB-INF/views/return/string.jsp
	}// return String

-redirect 의 반환

-외부 URL 허용

	@GetMapping("/redirect")
	public String returnRedirect() {
		log.trace("returnRedirect() invoked.");
//		return "redirect:/return/void"; // 최종 보여주는 화면은 /return/void 
//		return "redirect:void";         // base생략해도 최종 보여주는 화면은 /return/void 
		return "redirect:http://naver.com";  // OK 외부 URL도 리다이렉트 가능

	}//returnRedirect

-forward 의 반환

-외부 URL 허용하지 않는다.


	@GetMapping("/forward")
	public String returnForward() {
		log.trace("returnForward() invoked.");
		
		//Servlet에서 우리가 직접 Request Forwarding 수행시 코드와 같다. 
		// RequestDispatcher  dispather = request.getRequestDispatcher(target_url);
		// dispatcher.forward(request,response);
		
		return "forward:/WEB-INF/views/return/void.jsp"; //OK
//		return "forward:/return/void"; OK
//		return "forward:void";       OK
//		return "forward:http://naver.com";   XX: 리다이렉트와 다르게 외부 URL 허용하지 않는다.
											// return/http://naver.com  이런식으로 base가 깔린다.
//		return "forward:/board/basicGet" // 같은 웹앱 내에 있는 다른 컨트롤러 핸들러에 떠넘길 수 있다.
	}//returnForward

-일반 참조타입의 자바객체를 반환

  1. Json/xml 로 응답해야한다.
  2. 이를 위한 라이브러리가 필요하다.
  3. @ResponseBody 반드시 이 어노테이션이 필요한가
    => 제외할시 요청받은 값들은 공유속성에 속해지고 return 값은 URI로 자동결정이 된다.
    => 포함할시 반환타입을 바디의 내용으로 추가

pom.xml에 어떤 것을 추가해줄지

Json 은 "연관배열" / '자바스크립트 때 배움'
xml 은 태그형식으로 하위태그에 들어감

자바객체를 리턴타입으로 하는경우는 왜 일까요?
JSON형식의 연관배열로 데이터를 전달하기 위해서말고 더 구체적으로 다른 이유도 알아보자꾸나

	@GetMapping("/ResponseBody")
	public @ResponseBody SampleDTO  returnResponseBody(
				@NonNull @RequestParam("name") String NAME,
				@NonNull @RequestParam("age") Integer AGE
			) {
		log.trace("returnResponseBody({},{}) invoked.", NAME, AGE);
		SampleDTO dto = new SampleDTO();
		dto.setName(NAME);
		dto.setAge(AGE);
		
		log.info("\t + dto: {}", dto);
		
		// 반환할 자바객체를, 표현가능한 문서형식(예: JSON/XML)로 변환해서, 응답메시지의 바디에 넣어서 
		//전달해야 한다. 그래야 406(Not acceptable)오류가 발생하지 않는다.
		// 하지만, 이를 위해서는 ,소위 "변환" 라이브러리 (==Data-binding libraries)가 필요하다.
		// Spring 에서 가장 많이 사용하는 Data-binding 라이브러리로 Jackson 계열의 라이브러리를 사용한다. 
		// 이 라이브러리를 pom.xml 파일에 추가해준다. (자바객체 -> JSON/XML 로 변환)
		return dto;				// ***: 일반 참조타입의 자바객체를 반환하는 경우
	}//returnResponseBody

-ResponseEntity<~~>

-응답에 바디에 들어갈 타입을 제네릭으로 정해서 보내겠다.
-이 타입을 통해 응답 메세지에 대한 바디 내용과 헤더, 상태 등 통제가능.

자바안에서 자바 문자를 JSON으로 바꿔주는 라이브러리 Gson

  • Gson library 의 용도 *
    (1) 자바객체 ---> Serialize ---> JSON 문자열로 변환 (***)
    (2) JSON 문자열 --> De-serialize --> 자바객체로 변환
	@GetMapping("/ResponseEntity")
	public ResponseEntity<String> returnResponseEntity() {
		log.debug("returnResponseEntity() invoked.");

//		String json = "{'name':'koo','age':23}";

//		SampleDTO dto = new SampleDTO();
//		dto.setName("Koo");
//		dto.setAge(23);
		
		
		Gson gson = new Gson();
		Person person = new Person();
		String json = gson.toJson(person);
		log.info("\t + json:{}",json);
		
		HttpHeaders headers= new HttpHeaders();
		headers.add("Content-Type", "application/json; charset-utf8");
		
		return new ResponseEntity<>(json, headers, HttpStatus.OK);
		
	}//returnResponseEntity


파일업로드를 처리

jsp

<html>
  <head>
    <title>File Upload</title>
  </head>
  <body>
    <h1>File Upload</h1>

    <P> /WEB-INF/views/fileupload/page.jsp </P>
				처음은 넷켓으로 보냈엇음 7000번포트로 
    <form action="/fileupload/doit" method="POST" enctype="multipart/form-data">
      <div>Name: <input type="text" size="30" name="myName"></div>
      <div>Age: <input type="text" size="30" name="myAge"></div>
      
      
      <div>1. <input type="file" name="files" /></div>
      <div>2. <input type="file" name="files" /></div>
      <div>3. <input type="file" name="files" /></div>
      <div>4. <input type="file" name="files" /></div>
      <div>5. <input type="file" name="files" /></div>

      <br>
      
      <div><input type="submit" value = "upload" /></div>
    </form>
  </body>
</html>

- 넷켓을 통해 파일 업로드 및 정보를 보냈을때 결과

- 위의 정보를 받기위해는 Spring MVC에서는 파일 업로드를 처리할 수 있는 라이브러리가 있어야한다.

- 라이브러리에 있는 클래스 multipartResolver를 Bean으로 추가해준다.

  • beans:property로 설정할 속성들은 CommonsFileUploadSupport클래스에 set~~메서드로 해당 클래스에 정의되어있다.


servlet-context.xml :


	<beans:bean 
	id="multipartResolver" 
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
	
	<beans:property name="defaultEncoding" value="utf8"/>
	<beans:property name="maxInMemorySize" value="10485760"/>
	<beans:property name="maxUploadSize" value="1048"/>
	<beans:property name="maxUploadSizePerFile" value="20971520"/>
	<beans:property name="preserveFilename" value="true"/>
	<beans:property name="uploadTempDir" value="file:///C:/Temp"/>

	</beans:bean>
	

파일 시스템에 파일을 저장하려면, 아래의 2단계 절차에 따라 하는것이 안정하다.
(1) 임시폴더에 쓰기작업이 끝나면
(2) 최종 저장폴더로 임시저장파일을 이동 (move) 시킨다.

왜? 파일로 데이터를 쓰는 중간에 이 파일을 읽어갈 수도 있다.
==> 불완전하게 파일데이터를 읽어가게된다.
-쓸때는 파일락 걸고 쓰고나서는 파일락을 해제해줘야한다.

-업로드 하는 메소드

  1. transferTo 수신된 파일을 지정된 대상 파일 또는 경로로 전송한다.

	@PostMapping("/doit")
	public void DoFileUpload(
			String myName, String myAge ,
//			MultipartFile[] files // ok: 배열로 달라! 야는 1개밖에 전달이안됌 왜일까?
//			List<MultipartFile> files // ok:  리스트 컬렉션
//			Set<MultipartFile> files  // xx: Set 으로는 안된다.
//			HashSet<MultipartFile> files // 절반성공 요소가 생성되지 않는다.
//			@RequestParam("files") Set<MultipartFile> files  // ok 성공
			@RequestParam("files") List<MultipartFile> files // 당근 성공
	) throws IllegalStateException, IOException {
		log.trace("DoFileUpload() invoked.");
		
		log.info("\t + files: {}", files);
		log.info("\t + myName: {} / myAge: {}", myName,myAge);
		
		String targetDir = "C:/Temp/upload/";
		
		for(MultipartFile file:files) {
			log.info("\t ====================");
			log.info("\t+1. Name: {}", file.getName());
			log.info("\t+2. OriginalFilename: {}", file.getOriginalFilename());
			log.info("\t+3. ContentType: {}", file.getContentType());
			log.info("\t+4. Empty: {}", file.isEmpty());
			log.info("\t+5. Size: {}", file.getSize());
			log.info("\t+6. Resource: {}", file.getResource());
			
			String targetFile = targetDir +  file.getOriginalFilename();
			log.info("\t+7. targetFile:{}",targetFile);
			
			file.transferTo(new File(targetFile));
		}// for 
	}// DoFileUpload

멀티파트파일에 실제 파일저장 메소드


뜬금 확인점

-servlet-context.xml에 view-controller 태그추가와 @Controller 차이점

-view-controller 태그추가는 show RequestMapping에 표시되지않음.
@Controller을 이용하면 추가 표시된다.

profile
일단 흐자

0개의 댓글