!=和notin哪个快
一个想法就像痒:您需要抓挠它,当您这样做时会感觉更好。 作为软件开发人员,我们花费大量时间思考各种应用程序的想法。 很好玩吧? 面临的挑战是弄清楚如何使软件产品实现。 想像一下然后创建它就很令人满意。 另一种选择(痒痒)只是令人沮丧。
许多应用程序从未落地的原因之一就是对基础架构的需求。 维护良好的基础结构通常需要系统管理员,DBA和网络工程师组成的团队,这些团队直到最近才是主要针对富人的企业。 即使是向第三方付费以托管您的应用程序也不是万无一失的:如果该应用程序的受欢迎程度飞速上升,并突然受到欢迎,会发生什么? 所谓的Slashdot效应可以说是一个好主意,仅仅是因为很难预测负载峰值。
但是,众所周知,这正在改变。 Web服务的前提已经发生了变化,如今,它通过云计算及其强大的表亲,平台即服务/ PAAS为我们带来了更轻松地构建,部署和分发应用程序的方式。 现在,当您编写下一个Twitter并将其部署在云平台上时,它将可以扩展,扩展,扩展。 哇,真好!
在这一由三部分组成的文章中,您将亲身体验为什么云计算/ PAAS是软件开发如此重要的进化转变,同时还为Java开发提供了令人兴奋的新平台:Google App Engine for Java,当前在预览版中可用。 我将首先概述App Engine for Java,包括它提供的应用程序服务的类型。 之后,您将直接使用Java的App Engine Google Eclipse插件直接进入一个应用程序示例(两个示例之一)。 第一个应用程序示例将利用App Engine for Java对Java Servlet API的支持,第二个示例将利用其对GWT的支持。 在第2部分中 ,您将使用App Engine for Java对servlet和GWT的支持分别创建一个小的联系人管理应用程序。 在第3部分中,您将使用自定义构建的应用程序来探索App Engine for Java的基于Java的持久性支持,该支持基于Java数据对象(JDO)和Java持久性API(JPA)。
好吧,足够多的谈话:让我们快转!
Google(我相信也是某种搜索引擎的制造商)于2008年4月首次发布了Google App Engine。令许多Java开发人员感到沮丧的是,最初的发布纯粹是Python程序员的领域-人们认为空白应该是用于块! (我写了一本关于Python的书,所以我应该知道。)Google于2009年4月发布了针对Java的Google App Engine,以此回应了大众的需求。
Google App Engine for Java提供了用于企业Java开发的端到端解决方案:基于浏览器的Ajax GUI(易于使用),Eclipse工具支持和后端的Google App Engine。 与其他云计算解决方案相比,易用性和工具优势是Google App Engine for Java的优势。
App Engine for Java中的应用程序开发意味着使用Google的资源来存储和检索Java对象。 数据存储基于BigTable ,但具有JDO和JPA接口,使您可以编写不直接与BigTable绑定的代码。 实际上,Google为许多API提供了基于标准的支持,因此您可以编写与Java平台的App Engine无关的代码。
App Engine for Java依赖以下标准Java API:
java.net.URL
以获取服务(通过使用HTTP和HTTPS协议与其他主机进行通信) 此外,适用于Java的App Engine还为以下应用程序服务提供支持:
数据导入/导出对于将数据从其他来源转移到App Engine for Java应用程序中非常重要。 这是您不受App Engine for Java束缚的另一种方式。 Google的CRON支持基于内部URL在特定时间表上受到攻击,这使其成为一项不错的服务,并且与App Engine for Java没有太多的关联。 用户认证和授权机制是具体到App Engine for Java中,但你可以写一个ServletFilter
,以尽量减少紧耦合,方面或Spring Security的插件。
如果您已经阅读了本文,那么您就可以开始构建第一个App Engine for Java应用程序了。 第一步是安装Google Eclipse for App Engine for Java插件 ; 完成后,您就可以开始了。
打开你的Eclipse IDE中,你会看到三个在Eclipse IDE旁边的打印机按钮新的按钮:A G在一个蓝色的球,在一个红色的工具箱中的G和一个App Engine的Java迷你喷气式飞机,如图图1:
这些按钮的作用如下:
您将使用项目创建向导创建两个新项目:一个基于servlet,另一个使用GWT构建。 您将使用工具箱功能来编译GWT项目。 准备部署App Engine项目时,您将启动微型喷气机,从而使它生效。
现在开始创建一个Java Java App Engine项目。 首先,单击蓝色球以访问项目创建向导。 然后使用名为gaej.example的包创建一个名为SimpleServletApp的应用程序,如图2所示:
请注意,对于第一个简单示例,如何取消选择GWT支持。 完成此步骤后,项目创建向导将创建一个具有Hello World类型的servlet的基于servlet的简单应用程序。 图3显示了该项目的屏幕截图:
请注意,此新的基于Servlet的项目自动包含了JAR文件:
从本文的第2部分开始,您将学习如何使用App Engine for Java和一些App Engine for Java的应用程序服务中的持久性API。
还要注意用于配置Google App Engine运行时容器的文件,名为appengine.xml。 在此示例中,将使用appengine.xml来配置logging.properties文件,以使用App Engine for Java进行日志记录。
在项目创建向导中配置完所有内容后,适用于Java的App Engine将向您展示Hello World风格的servlet应用程序的基础知识。 查看代码,然后查看如何使用App Engine for Java Eclipse工具运行应用程序。 该应用程序的主要入口是SimpleServletAppServlet
,如清单1所示:
package gaej.example;
import java.io.IOException;
import javax.servlet.http.*;
@SuppressWarnings("serial")
public class SimpleServletAppServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, world");
}
}
该servlet被映射到web.xml中的URI /simpleservletapp
下,如清单2所示:
simpleservletapp
gaej.example.SimpleServletAppServlet
simpleservletapp
/simpleservletapp
index.html
项目创建向导还提供了一个index.html文件,该文件具有指向新servlet的链接,如清单3所示:
Hello App Engine
Hello App Engine!
Available Servlets:
SimpleServletAppServlet
现在,您仅使用一些Java API构建了一个简单的servlet应用程序。 这就是重点:适用于Java的App Engine使用标准Java API封装了App Engine功能,从而使App Engine可以支持Java平台可用的大量框架。
要使用App Engine for Java Eclipse工具运行基于servlet的应用程序,首先右键单击该项目并选择Run As菜单,然后选择旁边带有蓝色球的“ Web Application”,如图4所示:
现在,您应该能够在浏览器中导航到http:// localhost:8080 / simpleservletapp,并看到带有Hello World消息的应用程序。
您已经了解了简单的Java Servlet应用程序App Engine的工作原理,因此接下来让我们探索GWT应用程序的Java Eclipse App Engine工具。 首先单击Eclipse IDE工具栏中的蓝色球,以激活Google项目创建向导。 这次,选择对GWT的支持,如图5所示:
如您在图6中看到的,App Engine for Java为GWT应用程序提供了比基于servlet的简单代码工件更多的代码工件。 示例应用程序是在GWT中完成的GUI,可与问候服务应用程序对话。
GWT应用程序还有一个额外的JAR,而基于servlet的应用程序则不需要,即gwt-servlet.jar。
其他工件如下:
GreetingServiceImpl
部署描述符 在深入研究应用程序的体系结构和源代码之前,请查看运行该应用程序时会发生什么。 要运行该应用程序,请单击工具栏上的红色工具箱,然后单击“ 编译”按钮。 现在,右键单击该项目,然后像以前一样选择“ 运行方式-> Web应用程序”菜单项。 这次,因为您正在使用GWT应用程序,所以将显示GWT托管模式控制台和浏览器。 继续并使用Web应用程序输入您的姓名并查看响应。 我收到了如图7所示的响应:
在下一节中,我将引导您完成示例GWT应用程序。 如果您想了解更多有关GWT的信息(或参加GWT教程),请参阅参考资料 。
基于提供的配置,Eclipse的GWT工具创建了一个具有HTML前端( 清单10所示的SimpleGWTApp.html)的启动程序应用程序,该应用程序加载了simplegwtapp.js和simplegwtapp.nocache.js。 这是GWT从您的Java代码生成JavaScript代码; 即,这是在gaej.example.client包下src目录代码(参见清单6 , 7 ,和8 )。
创建GUI的主要入口是gaej.example.client.SimpleGWTApp
,如清单8所示。 此类创建GWT GUI元素,并将它们与SimpleGWTApp.html上HTML DOM元素关联(请参见清单10 )。 SimpleGWTApp.html定义了两个名为nameFieldContainer
和sendButtonContainer
(表中的列)的DOM元素。 SimpleGWTApp
类使用RootPanel.get("nameFieldContainer")
访问与那些DOM元素关联的面板,并将其替换为GUI元素。 然后, SimpleGWTApp
类定义一个文本框和按钮,您可以使用它们输入某人的名字并向他们发送问候(见清单10 )。
GWT知道SimpleGWTApp
类是应用程序的主要入口点,因为SimpleGWTApp.gwt.xml使用入口点元素指定了它。
SimpleGWTApp
连接名为sendButton
的按钮,以便单击该按钮时, SimpleGWTApp
将在GreetingService
上调用greetServer
方法。 GreetingService
接口在src / gaej.example.client.GreetingService.java中定义( 清单6 )。
由于Ajax本质上是异步的,因此GWT定义了用于访问远程服务的异步接口。 SimpleGWTApp使用src / gaej.example.client.GreetingServiceAsync.java( 清单7 )中定义的异步接口。 所述GreetingServiceImpl
的(SRC / gaej.example.server.GreetingServiceImpl.java)实现greetServer
在所定义的方法GreetingService
( 清单5 )。 GreetingServiceImpl.greetServer
方法返回问候消息String
,SimpleGWTApp使用该String
在其创建的对话框中显示问候消息。
GWT模块描述符声明了GUI应用程序的主要入口点,即gaej.example.client.SimpleGWTApp
,如清单4所示:
GreetingServiceImpl
是GreetingServiceImpl
-service应用程序的实际实现,如清单5所示。它在服务器端运行,客户端代码通过远程过程调用对其进行调用。
package gaej.example.server;
import gaej.example.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
public String greetServer(String input) {
String serverInfo = getServletContext().getServerInfo();
String userAgent = getThreadLocalRequest().getHeader("User-Agent");
return "Hello, " + input + "!
I am running " + serverInfo
+ ".
It looks like you are using:
" + userAgent;
}
}
清单6中所示的GreetingService
是客户端代码使用的远程过程调用的接口:
package gaej.example.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
String greetServer(String name);
}
GreetingServiceAsync
是客户端代码将使用的实际接口,如清单7所示。每个方法都提供一个回调对象,以便在远程过程调用完成后以异步方式通知您。 在后台,GWT使用Ajax。 在客户端上使用Ajax时,最好不要阻塞客户端,从而避免异步调用。 阻塞会破坏使用Ajax的目的。
package gaej.example.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* The async counterpart of GreetingService
.
*/
public interface GreetingServiceAsync {
void greetServer(String input, AsyncCallback callback);
}
SimpleGWTApp
是执行大多数操作的地方。 它注册GUI事件,然后将Ajax请求发送到GreetingService
。
package gaej.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Entry point classes define onModuleLoad()
.
*/
public class SimpleGWTApp implements EntryPoint {
/**
* The message displayed to the user when the server cannot be reached or
* returns an error.
*/
private static final String SERVER_ERROR = "An error occurred while "
+ "attempting to contact the server. Please check your network "
+ "connection and try again.";
/**
* Create a remote service proxy to talk to the server-side Greeting service.
*/
private final GreetingServiceAsync greetingService = GWT
.create(GreetingService.class);
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Button sendButton = new Button("Send");
final TextBox nameField = new TextBox();
nameField.setText("GWT User");
// You can add style names to widgets
sendButton.addStyleName("sendButton");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("nameFieldContainer").add(nameField);
RootPanel.get("sendButtonContainer").add(sendButton);
// Focus the cursor on the name field when the app loads
nameField.setFocus(true);
nameField.selectAll();
// Create the popup dialog box
final DialogBox dialogBox = new DialogBox();
dialogBox.setText("Remote Procedure Call");
dialogBox.setAnimationEnabled(true);
final Button closeButton = new Button("Close");
// You can set the id of a widget by accessing its Element
closeButton.getElement().setId("closeButton");
final Label textToServerLabel = new Label();
final HTML serverResponseLabel = new HTML();
VerticalPanel dialogVPanel = new VerticalPanel();
dialogVPanel.addStyleName("dialogVPanel");
dialogVPanel.add(new HTML("Sending name to the server:"));
dialogVPanel.add(textToServerLabel);
dialogVPanel.add(new HTML("
Server replies:"));
dialogVPanel.add(serverResponseLabel);
dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
dialogVPanel.add(closeButton);
dialogBox.setWidget(dialogVPanel);
// Add a handler to close the DialogBox
closeButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
sendButton.setEnabled(true);
sendButton.setFocus(true);
}
});
// Create a handler for the sendButton and nameField
class MyHandler implements ClickHandler, KeyUpHandler {
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
sendNameToServer();
}
/**
* Fired when the user types in the nameField.
*/
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
sendNameToServer();
}
}
/**
* Send the name from the nameField to the server and wait for a response.
*/
private void sendNameToServer() {
sendButton.setEnabled(false);
String textToServer = nameField.getText();
textToServerLabel.setText(textToServer);
serverResponseLabel.setText("");
greetingService.greetServer(textToServer,
new AsyncCallback() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
dialogBox
.setText("Remote Procedure Call - Failure");
serverResponseLabel
.addStyleName("serverResponseLabelError");
serverResponseLabel.setHTML(SERVER_ERROR);
dialogBox.center();
closeButton.setFocus(true);
}
public void onSuccess(String result) {
dialogBox.setText("Remote Procedure Call");
serverResponseLabel
.removeStyleName("serverResponseLabelError");
serverResponseLabel.setHTML(result);
dialogBox.center();
closeButton.setFocus(true);
}
});
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
sendButton.addClickHandler(handler);
nameField.addKeyUpHandler(handler);
}
}
Web部署描述符(web.xml,如清单9所示)将GreetingService
映射为基于servlet的Web资源。 它以/simplegwtapp/greet
名称映射GreetingService
servlet,以便SimpleGWTApp
可以加载它并对其进行调用。 Web部署描述符还表示SimpleGWTApp.html是应用程序的欢迎页面,因此它将始终加载。
SimpleGWTApp.html
greetServlet
gaej.example.server.GreetingServiceImpl
greetServlet
/simplegwtapp/greet
HTML前端是SimpleGWTApp.html,如清单10所示。该页面加载了simplegwtapp.js和simplegwtapp.nocache.js,这是GWT从Java代码生成JavaScript代码。 如前面提到的,这个代码生活在src目录的gaej.example.client包下(从信息6 , 7 ,和8 )。
Web Application Starter Project
Web Application Starter Project
Please enter your name:
使用GWT,您可以通过CSS控制应用程序的外观,如清单11所示:
/** Add css rules here for your application. */
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
.sendButton {
display: block;
font-size: 16pt;
}
/** Most GWT widgets already have a style name defined */
.gwt-DialogBox {
width: 400px;
}
.dialogVPanel {
margin: 5px;
}
.serverResponseLabelError {
color: red;
}
/** Set ids using widget.getElement().setId("idOfElement") */
#closeButton {
margin: 15px 6px 6px;
}
一旦创建了世界上下一个杀手级应用程序(因为我们确实需要一个用户友好的问候语应用程序),您将需要对其进行部署。 使用Google App Engine的全部目的是,您可以在Google的坚实基础架构上部署应用程序,从而更易于扩展。 Google App Engine旨在提供一个平台来构建可扩展的应用程序,“这些应用程序可以从无数用户增长到数百万,而不会遭受基础架构的困扰”(如App Engine主页上所述)。 为了使用此基础架构,您需要一个Google App Engine for Java帐户 。
就像生活中的许多事情一样,第一次是免费的。 App Engine for Java的免费版本为已部署的应用程序提供了足够的CPU,带宽和存储空间,可提供约500万次浏览量。 除此之外,它是随用随付的。 (还要记住,在撰写本文时,可用的是Java平台App Engine的预览版。)
获得该帐户后,您应该在App Engine for Java网站上看到一个空白的应用程序列表。 单击Create New Application按钮,将出现一个如图8所示的表单。 输入唯一的应用程序名称和描述,然后您将看到一条确认消息,其中包含应用程序的标识符。
该标识符也属于您应用程序的app.yaml文件。 注意,标识符不能更改。 如果您对应用程序使用Google身份验证,则在访问应用程序时,“登录页面”中会显示“ GAEj Rick Part 1文章”。 您将使用gaejarticleforrick
通过适用于Java的App Engine Eclipse插件将应用程序部署到Google App Engine。
设置应用程序ID之后,可以从Eclipse部署应用程序。 首先,点击看起来类似于Google App Engine徽标(带有机翼和尾巴的喷气发动机)的工具栏按钮,如图9所示:
在图10所示的对话框中单击Deploy之前,您可能需要确保选择了Java的App Engine项目。将提示您输入Google凭据,即您的电子邮件地址和用户名。
图10中的对话框具有指向“ App Engine项目设置”的链接。 单击此链接(也可以从项目设置文件访问),然后输入应用程序ID(在本例中为gaejarticleforrick
),如图11所示。填写应用程序ID后,单击OK ,然后单击Deploy 。
部署应用程序后,可以从http://
。
到此结束我对Java的Google App Engine简介的第1部分。 到目前为止,您已经获得了有关Java App Engine的所有内容的概述,并通过使用Java App Engine Google Eclipse插件迈出了第一步。 您创建了两个小型启动器应用程序(一个基于servlet,另一个基于GWT),然后将GWT应用程序部署到Google App Engine平台。
到目前为止的示例已经展示了工具和功能,这些工具和功能使创建和部署可扩展的基于Java的应用程序变得更加容易,甚至可能达到YouTube或Facebook的规模。 在第2部分中 ,您将继续探索致力于App Engine for Java的Java开发人员可以使用的机会。 摆脱本文演示的示例应用程序,您将构建一个自定义联系人管理应用程序。 该应用程序还将成为第3部分中练习的重点,深入研究App Engine for Java的数据存储区及其GUI前端。
翻译自: https://www.ibm.com/developerworks/java/library/j-gaej1/index.html
!=和notin哪个快