完整的WebApplication JSF EJB JPA JAAS –第1部分

这篇文章将是迄今为止我博客中最大的一篇文章! 我们将看到完整的Web应用程序。 最新的技术将完成此工作(直到今天),但是我将给出一些提示以显示如何使本文适用于较旧的技术。

在本文的结尾,您将找到要下载的源代码。 您可以根据需要使用它。 只需转到最后一页并进行下载。 \ o /

如果您下载了代码但不了解某些内容,则在本文中,我将解释代码中找到的每个详细信息。 只需阅读此帖子中想要的主题即可。

我将在下面列出我将在本文中使用的技术:

  • JSF 2.0 Mojarra –使用ManagedBeans作为RequestScope和SessionScope。
  • 消息国际化–包含我们系统所有消息的文件; 轻松翻译您的页面。
  • 将作为库导入的默认CSS文件。
  • EJB 3 –我们的DAO和Façades将是@Stateless。
  • 通用DAO –通用DAO,它将执行CRUD动作以使我们的生活更轻松。
  • JPA 2 –在数据库中映射我们的类
  • JAAS –控制登录和用户对页面的访问。
  • MVC –我将使用此模式进行少量修改。
  • Postgres作为数据库,但我还将展示如何将您的应用设置为MySQL。

我不会使用TDD – JUnit测试我们的View / Model / Classes,但是在下面的链接中,您可以看到一种使用JUnit测试您的ManagedBeans的技术: 具有HSQLDB,JPA和Hibernate的JUnit

我们将使用的工具:

这篇文章将有几页; 这第一页只是显示今天帖子的技术细节。

我不会编写代码来连接模型/ DAO,只是为了节省空间。 请记住,您应该始终对接口进行编码( 设计模式-策略

在继续之前,请确保以正确的顺序安装了JBoss工具和JBoss 7。

商业模式

让我们创建将容纳我们的系统业务的EJB项目。

点击“ 完成 ”按钮。

让我们创建将在“ com”包中的User和Dog类。 它将具有以下代码:

package com.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name = 'USERS')
@NamedQuery(name='User.findUserByEmail', query='select u from User u where u.email = :email')
public class User {

 public static final String FIND_BY_EMAIL = 'User.findUserByEmail';

 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 private int id;

 @Column(unique = true)
 private String email;
 private String password;
 private String name;
 private String role;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }

 public String getPassword() {
  return password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getRole() {
  return role;
 }

 public void setRole(String role) {
  this.role = role;
 }

 @Override
 public int hashCode() {
  return getId();
 }

 @Override
 public boolean equals(Object obj) {
  if(obj instanceof User){
   User user = (User) obj;
   return user.getEmail().equals(getEmail());
  }

  return false;
 }
}
package com.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = 'DOGS')
public class Dog {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String name;
 private double weight;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public double getWeight() {
  return weight;
 }

 public void setWeight(double weight) {
  this.weight = weight;
 }

 @Override
 public int hashCode() {
  return getId();
 }

 @Override
 public boolean equals(Object obj) {

  if(obj instanceof Dog){
   Dog dog = (Dog) obj;
   return dog.getId() == getId();
  }

  return false;
 }
}

关于上面的代码:

  • User类具有一个名为“ role”的字段,该字段将存储用户的角色级别。 我将其创建为一个字段,并将所有数据保留在同一表中,以便于理解。 如果您想要有关JAAS的更多详细信息,可以在这篇文章中: 使用JAAS和JSF进行用户登录验证
  • 我将让JPA处理表ID代。 如果要更改ID的创建方式,可以查看以下文章以了解如何执行: JPA SequenceGeneratorJPA TableGenerator –简单Primay密钥
  • 该电子邮件将是唯一的; 这将是登录标识符。
  • 注意,要声明为Entity的类,只需要以下注释:“ @Entity”和“ @Id”。 该类不需要实现Serializable接口。

商业– DAO

我将使用通用DAO进行基本的CRUD操作,而其他两个DAO:一个用于User,另一个用于Dog。 理解它的用法将非常容易:

package com.dao;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

public abstract class GenericDAO<T> {
 private final static String UNIT_NAME = 'CrudPU';

