package com.gsww.chis.aop;

import java.util.Arrays;

import com.google.common.base.Throwables;
import com.gsww.chis.pojo.pacs.PacswsLog;
import com.gsww.chis.service.pacs.PacswsLogService;
import com.gsww.chis.util.TimeHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; /**
* 系统日志
* @author fenglanglang
*
*/
@Aspect
@Component
public class WebServiceLogAspect {
private static final Logger logger = LoggerFactory.getLogger(WebServiceLogAspect.class); @Autowired
private PacswsLogService pacswsLogService; @Pointcut("execution(public * com.gsww.chis.webservice.*.*(..)) && @annotation(com.gsww.chis.annotation.WebServiceLog)")
public void Pointcut() {
} @Around("Pointcut()")
public Object around(ProceedingJoinPoint point) {
PacswsLog log = new PacswsLog();
log.setRst("T");
log.setTime(TimeHelper.getCurrentTime()); MethodSignature signature = (MethodSignature) point.getSignature();
// 请求的方法名
String methodName = signature.getName();
log.setHisMethod(methodName);
// 请求的参数
Object[] args = point.getArgs();
log.setParamsIn(Arrays.toString(args)); // 执行方法
Object result =null;
long beginTime = System.currentTimeMillis();
try {
result = point.proceed();
log.setTimeConsuming(System.currentTimeMillis() - beginTime);
log.setParamsOut(result.toString());
} catch (Throwable e) {
if("RisCheckInfo".equals(methodName)){
result = "<Response><list></list><ResultCode>-1</ResultCode><ResultContent>"+e.getMessage()+"</ResultContent></Response>";
}else{
result = "<Response><ResultCode>-1</ResultCode><ResultContent>"+e.getMessage()+"</ResultContent></Response>";
}
log.setRst("F");
log.setParamsOut(result.toString());
log.setTimeConsuming(0L);
logger.error("请求异常:请求方法:{}, 异常信息:{}",methodName,Throwables.getStackTraceAsString(e));
}
saveWebServiceLog(log);
return result;
} /**
* 保存接口日志
* @param pacswsLog
*/
private void saveWebServiceLog(PacswsLog pacswsLog){
try{
pacswsLogService.save(pacswsLog);
}catch(Exception e){
logger.error("请求异常:请求方法:{}, 异常信息:{}","saveWebServiceLog",Throwables.getStackTraceAsString(e));
}
}
}
package com.gsww.bhis.common.aop;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import com.google.common.base.Throwables; /**
* @author fenglanglang
* @see
*
*/
@Aspect //声明是个切面
@Component
public class LogAspect {
private static final Logger logger = LogManager.getLogger("LogConfig"); //切点
@Pointcut("execution(public * com.gsww.bhis..controller.*.*(..))")
public void Pointcut(){} /**
*
* doAround:(环绕方法,统一日志处理). <br/>
*
* @author fenglanglang
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("Pointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long beginTime = System.currentTimeMillis();//1、开始时间
ServletRequestAttributes requestAttr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
String uri = requestAttr.getRequest().getRequestURI();
logger.info("开始计时: {} URI: {}", new Date(),uri); //访问目标方法的参数 可动态改变参数值
Object[] args = joinPoint.getArgs();
//方法名获取
String methodName = joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName();
logger.info("请求方法:{}, 请求参数: {}", methodName, Arrays.toString(args));
//可能在反向代理请求进来时,获取的IP存在不正确行 这里直接摘抄一段来自网上获取ip的代码
logger.info("请求ip:{}", getIpAddr(requestAttr.getRequest())); //调用实际方法
Object object = joinPoint.proceed();
logger.info("请求返回值:{}",object); long endTime = System.currentTimeMillis();
logger.info("结束计时: {}, URI: {},耗时:{}", new Date(),uri,endTime - beginTime);
return object;
} /**
*
* afterThrowable:(统一异常处理). <br/>
*
* @author fenglanglang
* @param e
*/
@AfterThrowing(pointcut="Pointcut()",throwing="e")
public void afterThrowable(JoinPoint joinPoint,Throwable e) {
//方法名获取
String methodName = joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName();
logger.error("请求异常:请求方法:{}, 异常信息:{}",methodName,Throwables.getStackTraceAsString(e));
} /**
*
* getIpAddr:(获取ip). <br/>
*
* @author fenglanglang
* @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) {
logger.error("获取ip异常:{}" ,Throwables.getStackTraceAsString(e));
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
}
package com.gsww.bhis.common.aop;

import java.lang.annotation.Annotation;
import java.util.LinkedHashMap; import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.gsww.bhis.common.util.GlobalResponse; /**
*
* 类名: GlobalResponseHandler <br/>
* 功能: 正常请求统一响应数据格式 <br/>
* 创建时间: 2018年9月6日 上午10:33:32 <br/>
*
* @author fenglanglang
* @version
*/
@ControllerAdvice(annotations={RestController.class,Controller.class})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object>{ /**
*
* 拦截没有进行统一数据格式的方法
* @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#supports(org.springframework.core.MethodParameter, java.lang.Class)
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { //swagger2 api 数据不进行转换 ,否则api界面会出错
String ngp = returnType.getNestedGenericParameterType().toString();
if(ngp.indexOf("swagger")>=0){
return false;
}
Annotation[] ano = returnType.getMethodAnnotations();
for(Annotation a:ano){
if(a.annotationType().getName().indexOf("ApiIgnore")>=0){
return false;
}
} //已经是标准格式的数据不进行转换
String returnTypeName = returnType.getParameterType().getName();
return !"com.gsww.bhis.common.util.GlobalResponse".equals(returnTypeName);
} @SuppressWarnings("unchecked")
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if(body == null) {
return JSON.toJSONString(GlobalResponse.success(null));
}
//权限校验特殊处理
if(body instanceof LinkedHashMap){
LinkedHashMap<String, Object> hashMapBody = (LinkedHashMap<String, Object>)body;
Integer status = (Integer)hashMapBody.get("status");
Object message = hashMapBody.get("message");
if(status != null && message != null){
return GlobalResponse.fail(message.toString(),status);
}
}
//防止classCaseExceptiin https://my.oschina.net/u/1757225/blog/1543715
if(body instanceof String) {
return JSON.toJSONString(GlobalResponse.success(body));
}
//不是json类型类型的返回值
if(!selectedContentType.includes(MediaType.APPLICATION_JSON)){
return body;
}
return GlobalResponse.success(body);
} /**
*
* handlerThrowable:(异常时返回统一格式). <br/>
*
* @author fenglanglang
* @param e
* @return
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler({Throwable.class})
public <T> GlobalResponse<T> handlerThrowable(Throwable e){
return GlobalResponse.fail(Throwables.getStackTraceAsString(e), 500);
}
}
package com.gsww.bhis.common.util;

import java.io.Serializable;

/**
*
* @author fenglanglang
* 数据格式
* @param <T>
*/
public class GlobalResponse<T> implements Serializable{ private static final long serialVersionUID = 8696541815421373761L; private Boolean rst = false;
private T data;
private Integer errorCode;
private String errorMsg; public GlobalResponse() {
super();
} public GlobalResponse(T data,Boolean rst) {
super();
this.rst = rst;
this.data = data;
} public static <T> GlobalResponse<T> success(T data){
return new GlobalResponse<T>(data,true);
} public static <T> GlobalResponse<T> fail(String errorMsg,Integer errorCode){
GlobalResponse<T> gr = new GlobalResponse<T>();
gr.setErrorCode(errorCode);
gr.setErrorMsg(errorMsg);
gr.setRst(false);
return gr;
} public Boolean isRst() {
return rst;
} public void setRst(Boolean rst) {
this.rst = rst;
} public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public Integer getErrorCode() {
return errorCode;
} public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
} public String getErrorMsg() {
return errorMsg;
} public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
} @Override
public String toString() {
return "GlobalResponse [rst=" + rst + ", data=" + data + ", errorCode=" + errorCode + ", errorMsg=" + errorMsg
+ "]";
}
}

