阅读更多

15顶
4踩

开源软件

原创新闻 开源框架eweb4j发布1.b.7新版本

2011-10-02 19:18 by 见习记者 laiweiweihi 评论(43) 有18845人浏览
eweb4j是一个简单、轻量的JavaWeb开发框架。涵盖MVC、ORM、IOC。超轻量、面向接口,扩展灵活。

可先使用本框架快速开发,然后方便的转换成SSH。只需修改部分代码,无需修改业务逻辑代码。

MVC、IOC、ORM自由选择开闭,灵活与其他框架集成。

特性:

Component组件支持
  • DWZ组件
  • 分页组件
  • ……

MVC
  • 约定由于配置,可零配置。
  • 两种配置方式(xml,注解)供您选择
  • 更加灵活方便的url mapping
  • 两种参数绑定方式(类属性、方法参数)供您选择
  • RESTful
  • Json渲染
  • URL拦截器
  • action验证器
  • ……

IOC
  • 基本数据类型注入
  • 无限制嵌套Pojo注入
  • setter方法注入和构造方法注入

ORM
  • 约定由于配置,可零配置。
  • 两种配置方式(xml、注解),供您选择
  • 简单的DAOFactory,提供InsertDAO、DeleteDAO、UpdateDAO、SelectDAO、DivPageDAO、SearchDAO、CascadeDAO接口。
  • 支持表关系、级联操作
  • 事务模板
  • JdbcTemplate
  • 支持多个数据源
  • 无缓存,无懒加载,主动级联操作,纯粹的ORM
  • ……

各种Util工具类
  • BeanXMLUtil,一个pojo序列化和反序列化到xml的工具类,基于注解
  • FileUtil,一个文件操作工具类
  • JsonConverter,JSON转换工具类
  • ReflectUtil,一个反射工具类,能获取setter、getter,使反射获取方法,属性更简易,支持父类的反射
  • ……


简单就是美。使用文档已经编写齐全,在下载包里有,PDF格式。
纯开源、纯分享,不喜勿喷,还望各位大大多多支持。

下载地址http://code.google.com/p/eweb4j/downloads/list

启动配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans>
  <bean xmlBean="com.cfuture08.eweb4j.config.bean.ConfigBean">
    <debug>0</debug>
    <ioc xmlBean="com.cfuture08.eweb4j.config.bean.ConfigIOC">
      <open>1</open>
      <debug>true</debug>
      <logFile>logs/ioc.log</logFile>
      <logMaxSize>5</logMaxSize>
      <iocXmlFiles xmlBean="com.cfuture08.eweb4j.config.bean.IOCXmlFiles">
        <path>ioc.xml</path>
      </iocXmlFiles>
    </ioc>
    <orm xmlBean="com.cfuture08.eweb4j.config.bean.ConfigORM">
      <open>1</open>
      <debug>true</debug>
      <logFile>logs/orm.log</logFile>
      <logMaxSize>5</logMaxSize>
      <dataSource>com.mchange.v2.c3p0.ComboPooledDataSource</dataSource>
      <scanPojoPackage xmlBean="com.cfuture08.eweb4j.config.bean.ScanPojoPackage">
        <path>.</path>
      </scanPojoPackage>
      <ormXmlFiles xmlBean="com.cfuture08.eweb4j.config.bean.ORMXmlFiles">
        <path></path>
      </ormXmlFiles>
      <dbInfoXmlFiles xmlBean="com.cfuture08.eweb4j.config.bean.DBInfoXmlFiles">
        <path>mysql_con_info.xml</path>
      </dbInfoXmlFiles>
    </orm>
    <mvc xmlBean="com.cfuture08.eweb4j.config.bean.ConfigMVC">
      <open>true</open>
      <debug>true</debug>
      <logFile>logs/mvc.log</logFile>
      <logMaxSize>5</logMaxSize>
      <scanActionPackage xmlBean="com.cfuture08.eweb4j.config.bean.ScanActionPackage">
        <path>.</path>
      </scanActionPackage>
      <actionXmlFiles xmlBean="com.cfuture08.eweb4j.config.bean.ActionXmlFile">
        <path></path>
      </actionXmlFiles>
      <interXmlFiles xmlBean="com.cfuture08.eweb4j.config.bean.InterXmlFile">
        <path>interceptor.xml</path>
      </interXmlFiles>
    </mvc>
  </bean>
</beans>



新版本1.b.7更新:

(1) Controller支持以下约定:
action方法不填写注解RequestMapping的时候,默认以方法名为url-mapping值。
action 方法返回类型为void的时候框架不做任何跳转处理。
缺省返回值忽略大小写。例如ajax。
类名如果以“Controller”,“Control”,“Action”结尾的话,可以不用添加@Controller注解,框架也能识别为控制器。
(2)mvc中,为了改进性能,将Class.forName(ActionBeanName),改为缓存方式调用。这样省去了lookup的过程,效能会提升。当系统需要应对高并发的时候,很有效。
(3)废除了formBean的配置,框架自动识别pojo参数,并且支持无限嵌套pojo属性。无需任何配置。
(4)将MVC的@Result(location="")属性改为@Result(value="")
(5)将ORM的BaseDAO.getOne(Integer id)之类的Integer改为Number
(6)让MVC Controller 的属性的 setter 方法 和 getter 方法 无法映射到url。前提是这些方法没有使用@RequestMapping注解
(7)修复 MVC Controller 实例属性与action方法@RequestMapping("xxx/{id}")中的“{}”变量的绑定。
(8)当MVC Controller 实例属性绑定的UrlParam的值为null时,不将参数值注入到该属性。
(9)添加Json支持,MVC的@Result(type="json"),被注解的方法,返回值会被JsonConverter.convert(re),接着被写入到响应流。
(10)所有的注解都被加上@Inherited,允许类、public方法上的注解被子类继承。
(11)框架使用的反射工具类范围调整至涵盖父类。原先取得某个类的属性,是不能获取到它的父类的属性的(同理,方法也是),现在父类的也会被获取,主要考虑到MVC的Controller、ORM的
POJO等对象需要使用继承来复用代码。
(12)修复MVC的Controller无法实例化的时候框架报致命错误导致程序中断,现在为跳过该类,将其认为非控制器,且继续处理下一个类。
(13)修复MVC的Controller属性绑定到UrlParam过程中,pojo属性互相调用导致的循环递归异常。
(14)ORM的CascadeDAO @One 关系中的级联更新操作,对新更新的关联对象如果在数据库中找不到记录就不被更新的规则修改为当关联对象为null或者其主键值为null的时候不级联更新。例如
更新某个菜单的父菜单为空这种情况。
(16)重新调整了MVC的Validator有关的注解。去掉了冗余。举个实例:

