添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

对于请求参数的处理和响应, 如果在代码中体现日志会显得很繁琐, 普遍的解决方案是使用spring的切面方案去解决.

这儿使用的是springboot的切面: http://www.cnblogs.com/wenbronk/p/6848984.html

最开始的aspectj切面解决:
package com.iwhere.easy.travel.aspect;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSONObject;
@Aspect
@Component
public class ControllerAspect {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());  
    private String name = "easy-travel-server";
    @Pointcut("execution(public * com.wenbronk.controller.*.*(..))")
    public void controllerLog(){}
    @Pointcut("execution(public * com.wenbronk.service.*.*(..))")
    public void serviceLog(){}
    private ThreadLocal<Long> startTime = new ThreadLocal<>();
    private ThreadLocal<String> requestId = new ThreadLocal<>();
    private ThreadLocal<String> interfaceName = new ThreadLocal<>();
    private ThreadLocal<String> param = new ThreadLocal<>();
    private SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
    @Before("controllerLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 设置请求开始时间
        startTime.set(System.currentTimeMillis());
        Date stTimeDate = new Date(startTime.get());
        String dateStr = dataFormat.format(stTimeDate);
        // 设置请求标识
        String requestIdStr = UUID.randomUUID().toString();
        requestId.set(requestIdStr);
        // 提取全部参数  paramJson
        Enumeration<String> paramNames = request.getParameterNames();
        JSONObject paramJson = new JSONObject();
        while(paramNames.hasMoreElements()){
            String paramName = paramNames.nextElement();
            paramJson.put(paramName, request.getParameter(paramName));
        // 提取接口标识(url中截取)
        String requestUrl = request.getRequestURL().toString();
        int start = requestUrl.lastIndexOf("/")+1;
        String interfaceNameStr = null;
        if (requestUrl.contains("?")){
            interfaceNameStr = requestUrl.substring(start, requestUrl.indexOf("?"));
        } else {
            interfaceNameStr = requestUrl.substring(start);
        param.set(paramJson.toJSONString());
        interfaceName.set(interfaceNameStr);
        // 将requst的唯一标识放置在request中,在其他环节可以穿起来
        request.setAttribute("requestId", requestId.get());
    @AfterReturning(returning="rvt",pointcut="controllerLog()")
    public void doAfterReturning(JoinPoint joinPoint,Object rvt) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        logger.info("finished" + " " + name + " " + interfaceName.get() + " " + requestId.get() + " " 
                 + request.getRequestURL().toString() + " " + param.get()
                 + (System.currentTimeMillis() - startTime.get())
                 + " " + rvt.toString());
    @AfterThrowing(throwing="ex", pointcut="controllerLog()")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable ex) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
         // 发生地点
         int lineNum = 0;
         String className = null;
         String methodName = null;
         StackTraceElement[] st = ex.getStackTrace();
         for (StackTraceElement stackTraceElement : st) {
             lineNum = stackTraceElement.getLineNumber();
             className = stackTraceElement.getClassName();
             methodName = stackTraceElement.getMethodName();
            System.out.println("[类:" + className + "]调用"
            + methodName + "时在第" + lineNum
            + "行代码处发生异常!异常类型:" + ex.getClass().getName());
            break;
         String exceptionMessage = "[类:" + className + "]调用"+ methodName + "时在第" + lineNum + "行代码处发生异常!异常类型:" + ex.getClass().getName();
        logger.info("exception" + " " + name + " " + interfaceName.get() + " " + requestId.get() + " "
                 + request.getRequestURL().toString() + " " + param.get()
                 + " " + exceptionMessage);
 

可见这个里面有一个before和after, 然后还有一个异常处理的方法

附: joinpoint的简要api

AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法: 
1)JoinPoint 
 java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 
 Signature getSignature() :获取连接点的方法签名对象; 
 java.lang.Object getTarget() :获取连接点所在的目标对象; 
 java.lang.Object getThis() :获取代理对象本身; 
2)ProceedingJoinPoint 
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 
 java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法; 
 java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。 
http://blog.csdn.net/lhqj1992/article/details/52451136
https://my.oschina.net/xpbug/blog/113444
https://segmentfault.com/a/1190000000537475

由于此项目采用的是线程池, 所以可能存在内存一直上涨, 一直到线程池max之后达到一个稳定态, 也就发生了我们认为的内存泄漏

之后改成这个方法: 

package com.iwhere.scrapy.aspect;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSON;
 * 日志记录
 * @author wenbronk
 * @Date 上午9:33:47
@Aspect
@Configuration
public class LogAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
    // 定义切点 Pointcut
    @Pointcut("execution(* com.iwhere.scrapy.controller.*Controller.*(..))")
    public void excudeService() {}
    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        Long startTime = System.currentTimeMillis();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
//        Object target = pjp.getTarget();
//        String name = target.getClass().getName();
        Signature signature = pjp.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
        LOGGER.info("请求开始, {}#{}() URI: {}, method: {}, URL: {}, params: {}",className, methodName, uri, method, url, queryString);
        // result的值就是被拦截方法的返回值
        Object result = pjp.proceed();
        Long endTime = System.currentTimeMillis();
        LOGGER.info("请求结束, {}#{}(), URI: {}, method: {}, URL: {}, time: {}, result: {} ", className, methodName, uri, method, url, (endTime - startTime), JSON.toJSONString(result));
        return result;
//    @AfterThrowing(throwing="ex", pointcut="excudeService()")
//    public String doAfterThrowing(JoinPoint joinPoint, Throwable ex) throws Throwable {
//        // 接收到请求,记录请求内容
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//         // 发生地点
//         int lineNum = 0;
//         String className = null;
//         String methodName = null;
//         StackTraceElement[] st = ex.getStackTrace();
//         if (ArrayUtils.isNotEmpty(st)) {
//             lineNum = st[0].getLineNumber();
//             className = st[0].getClassName();
//             methodName = st[0].getMethodName();
//        LOGGER.info("Exception: {}#{}() 在第{}行发生{}异常!!!", className, methodName, lineNum, ex.getClass().getName());
//        return "exception";
 

在里面处理异常, 还是会抛出, 所以单独出一个异常处理

然后还需要加入一个全局异常处理框架: 

http://www.cnblogs.com/wenbronk/p/6850785.html

具体效果等待进一步测试

 推荐一个好的博客, 关于aspect的 : http://blog.csdn.net/lemon1003657090/article/details/52431584

转载于:https://www.cnblogs.com/wenbronk/p/6888568.html

对于请求参数的处理和响应, 如果在代码中体现日志会显得很繁琐, 普遍的解决方案是使用spring的切面方案去解决.这儿使用的是springboot的切面: http://www.cnblogs.com/wenbronk/p/6848984.html最开始的aspectj切面解决:package com.iwhere.easy.travel.aspect;import j... 2)批处理任务不可重用,特别是无法对批处理任务做:定时?重复使用?频次?其中路由调度? 3)批处理任务无法做到网格计算(特别像:websphere ibm grid computing)即批处理任务本身可以做成集群、fail over、sharding 由其是批处理任务可以做成“网格计算”这个功能,有了xxljob后你会发觉特别强大
发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~ 博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的。 小伙伴们有兴趣想了解内容和更多相关学习资料的请点赞收藏+评论转发+关注我,后面会有很多干货。我有一些面试题、架构、设计类资料可以说是程序员面试必备!所有资料都整理到网盘了,需要的话欢迎下载!私信我回复【000】即可免费获取 一、Java 基础 1. JDK 和 JRE 有什么区别? JDK:Java Develop
注册登录可以说是平时开发中最常见的东西了,但是一般进入到公司之后,像这样的功能早就开发完了,除非是新的项目。这两天就碰巧遇到了这样一个需求,完成pc端的注册登录功能。 实现这样的需求有很多种方式:像 1)HandlerInterceptor+WebMvcConfigurer+ThreadLocal 2)Filter过滤器 3)安全框架Shiro(轻量级框架) 4)安全框架Spring Securety(重量级框架) 而我采用的是第一种 SpringHandlerIntercepto. 用AspectJExpressionPointcut实现的切点比JdkRegexpMethodPointcut实现切点的好处就是,在设置切点的时候可以用切点语言来更加精确的表示拦截哪个方法! 可以精确到返回参数,参... nginx报错[error] CreateFile() "D:\Java-windows\nginx-1.16.0/logs/nginx.pid" failed (2: The system cann... 13382