分享spring boot controller统一日志代码

最近项目需要做一个controller层的aop,主要解决下面问题:

1.controller日志统一打印输出json格式,兼容json和velocity 。

2.项目异常处理

3.异常邮件发送

4.页面访问统计

主要思路使用aop实现,controller参数统一使用@RequestParam接收。

controller

    @RequestMapping(name = "添加个人信息", value ="/addInfo", method = RequestMethod.POST)
    public String addInfo(@RequestParam("idFront") MultipartFile idFront,
                           @RequestParam("idReverse") MultipartFile idReverse,
                           @RequestParam("idNo")  String idNo,
                           @RequestParam("realName") String  realName,
                           @RequestParam("token") String token,
                           HttpServletRequest request)
            throws Exception {

aop

@Aspect
@Component
public class CotrollerLogAop {

    private final static Logger logger = LoggerFactory.getLogger(CotrollerLogAop.class);
   //请求信息缓存
    private final static Map<String, Object[]> MethodInfo=new ConcurrentHashMap<String, Object []>();
    //项目名
    @Value("${base.project.name}")
    private String projectName;
    //spring boot 错误页面uri
    @Value("${server.error.path:/error}")
    private String errorPath;
    //邮件发送
    @Autowired
    private EmailClient emailClient;
    //页面统计
    @Autowired
    private PageStatService pageStatService;
    //切面
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void requestMapping() {
    }
    //增强
    @Around("requestMapping()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        long startTime=System.currentTimeMillis();
        long endTime=0;
        Object[] objects = pjp.getArgs();
        String userName = "";
        String reqArray = "";
        String respView = null;
        String respData = null;
        String operation = null;
        Object object = null;
        String ip = null;
        Boolean returnJson=false;
        String[] paramNames=null;
        String referer=null;
        String userAgent=null;
        boolean errorReq=false;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            operation=request.getRequestURI();
            referer=request.getHeader("Referer");
            if(referer==null) referer="";
            userAgent=request.getHeader("User-Agent");
            if(userAgent==null) userAgent="";
            Method method = ((MethodSignature) pjp.getSignature()).getMethod();
            if (operation.equals(errorPath)) {
                errorReq=true;
                returnJson=method.getAnnotation(ResponseBody.class)!=null;
            }else{
                Object [] info=getMethodInfo(operation, method);
                returnJson=(Boolean) info[0];
                paramNames=(String [])info[1];
            }
            //请求相关参数
            ip = RequestParamUtil.getClientIpAddr(request);
            SessionUser securityUser = (SessionUser) request.getSession().getAttribute(Constants.SESSIONKEY);
            if (securityUser != null) {
                userName = securityUser.getShowName();
            }
            reqArray = ArrayToJsonString(objects, paramNames);
            //执行该方法
            object = pjp.proceed();
            //响应相关参数
            if (returnJson) {
                if(object instanceof String){
                    respData=(String)object;
                }else{
                    respData = JSON.toJSONString(object);
                }
            } else {
                if (object instanceof ModelAndView) {
                    respView = ((ModelAndView) object).getViewName();
                } else {
                    respView = (String) object;
                }
                respData = RequestParamUtil.getResponseStr(request);
            }
            //spring boot 系统错误
            if(errorReq){
                pageStatService.addStat("/error");
                HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
                if(returnJson){
                    Map<String, Object> map = new HashMap<String, Object>();
                    ResponseEntity entity = null;
                    if (response.getStatus() == 404) {
                        map.put("code", MsgCode.ERROR);
                        map.put("msg", "资源不存在!");
                        entity = new ResponseEntity<Map<String, Object>>(map, HttpStatus.OK);
                    } else {
                        map.put("code", MsgCode.ERROR);
                        map.put("msg", "系统异常!");
                        entity = new ResponseEntity<Map<String, Object>>(map, HttpStatus.OK);
                    }
                    emailClient.sendSysErrorEmail(operation, response.getStatus() + "-->"+respData);
                    logger.info("<|>error_redirect<|>{}<|>{}<|>{}<|>{}<|>异常信息<|>{}<|>改写<|>{}<|>", projectName, userName, ip, operation, respData, JSON.toJSONString(map));
                    return entity;
                }else{
                    ModelAndView view = null;
                    if (response.getStatus() == 404) {
                        view = new ModelAndView("error/404");
                    } else {
                        view = new ModelAndView("error/500");
                    }
                    String msg=JSON.toJSONString(((ModelAndView) object).getModel());
                    emailClient.sendSysErrorEmail(operation, response.getStatus() + "-->"+msg);
                    logger.info("<|>error_redirect<|>{}<|>{}<|>{}<|>{}<|>异常信息<|>{}<|>改写<|>{}<|>", projectName, userName, ip, operation, msg, view.getViewName());
                    return view;
                }
            }
            endTime=System.currentTimeMillis();
            logger.info("<|>common<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>", projectName, userName, ip, operation, referer, reqArray, userAgent, respView, respData, endTime-startTime);
            pageStatService.addStat(operation);
            return object;
        } catch (Exception e) {
            endTime=System.currentTimeMillis();
            if (returnJson) {
                BaseResp baseResp = new BaseResp();
                if (e instanceof OpenException) {
                    OpenException openException = (OpenException) e;
                    baseResp.setFailedMsg(openException.getMessage());
                    logger.info("<|>common<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>", projectName, userName, ip, operation, referer, reqArray, userAgent, "", JSON.toJSONString(baseResp), endTime-startTime);
                } else {
                    e.printStackTrace();
                    logger.info("<|>error<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>", projectName, userName, ip, operation,referer, reqArray,userAgent, e.getMessage(), startTime-endTime);
                    baseResp.setFailedMsg("系统异常!");
                    emailClient.sendSysErrorEmail(operation, e.getMessage());
                }
                return baseResp;
            } else {
                e.printStackTrace();
                emailClient.sendSysErrorEmail(operation, e.getMessage());
                logger.info("<|>error<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>{}<|>", projectName, userName, ip, operation, referer, reqArray, userAgent, e.getMessage(), startTime-endTime);
                return "error/500";
            }
        }
    }
    //拼接请求json
    private String ArrayToJsonString(Object[] objects, String [] paramNames) throws Exception {
        StringBuilder reqArray = new StringBuilder("{");
        if (paramNames!=null && paramNames.length>0 && objects != null && objects.length > 0) {
            for (int i = 0; i < objects.length; i++) {
                if (objects[i] == null) {
                    continue;
                }
                if(paramNames.length>i) {
                    String className = objects[i].getClass().getName();
                    if (className.contains("MultipartFile")) {
                        MultipartFile multipartFile = (MultipartFile) objects[i];
                        reqArray.append("\"").append(paramNames[i]).append("\":\"").
                                append(multipartFile.getOriginalFilename()).append("\",");
                     } else {
                        reqArray.append("\"").append(paramNames[i]).append("\":").
                                append(JSON.toJSONString(objects[i])).append(",");
                    }
                }else{
                    break;
                }
            }
        }
        if (reqArray.length() > 1) {
            reqArray.replace(reqArray.length() - 1, reqArray.length(), "}");
        } else {
            reqArray.append("}");
        }
        return reqArray.toString();
    }

    private  Object[] getMethodInfo(String operation, Method method) throws Exception{
        Object [] info=MethodInfo.get(operation);
        if(info==null){
           info=new Object[2];
        }else{
            return info;
        }
        Boolean returnJson=false;
        if(method.getAnnotation(ResponseBody.class)!=null){
            returnJson=true;
        }
        info[0]=returnJson;
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        List<String> list=new ArrayList<String>();
        if (parameterAnnotations != null) {
            int i = 0; //数组增强for和普通遍历等价
            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof RequestParam) {
                        RequestParam param = (RequestParam) annotation;
                        list.add(param.value());
                        break;
                    }
                }
            }
        }
        info[1]=list.toArray(new String[0]);
        MethodInfo.put(operation, info);
        return info;
    }

}

