빌드 승인 콜백 핸들러

이 문서에서는 Google Tasks API를 사용하여 사용자의 할 일을 표시하는 샘플 웹 애플리케이션을 통해 Java Servlet을 사용하여 OAuth 2.0 승인 콜백 핸들러를 구현하는 방법을 설명합니다. 샘플 애플리케이션은 먼저 사용자의 Google Tasks에 액세스할 수 있는 권한을 요청한 다음 기본 할 일 목록에 사용자의 할 일을 표시합니다.

잠재고객

이 문서는 Java 및 J2EE 웹 애플리케이션 아키텍처에 익숙한 사용자를 대상으로 합니다. OAuth 2.0 승인 흐름에 대한 지식이 있으면 좋습니다.

목차

완전히 작동하는 샘플을 만들려면 다음 단계를 따라야 합니다.

web.xml 파일에서 서블릿 매핑 선언

애플리케이션에서는 다음과 같은 두 가지 servlet을 사용합니다.

  • PrintTasksTitlesServlet (/에 매핑됨): 사용자 인증을 처리하고 사용자의 작업을 표시하는 애플리케이션의 진입점입니다.
  • OAuthCodeCallbackHandlerServlet (/oauth2callback에 매핑됨): OAuth 승인 엔드포인트의 응답을 처리하는 OAuth 2.0 콜백

다음은 이러한 두 서블릿을 애플리케이션의 URL에 매핑하는 web.xml 파일입니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 <servlet>
   <servlet-name>PrintTasksTitles</servlet-name>
   <servlet-class>com.google.oauthsample.PrintTasksTitlesServlet</servlet-class>
 </servlet>

 <servlet-mapping>
   <servlet-name>PrintTasksTitles</servlet-name>
   <url-pattern>/</url-pattern>
 </servlet-mapping>

 <servlet>
   <servlet-name>OAuthCodeCallbackHandlerServlet</servlet-name>
   <servlet-class>com.google.oauthsample.OAuthCodeCallbackHandlerServlet</servlet-class>
 </servlet>

 <servlet-mapping>
   <servlet-name>OAuthCodeCallbackHandlerServlet</servlet-name>
   <url-pattern>/oauth2callback</url-pattern>
 </servlet-mapping>

</web-app>
/WEB-INF/web.xml 파일

시스템의 사용자를 인증하고 작업에 액세스할 수 있는 권한을 요청합니다.

사용자는 PrintTaskListsTitlesServlet 서블릿에 매핑된 루트 '/' URL을 통해 애플리케이션에 진입합니다. 이 servlet에서는 다음 작업이 실행됩니다.

  • 사용자가 시스템에서 인증되었는지 확인합니다.
  • 사용자가 인증되지 않은 경우 인증 페이지로 리디렉션됩니다.
  • 사용자가 인증되면 데이터 저장소에 이미 새로고침 토큰이 있는지 확인합니다. 이는 아래의 OAuthTokenDao에서 처리합니다. 사용자의 스토어에 갱신 토큰이 없는 경우 이는 사용자가 아직 할 일 액세스 권한을 애플리케이션에 부여하지 않았음을 의미합니다. 이 경우 사용자는 Google의 OAuth 2.0 승인 엔드포인트로 리디렉션됩니다.
다음은 이를 구현하는 방법입니다.

package com.google.oauthsample;

import ...

/**
 * Simple sample Servlet which will display the tasks in the default task list of the user.
 */
@SuppressWarnings("serial")
public class PrintTasksTitlesServlet extends HttpServlet {

  /**
   * The OAuth Token DAO implementation, used to persist the OAuth refresh token.
   * Consider injecting it instead of using a static initialization. Also we are
   * using a simple memory implementation as a mock. Change the implementation to
   * using your database system.
   */
  public static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the current user
    // This is using App Engine's User Service but you should replace this to
    // your own user/login implementation
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();

    // If the user is not logged-in it is redirected to the login service, then back to this page
    if (user == null) {
      resp.sendRedirect(userService.createLoginURL(getFullRequestUrl(req)));
      return;
    }

    // Checking if we already have tokens for this user in store
    AccessTokenResponse accessTokenResponse = oauthTokenDao.getKeys(user.getEmail());