完全参考自

AOP Aspect 统一日志、异常处理、数据格式==》https://my.oschina.net/langgege/blog/3025492

AOP Aspect 统一日志、异常处理、数据格式 【转】的更多相关文章

  1. Spring MVC 中使用AOP 进行统一日志管理--XML配置实现

    1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的 ...

  2. Spring AOP实现统一日志输出

    目的: 统一日志输出格式 思路: 1.针对不同的调用场景定义不同的注解,目前想的是接口层和服务层. 2.我设想的接口层和服务层的区别在于: (1)接口层可以打印客户端IP,而服务层不需要 (2)接口层 ...

  3. Spring MVC 中使用AOP 进行统一日志管理--注解实现

    1.AOP简介 AOP称为面向切面编程 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的 ...

  4. SpringBoot | 第二十四章:日志管理之AOP统一日志

    前言 上一章节,介绍了目前开发中常见的log4j2及logback日志框架的整合知识.在很多时候,我们在开发一个系统时,不管出于何种考虑,比如是审计要求,或者防抵赖,还是保留操作痕迹的角度,一般都会有 ...

  5. SpringBoot系列(十三)统一日志处理,logback+slf4j AOP+自定义注解,走起!

    往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件详解 SpringBoot系列(四)we ...

  6. 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  7. Spring Boot 2.0 教程 | AOP 切面统一打印请求日志

    欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...

  8. Spring Boot 自定义注解,AOP 切面统一打印出入参请求日志

    其实,小哈在之前就出过一篇关于如何使用 AOP 切面统一打印请求日志的文章,那为什么还要再出一篇呢?没东西写了? 哈哈,当然不是!原因是当时的实现方案还是存在缺陷的,原因如下: 不够灵活,由于是以所有 ...

  9. Java 项目创建 -- 统一结果处理、统一异常处理、统一日志处理

    一.IDEA 插件使用 1.说明 此处使用 SpringBoot 2.2.6 .JDK 1.8 .mysql 8.0.18 作为演示. 使用 IDEA 作为开发工具. 2.IDEA 插件 -- Lom ...