 @PersistenceContext(unitName = UNIT_NAME)
 private EntityManager em;

 private Class<T> entityClass;

 public GenericDAO(Class<T> entityClass) {
  this.entityClass = entityClass;
 }

 public void save(T entity) {
  em.persist(entity);
 }

 public void delete(T entity) {
  T entityToBeRemoved = em.merge(entity);

  em.remove(entityToBeRemoved);
 }

 public T update(T entity) {
  return em.merge(entity);
 }

 public T find(int entityID) {
  return em.find(entityClass, entityID);
 }

 // Using the unchecked because JPA does not have a
 // em.getCriteriaBuilder().createQuery()<T> method
 @SuppressWarnings({ 'unchecked', 'rawtypes' })
 public List<T> findAll() {
  CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
  cq.select(cq.from(entityClass));
  return em.createQuery(cq).getResultList();
 }

 // Using the unchecked because JPA does not have a
 // ery.getSingleResult()<T> method
 @SuppressWarnings('unchecked')
 protected T findOneResult(String namedQuery, Map<String, Object> parameters) {
  T result = null;

  try {
   Query query = em.createNamedQuery(namedQuery);

   // Method that will populate parameters if they are passed not null and empty
   if (parameters != null && !parameters.isEmpty()) {
    populateQueryParameters(query, parameters);
   }

   result = (T) query.getSingleResult();

  } catch (Exception e) {
   System.out.println('Error while running query: ' + e.getMessage());
   e.printStackTrace();
  }

  return result;
 }

 private void populateQueryParameters(Query query, Map<String, Object> parameters) {

  for (Entry<String, Object> entry : parameters.entrySet()) {
   query.setParameter(entry.getKey(), entry.getValue());
  }
 }
}
package com.dao;

import javax.ejb.Stateless;

import com.model.Dog;

@Stateless
public class DogDAO extends GenericDAO<Dog> {

 public DogDAO() {
  super(Dog.class);
 }
}
package com.dao;

import java.util.HashMap;
import java.util.Map;

import javax.ejb.Stateless;

import com.model.User;

@Stateless
public class UserDAO extends GenericDAO<User> {

 public UserDAO() {
  super(User.class);
 }

 public User findUserByEmail(String email){
  Map<String, Object> parameters = new HashMap<String, Object>();
  parameters.put('email', email);  

  return super.findOneResult(User.FIND_BY_EMAIL, parameters);
 }
}

关于上面的代码:

  • 我隐藏了一些警告,因为JPA代码尚未“理解”泛型。
  • “ findOneResult”方法具有受保护的访问权限,只是为了防止其他类进行外部访问。 正如我们在UserDAO中看到的那样,此方法需要逻辑来填充参数。
  • GenericDAO类具有完整的CRUD方法以及给定NamedQuery返回单个对象的方法。
  • UserDAO类具有仅属于该类的方法(findUserByEmail); 但是它通过继承具有所有CRUD方法。 通过这种DAO模式,我们获得了更灵活的代码。
  • DogDAO中没有方法,只有CRUD方法。 您可以毫无问题地实现类中的任何方法。
  • 可以使用一种方法“ entityManager.merge()”代替使用“保存”方法,而使用其他方法“更新”对象。 您将获得相同的结果,但需要注意Cascade选项。
  • 我没有使用接口,因为EJB 3.1允许我们拥有无接口的无状态本地会话Bean。 如果使用的是较旧的EJB版本,则需要实现一个接口(如何在Façades页面上的这篇文章中看到如何使用接口实现EJB)。 我不会使用DAO /模型的接口进行开发,只是为了节省空间。 记住:“总是编程到一个接口”( 设计模式–策略 )。
  • 如果使用JBoss 4.2,则可以使用org.jboss.annotation.ejb.LocalBinding或org.jboss.annotation.ejb.RemoteBinding注释; 在此注释中,您可以编写将由EJB映射和引用的名称。

商业–外墙

我将创建Façades,它将成为View和DAO之间的“桥梁”。 在Façade中,我们将保留所有业务规则,仅将DAO保留为“数据库”功能/事务,例如CRUD和查询。

让我们看看我们的类UserFacade和DogFacade将如何:

package com.facade;

import java.util.List;

import javax.ejb.Local;

import com.model.Dog;

@Local
public interface DogFacade {

 public abstract void save(Dog dog);

 public abstract Dog update(Dog dog);

 public abstract void delete(Dog dog);

 public abstract Dog find(int entityID);

 public abstract List<Dog> findAll();
}
package com.facade;

import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import com.dao.DogDAO;
import com.model.Dog;

@Stateless
public class DogFacadeImp implements DogFacade {

 @EJB
 private DogDAO dogDAO;

 @Override
 public void save(Dog dog) {
  isDogWithAllData(dog);

  dogDAO.save(dog);
 }

 @Override
 public Dog update(Dog dog) {
  isDogWithAllData(dog);

  return dogDAO.update(dog);
 }

 @Override
 public void delete(Dog dog) {
  dogDAO.delete(dog);
 }

 @Override
 public Dog find(int entityID) {
  return dogDAO.find(entityID);
 }

 @Override
 public List<Dog> findAll() {
  return dogDAO.findAll();
 }

 private void isDogWithAllData(Dog dog){
  boolean hasError = false;

  if(dog == null){
   hasError = true;
  }

  if (dog.getName() == null || ''.equals(dog.getName().trim())){
   hasError = true;
  }

  if(dog.getWeight() <= 0){
   hasError = true;
  }

  if (hasError){
   throw new IllegalArgumentException('The dog is missing data. Check the name and weight, they should have value.');
  }
 }
}
package com.facade;

import javax.ejb.Local;

import com.model.User;

@Local
public interface UserFacade {
 public User findUserByEmail(String email);
}
package com.facade;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import com.dao.UserDAO;
import com.model.User;

@Stateless
public class UserFacadeImp implements UserFacade {

 @EJB
 private UserDAO userDAO;

 public User findUserByEmail(String email) {
  return userDAO.findUserByEmail(email);
 }
}

关于上面的代码:

  • DogFacadeImp类完成了从视图保护DogDAO的所有工作。 它可能具有业务规则,并且如果某些数据丢失或任何其他业务规则已被破坏,则避免访问数据库。
  • UserFacade只有一种方法,因为在这篇文章中我们将不会有一个User类。 如果视图未在HttpSession中找到,则Bean将仅搜索用户。
  • 如果使用JBoss 4.2,则可以使用org.jboss.annotation.ejb.LocalBinding或org.jboss.annotation.ejb.RemoteBinding注释; 在此注释中,您可以编写将由EJB映射和引用的名称。
  • 我在DogFacadeImp中进行验证,以确保Dog仅具有有效数据。 请记住,每个人都可以向您发送无效数据,并且您的视图验证可能无法按您预期的那样进行。 您的应用程序的数据非常重要,仔细检查总是值得的。

接口使用@Local进行注释,但我记得您该注释是可选的。 如果不写@Local批注,则服务器将默认假定您的EJB是本地的。

业务–数据源(按模块)

我们还需要设置数据源。

最初,我尝试通过遵循本教程http://community.jboss.org/wiki/JBossAS7-DatasourceConfigurationForPostgresql创建数据源(我确实像其他任何人一样都遵循教程),但是在部署时使用了一些错误EJB和JBoss找不到Postgres jar。

如果您使用的是JBoss 6或它下面的任何版本,则无需创建模块。 只需将文件放在“ default / lib”文件夹中即可。 如果您对设置数据源有任何疑问,请在下面的JBoss 6或其他版本中显示如何进行操作: 使用JAAS和JSF进行用户登录验证

让我们创建Postgres模块。 在JBoss 7内部创建目录: YOUR_JBOSS / modules / org / postgresql / main ”。 将jar复制到创建的目录并创建一个名为“ module.xml”的文件; 将下面的代码复制到“ module.xml”文件中:

<?xml version='1.0' encoding='UTF-8'?>
<module xmlns='urn:jboss:module:1.0' name='org.postgresql'>
 <resources>
  <resource-root path='postgresql-9.1-901.jdbc4.jar'/>
 </resources>
 <dependencies><module name='javax.api'/></dependencies>
</module>