    // If we don't have tokens for this user
    if (accessTokenResponse == null) {
      OAuthProperties oauthProperties = new OAuthProperties();
      // Redirect to the Google OAuth 2.0 authorization endpoint
      resp.sendRedirect(new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
          OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
              .getScopesAsString()).build());
      return;
    }
  }

  /**
   * Construct the request's URL without the parameter part.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getFullRequestUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = req.getServletPath();
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo + queryString;
  }
}
PrintTasksTitlesServlet.java 파일

참고: 위의 구현은 일부 App Engine 라이브러리를 사용합니다. 이는 단순화를 위해 사용됩니다. 다른 플랫폼용으로 개발하는 경우 사용자 인증을 처리하는 UserService 인터페이스를 자유롭게 다시 구현할 수 있습니다.

애플리케이션은 DAO를 사용하여 사용자의 승인 토큰을 유지하고 액세스합니다. 다음은 이 샘플에서 사용되는 인터페이스(OAuthTokenDao) 및 모의(메모리 내) 구현(OAuthTokenDaoMemoryImpl)입니다.

package com.google.oauthsample;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;

/**
 * Allows easy storage and access of authorization tokens.
 */
public interface OAuthTokenDao {

  /**
   * Stores the given AccessTokenResponse using the {@code username}, the OAuth
   * {@code clientID} and the tokens scopes as keys.
   *
   * @param tokens The AccessTokenResponse to store
   * @param userName The userName associated wit the token
   */
  public void saveKeys(AccessTokenResponse tokens, String userName);

  /**
   * Returns the AccessTokenResponse stored for the given username, clientId and
   * scopes. Returns {@code null} if there is no AccessTokenResponse for this
   * user and scopes.
   *
   * @param userName The username of which to get the stored AccessTokenResponse
   * @return The AccessTokenResponse of the given username
   */
  public AccessTokenResponse getKeys(String userName);
}
OAuthTokenDao.java 파일
package com.google.oauthsample;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
...

/**
 * Quick and Dirty memory implementation of {@link OAuthTokenDao} based on
 * HashMaps.
 */
public class OAuthTokenDaoMemoryImpl implements OAuthTokenDao {

  /** Object where all the Tokens will be stored */
  private static Map<String, AccessTokenResponse> tokenPersistance = new HashMap<String, AccessTokenResponse>();

  public void saveKeys(AccessTokenResponse tokens, String userName) {
    tokenPersistance.put(userName, tokens);
  }

  public AccessTokenResponse getKeys(String userName) {
    return tokenPersistance.get(userName);
  }
}
OAuthTokenDaoMemoryImpl.java 파일

또한 애플리케이션의 OAuth 2.0 사용자 인증 정보는 속성 파일에 저장됩니다. 또는 Java 클래스 중 하나의 어딘가에 상수로 간단히 포함할 수도 있습니다. 여기서는 샘플에서 사용되는 OAuthProperties 클래스와 oauth.properties 파일을 보여줍니다.

package com.google.oauthsample;

import ...

/**
 * Object representation of an OAuth properties file.
 */
public class OAuthProperties {

  public static final String DEFAULT_OAUTH_PROPERTIES_FILE_NAME = "oauth.properties";

  /** The OAuth 2.0 Client ID */
  private String clientId;

  /** The OAuth 2.0 Client Secret */
  private String clientSecret;

  /** The Google APIs scopes to access */
  private String scopes;

  /**
   * Instantiates a new OauthProperties object reading its values from the
   * {@code OAUTH_PROPERTIES_FILE_NAME} properties file.
   *
   * @throws IOException IF there is an issue reading the {@code propertiesFile}
   * @throws OauthPropertiesFormatException If the given {@code propertiesFile}
   *           is not of the right format (does not contains the keys {@code
   *           clientId}, {@code clientSecret} and {@code scopes})
   */
  public OAuthProperties() throws IOException {
    this(OAuthProperties.class.getResourceAsStream(DEFAULT_OAUTH_PROPERTIES_FILE_NAME));
  }

  /**
   * Instantiates a new OauthProperties object reading its values from the given
   * properties file.
   *
   * @param propertiesFile the InputStream to read an OAuth Properties file. The
   *          file should contain the keys {@code clientId}, {@code
   *          clientSecret} and {@code scopes}
   * @throws IOException IF there is an issue reading the {@code propertiesFile}
   * @throws OAuthPropertiesFormatException If the given {@code propertiesFile}
   *           is not of the right format (does not contains the keys {@code
   *           clientId}, {@code clientSecret} and {@code scopes})
   */
  public OAuthProperties(InputStream propertiesFile) throws IOException {
    Properties oauthProperties = new Properties();
    oauthProperties.load(propertiesFile);
    clientId = oauthProperties.getProperty("clientId");
    clientSecret = oauthProperties.getProperty("clientSecret");
    scopes = oauthProperties.getProperty("scopes");
    if ((clientId == null) || (clientSecret == null) || (scopes == null)) {
      throw new OAuthPropertiesFormatException();
    }
  }

