该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-04-05
private final static String GET_ALL_USER_QUERY = "form User as user"; private final static String CHECK_USER_NAME_QUERY = "from User as user where user.userName=:userName"; private final static String LOGIN_QUERY = "from User as user where user.userName=:userName and user.passWord=:passWord"; /** * 检查此用户名是否可注册使用,如果已经存在则为false,如果不存在则为true * @param userName * @return */ public boolean checkUserName(final String userName); throws ExampleException{ List list = this.getHibernateTemplate();.executeFind(new HibernateCallback(); { public Object doInHibernate(Session session); throws HibernateException, SQLException { Query query = session.createQuery(CHECK_USER_NAME_QUERY);; query.setString("userName",userName);; return query.list();; } });; if(list.size();==0);{ return true; }else if(list.size();>1);{ throw new ExampleException("数据库user表中有个两个"+userName+"帐号");; }else{ return false; } } /** * 用户登录 * @param userName 用户名 * @param passWord 密码 * @return 二维对象数组,object[0]表示登陆状态,0为登陆成功,1为无此用户,2为密码错误,3为用户已经被禁用,若登陆成功oject[1]为User实体对象,若未成功则为null * @throws ExampleException 数据库数据错误 */ public Object[] login(final String userName,final String passWord); throws ExampleException{ //登陆成功 final Integer login_success = new Integer(0);; //无此用户名 final Integer have_not_this_username = new Integer(1);; //密码错误 final Integer wrong_password = new Integer(2);; //此用户已经被禁用 final Integer deny_username = new Integer(3);; boolean usable = checkUserName(userName);; if(usable);{ return new Object[]{have_not_this_username,null}; }else{ List list = this.getHibernateTemplate();.executeFind(new HibernateCallback(); { public Object doInHibernate(Session session); throws HibernateException, SQLException { Query query = session.createQuery(LOGIN_QUERY);; query.setString("userName",userName);; query.setString("passWord",passWord);; return query.list();; } });; if(list.size();==0);{ return new Object[]{wrong_password,null}; }else{ User user = (User);list.get(0);; if(false);{//如果用户被禁用 return new Object[]{deny_username,null}; }else{ return new Object[]{login_success,user}; } } } } |
|
返回顶楼 | |
发表时间:2005-04-05
/* * 创建日期 2005-3-21 * */ package com.bupticet.example.struts; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm; import org.apache.struts.actions.DispatchAction; import org.apache.struts.util.ModuleException; import com.bupticet.example.Constants; import com.bupticet.example.dao.UserDao; import com.bupticet.example.entity.User; import com.bupticet.example.exception.ExampleException; import com.bupticet.example.transform.UserTransform; import com.bupticet.util.MD5; /** * <p>Title: LoginAction</p> * * <p>Description: 登陆AcitionServlet</p> * * <p>Copyright: Copyright (c);北京邮电大学网络教育技术研究所[www.buticet.com] 2005</p> * * <p>Company: 北京邮电大学网络教育技术研究所[www.buticet.com] </p> * * @author LJ-silver * @version 1.0 */ public class LoginTAction extends DispatchAction { private final static String LOGIN_SUCCESS = "login-success"; private final static String LOGIN_FAILURE = "login-failure"; static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(LoginTAction.class);; private UserDao userDao; public ActionForward login(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response); throws Exception { DynaActionForm form = (DynaActionForm);actionForm; ActionMessages errors = new ActionMessages();; if (!isTokenValid(request,true);); { errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("errors.token"););; saveErrors(request, errors);; saveToken(request);; return mapping.findForward(LOGIN_FAILURE);; } resetToken(request);; String userName = (String);form.get("userName");; String passWord = (String);form.get("passWord");; try{ Object[] object = userDao.login(userName,MD5.toMD5(passWord););; switch (((Integer);object[0]);.intValue(););{ case 1: errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("error.login.havenotthisaccount"););; break; case 2: errors.add(ActionMessages.GLOBAL_MESSAGE ,new ActionMessage("error.login.wrongpassword"););; break; case 3: errors.add(ActionMessages.GLOBAL_MESSAGE ,new ActionMessage("error.login.denyusername"););; break; case 0: User user = (User);object[1]; HttpSession session = request.getSession(true);; session.setAttribute(Constants.USER_ATTRIBUTE,UserTransform.pOToVO(user););; break; default: errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("error.login.returnunknowncode"););; break; } }catch(ExampleException e);{ logger.error("In method login, Exception Occured ! Info :数据库member表中存在着多个"+userName+"帐户");; throw new ModuleException("error.databaseerror");; } if(!errors.isEmpty(););{ saveErrors(request, errors);; saveToken(request);; return mapping.findForward(LOGIN_FAILURE);; }else{ return mapping.findForward(LOGIN_SUCCESS);; } } /** * @return */ public UserDao getUserDao(); { return userDao; } /** * @param dao */ public void setUserDao(UserDao dao); { userDao = dao; } } |
|
返回顶楼 | |
发表时间:2005-04-05
这是前几天为作技术交流写的一个小例子。
各位大牛说的很有道理,我觉得checked exception和unchecked exception结合着用就可以了。 |
|
返回顶楼 | |
发表时间:2005-04-15
一、我对客户非常友好(指有非常详细的错误提示给他),这时的代码:
WebLayer { try { User user = login(name, passwd); } catch(LoginException e) { } } BusinessLayer { User login(name, passwd) throws LoginException { throw LoginException("用户不存在"); throw LoginException("密码错误"); ... } } 我们自己创建异常的原则是: 1、最好不要创建新异常,使用已有的异常,没办法就2 2、创建最少最通用的异常。这个可以避免aders 说的接口签名问题。 假如: User login(name, passwd) throws UserExistsException,PasswdInvalidException { } 要是以后要添加检查name 是否规范的逻辑,这是怎么办呢??抛出一个NameInvalidException 异常??可是我的这个login 已经在n 多个地方被使用了?? 二、我对客户比较友好(有出错提示,但不详细): 这时的代码可以用第一种情况的代码实现。也可以是下面的代码: boolean login(name, passwd) { } if (login(name, passwd)) .... else throw new XxxException("登录失败"); 从上面两种实现看来应该是第一段代码实现的较好,能应付以后出现的许多情况。第二段就不行了。 非常反对用异常控制程序流程的想法。也许有人认为第一种情况中代码也属于异常控制流程。那我想我脑中想的程序流程和你的不一样。 |
|
返回顶楼 | |
发表时间:2005-04-17
无数人说异常不应该控制程序流程。
谁仔细想过为什么吗?只怕都是人云亦云罢了。 知道,异常效率低嘛。可是程序流程不见得就是都要高效率的呀。 要真是效率决定一切,java程序员都去要饭得了,连c++扇子们都知道什么2/8原则,你们这里拿效率这么个鸡毛还当令箭耍什么劲? 没人什么地方都用异常。但是有些场合用异常就是方便,错误种类可扩展,错误信息详细,错误处理结构化,可以集中处理错误,不复杂化函数接口等等等等,这些都是用异常表达部分程序逻辑的好处。 你说不应该控制程序流程,好办。给个替代品啊。 UserInfo login(String username, String pwd); throws AuthencationException; 我这里如果login失败,用异常清晰简单。您给个其它的好用的解决方案先? 也不知道哪个弱人脑子都不过就给出这么个教条来。scheme还有continuation呢,那可是超级异常,不是一样用来处理程序流程? 具体情况具体分析,哪个方案最好用就用哪个,哪来那么多教条? |
|
返回顶楼 | |
发表时间:2005-04-17
关键词:不正常、正常
又把前面的帖子看了一遍,感觉是大家对程序控制流程有着不同的看法。在《Effective Java》(中文版)上说“异常只应该被用于不正常的条件,它们永远不应该被永远正常的控制流”。 我原先以为那个不是一个程序控制流程,所以我用 try { User login(...); } catch (e) {} 来替代 if (login(...)) {} 是正确的。 但实际上那是一个控制流程,只不过用boolean 来实现时变成了不正常的控制流程--不能返回更详细的出错信息。异常不应该被用来控制正常的控制流,但可以用来替换不正常的控制流。 |
|
返回顶楼 | |
发表时间:2005-05-13
既然有争议说明双方的方案都有问题,也各有道理,各不服气。
窃以为checked exception和unchecked exception的区别在于显式的和隐式,分散和集中的处理exception。单纯从语言的角度看Anders Hejlsberg的观点不是瞎扯的,毕竟人家是语言大家,不能因为人家端微软的饭就鄙视人家。ah确实是点到了java的软肋上,何必否认呢。说人家不熟悉企业开发,真是扯淡,人家是站在什么层次上看问题,难道比企业级的鹅站的低吗? 谁是谁非,没有完美的解决方案的问题就没必要争论不息了,毕竟偶们不能左右语言的发展,讨论怎么用好这些机制可能更有意义。 |
|
返回顶楼 | |
发表时间:2005-05-13
neooen 写道 毕竟偶们不能左右语言的发展,讨论怎么用好这些机制可能更有意义。
今天中午去食堂吃饭时也想到了这个问题。我们应该讨论怎么用好java的checked exception。 |
|
返回顶楼 | |
发表时间:2005-05-29
我认为 在合适的地方使用异常会更加体现出OO的思想 以及合理的架构
|
|
返回顶楼 | |
发表时间:2005-05-30
对于这个问题,我很难完全同意robbin的看法(如果我没有误解他的意思的话)。
首先明确几个问题: 1.exception机制是语言级的工具,用于递异常并进行处理(将遇到的异常情况交给知道如何去处理它的人来处理)。使用它有两个问题要注意:a.不是业务级别的分支处理工具;b.不应当处理相对常见的异常情况──这些在《effective java》已经讲得很清楚了。 2.如果我没有理解错的话,大家说的快乐日场景指的是“happy scenario”,这是use case的一条主线,它描述了所谓的基本路径(main path),同时,由于系统的复杂性,还存在可选路径,这些可选路径通常表现为用户所需的附加功能和──业务级的异常处理。 下面讨论user login这个例子,如果仅仅是true/false,那么也没有必要过度设计,但是如果存在不能登录(例如用户名、密码不匹配)/用户权受限(例如用户被锁定)/系统故障(例如数据库出错)这样一些需要考虑的问题的话,那么就不能用返回整数值的方式,这是很明显的bad smell。 但是我也不同意都使用exception机制,这样做与使用返回值相比,仅仅是多了一些信息,在程序结构上仍然是分支处理,就象老庄说的,不过是if变成了try,而且这样还有严重的性能问题(即便不考虑有人恶意DOS,在一般情况下,登录信息输入的错误也是很常见的现象)。 我的作法是──使用多态:对于login代码段,返回值是一个User对象,如果登录失败,则返回一个缓存的anonymous 的User对象,如果用户被锁定,就返回一个被锁定的User对象,调用方只要使用这个User对象的getMainPage()即可(这是一个简化的作法,具体还要进一步修改)。 至于系统故障,这是属于极为罕见的情况,况且这种情况的出现一般就意味着什么也做不了了,那么针对它抛出一个异常也是很正常的(就像我带了一把锤子一样正常Smile),这个异常可以一直抛到最外层去截获,然后给出一个统一的错误页面即可,所以应该使用runtime异常(客户不希望看到任何异常显示出来,因此即便是runtime也要在用户界面上保护起来)。 |
|
返回顶楼 | |