本博客文章的目的是带您从简单的静态网页开始,直到我们拥有以下列表中的完整堆栈。我将这个堆栈称为“Summer”,因为在漫长的寒冬之后,春天可能很美好,但等到夏天到来时,那就更美了 ;-)

  • CDI (Weld)
  • JSF 2 (facelets, ICEfaces 2)
  • JPA 2 (Hibernate, Envers)
  • EJB 3.1 (无本地视图,异步,单例,调度)
  • Bean Validation (Hibernate Validator)
  • JMS (MDB)
  • JAX-RS (RESTEasy)
  • JAX-WS
  • Arqullian (incontainer-AS6)

我们将将这些功能打包到一个单独的WAR文件中。因为我们能这样做(剧透:在第 IV 部分)。请注意,除了组件和测试框架外,它们都是标准?这有很多东西。幸运的是,应用服务器已经提供了大部分东西,所以您的应用程序仍然相对较小。

至于我使用的环境

  • Eclipse (Galileo SR2)
  • JBoss 6.0 M3
  • Maven 3 (beta1)
  • Sun JDK 6
  • m2eclipse 0.10

这不会是一篇典型的博客文章,其中一切都很顺利——我们会遇到错误。会有诅咒、鲜血和内脏,以及戏剧性的情节,我们将随着进程进行而进行工作区间的解决方案和重写。这几乎与您作为软件开发商的平均一天看起来几乎一样。我在这篇文章中使用的技术也不是专家,所以可能有些事情可以做得更好。将此视为我在EE6领域的经验记录,这可能与其他人的经历相呼应。我也不会提供链接或额外信息,假设如果您说“RESTEasy”,那么如果您感兴趣,您可以通过谷歌搜索更多相关信息。

而且我差点忘了:不要慌张。

开始:项目设置

那么,让我们开始吧 - 如果您还没有,请下载环境中提到的内容。我不会通过引导您来完成这个任务来侮辱您的智商(稍后提醒我侮辱它)。此外,这很简单。