  /**
   * @return the clientId
   */
  public String getClientId() {
    return clientId;
  }

  /**
   * @return the clientSecret
   */
  public String getClientSecret() {
    return clientSecret;
  }

  /**
   * @return the scopes
   */
  public String getScopesAsString() {
    return scopes;
  }

  /**
   * Thrown when the OAuth properties file was not at the right format, i.e not
   * having the right properties names.
   */
  @SuppressWarnings("serial")
  public class OAuthPropertiesFormatException extends RuntimeException {
  }
}
OAuthProperties.java 파일

다음은 애플리케이션의 OAuth 2.0 사용자 인증 정보가 포함된 oauth.properties 파일입니다. 아래 값은 직접 변경해야 합니다.

# Client ID and secret. They can be found in the APIs console.
clientId=1234567890.apps.googleusercontent.com
clientSecret=aBcDeFgHiJkLmNoPqRsTuVwXyZ
# API scopes. Space separated.
scopes=https://www.googleapis.com/auth/tasks
oauth.properties 파일

OAuth 2.0 클라이언트 ID 및 클라이언트 비밀번호는 애플리케이션을 식별하고 Tasks API가 애플리케이션에 정의된 필터 및 할당량 규칙을 적용할 수 있도록 허용합니다. 클라이언트 ID와 보안 비밀은 Google API 콘솔에서 확인할 수 있습니다. 콘솔에 있으면 다음을 실행해야 합니다.

  • 프로젝트를 만들거나 선택합니다.
  • 서비스 목록에서 Tasks API 상태를 사용으로 전환하여 Tasks API를 사용 설정합니다.
  • API 액세스에서 아직 OAuth 2.0 클라이언트 ID가 없는 경우 만듭니다.
  • 프로젝트의 OAuth 2.0 코드 콜백 핸들러 URL이 리디렉션 URI에 등록/허용 목록에 추가되어 있는지 확인합니다. 예를 들어 이 샘플 프로젝트에서 웹 애플리케이션이 https://www.example.com 도메인에서 제공되는 경우 https://www.example.com/oauth2callback을 등록해야 합니다.

API 콘솔의 리디렉션 URI
API 콘솔의 리디렉션 URI

Google 승인 엔드포인트에서 승인 코드 리슨

사용자가 아직 애플리케이션이 할 일 목록에 액세스하도록 승인하지 않았으므로 Google의 OAuth 2.0 승인 엔드포인트로 리디렉션된 경우 사용자에게 애플리케이션이 할 일 목록에 액세스하도록 승인해 달라는 Google의 승인 대화상자가 표시됩니다.

Google 승인 대화상자
Google 승인 대화상자

액세스 권한을 부여하거나 거부한 후 사용자는 Google 승인 URL을 구성할 때 리디렉션/콜백으로 지정된 OAuth 2.0 코드 콜백 핸들러로 다시 리디렉션됩니다.

new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
      OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
          .getScopesAsString()).build()

OAuth 2.0 코드 콜백 핸들러인 OAuthCodeCallbackHandlerServlet은 Google OAuth 2.0 엔드포인트의 리디렉션을 처리합니다. 처리해야 할 두 가지 사례가 있습니다.

  • 사용자가 액세스를 승인함: 요청을 파싱하여 URL 매개변수에서 OAuth 2.0 코드를 가져옵니다.
  • 사용자가 액세스를 거부함: 사용자에게 메시지를 표시합니다.

package com.google.oauthsample;

import ...

/**
 * Servlet handling the OAuth callback from the authentication service. We are
 * retrieving the OAuth code, then exchanging it for a refresh and an access
 * token and saving it.
 */
@SuppressWarnings("serial")
public class OAuthCodeCallbackHandlerServlet extends HttpServlet {

  /** The name of the Oauth code URL parameter */
  public static final String CODE_URL_PARAM_NAME = "code";

  /** The name of the OAuth error URL parameter */
  public static final String ERROR_URL_PARAM_NAME = "error";

  /** The URL suffix of the servlet */
  public static final String URL_MAPPING = "/oauth2callback";

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the "error" URL parameter
    String[] error = req.getParameterValues(ERROR_URL_PARAM_NAME);

