Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CH6. 웹 앱 개발 예약 서비스 4 #17

Open
KeonHee opened this issue Aug 29, 2021 · 0 comments
Open

CH6. 웹 앱 개발 예약 서비스 4 #17

KeonHee opened this issue Aug 29, 2021 · 0 comments

Comments

@KeonHee
Copy link
Contributor

KeonHee commented Aug 29, 2021

1. Interceptor

Interceptor?

image

작성법

  1. Interceptor 구현체 작성
    1. org.springframework.web.servlet.HandlerInterceptor 인터페이스를 구현합니다.
    2. org.springframework.web.servlet.handler.HandlerInterceptorAdapter 클래스를 상속받습니다.
  2. 설정 추가
    • Java Config를 사용한다면, WebMvcConfigurerAdapter가 가지고 있는 addInterceptors 메소드를 오버라이딩하고 등록하는 과정을 거칩니다.
    • xml 설정을 사용한다면, mvc:interceptors 요소에 인터셉터를 등록합니다.

실습 코드

  • HandlerInterceptorAdapter 상속 클래스 작성
package kr.or.connect.guestbook.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class LogInterceptor extends HandlerInterceptorAdapter{

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println(handler.toString() + " 가 종료되었습니다.  " + modelAndView.getViewName() + "을 view로 사용합니다.");
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println(handler.toString() + " 를 호출했습니다.");
		return true;
	}	
}
  • 설정 추가(Java config 방식)
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LogInterceptor());
}

2. Argument Resolver

Argument Resolver?

  • 컨트롤러의 메소드의 인자로 사용자가 임의의 값을 전달하는 방법을 제공하고자 할 때 사용됩니다.
  • 예를 들어, 세션에 저장되어 있는 값 중 특정 이름의 값을 메소드 인자로 전달합니다.

작성법

  1. HandlerMethodArgumentResolver 구현 클래스 작성
  • org.springframework.web.method.support.HandlerMethodArgumentResolver를 구현한 클래스를 작성합니다.
  • supportsParameter메소드를 오버라이딩 한 후, 원하는 타입의 인자가 있는지 검사한 후 있을 경우 true가 리턴되도록 합니다.
  • resolveArgument메소드를 오버라이딩 한 후, 메소드의 인자로 전달할 값을 리턴합니다.
  1. 설정 추가
  • Java Config에 설정하는 방법
    • WebMvcConfigurerAdapter를 상속받은 Java Config 파일에서 addArgumentResolvers 메소드를 오버라이딩 한 후 원하는 아규먼트 리졸버 클래스 객체를 등록합니다.
  • xml 파일에 설정하는 방법
 <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="아규먼트리졸버클래스"></bean>      
        </mvc:argument-resolvers>
    </mvc:annotation-driven>

실습 코드

package kr.or.connect.guestbook.argumentresolver;

import java.util.HashMap;
import java.util.Map;

public class HeaderInfo {
	private Map<String, String> map;
	
	public HeaderInfo() {
		map = new HashMap<>();
	}

	public void put(String name, String value) {
		map.put(name,  value);
	}
	
	public String get(String name) {
		return map.get(name);
	}
}
package kr.or.connect.guestbook.argumentresolver;

import java.util.Iterator;

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class HeaderMapArgumentResolver implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.getParameterType() == HeaderInfo.class;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

		HeaderInfo headerInfo = new HeaderInfo();
		
		Iterator<String> headerNames = webRequest.getHeaderNames();
		while(headerNames.hasNext()) {
			String headerName = headerNames.next();
			String headerValue = webRequest.getHeader(headerName);
//			System.out.println(headerName + " , " + headerValue);
			headerInfo.put(headerName, headerValue);
		}		
		return headerInfo;
	}
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    	System.out.println("아규먼트 리졸버 등록..");
	argumentResolvers.add(new HeaderMapArgumentResolver());
}
@GetMapping(path="/list")
public String list(@RequestParam(name="start", required=false, defaultValue="0") int start,
					   ModelMap model, @CookieValue(value="count", defaultValue="1", required=true) String value,
                                             HttpServletRequest request,
					   HttpServletResponse response,
					   HeaderInfo headerInfo) {
   // request 에서 header 값을 가져와서 사용할 수 있으나
   // argument resovler에서 HeaderInfo 객체로 만들어 줌으로써 더 편하고 명확하게 사용할 수 있다
    System.out.println("-----------------------------------------------------");
    System.out.println(headerInfo.get("user-agent"));
    System.out.println("-----------------------------------------------------");
}

