JavaEE Web Project(jboss quickStart)简单的增加和显示操作

jboss quickStart创建的项目,从index页面开始学习。整理学习遇到的问题

实现目标: 

实现member的新增和数据库表的显示

每新增一条记录自动刷新列表

一、自己要实现的页面:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	
	xmlns:p="http://primefaces.org/ui"
   	xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
	>
<h:body>
	<br /> 新增
	<h:form>
		<h:panelGrid columns="2">
			<h:outputLabel value="name" for="name"/>
			<h:inputText value="#{myNewMember.name}" id="name"/>
			
			<h:outputLabel value="email" for="email"/>
			<h:inputText value="#{myNewMember.email}" id="email"/>
			
			<h:outputLabel value="phoneNumber" for="phoneNumber"/>
			<h:inputText value="#{myNewMember.phoneNumber}" id="phoneNumber"/>
			
			<h:commandButton action="#{myController.myRegister()}" value="register" />
		</h:panelGrid>
	</h:form>
	
	<br /> 表格
	<ui:remove>
		<p:dataList value="#{memberController.memberList()}" var="_member" >
			<f:facet name="header">
				Member
			</f:facet>
			<p:panel header="#{_member.id}">
				<h:outputText value="#{_member.email}" class="removeBtn"/>
			</p:panel>
		</p:dataList>
	</ui:remove>
	
	<p:dataList value="#{myMembers}" var="_member" >
		<f:facet name="header">
			Member
		</f:facet>
		<p:panel header="#{_member.name}">
			<h:outputText value="#{_member.email}" class="removeBtn"/>
		</p:panel>
	</p:dataList>
</h:body>
</html>

<?xml version="1.0" encoding="UTF-8"?> 页面编码格式,不然传到后台的数据格式乱码!

#{memberController.memberList()} 是在model里写的静态的查询数据表信息,无法接收event事件实现自动刷新。代码如下

package org.jboss.tools.examples.controller;

import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.jboss.tools.examples.model.Member;
import org.jboss.tools.examples.service.MemberRegistration;

// The @Model stereotype is a convenience mechanism to make this a request-scoped bean that has an
// EL name
// Read more about the @Model stereotype in this FAQ:
// http://www.cdi-spec.org/faq/#accordion6
@Model
public class MemberController {
 
    @Inject
    private EntityManager em;
    
    //写个查询list
    public List<Member> memberList(){
    	
    	CriteriaBuilder criteriaBuilder  = em.getCriteriaBuilder();
		CriteriaQuery<Member> query = criteriaBuilder.createQuery(Member.class);	//createQuery的参数是Query返回值类型
		Root<Member> member = query.from(Member.class);								//参数是对应于order表的实体类,query.from类似于sql中的from语句,该方法的执行等价于sql中的from Member。
		
		//默认查询全部
		query.select(member);	//query.select(root)则等价于select *
		TypedQuery<Member> tq = em.createQuery(query);	
		List<Member> list = tq.getResultList();
    	return list;
    }

}

 

 

二、显示 myMembers

1、后台代码如下,这里通过打印语句把构造函数和 @PostConstruct 注解进行了比较,代码执行顺序。构造函数先执行,@PostConstruct再执行一次。

2、主要就是查询 myMembers 列表,类是@RequestScoped,每次request执行一次class(例如一次action)

3、CDI事件

知识点只有两个:

1 @Observes注解

2 Event<T>接口

正确的做法是写一个观察者类,在观察者类中的观察方法参数里加上@Observes注解就可以了。

参考例子:CDI进阶第五步 CDI事件

当前例子中 @Observes 新增完以后 会通知观察者 重新获取数据 实现当前页面的刷新 

reGetMemberList方法再一次被执行,myMembers重新获取新值,实现页面刷新。

4、特别注意 @Produces
    @Named 的位置

二者缺一不可,缺少一个,html就定位不到该bean方法。

@Produces 动态注入,标识生产者方法或字段。 可以应用于bean类的方法或字段。

@Named 基于字符串的限定符。

@Named注释的主要作用是定义一个bean,用于解析应用程序中的EL语句,通常是通过JSF EL解析器。

 

 

 

