在我自己搭建的开发框架中有设计这么两种异常,如下:
1.业务逻揖异常
/**
* 业务逻揖异常
* @author lenovo
*
*
*/
public class ServiceException extends Exception {
public ServiceException(String msg) {
super(msg);
}
}
2.非业务逻揖异常(一般是数据异常或系统异常等)
/**
* 非业务逻揖异常
* @author lenovo
*
*/
public class FaultException extends RuntimeException {
public FaultException(String msg) {
super(msg);
}
}
举个例子,比如登录的的业务逻揖:
public class UserService {
.....
public User login(String username, String password) throws ServiceException {
User user = null;
//根据账号获取用户对象
List<User> users = userDao.queryByUsername(usernmae);
if (!users.isEmpty()) {
if (users.size() > 1) {
//根据用户名可查到1个以上的用户,这明显是有脏数据存在,属于不可预料预知的异常,此处应该抛出非业务逻揖异常
throw new FaultException("数据有问题,存在1个以上同用户名的用户!");
}
user = users.get(0);
if (!user.getPassword.equals(password)) {
//密码不正确,此处应该抛出业务逻揖异常
throw new ServiceException("密码错误");
}
} else {
//用户不存在,此处应该抛出业务逻揖异常
throw new ServiceException("用户名不存在");
}
return user;
}
}
这个例子中,象用户名不存在和密码错误属于可预知的异常,属于正常的将会,所以抛出业务逻揖异常,而根据用户名可查出一个以上的用户这种情况,正常情况下是不应该出现的,说明数据库中存在有脏数据,这种情况不应该是可预知的情况,程序员不应该去处理这种异常,所以此处应该抛出非业务逻揖异常。
当然也可以通过返回状态码的方式来处理业务逻揖的异常情况,比如:
/*
*因为一般登录后都需要返回用户对象,所以这边需要特意写一个类来封装用户类和状态码
*/
public class ResultWrapper {
private User user;
//1-表示正常,2表示用户名不存在,3表示数据异常,.....(当然这边也可以用枚举来处理)
private int resultCode;
//get set方法
.....
}
public class UserService {
.....
public ResultWrapper login(String username, String password) throws ServiceException {
ResultWrapper result = new ResultWrapper();
User user = null;
//根据账号获取用户对象
List<User> users = userDao.queryByUsername(usernmae);
if (!users.isEmpty()) {
if (users.size() > 1) {
//根据用户名可查到1个以上的用户,这明显是有脏数据存在,属于不可预料预知的异常
result.setResultCode(3);
}
user = users.get(0);
if (!user.getPassword.equals(password)) {
//密码不正确
result.setResultCode(4);
}
result.setResultCode(4=1);
result.setUser(user);
} else {
//用户不存在,此处应该抛出业务逻揖异常
result.setResultCode(2);
}
return result;
}
}
这也是一种处理方式,具体使用见仁见智了,因为使用异常确实代价比较大(性能上的代价,java语言中处理异常的性能代价),但我还是比较喜欢使用异常的方式来处理业务逻揖异常,主要是基于以下原因:
主线比较明确,使用异常来处理业务逻揖可以突出主线,比如登录的场景,正常情况下就是使用名密码登录成功,而如果使用状态码来区分的话从业务层面上来说这几种状态都是平级的,最后都是通过return一个结果回去。
代码比较简洁,使用异常来处理省了一个外层的包装ResultWrapper,这边只是一个例子,正常项目如果要用这种方式的话就会产生非常多的包装类的,而用异常只需要两个异常类即可
调用方处理简单,比如在Action中调用的话,程序员就不需要写一堆的if else了,只需要catch一下ServiceException即可(FaultException是继承RuntimeException的不需要特意的catch)