首先先来讲讲上个章节的,修正了2个bug:1、自读字段不用disabled而是用readonly;2、修正了parseAttr默认值覆盖当前值的bug。
上个章节的效果图补在这:




这个章节,由于我考虑到的是,我在后台进行操作时可能需要给后台反馈许多信息,例如操作的成功与否、是否出现程序异常等,而这些信息都需要通过CtrlResult的实例返回,这样才能够正确的与我前台封装的控件挂上勾来。但是如果我们每次都手动的new一个CtrlResult的实例,然后去设置值,未免显得有些太粗糙了,在加上异常信息的处理,每次都去try catch之后再包裹信息,多烦啊。
因此,nutz默认为我们提供的json视图已经不能满足我的需求了。于是我用了nutz的自定义视图。我写的时候,其实只是把nutz源码中的json的视图拿过来做做修改而已。
我定义了两个视图(只贴主要部分):
public void render(HttpServletRequest req, HttpServletResponse resp, Object obj)
throws IOException {
if(obj!=null){//如果不为空
if(obj instanceof TPager) {//分页数据
CtrlResult cr = new CtrlResult();
cr.setValue(obj);
Mvcs.write(resp, cr, format);
}else {//直接返回当前数据。
Mvcs.write(resp, obj, format);
}
}else{//void形式时,返回提示信息“操作成功!”
CtrlResult cr = new CtrlResult();
cr.setMsg("操作成功!");
Mvcs.write(resp, cr, format);
}
}
public void render(HttpServletRequest req, HttpServletResponse resp, Object obj)
throws IOException {
if(obj!=null){
CtrlResult cr = new CtrlResult();
if(obj instanceof RuntimeException){//运行时异常
cr.setMsgType(CtrlResult.MSG_TYPE_ERR);
cr.setValue(obj);
RuntimeException re = (RuntimeException) obj;
cr.setMsg(re.getMessage());
}else{
cr.setMsgType(CtrlResult.MSG_TYPE_ERR);
cr.setValue(obj);
Exception re = (Exception) obj;
cr.setMsg(re.getMessage());
}
Mvcs.write(resp, cr, format);
}else{
Mvcs.write(resp, data, format);
}
}
public View make(Ioc ioc, String type, String value) {
type = type.toLowerCase();
if (VIEW_EXCEPTION.equals(type))//异常
if (Strings.isBlank(value))
return new ExceptionView(JsonFormat.compact());
else
return new ExceptionView(Json.fromJson(JsonFormat.class, value));
else if (VIEW_SUCCESS.equals(type))//成功
if (Strings.isBlank(value))
return new SuccessView(JsonFormat.compact());
else
return new SuccessView(Json.fromJson(JsonFormat.class, value));
return null;
}
然后在MainModule中修改annotation配置:
@Modules(scanPackage=true)
@Views(TViewMaker.class)
@Ok("success")
@Fail("exception")
@IocBy(type=ComboIocProvider.class, args={
"*org.nutz.ioc.loader.json.JsonLoader", "cfg/ioc/",
"*org.nutz.ioc.loader.annotation.AnnotationIocLoader", "com.tt"
})
@SetupBy(value=TSetup.class)
public class MainModule {
}
这样,在成功情况下,我的ctrl可以不设置返回值,那么前台默认提示“操作成功!”
@At("/create")
public void create(@Param("..")Curd curd){
//插入操作
}
如果返回值为TPager,我将视为分页数据,因此为自动为其包裹在CtrlResult实例中:
@At("/query4Page")
public TPager query4Page(){
List<Curd> list = new ArrayList<Curd>();
for(int i = 0; i < 10; i++){
Curd curd = new Curd(i, "name" + i, "address" + i, i);
list.add(curd);
}
return new TPager(list, list.size());
}
除以上情况,我将直接将对象返回给前台。
为了方便返回成功状态下的CtrlResult实例,在TUtils中封装了getOk方法。
当系统的提示信息一多时,如果用String写死在每段业务代码中的话,那么后期维护起来肯定会吐血的,所以建议要嘛通过配置文件管理,要嘛通过数据库管理。严禁直接写死在代码中(我目前在写的一些例子可能还是会出现直接写死的情况,1是做测试而已比较懒,你们不能学的哈;2、是为了写博客的时候方便大家直接了解意思,喷我吧~~)。至于是采用文件还是数据库,这个可能就要看具体的项目要求了,因此我定义了一个IMsgLoader接口:
/** * DESC:通过信息编码获取到对应的提示信息,并为占位符填充相应信息。 * @author Small * @Email 536762164@qq.com * @since 2013-5-20 * * @param msgCode * @param args * @return */ public String getMsg(String msgCode, Object... args);
默认的,我定义了一个通过properties文件配置消息码的,采用了ResourceBundle实现,具体代码我就不贴了。然后在cfg.ioc下面新增一个app.js,用来放置一些注入实例,在其中添加对IMsgLoader的注入:
msgLoader : {
type : "com.tt.pub.msg.impl.MsgLoader4Prop"
}
如果要切换实现方式,只需要在这个配置中改就可以了。
接着,我将msgLoader缓存在TCache中,设置的代码在TInit中实现。然后在TUtils中实现了getMsg方法,用于公共获取消息。这部分实现之后,我们就可以来设计一个属于自己的异常类了。
异常类我定义为MsgException:
public class MsgException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
/** 消息码 */
protected String msgCode = "";
/** 传参 */
protected Object[] args;
/**
* @param e 异常类
* @param msgCode 消息码
* @param args 传参
*/
public MsgException(Throwable e, String msgCode, Object... args){
super(e);
this.msgCode = msgCode;
this.args = args;
}
/**
* @param msgCode 消息码
* @param args 传参
*/
public MsgException(String msgCode, Object... args){
this.msgCode = msgCode;
this.args = args;
}
/**
* Desc:获取消息。
* @author Small
* @Email 536762164@qq.com
* @since 2013-5-20
*
* @return
*/
public String getMsg(){
return TUtils.getMsg(msgCode, args);
}
public String getMessage(){
return TUtils.getMsg(msgCode, args);
}
}
其实也就是重写了getMessage方法,这时候就与ExceptionView中的内容相结合了。我们用这个异常类来返回我们的业务异常提示信息。
通常我们在进行一些业务操作时,会进行一些判断,如果判断不通过则终断并返回给前台信息。在没有这个异常类前,我们可能会这么处理:
public CtrlResult oper(){
//TODO 业务操作1
if(用户不存在) return 用户不存在
//TODO 业务操作2
return 成功
}
但是这种操作会产生很多问题,代码量多时一回事,有时还得自己做事务回滚操作。
于是我们有了通过异常的解决方案:
public CtrlResult oper(){
//TODO 业务操作1
if(用户不存在) throw new MsgException("用户不存在");
//TODO 业务操作2
return 成功
}
如此,通过异常我们就可以很容易来操作了。但是这还不满我意。于是我在TUtils中定义了一个pass方法。当第一个参数为ture时表示通过,否则将抛出异常:
public static void pass(boolean judge, String msgCode, Object... args){
if(!judge){
throw new MsgException(msgCode, args);
}
}
获取你们会觉得有些多余,但这是我个人的习惯,觉得这样挺好理逻辑的,个人相对比较喜欢这样的代码:
public CtrlResult oper(){
//TODO 业务操作1
TUtils.pass(用户存在, "用户不存在");
//TODO 业务操作2
return 成功
}
当然,你有权不按我这么做,也可以喷我哈~~
至此,今天的内容就结束了。值得说的是,nutz的视图实在给力!
源码还是传不上去,明天传,睡觉去了,明天还得上班呢~~
本文介绍如何在NutZ框架中自定义视图以更好地处理前后台交互,包括异常处理、信息反馈等内容。

631

被折叠的 条评论
为什么被折叠?



