一学一做专题网站,建设网站总结,大连建设安全网站,诸城网络科技网站建设一 、请求数据记录
Spring Boot提供了一个内置的日志记录解决方案#xff0c;通过 AbstractRequestLoggingFilter 可以记录请求的详细信息。
AbstractRequestLoggingFilter 有两个不同的实现类#xff0c;我们常用的是 CommonsRequestLoggingFilter。 通过 CommonsRequestL…一 、请求数据记录
Spring Boot提供了一个内置的日志记录解决方案通过 AbstractRequestLoggingFilter 可以记录请求的详细信息。
AbstractRequestLoggingFilter 有两个不同的实现类我们常用的是 CommonsRequestLoggingFilter。 通过 CommonsRequestLoggingFilter 开发者可以自定义记录请求的参数、请求体、请求头和客户端信息。
启用方式很简单加个配置就行了
Configuration
public class RequestLoggingConfig {Beanpublic CommonsRequestLoggingFilter logFilter() {CommonsRequestLoggingFilter filter new CommonsRequestLoggingFilter();filter.setIncludeQueryString(true);filter.setIncludePayload(true);filter.setIncludeHeaders(true);filter.setIncludeClientInfo(true);filter.setAfterMessagePrefix(REQUEST DATA-);return filter;}
}接下来需要配置日志级别为 DEBUG就可以详细记录请求信息
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilterDEBUG二 、请求/响应包装器多次获取json body参数
在 Spring Boot 中请求和响应包装器是用于增强原生 HttpServletRequest 和 HttpServletResponse 对象的功能。这些包装器允许开发者在请求处理过程中拦截和修改请求和响应数据从而实现一些特定的功能如请求内容的缓存、修改、日志记录以及响应内容的修改和增强。
请求包装器
ContentCachingRequestWrapper这是 Spring 提供的一个请求包装器用于缓存请求的输入流。它允许多次读取请求体这在需要多次处理请求数据如日志记录和业务处理时非常有用。
响应包装器
ContentCachingResponseWrapper这是 Spring 提供的一个响应包装器用于缓存响应的输出流。它允许开发者在响应提交给客户端之前修改响应体这在需要对响应内容进行后处理如添加额外的头部信息、修改响应体时非常有用。
使用场景
请求日志记录在处理请求之前和之后记录请求的详细信息包括请求头、请求参数和请求体。修改请求数据在请求到达控制器之前修改请求数据例如添加或修改请求头。响应内容修改在响应发送给客户端之前修改响应内容例如添加或修改响应头或者对响应体进行签名。性能测试通过缓存请求和响应数据可以进行性能测试而不影响实际的网络 I/O 操作。
具体用法
请求包装器的使用
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Component
public class RequestWrapperFilter extends OncePerRequestFilter {Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {ContentCachingRequestWrapper requestWrapper new ContentCachingRequestWrapper(request);// 可以在这里处理请求数据byte[] body requestWrapper.getContentAsByteArray();// 处理body例如记录日志//。。。filterChain.doFilter(requestWrapper, response);}
}响应包装器的使用
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Component
public class ResponseWrapperFilter extends OncePerRequestFilter {Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {ContentCachingResponseWrapper responseWrapper new ContentCachingResponseWrapper(response);filterChain.doFilter(request, responseWrapper);// 可以在这里处理响应数据byte[] body responseWrapper.getContentAsByteArray();// 处理body例如添加签名responseWrapper.setHeader(X-Signature, some-signature);// 必须调用此方法以将响应数据发送到客户端responseWrapper.copyBodyToResponse();}
}在上面的案例中OncePerRequestFilter 确保过滤器在一次请求的生命周期中只被调用一次这对于处理请求和响应数据尤为重要因为它避免了在请求转发或包含时重复处理数据。
通过使用请求和响应包装器开发者可以在不改变原有业务逻辑的情况下灵活地添加或修改请求和响应的处理逻辑。
三、单次过滤器
3.1 OncePerRequestFilter
OncePerRequestFilter 是 Spring 框架提供的一个过滤器基类它继承自 Filter 接口。这个过滤器具有以下特点
单次执行OncePerRequestFilter 确保在一次请求的生命周期内无论请求如何转发forwarding或包含including过滤器逻辑只执行一次。这对于避免重复处理请求或响应非常有用。内置支持它内置了对请求和响应包装器的支持使得开发者可以方便地对请求和响应进行包装和处理。简化代码通过继承 OncePerRequestFilter开发者可以减少重复代码因为过滤器的执行逻辑已经由基类管理。易于扩展开发者可以通过重写 doFilterInternal 方法来实现自己的过滤逻辑而不需要关心过滤器的注册和执行次数。
3.2 OncePerRequestFilter 使用场景
请求日志记录在请求处理之前和之后记录请求的详细信息如请求头、请求参数和请求体而不希望在请求转发时重复记录。请求数据修改在请求到达控制器之前对请求数据进行预处理或修改例如添加或修改请求头而不希望这些修改在请求转发时被重复应用。响应数据修改在响应发送给客户端之前对响应数据进行后处理或修改例如添加或修改响应头而不希望这些修改在请求包含时被重复应用。安全控制实现安全控制逻辑如身份验证、授权检查等确保这些逻辑在一次请求的生命周期内只执行一次。请求和响应的包装使用 ContentCachingRequestWrapper 和 ContentCachingResponseWrapper 等包装器来缓存请求和响应数据以便在请求处理过程中多次读取或修改数据。性能监控在请求处理前后进行性能监控如记录处理时间而不希望这些监控逻辑在请求转发时被重复执行。异常处理在请求处理过程中捕获和处理异常确保异常处理逻辑只执行一次即使请求被转发到其他处理器。
通过使用 OncePerRequestFilter开发者可以确保过滤器逻辑在一次请求的生命周期内只执行一次从而避免重复处理和潜在的性能问题。这使得 OncePerRequestFilter 成为处理复杂请求和响应逻辑时的一个非常有用的工具。
四 AOP 三件套
在 Spring 框架中AOP面向切面编程是一个强大的功能它允许开发者在不修改源代码的情况下对程序的特定部分进行横向切入。AopContext、AopUtils 和 ReflectionUtils 是 Spring AOP 中提供的几个实用类。
我们一起来看下。
4.1 AopContext
AopContext 是 Spring 框架中的一个类它提供了对当前 AOP 代理对象的访问以及对目标对象的引用。
AopContext 主要用于获取当前代理对象的相关信息以及在 AOP 代理中进行一些特定的操作。
常见方法有两个
getTargetObject(): 获取当前代理的目标对象。currentProxy(): 获取当前的代理对象。
其中第二个方法在防止同一个类中注解失效的时候可以通过该方法获取当前类的代理对象。
举个栗子
public void noTransactionTask(String keyword){ // 注意这里 调用了代理类的方法((YourClass) AopContext.currentProxy()).transactionTask(keyword);
}Transactional
void transactionTask(String keyword) {try {Thread.sleep(5000);} catch (InterruptedException e) { //logger//error tracking}System.out.println(keyword);
}同一个类中两个方法noTransactionTask 方法调用 transactionTask 方法为了使事务注解不失效就可以使用 AopContext.currentProxy() 去获取当前代理对象。
4.2 AopUtils
AopUtils 提供了一些静态方法来处理与 AOP 相关的操作如获取代理对象、获取目标对象、判断代理类型等。
常见方法有三个
getTargetObject(): 从代理对象中获取目标对象。isJdkDynamicProxy(Object obj): 判断是否是 JDK 动态代理。isCglibProxy(Object obj): 判断是否是 CGLIB 代理。
举个栗子
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;public class AopUtilsExample {public static void main(String[] args) {MyService myService ...// 假设 myService 已经被代理if (AopUtils.isCglibProxy(myService)) {System.out.println(这是一个 CGLIB 代理对象);}}
}4.3 ReflectionUtils
ReflectionUtils 提供了一系列反射操作的便捷方法如设置字段值、获取字段值、调用方法等。这些方法封装了 Java 反射 API 的复杂性使得反射操作更加简单和安全。
常见方法
makeAccessible(Field field): 使私有字段可访问。getField(Field field, Object target): 获取对象的字段值。invokeMethod(Method method, Object target, Object... args): 调用对象的方法。
举个栗子
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;
import java.util.Map;public class ReflectionUtilsExample {public static void main(String[] args) throws Exception {ExampleBean bean new ExampleBean();bean.setMapAttribute(new HashMap());Field field ReflectionUtils.findField(ExampleBean.class, mapAttribute);ReflectionUtils.makeAccessible(field);Object value ReflectionUtils.getField(field, bean);System.out.println(value);}static class ExampleBean {private MapString, String mapAttribute;public void setMapAttribute(MapString, String mapAttribute) {this.mapAttribute mapAttribute;}}
}总结 / oauth2示例
还有哪些实用内置类呢欢迎小伙伴们留言我会研究一下记录在博文里同时会署名提供的朋友。
最近看到好多朋友在问oauth2的demo我之前写过一个不是很详细大致功能都有有兴趣的朋友可以参考一下。gitee地址: