将LogClientInfo修改为全阶段过滤器以支持将请求的响应代码和响应体存入AccessLog表

This commit is contained in:
2025-09-26 11:54:14 +08:00
parent 2c0b79e7d9
commit f6eb9ebb51
@@ -1,13 +1,12 @@
package xyz.thewhitedog9487.WebAPI.Controller.Filter; package xyz.thewhitedog9487.WebAPI.Controller.Filter;
import jakarta.servlet.FilterChain; import jakarta.servlet.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.ContentCachingResponseWrapper;
import xyz.thewhitedog9487.WebAPI.Data.Entity.AccessLog; import xyz.thewhitedog9487.WebAPI.Data.Entity.AccessLog;
import xyz.thewhitedog9487.WebAPI.Data.Repository.AccessLogRepository; import xyz.thewhitedog9487.WebAPI.Data.Repository.AccessLogRepository;
@@ -18,52 +17,65 @@ import java.util.Locale;
@Slf4j @Slf4j
@Component @Component
public class LogClientInfo extends OncePerRequestFilter { public class LogClientInfo implements Filter {
@Autowired AccessLogRepository AccessLogRepository; @Autowired AccessLogRepository AccessLogRepository;
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("接收到对于{} {} 的请求", request.getMethod(), request.getRequestURL() + ( ( request.getQueryString() == null ) ? "" : "?" + request.getQueryString() ) ); HttpServletRequest HttpServletRequest = (HttpServletRequest) request;
if ( request.getHeader("CF-Connecting-IP".toLowerCase() ) instanceof String IP ) { HttpServletResponse HttpServletResponse = (HttpServletResponse) response;
var Response = new ContentCachingResponseWrapper(HttpServletResponse);
log.info("接收到对于{} {} 的请求", HttpServletRequest.getMethod(), HttpServletRequest.getRequestURL() + ( ( HttpServletRequest.getQueryString() == null ) ? "" : "?" + HttpServletRequest.getQueryString() ) );
if ( HttpServletRequest.getHeader("CF-Connecting-IP".toLowerCase() ) instanceof String IP ) {
/* /*
↑ 如果成功完成instanceof模式匹配,那么模式变量一定非空 ↑ 如果成功完成instanceof模式匹配,那么模式变量一定非空
相当于是: 相当于是:
if ( request.getHeader("CF-Connecting-IP".toLowerCase() ) != null ) { if ( HttpServletRequest.getHeader("CF-Connecting-IP".toLowerCase() ) != null ) {
String IP = request.getHeader( "CF-Connecting-IP".toLowerCase() ); } String IP = HttpServletRequest.getHeader( "CF-Connecting-IP".toLowerCase() ); }
*/ */
log.info("请求携带了CF-Connecting-IP头部,IP{}", IP); } log.info("请求携带了CF-Connecting-IP头部,IP{}", IP); }
else if( request.getHeader("X-Forwarded-For".toLowerCase() ) instanceof String IP ) { else if( HttpServletRequest.getHeader("X-Forwarded-For".toLowerCase() ) instanceof String IP ) {
IP = IP.split(",")[0].trim(); IP = IP.split(",")[0].trim();
log.info("请求携带了X-Forwarded-For头部,IP{}", IP); } log.info("请求携带了X-Forwarded-For头部,IP{}", IP); }
else { else {
log.info("请求未携带CF-Connecting-IP和X-Forwarded-For头部,HttpServletRequest获取到的IP为:{}", request.getRemoteAddr()); } log.info("请求未携带CF-Connecting-IP和X-Forwarded-For头部,HttpServletRequest获取到的IP为:{}", HttpServletRequest.getRemoteAddr()); }
if ( request.getHeader("CF-IPCountry".toLowerCase() ) instanceof String IP ) { if ( HttpServletRequest.getHeader("CF-IPCountry".toLowerCase() ) instanceof String IP ) {
var Country = Locale.of(Locale.PRC.getLanguage(), IP, Locale.SIMPLIFIED_CHINESE.getVariant()); var Country = Locale.of(Locale.PRC.getLanguage(), IP, Locale.SIMPLIFIED_CHINESE.getVariant());
log.info("请求携带了CF-IPCountry头部,ISO3166代码:{},对应的国家/地区:{}", IP, Country.getDisplayCountry(Locale.SIMPLIFIED_CHINESE)); } log.info("请求携带了CF-IPCountry头部,ISO3166代码:{},对应的国家/地区:{}", IP, Country.getDisplayCountry(Locale.SIMPLIFIED_CHINESE)); }
else { else {
log.info("请求未携带CF-IPCountry头部,无法获取国家/地区信息。"); } log.info("请求未携带CF-IPCountry头部,无法获取国家/地区信息。"); }
var UserAgent = request.getHeader("User-Agent"); var UserAgent = HttpServletRequest.getHeader("User-Agent");
if( UserAgent == null ){ if( UserAgent == null ){
log.info("请求未携带User-Agent头部,无法获取客户端软件信息。"); } log.info("请求未携带User-Agent头部,无法获取客户端软件信息。"); }
else{ else{
log.info("请求的User-Agent{}", UserAgent); } log.info("请求的User-Agent{}", UserAgent); }
var Log = new AccessLog( var Log = new AccessLog(
null, null,
request.getRequestId(), HttpServletRequest.getRequestId(),
request.getHeader("CF-Connecting-IP".toLowerCase() ), HttpServletRequest.getHeader("CF-Connecting-IP".toLowerCase() ),
request.getHeader("X-Forwarded-For".toLowerCase() ), HttpServletRequest.getHeader("X-Forwarded-For".toLowerCase() ),
request.getRemoteAddr(), HttpServletRequest.getRemoteAddr(),
request.getHeader("CF-IPCountry".toLowerCase() ), HttpServletRequest.getHeader("CF-IPCountry".toLowerCase() ),
( request.getHeader("CF-IPCountry".toLowerCase() ) == null ) ? null : Locale.of(Locale.PRC.getLanguage(), request.getHeader("CF-IPCountry".toLowerCase() ), Locale.SIMPLIFIED_CHINESE.getVariant()).getISO3Country(), ( HttpServletRequest.getHeader("CF-IPCountry".toLowerCase() ) == null ) ? null : Locale.of(Locale.PRC.getLanguage(), HttpServletRequest.getHeader("CF-IPCountry".toLowerCase() ), Locale.SIMPLIFIED_CHINESE.getVariant()).getISO3Country(),
UserAgent, UserAgent,
request.getMethod(), HttpServletRequest.getMethod(),
request.getRequestURL().toString(), HttpServletRequest.getScheme(),
request.getQueryString(), HttpServletRequest.getProtocol(),
Collections.list( request.getHeaderNames() ) HttpServletRequest.getRequestURL().toString(),
HttpServletRequest.getQueryString(),
Collections.list( HttpServletRequest.getHeaderNames() )
.stream() .stream()
.map( name -> name + ": " + Collections.list(request.getHeaders(name)) ) .map( name -> name + ": " + Collections.list(HttpServletRequest.getHeaders(name)) )
.reduce( ( a, b ) -> a + "\n" + b ) .reduce( ( a, b ) -> a + "\n" + b )
.orElse(""), .orElse(""),
Instant.now() ); Instant.now(),
null,
null );
Log = AccessLogRepository.save(Log);
chain.doFilter(request, Response);
var ResponseBody = new String( Response.getContentAsByteArray(), Response.getCharacterEncoding() );
Log.setResponseStatusCode(HttpServletResponse.getStatus());
Log.setResponseBody(ResponseBody);
AccessLogRepository.save(Log); AccessLogRepository.save(Log);
filterChain.doFilter(request, response); } } log.info("请求处理完成,响应状态码:{}", HttpServletResponse.getStatus());
Response.copyBodyToResponse(); } }