- 浏览: 118427 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
lufazhi:
楼主,是否可以将源码分享,谢谢,小弟初次接触nutz不太理解, ...
基于Nutz与ExtJs的快速开发 -
qazxcdews:
jbpm不是使用hibernate吗?你是怎么将Nutz与jb ...
ExtJS+Nutz+JBPM实现一个简单的请假流程 -
kk63643813:
代码很经典,楼主你很强,代码思路也很好,求源码,谢谢17146 ...
使用Nutz+ExtJS+JBPM4.4实现会签 -
qinboss:
...
jbpm4表结构(1) -
han0917:
hello,我想问下我使用XBlink序列化对象为xml的时候 ...
最近的一点计划
这里对Nutz与ExtJs都进行二次封装,使前后台代码尽可能的复用,大部分操作都是在基类中完成的。
使用过程请看附件中的视频。
生成后的代码:
后台代码
分别在src目录下生产了java代码,在resource目录下生成了nutz的配置文件。
model层
User.java
package org.nutz.demo3.model.admin; import java.util.Date; import java.util.List; import java.util.Set; import org.nutz.dao.entity.annotation.Column; import org.nutz.dao.entity.annotation.Id; import org.nutz.dao.entity.annotation.Name; import org.nutz.dao.entity.annotation.Table; @Table("user") public class User { @Id private long id; @Column private String name; @Column private int age; @Column private Date birthday; @Column private String phone; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
Srevice层
UserService.java
package org.nutz.demo3.service.admin; import com.geor.nutz.common.service.EntityService; import org.nutz.demo3.model.admin.User; public interface UserService extends EntityService<User> { }
UserServiceImpl.java
package org.nutz.demo3.service.impl.admin; import com.geor.nutz.common.service.impl.EntityServiceImpl; import org.nutz.demo3.model.admin.User; import org.nutz.demo3.service.admin.UserService; public class UserServiceImpl extends EntityServiceImpl<User> implements UserService { }
可以看到这里的Service层代码非常简洁(ME觉得已经不能再简洁了,这里可是一行代码都木有呀!),常用的增删改查功能,已经在基类中实现了。
Nutz本身就提供了类似EntityService这样的基类,大家也可以去看看。
这里是觉得自己封装的更加顺手些,并加入了一些Nutz本身没有提供的特性,大家可以仿照Nutz提供的基类,在自己需求的基础上来实现自己的基类。
Action层
UserAction.java
package org.nutz.demo3.action.admin; import javax.servlet.http.HttpServletRequest; import org.nutz.ioc.annotation.InjectName; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Param; import com.geor.nutz.extjs.action.ExtEntityAction; import org.nutz.demo3.model.admin.User; import org.nutz.demo3.service.admin.UserService; @InjectName("UserAction") @At("/admin/user") public class UserAction extends ExtEntityAction<UserService, User> { public void needCombobox() { // TODO Auto-generated method stub } public Object fetch(@Param("..") User entity, HttpServletRequest request) { // TODO Auto-generated method stub return null; } @At() public Object insert(@Param("..") User entity, HttpServletRequest request) { return getService().insert(entity); } @At() public Object update(@Param("..") User entity, HttpServletRequest request) { return getService().update(entity); } @At() public Object delete(@Param("..") User entity, HttpServletRequest request) { return getService().delete(entity); } @At() public Object save(@Param("entities") User[] entities, HttpServletRequest request) { return getService().save(entities); } }
这里会继承一个ExtEntityAction
在这个基类中,有针对ExtJS的特点,进行了一些列的封装,因为在ExtJS中某些数据,需要使用特定的格式,所以这里只针对前台ExtJS的情况。
将来如果前台框架换了其他的,只需要仿照这个基类,做一个对应的就可以了。而Service层与model层的代码是不需要改动的。
可以看到,这里没有list方法(查询)与clear方法(批量删除),那是因为他们在方法入参没有自定义类型的情况下,可以抽共通,放到基类中。
而insert,update,delete等等方法,因为参数会自动转换为User类型,入参中必须使用这个自定义类型,所以实在是无法省略掉这部分代码,因为本人最初的想法也是将这一层做成像Service层一样,一行代码也没有...那样看起来是多么的爽呀(好吧,ME承认自己有点偏执了)
oh,还有一个Nutz的入口函数,这是Nutz启动时的关键。
Entrance.java
package org.nutz.demo3.action; import org.nutz.mvc.annotation.Fail; import org.nutz.mvc.annotation.IocBy; import org.nutz.mvc.annotation.Modules; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Views; import org.nutz.mvc.ioc.provider.JsonIocProvider; import com.geor.nutz.extjs.view.ExtViewMaker; /** * 系统入口。 * * @author pangwu86@gmail.com * */ @IocBy(type = JsonIocProvider.class, args = { "/action.js", "/aop.js" }) @Modules(scanPackage = true) @Views(ExtViewMaker.class) @Ok("ext") @Fail("ext") public class Entrance { }
这里会使用一个自定义View,是针对ExtJS封装的,大家不要问为什么哪里都有封装,如果不封装,不代码复用,生成的代码怎么可能会如此简洁来,代码复用确实是必须的。
其实@Ok("ext"),本质上还是@Ok("json"),只是针对ExtJS格式的特点做了一些特殊处理。
@Modules(scanPackage = true)
这句话的作用就是扫描当前目录下的文件(包括子目录),发现有Action类的话,就会将其配置的路径信息加载,你在后面访问时,才会进去到对应的方法中。用了它,你就尽管在该目录下写action类吧,自动扫描会一个不拉的全部加载,不用在一个一个配置了。
有了上述代码,后台的就基本完成了,下面是配置文件的情况。
Service.js
/** * 服务。 */ var services = { UserService : { type : 'org.nutz.demo3.service.impl.admin.UserServiceImpl', singleton : false } }
这里用过IOC的都会明白,依赖注入,不解释了。
Action.js
/** * * @type */ var actions = { UserAction : { type : "org.nutz.demo3.action.admin.UserAction", singleton : false, scope : "session" } }
这里本身其实可以不用Nutz的容器,但因为为了使用AOP做log输出与事务控制,这里所有的Action必须是在容器中的。
Aop.js
/** * AOP的定义与规则。 * * @type */ var aop = { /** * 记录日志。 * * @type */ log : { type : 'com.geor.nutz.common.aop.LogAop' }, /** * 声明式事务。 * * @type */ trans : { type : 'com.geor.nutz.common.aop.TransAop' }, /** * aop规则。 * * @type */ $aop : { type : 'org.nutz.ioc.aop.config.impl.JsonAopConfigration', fields : { itemList : [ ['org\.nutz\.demo3\.action\..+\..+', '(insert|update|delete|clear|save)', 'ioc:log'], ['org\.nutz\.demo3\.action\..+\..+', '(insert|update|delete|clear|save)', 'ioc:trans'] ] } } };
这种AOP的使用方式应该是Nutz中最简单却最强大好用(兽(又是屏蔽词)兽出品,必属精品)
Nutz本身也就提供了TransAop与LogAop,ME只是对其做了一下汉化与加入了点个性化东西,大家使用默认的即可。
可以看到只要通过一个牛X的正则表达式,你就可以对工程中你想aop的地方插一脚了,so easy!
Jdbc.js
/** * JDBC配置信息。 * * @type */ var jdbc = { dataSource : { type : "com.mchange.v2.c3p0.ComboPooledDataSource", events : { depose : 'close' }, fields : { driverClass : 'com.mysql.jdbc.Driver', jdbcUrl : 'jdbc:mysql://localhost:3306/nutz', user : 'root', password : 'toor' } } };
数据库连接,直接copy官方文档中的,nutz中有对常用的四种数据库连接池的写法,方便大家copy。
log4j.properties
不贴代码了,没有意义,反正是帮你默认生成一个,如果有现成的,就不会再生成了。
后台代码还一个就是web.xml,新建工程里的web.xml只有首页信息,要加上nutz的配置信息才行。
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Demo3</display-name> <!-- filter定义 --> <filter> <filter-name>entrance</filter-name> <filter-class>org.nutz.mvc.NutFilter</filter-class> <init-param> <param-name>modules</param-name> <param-value>org.nutz.demo3.action.Entrance</param-value> </init-param> </filter> <filter-mapping> <filter-name>entrance</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- listener定义 --> <listener> <listener-class>org.nutz.mvc.NutSessionListener</listener-class> </listener> <!-- 首页 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
就是加入了org.nutz.mvc.NutFilter这个过滤器,拦截下所有的请求(/*)
然后通过上面配置的入口函数,进去到对应的Action中。
前台代码
前台代码,默认生成在page目录下,js目录下就是ExtJS的类库了,还有一个针对其部分空间二次封装的类库xExt。
来看一下生成页面文件
user.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>用户管理</title> <link rel='stylesheet' type='text/css' href='../../js/resources/css/ext-all.css'/> <link rel='stylesheet' type='text/css' href='../../js/resources/css/ext-patch.css' /> <link rel='stylesheet' type='text/css' href='../../js/xExt/xExt.css' /> <script type='text/javascript' src='../../js/ext-base.js'></script> <script type='text/javascript' src='../../js/ext-all.js'></script> <script type='text/javascript' src='../../js/ext-lang-zh_CN.js'></script> <script type='text/javascript' src='../../js/xExt/xExt-base.js'></script> <script type='text/javascript' src='../../js/xExt/xExt.js'></script> <script type='text/javascript' src='../../js/s.js'></script> <script type='text/javascript' src='user.js'></script> </head> <body> <div id='userDiv' style='width:100%;height:100%;'></div> </body> </html>
可以看到这里的代码也是非常简洁的,大部分是对js,css文件的导入。
body标签中只有一个div,生成的grid会绑定到该div上。
user.js
Ext.onReady(function() { // xExt式样初始化(路径设定,默认当前为二级目录) xExt.css.init(); // 配置Grid var gridConfig = xExt.grid.GridConfig({ // 工程名称 webroot : 'Demo3', // 主模块名称 mainModule : 'admin', // 子模块名称 subModule : 'user', // 列相关信息 columns : [{ name : 'id', type : 'int', header : '编号', hidden : true, filterable : false, sortable : false }, { name : 'name', type : 'string', header : '用户名称', hidden : false, filterable : true, sortable : true }, { name : 'age', type : 'int', header : '年龄', hidden : false, filterable : true, sortable : true }, { name : 'birthday', type : 'date', header : '生日', hidden : false, filterable : true, sortable : true }, { name : 'phone', type : 'string', header : '电话', hidden : false, filterable : true, sortable : true }], queryMode : 1, editableGrid : false, basicGridConfig : { // 新建按钮 needInsertButton : true, // 窗口控件 insertFormItems : [{ xtype : 'fieldset', title : '基本信息', layout : 'form', style : xExt.css.fieldset.margins_7px, defaults : { width : xExt.css.form.fieldWidth }, items : [{ xtype : 'hidden', fieldLabel : '编号', name : 'id' }, { xtype : 'textfield', fieldLabel : '用户名称', name : 'name', allowBlank : true, maxLength : 50 }, { xtype : 'numberfield', fieldLabel : '年龄', name : 'age', allowBlank : true, maxLength : 50 }, { xtype : 'datefield', fieldLabel : '生日', name : 'birthday', allowBlank : true, maxLength : 50, format : 'Y-m-d' }, { xtype : 'textfield', fieldLabel : '电话', name : 'phone', allowBlank : true, maxLength : 50 }] }], // 更新按钮 needUpdateButton : true, // 窗口控件 updateFormItems : [{ xtype : 'fieldset', title : '基本信息', layout : 'form', style : xExt.css.fieldset.margins_7px, defaults : { width : xExt.css.form.fieldWidth }, items : [{ xtype : 'hidden', fieldLabel : '编号', name : 'id' }, { xtype : 'textfield', fieldLabel : '用户名称', name : 'name', allowBlank : true, maxLength : 50 }, { xtype : 'numberfield', fieldLabel : '年龄', name : 'age', allowBlank : true, maxLength : 50 }, { xtype : 'datefield', fieldLabel : '生日', name : 'birthday', allowBlank : true, maxLength : 50, format : 'Y-m-d' }, { xtype : 'textfield', fieldLabel : '电话', name : 'phone', allowBlank : true, maxLength : 50 }] }], // 删除按钮 needDeleteButton : true, // 批量删除按钮 needClearButton : true }, // 默认双击事件,弹出更新窗口(在有更新窗口的前提下) listeners : { rowdblclick : true } }); // 生成Grid var dataGrid = xExt.grid.GridPanel(gridConfig); });
可以看到,这里并没有直接使用Ext里面的控件,而是针对这个增删改查页面的需求,封装到了xExt这个类库中。
调用xExt.grid.GridConfig生成配置信息后,调用 xExt.grid.GridPanel就可以生成Grid了。
// 新建按钮 needInsertButton : true,
像这个新建按钮,只需要设置true,页面上就会多一个新增按钮,并会有一个弹出窗口,在窗口中可以添加新数据,省去了直接使用Ext生成按钮再生成窗口的一大段代码,总的来说,一样是遵循了代码复用的思想。
总结
以上代码都是使用代码生成工具生成的,可以看到,本人在遵循代码复用的基础上,尽可能的把共通代码提取出来,将变化的地方空出来,留给开发人员使用。生成的代码也基本具有可读性。
做这个代码生成工具的目的,算是对快速开发的一种尝试,Nutz项目中也有代码生成工具,只是目前貌似进度停止了,这里写的这个也是期望能起到一个抛砖引玉的作用,激发其大家的思考。
望Nutz的代码生成工具,早日Release。
***************************邪恶的分割线******************************
代码生成工具的原理,下次再讲
- 快速开发操作视频.rar (8.4 MB)
- 下载次数: 263
发表评论
-
MySQL关于Timestamp类型的一个要注意的地方
2011-11-02 19:18 1881使用Nutz提供的建表功能。 测试类: @Tab ... -
使用Nutz+ExtJS+JBPM4.4实现会签
2011-07-17 08:06 6715会签的例子依然采用Nutz+ExtJS+JBPM来实现。 ... -
ExtJS+Nutz+JBPM实现一个简单的请假流程
2011-07-04 16:26 10182学习了一段时间的JBPM工作流,根据网上一个很常见的请假的例子 ... -
Nutz+ExtJS示例教程——后台Service实现
2011-02-20 16:56 4689后台的结构图如下: 这里 ... -
Nutz+ExtJS示例教程——数据库设计
2011-02-19 19:15 2079因为这里只是个简单的Demo,所以设计上就简单点了。 ... -
Nutz+ExtJS示例教程——搭建开发环境
2011-02-14 13:28 4863这里介绍下,开发环境 ... -
Nutz+ExtJS示例教程——预告篇
2011-01-08 00:21 7566最近一直在新项目,决定采用全新的架构 ...
相关推荐
Nutz是一款基于Java的轻量级框架,它提供了全面的Web开发解决方案,包括ORM、AOP、IOC等。而ExtJS则是一个强大的JavaScript前端框架,用于构建复杂的、数据驱动的用户界面。 在这个示例教程中,我们将探讨如何结合...
6. **开发与部署**:开发者可能使用IDE如IntelliJ IDEA或Eclipse来编写和调试代码,使用Git进行版本控制。在部署时,应用可能被打包成WAR文件部署到Tomcat或Jetty等Java应用服务器,同时MySQL服务器需要配置并运行以...
qtz40塔式起重机总体及塔身有限元分析法设计().zip
Elasticsearch是一个基于Lucene的搜索服务器
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
美国纽约HVAC(暖通空调)数据示例,谷歌地图数据包括:时间戳、名称、类别、地址、描述、开放网站、电话号码、开放时间、更新开放时间、评论计数、评级、主图像、评论、url、纬度、经度、地点id、国家等。 在地理位置服务(LBS)中,谷歌地图数据采集尤其受到关注,因为它提供了关于各种商业实体的详尽信息,这对于消费者和企业都有极大的价值。本篇文章将详细介绍美国纽约地区的HVAC(暖通空调)系统相关数据示例,此示例数据是通过谷歌地图抓取得到的,展示了此技术在商业和消费者领域的应用潜力。 无需外网,无需任何软件抓取谷歌地图数据:wmhuoke.com
2023-04-06-项目笔记-第四百五十五阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.453局变量的作用域_453- 2025-04-01
1_实验三 扰码、卷积编码及交织.ppt
北京交通大学901软件工程导论必备知识点.pdf
内容概要:本文档总结了 MyBatis 的常见面试题,涵盖了 MyBatis 的基本概念、优缺点、适用场合、SQL 语句编写技巧、分页机制、主键生成、参数传递方式、动态 SQL、缓存机制、关联查询及接口绑定等内容。通过对这些问题的解答,帮助开发者深入理解 MyBatis 的工作原理及其在实际项目中的应用。文档不仅介绍了 MyBatis 的核心功能,还详细解释了其在不同场景下的具体实现方法,如通过 XML 或注解配置 SQL 语句、处理复杂查询、优化性能等。 适合人群:具备一定 Java 开发经验,尤其是对 MyBatis 有初步了解的研发人员,以及希望深入了解 MyBatis 框架原理和最佳实践的开发人员。 使用场景及目标:①理解 MyBatis 的核心概念和工作原理,如 SQL 映射、参数传递、结果映射等;②掌握 MyBatis 在实际项目中的应用技巧,包括 SQL 编写、分页、主键生成、关联查询等;③学习如何通过 XML 和注解配置 SQL 语句,优化 MyBatis 性能,解决实际开发中的问题。 其他说明:文档内容详尽,涵盖面广,适合用于面试准备和技术学习。建议读者在学习过程中结合实际项目进行练习,以更好地掌握 MyBatis 的使用方法和技巧。此外,文档还提供了丰富的示例代码和配置细节,帮助读者加深理解和应用。
《基于YOLOv8的智能电网设备锈蚀评估系统》(包含源码、可视化界面、完整数据集、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计
插头模具 CAD图纸.zip
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
《基于YOLOv8的智慧农业水肥一体化控制系统》(包含源码、可视化界面、完整数据集、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计
python爬虫;智能切换策略,反爬检测机制
台区终端电科院送检文档
e235d-main.zip
丁祖昱:疫情对中国房地产市场影响分析及未来展望
MCP快速入门实战,详细的实战教程