├── .gitignore ├── .leanignore ├── README.md ├── pom.xml ├── src └── main │ ├── java │ └── cn │ │ └── leancloud │ │ └── demo │ │ └── todo │ │ ├── AppInitListener.java │ │ ├── Cloud.java │ │ ├── LoginServlet.java │ │ ├── LogoutServlet.java │ │ ├── ProfileServlet.java │ │ ├── TimeServlet.java │ │ ├── Todo.java │ │ └── TodoServlet.java │ ├── resources │ └── log4j2.xml │ └── webapp │ ├── WEB-INF │ └── web.xml │ ├── index.html │ ├── login.jsp │ ├── profile.jsp │ ├── stylesheets │ └── style.css │ ├── time.jsp │ └── todos.jsp └── system.properties /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | .classpath 4 | target 5 | 6 | *.iml 7 | .idea/ 8 | 9 | # LeanCloud 10 | .avoscloud 11 | .leancloud 12 | -------------------------------------------------------------------------------- /.leanignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .avoscloud/ 3 | .leancloud/ 4 | target/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Getting started 2 | 3 | A simple Java application, based on Servlet, packaged as a WAR file, for LeanEngine Java runtime. 4 | 5 | ## Documentation 6 | 7 | - [Java Web Hosting Guide](https://docs.leancloud.app/leanengine_webhosting_guide-java.html) 8 | - [Java Cloud Function Guide](https://docs.leancloud.app/leanengine_cloudfunction_guide-java.html) 9 | - [LeanStorage Java Guide](https://docs.leancloud.app/leanstorage_guide-java.html) 10 | - [Java SDK API](https://leancloud.cn/api-docs/android/index.html) 11 | - [lean-cli Guide](https://docs.leancloud.app/leanengine_cli.html) 12 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | cn.leancloud.demo 6 | java-war-getting-started 7 | 1.0.0-SNAPSHOT 8 | war 9 | 10 | java-war-getting-started 11 | 12 | 13 | UTF-8 14 | 11 15 | 11 16 | 9.4.38.v20210224 17 | 2.17.0 18 | 19 | 20 | 21 | 22 | cn.leancloud 23 | engine-core 24 | [8.2.1, 9.0) 25 | 26 | 27 | org.apache.logging.log4j 28 | log4j-api 29 | ${log4j.version} 30 | 31 | 32 | org.apache.logging.log4j 33 | log4j-core 34 | ${log4j.version} 35 | 36 | 37 | org.apache.logging.log4j 38 | log4j-web 39 | ${log4j.version} 40 | 41 | 42 | junit 43 | junit 44 | 4.13.1 45 | test 46 | 47 | 48 | javax.servlet 49 | javax.servlet-api 50 | 3.1.0 51 | provided 52 | 53 | 54 | 55 | 56 | 57 | lean-up 58 | 59 | true 60 | 61 | 62 | ${jettyVersion} 63 | ${env.LEANCLOUD_APP_PORT} 64 | 65 | 66 | 67 | 68 | org.eclipse.jetty 69 | jetty-maven-plugin 70 | ${lean-jetty.version} 71 | 72 | ${project.basedir}/src/main/webapp 73 | 3 74 | foo 75 | 9999 76 | 77 | ${lean-jetty.port} 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/AppInitListener.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import javax.servlet.ServletContextEvent; 4 | import javax.servlet.ServletContextListener; 5 | import javax.servlet.annotation.WebListener; 6 | 7 | import cn.leancloud.*; 8 | import cn.leancloud.utils.StringUtil; 9 | import org.apache.logging.log4j.LogManager; 10 | import org.apache.logging.log4j.Logger; 11 | 12 | import cn.leancloud.core.LeanCloud; 13 | import cn.leancloud.core.GeneralRequestSignature; 14 | 15 | @WebListener 16 | public class AppInitListener implements ServletContextListener { 17 | 18 | private static final Logger logger = LogManager.getLogger(AppInitListener.class); 19 | 20 | private String appId = System.getenv("LEANCLOUD_APP_ID"); 21 | private String appKey = System.getenv("LEANCLOUD_APP_KEY"); 22 | private String appMasterKey = System.getenv("LEANCLOUD_APP_MASTER_KEY"); 23 | private String hookKey = System.getenv("LEANCLOUD_APP_HOOK_KEY"); 24 | private String apiServerUrl = System.getenv("LEANCLOUD_API_SERVER"); 25 | private String appEnv = System.getenv("LEANCLOUD_APP_ENV"); 26 | private String haveStaging = System.getenv("LEAN_CLI_HAVE_STAGING"); 27 | 28 | @Override 29 | public void contextDestroyed(ServletContextEvent arg0) {} 30 | 31 | @Override 32 | public void contextInitialized(ServletContextEvent arg0) { 33 | logger.info("LeanEngine app init."); 34 | // Enables debug logging. 35 | LeanCloud.setLogLevel(LCLogger.Level.DEBUG); 36 | // Registers subclass. 37 | LCObject.registerSubclass(Todo.class); 38 | 39 | if ("development".equals(appEnv) && "true".equals(haveStaging) || "stage".equals(appEnv)) { 40 | LCCloud.setProductionMode(false); 41 | } 42 | // Initializes application. 43 | // Ensure that you only perform one initialization in the whole project. 44 | if (StringUtil.isEmpty(apiServerUrl)) { 45 | LeanEngine.initialize(appId, appKey, appMasterKey, hookKey); 46 | } else { 47 | LeanEngine.initializeWithServerUrl(appId, appKey, appMasterKey, hookKey, apiServerUrl); 48 | } 49 | // Uses masterKey for the whole project. 50 | GeneralRequestSignature.setMasterKey(appMasterKey); 51 | 52 | // If you don't need session cookie, you can comment following line. 53 | LeanEngine.addSessionCookie(new EngineSessionCookie("my secret", 3600, false)); 54 | 55 | // Registers cloud functions. 56 | LeanEngine.register(Cloud.class); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/Cloud.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import cn.leancloud.*; 4 | import cn.leancloud.json.JSONObject; 5 | import cn.leancloud.sms.LCSMS; 6 | import cn.leancloud.sms.LCSMSOption; 7 | import cn.leancloud.types.LCNull; 8 | import cn.leancloud.utils.StringUtil; 9 | import io.reactivex.Observer; 10 | import io.reactivex.disposables.Disposable; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | public class Cloud { 14 | 15 | @EngineFunction("hello") 16 | public static String hello(@EngineFunctionParam("name") String name) { 17 | if (name == null) { 18 | return "What is your name?"; 19 | } 20 | // the following code just does demonstrate how to get authenticated user's sessionToken. 21 | String authUserSessionToken = EngineRequestContext.getSessionToken(); 22 | System.out.println("authUserSessionToken: " + authUserSessionToken); 23 | 24 | return String.format("Hello %s!", name); 25 | } 26 | 27 | @EngineFunction("sendSMS") 28 | public static String sendSMS(@EngineFunctionParam("mobile") String mobile) { 29 | if (StringUtil.isEmpty(mobile)) { 30 | return "What is your name?"; 31 | } 32 | LCSMSOption option = new LCSMSOption(); 33 | LCSMS.requestSMSCodeInBackground(mobile, option).subscribe(new Observer() { 34 | @Override 35 | public void onSubscribe(Disposable disposable) { 36 | 37 | } 38 | 39 | @Override 40 | public void onNext(LCNull avNull) { 41 | ; 42 | } 43 | 44 | @Override 45 | public void onError(Throwable throwable) { 46 | 47 | } 48 | 49 | @Override 50 | public void onComplete() { 51 | 52 | } 53 | }); 54 | return ""; 55 | } 56 | 57 | @EngineFunction("sendPush") 58 | public static String sendPush(@EngineFunctionParam("installationId") String installationId) { 59 | if (StringUtil.isEmpty(installationId)) { 60 | return "Illegal parameter: installationId is null."; 61 | } 62 | LCPush push = new LCPush(); 63 | LCQuery query = LCInstallation.getQuery(); 64 | query.whereEqualTo("installationId", installationId); 65 | push.setQuery(query); 66 | push.setMessage("test from LeanCloud Engine."); 67 | push.sendInBackground().subscribe(new Observer() { 68 | @Override 69 | public void onSubscribe(@NotNull Disposable disposable) { 70 | 71 | } 72 | 73 | @Override 74 | public void onNext(@NotNull JSONObject jsonObject) { 75 | System.out.println("succeed to sent push with installationId: " + installationId); 76 | } 77 | 78 | @Override 79 | public void onError(@NotNull Throwable throwable) { 80 | System.out.println("failed to sent push with installationId: " + installationId); 81 | throwable.printStackTrace(); 82 | } 83 | 84 | @Override 85 | public void onComplete() { 86 | 87 | } 88 | }); 89 | return ""; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/LoginServlet.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import cn.leancloud.*; 4 | import cn.leancloud.json.JSON; 5 | import io.reactivex.Observer; 6 | import io.reactivex.disposables.Disposable; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.util.*; 15 | 16 | @WebServlet(name = "LoginServlet", urlPatterns = "/login") 17 | public class LoginServlet extends HttpServlet { 18 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 19 | IOException { 20 | req.getRequestDispatcher("/login.jsp").forward(req, resp); 21 | } 22 | 23 | protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { 24 | String username = req.getParameter("username"); 25 | String passwd = req.getParameter("password"); 26 | LCUser.logIn(username, passwd).subscribe(new Observer() { 27 | @Override 28 | public void onSubscribe(Disposable disposable) { 29 | 30 | } 31 | 32 | @Override 33 | public void onNext(LCUser avUser) { 34 | try { 35 | // save user info to cookie and local session. 36 | EngineRequestContext.setAuthenticatedUser(avUser); 37 | EngineSessionCookie sessionCookie = LeanEngine.getSessionCookie(); 38 | if (null != sessionCookie) { 39 | sessionCookie.wrapCookie(true); 40 | } 41 | 42 | resp.sendRedirect("/profile"); 43 | } catch (IOException ex) { 44 | ex.printStackTrace(); 45 | } 46 | } 47 | 48 | @Override 49 | public void onError(Throwable throwable) { 50 | resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); 51 | resp.setContentType("application/json; charset=UTF-8"); 52 | Map result = new HashMap<>(); 53 | result.put("error", throwable.getMessage()); 54 | try { 55 | resp.getWriter().write(JSON.toJSONString(result)); 56 | } catch (IOException ex) { 57 | ex.printStackTrace(); 58 | } 59 | } 60 | 61 | @Override 62 | public void onComplete() { 63 | 64 | } 65 | }); 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/LogoutServlet.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import cn.leancloud.LCUser; 4 | import cn.leancloud.EngineRequestContext; 5 | import cn.leancloud.EngineSessionCookie; 6 | import cn.leancloud.LeanEngine; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | @WebServlet(name = "LogoutServlet", urlPatterns = "/logout") 16 | public class LogoutServlet extends HttpServlet { 17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 18 | IOException { 19 | doPost(req, resp); 20 | } 21 | 22 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 23 | IOException { 24 | // get authenticated user from request cookie. 25 | LCUser user = EngineRequestContext.getAuthenticatedUser(); 26 | if (user != null) { 27 | user.logOut(); 28 | } 29 | // delete cookie/session for next login. 30 | EngineRequestContext.setAuthenticatedUser(null); 31 | EngineSessionCookie sessionCookie = LeanEngine.getSessionCookie(); 32 | if (null != sessionCookie) { 33 | sessionCookie.wrapCookie(true); 34 | } 35 | resp.sendRedirect("/login"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/ProfileServlet.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import cn.leancloud.LCUser; 4 | import cn.leancloud.EngineRequestContext; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.annotation.WebServlet; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | @WebServlet(name = "ProfileServlet", urlPatterns = "/profile") 14 | public class ProfileServlet extends HttpServlet { 15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 16 | IOException { 17 | // get authenticated user from request cookie. 18 | LCUser currentUser = EngineRequestContext.getAuthenticatedUser(); 19 | if (null != currentUser) { 20 | req.setAttribute("currentUser", currentUser); 21 | } else { 22 | System.out.println("current User is empty."); 23 | } 24 | try { 25 | req.getRequestDispatcher("/profile.jsp").forward(req, resp); 26 | } catch (Exception ex) { 27 | ex.printStackTrace(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/TimeServlet.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import java.io.IOException; 4 | import java.util.Date; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.annotation.WebServlet; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | @WebServlet(name = "TimeServlet", urlPatterns = {"/time"}) 13 | public class TimeServlet extends HttpServlet { 14 | 15 | private static final long serialVersionUID = 110533133254086356L; 16 | 17 | @Override 18 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) 19 | throws ServletException, IOException { 20 | req.setAttribute("currentTime", new Date()); 21 | req.getRequestDispatcher("/time.jsp").forward(req, resp); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | 7 | import cn.leancloud.annotation.LCClassName; 8 | import cn.leancloud.LCObject; 9 | import cn.leancloud.json.JSON; 10 | 11 | @LCClassName("Todo") 12 | public class Todo extends LCObject { 13 | 14 | public String getContent() { 15 | return getString("content"); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | Map result = new HashMap(); 21 | result.put("content", this.getString("content")); 22 | result.put("objectId", this.getObjectId()); 23 | result.put("createdAt", this.getCreatedAt()); 24 | return JSON.toJSONString(result); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/leancloud/demo/todo/TodoServlet.java: -------------------------------------------------------------------------------- 1 | package cn.leancloud.demo.todo; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import javax.servlet.ServletException; 8 | import javax.servlet.annotation.WebServlet; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import cn.leancloud.LCException; 14 | import cn.leancloud.LCObject; 15 | import cn.leancloud.LCQuery; 16 | import cn.leancloud.utils.StringUtil; 17 | import io.reactivex.Observer; 18 | import io.reactivex.disposables.Disposable; 19 | 20 | @WebServlet(name = "AppServlet", urlPatterns = { "/todos" }) 21 | public class TodoServlet extends HttpServlet { 22 | 23 | private static final long serialVersionUID = -225836733891271748L; 24 | 25 | @Override 26 | protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { 27 | String offsetParam = req.getParameter("offset"); 28 | int offset = 0; 29 | if (!StringUtil.isEmpty(offsetParam)) { 30 | offset = Integer.parseInt(offsetParam); 31 | } 32 | LCQuery query = LCObject.getQuery(Todo.class); 33 | query.orderByDescending("createdAt"); 34 | query.skip(offset); 35 | 36 | query.findInBackground().subscribe(new Observer>() { 37 | @Override 38 | public void onSubscribe(Disposable disposable) { 39 | 40 | } 41 | 42 | @Override 43 | public void onNext(List todos) { 44 | req.setAttribute("todos", todos); 45 | try { 46 | req.getRequestDispatcher("/todos.jsp").forward(req, resp); 47 | } catch (Exception ex) { 48 | ex.printStackTrace(); 49 | } 50 | } 51 | 52 | @Override 53 | public void onError(Throwable throwable) { 54 | if (throwable instanceof LCException) { 55 | if (((LCException) throwable).getCode() == 101) { 56 | // Todo class does not exist in the cloud yet. 57 | req.setAttribute("todos", new ArrayList<>()); 58 | } 59 | req.setAttribute("todos", new ArrayList<>()); 60 | try { 61 | req.getRequestDispatcher("/todos.jsp").forward(req, resp); 62 | } catch (Exception ex) { 63 | ex.printStackTrace(); 64 | } 65 | } 66 | } 67 | 68 | @Override 69 | public void onComplete() { 70 | 71 | } 72 | }); 73 | } 74 | 75 | @Override 76 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 77 | String content = req.getParameter("content"); 78 | 79 | LCObject note = new Todo(); 80 | note.put("content", content); 81 | note.save(); 82 | resp.sendRedirect("/todos"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | index.html 9 | 10 | -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LeanEngine 6 | 7 | 8 | 9 |