    // Checking if there was an error such as the user denied access
    if (error != null && error.length > 0) {
      resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "There was an error: \""+error[0]+"\".");
      return;
    }
    // Getting the "code" URL parameter
    String[] code = req.getParameterValues(CODE_URL_PARAM_NAME);

    // Checking conditions on the "code" URL parameter
    if (code == null || code.length == 0) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "The \"code\" URL parameter is missing");
      return;
    }
  }

  /**
   * Construct the OAuth code callback handler URL.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getOAuthCodeCallbackHandlerUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = URL_MAPPING;
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo;
  }
}
OAuthCodeCallbackHandlerServlet.java 파일

승인 코드를 갱신 토큰 및 액세스 토큰으로 교환

그런 다음 OAuthCodeCallbackHandlerServlet이 Auth 2.0 코드를 갱신 및 액세스 토큰으로 교환하고, 데이터 스토어에 유지한 후 사용자를 PrintTaskListsTitlesServlet URL로 다시 리디렉션합니다.

아래 파일에 추가된 코드는 구문 강조 표시되어 있고 이미 있는 코드는 비활성화되어 있습니다.

package com.google.oauthsample;

import ...

/**
 * Servlet handling the OAuth callback from the authentication service. We are
 * retrieving the OAuth code, then exchanging it for a refresh and an access
 * token and saving it.
 */
@SuppressWarnings("serial")
public class OAuthCodeCallbackHandlerServlet extends HttpServlet {

  /** The name of the Oauth code URL parameter */
  public static final String CODE_URL_PARAM_NAME = "code";

  /** The name of the OAuth error URL parameter */
  public static final String ERROR_URL_PARAM_NAME = "error";

  /** The URL suffix of the servlet */
  public static final String URL_MAPPING = "/oauth2callback";
/** 콜백을 처리한 후 사용자를 리디렉션할 URL입니다. 리디렉션할 수 있는 URL이 여러 개인 경우 사용자를 Google 승인 URL로 리디렉션하기 전에 이를 쿠키에 저장하는 것이 좋습니다. */ public static final String REDIRECT_URL = "/"; /** OAuth 토큰 DAO 구현입니다. 정적 초기화를 사용하는 대신 삽입하는 것이 좋습니다. 또한 간단한 메모리 구현을 * 모의로 사용합니다. 데이터베이스 시스템을 사용하도록 구현을 변경합니다. */ public static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the "error" URL parameter
    String[] error = req.getParameterValues(ERROR_URL_PARAM_NAME);

    // Checking if there was an error such as the user denied access
    if (error != null && error.length > 0) {
      resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "There was an error: \""+error[0]+"\".");
      return;
    }

    // Getting the "code" URL parameter
    String[] code = req.getParameterValues(CODE_URL_PARAM_NAME);

    // Checking conditions on the "code" URL parameter
    if (code == null || code.length == 0) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "The \"code\" URL parameter is missing");
      return;
    }