这是修改之前的写法:
@Validator({"int","required","length"})
@ValField(index={0,1,2},field={"id","name","name"},value={"id必须为数字","name必填","name长度4-6位"})
@ValParam(index={2,2},name={"minLength","maxLength"},value={"4","6"})
public void doActoin(){}

这是修改之后的写法:
@Validator({"int","required","length"})
@ValField({"id","name"})
@ValMess(validator={0,1,2},field={0,1,1},value={"id必须为数字","name必填","name长度4-6位"})
@ValParamName("minLength","maxLength")
@ValParam(valMess={2,2},name={0,1},value={"4","6"})
public void doActoin(){}

可以看到,原来的ValField对要验证的field会产生冗余,例如上例中的“name”,修改后是将这些field写到另外一个@ValField注解中,然后在@ValMess中进行引用,注意那些数字引用表表
示的是数组下标。
同样道理,对于@ValParam来说也是这样,为了去掉冗余。

备注:说去掉冗余是不严谨的说法,实际上应该是将语言文字的冗余转化为数字的冗余,后者相对而言是降低了冗余。思路也更清晰。

(17)IOC增加@Ioc注解,只能用在Action类属性上,且需要setter方法才能注入。具体用法:
@Controller
class TestAction{
        @Ioc("这里填写在IOC配置文件里的BeanID,不填的话默认是简单类名TestDAO")
private TestService testService;
public void setTestService(TestService testService){
this.testService = testService;
}
}

(18)添加 DAOFactory.getSelectDAO().selectCount(Class<?> clazz,String condition,Object... args);用来查询表的记录数。给定where条件,允许有?占位符。
(19)修复了当被扫描的包里含有.svn或者其他非.class文件的时候,框架启动失败的一个bug
(20)改善了MVC.Action的ParamUtil进行URL参数绑定到Aciton属性的时候,如果是属性为pojo,例如:
private Pet pet;
那么绑定参数的时候,优先找到 pet.name绑定到pet里面的name属性。
如果找不到pet.name 参数,则找name参数绑定。如果还找不到,就不进行任何绑定。
可以看到跟属性名字“pet”有关,可以理解为参数的一个scope,这样解决了不同pojo但相同属性名字的参数绑定。
url:/testPojoParamAndUrlParam?name=thisName&pet.name=xiaohei&master.name=weiwei
支持深层次。例如:
url:/testPojoParamAndUrlParam?name=thisName&pet.master.name=masterName&pet.name=petName

(21)MVC Action URL变量支持多个。例如:
@RequestMapping("test/{cate}/{name}/edit")
public void testParamArg(){

}
要注意不要无任何间隔的连续写两个变量,例如:"test/{cate}{name}/edit"这是不合法的。"test/{cate}at{name}/edit"这是合法的。
(22)ORM 持久化类属性 添加了@Ignore 注解,表示该属性不映射到表字段中。


上些实例代码,其中包括快要发布的Simportal新版本。
package com.cfuture08.eweb4j.component.dwz.menu.domain.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.cfuture08.eweb4j.orm.config.annotation.Column;
import com.cfuture08.eweb4j.orm.config.annotation.Id;
import com.cfuture08.eweb4j.orm.config.annotation.Many;
import com.cfuture08.eweb4j.orm.config.annotation.One;
import com.cfuture08.eweb4j.orm.config.annotation.Table;

/**
 * DWZ中左边树形结构菜单模型
 * 
 * @author weiwei
 * 
 */
@Table("t_TreeMenu")
public class TreeMenu implements Serializable {
	private static final long serialVersionUID = 5264149396283615258L;
	@Id
	@Column("id")
	private Long treeMenuId = 0L;
	private String name;// 菜单名
	private String target = "navTab";// navTab或dialog
	private String rel;// navTabId
	private String reloadFlag = "1";// 是否自动刷新
	private String href;// 跳转路径
	private int rank;// 排序
	@One(column = "pid")
	private TreeMenu parent;// 父亲菜单
	@One(column = "navMenuId")
	private NavMenu navMenu = new NavMenu();// 所在的导航菜单
	@Many(target = TreeMenu.class, column = "pid")
	private List<TreeMenu> children = new ArrayList<TreeMenu>();// 孩子菜单们

	public Long getTreeMenuId() {
		return treeMenuId;
	}

	public void setTreeMenuId(Long treeMenuId) {
		this.treeMenuId = treeMenuId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public TreeMenu getParent() {
		return parent;
	}

	public void setParent(TreeMenu parent) {
		this.parent = parent;
	}

	public int getRank() {
		return rank;
	}

	public void setRank(int rank) {
		this.rank = rank;
	}

	public String getTarget() {
		return target;
	}

	public void setTarget(String target) {
		this.target = target;
	}

	public String getRel() {
		return rel;
	}

	public void setRel(String rel) {
		this.rel = rel;
	}

	public String getReloadFlag() {
		return this.reloadFlag;
	}

	public void setReloadFlag(String reloadFlag) {
		this.reloadFlag = reloadFlag;
	}

	public String getHref() {
		return href;
	}

	public void setHref(String href) {
		this.href = href;
	}

	public NavMenu getNavMenu() {
		return navMenu;
	}

	public void setNavMenu(NavMenu navMenu) {
		this.navMenu = navMenu;
	}

	public List<TreeMenu> getChildren() {
		return children;
	}

	public void setChildren(List<TreeMenu> children) {
		this.children = children;
	}

	public String toString() {
		Long pid = parent == null ? 0L : parent.treeMenuId;
		return "{\"treeMenuId\":\"" + treeMenuId + "\",\"navMenuId\":\""
				+ navMenu.getNavMenuId() + "\",\"pid\":\"" + pid
				+ "\",\"name\":\"" + name + "\",\"href\":\"" + href + "\"}";
	}
}


package com.lurencun.ewebdemo;
import java.io.PrintWriter;

import com.cfuture08.eweb4j.mvc.annotation.Param;
import com.cfuture08.eweb4j.mvc.annotation.RequestMapping;
import com.cfuture08.eweb4j.orm.dao.factory.DAOFactory;
public class HelloAction {
	//默认方法名为访问url
	public void helloWorld(PrintWriter out) {
		out.print("Hello World !");
	}
	
	@RequestMapping("hello")
	public void doHello(PrintWriter out){
		out.print("doHello");
	}
	
	@RequestMapping(value="articles/{id}",method="GET")
	public void restful(PrintWriter out,@Param("id")int id){
		out.print("id->"+id);
	}
	
	public String defaultForward(){
		return "test.jsp";
	}
	
	public String forward(){
		return "forward:test.jsp";
	}
	
	public String redirect(){
		return "redirect:test.jsp";
	}
	
	/**
	 * url: "/test?name=ooo&pojo.name=xxx&pojo.age=2"
	 * 
	 */
	public void bindParam(String name,@Param("pojo") Pojo pojo){
		Long id = (Long) DAOFactory.getInsertDAO().insert(pojo);
		pojo.setId(id);
		DAOFactory.getCascadeDAO().update(pojo, "xxx","ooo");
	}
	
	public void testDAO(){
		
	}
}



最新的Simportal版本还在开发当中。贴上部分代码:
package com.cfuture08.eweb4j.component.dwz.menu.action.treeMenu;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;

import com.cfuture08.eweb4j.component.dwz.DWZ;
import com.cfuture08.eweb4j.component.dwz.menu.constant.CommonCons;
import com.cfuture08.eweb4j.component.dwz.menu.constant.TreeMenuCons;
import com.cfuture08.eweb4j.component.dwz.menu.domain.model.TreeMenu;
import com.cfuture08.eweb4j.component.dwz.menu.domain.service.TreeMenuService;
import com.cfuture08.eweb4j.ioc.annotation.Ioc;
import com.cfuture08.eweb4j.mvc.annotation.Controller;
import com.cfuture08.eweb4j.mvc.annotation.RequestMapping;
import com.cfuture08.eweb4j.mvc.annotation.Singleton;

/**
 * 抽象类BaseAction
 * 
 * @author weiwei
 * 
 */
@Controller
@Singleton
@RequestMapping(TreeMenuCons.MODULE_PATH)
public abstract class BaseAction {
	@Ioc(TreeMenuCons.IOC_SERVICE_BEAN_ID)
	protected TreeMenuService service = null;
	@Ioc(CommonCons.IOC_DWZ_BEAN_ID)
	protected DWZ dwz = null;

	protected HttpServletRequest request;
	protected PrintWriter out;

	protected TreeMenu treeMenu;

	protected Long[] ids;
	protected Long id = 0L;
	protected String keyword = "";
	protected Long treeMenuId = 0L;
	protected Long navMenuId = 0L;
	protected int pageNum = 1;
	protected int numPerPage = 20;

        //setter and getter 
}


package com.cfuture08.eweb4j.component.dwz.menu.action.treeMenu;

import com.cfuture08.eweb4j.component.dwz.menu.constant.TreeMenuCons;
import com.cfuture08.eweb4j.mvc.annotation.Param;
import com.cfuture08.eweb4j.mvc.annotation.RequestMapping;
import com.cfuture08.eweb4j.mvc.annotation.ValField;
import com.cfuture08.eweb4j.mvc.annotation.ValMess;
import com.cfuture08.eweb4j.mvc.annotation.Validator;

public class AddAction extends BaseAction {
	@RequestMapping(value = "/new", method = "GET|POST")
	public String doNew() {
		request.setAttribute("model", TreeMenuCons.MODEL_NAME);
		return "add.jsp";
	}

	@RequestMapping(value = "/", method = "POST", showValErr = "dwzJson")
	@Validator({ "int", "required" })
	@ValField({ "rank", "navMenus.dwz_navMenu2.navMenuId" })
	@ValMess(validator = { 0, 1 }, field = { 0, 1 }, value = { "排序项只能输入数字",
			"导航菜单不能为空" })
	public void doAdd(@Param("navMenus.dwz_navMenu2.navMenuId") Long navMenuId,
			@Param(value = TreeMenuCons.MODEL_NAME
					+ ".dwz_treeMenu2.treeMenuId", init = "0") Long pid) {
		try {
			service.addWithCascade(treeMenu, navMenuId, pid);
			out.print(TreeMenuCons.DWZ_SUCCESS_JSON_CLOSE_CURRENT);
		} catch (Exception e) {
			out.print(dwz.getFailedJson(e.getMessage()));
		}
	}
}



package com.cfuture08.eweb4j.component.dwz.menu.domain.service;

import java.util.ArrayList;
import java.util.List;

import com.cfuture08.eweb4j.component.DivPageComp;
import com.cfuture08.eweb4j.component.dwz.menu.constant.CommonCons;
import com.cfuture08.eweb4j.component.dwz.menu.constant.TreeMenuCons;
import com.cfuture08.eweb4j.component.dwz.menu.domain.dao.NavMenuDAO;
import com.cfuture08.eweb4j.component.dwz.menu.domain.dao.TreeMenuDAO;
import com.cfuture08.eweb4j.component.dwz.menu.domain.model.NavMenu;
import com.cfuture08.eweb4j.component.dwz.menu.domain.model.TreeMenu;
import com.cfuture08.eweb4j.component.dwz.menu.exception.CannotBeParentMenuException;
import com.cfuture08.eweb4j.component.dwz.menu.exception.CannotFindNavMenuException;
import com.cfuture08.eweb4j.component.dwz.menu.exception.CannotFindParentMenuException;
import com.cfuture08.eweb4j.component.dwz.menu.exception.DuplicateMenuNameException;
import com.cfuture08.eweb4j.component.dwz.menu.exception.MenuDataAccessException;
import com.cfuture08.eweb4j.component.dwz.menu.exception.MenuNotFoundException;
import com.cfuture08.eweb4j.component.dwz.view.EditPage;
import com.cfuture08.eweb4j.component.dwz.view.ListPage;
import com.cfuture08.eweb4j.component.dwz.view.SearchForm;

public class TreeMenuServiceImpl implements TreeMenuService {

