CDI可以理解为Spring,但其中的一些功能比spring更强大,灵活。本章是个简单的项目示例。推荐有一定基础的看。
1.JPA定义(MVC--M)
@Entity
public class User {
private @NotNull @Length(min=3, max=25) @Id String username;
private @NotNull @Length(min=6, max=20) String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String setPassword(String password) { this.password = password; }
}
Bean Validation 里面注解可参考http://my.oschina.net/zhaoqian/blog/118458
2.定义一个managedBean(MVC-C)
@Named(' Credentials')
@RequestScoped
public class CredentialsBean{
private String username;
private String password;
@NotNull @Length(min=3, max=25)
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@NotNull @Length(min=6, max=20)
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
3.jsf登录页面(MVC-V)
<h:form>
<h:panelGrid columns="2" rendered="#{!login.loggedIn}">
<f:validateBean>
<h:outputLabel for="username">Username:</h:outputLabel>
<h:inputText id="username" value="#{credentials.username}"/>
<h:outputLabel for="password">Password:</h:outputLabel>
<h:inputSecret id="password" value="#{credentials.password}"/>
</f:validateBean>
</h:panelrid>
<h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
<h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form>
4.定义2个qualifier注解
我们要用session scope bean 维护当前登录用户信息,并提供给上下文的其他Bean使用.
首先定义2个qualifier。用于登录,JPA EntityManager。
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, PARAMETER, FIELD})
public @interface LoggedIn {}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, PARAMETER, FIELD})
public @interface UserDatabase {}
A:我们需要适配一个类型安全的EntityManager:,作为资源存在于项目中,JPA就可以以inject的方式注入调用。代码如下:
class UserDatabaseProducer {
@Produces
@UserDatabase
@PersistenceContext
static EntityManager userDatabase;
}
5.开发SessionScope
@SessionScoped @Named
public class Login implements Serializable {
@Inject Credentials credentials;
@Inject @UserDatabase EntityManager userDatabase;
private User user;
public void login() {
List<User> results = userDatabase.createQuery(
"select u from User u where u.username = :username and u.password = :password")
.setParameter("username", credentials.getUsername())
.setParameter("password", credentials.getPassword())
.getResultList();
if (!results.isEmpty()) {
user = results.get(0);
}
else {
// perhaps add code here to report a failed login
}
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user != null;
}
@Produces @LoggedIn User getCurrentUser() {
return user;
}
}
现在,其他的Bean就可以随意的注入 qualifiers为:@LoggedIn,type为: User的资源。
如下代码调用:
public class ViewUserBean {
@Inject @LoggedIn User currentUser;
@Inject @UserDatabase EntityManager docDatabase;
public void viewUser() {
//........todo
}
}
在页面:
<h:panelGroup rendered="#{login.loggedIn}">
signed in as #{currentUser.username}
</h:panelGroup>
最后写出一段相关在实际项目中使用的resources。
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Resources {
/**
* We are using a non JTA managed persistence context, so we cannot inject an EntityManager with @PersistenceContext,
* as this would try to inject a container managed EntityManager.
*/
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
@Produces
@RequestScoped
protected EntityManager createEntityManager() {
return entityManagerFactory.createEntityManager();
}
protected void closeEntityManager(@Disposes EntityManager entityManager) {
if ( entityManager.isOpen() )
entityManager.close();
}
// if you using JTA,you can used this
// @Produces
// @PersistenceContext
// EntityManager em;
@Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}
在其他Bean就可以直接@inject这样注入使用。会非常方便。
如: @Inject EntityManager em;
@Inject Logger log;
本章用于CDI项目演示。