浏览 4141 次
锁定老帖子 主题:Seam 使用心得(二)接口实现
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-12-19
最后修改:2009-11-13
@Local public interface Register { public String register(); } 这一节里面将实现这个接口来通过测试。 现在应用系统有很多良好的分层方法,但是我还是喜欢Evans的领域驱动设计的方法。 1,视图层将使用RichFaces。 2,使用无状态SessionBean作为Facade对领域逻辑进行封装。 3,领域层实现核心业务逻辑,主要包括有实体,值对象,仓库,服务等。 源文件目录结构大致如下: src |----action (SLSB) |----model (Service, Entity, Repository, Vo) |----test view |----css |----js …… 经过简单的分析model层向facade暴露UserView接口 package org.qpt.domain.user; import org.qpt.domain.user.User.RegState; /** * 用户接口 * @author xiaoqiu */ public interface UserView { String getConfirmPwd(); String getEmail(); String getName(); String getPwd(); /** * 注册一个新用户 * @param ur 用户仓库接口 * @return 注册结果状态码(共5种状态,上一节已经提到过) */ RegState register(UserRepository ur); void setConfirmPwd(String confirmPwd); void setEmail(String email); void setName(String name); void setPwd(String pwd); } 注:因为EJB2严重的依赖于容器的基础设施,如果在实体bean中包含业务逻辑,将很难进行测试,所以实体bean只能作为数据容器,而背离面向对象的分析和设计方法。但是EJB3已经可以对实体进行透明持久化,并且很容易在容器外进行测试,所以就用User实体实现UserView接口,这里用户注册的并没有跨越多个实体,只涉及用户实体,所以包含了业务方法register的User类代码如下: /** * 用户实体 * * @author xiaoqiu */ @Entity @Name("user") @Scope(SESSION) @Table(name = "users") public class User implements Serializable, UserView { private static final long serialVersionUID = 3836699581343986461L; @Id @NotNull @Length(min = 6, max = 15) private String name; @NotNull @Length(min = 6, max = 15) private String pwd; @Transient private String confirmPwd; @NotNull @Email private String email; @Transient private String confirmEmail; public enum RegState { EXISTS_EMAIL, EXISTS_NAME, PWD_NOT_EQ_IN_TWICE, EMAIL_NOT_EQ_IN_TWICE, SUCCESS } @Override public RegState register(UserRepository ur) { if (!pwd.equals(confirmPwd)) { return PWD_NOT_EQ_IN_TWICE; } else if (!email.equals(confirmEmail)) { return EMAIL_NOT_EQ_IN_TWICE; } else if (ur.findByProperty("name", name)) { return EXISTS_NAME; } else if (ur.findByProperty("email", email)) { return EXISTS_EMAIL; } else { ur.save(this); return SUCCESS; } } …… get&set method } 考虑到视图层RichFaces和hibernate验证结合可以进行很简单的零脚本ajax验证,所以本例子里面使用了hibernate验证。 由于register方法需要用的UserRepository来访问数据库,所以现在来看一下UserRepository接口。通过隔离基础设施,这就是GOF设计模式中著名的Strategy模式,由于Java语言想要在实体中注入UserRepository在技术上存在困难,所以把UserRepository作为方法的参数传递我个人认为也是一种较为简洁的方法,而且通过接口的隔离不会和基础设施产生强烈的耦合,UserRepository代码如下: /** * 用户仓库接口 * @author xiaoqiu */ @Local public interface UserRepository { void save(User user); User findByName(String name); List<User> findAllUser(); /** * 找出该属性是否存在当前值 * @param name 属性名 * @param value 属性值 * @return 该属性存在这个值返回true,否则返回false */ boolean findByProperty(String name, String value); } 在本例里面UserRepository的实现使用的JPA,这个接口的实现相当容易所以它的实现类UserRepositoryJPAImp代码就不贴出来了,可以直接看提供的源码。 model层的接口已经实现完毕,接下来实现facade,代码如下: @Stateless @Name("register") public class RegisterBean implements Register { @Logger private Log log; @In FacesMessages facesMessages; @In private UserView user; @In("userRepository") UserRepository ur; public String register() { RegState state = user.register(ur); switch (state) { case PWD_NOT_EQ_IN_TWICE: log.info("the register state is " + state); facesMessages.addFromResourceBundle("myapp.register.pwd.noteq"); break; case EMAIL_NOT_EQ_IN_TWICE: log.info("the register state is " + state); facesMessages.addFromResourceBundle("myapp.register.email.noteq"); break; case EXISTS_NAME: log.info("the register state is " + state); facesMessages.addFromResourceBundle("myapp.register.name.exists"); break; case EXISTS_EMAIL: log.info("the register state is " + state); facesMessages.addFromResourceBundle("myapp.register.email.exists"); break; case SUCCESS: log.info("register a new user #{user.name}" + "\nthe register state is " + state); facesMessages.addFromResourceBundle("myapp.register.success"); break; } return state.toString(); } } 这里facade是很薄的一层,不能包含任何业务逻辑,它主要根据model返回的状态是向显示层发送信息,使用facesMessages组件就可以很容易向Richfaces发送ajax验证的响应信息,并且事务处理统一在facade层进行,由于使用EJB,所以就可以使用容器提供的事务管理。 上述类的结构如下图所示: facade: Register-->RegisterBean-->UserView&UserRepository domain:UserView-->User(Eneity)<-->UserRepository-->UserRepositoryJPAImp 至此为止,注册用户所需要的全部接口都已经实现,现在就可以用seam test命令来运行上一节写好的测试代码了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-12-24
如何把一个SESSION BEAN注入到另外一个SESSION BEAN中阿?
@In(value="chatroomAction") ChatRoomAction chatroomAction; 这个代码老是报错: Could not set field value by reflection: DepartMentAction.chatroomAction on: com.ctazc.zs.web.action.newuser.DepartMentAction with value: class org.javassist.tmp.java.lang.Object_$$_javassist_6 |
|
返回顶楼 | |
发表时间:2007-12-24
我在运用时候,我直接在coponents.xml里写了数据库session hs
<core:manager conversation-timeout="120000" concurrent-request-timeout="500" conversation-id-parameter="cid"/> <persistence:hibernate-session-factory name="hibernateSessionFactory"/> <persistence:managed-hibernate-session name="hs" session-factory="#{hibernateSessionFactory}" auto-create="true"/> <transaction:hibernate-transaction session="#{hs}"/> 如果我在DAOImpl里引用这个hs, public class userDAO { @In private Session hs public void saveUser(User user) { hs.save(user); } } 那么 这个hs是空的,也就是说的不到数据库的链接 而在托管bean里却能得到,这是为什么 |
|
返回顶楼 | |
发表时间:2007-12-28
这几天有时间的话准备写一下 第三章 视图与导航,但是有一个RichFaces的问题一直没解决-_-!,那就是我原本打算在 离开用户名输入框 的时候触发一个Ajax事件验证是否存在用户名,但是发现这样会报异常,只能在提交的时候触发Ajax事件验证用户名是否重复……
不知道哪位遇到过 |
|
返回顶楼 | |
发表时间:2008-01-24
DDD领域驱动设计结合seam不错。
|
|
返回顶楼 | |