// 수신 요청 URL 생성 String requestUrl = getOAuthCodeCallbackHandlerUrl(req); // 코드를 OAuth 토큰으로 교환합니다. AccessTokenResponse accessTokenResponse = exchangeCodeForAccessAndRefreshTokens(code[0], requestUrl); // 현재 사용자 가져오기 // App Engine의 사용자 서비스를 사용하지만 이를 자체 사용자/로그인 구현으로 대체해야 합니다. UserService userService = UserServiceFactory.getUserService(); String email = userService.getCurrentUser().getEmail(); // 토큰 저장 oauthTokenDao.saveKeys(accessTokenResponse, email); resp.sendRedirect(REDIRECT_URL); }
  /**
   * Construct the OAuth code callback handler URL.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getOAuthCodeCallbackHandlerUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = URL_MAPPING;
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo;
  }
/** * 주어진 코드를 교환 및 갱신 토큰으로 교환합니다. * * @param code 승인 서비스에서 다시 가져온 코드입니다. * @param currentUrl 콜백의 URL입니다. * @param oauthProperties OAuth 구성을 포함하는 객체입니다. * @return 액세스 토큰과 새로고침 토큰을 모두 포함하는 객체입니다. * @throws IOException */ public AccessTokenResponse exchangeCodeForAccessAndRefreshTokens(String code, String currentUrl) throws IOException { HttpTransport httpTransport = new NetHttpTransport(); JacksonFactory jsonFactory = new JacksonFactory(); // oauth 구성 파일 로드 OAuthProperties oauthProperties = new OAuthProperties(); return new GoogleAuthorizationCodeGrant(httpTransport, jsonFactory, oauthProperties .getClientId(), oauthProperties.getClientSecret(), code, currentUrl).execute(); } }
OAuthCodeCallbackHandlerServlet.java 파일

참고: 위의 구현은 일부 App Engine 라이브러리를 사용합니다. 이는 단순화를 위해 사용됩니다. 다른 플랫폼용으로 개발하는 경우 사용자 인증을 처리하는 UserService 인터페이스를 자유롭게 다시 구현할 수 있습니다.

사용자의 할 일을 읽고 표시

사용자가 애플리케이션에 작업에 대한 액세스 권한을 부여했습니다. 애플리케이션에는 OAuthTokenDao를 통해 액세스할 수 있는 데이터 저장소에 저장된 갱신 토큰이 있습니다. 이제 PrintTaskListsTitlesServlet servlet은 이러한 토큰을 사용하여 사용자의 작업에 액세스하고 표시할 수 있습니다.

아래 파일에 추가된 코드는 구문 강조 표시되어 있고 이미 있는 코드는 비활성화되어 있습니다.

package com.google.oauthsample;

import ...

/**
 * Simple sample Servlet which will display the tasks in the default task list of the user.
 */
@SuppressWarnings("serial")
public class PrintTasksTitlesServlet extends HttpServlet {

  /**
   * The OAuth Token DAO implementation, used to persist the OAuth refresh token.
   * Consider injecting it instead of using a static initialization. Also we are
   * using a simple memory implementation as a mock. Change the implementation to
   * using your database system.
   */
  public static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the current user
    // This is using App Engine's User Service but you should replace this to
    // your own user/login implementation
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();

    // If the user is not logged-in it is redirected to the login service, then back to this page
    if (user == null) {
      resp.sendRedirect(userService.createLoginURL(getFullRequestUrl(req)));
      return;
    }

    // Checking if we already have tokens for this user in store
    AccessTokenResponse accessTokenResponse = oauthTokenDao.getKeys(user.getEmail());

    // If we don't have tokens for this user
    if (accessTokenResponse == null) {
      OAuthProperties oauthProperties = new OAuthProperties();
      // Redirect to the Google OAuth 2.0 authorization endpoint
      resp.sendRedirect(new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
          OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
              .getScopesAsString()).build());
      return;
    }
// 응답에 사용자의 할 일 목록 제목을 출력합니다. resp.setContentType("text/plain"); resp.getWriter().append("사용자 '+ user.getEmail() + '의 할 일 목록 제목:\n\n"); printTasksTitles(accessTokenResponse, resp.getWriter());
  }

  /**
   * Construct the request's URL without the parameter part.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getFullRequestUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = req.getServletPath();
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo + queryString;
  }
/** * Google Tasks API를 사용하여 기본 할 일 목록에서 사용자의 할 일 목록을 가져옵니다. * * @param accessTokenResponse 액세스 토큰과 갱신 토큰이 포함된 OAuth 2.0 AccessTokenResponse 객체입니다. * @param output 할 일 목록 제목을 작성할 출력 스트림 작성자 * @return 기본 할 일 목록에 있는 사용자의 할 일 제목 목록입니다. * @throws IOException */ public void printTasksTitles(AccessTokenResponse accessTokenResponse, Writer output) throws IOException { // Tasks 서비스를 초기화합니다. HttpTransport transport = new NetHttpTransport(); JsonFactory jsonFactory = new JacksonFactory(); OAuthProperties oauthProperties = new OAuthProperties(); GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource( accessTokenResponse.accessToken, transport, jsonFactory, oauthProperties.getClientId(), oauthProperties.getClientSecret(), accessTokenResponse.refreshToken); Tasks service = new Tasks(transport, accessProtectedResource, jsonFactory); // 초기화된 Tasks API 서비스를 사용하여 할 일 목록 목록을 쿼리합니다. com.google.api.services.tasks.model.Tasks tasks = service.tasks.list("@default").execute(); for (Task task : tasks.items) { output.append(task.title + "\n"); } } }
PrintTasksTitlesServlet.java 파일

사용자에게 작업이 표시됩니다.

사용자의 할 일&#39;
사용자의 할 일

샘플 애플리케이션

이 샘플 애플리케이션의 코드는 여기에서 다운로드할 수 있습니다. 언제든지 확인해 보세요.