	private SearchForm searchForm = new SearchForm(TreeMenuCons.MODEL_NAME
			+ "/search", "");

	private NavMenuDAO navMenuDAO = null;
	private TreeMenuDAO treeMenuDAO = null;

	// IOC注入
	public void setNavMenuDAO(NavMenuDAO navMenuDAO) {
		if (this.navMenuDAO == null)
			this.navMenuDAO = navMenuDAO;
	}

	// IOC注入
	public void setTreeMenuDAO(TreeMenuDAO treeMenuDAO) {
		if (this.treeMenuDAO == null)
			this.treeMenuDAO = treeMenuDAO;
	}

	@Override
	public ListPage getPageWithCascade(int pageNum, int numPerPage)
			throws MenuDataAccessException {
		List<TreeMenu> list = treeMenuDAO.getPageWithCascade(pageNum,
				numPerPage);
		DivPageComp dpc = new DivPageComp(pageNum, numPerPage,
				this.treeMenuDAO.countAll(), CommonCons.DIV_PAGE_BTN_MAX_SHOW);

		return new ListPage(TreeMenuCons.MODEL_NAME, searchForm, list, dpc);
	}

	@Override
	public ListPage getSearchResult(String keyword, int pageNum, int numPerPage)
			throws MenuDataAccessException {

		if (keyword == null || keyword.length() == 0) {
			searchForm.setKeyword("");
			return getPageWithCascade(pageNum, numPerPage);
		}

		List<TreeMenu> list = treeMenuDAO.getSearchResult(keyword, pageNum,
				numPerPage);

		DivPageComp dpc = new DivPageComp(pageNum, numPerPage,
				this.treeMenuDAO.countSearch(keyword),
				CommonCons.DIV_PAGE_BTN_MAX_SHOW);

		searchForm.setKeyword(keyword);

		return new ListPage(TreeMenuCons.MODEL_NAME, searchForm, list, dpc);
	}

	@Override
	public ListPage getParentsPage(Long navMenuId, Long treeMenuId,
			int pageNum, int numPerPage) throws MenuDataAccessException,
			CannotFindNavMenuException {
		return getParentsSearchResult(navMenuId, treeMenuId, "", pageNum,
				numPerPage);
	}

	@Override
	public ListPage getParentsSearchResult(Long navMenuId, Long treeMenuId,
			String keyword, int pageNum, int numPerPage)
			throws MenuDataAccessException, CannotFindNavMenuException {
		if (navMenuId == null || navMenuId <= 0)
			throw new CannotFindNavMenuException();

		NavMenu navMenu = this.navMenuDAO.getOne(navMenuId);
		if (navMenu == null)
			throw new CannotFindNavMenuException();

		if (keyword == null)
			keyword = "";

		List<TreeMenu> pojos = this.treeMenuDAO.getParentSearchResult(pageNum,
				numPerPage, keyword, navMenuId, treeMenuId);

		if (pojos == null)
			pojos = new ArrayList<TreeMenu>();
		TreeMenu tm = new TreeMenu();
		tm.setTreeMenuId(0L);
		tm.setName("主菜单-没有父节点");
		tm.setNavMenu(navMenu);
		pojos.add(tm);

		long allCount = this.treeMenuDAO.countParentSearchResult(keyword,
				navMenuId, treeMenuId);
		DivPageComp dpc = new DivPageComp(pageNum, numPerPage, allCount,
				CommonCons.DIV_PAGE_BTN_MAX_SHOW);

		searchForm.setAction(TreeMenuCons.MODEL_NAME + "/" + navMenuId
				+ "/lookupSearch");
		searchForm.setKeyword(keyword);

		return new ListPage(TreeMenuCons.MODEL_NAME, searchForm, pojos, dpc);
	}

	@Override
	public String getParentsFormatJson(Long navMenuId, Long treeMenuId)
			throws MenuDataAccessException, CannotFindNavMenuException {
		if (navMenuId == null || navMenuId <= 0)
			throw new CannotFindNavMenuException();

		NavMenu navMenu = this.navMenuDAO.getOne(navMenuId);
		if (navMenu == null)
			throw new CannotFindNavMenuException();

		List<TreeMenu> pojos = this.treeMenuDAO
				.getParent(navMenuId, treeMenuId);
		if (pojos == null)
			pojos = new ArrayList<TreeMenu>();

		TreeMenu tm = new TreeMenu();
		tm.setTreeMenuId(0L);
		tm.setName("主菜单-没有父节点");
		tm.setNavMenu(navMenu);

		pojos.add(tm);

		return pojos.toString();
	}

	@Override
	public void batchRemove(Long[] ids) throws MenuDataAccessException,
			MenuNotFoundException {
		TreeMenu treeMenu = null;
		for (Long id : ids) {
			treeMenu = treeMenuDAO.getOne(id);
			if (treeMenu == null)
				throw new MenuNotFoundException();

			treeMenuDAO.deleteOne(id);
		}
	}

	@Override
	public void removeOne(Long id) throws MenuDataAccessException,
			MenuNotFoundException {
		TreeMenu treeMenu = treeMenuDAO.getOne(id);
		if (treeMenu == null)
			throw new MenuNotFoundException();

		treeMenuDAO.deleteOne(id);
	}

