Java SE还可以。
Java EE是邪恶的。
这就是我一直想的。 好吧,现在不再了。 让我分享我的经验。
几周前,我开始考虑将旧版spring + hibernate + tomcat应用程序移植到新平台上: SAP NetWeaver云 。 我知道您在极客那里的想法:这篇文章越来越糟。 它从Java EE开始,不完全是一个怪胎,而现在进入SAP ,不完全是一个怪胎公司……请再给我十分钟!
我的遗留应用程序的spring层的配置是基于xml的(它是在注释进入游戏之前编写的)。 我对再次陷入我自己的xml恐怖的前景感到恐惧。
然后出现此推文:
欢迎@ sap参加#JavaEE6聚会,NetWeaver Cloud现在已通过Java EE 6 Web Profile认证: bit.ly/Wf8VNS
— GlassFish(@glassfish) 2012年11月16日
几天后,还有本文档 。 我尝试了。 而且有效。 我改变了对Java EE的想法。 “水管工比尔”(Bill the Plumber)有一篇博客文章, 准确地描述了我在经历之后的想法 。
bla bla bla太多了。 让我们开始编码! 如果您赶时间,请从https://github.com/cthiebaud/adventscloud克隆完整的应用程序
在疯狂剪切和粘贴之前,让我们简要描述一下下面的代码。 我们将免费构建一个小型Web应用程序并将其部署到云中:
1.登录用户(对不起,您需要一个SAP Community Network帐户,不用担心它是免费的),
2.登录后,代表用户向世界其他地方问好,
3.连续登录后,不必一遍又一遍地说“你好”,而只是在数据库中存储说了多少个“ hellos”,并且
4.就是这样。
为此,我们需要一个Java接口,三个Java类,一个Java服务器页面以及persistence.xml(用于数据库配置)和web.xml(用于安全性约束向导)的最终版本。
为了简洁起见,以下代码中省略了包,导入,getter和setter。 但是,正如刚刚所说的, 完整的源代码可以在github上找到。
编写一个Hello.java POJO( 此处是完整的类):
public class Hello {
private Long id;
private String username;
private Integer counter;
private Timestamp when;
// ... getters and setters ...
}
显而易见:对于每个username ,此POJO都会在counter存储用户点击我们应用程序的index.jsp的次数,以及上次是when 。
使用JPA批注对此Hello.java POJO批注( 在此处完成类):
@Entity
@Table(name="T_HELLO")
@NamedQueries( {
@NamedQuery(name = "allHellos", query = "select h from Hello h"),
@NamedQuery(name = "helloFromUsername", query = "select h from Hello h where h.username = :username")
})
public class Hello {
@Id
@GeneratedValue
private Long id;
@Column(name="A_USER", unique=true, nullable=false)
private String username;
@Column(name="A_COUNTER", nullable=false)
private Integer counter;
@Version
@Column(name="A_TIMESTAMP", nullable=false)
private Timestamp when;
public Hello() {
this.counter = 1;
}
// ... getters and setters ...
}
编写一个访问POJO的HelloDao.java接口( 此处为完整接口)
@Local
public interface HelloDao {
List<hello> getAll();
Hello fromUsername(String username);
Hello save(Hello hello);
}
编写一个用EJB注释注释的HelloBean.java,它实现了HelloDao接口( 此处是完整的类):
@Stateless
public class HelloBean implements HelloDao {
@PersistenceContext
private EntityManager em;
@Override
public List<hello> getAll() {
@SuppressWarnings("unchecked")
List<hello> hellos = (List<hello>)em.createNamedQuery("allHellos").getResultList();
Collections.sort(hellos, new Comparator<hello>() {
@Override
public int compare(Hello o1, Hello o2) {
return o2.getWhen().compareTo(o1.getWhen()); // latest first
}
});
return hellos;
}
@Override
public Hello fromUsername(String username) {
Query query = em.createNamedQuery("helloFromUsername");
query.setParameter("username", username);
Hello hello = null;
try {
hello = (Hello)query.getSingleResult();
} catch (NoResultException ignored) {
}
return hello;
}
@TransactionAttribute
@Override
public Hello save(Hello hello) {
hello = em.merge(hello);
return hello;
}
}
编写一个HelloFilter.java Java Servlet 3过滤器,该过滤器是1.登录时更改计数器,并且2.在即将推出的Java Server页面( 此处是完整类)中公开HelloBean实例:
@WebFilter("/index.jsp")
public final class HelloFilter implements Filter {
@EJB
HelloDao helloDao;
@Override
public void init(FilterConfig fConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
request.setAttribute("helloDao", helloDao);
String username = ((HttpServletRequest)request).getRemoteUser();
Hello hello = helloDao.fromUsername(username);
if (hello == null) {
hello = new Hello();
hello.setUsername(username);
} else {
hello.setCounter(hello.getCounter()+1);
}
hello = helloDao.save(hello);
chain.doFilter(request, response);
} finally {
request.removeAttribute("helloDao");
}
}
@Override
public void destroy() {
}
}
注意 上面的粗体字是我们的Java EE 6 Web Profile容器在所有这些类之间完成的神奇工作:
@PersistenceContext EntityManager em;
@EJB HelloDao helloDao;
@WebFilter('/index.jsp')
编写一个persistence.xml JPA配置( 在此处完成xml)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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">
<persistence-unit name="adventscloud-persist" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/DefaultDB</jta-data-source>
<class>net.aequologica.adventscloud.Hello</class>
<properties>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
</properties>
</persistence-unit>
</persistence>
编写一个web.xml,以在用户访问index.jsp时触发登录,并通知Web应用程序容器管理数据库的存在( 在此处完整xml):
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<login-config>
<auth-method>FORM</auth-method>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/index.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Everyone</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>All SAP NetWeaver Cloud users</description>
<role-name>Everyone</role-name>
</security-role>
<resource-ref>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
</web-app>
再次,NB。 以上以粗体显示的进一步魔术效果:
<jta-data-source>jdbc/DefaultDB</jta-data-source>
<class>net.aequologica.adventscloud.Hello</class>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
最后,编写一个index.jsp Java服务器页面,其中显示所有“ hellos”( 此处完整页面):
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<!DOCTYPE html>
<html>
<head>
<title>adventscloud</title>
</head>
<body>
<table>
<tbody>
<c:forEach var="hello" items="${requestScope.helloDao.all}" varStatus="status">
<tr>
<td><fmt:formatDate type="both" value="${hello.when}" /></td>
<td>${hello.counter}</td>
<td>hello<c:if test = "${hello.counter > 1}">(s)</c:if> from</td>
<td>${hello.username}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
我们几乎完成了……最后两件事:1.类路径地狱,以及2.使用javac -processor生成JPA 2.0元模型。
1.类路径地狱。
为了编译所有这些东西,您需要某种方式在类路径上具有以下jar:
group | artifact | version
javax.persistence : persistence-api : >= 1.0
javax.ejb : ejb-api : >= 3.0
javax.servlet : javax.servlet-api : >= 3.0
javax.servlet : jstl : >= 1.2
当然,最简单的方法是在像我的maven项目中声明这些依赖关系,但是如果您是厌恶Maven的人,我会花一些时间超链接到上面的jars,以便在maven Central中节省一些时间来追逐jars。
2.使用javac -processor生成JPA 2.0元模型。
最后,该构建必须能够生成JPA 2.0元模型类 。 在这里,我选择eclipselink生成器,因为eclipselink最终是SAP NetWeaver Cloud使用的JPA实现。 我相信,任何符合JPA 2.0的生成器也应完成此工作。 同样,maven在pom.xml的<build> <plugins>部分中提供了以下xml片段,可以为您提供帮助:
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<processors>
<processor>org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor>
</processors>
</configuration>
</execution>
</executions>
</plugin>
Maven-averse可以参考有关JPA 2.0 matamodel生成的eclipselink文档,以获取生成JPA 2.0元模型类的替代方法。
至此,我们有了一个adventscloud.war文件,该文件应在所有符合Java EE 6 Web Profile的容器上逐字运行。
其中包括SAP NetWeaver Cloud。 您可以在我的SAP NetWeaver Cloud终生免费试用版实例上运行该应用程序。 它比本博客文章中显示的代码更丰富,并带有Twitter引导程序的响声。 如果您对火花感兴趣,请遵循应用程序中的github功能区。
如果你想获得的SAP NetWeaver云的免费的终身试用实例,请描述的初始步骤在这里 。
参考: Java EE 6 Web配置文件。 在云上。 简单。 在Java Advent Calendar博客上可以从我们的JCG合作伙伴 Christophe Thiebaud获得。
翻译自: https://www.javacodegeeks.com/2012/12/java-ee-6-web-profile-on-the-cloud-easy.html