接口拦截 日志打印 自定义异常输出
This commit is contained in:
@@ -65,7 +65,8 @@ public class GlobalExceptionHandler {
|
|||||||
@ExceptionHandler(value = BadRequestException.class)
|
@ExceptionHandler(value = BadRequestException.class)
|
||||||
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
// log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
log.error(e.getMessage());
|
||||||
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package cn.ysk.cashier.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializeConfig;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json工具类,所有JSON转换通用该JSON工具类,不许直接使用外部JSON转换,后期会封闭掉直接调用JSON转换。
|
||||||
|
*/
|
||||||
|
public final class FastJsonUtils {
|
||||||
|
|
||||||
|
private static final List<SerializerFeature> listFeatures = new ArrayList<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 输出空置字段
|
||||||
|
listFeatures.add(SerializerFeature.WriteMapNullValue);
|
||||||
|
// list字段如果为null,输出为[],而不是null
|
||||||
|
listFeatures.add(SerializerFeature.WriteNullListAsEmpty);
|
||||||
|
// 数值字段如果为null,输出为0,而不是null
|
||||||
|
// SerializerFeature.WriteNullNumberAsZero,
|
||||||
|
// Boolean字段如果为null,输出为false,而不是null
|
||||||
|
listFeatures.add(SerializerFeature.WriteNullBooleanAsFalse);
|
||||||
|
// 字符类型字段如果为null,输出为"",而不是null
|
||||||
|
listFeatures.add(SerializerFeature.WriteNullStringAsEmpty);
|
||||||
|
// 循环引用
|
||||||
|
listFeatures.add(SerializerFeature.DisableCircularReferenceDetect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换对象为JSON字符串
|
||||||
|
*
|
||||||
|
* @param object 转换对象
|
||||||
|
* @return 转换结果
|
||||||
|
*/
|
||||||
|
public static String toJSONString(Object object) {
|
||||||
|
//不可序列化的类型直接打印其类名称
|
||||||
|
if (object instanceof HttpServletRequest
|
||||||
|
|| object instanceof HttpServletResponse
|
||||||
|
|| object instanceof MultipartFile
|
||||||
|
|| object instanceof MultipartFile[]) {
|
||||||
|
return "[" + object.getClass().getSimpleName() + "]";
|
||||||
|
} else {
|
||||||
|
return toJSONString(object, null, "yyyy-MM-dd HH:mm:ss");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON 转换出口
|
||||||
|
*
|
||||||
|
* @param o 转换对象
|
||||||
|
* @param serializeConfig 转换配置
|
||||||
|
* @param DateFormat 时间格式化
|
||||||
|
* @return 转换结果
|
||||||
|
*/
|
||||||
|
private static String toJSONString(Object o, SerializeConfig serializeConfig, String DateFormat) {
|
||||||
|
SerializeConfig config;
|
||||||
|
SerializerFeature[] features;
|
||||||
|
if (serializeConfig != null) {
|
||||||
|
config = serializeConfig;
|
||||||
|
} else {
|
||||||
|
config = new SerializeConfig();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(DateFormat)) {
|
||||||
|
// 设置自定义时间
|
||||||
|
JSON.DEFFAULT_DATE_FORMAT = DateFormat;
|
||||||
|
features = new SerializerFeature[listFeatures.size() + 1];
|
||||||
|
features = listFeatures.toArray(features);
|
||||||
|
features[features.length - 1] = SerializerFeature.WriteDateUseDateFormat;
|
||||||
|
} else {
|
||||||
|
features = new SerializerFeature[listFeatures.size()];
|
||||||
|
features = listFeatures.toArray(features);
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(o, config, features);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package cn.ysk.cashier.config;
|
package cn.ysk.cashier.config;
|
||||||
|
|
||||||
|
import cn.ysk.cashier.utils.FastJsonUtils;
|
||||||
import cn.ysk.cashier.utils.SpringContextHolder;
|
import cn.ysk.cashier.utils.SpringContextHolder;
|
||||||
import cn.ysk.cashier.utils.StringUtils;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.Signature;
|
import org.aspectj.lang.Signature;
|
||||||
@@ -16,8 +15,8 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.util.HashMap;
|
||||||
import java.lang.reflect.Method;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 方法调用统一切面处理
|
* 方法调用统一切面处理
|
||||||
@@ -40,93 +39,35 @@ public class AppApiMethodAspect {
|
|||||||
|
|
||||||
@Around("pkg()")
|
@Around("pkg()")
|
||||||
// @SuppressWarnings("unchecked")
|
// @SuppressWarnings("unchecked")
|
||||||
public Object around(ProceedingJoinPoint pjp) throws Throwable {
|
public Object around(ProceedingJoinPoint pjp) throws JsonProcessingException {
|
||||||
Object[] args = pjp.getArgs();
|
|
||||||
HttpServletRequest req = SpringContextHolder.getRequest();
|
HttpServletRequest req = SpringContextHolder.getRequest();
|
||||||
Signature sign = pjp.getSignature();
|
Signature sign = pjp.getSignature();
|
||||||
MethodSignature ms = (MethodSignature) sign;
|
MethodSignature ms = (MethodSignature) sign;
|
||||||
Object result;
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
Map<String, Object> params = new HashMap<>();
|
||||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 设置忽略空值
|
Object result = null;
|
||||||
try {
|
try {
|
||||||
|
// 获取方法参数
|
||||||
|
Object[] args = pjp.getArgs();
|
||||||
|
String[] paramNames = ms.getParameterNames();
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
params.put(paramNames[i], FastJsonUtils.toJSONString(args[i]));
|
||||||
|
}
|
||||||
// 执行被拦截的方法
|
// 执行被拦截的方法
|
||||||
result = pjp.proceed();
|
result = pjp.proceed();
|
||||||
ResponseEntity<?> responseEntity = (ResponseEntity<?>) result;
|
|
||||||
Object responseBody = responseEntity.getBody();
|
|
||||||
log.info("\n>>>>>>{} {}\n>>>>>>{}\n>>>>>>Request: {}\n>>>>>>Response: {}"
|
log.info("\n>>>>>>{} {}\n>>>>>>{}\n>>>>>>Request: {}\n>>>>>>Response: {}"
|
||||||
, req.getMethod(), req.getRequestURL(), req.getRemoteAddr(),
|
, req.getMethod(), req.getRequestURL(), req.getRemoteAddr(),
|
||||||
mapper.writeValueAsString(args),
|
FastJsonUtils.toJSONString(params),
|
||||||
mapper.writeValueAsString(responseBody)
|
FastJsonUtils.toJSONString(result)
|
||||||
);
|
);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
result = getReturnObject(ms.getReturnType(), HttpStatus.INTERNAL_SERVER_ERROR);
|
log.error("\n>>>>>>{} {}\n>>>>>>{}\n>>>>>>Request: {}\n>>>>>>Exception: {}"
|
||||||
log.warn("{}", e);
|
, req.getMethod(), req.getRequestURL(), req.getRemoteAddr(),
|
||||||
log.error("\n>>>>>>{} {}\n>>>>>> {}\n>>>>>>Request: {}\n>>>>>>Exception: {}"
|
FastJsonUtils.toJSONString(params),
|
||||||
, req.getMethod(),
|
e.getMessage());
|
||||||
req.getRequestURL(),
|
ResponseEntity<String> body = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
|
||||||
req.getRemoteAddr(),
|
return body;
|
||||||
mapper.writeValueAsString(args),
|
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 反射封装方法的返回值
|
|
||||||
*
|
|
||||||
* @param clz 方法返回值的字节码对象
|
|
||||||
* @param _enum 错误信息
|
|
||||||
* @param <T> 返回值类型
|
|
||||||
* @return 返回原方法的返回对象
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("SameParameterValue") // 忽略枚举只传入了一个值的异常
|
|
||||||
private <T> T getReturnObject(Class<T> clz, HttpStatus _enum) {
|
|
||||||
if (clz.getName().equals("void")) { //没有返回值时
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
T t = null;
|
|
||||||
try {
|
|
||||||
t = clz.newInstance();
|
|
||||||
} catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
log.warn("{}", e);
|
|
||||||
}
|
|
||||||
//设置错误码
|
|
||||||
setFiledValue("code", _enum.value(), t);
|
|
||||||
//设置错误信息
|
|
||||||
setFiledValue("message", _enum.getReasonPhrase(), t);
|
|
||||||
return t;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调用setXX方法设置属性
|
|
||||||
*
|
|
||||||
* @param fileName 方法名
|
|
||||||
* @param value 方法值
|
|
||||||
* @param obj 返回对象
|
|
||||||
*/
|
|
||||||
private void setFiledValue(String fileName, Object value, Object obj) {
|
|
||||||
//该方式找不到对应字段不会报错
|
|
||||||
if (StringUtils.isBlank(fileName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//转成SetXXX方法名
|
|
||||||
char[] chars = fileName.toCharArray();
|
|
||||||
chars[0] = (char) (chars[0] - 32); //首字母转大写
|
|
||||||
//拼接成方法名
|
|
||||||
String methodName = "set" + String.copyValueOf(chars);
|
|
||||||
Class<?> clz = obj.getClass();
|
|
||||||
Method[] declaredMethods = clz.getMethods();
|
|
||||||
for (Method method : declaredMethods) {
|
|
||||||
boolean equals = method.getName().equals(methodName);
|
|
||||||
if (equals) {
|
|
||||||
try {
|
|
||||||
method.invoke(obj, value);
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
||||||
log.warn("{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class DictController {
|
|||||||
@Log("新增字典")
|
@Log("新增字典")
|
||||||
@ApiOperation("新增字典")
|
@ApiOperation("新增字典")
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@PreAuthorize("@el.check('dict:add')")
|
// @PreAuthorize("@el.check('dict:add')")
|
||||||
public ResponseEntity<Object> createDict(@Validated @RequestBody Dict resources){
|
public ResponseEntity<Object> createDict(@Validated @RequestBody Dict resources){
|
||||||
if (resources.getId() != null) {
|
if (resources.getId() != null) {
|
||||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||||
|
|||||||
Reference in New Issue
Block a user