关于业务逻辑层
业务逻辑层,也称之为“业务层”(Service Layer),主要:设计业务流程,处理业务逻辑,以保证数据的完整性和安全性。
业务层应该由接口(原因后续再解释)和实现类这2种文件组成!
关于Service中的方法的定义:
- 返回值类型:仅以操作成功为前提来设计
- 方法名称:自定义
- 参数列表:通常是控制器调用时传入,典型的参数就是客户端提交的请求参数
- 异常:处理业务时可能的“失败”,通常,使用
RuntimeException
或其子孙类异常,所以,在声明业务方法时,并不需要显式的声明抛出异常
关于异常类型的属性定义
关于异常,如果使用现有的异常(例如NullPointerException
等),可能会产生歧义,所以,通常会自定义异常,继承自RuntimeException
。
如果在项目中只使用1种异常类型,不便于不区分同一个业务可能出现的多种“错误”,所以,应该在异常类型中添加某个属性,来区分多种“错误”!关于此属性,可以是int
、String
等各种你认为合适的类型,但是,这些类型的取值范围(值的可能性)非常大,为了限制取值,可以使用枚举类型,例如:
public enum ServiceCode {
ERR_INSERT(1), ERR_UPDATE, ERR_DELETE;
}
如果仅仅只是以上代码,当尝试输出某个枚举值,输出的结果就是以上名称,例如ERR_INSERT
,不便于获取此值时编写条件判断相关的代码,通常,使用数值进行判断会更加方便,所以,可以为以上每个枚举值指定相关的数值,同时,需要添加枚举的构造方法,例如:
public enum ServiceCode {
ERR_INSERT(1),
ERR_UPDATE(2),
ERR_DELETE(3);
ServiceCode(int value) {}
}
为了保证各个值能够被使用,还需要添加全局属性,用于保存通过构造方法传入的值,并提供相应获取值的方法,使得后续得到得这些数值:
public enum ServiceCode {
ERR_CONFLICT(1),
ERR_INSERT(2),
ERR_DELETE(3),
ERR_UPDATE(4);
private int value;
ServiceCode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "" + value;
}
}
另外,各枚举值对应的数值编号应该是有一定规律的,而不是盲目的顺序编号,所以,应该自行设计一套编码规则,或者,如果没有比较成熟的编码规则,可大致参考已有的某套规则,例如参考HTTP响应码:
package cn.tedu.csmall.product.ex;
/**
* 业务状态码的枚举
*/
public enum ServiceCode {
OK(20000),
ERR_NOT_FOUND(40400),
ERR_CONFLICT(40900),
ERR_INSERT(50000),
ERR_DELETE(50100),
ERR_UPDATE(50200);
private int value;
ServiceCode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "" + value;
}
}
提示:以上类型创建在项目的根包下的ex.ServiceCode
。
然后,在项目的根包下的ex
包下创建ServiceException
:
public class ServiceException extends RuntimeException {
private ServiceCode serviceCode;
public ServiceException(ServiceCode serviceCode, String message) {
super(message);
this.serviceCode = serviceCode;
}
public ServiceCode getServiceCode() {
return serviceCode;
}
}
User login(String username, String password) throws 用户名错误异常, 密码错误异常, 账号禁用异常;
try {
User user = service.login("root", "1234");
// 处理成功
} catch (用户名错误异常 e) {
// 处理用户名错误异常
} catch (密码错误异常 e) {
// 处理密码错误异常
} catch (账号禁用异常 e) {
// 处理账号禁用异常
}