	@Override
	public void addWithCascade(TreeMenu treeMenu, Long navMenuId, Long pid)
			throws MenuDataAccessException, CannotFindNavMenuException,
			CannotFindParentMenuException, CannotBeParentMenuException,
			DuplicateMenuNameException {

		TreeMenu tmp_TreeMenu = this.treeMenuDAO.getOneByName(treeMenu
				.getName());
		if (tmp_TreeMenu != null)
			throw new DuplicateMenuNameException();

		if (navMenuId == null || navMenuId <= 0)
			throw new CannotFindNavMenuException();

		NavMenu navMenu = this.navMenuDAO.getOne(navMenuId);
		if (navMenu == null)
			throw new CannotFindNavMenuException();

		if (pid > 0) {
			TreeMenu parent = this.treeMenuDAO.getOne(pid);
			if (parent == null)
				throw new CannotFindParentMenuException();
			if (pid.equals(treeMenu.getTreeMenuId()))
				throw new CannotBeParentMenuException();
			treeMenu.setParent(parent);
		} else {
			treeMenu.setParent(new TreeMenu());
		}

		treeMenu.setNavMenu(navMenu);

		String reloadFlag = treeMenu.getReloadFlag();
		treeMenu.setReloadFlag("on".equals(reloadFlag) ? "1" : "0");

		this.treeMenuDAO.create(treeMenu);
	}

	@Override
	public EditPage<TreeMenu> getEditPage(Long id)
			throws MenuDataAccessException, MenuNotFoundException {

		TreeMenu treeMenu = this.treeMenuDAO.getOne(id);
		if (treeMenu == null)
			throw new MenuNotFoundException();

		String reloadFlag = treeMenu.getReloadFlag();
		treeMenu.setReloadFlag("1".equals(reloadFlag) ? "checked" : "");

		EditPage<TreeMenu> editPage = new EditPage<TreeMenu>(
				TreeMenuCons.MODEL_NAME, TreeMenuCons.MODEL_NAME + "/" + id,
				treeMenu);

		return editPage;
	}

	@Override
	public void updateWithCascade(TreeMenu treeMenu, Long navMenuId, Long pid)
			throws MenuDataAccessException, MenuNotFoundException,
			CannotFindNavMenuException, CannotFindParentMenuException,
			CannotBeParentMenuException, DuplicateMenuNameException {
		Long id = treeMenu.getTreeMenuId();
		if (id == null || id <= 0)
			throw new MenuNotFoundException();

		TreeMenu tmp_TreeMenu = this.treeMenuDAO.getOne(treeMenu
				.getTreeMenuId());
		if (tmp_TreeMenu == null)
			throw new MenuNotFoundException();

		tmp_TreeMenu = this.treeMenuDAO.getOneByName(treeMenu.getName());
		if (tmp_TreeMenu != null
				&& !tmp_TreeMenu.getTreeMenuId().equals(
						treeMenu.getTreeMenuId()))
			throw new DuplicateMenuNameException();

		if (navMenuId == null || navMenuId <= 0)
			throw new CannotFindNavMenuException();
		NavMenu navMenu = this.navMenuDAO.getOne(navMenuId);
		if (navMenu == null)
			throw new CannotFindNavMenuException();

		if (pid > 0) {
			TreeMenu parent = this.treeMenuDAO.getOne(pid);
			if (parent == null)
				throw new CannotFindParentMenuException();
			if (pid.equals(treeMenu.getTreeMenuId()))
				throw new CannotBeParentMenuException();
			treeMenu.setParent(parent);
		}else {
			treeMenu.setParent(new TreeMenu());
		}

		treeMenu.setNavMenu(navMenu);

		String reloadFlag = treeMenu.getReloadFlag();
		treeMenu.setReloadFlag("on".equals(reloadFlag) ? "1" : "0");

		this.treeMenuDAO.update(treeMenu);
	}

	@Override
	public List<TreeMenu> getTopParent(Long navMenuId)
			throws CannotFindNavMenuException, MenuDataAccessException {
		if (navMenuId == null || navMenuId <= 0)
			throw new CannotFindNavMenuException();

		NavMenu navMenu = this.navMenuDAO.getOne(navMenuId);
		if (navMenu == null)
			throw new CannotFindNavMenuException();

		return this.treeMenuDAO.getTopParentOrderByRankASC(navMenuId);
	}

	@Override
	public List<TreeMenu> getChildren(Long pid)
			throws CannotFindParentMenuException, MenuDataAccessException {
		if (pid == null || pid <= 0)
			throw new CannotFindParentMenuException();

		TreeMenu parent = this.treeMenuDAO.getOne(pid);
		if (parent == null)
			throw new CannotFindParentMenuException();

		return this.treeMenuDAO.getChildrenOrderByRankASC(pid);
	}
}



package com.cfuture08.eweb4j.component.dwz.menu.domain.dao;

import java.util.List;

import com.cfuture08.eweb4j.component.dwz.menu.domain.model.TreeMenu;
import com.cfuture08.eweb4j.component.dwz.menu.exception.MenuDataAccessException;
import com.cfuture08.eweb4j.orm.dao.DAOException;
import com.cfuture08.eweb4j.orm.dao.base.BaseDAO;
import com.cfuture08.eweb4j.orm.dao.base.BaseDAOImpl;
import com.cfuture08.eweb4j.orm.dao.factory.DAOFactory;
import com.cfuture08.eweb4j.orm.sql.constant.OrderType;

public class TreeMenuDAOImpl implements TreeMenuDAO {
	private BaseDAO<TreeMenu> dao = new BaseDAOImpl<TreeMenu>(TreeMenu.class);

