代码生成器(2)

上节课完成了45%的代码生成器,接下来我们来写关于Menu表的controller层、model层


主要任务:完成Menu表的controller层、model层


我们继续自己写代码生成器,来完善我们的代码

  1. 在vm下建立controller.vm
package com.lf.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.github.pagehelper.PageInfo;

#if(${modelName}=='menu')
import com.lf.model.${modelClass};
import com.lf.service.${modelClass}Service;
#else
import com.lf.model.${modelClass};
import com.lf.service.${modelClass}Service;
import com.lf.model.Menu;
import com.lf.service.MenuService;
#end

@RequestMapping("/${modelName}")
@Controller
public class ${modelClass}Controller {
	
#if(${modelName}=='menu')
	@Autowired
	private MenuService menuService;
#else
	@Autowired
	private ${modelClass}Service ${modelName}Service;
	@Autowired
	private MenuService menuService;
#end
	
	
	
	@ResponseBody
	@RequestMapping("/delete.do")
	public boolean delete(Integer id){
		try{
			${modelName}Service.delete(id);
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	@ResponseBody
	@RequestMapping("/findById.do")
	public ${modelClass} findById(Integer id){
		return ${modelName}Service.findById(id);
	}
	
	@ResponseBody
	@RequestMapping("/create.do")
	public boolean create(${modelClass} ${modelName}){
		try{
			${modelName}Service.create(${modelName});
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	@RequestMapping("/list.do")
	public String list(${modelClass} ${modelName},Model model,
			@RequestParam(required=true,value="pageNum",defaultValue="1") Integer pageNum,
			@RequestParam(required=true,value="pageSize",defaultValue="3") Integer pageSize
			){
		PageInfo<${modelClass}> ${modelName}s  = ${modelName}Service.list(pageNum,pageSize,${modelName});
		model.addAttribute("pageInfo", ${modelName}s);
		
		List<Menu> menuList = menuService.list(null);
		model.addAttribute("menuList",menuList);
		
		return "${modelName}";
	}
	
	@ResponseBody
	@RequestMapping("/list.do")
	public List<${modelClass}> list(${modelClass} ${modelName},Model model){
		return ${modelName}Service.list(${modelName});
	}
}

${modelClass}代表User的位置
${modelName}代表user的位置

在userController中添加
如下

		List<Menu> menuList = menuService.list(null);
		model.addAttribute("menuList",menuList);

同时在controller.vm中添加上面两行

  1. 在code层中的CodeBuilder.java中添加关于controller的代码
		// controller的
		Template controllerVm = ve.getTemplate("/WebContent/WEB-INF/vm/controller.vm");
		CodeBuilder.merge(controllerVm, ctx, rootPath +"src/com/lf/controller/" + modelClass +"Controller.java");
		

这时候运行Run As——Java Application会生成相应的MenuController.java
具体如下:

package com.lf.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.github.pagehelper.PageInfo;

import com.lf.model.Menu;
import com.lf.service.MenuService;

@RequestMapping("/menu")
@Controller
public class MenuController {
	
	@Autowired
	private MenuService menuService;
	
	
	
	@ResponseBody
	@RequestMapping("/delete.do")
	public boolean delete(Integer id){
		try{
			menuService.delete(id);
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	@ResponseBody
	@RequestMapping("/findById.do")
	public Menu findById(Integer id){
		return menuService.findById(id);
	}
	
	@ResponseBody
	@RequestMapping("/create.do")
	public boolean create(Menu menu){
		try{
			menuService.create(menu);
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	@RequestMapping("/list.do")
	public String list(Menu menu,Model model,
			@RequestParam(required=true,value="pageNum",defaultValue="1") Integer pageNum,
			@RequestParam(required=true,value="pageSize",defaultValue="3") Integer pageSize
			){
		PageInfo<Menu> menus  = menuService.list(pageNum,pageSize,menu);
		model.addAttribute("pageInfo", menus);
		
		List<Menu> menuList = menuService.list(null);
		model.addAttribute("menuList",menuList);
		
		return "menu";
	}
	
	@ResponseBody
	@RequestMapping("/list.do")
	public List<Menu> list(Menu menu,Model model){
		return menuService.list(menu);
	}
}

  1. 在vm下建立model.vm
package com.lf.model;

public class ${modelClass} {
#foreach(${e} in ${columnList})
	private ${e.columnType} ${e.attrName};//${e.columnComment} 
#end

#foreach(${e} in ${columnList})
	
	public ${e.columnType} get${e.uperName}() {
		return ${e.attrName};
	}
	public void set${e.uperName}(${e.columnType} ${e.attrName}) {
		this.${e.attrName} = ${e.attrName};
	}
#end
}

  1. 在code层建立CodeBean.java
package com.lf.code;

public class CodeBean {
	private String columnName;//字段名字
	private String columnType;//类型
	private String columnComment;//注释
	
	private String attrName;//goodName
	private String uperName;//GoodName set/get
	
	
	public String getColumnName() {
		return columnName;
	}
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}
	public String getColumnType() {
		return columnType;
	}
	public void setColumnType(String columnType) {
		this.columnType = columnType;
	}
	public String getColumnComment() {
		return columnComment;
	}
	public void setColumnComment(String columnComment) {
		this.columnComment = columnComment;
	}
	public String getAttrName() {
		return attrName;
	}
	public void setAttrName(String attrName) {
		this.attrName = attrName;
	}
	public String getUperName() {
		return uperName;
	}
	public void setUperName(String uperName) {
		this.uperName = uperName;
	}
	
}

  1. 在codeBuilder.java中添加model的
// model的
		// 从数据库查询表的字段:字段名称,字段类型,字段注释 good_name goodName setGoodName
		List<CodeBean> list = selectColumn(modelName);
		ctx.put("columnList", list);
		
		Template modelVm = ve.getTemplate("/WebContent/WEB-INF/vm/model.vm");
		CodeBuilder.merge(modelVm, ctx, rootPath +"src/com/lf/model/" + modelClass +"Model.java");
				
  1. jdbc连接数据库——在codeBuilder.java中添加
// jdbc连接数据库
	private static List<CodeBean> selectColumn(String modelName) {
		List<CodeBean> list = new ArrayList<CodeBean>();
		// java.sql这个包里的类
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			// 注册数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 创建数据库
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/shop", "root", "");
			// sql语句
			String sql = "SELECT t.COLUMN_NAME,t.DATA_TYPE,t.COLUMN_COMMENT "
					+ " FROM information_schema.COLUMNS t "
					+ " WHERE t.TABLE_NAME = '"+modelName+"' "
					+ " AND t.TABLE_SCHEMA = 'shop' ";
			// 执行sql语句
			ps = conn.prepareStatement(sql);
			// 获取查询结果
			rs = ps.executeQuery();
			// 循环遍历查询结果,塞到columnList里面
			while(rs.next()){
				CodeBean bean = new CodeBean();
				bean.setColumnName(rs.getString(1));
				bean.setColumnComment(rs.getString(3));
				//类型 
				String type = rs.getString(2);
				if(type.equalsIgnoreCase("varchar") || type.equalsIgnoreCase("varchar2")){//字符串
					bean.setColumnType("String");
				}else if(type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer")){//整数
					bean.setColumnType("Integer");
				}else if(type.equalsIgnoreCase("float")
						|| type.equalsIgnoreCase("double")
						|| type.equalsIgnoreCase("decimal")){//小数:float double decimal
					bean.setColumnType("Double");
				}else{
					bean.setColumnType("String");
				}
				
				//good_name goodName GoodName
				bean.setAttrName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, bean.getColumnName()));
				bean.setUperName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, bean.getColumnName()));
				
				list.add(bean);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				rs.close();
				ps.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
		
		return null;
	}

对于数据库的menu表我们对其各属性进行了备注,具体查询语句为

SELECT t.COLUMN_NAME,t.DATA_TYPE,t.COLUMN_COMMENT
FROM information_schema.COLUMNS t
WHERE t.TABLE_NAME = ‘menu’
AND t.TABLE_SCHEMA = ‘shop’ ;

执行结果如下
在这里插入图片描述本节课的大体重点如上,后续相应的优化将会在下次继续~

由《Ext JS源码分析与开发实例宝典》作者:彭仁夔团队开发而成 根据数据模型(如数据库、PDM等)可以生成直接运行的SSH项目,初始化数据库数据等。在当前的模板中生成完善的CRUD操作,生成验证,根据不同的类型生成富文本,日历、树表结构等,并且还能生成完善强大的的实现权限系统。 功能之强大用了就知道! 两年前,我负责指导Java方向实训,在最后评审准备过程,.Net组负责人要求Java和.Net的归结一起统一评审,Java指导老师们的第一反应是Java和.Net开始怎么能相提并论? 为什么不能并论?是因为Java开发阳春白雪?在我们的潜意识中,Java开发就是让程序员(学生)一行一行地编写代码,编写HTML、CSS等,而.Net开发只要把控件拖到页面上即可,Java开发的效率一定比.Net低很多很多。 那么能不能提高Java的开发效率呢?作者经过分析并总结思考,发现业务系统有一定的共性所有操作,即增删改查,既然有共性,那么能不能抽象出来? 可以思考一下,通过继承、组件化等重用设计方式是可以抽象代码的共性,但是不同表(实体)增删改查的内容是不同的,通过泛型也很难抽象出来的。如对于A表的查询和对于B表的查询都需要使用到SQL语句,怎么去剥离出来? 此时,我们就需要采用另外一种方式,把它们抽象出来更高层级的模板,然后把不同数据传入该模板的占位符,这样就变成不同的代码,这种方式就是代码生成技术。 在软件的设计过程中,代码生成及重用设计仿若陌路人,互相排斥。重用设计中很多的共性是不能抽象出来的,而一味追求生成,造成大量的雷同代码,是重用设计人员或真正开发人员最不能容忍的事件。 如果把它们两个结合起来,那就是完全不同的效果,首先通过重用设计抽象其能抽象的代码,其不能抽象的共性通过生成技术生成,开发效率就会成倍增加。以前我们都是在X或y轴上分别进行,其最大的点也不过是线,如果两者结合起来,其变成一个平面,把我们的重用从点提高到面。
由《Ext JS源码分析与开发实例宝典》作者:彭仁夔团队开发而成 90%以上代码可以生成验证、生成三层代码、生成完善的权限系统、生成数据库等功能 功能之强大用了就知道! 两年前,我负责指导Java方向实训,在最后评审准备过程,.Net组负责人要求Java和.Net的归结一起统一评审,Java指导老师们的第一反应是Java和.Net开始怎么能相提并论? 为什么不能并论?是因为Java开发阳春白雪?在我们的潜意识中,Java开发就是让程序员(学生)一行一行地编写代码,编写HTML、CSS等,而.Net开发只要把控件拖到页面上即可,Java开发的效率一定比.Net低很多很多。 那么能不能提高Java的开发效率呢?作者经过分析并总结思考,发现业务系统有一定的共性所有操作,即增删改查,既然有共性,那么能不能抽象出来? 可以思考一下,通过继承、组件化等重用设计方式是可以抽象代码的共性,但是不同表(实体)增删改查的内容是不同的,通过泛型也很难抽象出来的。如对于A表的查询和对于B表的查询都需要使用到SQL语句,怎么去剥离出来? 此时,我们就需要采用另外一种方式,把它们抽象出来更高层级的模板,然后把不同数据传入该模板的占位符,这样就变成不同的代码,这种方式就是代码生成技术。 在软件的设计过程中,代码生成及重用设计仿若陌路人,互相排斥。重用设计中很多的共性是不能抽象出来的,而一味追求生成,造成大量的雷同代码,是重用设计人员或真正开发人员最不能容忍的事件。 如果把它们两个结合起来,那就是完全不同的效果,首先通过重用设计抽象其能抽象的代码,其不能抽象的共性通过生成技术生成,开发效率就会成倍增加。以前我们都是在X或y轴上分别进行,其最大的点也不过是线,如果两者结合起来,其变成一个平面,把我们的重用从点提高到面。如下图所示: 面。如下图所示, Y重用 现在的软件开发不再仅仅是编写代码,重用等,而是需求调研、架构设计、数据库、编码开发、测试部署等过程的有机组合,组合的好与坏,其结果相差万里,这就是著名的米格-25效应。 在开发过程怎么去把这些最大效应化呢?回想一下我们的开发流程: 需求开发,形成文档 采用powerDesigner等进行实体及实体关系的设计 通过Pdm创建数据库 在开发工具中创建搭建项目 通过相关的工具(hibernate tools,myeclipse)生成实体 设计及编写Dao 设计及编写Service 设计及编写Action及相关页面 这样的线性流程有着极大的问题,首先架构师或数据库专家不是圣人,设计数据库,Dao,Service接口之后,就不需要修改,在编码过程中,会进行大量的修改,特别是那种那只懂数据库的专家在设计之后,开发人员怨声载道。另外设计的dao,service接口及实现很多都用不着,用得着的根本就没有设计。因为需要的dao,service很多都是由页面根据取数操作的不同而进行不同的编写。 开发过程的修改,就会带来原前置流程步骤的修改,所以软件开发完成之后,不会有很多公司其PDM与数据库、实体是一一对应的。而有一些是必须要修改,如在实体中修改属性,一定要到数据库中修改,到dao,service,action,page一一进行修改,如果修改的是外键属性,修改的代码更为复杂。开发人员最痛苦的事情就无穷无尽的修改,领导简单的一句话:不就修改一个属性吗?你可能就要改一个下午。 能不能有这样的方法呢?修改一处其它处跟着改,这时就需要把原来的线性流程乾变换,改成为无前置的试,即卫星城的方式,中心城就是模型,可以称为Domain、域、实体,在实体的基础是加上一些设计,如下图所示: 现在只要中间模型发生变化,其变化会通过其背后的关系推向卫星城,让其发生相对应的变化,就像蝴蝶效应一样。 此时,我们可以站在一个更高的层面去思考开发,开发不仅仅是代码,开发不仅仅是处理代码之间关系,还需要处理与数据存储的关系,与测试部署关系等。 这些关系我们需不需要去体现出来,肯定需要。我们可以把这些关系看作是软件中区别于业务逻辑属性的特殊属性,这种属性主要包括: 与数据存储之间的关系 代码结构组织的方面(如采用三层) 与设计及设计文档的关系 与开发模型(如瀑布)的关系 与需求及需求变更的关系 与测试部署之间的关系 除了这些特殊关系,代码中还有实体之间的关系,业务关系等。 我们可以发现软件不单纯是一个对象,而且是一组关系。它们相互关联,相互牵制。 续而推之,我们编写的类也是关系,是处理一类事物的抽象关系。泛型是处理类的抽象关系。所有东西都是关系体。 那么能不能在现有的面向对象的理论上推进一步呢?世界不是一个个单独的对象,而是不同的对象相互发生关系的有机结构体(可以称为关系体),只有这样,世界才多姿多彩。就算是一个个对象,它也不是静止的,它的内部也是由不同分子原子发生作用的结果,可以讲对象也是一个关系体。 软件是用来对世界进行描述的一种方式,最初我们采用过程的编程,后来与世界的描述不相符,所以就出现了面向对象,而现在面向对象并不能很好地解析如抽象类,Service类等。要解释这些东西,最好的方式是通过关系来表达。也就是面向对象的编程方式可以更进一步地改进为面向关系编程方式。 面向关系编程需要首先需要找到软件模型与需求、架构,数据,测试,部署之间的变化关系。这些关系有业务层面的,也有开发层面的。这种关系可以抽离出来,形成模板。 接下来把业务模型+关系模板通过工具生产出来,就成为一个有血有肉的软件。Mgicode(码奇)生成器就从这里出发,帮我们抽象软件背后的关系,提高开发效率。 所以通过Mgicode生成器,你可以获得如下好处: 根据设计(pdm,数据库等)快速生成可运行的项目。 修改实体之后,会帮助你找到所有需要修改的东西,并且给出最佳的修改方案。 统一代码编程风格(如同一项目中选择几种不同日历控制) 把自己的项目模板化(关系化),方便之后使用 把模板化的项目放到Mgicode市场获得一些外快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值