随机推荐

  1. HBase 面向列的存储

  2. 如何解决mysql服务器load高

    .登录主机 # ssh hostname .确定是否是mysql导致 # top .查看是哪些sql正在慢查询 # mysql -h hostname -P port -u username # sh ...

  3. 使用由 Python 编写的 lxml 实现高性能 XML 解析

    lxml 简介 Python 从来不出现 XML 库短缺的情况.从 2.0 版本开始,它就附带了 xml.dom.minidom 和相关的 pulldom 以及 Simple API for XML ...

  4. vue.js组件的个人总结

    vue.js的组件使用过程分为三个步骤:1.创建组件构造器: 2.注册组件: 3.使用组件 组件同时也分为全局组件与局部组件 1.全局组件 2.局部组件 注意:由于 HTML 标签不区分大小写,所以在 ...

  5. Linux下IP修改后重启服务器 oralce 出错(监听无法启动)

    针对linux下修改IP导致的Oracle不能启动问题的解决 主要修改/etc/hosts配置文件.修改前配置: # Do not remove the following line, or vari ...

  6. LRU Cache数据结构简介

    什么是LRU Cache LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法. 什么是Cache?狭义的Cache指的是位于CPU和主存间的快速RAM ...

  7. PAT甲级——A1059 Prime Factors

    Given any positive integer N, you are supposed to find all of its prime factors, and write them in t ...

  8. PAT甲级——A1010 Radix

    Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The an ...

  9. Activiti实战01_认识Activiti

    什么是Activiti Activiti是为解决工作流而创建的一套流程引擎.举个最简单的例子,请假流程就是一个工作流,从开始到审批到结束,像流一样的贯穿整个流程.在工作中最常见的就是OA了.工作流总是 ...

  10. HDFS数据读写过程