	@Override
	public List<TreeMenu> getPageWithCascade(int pageNum, int numPerPage)
			throws MenuDataAccessException {
		List<TreeMenu> list = null;
		try {
			list = dao.getPage(pageNum, numPerPage);
			if (list != null)
				DAOFactory.getCascadeDAO().select(
						list.toArray(new TreeMenu[] {}), "parent", "navMenu");
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return list;
	}

	@Override
	public long countAll() throws MenuDataAccessException {
		long count = 0;
		try {
			count = dao.countAll();
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return count;
	}

	@Override
	public long countSearch(String keyword) throws MenuDataAccessException {
		long count = 0;
		try {
			String condition = "name like '%" + keyword + "%'";
			count = DAOFactory.getSelectDAO().selectCount(TreeMenu.class,
					condition);
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return count;
	}

	@Override
	public List<TreeMenu> getSearchResult(String keyword, int pageNum,
			int numPerPage) throws MenuDataAccessException {
		List<TreeMenu> list = null;
		try {
			String[] fields = new String[] { "name" };
			list = dao.searchByKeywordAndPaging(fields, keyword, pageNum,
					numPerPage, 0);
			if (list != null)
				DAOFactory.getCascadeDAO().select(
						list.toArray(new TreeMenu[] {}), "parent", "navMenu");
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return list;
	}

	@Override
	public TreeMenu getOne(Long id) throws MenuDataAccessException {
		TreeMenu treeMenu = null;
		try {
			treeMenu = dao.getOne(id);
			if (treeMenu != null)
				DAOFactory.getCascadeDAO()
						.select(treeMenu, "navMenu", "parent");
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return treeMenu;
	}

	@Override
	public void update(TreeMenu treeMenu) throws MenuDataAccessException {
		try {
			DAOFactory.getUpdateDAO().update(treeMenu);
			DAOFactory.getCascadeDAO().update(treeMenu, "parent", "navMenu");
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}
	}

	@Override
	public void create(TreeMenu treeMenu) throws MenuDataAccessException {
		try {
			Long treeMenuId = Long.parseLong(""
					+ DAOFactory.getInsertDAO().insert(treeMenu));
			treeMenu.setTreeMenuId(treeMenuId);
			DAOFactory.getCascadeDAO().update(treeMenu, "parent", "navMenu");
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}
	}

	@Override
	public List<TreeMenu> getParent(Long navMenuId, Long treeMenuId)
			throws MenuDataAccessException {
		List<TreeMenu> pojos = null;
		try {
			String condition = "id <> ? and navMenuId = ? ";
			pojos = DAOFactory.getSelectDAO().selectWhere(TreeMenu.class,
					condition, treeMenuId, navMenuId);
			if (pojos != null) 
				DAOFactory.getCascadeDAO().select(
						pojos.toArray(new TreeMenu[] {}), "parent", "navMenu");
			
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return pojos;
	}

	@Override
	public List<TreeMenu> getParentSearchResult(int pageNum, int numPerPage,
			String keyword, Long navMenuId, Long treeMenuId)
			throws MenuDataAccessException {
		List<TreeMenu> pojos = null;
		try {
			String condition = "id <> ? and navMenuId = ? and name like ? ";
			Object[] args = new Object[] { treeMenuId, navMenuId,
					"%" + keyword + "%" };
			pojos = DAOFactory.getDivPageDAO().divPageByWhere(TreeMenu.class,
					pageNum, numPerPage, condition, args);
			if (pojos != null) 
				DAOFactory.getCascadeDAO().select(
						pojos.toArray(new TreeMenu[] {}), "parent", "navMenu");
			
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return pojos;
	}

	@Override
	public long countParentSearchResult(String keyword, Long navMenuId,
			Long treeMenuId) throws MenuDataAccessException {
		long count = 0;
		try {
			String condition = "id <> '" + treeMenuId + "' and navMenuId = '"
					+ navMenuId + "' and name like '%" + keyword + "%'";
			count = DAOFactory.getSelectDAO().selectCount(TreeMenu.class,
					condition);
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}
		return count;
	}

	@Override
	public void deleteOne(Long id) throws MenuDataAccessException {
		try {
			dao.delete(new Long[] { id });
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}
	}

	@Override
	public TreeMenu getOneByName(String name) throws MenuDataAccessException {
		TreeMenu treeMenu = null;
		try {
			treeMenu = DAOFactory.getSelectDAO().selectOne(TreeMenu.class,
					new String[] { "name" }, new String[] { name });
		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return treeMenu;
	}

	@Override
	public List<TreeMenu> getTopParentOrderByRankASC(Long navMenuId)
			throws MenuDataAccessException {
		List<TreeMenu> pojos = null;
		try {
			String[] fields = new String[] { "pid", "navMenuId" };
			String[] values = new String[] { "0", String.valueOf(navMenuId) };

			pojos = DAOFactory.getSearchDAO().searchByExact(TreeMenu.class,
					fields, values, "rank", OrderType.ASC_ORDER, false);

		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return pojos;
	}

	@Override
	public List<TreeMenu> getChildrenOrderByRankASC(Long pid)
			throws MenuDataAccessException {
		List<TreeMenu> pojos = null;
		try {
			String[] fields = new String[] { "pid" };
			String[] values = new String[] { String.valueOf(pid) };

			pojos = DAOFactory.getSearchDAO().searchByExact(TreeMenu.class,
					fields, values, "rank", OrderType.ASC_ORDER, false);

		} catch (DAOException e) {
			throw new MenuDataAccessException(e.getMessage());
		}

		return pojos;
	}
}



15
4
评论 共 43 条 请登录后发表评论
43 楼 ta8210 2013-06-19 14:22
laiweiweihi 写道
ta8210 写道
"可先使用本框架快速开发,然后方便的转换成SSH"

冲着这句话我不看好这个框架的,更不会选择它。

首先我觉得作者对这个框架的定位有问题。框架不是用来换来换去的,那种东西是Toos。
框架在程序的架构中占有很重要的角色。

后来我自己也觉得当初这么定位是有些欠考虑的,独立的东西就该独立而不要附和其他框架,当然一些官方规范还是要支持的。比如JPA、JAX-RS此类的。


嗯,还有就是(MVC、ORM、IOC)这些的框架满地开花,其价值已经不高了,在把框架的步子扩大点。

期待看到你新版本的诞生。给你个建议,例子不要写的这么复杂,只做功能性演示就好。还有就是你的配置我觉得可以简化。试试注解配置把。
42 楼 laiweiweihi 2013-06-19 10:36
ta8210 写道
"可先使用本框架快速开发,然后方便的转换成SSH"

冲着这句话我不看好这个框架的,更不会选择它。

首先我觉得作者对这个框架的定位有问题。框架不是用来换来换去的,那种东西是Toos。
框架在程序的架构中占有很重要的角色。

后来我自己也觉得当初这么定位是有些欠考虑的,独立的东西就该独立而不要附和其他框架,当然一些官方规范还是要支持的。比如JPA、JAX-RS此类的。
41 楼 ta8210 2013-06-14 18:14
"可先使用本框架快速开发,然后方便的转换成SSH"

冲着这句话我不看好这个框架的,更不会选择它。

首先我觉得作者对这个框架的定位有问题。框架不是用来换来换去的,那种东西是Toos。
框架在程序的架构中占有很重要的角色。
40 楼 nggno1 2012-08-14 09:06
支持楼主,开源就是美!鄙视那些说垃圾的人,有本事自己写
39 楼 laiweiweihi 2011-10-08 10:24
抱歉,之前发的下载包里doc下的使用文档都是PDF的,现在更新一个Word格式的吧,先从QuickStart开始哦。
另外,使用eweb4j,不要去自己手写配置文件,框架会自动生成的。

http://code.google.com/p/eweb4j/downloads/list
38 楼 laiweiweihi 2011-10-08 10:00
zhu_chen001 写道
代码还是复杂了,基于数据库操作的页面+后台代码,再复杂的关联也是150行可以完成增删改查的操作的。多与150行就是多余的代码。

冒昧的请教下,这个150行是阁下的经验成果么?
37 楼 laiweiweihi 2011-10-08 09:56
zhu_chen001 写道
代码还是复杂了,基于数据库操作的页面+后台代码,再复杂的关联也是150行可以完成增删改查的操作的。多与150行就是多余的代码。

代码行数确实是一个参考,不过那是业务层的考量,我已经能够将逻辑代码精简过一次了,不过分层总会带来代码的肿胀,看具体项目开发需求了,我一般都喜欢前期Action+泛型DAO解决问题。后期慢慢分层,封装,异常设计。现在看到的是稍微考量之后的代码。
36 楼 zhu_chen001 2011-10-08 09:52
代码还是复杂了,基于数据库操作的页面+后台代码,再复杂的关联也是150行可以完成增删改查的操作的。多与150行就是多余的代码。
35 楼 laiweiweihi 2011-10-08 09:25
leon1509 写道
一颗树就要这么复杂?

NO,不是一棵树的问题。是两个有关系的实体的CRUD,如果数据不需要管理,那表现一棵树很简单。那是前端的事。
34 楼 leon1509 2011-10-08 09:11
一颗树就要这么复杂?
33 楼 laiweiweihi 2011-10-07 21:17
ch_reynold 写道
eweb4j框架对spring mvc进行微创新,合理使用注解替换xml配置,将主流ORM.mvc理念根据自己需要做了相应组合和封装,但现在一般主流企业级框架组合起来可以达到企业开发需要需求,同时我个人认为注解使用最好不要与通过注解对DO和VO映射起来,并且对action成web资源控制不要注解化,因为注解意味着强耦合,强关联,对类和资源定位非常简单化,导致web资源修改时非常麻烦,同是代码关联可寻性非常麻烦。所以个人想法:
对service和Dao 事物处理可以采用注解,对vo和do还是采用javaBean形式。对action的web资源访问还是采用xml配置。。。。


Action url配置等都是一些常量,可以统一设计一个常量类或接口来进行管理。我自己在编码中也是如此做的,感觉效果还行。
32 楼 kjj 2011-10-07 20:19
感觉到没有play的步子大!!!!!
31 楼 jimly1032 2011-10-07 18:03
shuaiji 写道
不要说垃圾不垃圾,等你我又能力编写出类似这个同样的程序时,再评论人家垃圾不垃圾不迟

同意,哈哈,来支持了。
30 楼 shuaiji 2011-10-07 16:40
不要说垃圾不垃圾,等你我又能力编写出类似这个同样的程序时,再评论人家垃圾不垃圾不迟
29 楼 laiweiweihi 2011-10-07 13:50
ch_reynold 写道
eweb4j框架对spring mvc进行微创新,合理使用注解替换xml配置,将主流ORM.mvc理念根据自己需要做了相应组合和封装,但现在一般主流企业级框架组合起来可以达到企业开发需要需求,同时我个人认为注解使用最好不要与通过注解对DO和VO映射起来,并且对action成web资源控制不要注解化,因为注解意味着强耦合,强关联,对类和资源定位非常简单化,导致web资源修改时非常麻烦,同是代码关联可寻性非常麻烦。所以个人想法:
对service和Dao 事物处理可以采用注解,对vo和do还是采用javaBean形式。对action的web资源访问还是采用xml配置。。。。


eweb也提供action和orm的xml配置, ,不过我个人确实更推崇注解。
28 楼 ch_reynold 2011-10-07 12:21
eweb4j框架对spring mvc进行微创新,合理使用注解替换xml配置,将主流ORM.mvc理念根据自己需要做了相应组合和封装,但现在一般主流企业级框架组合起来可以达到企业开发需要需求,同时我个人认为注解使用最好不要与通过注解对DO和VO映射起来,并且对action成web资源控制不要注解化,因为注解意味着强耦合,强关联,对类和资源定位非常简单化,导致web资源修改时非常麻烦,同是代码关联可寻性非常麻烦。所以个人想法:
对service和Dao 事物处理可以采用注解,对vo和do还是采用javaBean形式。对action的web资源访问还是采用xml配置。。。。
27 楼 KimHo 2011-10-06 14:32
国人还是学习不到乔布斯那种创新精神
26 楼 kimmking 2011-10-06 12:08
kimmking 写道
太像spring mvc了,
有什么不同?


没有比较和批评,何谈进步。。。
一个项目的评论都是和谐的,
不是nb到bt的东西,就是快死了。
25 楼 caoyangx 2011-10-05 13:45
ray_linn 写道
简化了半天,具体简化了多少,相同功能用SSH实现需要多少行代码,你的又要多少行,Rails是多少行?给点数据比一比呗。


从你目前给的东西来看,确实一点兴趣没有。


你完全没有搞懂这个框架的优点,
别拿卡车和跑车比载重量好吗?
用生工具根本就不用写几行代码,你能用吗?
24 楼 ray_linn 2011-10-05 09:28
简化了半天,具体简化了多少,相同功能用SSH实现需要多少行代码,你的又要多少行,Rails是多少行?给点数据比一比呗。


从你目前给的东西来看,确实一点兴趣没有。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 出现 Property or method “xx“ is not defined on the instance but referenced during render 解决方法(全面分析)

    出现 Property or method "xx" is not defined on the instance but referenced during render 解决方法(全面分析)

  • SimpleASM Project-开源

    SimpleASM是MASM(Microsoft的宏汇编程序)的IDE,它是用Borland Delphi6完全编写的。 它使用多个控件(请参阅首页),并且能够修改哈希表以更改标记(颜色,样式等)。编译器参数可以

  • Win32_Simple.asm

    ; [ W32.Simple by XXXXXX ] ; -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- ; THIS IS A VERY SMALL AND SIMPLE WIN32 PE INFECTOR.. IT INFECTS ONLY ; FILES IN THE CURRENT DIRECTORY.

  • 推荐开源项目:SimpleAMS

    推荐开源项目:SimpleAMS 去发现同类优质开源项目:https://gitcode.com/ 在开发过程中,我们经常需要与现代API进行交互,为此需要构建强大的库来支持。SimpleAMS就是这样一款现代化的Ruby序列化库,它以简单易用为设计理念,同时也为复杂的任务提供了可能。 项目介绍 SimpleAMS是一个轻量级的序列化解决方案,专为处理现代API而设计,尤其适合那些寻求简洁且灵活的...

  • “Property or method “***“ is not defined on the instance but referenced during render.”报错的原因及解决方案

    报错问题: 在使用vue-cli运行项目的过程中,在VScode中不报错,但在浏览器调试工具中发出 [Vue warn]: Property or method "pic" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by in.

  • Property or method “XXX“ is not defined on the instance but referenced during render.(Vue项目报错)

    报错内容如下: [Vue warn]: Property or method "cancelForm" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https:/

  • Property or method “option“ is not defined on the instance but referenced during render. Make sure t

    完整的报错信息如下: 原因: 你的“”xxx‘’属性或者"xxx"方法没有定义,查看你的data或者methods或者prop 解决: export default { data(){ return{ xxx:"" }, methods:{ xxx(){} } }, }

  • Property or method “xxx“ is not defined on the instance but referenced during render.

    解决方法:查看相应位置的代码,未定义的方法在methods中进行定义,名称不一致的改成一致的。错误原因:一种是未定义的方法被引用;另一种是定义了方法,但是定义的名称和引用的名称不一致。方法或特性违背定义就被引用。点击的事件处理是无效的。

  • VUE报错:Property or method “****“ is not defined on the instance but referenced during render

    其实报错已经很明显了,没有定义。因为js不会进行语法检查,出现未定义警告简直常见。最主要还是要细心,代码不规范,亲人两行泪。:在警告提示的文件里,找到改属性或方法重新在data或methods中定义。:在实例渲染期间,属性或方法XXX没有定义。...

  • ASM简单入门笔记

    1. 前言 前几天,在Q群里有个大佬,展示了下 Android 做无痕埋点,觉得挺厉害的 问了下使用的是 AspectJ, 网上搜了下资料 ASM 比 AspectJ 更灵活,更轻量 刚好趁着五一假期系统的学习下 复制代码 2. 介绍 ASM 是一款轻量级的Java字节码操作仓库 复制代码 3. 前期准备 3.1 简单的asm 方面的知识 ASM 主要有几个类需要了解 而且需要对 Java字节码 ...

  • ros源码分析(三)ros::spin( )背后发生的事

    接收器subscriber的demo大家也耳熟能详,它和发布器一样,在nodehandle中调用subscribe函数,实现话题名与回调函数的注册,而在进程的main函数中,又在调用ros::spin函数,那么就从这两个部分依次分析接收器的原理。 一、subscribe的声明 在node_handle.cpp中,subscribe函数的声明如下, template&lt;class M,...

  • Memcached 使用中的问题

    1.Memcached是一个key-value形式的高性能的分布式 内存对象缓存系统.可以让不同主机上的多个用户同时访问,用于在动态应用中减少数据库负载,提升访问速度。 2.memcached下载地址:http://windows.php.net/downloads/pecl/releases/memcache/3.0.8/ 3.memcached基本命令: memcached

  • Brief for Django using 3

    DRY::(Don’t Repeat Yourself) Django provides with a lot of high-efficient tools which can speed up your developing process. Learning to use them is a big deal, however, you are going to learn much mor

  • [Vue warn]: The data property "orderId" is already declared as a prop.Use prop default value instead

    在使用Vue开发中,使用组件时报了这么一个错误: [Vue warn]: The data property &quot;list&quot; is already declared as a prop. Use prop default value instead. 翻译的白话就是:“list”已经在prop声明了. 错误代码: export default { props:{ ...

  • java异常处理

    版权声明:原创不易,转载请注明转自Error Handling with Exceptions异常恢复是提高鲁棒性最重要的方法。前言:这篇文章是我自己的笔记,基本上是我翻译的《Thinking in Java》第12章,翻译不是目的,目的是想写一遍印象深刻,因为有些句子翻译不好,就抄了原文。。。基本概念异常条件(exceptional conditions)是一个可以阻止程序继续执行的问题。出现了异

  • 使用session 报错:Exception thrown without a stack frame in Unknown on line 0

    解决办法:开启php.ini,设置session.save_path路径,就ok了。 问题:为何使用session的默认路径报错?????

  • Memcache 异常调查 一

    异常++++ exception thrown while trying to get object from cache for key: s2i1-E%2573gyod66%2B1%25%25al%25%25yDue%25ila4xQp3ns%25irrloPteLvPsel372D3lu_2D%2B_af675c67093ec75db15b6d740733bd87_775183877_1837

Global site tag (gtag.js) - Google Analytics