让我们创建一个新的Maven项目(文件 -> 新建 -> 项目... -> Maven -> Maven项目。我们跳过存根选择,只创建一个简单的项目,组ID为com.acme,构件ID为Greetings,版本为1.0.0-SNAPSHOT,打包为WAR。现在完成向导,现在您应该有一个完美、理想的项目。我们的下一步是向其中添加代码,它将永远保持这种完美。

针对Windows用户的Maven每日小贴士。在Google上搜索如何更改本地仓库的路径,因为它可能位于文档和设置下的某个位置,这将有两个影响:类路径会变得非常大,并且由于空格可能会导致问题。将其更改为类似于c:\java\m2repo的位置。

我们首先注意到m2eclipse默认使用J2SE-1.4。这是2002年吗?此外,这将使得使用注解变得不可能,因此让我们将其更改为。编辑pom.xml并添加以下内容

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>2.3.1</version>
			<configuration>
				<source>1.6</source>
				<target>1.6</target>
			</configuration>
		</plugin>
	</plugins>
</build>

保存并右键单击项目根目录,然后选择Maven -> 更新项目配置。啊,这样好多了

JSF

让我们唤醒JSF。我们在src/main/webapp下创建一个WEB-INF文件夹,并添加一个web.xml,因为没有web应用是完整的(由maven war插件强制)。好的,实际上这可以在插件中配置,但让我们保留web.xml,因为稍后我们还需要它。

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.0" 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_3_0.xsd"/>

并在旁边放置一个空的faces-config.xml

<faces-config 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-facesconfig_2_0.xsd"
              version="2.0"/>

然后在webapp中添加一个greeting.xhtml,如下所示

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:ui="http://java.sun.com/jsf/facelets">
	<h:head>
		<title>
			Greetings
		</title>
	</h:head>

	<h:body>
		<h:outputText value="Hello world"/>
	</h:body>
</html>

它会融合吗?我是说,它会部署吗?执行mvn clean package,您应该在项目的target目录下看到一个Greetings-1.0.0-SNAPSHOT。将其放入AS服务器/default/deploy目录中,启动服务器,然后访问

http://localhost:8080/Greetings-1.0.0-SNAPSHOT/faces/greetings.xhtml

URL不够美观,但服务器端口、Web上下文根、欢迎文件和JSF映射都可以稍后调整,让我们现在关注技术和依赖项。但是等等 - 我们在web.xml中定义了JSF.servlet和映射在哪个点?我们没有。对于启用了JSF的应用程序,这是自动的。

EJB和CDI

下一步是引入一些后端bean,让我们将问候外包出去。我们创建一个无状态的EJB并在CDI中使用它。

package com.acme.greetings;

@Stateful
@Model
public class GreetingBean 
{
	public String getGreeting()
	{
		return "Hello world";
	}
}

@Stateful定义了一个有状态的会话EJB(由于是POJO,所以是3.1版本),@Model是一个CDI泛型,它具有@RequestScoped和@Named属性(这意味着生命周期绑定到一个单个HTTP请求,并且它有一个可以在EL中引用的名称,在本例中默认为greetingBean)。但是我们有问题 - 注解没有解析到任何内容。因此,我们需要从某处获取它们(tm)。幸运的是,我们可以通过在pom.xml中添加以下内容来自动获取所有API

<dependencies>
	<dependency>
		<groupId>org.jboss.spec</groupId>
		<artifactId>jboss-javaee-6.0</artifactId>
		<version>1.0.0.Beta4</version>
		<type>pom</type>
		<scope>provided</scope>
	</dependency>
</dependencies>

Sun Java API构件有点有趣,因为获取它们可能有点棘手。首先,它们在JSR中发布它们,然后它们像对待绝密一样对待它们。幸运的是,Glassfish和JBoss现在开始在自己的存储库中提供它们(尽管使用自己的构件名称,但仍然)...

我们还必须确保根据http://community.jboss.org/wiki/MavenGettingStarted-Users设置了JBoss存储库。看看项目中的Maven Dependencies发生了什么。好的。现在关闭它并退后。那里的事情变得复杂了,所以最好相信Maven从此跟踪依赖项。

现在应该在bean中可用,所以我们导入

import javax.ejb.Stateful;
import javax.enterprise.inject.Model;

并将bean与

<h:body>
	<h:outputText value="#{greetingBean.greeting}"/>
</h:body>

在greeting.xhtml中EL挂钩。

就像没有web.xml的web应用是不完整的,没有bean.xml的CDI应用也是不完整的。让我们将其添加到WEB-INF中。

<?xml version="1.0" encoding="ISO-8859-1"?>
<beans 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/beans_1_0.xsd" />

打包和重新部署。编译时我们收到关于编码的警告,所以让我们将这个添加到我们的pom.xml文件中。

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

回到http://localhost:8080/Greetings-1.0.0-SNAPSHOT/faces/greetings.xhtml SUCCESS! 等等。一大堆堆栈跟踪信息让你受到300点伤害。让我们回到我们的EJB上,在AS 6 M3的WAR-only打包中3.1风格的EJB还有一些问题。移除@Stateful注解,它就变成了一个普通的CDI管理POJO。重新打包。重新部署。回收。

测试

现在测试很流行,所以我们引入Arquillian。Arquillian是EE测试(嵌入式或容器内)的最新和最伟大工具。现在就开始使用它。大约一年后,当其他人赶上来时,你可以去说 "我从Alpha版本就开始使用了"。将以下属性添加到pom.xml中

<arquillian.version>1.0.0.Alpha2</arquillian.version>

以及这些依赖项

<dependency>
	<groupId>org.jboss.arquillian</groupId>
	<artifactId>arquillian-junit</artifactId>
	<version>${arquillian.version}</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.8.1</version>
	<scope>test</scope>
</dependency>

以及这个配置文件

<profiles>	
	<profile>
		<id>jbossas-local-60</id>
		<dependencies>
			<dependency>
				<groupId>org.jboss.arquillian.container</groupId>
				<artifactId>arquillian-jbossas-local-60</artifactId>
				<version>1.0.0.Alpha2</version>
			</dependency>
			<dependency>
				<groupId>org.jboss.jbossas</groupId>
				<artifactId>jboss-server-manager</artifactId>
				<version>1.0.3.GA</version>
			</dependency>
			<dependency>
				<groupId>org.jboss.jbossas</groupId>
				<artifactId>jboss-as-client</artifactId>
				<version>6.0.0.20100429-M3</version>
				<type>pom</type>
			</dependency>
		</dependencies>
	</profile>
</profiles>

Maven现在可能会为你下载整个互联网。

让我们编写我们的第一个测试并将其放置在测试源文件夹中

package com.acme.greetings.test;

import javax.inject.Inject;

import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.acme.greetings.GreetingBean;

@RunWith(Arquillian.class)
public class GreetingTest 
{
	@Inject
	GreetingBean greetingBean;

	@Deployment
	public static JavaArchive createTestArchive() 
	{
		return ShrinkWrap.create("test.jar", JavaArchive.class).addClass(
				GreetingBean.class).addManifestResource(
				new ByteArrayAsset("<beans/>".getBytes()),
				ArchivePaths.create("beans.xml"));
	}

	@Test
	public void testInjection() 
	{
		Assert.assertEquals("Hello World", greetingBean.getGreeting());
	}

}

然后我们使用 mvn test -Pjbossas-local-60 来尝试它。如果我们有AS运行,我们可以节省一些时间,否则管理器会自动启动它。设置JBOSS_HOME环境变量有帮助。这里发生的事情是,我们使用Shrinkwrap创建一个部署,其中包含我们的GreetingBean和一个空的beans.xml文件(用于CDI),然后该bean被注入以供测试中使用。

这完成了第一部分。在第二部分中,我们将设置ICEfaces并扩展我们的应用程序,在第三部分中我们将设置JPA。第四部分是用于MDB和EJB,第五部分是添加JAX-RS和JAX-WS以导入和导出内容。


返回顶部