请注意,在“ module.xml”文件中,我们编写了jar文件名,该名称必须与Postgres jar文件名相同。

要创建MySQL模块,请创建以下文件夹 YOUR_JBOSS / modules / com / mysql / main 。 将jar复制到创建的目录并创建一个名为“ module.xml”的文件; 将下面的代码复制到“ module.xml”文件中:

<?xml version='1.0' encoding='UTF-8'?>

<!--
  ~ JBoss copyrights
  ~ http://community.jboss.org/wiki/DataSourceConfigurationInAS7
  -->

<module xmlns='urn:jboss:module:1.0' name='com.mysql'>
  <resources>
    <resource-root path='mysql-connector-java-5.1.15.jar'/>
  </resources>
  <dependencies>
    <module name='javax.api'/>
  </dependencies>
</module>

让我们编辑文件“ YOUR_JBOSS / standalone / configuration / standalone.xml ”。 在键“ <datasources>”内,添加以下代码:

<datasources>
 <!-- Add this config: begin -->
 <datasource jndi-name='CrudDS' pool-name='CrudDS_Pool' enabled='true' jta='true' use-java-context='true' use-ccm='true'>
  <connection-url>jdbc:postgresql://localhost:5432/CrudDB</connection-url>
  <driver-class>org.postgresql.Driver</driver-class>
  <driver>postgresql-jdbc4</driver>
  <pool>
   <min-pool-size>2</min-pool-size>
   <max-pool-size>20</max-pool-size>
   <prefill>true</prefill>
   <use-strict-min>false</use-strict-min>
   <flush-strategy>FailingConnectionOnly</flush-strategy>
  </pool>
  <security>
   <user-name>postgres</user-name>
   <password>postgres</password>
  </security>
  <validation>
   <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
   <validate-on-match>false</validate-on-match>
   <background-validation>false</background-validation>
   <use-fast-fail>false</use-fast-fail>
  </validation>
 </datasource>
 <!-- Add this config: end -->
 <drivers>
  <!-- Add this config: begin -->
  <driver name='postgresql-jdbc4' module='org.postgresql'/>
  <!-- Add this config: end -->
 </drivers>

要使用MySQL配置数据源,请看这里:
http://community.jboss.org/wiki/DataSourceConfigurationInAS7

业务– XML配置

让我们看看我们的persistence.xml将会如何(该文件必须在文件夹src / META-INF中):

<?xml version='1.0' encoding='UTF-8'?>
<persistence version='1.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_1_0.xsd'>
    <persistence-unit name='CrudPU' transaction-type='JTA'>
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/CrudDS</jta-data-source>
        <properties>
            <property name='hibernate.hbm2ddl.auto' value='update'/>
        </properties>
    </persistence-unit>
</persistence>

我们有一个非常简单的代码; 它只是指向一个数据源,并带有使用“ update”生成所有数据库表的选项。

将EJB项目添加到JBoss。

在Postgres中创建数据库并启动JBoss; 启动后,JPA将创建表。

在下面的图片中查看JPA为我们创建的表/序列。

在WEB-INF文件夹中创建一个名为“ jboss-web.xml”的文件,并在其中编写以下代码:

<?xml version='1.0' encoding='UTF-8'?>

<jboss-web>
 <!-- URL to access the web module -->
 <context-root>CrudJSF</context-root>

 <!-- Realm that will be used -->
 <security-domain>java:/jaas/CrudJSFRealm</security-domain>
</jboss-web>

在上面的文件中,我们设置了应用程序将使用的领域。 让我们将用户插入将通过JAAS进行登录的数据库中(如果您想查看有关JAAS的更多详细信息,可以在此处查看: 使用JAAS和JSF的用户登录验证 )。 我不会获得JAAS详细信息,因为您可以找到上一个链接中详细介绍的每个步骤。

在下面的图像中看到我在数据库中手动插入的数据(您应该执行相同的操作):

继续本教程的第二部分

参考: uaiHebert博客上来自我们的JCG合作伙伴 Hebert Coelho的完整WebApplication JSF EJB JPA JAAS


翻译自: https://www.javacodegeeks.com/2012/06/full-webapplication-jsf-ejb-jpa-jaas.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值