目录结构如下
BizCodeEnum
package net.xdclass.enums; import lombok.Getter; /** * 小滴课堂,愿景:让技术不再难学 * * @Description 状态码定义约束,共6位数,前三位代表服务,后3位代表接口 * 比如 商品服务210,购物车是220、用户服务230,403代表权限 * **/ public enum BizCodeEnum { /** * 短链分组 */ GROUP_REPEAT(23001,"分组名重复"), GROUP_OPER_FAIL(23503,"分组名操作失败"), GROUP_NOT_EXIST(23404,"分组不存在"), /** *验证码 */ CODE_TO_ERROR(240001,"接收号码不合规"), CODE_LIMITED(240002,"验证码发送过快"), CODE_ERROR(240003,"验证码错误"), CODE_CAPTCHA_ERROR(240101,"图形验证码错误"), /** * 账号 */ ACCOUNT_REPEAT(250001,"账号已经存在"), ACCOUNT_UNREGISTER(250002,"账号不存在"), ACCOUNT_PWD_ERROR(250003,"账号或者密码错误"), ACCOUNT_UNLOGIN(250004,"账号未登录"), /** * 短链 */ SHORT_LINK_NOT_EXIST(260404,"短链不存在"), /** * 订单 */ ORDER_CONFIRM_PRICE_FAIL(280002,"创建订单-验价失败"), ORDER_CONFIRM_REPEAT(280008,"订单恶意-重复提交"), ORDER_CONFIRM_TOKEN_EQUAL_FAIL(280009,"订单令牌缺少"), ORDER_CONFIRM_NOT_EXIST(280010,"订单不存在"), /** * 支付 */ PAY_ORDER_FAIL(300001,"创建支付订单失败"), PAY_ORDER_CALLBACK_SIGN_FAIL(300002,"支付订单回调验证签失败"), PAY_ORDER_CALLBACK_NOT_SUCCESS(300003,"支付宝回调更新订单失败"), PAY_ORDER_NOT_EXIST(300005,"订单不存在"), PAY_ORDER_STATE_ERROR(300006,"订单状态不正常"), PAY_ORDER_PAY_TIMEOUT(300007,"订单支付超时"), /** * 流控操作 */ CONTROL_FLOW(500101,"限流控制"), CONTROL_DEGRADE(500201,"降级控制"), CONTROL_AUTH(500301,"认证控制"), /** * 流量包操作 */ TRAFFIC_FREE_NOT_EXIST(600101,"免费流量包不存在,联系客服"), TRAFFIC_REDUCE_FAIL(600102,"流量不足,扣减失败"), TRAFFIC_EXCEPTION(600103,"流量包数据异常,用户无流量包"), /** * 通用操作码 */ OPS_REPEAT(110001,"重复操作"), OPS_NETWORK_ADDRESS_ERROR(110002,"网络地址错误"), /** * 文件相关 */ FILE_UPLOAD_USER_IMG_FAIL(700101,"用户头像文件上传失败"); @Getter private String message; @Getter private int code; private BizCodeEnum(int code, String message){ this.code = code; this.message = message; } }
package net.xdclass.exception;
import lombok.Data;
import net.xdclass.enums.BizCodeEnum;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
@Data
public class BizException extends RuntimeException {
private int code;
private String msg;
public BizException(Integer code, String message) {
super(message);
this.code = code;
this.msg = message;
}
public BizException(BizCodeEnum bizCodeEnum){
super(bizCodeEnum.getMessage());
this.code = bizCodeEnum.getCode();
this.msg = bizCodeEnum.getMessage();
}
}
package net.xdclass.exception;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.util.JsonData;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
@ControllerAdvice
//@RestControllerAdvice
@Slf4j
public class CustomExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonData handler(Exception e){
if(e instanceof BizException){
BizException bizException = (BizException) e;
log.error("[业务异常]{}",e);
return JsonData.buildCodeAndMsg(bizException.getCode(),bizException.getMsg());
}else {
log.error("[系统异常]{}",e);
return JsonData.buildError("系统异常");
}
}
}
package net.xdclass.util;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.*;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
@Slf4j
public class CommonUtil {
/**
* 获取ip
*
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
// "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
/**
* 获取全部请求头
*
* @param request
* @return
*/
public static Map getAllRequestHeader(HttpServletRequest request) {
Enumeration headerNames = request.getHeaderNames();
Map map = new HashMap<>();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
//根据名称获取请求头的值
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
/**
* MD5加密
*
* @param data
* @return
*/
public static String MD5(String data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
} catch (Exception exception) {
}
return null;
}
/**
* 获取验证码随机数
*
* @param length
* @return
*/
public static String getRandomCode(int length) {
String sources = "0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int j = 0; j < length; j++) {
sb.append(sources.charAt(random.nextInt(9)));
}
return sb.toString();
}
/**
* 获取当前时间戳
*
* @return
*/
public static long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* 生成uuid
*
* @return
*/
public static String generateUUID() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
/**
* 获取随机长度的串
*
* @param length
* @return
*/
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String getStringNumRandom(int length) {
//生成随机数字和字母,
Random random = new Random();
StringBuilder saltString = new StringBuilder(length);
for (int i = 1; i <= length; ++i) {
saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
}
return saltString.toString();
}
/**
* 响应json数据给前端
*
* @param response
* @param obj
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) {
response.setContentType("application/json; charset=utf-8");
try (PrintWriter writer = response.getWriter()) {
writer.print(JsonUtil.obj2Json(obj));
response.flushBuffer();
} catch (IOException e) {
log.warn("响应json数据给前端异常:{}", e);
}
}
}
package net.xdclass.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.xdclass.enums.BizCodeEnum;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonData {
/**
* 状态码 0 表示成功
*/
private Integer code;
/**
* 数据
*/
private Object data;
/**
* 描述
*/
private String msg;
/**
* 获取远程调用数据
* 注意事项:
* 支持多单词下划线专驼峰(序列化和反序列化)
*
* @param typeReference
* @param
* @return
*/
public T getData(TypeReference typeReference){
return JSON.parseObject(JSON.toJSONString(data),typeReference);
}
/**
* 成功,不传入数据
* @return
*/
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
/**
* 成功,传入数据
* @param data
* @return
*/
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
/**
* 失败,传入描述信息
* @param msg
* @return
*/
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
/**
* 自定义状态码和错误信息
* @param code
* @param msg
* @return
*/
public static JsonData buildCodeAndMsg(int code, String msg) {
return new JsonData(code, null, msg);
}
/**
* 传入枚举,返回信息
* @param codeEnum
* @return
*/
public static JsonData buildResult(BizCodeEnum codeEnum){
return JsonData.buildCodeAndMsg(codeEnum.getCode(),codeEnum.getMessage());
}
}
package net.xdclass.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import java.text.SimpleDateFormat;
import java.util.List;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
@Slf4j
public class JsonUtil {
private static final ObjectMapper mapper = new ObjectMapper();
static {
//设置可用单引号
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//序列化的时候序列对象的所有属性
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//如果是空对象的时候,不抛异常
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
/**
* 对象转为Json字符串
* @param data
* @return
*/
public static String obj2Json(Object obj) {
String jsonStr = null;
try {
jsonStr = mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
//e.printStackTrace();
log.error("json格式化异常:{}",e);
}
return jsonStr;
}
/**
* json字符串转为对象
* @param str
* @param valueType
* @return
*/
public static T json2Obj(String jsonStr, Class beanType) {
T obj = null;
try {
obj = mapper.readValue(jsonStr, beanType);
} catch (Exception e){
//e.printStackTrace();
log.error("json格式化异常:{}",e);
}
return obj;
}
/**
* json数据转换成pojo对象list
* @param jsonData
* @param beanType
* @return
*/
public static List json2List(String jsonData, Class beanType) {
JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);
try {
List list = mapper.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
//e.printStackTrace();
log.error("json格式化异常:{}",e);
}
return null;
}
/**
* 对象转为byte数组
* @param data
* @return
*/
public static byte[] obj2Bytes(Object obj) {
byte[] byteArr = null;
try {
byteArr = mapper.writeValueAsBytes(obj);
} catch (JsonProcessingException e) {
//e.printStackTrace();
log.error("json格式化异常:{}",e);
}
return byteArr;
}
/**
* byte数组转为对象
* @param byteArr
* @param valueType
* @return
*/
public static T bytes2Obj(byte[] byteArr, Class beanType) {
T obj = null;
try {
obj = mapper.readValue(byteArr, beanType);
} catch (Exception e) {
//e.printStackTrace();
log.error("json格式化异常:{}",e);
}
return obj;
}
}
package net.xdclass.util;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
public class TimeUtil {
/**
* 默认日期格式
*/
private static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 默认日期格式
*/
private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_PATTERN);
private static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();
/**
* LocalDateTime 转 字符串,指定日期格式
* @param time
* @param pattern
* @return
*/
public static String format(LocalDateTime localDateTime, String pattern){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
String timeStr = formatter.format(localDateTime.atZone(DEFAULT_ZONE_ID));
return timeStr;
}
/**
* Date 转 字符串, 指定日期格式
* @param time
* @param pattern
* @return
*/
public static String format(Date time, String pattern){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
String timeStr = formatter.format(time.toInstant().atZone(DEFAULT_ZONE_ID));
return timeStr;
}
/**
* Date 转 字符串,默认日期格式
* @param time
* @return
*/
public static String format(Date time){
String timeStr = DEFAULT_DATE_TIME_FORMATTER.format(time.toInstant().atZone(DEFAULT_ZONE_ID));
return timeStr;
}
/**
* timestamp 转 字符串,默认日期格式
*
* @param time
* @return
*/
public static String format(long timestamp) {
String timeStr = DEFAULT_DATE_TIME_FORMATTER.format(new Date(timestamp).toInstant().atZone(DEFAULT_ZONE_ID));
return timeStr;
}
/**
* 字符串 转 Date
*
* @param time
* @return
*/
public static Date strToDate(String time) {
LocalDateTime localDateTime = LocalDateTime.parse(time, DEFAULT_DATE_TIME_FORMATTER);
return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
}
/**
* 获取当天剩余的秒数,用于流量包过期配置
* @param currentDate
* @return
*/
public static Integer getRemainSecondsOneDay(Date currentDate) {
LocalDateTime midnight = LocalDateTime.ofInstant(currentDate.toInstant(),
ZoneId.systemDefault()).plusDays(1).withHour(0).withMinute(0)
.withSecond(0).withNano(0);
LocalDateTime currentDateTime = LocalDateTime.ofInstant(currentDate.toInstant(),
ZoneId.systemDefault());
long seconds = ChronoUnit.SECONDS.between(currentDateTime, midnight);
return (int) seconds;
}
}