LeanEngine

10 |

This is a LeanEngine demo application.

11 |

Routing example

12 |

A simple todo demo

13 | 14 | -------------------------------------------------------------------------------- /src/main/webapp/login.jsp: -------------------------------------------------------------------------------- 1 | 2 | <%@ page language="java" contentType="text/html; charset=UTF-8" 3 | pageEncoding="UTF-8"%> 4 | 5 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 6 | 7 | 8 | 9 | UserLogin - LeanEngine Demo 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /src/main/webapp/profile.jsp: -------------------------------------------------------------------------------- 1 | 2 | <%@ page language="java" contentType="text/html; charset=UTF-8" 3 | pageEncoding="UTF-8"%> 4 | 5 | 6 | 7 | 8 | UserProfile - LeanEngine Demo 9 | 10 | 11 | 12 |

Current User Profile: ${currentUser}

13 | 14 |
15 | 16 |
17 | 18 | -------------------------------------------------------------------------------- /src/main/webapp/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | a { 6 | color: #00b7ff; 7 | } -------------------------------------------------------------------------------- /src/main/webapp/time.jsp: -------------------------------------------------------------------------------- 1 | 2 | <%@ page language="java" contentType="text/html; charset=UTF-8" 3 | pageEncoding="UTF-8"%> 4 | 5 | 6 | 7 | 8 | Server Time - LeanEngine Demo 9 | 10 | 11 | 12 |

Current time: ${currentTime}

13 | 14 | -------------------------------------------------------------------------------- /src/main/webapp/todos.jsp: -------------------------------------------------------------------------------- 1 | 2 | <%@ page language="java" contentType="text/html; charset=UTF-8" 3 | pageEncoding="UTF-8"%> 4 | 5 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 6 | 7 | 8 | 9 | Todos - LeanEngine Demo 10 | 11 | 12 | 13 |

TODO list

14 |
15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |

content

objectId

createdAt

${todo.content}${todo.objectId}${todo.createdAt}
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /system.properties: -------------------------------------------------------------------------------- 1 | java.runtime.version=11 2 | --------------------------------------------------------------------------------