package org.jboss.tools.examples.data;

import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.jboss.tools.examples.model.Member;

@RequestScoped
public class MyMemberListProducer {
	
	//构造函数
	public MyMemberListProducer() {
		System.out.println("MyMemberListProducer 构造函数");
	}
	
	
	private List<Member> myMembers;

	@Inject
	private EntityManager em;

	
	@Produces
	@Named
	public List<Member> getMyMembers() {
		return myMembers;
	}
	
	//新增完以后 会通知观察者  重新获取数据 实现当前页面的刷新
	public void reGetMemberList(@Observes Member member) {
		
		System.out.println("@Observes:"+member.getName());
		
		getMemberList();
	}
	
	//构造函数以后执行这里
	@PostConstruct
	public void getMemberList() {
		
		System.out.println("MyMemberListProducer @PostConstruct");
		
		myMembers = memberList();
	}
	
	public List<Member> memberList() {
		
		System.out.println("开始查询数据库...");
		
		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		CriteriaQuery<Member> query = criteriaBuilder.createQuery(Member.class); // createQuery的参数是Query返回值类型
		Root<Member> member = query.from(Member.class); // 参数是对应于order表的实体类,query.from类似于sql中的from语句,该方法的执行等价于sql中的from

		// 默认查询全部
		query.select(member); // query.select(root)则等价于select *
		// 条件查询
		// Predicate condition = criteriaBuilder.equal(member.get("name"), "王灵生");
		// query.where(condition);

		TypedQuery<Member> tq = em.createQuery(query);

		List<Member> list = tq.getResultList();
		return list;
	}

}

5、页面第一次加载 

 

 

三、新增myNewMember

1、这里使用 @Produces     //动态注入
    @Named    注解 myNewMember 

2、@PostConstruct 第一次就执行 完成初始化 

3、以为涉及到 persist操作,需要用到事物。单独在model里写的话会报错,需要添加@Transactional注解。

根据官方Demo学习,写了一个方法myRegister,使用@stateless 注解(这里的解释是 @Stateless注释消除了手动事务划分的需要)

解释

@stateless 是EJB的bean,EJB不需要配置任何注解就自带了事物,所以这里添加了 @Stateless就不用添加@Transactional注解了。CDI与EJB不同的是默认不带事物上下文的,要是直接在@Model里面写数据库操作的话就会报错!

 

4、fire涉及到CDI的 event 

这个代码里注入了一个事件对象。在业务方法中将调用事件对象的绑定方法。然后CDI上下文就会去找观察者。

也可以参考以下链接学习:

CDI(Weld)高级<4> Event(事件) 

CDI进阶第五步 CDI事件

 

 

package org.jboss.tools.examples.controller;

import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import org.jboss.tools.examples.model.Member;
import org.jboss.tools.examples.service.MyMemberRegistration;

@Model
public class MyController {

	@Inject
	private MyMemberRegistration myMemberRegistration;
	
	@Produces
	@Named
	private Member myNewMember;

	//注解,初始化执行一次
	@PostConstruct
	public void initMyMember() {
		myNewMember = new Member();
	}
	
	public void myRegister() throws Exception{	
		myMemberRegistration.myRegister(myNewMember);	
		//清空 界面
		initMyMember();
	}
}

 

//The @Stateless annotation eliminates the need for manual transaction demarcation
//@Stateless注释消除了手动事务划分的需要

@Stateless
public class MyMemberRegistration {
	
	@Inject
	private EntityManager em;
	
	@Inject
	private Event<Member> event;
	
	public void myRegister(Member member) {
		em.persist(member);
		
		//通知观察者 执行带 @Observes 的方法 (重新获取数据库中的member)
		//使用指定的限定符触发事件并通知观察者。
		event.fire(member);	
	}

 

四、测试

新增点击register按钮就会写入数据库一条新纪录,下面的列表自动更新。

这样就完成了一个最基本简单的新增查询操作,涉及到的注解特别多,理解方法的执行顺序特别关键。

还学习到了观察者模式,想起了以前开发android用到的EventBus,哦,之前是传参,好像不太一样!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿姨不可以嘛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值