3. Logging

로깅(Logging)이란?

  • 정보를 제공하는 일련의 기록인 로그(log)를 생성하도록 시스템을 작성하는 활동
  • 프린트 줄 넣기(printlining)는 간단한, 보통은 일시적인, 로그를 생성하기만 한다.
  • 시스템 설계자들은 시스템의 복잡성 때문에 로그를 이해하고 사용해야 한다.
  • 로그가 제공하는 정보의 양은, 이상적으로는 프로그램이 실행되는 중에도, 설정 가능해야 한다.
  • 일반적으로 로그 기록의 이점
    • 로그는 재현하기 힘든 버그에 대한 유용한 정보를 제공할 수 있다.
    • 로그는 성능에 관한 통계와 정보를 제공할 수 있다.
    • 설정이 가능할 때, 로그는 예기치 못한 특정 문제들을 디버그하기 위해, 그 문제들을 처리하도록 코드를 수정하여 다시 적용하지(redeploy) 않아도, 일반적인 정보를 갈무리할 수 있게 한다.

로그를 출력하는 방법

  • System.out.print() 이용
  • 로깅 라이브러리 이용

로그 라이브러리 종류

  • java.util.logging
    • JDK 1.4부터 포함된 표준 로깅 API
    • 별도 라이브러리 추가 불필요
    • 기능이 많이 부족해 다른 로그 라이브러리를 더 많이 사용
  • Apache Commons logging
    • 아파치 재단에 Commons 라이브러리 중에 로그 출력을 제공하는 라이브러리
  • Log4j
    • 아파치 제단에서 제공하며 가장 많이 사용되는 로깅 라이브러리
  • Logback
    • Log4j를 개발한 Ceki Gulcu가 Log4j의 단점 개선 및 기능을 추가하여 개발한 로깅 라이브러리

System.out.println()을 자주 이용하게 되면 웹 어플리케이션의 속도는 상당히 느려집니다. 운영 중인 서버에서는 System.out.println()으로 로그를 출력하면 안 됩니다. 이번 시간에 소개된 로거 객체 등을 이용해 로그를 남겨야 속도상에 문제가 발생하지 않습니다. 이번 시간에 소개한 로그 라이브들에 대해 찾아보시고 장단점에 대해 알아보세요.

System 메소드를 사용하면 system 단위로 global lock이 걸리기 때문

SLF4J 사용하기

@Slf4j 어노테이션으로 사용하기

  • application.yaml
logging:
  file:
    name: ${user.dir}/log/test.log  # 로깅 파일 위치이다.
    max-history: 7 # 로그 파일 삭제 주기이다. 7일 이후 로그는 삭제한다.
    max-size: 10MB  # 로그 파일 하나당 최대 파일 사이즈이다.
  level:  # 각 package 별로 로깅 레벨을 지정할 수 있다.
    com.project.study : error
    com.project.study.controller : debug
  • 설정
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
  • 어노테이션을 사용했을 때 장점?
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;

/// 생략 ///
Logger log = Logger.getLogger(this.getClass());
/// 생략 ///
log.info("blah blah log")
  • 예시
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@Slf4j
public class TestController {
    @GetMapping("/")
    public String String(String str){
        try {
            str.toString();
        } catch (NullPointerException e){
            log.trace("가장 디테일한 로그");
            log.warn("경고");
            log.info("정보성 로그");
            log.debug("디버깅용 로그");
            log.error("에러",e);
        }
        return "test";
    }
}

4. File upload & download

Multipart

  • 웹 클라이언트가 요청을 보낼 때 HTTP프로토콜의 바디 부분에 데이터를 여러 부분으로 나눠서 보내는 것
  • 보통 파일을 전송할 때 사용
    image
  • HttpServletRequest는 파일 업로드를 지원 안 함
    • HttpServletRequest는 웹 클라이언트가 전달하는 Multipart데이터를 쉽게 처리하는 메소드를 제공하지 않습니다.
    • 서블릿에서 파일 업로드를 처리하려면 별도의 라이브러리를 사용해야 한다.
    • 대표적인 라이브러리가 아파치 재단의 commons-fileupload입니다.
  • Spring MVC에서의 파일 업로드
    • Spring MVC에서 파일을 업로드 하려면 몇 가지 라이브러리와 설정을 추가해야 합니다.
    • commons-fileupload, commons-io 라이브러리 추가
    • MultipartResolver Bean 추가

업로드 구현

다운로드 구현

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant