ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] spread sheet 연동하기
    Backend/개발 2021. 7. 21. 01:32
    반응형

    TIL 29일차

    TODO

    구글 스프레드시트 파일 java api 찾아서 값 읽어오는거 구현하기

    필요 배경

    마요 대회때마다 구글 스프레드시트에 정리하시는데 구글에 들어가서 보는것 보다 홈페이지에서 확인하면 좋을 것 같다.

    팀명, 팀코드, 팀원

    대회 일정대회 결과

    순위 등등
    다 연동되게 하는것이 목표 ..!

    저번에 하려는데 뭔가 자꾸 실패했음 ㅠ

    일단 스프링말고라도 java api 찾아서 스프레드 시트 연동하기를 해봐야겠다.

     

    1. GCP api 라이브러리 google sheet api 활성화, drive api 활성화
    2. 사용자 인증 정보 - oauth2 클라이언트 id - 웹 클라이언
    3. 리다이렉션 주소는 /Callback
    4. 생성된 json파일 다운로드
    5. pom.xml에 디펜던시 추가 - 링크 참고
    6. 서비스 계정 생성 - sheet에 계정 권한 추가

     

    @Value annotation

    resoucre 폴더 하위에 application.property 또는 application.yml파일에 적은 property값을 불러온다.

    # application.yml
      api:
        google:
          appName: mayo-sheet
    • import org.springframework.beans.factory.annotation.Value;
    • @Value("${api.google.appName}")

    스프링 컨테이너 내부에서 빈을 등록할때 @Value()안에 맞는 값을 application.yml에서 찾아 넣어주기 때문에, bean으로 등록되지 않은 클래스에서 호출하면 null값이 들어올 수 있다.

    @Value("${api.google.appName}")
    private String appName;
    
    @Test
    public void sheet_테스트() {
    
    assertThat(appName).isEqualTo("mayo-sheet");
    }

    간단하게 String appName=""으로 하드코딩 하지 않은 이유는 나중에 spreadsheet 이름이나 설정값이 달라질 때 yml파일만 바꿔주기 위함이고, 또한 public으로 올리면 안되는 정보가 있다면 비공개 yml파일에 값을 저장해 불러오면 보호되기 때문이다. 그리고 static 변수에는 value 값이 injection되지 않는다.
    정 static으로 하고싶다면 클래스를 @Component로 bean으로 만든 후 setter를 이용해 주입하면 된다고 한다. - 블로그 내용 참고

    여러 블로그 보면서 해도 이해가 잘 안돼서 그냥 공식 문서로 봤다.

     

    Java Quickstart Sheets API

    https://developers.google.com/sheets/api/quickstart/java

    getcredential test

    @Test
    public void token_받아오기() throws IOException {
        File initialFile = new File("src/main/resources/" + CREDENTIALS_FILE_PATH);
        InputStream in = new FileInputStream(initialFile);
    
        if (in == null) {
                throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
    
        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
              new NetHttpTransport(), JSON_FACTORY, clientSecrets, SCOPES)
              .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
              .setAccessType("offline")
              .build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8080).build();
        Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    
        System.out.println(credential);
    }

    token이 받아와 만들어지는지 보기 위해 테스트코드로 먼저 돌려봤다. 맨 처음 코드를 실행하니 google login redirect url이 나왔다

    그리고나서는 credential이 저장되어있어서 더이상 인증을 하지 않았다.
    이 credential을 그대로 서버에 저장해도 되는건지, 매번 맨 처음에는 인증받는 화면을 보여줘야 사용할 수 있는건지 잘 모르겠다.

    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String TOKENS_DIRECTORY_PATH = "tokens";
    private static final List<String> SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS_READONLY);
    1. jacksonfactory
      JacksonFactory는 json 라이브러리를 구현하는 클래스다. getDefaultInstance는 글로벌 스레드 동기화가 된 인스턴스를 반환해준다
      [출처] Google Calendar API 1. 캘린더 정보 가져오기|작성자 혜영
    2. token
      /tokens 폴더에 StoredCredential파일이 생성됐다.

    getCredential함수로 만들고 credential파일 경로가 잘못되거나 값이 잘못되었을 경우 에러가 나는지 확인해보았다.

    json파일경로 잘못되었을 경우

    @Test
    public void getCredentialFile_error(){
    
        // given
        // 임의로 path 변경함
        CREDENTIALS_FILE_PATH +="aa";
    
        // when
        FileNotFoundException e = Assertions.assertThrows(FileNotFoundException.class,()->{
            new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
                .setApplicationName(appName)
                .build();
        });
        // then
        assertThat(e.getMessage()).contains("No such file or directory");
    
    }

    address in use

    BindException이 생기는데 이유랑 해결방법을 잘 못찾겠다.

    GCP default 뭐 어쩌고도 인텔리제이 팝업메세지로 뜨던데..
    더찾아봐야겠다 2탄에 계쏙

    마크다운 코드 하이라이트 적용해야겠다

    출처
    - @Value https://sas-study.tistory.com/273
    - https://www.baeldung.com/convert-file-to-input-stream
    - Value와 Static https://thingsthis.tistory.com/326
    - Calendar정보 가져오기 jacksonfactory

    댓글

Designed by Tistory.