eweb4j-1.9-控制器更新预览

自风 发布于 2012/04/13 17:28
阅读 213
收藏 0

主要增加以下更新:

  • 验证器
  • 声明式事务
  • 7个默认Action方法

PS:这个例子也演示了如何使用ActiveModel + Control + Validator 完成 Crud 。 

验证器 

1.8.6以及更旧版本的验证器使用起来非常鸡肋。主要存在一下几个缺点: 

  1. 验证规则定义之后,只要是控制器的属性,所有该控制器下的Action方法被执行的时候都会强制的激活验证程序。
  2. 验证程序检测到错误信息后,框架自己把它给处理了,虽然能满足一定的需求,但是这种方式让开发者无法自己灵活低控制。长久来说是不好的。

基于上述两点,本次即将发布的版本1.9针对它们做了改善。请先看看下面这段代码; 

Pet.java 

@Entity
@Table(name = "t_pet")
public class Pet extends Model {

	public final static Pet inst = new Pet();

	@Required
	@Length(min = 6, max = 6)
	private String num;

	@Required
	@Length(min = 2, max = 6)
	@Chinese
	@Forbid(words = {"性爱", "革命"})
	private String name;

	@Size(min = 1, max = 10)
	private int age = 1;

	@Required
	@Enumer(words = { "猫", "狗" })
	private String type;

	@Override
	public String toString() {
		return "Pet [num=" + num + ", name=" + name + ", age=" + age
				+ ", type=" + type + ", id=" + id + "]";
	}

        //setters and getters
}

PetsControl.java 
public class PetsControl {

	private final static String PAGE_INT = "分页参数必须是整数格式";
	private final static String PAGE_VALID = "分页参数必须大于 0 ";
	private final static List<String> TYPES = Arrays.asList("狗", "猫");

	private Pet pet = new Pet();// inject when create and update

	@Required
	@Size(min = 1)
	@Int
	private Long id;

	@Int(mess = PAGE_INT)
	@Size(min = 1, mess = PAGE_VALID)
	private int pageNum = 1;

	@Int(mess = PAGE_INT)
	@Size(min = 1, mess = PAGE_VALID)
	private int numPerPage = 10;

	private String keyword = "";

	@Validate({ "pageNum", "numPerPage" })
	public String index(Validation val, Map model) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		model.put("pets", Pet.inst.find().fetch(pageNum, numPerPage));
		model.put("dpc", new DivPageComp(pageNum, numPerPage, Pet.inst.count()));

		return "html";
	}

	public String doSearchAtGet(Map model) {
		model.put("pets", Pet.inst.find("name like ?", "%" + keyword + "%")
				.fetch());

		return "fmt:pets/view/list.html";
	}

	@Validate("pet.*")
	@Transactional
	public String create(Validation val, Map model) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		pet.create();

		model.put("types", TYPES);

		return "index";
	}

	@Validate({ "id", "pet.*" })
	@Transactional
	public String update(Validation val, Map model) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		pet.setId(id);
		pet.save();

		model.put("types", TYPES);

		return "index";
	}

	@Validate("id")
	@Transactional
	public String destroy(Validation val) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		pet.setId(id);
		pet.delete();

		return "index";
	}

	@Validate("id")
	public String show(Validation val) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		pet.setId(id);
		pet.load();
		
		return "html";
	}

	@Validate("id")
	public String edit(Validation val, Map model) {
		if (val.hasErr())
			return JsonConverter.convert(val.getAllErr());

		pet.setId(id);
		pet.load();
		
		model.put("types", TYPES);
		
		return "html";
	}

	public String editNew(Map model) {
		
		model.put("types", TYPES);
		
		return "html";
	}

        //setters and getters
}

上面有个 doSearchAtGet 方法不是默认约定的方法,是属于自定义的Action方法。请对照前面博文中提到的 Action 方法名字新语法支持的内容。 

注意对照 7 个默认的方法: 

HTTP Method URI Class.Method Params
GET /demo DemoControl.index
POST /demo DemoControl.create
PUT /demo/{id} DemoControl.update id={id}
DELETE /demo/{id} DemoControl.destroy id={id}
GET /demo/{id} DemoControl.show id={id}
GET /demo/{id}/edit DemoControl.edit id={id}
GET /demo/new DemoControl.editNew id={id}

当执行 GET /pets/new 打开 new.html后,直接什么也不填写就提交,然后验证器生效,页面上会打印: 

{"pet.num":"请完成必填内容","pet.name":"请填写全中文"}

 可以看到好几个Action方法上面都有 @Validate 注解。这个注解填写一个字符串数组。这些数组声明了在执行这个Action的时候哪些参数需要被验证。具体的验证规则交由属性上的那些类似 @Required @Size @Forbid 这样的注解来定义。也就是说: 

验证过程分为两点: 

  1. 定义规则, 在属性上面标注 @Required 等等的注解。 
  2. 触发验证行为, 在Action方法上标注 @Validate({"param1", "param2"}),来声明那些需要被验证的参数 

还有最后一个就是验证行为一旦触发,并且检测到错误消息后,框架不再截断当前Action的执行,而是将验证信息封装到一个 Validation 对象里面,就像: 

@Validate({ "id", "pet.*" })
@Transactional
public String update(Validation val, Map model) {
    if (val.hasErr())
        return JsonConverter.convert(val.getAllErr());

    return "通过验证啦...";
}

然后取出所有的参数验证信息: 

Map<String,String> errors = val.getAllErr();

上面这个 Map 里面是 “参数名”-“验证信息”这样的结构的。只要某个参数违反了验证规则的话,那么这个Map里面就会存在该参数以及对应的验证错误消息。 

例如: 

{"pet.age":"请填写一个大小介于 1 到 10 之间的整数","pet.num":"请填写长度介于6到6之间的文<本","pet.name":"请不要包含下列字眼:[性爱#革命] "}

这个PetControl的代码最好细细品读。方能理解一些约定思想。 

最后重申: 约定优于配置, 配置覆盖约定。 
加载中
0
开源狂人
开源狂人
不错,清晰多了,继续努力。
自风
自风
感谢大哥哥一直以来的关注和支持。
返回顶部
顶部