问题引出

在项目中经常会用到状态码和状态信息,比如用1表示操作成功,用0表示操作失败,用-1表示网络异常等。直接在业务代码中使用数字对比状态码然后输出状态信息是个不好的习惯(如下所示),因为项目越来越大,如果状态规则要发生变化,比如让-1表示权限不足,或者让2表示操作成功,那么修改工作将很困难。

if(code==1){
System.out.println("操作成功");
}




一、普通方法:常量值接口

有种做法是将所有的状态码与状态信息等常量值固定到一个接口中,然后让需要用到状态码/信息的类继承这个接口,则可以直接使用。


常量值接口:

public interface MyConstant {

// 激活成功
int ACTIVATION_SUCCESS_CODE = 0; // 激活成功的状态码
String ACTIVATION_SUCCESS_INFO = "激活成功,您的账号已经可以正常使用了!"; // 激活成功的状态信息

// 重复激活
int ACTIVATION_REPEAT_CODE = 1; // 重复激活的状态码
String ACTIVATION_REPEAT_INFO = "无效操作,该账号已经激活过了!"; // 重复激活的状态信息

// 激活失败
int ACTIVATION_FAILURE_CODE = 2; // 激活失败的状态码
String ACTIVATION_FAILURE_INFO = "激活失败,您提供的激活码不正确!"; // 激活失败的状态信息

}

需要引用的类:

@Controller
public class LoginController implements CommunityConstant {
@RequestMapping(path = "/activation/{userId}/{code}", method = RequestMethod.GET)
public String activation(Model model, @PathVariable("userId") int userId, @PathVariable("code") String code) {
int result = userService.activation(userId, code);
if (result == ACTIVATION_SUCCESS_CODE) { // 状态码
model.addAttribute("msg", ACTIVATION_SUCCESS_INFO); // 状态信息
model.addAttribute("target", "/login");
} else if (result == ACTIVATION_REPEAT_CODE) { // 状态码
model.addAttribute("msg", ACTIVATION_REPEAT_INFO); // 状态信息
model.addAttribute("target", "/index");
} else {
model.addAttribute("msg", ACTIVATION_FAILURE_INFO); // 状态信息
model.addAttribute("target", "/index");
}
return "/site/operate-result";
}
}


但有个问题是Java不允许多继承,如果某个类既需要继承其他类,又需要这些常量值,就很难办了。




二、更好的方法:枚举

可以有两种用法,一个是上面叙述的那种借助引用替换数值状态码或字符串状态信息,另一个是将整体按异常对象打印。


1、基础用法(替换数值状态码或字符串状态信息)

新建一个package,取名enum。新建关于订单信息的枚举:

import lombok.Getter;

@Getter
public enum OrderStatusEnum implements CodeEnum{

NEW(0,"新订单"),
FINISHED(1,"已完结"),
CANCLE(2,"已取消"),
;

private Integer code;
private String info;

OrderStatusEnum(Integer code, String info) {
this.code = code;
this.info = info;
}
}

然后在需要引用的方法中可以这样写:

import cn.hsy.enums.OrderStatusEnum;

@Controller
@RequestMapping(value = "/order")
public class OrderController {
@RequestMapping(value = "/cancel", method = RequestMethod.POST)
@ResponseBody
public HashMap<String, String> cancelById(@RequestParam("id") String id) {
int count = orderService.cancelById(id, OrderStatusEnum.CANCLE.getCode());//状态码
if (count > 0) {
msg.put("ans", ResultEnum.SUCCESS.getMessage()); // 状态信息
} else {
msg.put("ans", ResultEnum.FAIL.getMessage()); // 状态信息
}
return msg;
}
}



2、进阶用法(自定义异常,抛出状态对象)

新建一个package,取名enum。新建关于返回值信息的枚举:

import lombok.Getter;

@Getter
public enum ResultEnum {

PRODUCT_NOT_EXIST(0,"该商品不存在"),
;

private Integer code;
private String info;

ResultEnum(Integer code, String info) {
this.code = code;
this.info = info;
}
}

新建一个package,取名exception。新建自定义异常类:

import cn.hsy.enums.ResultEnum;

public class MyException extends RuntimeException{
private Integer code;

public MyException(ResultEnum resultEnum){
super(resultEnum.getInfo());

this.code = resultEnum.getCode();
}
}

然后在需要引用的位置可以这样写:

import cn.hsy.enums.ResultEnum;
import cn.hsy.exception.MyException;


if(~条件错误~){
throw new MyException(ResultEnum.PRODUCT_NOT_EXIST);
}





https://coding.imooc.com/class/117.html
【5-2节 买家商品-service~1】 00:03:58~00:06:25 (基础用法)
【6-4节 买家订单-service创建_B】 00:00:00~00:05:00 (进阶用法)