您的位置:首页 > 文旅 > 旅游 > 怎么搭建自己的网站挣钱_手机app定制开发多少钱_网站优化公司收费_数据分析网站

怎么搭建自己的网站挣钱_手机app定制开发多少钱_网站优化公司收费_数据分析网站

2025/4/30 4:32:32 来源:https://blog.csdn.net/weixin_44034675/article/details/147546432  浏览:    关键词:怎么搭建自己的网站挣钱_手机app定制开发多少钱_网站优化公司收费_数据分析网站
怎么搭建自己的网站挣钱_手机app定制开发多少钱_网站优化公司收费_数据分析网站

不改动接口参数和返回,打印接口ip/url/时间,之后加到拦截器或者AOP中

注意事项

  1. IPrequest.getRemoteAddr()获取的可能是代理服务器IP而非真实客户端IP,真实IP需要从X-Forwarded-For等header中获取。

  2. 线程安全RequestContextHolder是基于ThreadLocal实现的,在异步方法中可能无法获取到request

  3. 日志框架:建议使用SLF4J等日志框架替代System.out.println

  4. 异常处理:确保在catch块中也记录结束时间,否则会丢失异常请求的日志

方法1:在入参中添加HttpServletRequest

import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;@RestController
@RequestMapping("/api")
public class YourController {@GetMapping("/your-endpoint")public ResponseEntity<?> yourMethod(HttpServletRequest request) {// 获取请求信息String ip = request.getRemoteAddr();String methodName = "yourMethod";Date startTime = new Date();System.out.println("请求开始 - IP: " + ip + ", 方法: " + methodName + ", 时间: " + startTime);try {// 你的业务逻辑代码// ...Date endTime = new Date();long duration = endTime.getTime() - startTime.getTime();System.out.println("请求结束 - 方法: " + methodName + ", 时间: " + endTime + ", 耗时: " + duration + "ms");return ResponseEntity.ok("Success");} catch (Exception e) {Date endTime = new Date();System.out.println("请求异常 - 方法: " + methodName + ", 时间: " + endTime);throw e;}}
}

方法2:使用RequestContextHolder获取Request

import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;@RestController
@RequestMapping("/api")
public class YourController {@GetMapping("/your-endpoint")public ResponseEntity<?> yourMethod() {// 获取当前请求对象HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String ip = request.getRemoteAddr();String methodName = "yourMethod";Date startTime = new Date();System.out.println("请求开始 - IP: " + ip + ", 方法: " + methodName + ", 时间: " + startTime);try {// 你的业务逻辑代码// ...Date endTime = new Date();long duration = endTime.getTime() - startTime.getTime();System.out.println("请求结束 - 方法: " + methodName + ", 时间: " + endTime + ", 耗时: " + duration + "ms");return ResponseEntity.ok("Success");} catch (Exception e) {Date endTime = new Date();System.out.println("请求异常 - 方法: " + methodName + ", 时间: " + endTime);throw e;}}
}...
private String getClientIP(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr();} return ip.split(",")[0]; // 处理多级代理的情况 }}String apiName = request.getRequestURI(); 

方法3:方法2封装成工具类

日志工具类代码复用

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;public class RequestLogUtil {public static void logRequestStart(String methodName) {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String ip = request.getRemoteAddr();Date startTime = new Date();System.out.println("请求开始 - IP: " + ip + ", 方法: " + methodName + ", 时间: " + startTime);}public static void logRequestEnd(String methodName) {Date endTime = new Date();System.out.println("请求结束 - 方法: " + methodName + ", 时间: " + endTime);}
}

然后在控制器中使用:

@GetMapping("/your-endpoint")
public ResponseEntity<?> yourMethod() {RequestLogUtil.logRequestStart("yourMethod");try {// 业务逻辑// ...RequestLogUtil.logRequestEnd("yourMethod");return ResponseEntity.ok("Success");} catch (Exception e) {RequestLogUtil.logRequestEnd("yourMethod");throw e;}
}

后期

方式一:拦截器(Interceptor)

1. 创建日志拦截器类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;public class RequestLogInterceptor implements HandlerInterceptor {private static final Logger LOG = LoggerFactory.getLogger(RequestLogInterceptor.class);private static final ThreadLocal<Instant> startTimeThreadLocal = new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {startTimeThreadLocal.set(Instant.now());return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {Instant startTime = startTimeThreadLocal.get();Instant endTime = Instant.now();long duration = Duration.between(startTime, endTime).toMillis();String clientIP = getClientIP(request);String apiName = request.getRequestURI();LOG.info("接口请求日志 - IP: {}, 接口: {}, 开始时间: {}, 结束时间: {}, 耗时: {}ms",clientIP, apiName, startTime, endTime, duration);startTimeThreadLocal.remove();}private String getClientIP(HttpServletRequest request) {String ip = request.getHeader("X-Forwarded-For");if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}
}
2. 注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestLogInterceptor()).addPathPatterns("/api/**"); // 拦截所有/api路径的请求}
}

方式二:AOP

1. 添加AOP依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 创建切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
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 javax.servlet.http.HttpServletRequest;
import java.time.Instant;@Aspect
@Component
public class RequestLogAspect {private static final Logger LOG = LoggerFactory.getLogger(RequestLogAspect.class);@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();Instant startTime = Instant.now();String clientIP = getClientIP(request);String apiName = request.getRequestURI();try {Object result = joinPoint.proceed(); // 执行目标方法return result;} finally {Instant endTime = Instant.now();long duration = endTime.toEpochMilli() - startTime.toEpochMilli();LOG.info("接口请求日志 - IP: {}, 接口: {}, 开始时间: {}, 结束时间: {}, 耗时: {}ms",clientIP, apiName, startTime, endTime, duration);}}private String getClientIP(HttpServletRequest request) {String ip = request.getHeader("X-Forwarded-For");if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip.split(",")[0]; // 处理多级代理的情况}
}

说明

  1. 获取客户端IP

    • 优先从 X-Forwarded-For 头获取真实IP(适用于通过代理的情况)。
    • 直接使用 request.getRemoteAddr() 作为备用方案。
  2. 接口名称

    • 使用 request.getRequestURI() 获取请求路径(如 /api/user)。
    • 若需更精细的接口名(如方法名),可在AOP中通过 joinPoint.getSignature().getName() 获取。
  3. 耗时计算

    • 使用 Instant 记录时间戳,确保高精度。
    • 在拦截器的 afterCompletion 或AOP的 finally 块中计算总耗时。
  4. 线程安全

    • 拦截器中通过 ThreadLocal 存储开始时间,避免并发问题。

日志输出示例

2023-10-05 14:20:00 INFO  RequestLogAspect - 接口请求日志 - IP: 192.168.1.100, 接口: /api/user, 开始时间: 2023-10-05T14:20:00.123Z, 结束时间: 2023-10-05T14:20:00.456Z, 耗时: 333ms

扩展建议

  • 异步日志:若日志频繁,可使用异步Appender(如Logback的AsyncAppender)提升性能。
  • JSON格式:输出为JSON便于ELK采集:
    LOG.info("{}", new ObjectMapper().writeValueAsString(logMap));
    
  • 自定义注解:通过注解标记需要记录日志的接口:
    @Around("@annotation(com.example.YourLoggableAnnotation)")
    

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com