原文地址:https://www.cnblogs.com/nullAndValue/p/10035617.html

时间: 2024-08-27 17:18:37

分享spring boot controller统一日志代码的相关文章

Spring Boot - Logback配置日志要考虑哪些因素

Spring Boot - Logback配置日志 出于性能等原因,Logback 目前是springboot应用日志的标配: 当然有时候在生产环境中也会考虑和三方中间件采用统一处理方式.@pdai Spring Boot - Logback配置日志 配置时考虑点 实现范例 综合范例 在配置前可以参考如下文章 參考文档 代码示例 最全的Java后端知识体系 https://www.pdai.tech, 每天更新中.... 配置时考虑点 支持日志路径,日志level等配置 日志控制配置通过appl

spring boot Controller中使用注解@RequestBody遇到的一个问题

spring boot Controller中使用注解@RequestBody遇到的一个问题总结: 通过@RequestBody接收实体对象,如代码所示 @PostMapping(value = "addtype")public Object addAppType(@RequestBody AppType appType) throws Exception{ return JsonData.buildSuccess();} 用postman测试接口时, 首先选择post请求 然后Hea

基于Spring Boot的统一异常处理设计

摘自:https://www.cnblogs.com/greyzeng/p/11733327.html Practitioner 需要不断努力,才能毫不费力 基于Spring Boot的统一异常处理设计 基于Spring Boot的统一异常处理设计 作者: Grey 原文地址:https://www.cnblogs.com/greyzeng/p/11733327.html Spring Boot中,支持RestControllerAdvice统一处理异常,在一个请求响应周期当中,如果Contro

Spring Boot学习——统一异常处理

本随笔记录使用Spring Boot统一处理异常. 本文实例是从数据库中根据ID查询学生信息,要求学生的年龄在14--20岁之间.小于14岁,提示"你可能在上初中":大于20岁,提示"呢可能在上大学". 第一步,创建枚举类ResultEnum,用来管理异常信息 package *;//自己定义 public enum ResultEnum { UNKONW_ERROR(-1, "未知错误"), SUCCESS(0, "成功")

【spring boot logback】spring boot中logback日志乱码问题

在初次使用logback的自定义配置文件完整的控制spring boot日志后,发现了一个无法忍受的问题,就是日志乱码. 控制台看到打印日志乱码如下: 而日志文件打开: 记事本打开 sublime打开 关于这个问题,分析如下: 1.打印的"进入Controller日志控制中心---->>>"字样可以看出,至少代码本身和IDE环境的编码方式没有任何的关系: 2.打印出来的日志是logback-spring.xml文件起作用之后,显示在控制台的,而日志文件打开后,看到 不

Spring Boot 中 10 行代码构建 RESTful 风格应用

RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念,我这里就不做过多介绍了,传统的 Struts 对 RESTful 支持不够友好 ,但是 SpringMVC 对于 RESTful 提供了很好的支持,常见的相关注解有: @RestController @GetMapping @PutMapping @PostMapping @DeleteMapping @ResponseBody ... 这些注解都是和 RESTful 相关的,在移动互联网中,RESTful 得

剑指架构师系列-spring boot的logback日志记录

Spring Boot集成了Logback日志系统. Logback的核心对象主要有3个:Logger.Appender.Layout 1.Logback Logger:日志的记录器 主要用于存放日志对象,也可以定义日志类型.级别. 级别:ERROR.WARE.INFO.DEBUG和TRACE.没有FATAL,归纳到了ERROR级别里.ERROR.WARN and INFO level messages are logged by default. 在Spring Boot中,最好定义为logb

Spring Boot Controller

接上篇文章,HelloWorld程序中我们已经创建了一个HellController,里面包含了响应JSON的方法,本文针对Controller再做一下讲解. 回顾上篇文章,我们在Controller中使用 @RestController 注解,该注解是Spring 4.0引入的.查看源码可知其包含了 @Controller 和 @ResponseBody 注解.我们可以理解为 @Controller的增强版.专门为响应内容式的 Controller 而设计的,可以直接响应对象为JSON. 而

Spring Boot Controller(篇二)

接上篇文章,HelloWorld程序中我们已经创建了一个HellController,里面包含了响应JSON的方法,本文针对Controller再做一下讲解. 回顾上篇文章,我们在Controller中使用 @RestController 注解,该注解是spring 4.0引入的.查看源码可知其包含了 @Controller 和 @ResponseBody 注解.我们可以理解为 @Controller的增强版.专门为响应内容式的 Controller 而设计的,可以直接响应对象为JSON. 而