真香!Spring Boot 3.3 的这些内置功能绝对值得一用,开发者不需重复造轮子

科技   2024-11-17 07:31   河北  


真香!Spring Boot 3.3 的这些内置功能绝对值得一用,开发者不需重复造轮子

在Spring Boot框架中,内置了众多功能来帮助开发者高效地构建和维护应用程序。这些功能不仅简化了开发过程,还提供了丰富的工具来处理复杂的场景,如日志记录、请求和响应缓存、AOP切面等。通过这些内置工具,开发者可以轻松实现应用的横切关注点管理,如事务、权限和审计。这种结构化的支持极大提升了应用的可维护性和扩展性,特别适用于高并发、复杂业务逻辑的企业级应用开发。

请求日志记录(CommonsRequestLoggingFilter)

为了记录HTTP请求的详细信息,如客户端IP、查询参数、请求头等,可以使用CommonsRequestLoggingFilter来实现。该过滤器可以被自定义以确保记录完整而不过多占用资源。

配置示例:

@Bean
public CommonsRequestLoggingFilter requestLoggingFilter() {
CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
loggingFilter.setIncludeClientInfo(true); // 包含客户端信息
loggingFilter.setIncludeQueryString(true); // 包含查询字符串
loggingFilter.setIncludePayload(true); // 包含请求体
loggingFilter.setIncludeHeaders(true); // 包含请求头
loggingFilter.setMaxPayloadLength(1000); // 限制请求体长度
return loggingFilter;
}

深入分析:

  • setIncludeClientInfo(true):记录客户端的IP地址和会话信息,便于对请求来源进行审计。

  • setMaxPayloadLength(1000):确保请求体记录不会影响性能,适合在请求体较大的情况下限制记录内容。

请求/响应体缓存(ContentCachingRequestWrapper 和 ContentCachingResponseWrapper)

默认情况下,请求和响应体只能读取一次,使用ContentCachingRequestWrapperContentCachingResponseWrapper可以将它们缓存,便于多次访问请求/响应内容。

示例:

@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);

filterChain.doFilter(wrappedRequest, wrappedResponse);

// 获取并记录响应内容
byte[] responseBody = wrappedResponse.getContentAsByteArray();
String responseContent = new String(responseBody, wrappedResponse.getCharacterEncoding());

// 必须将响应体拷贝回实际响应流
wrappedResponse.copyBodyToResponse();
}

深入分析:

  • ContentCachingRequestWrapper 缓存请求体,ContentCachingResponseWrapper缓存响应体。适合在日志记录、审计或安全检查中反复读取内容。

单次执行过滤器(OncePerRequestFilter)

OncePerRequestFilter确保过滤器在同一次请求中只执行一次,适合处理例如日志、权限等不希望多次执行的操作。

示例:

public class CustomFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 执行过滤逻辑
filterChain.doFilter(request, response);
}
}

深入分析:

  • OncePerRequestFilter通过在请求的生命周期中确保过滤器只执行一次,避免了日志等重复操作,提高了系统性能。

AOP增强

Spring AOP(面向切面编程)允许开发者在业务逻辑外进行横切关注点的增强,特别适合用在日志记录、性能监控等场景。

示例:

@Aspect
@Component
public class LoggingAspect {

@Pointcut("execution(* com.example.service.*.*(..))")
public void applicationPackagePointcut() {
// 切入点:定义service包内所有方法的切面
}

@Before("applicationPackagePointcut()")
public void logBeforeMethod(JoinPoint joinPoint) {
// 在目标方法执行前记录日志
logger.info("Executing method: " + joinPoint.getSignature());
}
}

深入分析:

  • 通过在切面中记录日志,可以减少代码冗余,并集中处理日志记录、性能监控等任务,避免每个方法中都插入重复的日志逻辑。

AOP工具三件套

Spring AOP 提供了三个常用的工具类,分别是 AopContextAopUtils 和 ReflectionUtils。它们可以帮助开发者在处理代理对象、事务以及反射时更便捷地操作和增强代码逻辑。以下是每个工具类的使用示例:

AopContext 示例

用于在同一类中调用代理方法,防止事务注解失效:

@Service
public class MyService {

@Transactional
public void transactionalMethod() {
System.out.println("事务处理逻辑");
}

public void callTransactionalMethod() {
// 使用 AopContext 获取当前代理对象,确保事务生效
MyService proxyService = (MyService) AopContext.currentProxy();
proxyService.transactionalMethod();
}
}

在这里,AopContext.currentProxy() 会确保调用代理方法,从而保持事务逻辑不被跳过。

AopUtils 示例

用于检查对象是否为代理对象,并获取目标类:

public void checkProxyObject(Object object) {
if (AopUtils.isAopProxy(object)) {
// 如果对象是代理对象,打印出原始类
Object target = AopUtils.getTargetClass(object);
System.out.println("代理对象的目标类: " + target.getClass().getName());
} else {
System.out.println("对象不是代理对象");
}
}

AopUtils.isAopProxy(object) 可以判断对象是否为AOP代理,AopUtils.getTargetClass(object) 获取其目标类信息。

ReflectionUtils 示例

简化反射操作,获取类的私有字段并修改值:

public class Example {
private String secret = "秘密信息";

public static void main(String[] args) {
Example example = new Example();

// 使用 ReflectionUtils 查找并修改字段
Field field = ReflectionUtils.findField(Example.class, "secret");
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, example, "新的秘密信息");

System.out.println("更新后的字段值: " + example.secret);
}
}

ReflectionUtils 简化了反射操作,通过 findField 查找字段,makeAccessible 允许访问私有字段,并使用 setField 修改字段值。

结论

通过结合日志记录、请求体缓存、AOP切面等技术,开发者可以有效提升Spring Boot应用的可维护性和性能。这些工具不仅能增强系统的审计、日志功能,还能够通过横切关注点管理,使业务逻辑更加清晰简洁。尤其是在大规模分布式系统中,这些优化技术为系统扩展性和健壮性提供了重要支持。


今天就讲到这里,如果有问题需要咨询,大家可以直接留言或扫下方二维码来知识星球找我,我们会尽力为你解答。


AI资源聚合站已经正式上线,该平台不仅仅是一个AI资源聚合站,更是一个为追求知识深度和广度的人们打造的智慧聚集地。通过访问 AI 资源聚合网站 https://ai-ziyuan.techwisdom.cn/,你将进入一个全方位涵盖人工智能和语言模型领域的宝藏库


作者:路条编程(转载请获本公众号授权,并注明作者与出处)

路条编程
路条编程是一个友好的社区,在这里你可以免费学习编程技能,我们旨在激励想学编程的人尝试新的想法和技术,在最短的时间学习到工作中使用到的技术!
 最新文章