大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说Jdon框架开发指南「建议收藏」,希望能够帮助大家进步!!!
Jdon框架快速开发指南开发主要步骤如下:
JdonFramework6.0以上两步开发见这里。快速配置指南
新增/查询/修改/删除(CRUD);
批量查询和分页显示
本文Step By Step详细讲解如何使用Jdon框架基于领域模型快速开发这两个功能,通过Jdon框架的可以快速完成系统原型(ArcheType),使得开发者将真正精力集中在每个项目系统的特殊业务处理。
本案例源码下载
按这里查看更详细全面文档
快速配置指南Jdon框架有一个配置文件叫jdonframework.xml,其中配置的是我们编写的Java类,格式如下:
代码语言:javascript代码运行次数:0运行复制
或者使用Annotation注解@Service或@Component,就无需上面这个配置。
假如我们编写了一个类TestServicePOJOImp,代码简要如下:
| //@Service("testService")public class TestServicePOJOImp implements TestService{
private JdbcDAO jdbcDao;
public TestServicePOJOImp(JdbcDAO jdbcDao) { this.jdbcDao = jdbcDao; }
public void createUser(EventModel em) { .... } }
接口TestService代码:
public interface TestService {
void createUser(EventModel em);
} |
|:----|
上面TestServicePOJOImp代码创建完成后,下面有两个并行步骤:
如果在TestServicePOJOImp类前加上@Service注解,就可以了,无需再XML配置。2.如果你为了更加松耦合,在未来更换类时,不再重新编译源码,那么可以采取XML配置这个步骤,我们在源码目录需要创建一个叫jdonframework.xml配置文件,内容如下:
|
|:----|
这样,在servlet或jsp或struts的action等客户端代码中,我们可以使用如下代码调用TestServicePOJOImp,注意:以下代码没有具体TestServicePOJOImp类:
| TestService testService = (TestService) WebAppUtil.getService("testService ", request);testService.createUser(em); |
|:----|
以上步骤,只是简单展示框架的一个简要步骤,你可能没有觉得多了一个jdonframework.xml以后,好像比平常代码没什么不同,关键是:如果我们需要使用AnotherTestServicePOJOImp更换原来的TestServicePOJOImp类,只需要更改jdonframework.xml文件,而无须更改客户端代码,也无须重新编译项目了。
当然,还有另外一个优点,就是Ioc/DI依赖注射,细心的人已经注意到TestServicePOJOImp有一个构造参数如下:
代码语言:javascript代码运行次数:0运行复制 public TestServicePOJOImp(JdbcDAO jdbcDao) {
this.jdbcDao = jdbcDao;
}如果不传入JdbcDAO实例,我们如何能在客户端代码中直接创建TestServicePOJOImp实例呢?原来只要我们在jdonframework.xml中再配置一个JdbcDAO类,概时框架就会自动帮我们创建JdbcDAO实例,并且传入TestServicePOJOImp实例中。
新的jdonframework.xml内容如下:
|
|:----|
再进一步,如果我们经常遇到一些类中需要一些常量或参数定义,那么可以使用如下配置:
|
|:----|
这时,要求JdbcDAO构造参数有一个字符串和参数,这样constructor的值java:/TestDS就在JdbcDAO被创建时注射到它的实例中。 JdbcDAO代码如下:
代码语言:javascript代码运行次数:0运行复制public class JdbcDAO{
......
public JdbcDAO(String jndiName){
System.out.println("jndiname" = jndiName);
......
}
......
}启动Jdon框架
有了jdonframework.xml,我们需要在项目中启动它,有两种启动方式:一个是结合struts的struts-config.xml配置方式;另外一个是不结合struts的web.xml配置方式。
第一:web.xml配置方式:
如果你不使用Struts,可以通过web.xml下列配置来启动Jdon框架。
|
|:----|
上述param-value可以配置多个配置,中间以逗号隔开,如下:
|
|:----|
第二:结合struts配置方式(需要struts基础知识):
在struts-config.xml中配置Plugin实现子类:
|
|:----|
按这里查看更详细全面文档
增删改查(CRUD)和批量分页查询是每个系统的基本功能,下面分这两部分描述。
CRUD开发步骤说明:每个应用系统中存在大量重复的CRUD开发流程,通过本框架可快速完成这些基本基础工作量,将精力集中在特殊功能设计上。 CRUD快速开发主要简化了表现层的流程,将其固化,或者是模板化,以配置替代代码编制,灵活而快速。每个Model一套固化CRUD流程。
CRUD开发步骤分两个部分:代码编写 、配置。
CRUD代码: 代码只需要三步:
1、域建模:建立UserTest类如下:
代码语言:javascript代码运行次数:0运行复制 //@Model
public class UserTest extends Model {
private String userId;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
.......
}
注意点:
模型必须以@Model标注或者继承框架的com.jdon.controller.model.Model,或者实现com.jdon.controller.model.ModelIF接口。该模型类必须有一个能够标识其对象唯一性的主键,如userId,这个主键相当于数据表的主键,这个规定符合Evans DDD规定。 为了激活 Domain Model的对象实例驻留内存缓存中,在持久层模型类创建时,加入下面标注:
代码语言:javascript代码运行次数:0运行复制 @Component()
@Introduce("modelCache")
public class UserDAOJdbc implements UserRepository{
@Around
public UserTest getUser(String Id) {
...... //fetch from key-value stores or relation DB
}
}代码语言:txt复制 DCI:数据Data, 场景Context, 交互Interactions是由MVC发明者Trygve Reenskaug发明的。 见 DCI架构是什么? DCI让我们的核心模型更加简单,只有数据和基本行为。业务逻辑等交互行为在角色模型中 在运行时的场景,将角色的交互行为注射到数据中。代码语言:txt复制 JdonFramework的Domain Events是DCI的交互行为,在实现领域事件的同时也实现了DCI。代码语言:txt复制 为更清楚说明DCI,下面以JdonFramework案例说明。代码语言:txt复制 领域模型是DCI的Data,只有数据和基本行为,更简单,但注意不是只有setter/getter的贫血模型。如下:代码语言:javascript代码运行次数:0运行复制 @Model
public class UserModel {
private String userId;
private String name;
@Inject
private ComputerRole computerRole;
代码语言:txt复制 Domain Events事件或消息的生产者也就是DCI中的角色Role,比如我们有一个专门进行计数计算的角色,实际上真正计算核心因为要使用关系数据库等底层技术架构,并不真正在此实现,而是依托消息消费者@Consumer实现,那么消息生产者可以看出是一个接口,消费者看成是接口的实现:代码语言:javascript代码运行次数:0运行复制 @Introduce("message")
public class ComputerRole {
@Send("computeCount")
public DomainMessage computeCount(UserModel user) {
return new DomainMessage(user);
}
@Send("saveUser")
public DomainMessage save(UserModel user) {
return new DomainMessage(user);
}
}
代码语言:txt复制 DCI第三个元素是场景Context,在这个场景下,ComputeRole将被注入到模型UserModel中,实现计数计算的业务功能:代码语言:javascript代码运行次数:0运行复制 public class ComputeContext {
private DomainMessage ageAsyncResult;
public void preloadData(UserModel user) {
if (ageAsyncResult == null)
ageAsyncResult = user.getUserDomainEvents().computeCount(user);
}
public int loadCountNow(UserModel user) {
preloadData(user);
return (Integer) ageAsyncResult.getEventResult();
}
public int loadCountByAsync(UserModel user) {
if (ageAsyncResult == null)
ageAsyncResult = user.getUserDomainEvents().computeCount(user);
else if (ageAsyncResult != null)
return (Integer) ageAsyncResult.getEventResult();
return -1;
}
}
代码语言:txt复制 2、建立Model组件服务:首先建立模型的服务接口TestService:代码语言:javascript代码运行次数:0运行复制 public interface TestService {
void createUser(EventModel em);
void updateUser(EventModel em);
void deleteUser(EventModel em);
UserTest getUser(String userId);
}
代码语言:txt复制至于TestService的具体实现子类可以在现在或者以后建立 3、建立Model的表现层边界模型UserActionForm,必须继承框架的ModelForm,如下:
代码语言:javascript代码运行次数:0运行复制 public class UserActionForm extends ModelForm {
private String userId;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
....
} 表现层UserActionForm内容基本上是从业务层[模型](https://javajgs.com/go?url=http://cpro.baidu.com/cpro/ui/uijs.php?app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=e05d01307b9df40e&k=%C4%A3%D0%CD&k0=%C4%A3%D0%CD&kdi0=0&luki=5&n=10&p=baidu&q=banq_cpr&rb=0&rs=1&seller_id=1&sid=ef49d7b30015de0&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1683405&u=http%3A%2F%2Fwww%2Ejdon%2Ecom%2Fjdonframework%2Fthreemin%2Ehtm&urlid=0)UserTest类中拷贝过来的,属于界面对象,用来显示或录入数据。
一个模型的CRUD实现的代码工作到此结束,如果有其他模型,完全按照上述三个步骤再做一次,是不是不太费脑筋?有点模板化开发味道?下面谈谈CRUD实现第二组成部分
CRUD配置:
两个配置文件分别是:
将前面三步编写的类建立关系:jdonframework.xml配置界面流程:struts-config.xml一、Jdon框架配置文件
首先我们将前面三步编写的三个类:模型UserTest、服务TestService和界面模型UserActionForm建立起联系,也就是告诉Jdon框架这三者是解决一个模型增删改查CRUD功能实现的。 由于这个配置文件是告诉Jdon框架的,因此,我们取名为jdonframework.xml,当然你也可以取其他名称,无论取什么名称,都要告诉Jdon框架,在struts-config.xml中配置:
代码语言:javascript代码运行次数:0运行复制
jdonframework.xml配置内容如下:
class ="com.jdon.framework.test.model.UserTest">
......
class="com.jdon.framework.test.service.TestServicePOJOImp"/> ...... 以上配置是配置模型UserTest、模型服务TestService和界面模型UserActionForm三者关系的,下面详细说明三个部分的配置: 1、模型UserTest的配置: 这是通过第一行中的class值来指定当前Model是com.jdon.framework.test.model.UserTest: 代码语言:javascript代码运行次数:0运行复制 代码语言:javascript代码运行次数:0运行复制 代码语言:javascript代码运行次数:0运行复制 …… ….. 可见我们的界面模型完整类com.jdon.framework.test.web.UserActionForm是在[struts](https://javajgs.com/go?url=http://cpro.baidu.com/cpro/ui/uijs.php?app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=e05d01307b9df40e&k=struts&k0=struts&kdi0=0&luki=3&n=10&p=baidu&q=banq_cpr&rb=0&rs=1&seller_id=1&sid=ef49d7b30015de0&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1683405&u=http%3A%2F%2Fwww%2Ejdon%2Ecom%2Fjdonframework%2Fthreemin%2Ehtm&urlid=0)-config.[xml](https://javajgs.com/go?url=http://cpro.baidu.com/cpro/ui/uijs.php?app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=e05d01307b9df40e&k=xml&k0=xml&kdi0=0&luki=2&n=10&p=baidu&q=banq_cpr&rb=0&rs=1&seller_id=1&sid=ef49d7b30015de0&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1683405&u=http%3A%2F%2Fwww%2Ejdon%2Ecom%2Fjdonframework%2Fthreemin%2Ehtm&urlid=0)中form-beans中配置,并且命名为userActionForm,而这个userActionForm就是jdonframework.xml中的userActionForm。 3、模型服务TestService配置: 在jdonframework.xml中首先申明TestService完整实现是类com.jdon.framework.test.service.TestServicePOJOImp,并且取名为testService: 代码语言:javascript代码运行次数:0运行复制 代码语言:javascript代码运行次数:0运行复制 黑体字部分正是testService所指的接口TestService四个方法,可见前面代码步骤第二步。 二、界面流程配置 界面流程主要是配置CRUD界面流程,Jdon框架CRUD流程主要分两个部分:第一是推出供用户新增修改删除的页面;第二是接受用户提交新增修改过的数据,以便递交到业务层保存。 这部分配置主要是配置struts-config.xml: 1、配置推出CRUD页面流程: 代码语言:javascript代码运行次数:0运行复制 scope="request" validate="false"> 代码语言:javascript代码运行次数:0运行复制 userId: 其实在上一步的user.jsp中已经使用到这一步的配置,在user.jsp的表单action值就是本步配置的path值:/userSaveAction.do: 代码语言:javascript代码运行次数:0运行复制 scope="request" validate="true" input="/user.jsp"> 批量分页查询实现批量分页查询开发步骤也分两个部分:代码编写 、配置。 批量查询代码实现: 代码也分三步实现。 1、表现层编写一个查询Action,继承Jdon框架的com.jdon.strutsutil.ModelListAction,该类名称为com.jdon.framework.test.web.UserListAction,完成getPageIterator和findModelByKey两个方法。 其中getPageIterator方法内容是业务层TestService的调用: 代码语言:javascript代码运行次数:0运行复制 TestService testService = (TestService) WebAppUtil.getService("testService",request); return testService.getAllUsers(start, count); 所以TestService接口中必须有getAllUsers这个方法,主要功能是返回PageIterator对象findModelByKey方法内容也是业务层TestService的调用: 代码语言:javascript代码运行次数:0运行复制 TestService testService = (TestService) WebAppUtil.getService("testService", request); return testService.getUser((String)key); TestService接口中必须有**getUser**方法。 2、业务层实现TestService接口方法getAllUsers内容,一般是直接调用持久层JdbcDao方法。 3、持久层实现返回PageIterator对象: 代码语言:javascript代码运行次数:0运行复制 public PageIterator getUsers(int start, int count) throws Exception { String GET_ALL_ITEMS_ALLCOUNT = "select count(1) from usertest ";//usertest是数据表名 String GET_ALL_ITEMS = "select userId from usertest ";//usertest是数据表名 return pageIteratorSolver. getPageIterator (GET_ALL_ITEMS_ALLCOUNT, GET_ALL_ITEMS, "",start, count); } 如果有参数,可以如下查询: 代码语言:javascript代码运行次数:0运行复制 public PageIterator getUsers(Long categoryId, int start, int count) { String GET_ALL_ITEMS_ALLCOUNT = "select count(1) from usertest where categoryId = ? "; String GET_ALL_ITEMS = "select userId from usertest where categoryId = ? "; Collection params = new ArrayList(1); params.add(categoryId);//paramters will be put into Collection return pageIteratorSolver.getPageIterator(GET_ALL_ITEMS_ALLCOUNT, GET_ALL_ITEMS, params, start, count); } 批量查询配置一、Jdon框架配置文件 本步骤主要是需要告诉jdonframework.xml我们的TestService实现子类是什么,以及调用的JdbcDao等组件,jdonframework.xml如下: 代码语言:javascript代码运行次数:0运行复制 因为TestServicePOJOImp类中调用了JdbcDAO,JdbcDAO中又涉及JNDI名称,所以它们之间依赖关系靠Jdon框架的IOC容器实现。TestServicePOJOImp必须有构造器如下: 代码语言:javascript代码运行次数:0运行复制 public class TestServicePOJOImp implementsTestService{ private JdbcDAO jdbcDAO; public TestServicePOJOImp(JdbcDAO jdbcDAO){ this.jdbcDAO = jdbcDAO; } } 二、界面流程配置 这一步主要是struts-config.xml配置,和通常struts的ActionForm和Action配置类似: 代码语言:javascript代码运行次数:0运行复制 …… 其中com.jdon.[struts](https://javajgs.com/go?url=http://cpro.baidu.com/cpro/ui/uijs.php?app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=e05d01307b9df40e&k=struts&k0=struts&kdi0=0&luki=3&n=10&p=baidu&q=banq_cpr&rb=0&rs=1&seller_id=1&sid=ef49d7b30015de0&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1683405&u=http%3A%2F%2Fwww%2Ejdon%2Ecom%2Fjdonframework%2Fthreemin%2Ehtm&urlid=0)util.ModelListForm是框架批量查询特别使用的类。 代码语言:javascript代码运行次数:0运行复制 type="com.jdon.framework.test.web.UserListAction" scope="request"> 代码语言:javascript代码运行次数:0运行复制 .........
代码语言:javascript代码运行次数:0运行复制 模型UserTest的批量查询功能已经全部完成。 以上是介绍基于开源Jdon框架开发软件系统中的CRUD和批量查询功能步骤,遵循模板化开发,开发人员使用起来轻松而不容易出错,适合软件生产和严格的项目管理。 本案例源码下载 按这里查看更详细全面文档 附件:本案例代码结构图: 本案例全部代码(struts+jdon+jpa/hibernate架构): 业务模型类代码 @Entitypublic class UserTest extends Model { private String userId; private String name; @Id public String getUserId() { return userId; } public String getName() { return name; } public void setUserId(String userId) { this.userId = userId; } public void setName(String name) { this.name = name; } } 持久层代码 public class JdbcDAO extends DaoTemplate { private final static Logger logger = Logger.getLogger(JdbcDAO.class); public JdbcDAO(CacheManager cacheManager, DaoCRUD daoCRUD) { super(cacheManager, daoCRUD); } public PageIterator getModels(int start, int count) throws Exception{ String GET_ALL_ITEMS_ALLCOUNT = "select count(1) from usertest "; String GET_ALL_ITEMS = "select userId from usertest "; return pageIteratorSolver.getDatas("", GET_ALL_ITEMS_ALLCOUNT, GET_ALL_ITEMS, start, count); } } 业务层服务代码基本是委托持久层操作的简单代码 public class TestServicePOJOImp implements TestService, Poolable{ private final static Logger logger = Logger .getLogger(TestServicePOJOImp.class); private final static String USER_SAVE_ERROR = "USER.SAVE.ERROR"; private JdbcDAO jdbcDao; public TestServicePOJOImp(JdbcDAO jdbcDao) { this.jdbcDao = jdbcDao; } public void createUser(EventModel em) { UserTest user = (UserTest) em.getModel(); try { jdbcDao.insert(user); } catch (Exception ex) { logger.error(ex); em.setErrors(USER_SAVE_ERROR); } } public void updateUser(EventModel em) { UserTest user = (UserTest) em.getModel(); try { jdbcDao.update(user); } catch (Exception ex) { logger.error(ex); em.setErrors(USER_SAVE_ERROR); } } public void deleteUser(EventModel em) { UserTest user = (UserTest) em.getModel(); try { jdbcDao.delete(user); } catch (Exception ex) { logger.error(ex); em.setErrors(USER_SAVE_ERROR); } } public UserTest getUser(String userId) { logger.debug(" get User from DAO + JDBC " + userId); return (UserTest)jdbcDao.loadModelById(UserTest.class, userId); } public PageIterator getAllUsers(int start, int count) { PageIterator pageIterator = null; try { pageIterator = jdbcDao.getModels(start, count); } catch (Exception ex) { logger.error(ex); } return pageIterator; } } 表现层代码 public class UserListAction extends ModelListAction { private final static Logger logger = Logger.getLogger(UserListAction.class); public Model findModelByKey(HttpServletRequest request, Object key) { Model model = null; try { logger.debug("get the model for primary key=" + key + " type:"+ key.getClass().getName()); TestService testService = (TestService) WebAppUtil.getService("testService", request); model = testService.getUser((String)key); } catch (Exception ex) { logger.debug("get the model for primary key=" + key + " type:"+ key.getClass().getName()); logger.error(" error: " + ex); } return model; } public PageIterator getPageIterator(HttpServletRequest request, int start, int count) { PageIterator pageIterator = null; try { TestService testService = (TestService) WebAppUtil.getService("testService", request); pageIterator = testService.getAllUsers(start, count); } catch (Exception ex) { logger.error(ex); } return pageIterator; } }
Name: