• AOP Aspect 统一日志、异常处理、数据格式 【转】


    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

  • 相关阅读:
    序列操作
    上帝造题的七分钟2 / 花神游历各国
    火柴排队
    pair(对组)用法
    线段树
    链上分治
    Rem与Px的转换
    css中单位px和em,rem的区别
    css网页自适应-1
    css网页自适应-2
  • 原文地址:https://www.cnblogs.com/whatlonelytear/p/11275807.html
Copyright © 2020-2023  润新知