gwt-2.8.2下载
本分步指南将介绍如何使用Google的Web Toolkit( GWT )为富客户端和Spring作为后端服务器端框架开发简单的Web应用程序。 该示例Web应用程序将提供对数据库执行CRUD(创建检索更新删除)操作的功能。 对于数据访问层,我们将在Hibernate上使用JPA ,对于数据库,我们将使用Hypersonic。 当然,您可以更改配置并使用所需的任何内容。 我们将Web应用程序部署到Apache – Tomcat实例。
Maven有两种形式,一种是带有命令行支持的独立工具,另一种是作为IDE( Eclipse和Netbeans)集成插件的。 我们首选的开发环境是Eclipse ,因此,必须先安装具有Maven支持的Eclipse 。 用于Eclipse的Maven插件的安装不在本教程的讨论范围之内,因此不再讨论。 但是,您将需要以下组件:
我们将使用Eclipse Galileo和“ m2eclipse” Maven Integration for Eclipse插件版本0.10.0, GWT版本2.0.3, Spring版本3.0.1, Hibernate版本3.5.1,Hypersonic版本1.8.0.10,slf4j-log4j12版本1.5。在本教程中,请参见图8,c3p0连接池版本0.9.1.2和spring4gwt版本0.0.1。
聊够了,让我们动手吧!
- 创建一个新的Maven项目,转到File? 项目? Maven? Maven项目
- 在向导的“选择项目名称和位置”页面中,确保未选中“创建简单项目(跳过原型选择)”选项,单击“下一步”以继续使用默认值
- 在向导的“选择原型”页面中,在“目录”下拉列表中选择“ Nexus Indexer”,并在刷新原型选择区域后,从“ org.codehaus”中选择“ gwt-maven-plugin”原型。 mojo”来使用。 您可以使用“过滤器”文本框来缩小搜索结果范围。 点击“下一步”继续
- 在向导的“输入工件ID”页面中,您可以定义项目的名称和主程序包。 我们将“ Group Id”变量设置为“ com.javacodegeeks”,将“ Artifact Id”变量设置为“ gwtspring”。 前面提到的选择组成了主项目包“ com.javacodegeeks.gwtspring”和项目名“ gwtspring”。 点击“完成”退出向导并创建您的项目
- / src / main / java文件夹包含应用程序动态内容的源文件
- {main_package} .client子软件包包含仅适用于应用程序客户端的源文件
- {main_package} .server子软件包包含仅对应用程序的服务器端部分可用的源文件(此子软件包在创建项目时不会自动创建)
- {main_package} .shared子软件包包含可用于应用程序的客户端和服务器端的源文件(此子软件包在创建项目时不会自动创建)
- / src / main / resources包含静态内容的源文件,例如静态html页面和应用程序的资源文件,例如css文件
- / src / test / java文件夹包含用于单元测试的所有源文件
- / src / main / webapp文件夹包含用于创建有效的Web应用程序的基本文件,例如“ web.xml”
- / target文件夹包含已编译和打包的可交付成果
- / war文件夹用于构建和打包过程
- “ pom.xml”是项目对象模型(POM)文件。 包含所有项目相关配置的单个文件
为了在运行时正确地将Spring与GWT集成,我们必须向Web应用程序提供所有必需的库。 打开“ pom.xml”的图形编辑器并执行以下更改:
- 在POM编辑器的“概述”页面上的“属性”部分中找到并执行以下更改:
- 创建一个名为org.springframework.version且值为3.0.1.RELEASE的新属性。
- 创建一个名为org.hibernate.version且值为3.5.1-Final的新属性
- 将gwt.version属性的值更改为2.0.3
- 根据您的Java运行时环境版本更改maven.compiler.source和maven.compiler.target属性值,我们将使用1.6
- 导航到POM编辑器的“ Dependencies”页面,并创建以下依赖关系(您应在该页面的“ Dependency Details”部分的“ GroupId”,“ Artifact Id”和“ Version”字段中进行填充):
- 组ID: org.springframework工件ID: spring-orm版本: $ {org.springframework.version}
- 组ID: org.springframework工件ID: spring-web版本: $ {org.springframework.version}
- 组ID: org.hibernate工件ID: hibernate-core版本: $ {org.hibernate.version}
- 组ID: org.hibernate工件ID: hibernate-annotations版本: $ {org.hibernate.version}
- 组ID: org.hibernate工件ID: hibernate-entitymanager版本: $ {org.hibernate.version}
- 组ID: org.hibernate.javax.persistence工件ID: hibernate-jpa-2.0-api版本: 1.0.0.Final
- 组ID: org.slf4j神器ID: slf4j-log4j12版本: 1.5.8
- 组ID: org.hsqldb工件ID: hsqldb版本: 1.8.0.10
- 组ID: c3p0工件ID: c3p0版本: 0.9.1.2
- 找到您的POM编辑器右上方的“显示高级选项卡”按钮,然后单击它。 导航到“存储库”页面并创建以下存储库(您应在该页面的“存储库详细信息”部分中填写“ Id”和“ URL”字段):
- ID: JBoss URL: http : //repository.jboss.org/maven2/
如您所见, Maven以声明方式管理库依赖关系。 创建本地存储库(默认情况下,位于{user_home} /。m2文件夹下),所有必需的库都从公共存储库下载并放置在该库中。 此外,库内的依赖关系会自动解决和处理。 但是,并非所有库都可用于公共存储库。 在这种情况下,我们必须手动下载所需的库并在我们的项目中使用它。 这种情况就是“ spring4gwt”库。 要使用它,我们必须在/ src / main / webapp / WEB-INF文件夹下创建一个“ lib”文件夹,然后在其中放置“ spring4gwt-0.0.1.jar”。 在以后的文章中,我们将讨论如何创建您自己的Maven共享存储库以及如何安装不公开的库,敬请期待!
下一步是为Web应用程序提供钩子,以便在启动时加载Spring上下文,并允许“ spring4gwt”拦截客户端和服务器之间的RPC调用并将其转换为Spring服务调用。
在/ src / main / webapp / WEB-INF下找到“ web.xml”文件,然后添加以下内容:
为了在启动时加载Spring上下文,
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
在Servlet部分,包括
<servlet> <servlet-name>springGwtRemoteServiceServlet</servlet-name> <servlet-class>org.spring4gwt.server.SpringGwtRemoteServiceServlet </servlet-class> </servlet>
在servlet映射部分中,供spring4gwt拦截RPC调用。
<servlet-mapping> <servlet-name>springGwtRemoteServiceServlet</servlet-name> <url-pattern>/com.javacodegeeks.gwtspring.Application/springGwtServices/*</url-pattern> </servlet-mapping>
这里要注意的事情:
- 应该将springGwtRemoteServiceServlet servlet的servlet-mapping元素的url-pattern子元素更改为您的GWT模块名称,例如{module_name} / springGwtServices / *,默认情况下,模块名称为{main_package}。
- 您可以将spring4gwt Servlet的名称(此处为springGwtRemoteServiceServlet)更改为任意名称
下一步是创建“ persistence.xml”文件,以描述使用JPA与数据库的连接。 “ pesistence.xml”文件必须位于META-INF目录内,而该目录又必须由Web应用程序在运行时(在类路径上)访问。 为了满足上述要求,我们必须在项目的/ src / main / resources文件夹下创建META-INF文件夹。 最后,在/ src / main / resources / META-INF文件夹内创建“ persistence.xml”文件。 下面显示了一个示例persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="MyPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="false" /> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" /> <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:javacodegeeks" /> <property name="hibernate.connection.username" value="sa" /> <property name="hibernate.connection.password" value="" /> <property name="hibernate.c3p0.min_size" value="5" /> <property name="hibernate.c3p0.max_size" value="20" /> <property name="hibernate.c3p0.timeout" value="300" /> <property name="hibernate.c3p0.max_statements" value="50" /> <property name="hibernate.c3p0.idle_test_period" value="3000" /> </properties> </persistence-unit> </persistence>
现在让我们创建将驱动Spring容器的applicationContext.xml文件。 在/ src / main / webapp / WEB-INF目录下创建文件。 下面是一个示例“ applicationContext.xml”
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <context:component-scan base-package="com.javacodegeeks.gwtspring" /> <tx:annotation-driven /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="MyPersistenceUnit" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> </beans>
这里要注意的事情:
- 将context:component-scan元素的base-package属性更改为项目的基本包,以便扫描Spring组件(服务,DAO等)
- 按照“ persistence.xml”文件中的指示,将entityManagerFactory bean的persistentUnitName属性的value属性更改为您的持久单元的名称
在本教程的最后一部分中,我们将介绍用于在客户端和服务器之间传输数据的数据传输对象(DTO),用于访问数据库的数据访问对象(DAO)和用于公开功能的Spring服务。到GWT Web客户端。
DTO是客户端和服务器都可以使用的对象,因此您应该在主程序包(在我们的示例中为com.javacodegeeks.gwtspring)下创建一个“ shared.dto”子程序包,然后将DTO放置在此位置。 我们将创建一个EmployeeDTO,其中包含有关员工的信息,如下所示
package com.javacodegeeks.gwtspring.shared.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "EMPLOYEE") public class EmployeeDTO implements java.io.Serializable { private static final long serialVersionUID = 7440297955003302414L; @Id @Column(name="employee_id") private long employeeId; @Column(name="employee_name", nullable = false, length=30) private String employeeName; @Column(name="employee_surname", nullable = false, length=30) private String employeeSurname; @Column(name="job", length=50) private String job; public EmployeeDTO() { } public EmployeeDTO(int employeeId) { this.employeeId = employeeId; } public EmployeeDTO(long employeeId, String employeeName, String employeeSurname, String job) { this.employeeId = employeeId; this.employeeName = employeeName; this.employeeSurname = employeeSurname; this.job = job; } public long getEmployeeId() { return employeeId; } public void setEmployeeId(long employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getEmployeeSurname() { return employeeSurname; } public void setEmployeeSurname(String employeeSurname) { this.employeeSurname = employeeSurname; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } }
为了使DTO对象可用于GWT客户端,我们必须指示GWT编译器对其进行解析。 为此,请找到主GWT模块文件,应将其命名为“ Application.gwt.xml”,并位于您的主包(在我们的示例中为com.javacodegeeks.gwtspring)下,并附加以下指令:
<!-- Specify the paths for translatable code --> <source path='client'/> <source path='shared'/>
DAO对象将用于访问数据库并执行CRUD(创建检索更新删除)操作。 它是服务器端组件,因此应放在我们项目的“服务器”子程序包下。 在您的主项目程序包(在我们的示例中为com.javacodegeeks.gwtspring)下创建一个“ server.dao”子程序包,然后将DAO放在此处。 下面是一个示例DAO
package com.javacodegeeks.gwtspring.server.dao; import javax.annotation.PostConstruct; import javax.persistence.EntityManagerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; @Repository("employeeDAO") public class EmployeeDAO extends JpaDAO<Long, EmployeeDTO> { @Autowired EntityManagerFactory entityManagerFactory; @PostConstruct public void init() { super.setEntityManagerFactory(entityManagerFactory); } }
如您所见,EmployeeDAO类扩展了基本的DAO类(JpaDAO)。 EmployeeDAO类可以包含有关EmployeeDTO对象的特定查询,但是所有CRUD操作都可以从基本DAO类(JpaDAO)处理。 在“ dao”子程序包下,将JpaDAO类与EmployeeDAO类放在同一级别。 下面我们介绍JpaDAO类
package com.javacodegeeks.gwtspring.server.dao; import java.lang.reflect.ParameterizedType; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import javax.persistence.Query; import org.springframework.orm.jpa.JpaCallback; import org.springframework.orm.jpa.support.JpaDaoSupport; public abstract class JpaDAO<K, E> extends JpaDaoSupport { protected Class<E> entityClass; @SuppressWarnings("unchecked") public JpaDAO() { ParameterizedType genericSuperclass = (ParameterizedType) getClass() .getGenericSuperclass(); this.entityClass = (Class<E>) genericSuperclass .getActualTypeArguments()[1]; } public void persist(E entity) { getJpaTemplate().persist(entity); } public void remove(E entity) { getJpaTemplate().remove(entity); } public E merge(E entity) { return getJpaTemplate().merge(entity); } public void refresh(E entity) { getJpaTemplate().refresh(entity); } public E findById(K id) { return getJpaTemplate().find(entityClass, id); } public E flush(E entity) { getJpaTemplate().flush(); return entity; } @SuppressWarnings("unchecked") public List<E> findAll() { Object res = getJpaTemplate().execute(new JpaCallback() { public Object doInJpa(EntityManager em) throws PersistenceException { Query q = em.createQuery("SELECT h FROM " + entityClass.getName() + " h"); return q.getResultList(); } }); return (List<E>) res; } @SuppressWarnings("unchecked") public Integer removeAll() { return (Integer) getJpaTemplate().execute(new JpaCallback() { public Object doInJpa(EntityManager em) throws PersistenceException { Query q = em.createQuery("DELETE FROM " + entityClass.getName() + " h"); return q.executeUpdate(); } }); } }
最后,我们将为GWT客户端创建服务接口和实现类。 客户端和服务器都应该可以访问该服务接口,因此应将其放置在我们项目的“共享”子程序包下。 创建一个“服务”子程序包,并将服务接口放在此处。 下面是一个示例接口类
package com.javacodegeeks.gwtspring.shared.services; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; @RemoteServiceRelativePath("springGwtServices/employeeService") public interface EmployeeService extends RemoteService { public EmployeeDTO findEmployee(long employeeId); public void saveEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception; public void updateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception; public void saveOrUpdateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception; public void deleteEmployee(long employeeId) throws Exception; }
这里要注意的事情:
- GWT客户端必须能够对服务器端服务进行异步远程过程调用(RPC)。 因此,服务接口必须扩展RemoteService接口。 在项目编译和打包之前, Maven会自动创建指定接口的异步副本。
- 我们对接口进行注释,以定义可访问该服务的URL。 由于该服务是Spring服务,因此我们希望“ spring4gwt”拦截RPC调用并执行Spring服务调用。 为此,我们定义了一个相对路径,该相对路径将由“ web.xml”中声明的“ springGwtRemoteServiceServlet”处理,如上所示。
- 在“ RemoteServiceRelativePath”注释中声明的服务名称(此处为“ employeeService”)必须与Spring服务bean名称匹配。 我们将在服务实现类中定义Spring服务bean名称(请参见下文)
服务实现类是服务器端的组件,因此我们必须将其放在项目的“服务器”子包下。 创建“服务”子程序包并将其放在此处。 下面提供了一个示例服务实现类
package com.javacodegeeks.gwtspring.server.services; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.javacodegeeks.gwtspring.server.dao.EmployeeDAO; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; import com.javacodegeeks.gwtspring.shared.services.EmployeeService; @Service("employeeService") public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeDAO employeeDAO; @PostConstruct public void init() throws Exception { } @PreDestroy public void destroy() { } public EmployeeDTO findEmployee(long employeeId) { return employeeDAO.findById(employeeId); } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void saveEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception { EmployeeDTO employeeDTO = employeeDAO.findById(employeeId); if(employeeDTO == null) { employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription); employeeDAO.persist(employeeDTO); } } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void updateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception { EmployeeDTO employeeDTO = employeeDAO.findById(employeeId); if(employeeDTO != null) { employeeDTO.setEmployeeName(name); employeeDTO.setEmployeeSurname(surname); employeeDTO.setJob(jobDescription); } } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void deleteEmployee(long employeeId) throws Exception { EmployeeDTO employeeDTO = employeeDAO.findById(employeeId); if(employeeDTO != null) employeeDAO.remove(employeeDTO); } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void saveOrUpdateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception { EmployeeDTO employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription); employeeDAO.merge(employeeDTO); } }
这里要注意的事情:
- 我们使用@Service(“ employeeService”)构造型注释,以便声明该类以名称“ exampleService”表示Spring服务。 Spring容器将在启动时实例化所有服务
- 我们使用@Autowire批注将DAO类的实例注入“ employeeService”。 为了正确地实例化服务, Spring容器必须首先解析服务中所有可能的引用,因此实例化DAO类并将实例注入到“ employeeService”的适当字段–“ employeeDAO”字段。 如果您想知道,依赖项注入是根据类型(类)完成的,如果不满足则是根据名称完成的,这意味着如果我们定义了多个相同类型(类)的服务,则注入的服务将是名称相同的服务作为指定字段
- 我们使用Java批注@PostConstruct和@PreDestroy来声明在初始化(完成所有依赖项注入)和服务的先前销毁之后Spring容器将调用的方法。
- 对于需要对数据库执行更新操作的所有方法(INSERT,UPDATE,DELETE),我们使用@Transactional批注
- 我们不要在对数据库执行检索(FIND)操作的方法上使用@Transactional批注(包含延迟初始化的引用的对象除外-请参见下文),和/或不执行数据库操作。 那是因为每次您调用一个注解为事务性的方法时, Spring容器都会涉及到调用JPA的实体管理器以及结果平台的事务管理器,从而定义了将要应用的事务行为,特别是引入了明显的性能损失。适用于低延迟/高吞吐量应用
- 对于对包含延迟初始化的引用的对象执行检索(FIND)操作的方法,应使用@Transactional批注,指定“ NESTED”传播类型,以使Spring可以为整个方法调用保持Hibernate会话打开
- 事务处理行为仅应用于对服务的客户端调用。 事务处理行为不适用于内部操作调用。 例如,如果客户端调用未注释为事务性的操作,而后者的实现将对被注释为事务性的同一服务的另一个操作引入调用,则对于合并的操作,将不会应用任何事务行为。 这是因为Spring使用AOP代理类来强制执行事务行为
我们几乎完成了!,我们必须开发GWT用户界面才能访问我们的Spring服务。
找到您的GWT应用程序的入口点。 该文件应命名为“ Application.java”,并位于“客户端”子包或我们的主包下。 更改入口点类,如下所示
package com.javacodegeeks.gwtspring.client; import com.google.gwt.core.client.EntryPoint; 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; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; import com.javacodegeeks.gwtspring.shared.services.EmployeeServiceAsync; /** * Entry point classes define <code>onModuleLoad()</code>. */ public class Application 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. The error is : "; /** * Create a remote service proxy to talk to the server-side Employee service. */ private final EmployeeServiceAsync employeeService = EmployeeServiceAsync.Util.getInstance(); /** * This is the entry point method. */ public void onModuleLoad() { final Button saveOrUpdateButton = new Button("SaveOrUpdate"); final Button retrieveButton = new Button("Retrieve"); final TextBox employeeInfoField = new TextBox(); employeeInfoField.setText("Employee Info"); final TextBox employeeIdField = new TextBox(); final Label errorLabel = new Label(); // We can add style names to widgets saveOrUpdateButton.addStyleName("sendButton"); retrieveButton.addStyleName("sendButton"); // Add the nameField and sendButton to the RootPanel // Use RootPanel.get() to get the entire body element RootPanel.get("employeeInfoFieldContainer").add(employeeInfoField); RootPanel.get("updateEmployeeButtonContainer").add(saveOrUpdateButton); RootPanel.get("employeeIdFieldContainer").add(employeeIdField); RootPanel.get("retrieveEmployeeButtonContainer").add(retrieveButton); RootPanel.get("errorLabelContainer").add(errorLabel); // Focus the cursor on the name field when the app loads employeeInfoField.setFocus(true); employeeInfoField.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"); // We 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("<b>Sending request to the server:</b>")); dialogVPanel.add(textToServerLabel); dialogVPanel.add(new HTML("<br><b>Server replies:</b>")); 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(); saveOrUpdateButton.setEnabled(true); saveOrUpdateButton.setFocus(true); retrieveButton.setEnabled(true); } }); // Create a handler for the saveOrUpdateButton and employeeInfoField class SaveOrUpdateEmployeeHandler implements ClickHandler, KeyUpHandler { /** * Fired when the user clicks on the saveOrUpdateButton. */ public void onClick(ClickEvent event) { sendEmployeeInfoToServer(); } /** * Fired when the user types in the employeeInfoField. */ public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { sendEmployeeInfoToServer(); } } /** * Send the employee info from the employeeInfoField to the server and wait for a response. */ private void sendEmployeeInfoToServer() { // First, we validate the input. errorLabel.setText(""); String textToServer = employeeInfoField.getText(); // Then, we send the input to the server. saveOrUpdateButton.setEnabled(false); textToServerLabel.setText(textToServer); serverResponseLabel.setText(""); String[] employeeInfo = textToServer.split(" "); long employeeId = Long.parseLong(employeeInfo[0]); String employeeName = employeeInfo[1]; String employeeSurname = employeeInfo[2]; String employeeJobTitle = employeeInfo[3]; employeeService.saveOrUpdateEmployee(employeeId, employeeName, employeeSurname, employeeJobTitle, new AsyncCallback<Void>() { 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 + caught.toString()); dialogBox.center(); closeButton.setFocus(true); } public void onSuccess(Void noAnswer) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); serverResponseLabel.setHTML("OK"); dialogBox.center(); closeButton.setFocus(true); } }); } } // Create a handler for the retrieveButton and employeeIdField class RetrieveEmployeeHandler implements ClickHandler, KeyUpHandler { /** * Fired when the user clicks on the retrieveButton. */ public void onClick(ClickEvent event) { sendEmployeeIdToServer(); } /** * Fired when the user types in the employeeIdField. */ public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { sendEmployeeIdToServer(); } } /** * Send the id from the employeeIdField to the server and wait for a response. */ private void sendEmployeeIdToServer() { // First, we validate the input. errorLabel.setText(""); String textToServer = employeeIdField.getText(); // Then, we send the input to the server. retrieveButton.setEnabled(false); textToServerLabel.setText(textToServer); serverResponseLabel.setText(""); employeeService.findEmployee(Long.parseLong(textToServer), new AsyncCallback<EmployeeDTO>() { 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 + caught.toString()); dialogBox.center(); closeButton.setFocus(true); } public void onSuccess(EmployeeDTO employeeDTO) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); if(employeeDTO != null) serverResponseLabel.setHTML("Employee Information <br>Id : " + employeeDTO.getEmployeeId() + "<br>Name : " + employeeDTO.getEmployeeName() + "<br>Surname : " + employeeDTO.getEmployeeSurname() + "<br>Job Title : " + employeeDTO.getJob()); else serverResponseLabel.setHTML("No employee with the specified id found"); dialogBox.center(); closeButton.setFocus(true); } }); } } // Add a handler to send the employee info to the server SaveOrUpdateEmployeeHandler saveOrUpdateEmployeehandler = new SaveOrUpdateEmployeeHandler(); saveOrUpdateButton.addClickHandler(saveOrUpdateEmployeehandler); employeeInfoField.addKeyUpHandler(saveOrUpdateEmployeehandler); // Add a handler to send the employee id to the server RetrieveEmployeeHandler retrieveEmployeehandler = new RetrieveEmployeeHandler(); retrieveButton.addClickHandler(retrieveEmployeehandler); employeeIdField.addKeyUpHandler(retrieveEmployeehandler); } }
如您所见,对客户端透明地执行Spring服务调用,就像执行经典GWT服务调用一样。
最后找到您的项目的主页。 该文件应命名为“ Application.html”,位于项目的/ src / main / resources / {main_package} / public文件夹下(在我们的情况下为/ src / main / resources / com / javacodegeeks / gwtspring / public)。 更改主网页,如下所示
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!-- The HTML 4.01 Transitional DOCTYPE declaration--> <!-- above set at the top of the file will set --> <!-- the browser's rendering engine into --> <!-- "Quirks Mode". Replacing this declaration --> <!-- with a "Standards Mode" doctype is supported, --> <!-- but may lead to some differences in layout. --> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!-- --> <!-- Any title is fine --> <!-- --> <title>Spring GWT Web Application Starter Project</title> <!-- --> <!-- This script loads your compiled module. --> <!-- If you add any GWT meta tags, they must --> <!-- be added before this line. --> <!-- --> <script type="text/javascript" language="javascript" src="com.javacodegeeks.gwtspring.Application.nocache.js"></script> </head> <!-- --> <!-- The body can have arbitrary html, or --> <!-- you can leave the body empty if you want --> <!-- to create a completely dynamic UI. --> <!-- --> <body> <!-- OPTIONAL: include this if you want history support --> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> <!-- RECOMMENDED if your web app will not function without JavaScript enabled --> <noscript> <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif"> Your web browser must have JavaScript enabled in order for this application to display correctly. </div> </noscript> <h1 align="center"> Spring GWT Web Application Starter Project</h1> <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">Please enter employee info (id name surname job):</td> </tr> <tr> <td id="employeeInfoFieldContainer"></td> <td id="updateEmployeeButtonContainer"></td> </tr> <tr> <tr> <td colspan="2" style="font-weight:bold;">Please enter employee id:</td> </tr> <tr> <td id="employeeIdFieldContainer"></td> <td id="retrieveEmployeeButtonContainer"></td> </tr> <tr> <td colspan="2" style="color:red;" id="errorLabelContainer"></td> </tr> </table> </body> </html>
要构建应用程序,请右键单击您的项目? 运行为? Maven包
要部署Web应用程序,只需将“ .war”文件从“ target”目录复制到Apache – Tomcat “ webapps”文件夹
午餐应用程序将您的浏览器指向以下地址
http:// localhost:8080 / {application_name} /
如果一切顺利,您应该会看到您的主页。 应该显示两个文本框,每个文本框后面都有一个按钮。 在第一个文本框中,您可以将员工保存或更新到数据库。 作为输入,提供ID,名称,姓氏和职位描述,并用空格字符分隔。 单击“ SaveOrUpdate”按钮,将提供的信息存储到数据库中。 对于现有员工条目(相同的ID),将执行更新。 第二个文本框用于检索现有员工条目。 提供员工ID,然后单击“检索”按钮。 如果该员工存在,则应该看到该员工的ID,姓名,姓氏和职位描述。
您可以从这里下载项目
希望你喜欢
贾斯汀
相关文章 :- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程
- GWT Spring和Hibernate进入数据网格世界
- Spring 3 HornetQ 2.1集成教程
- Spring 3 RESTful Web服务
- 具有Spring和Maven教程的JAX–WS
相关片段:
翻译自: https://www.javacodegeeks.com/2010/07/gwt-2-spring-3-jpa-2-hibernate-35.html
gwt-2.8.2下载