简介:本文深入探讨SpringBoot嵌套网站架构设计与Spring AOP的嵌套应用,通过多模块分层、AOP切面编程实现权限控制、日志管理等核心功能,提供可复用的技术方案与代码示例。
SpringBoot嵌套网站的核心在于通过多模块分层实现业务解耦。典型架构采用”主模块+子模块”的嵌套结构:
<dependencyManagement>实现版本统一
<!-- 主工程pom.xml示例 --><modules><module>user-module</module><module>order-module</module></modules><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.1.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
采用”主路由+子路由”的嵌套路由机制:
@Controller处理基础路径(如/api)@RequestMapping实现细粒度路由(如/api/user/profile)@PathVariable实现跨模块参数共享
// 主模块控制器@RestController@RequestMapping("/api")public class ApiGatewayController {@Autowiredprivate UserModuleClient userModuleClient;@GetMapping("/user/{id}")public ResponseEntity<?> getUser(@PathVariable Long id) {return userModuleClient.getUserProfile(id);}}// 子模块Feign客户端@FeignClient(name = "user-module")public interface UserModuleClient {@GetMapping("/profile/{id}")ResponseEntity<?> getUserProfile(@PathVariable Long id);}
实现多级切面嵌套的典型场景:
@Around执行方法耗时统计)@Before检查方法注解)@AfterReturning处理返回值)
// 全局日志切面(第一级)@Aspect@Componentpublic class GlobalLoggingAspect {@Around("execution(* com.example..*.*(..))")public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();Object proceed = joinPoint.proceed();long executionTime = System.currentTimeMillis() - start;log.info("{} executed in {} ms", joinPoint.getSignature(), executionTime);return proceed;}}// 模块权限切面(第二级)@Aspect@Componentpublic class ModuleAuthAspect {@Before("@annotation(com.example.annotation.ModuleAuth)")public void checkPermission(JoinPoint joinPoint) {// 实现模块级权限校验逻辑}}
通过逻辑运算符实现复杂切点组合:
&&(与)、||(或)、!(非)@Pointcut定义可复用切点
@Aspect@Componentpublic class CompositeAspect {@Pointcut("within(com.example.user..*)")public void inUserModule() {}@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")public void isGetMethod() {}@Around("inUserModule() && isGetMethod()")public Object handleUserGet(ProceedingJoinPoint joinPoint) throws Throwable {// 仅对用户模块的GET请求生效return joinPoint.proceed();}}
通过@Order注解明确切面优先级:
@Aspect@Order(1) // 最高优先级public class PriorityAspect {// ...}@Aspect@Order(2)public class NormalAspect {// ...}
实现三级异常处理机制:
@AfterThrowing捕获@ControllerAdvice统一处理
@Aspect@Componentpublic class ExceptionHandlingAspect {@AfterThrowing(pointcut = "execution(* com.example..*.*(..))", throwing = "ex")public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {log.error("Exception in {}: {}", joinPoint.getSignature(), ex.getMessage());}}
使用Spring Boot Actuator监控切面耗时:
spring-boot-starter-actuator依赖management.endpoints.web.exposure.include=metrics/actuator/metrics/http.server.requests获取请求耗时数据
# application.yml配置management:endpoints:web:exposure:include: metrics,health,infometrics:export:prometheus:enabled: true
实现嵌套缓存策略:
@Cacheable
@Aspect@Componentpublic class CachingAspect {@Autowiredprivate CacheManager cacheManager;@Around("@annotation(com.example.annotation.CacheableModule)")public Object cacheResult(ProceedingJoinPoint joinPoint) throws Throwable {String cacheKey = generateCacheKey(joinPoint);Cache cache = cacheManager.getCache("moduleCache");return cache.get(cacheKey, () -> {try {return joinPoint.proceed();} catch (Throwable e) {throw new RuntimeException(e);}});}}
构建”用户-角色-权限”三级嵌套模型:
通过AOP实现权限校验链:
@Aspect@Componentpublic class PermissionAspect {@Before("@annotation(com.example.security.RequiresPermission)")public void checkPermission(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();RequiresPermission permission = signature.getMethod().getAnnotation(RequiresPermission.class);// 获取当前用户权限Set<String> userPermissions = SecurityContext.getCurrentPermissions();// 校验权限if (!userPermissions.containsAll(permission.value())) {throw new AccessDeniedException("Insufficient permissions");}}}
采用Saga模式实现跨模块事务:
@Aspect@Componentpublic class TransactionAspect {@Autowiredprivate TransactionCoordinator coordinator;@Around("@annotation(org.springframework.transaction.annotation.Transactional)")public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {String transactionId = UUID.randomUUID().toString();coordinator.startTransaction(transactionId);try {Object result = joinPoint.proceed();coordinator.commit(transactionId);return result;} catch (Exception e) {coordinator.rollback(transactionId);throw e;}}}
现象:A切面调用B方法,B方法又被A切面拦截
解决方案:
@Around("execution(* com.example.service.*.*(..)) && !within(com.example.aspect..*)")public Object avoidCircular(ProceedingJoinPoint joinPoint) throws Throwable {// 避免切面自调用return joinPoint.proceed();}
优化策略:
@Conditional减少不必要的切面执行
@Aspect@ConditionalOnProperty(name = "aop.enabled", havingValue = "true")public class ConditionalAspect {// 仅在配置启用时生效}
SpringBoot嵌套网站架构与Spring AOP的嵌套应用,通过模块化设计和切面编程实现了:
未来发展方向:
建议开发者在实施时: