在SpringBoot中使用AOP获取HttpServletRequest、HttpSession 内容

本文介绍如何在Spring Boot项目中使用AOP进行方法拦截。通过配置POM文件引入AOP依赖,并实现了一个具体的WebControllerAop类来记录方法调用的日志信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POM.xml添加AOP依赖:

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>

然后在拦截器类中添加切面代码:

package com.tbms2;

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.alibaba.fastjson.JSON;

@Component
@Aspect
public class WebControllerAop {

    Logger logger = LoggerFactory.getLogger(WebControllerAop.class);
    
    @Pointcut("execution(* com.tbms2.web..*.json*(..))")
    public void executeService(){
        
    }
    
    @Before("executeService()")
    public void doBeforeAdvice(JoinPoint joinPoint) {
        logger.info("==> json方法调用开始...");
        //获取目标方法的参数信息  
        Object[] obj = joinPoint.getArgs();  
        //AOP代理类的信息  
        joinPoint.getThis();  
        //代理的目标对象  
        joinPoint.getTarget();  
        //用的最多 通知的签名  
        Signature signature = joinPoint.getSignature();  
        //代理的是哪一个方法  
        logger.info("==> 代理的是哪一个方法 :"+signature.getName());
        //AOP代理类的名字  
        logger.info("==> AOP代理类的名字:"+signature.getDeclaringTypeName());
        //AOP代理类的类(class)信息  
        signature.getDeclaringType();  
        //获取RequestAttributes  
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();  
        //从获取RequestAttributes中获取HttpServletRequest的信息  
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);  
        logger.info("==> 请求者的IP:"+request.getRemoteAddr());
        //如果要获取Session信息的话,可以这样写:  
        //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);  
        Enumeration<String> enumeration = request.getParameterNames();  
        Map<String,String> parameterMap = new HashMap<String,String>();
        while (enumeration.hasMoreElements()){
            String parameter = enumeration.nextElement();  
            parameterMap.put(parameter,request.getParameter(parameter));  
        }  
        String str = JSON.toJSONString(parameterMap);  
        if(obj.length > 0) {  
            logger.info("==> 请求的参数信息为:"+str);
        }
    }
    
}

<think>首先,用户的问题是关于在面向切面编程(AOP)中如何获取session值。用户提供了几个引用,我需要参考这些内容来构建回答。 关键引用: - 引用[1]:解释了AOP的基本概念,将横切关注点封装到切面中。 - 引用[2]:强调了AOP用于非业务代码,如日志打印。 - 引用[3]:讨论了Spring Boot中的AOP,包括过滤器、拦截器和Aspect。 - 引用[4]:展示了使用@Pointcut和前置通知检查权限的例子,涉及从请求中获取用户角色。 - 引用[5]:提供了自定义注解的示例,用于拦截controller和service方法。 用户的问题:如何在切面编程中获取session值?session通常存储在HttpSession中,在Web应用中常见。 在Spring框架中,AOP常用于处理Web请求,session值可以通过HttpServletRequestHttpSession对象获取。 步骤: 1. **理解上下文**:在Spring AOP中,切面通常用于拦截方法调用,比如在Controller层。session值可以从HttpServletRequest获取。 2. **如何获取HttpServletRequest**:在Spring中,可以通过注入HttpServletRequest对象来访问session。 - 在切面类中,可以使用@Autowired注入HttpServletRequest。 - 或者,使用RequestContextHolder来获取当前请求。 具体方法: - 使用org.springframework.web.context.request.RequestContextHolder来获取ServletRequestAttributes,然后获取HttpServletRequest。 - 示例代码: ```java import javax.servlet.http.HttpServletRequest; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; public class MyAspect { public void someAdvice() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpSession session = request.getSession(); // 然后从session获取值 Object value = session.getAttribute("key"); } } ``` - 在切面通知中,比如@Before,@Around等,可以使用这种方法。 参考引用[4]:它提到了一个前置通知方法checkPermission,其中从请求中获取用户角色。这暗示了类似的方法: ```java private String getUserRole() { // 从请求中获取用户角色,可能涉及session HttpServletRequest request = ...; // 类似上面的方式 return ...; } ``` 在引用[5]中,有自定义注解用于拦截controller和service方法。在切面中,可以结合这些注解来定义切入点,然后在通知中获取session。 回答结构: 1. **介绍**:简要解释AOP获取session值的必要性,比如用于权限检查、用户信息等。 2. **核心方法**:描述如何在Spring AOP获取HttpServletRequestsession。 3. **代码示例**:提供一个简单的切面示例,展示如何实现。 4. **注意事项**:讨论线程安全、作用域等问题。 5. **生成相关问题**:根据用户指令,生成相关问题。 用户指令要求: - 系统级指令:使用$...$和$$...$$格式,中文回答,生成相关问题。 - 回答结构清晰,真实可靠。 生成相关问题: - 基于主题,比如如何自定义注解、如何处理session过期等。 完整回答: - 开头解释问题。 - 提供步骤和代码。 - 结尾生成相关问题。</think>### 在面向切面编程中获取Session值的方法 在面向切面编程(AOP)中,获取Session值通常用于处理横切关注点,如用户权限验证、登录状态检查或日志记录。Session值存储在HttpSession对象中,在Spring框架中,可以通过HttpServletRequest间接访问。以下是详细步骤和实现方法: #### 1. **核心原理** - Session是Web应用中用于存储用户会话数据的机制,一般通过HttpServletRequest对象获取。 - 在AOP切面中,**无法直接注入HttpSession**,因为切面本身不绑定Web上下文。但可以通过Spring的`RequestContextHolder`工具类获取当前请求的HttpServletRequest对象,进而访问Session[^3][^4]。 - 关键类: - `org.springframework.web.context.request.RequestContextHolder`:提供对当前请求上下文的访问。 - `javax.servlet.http.HttpServletRequest`:用于获取HttpSession。 #### 2. **实现步骤** 在Spring Boot项目中,按以下步骤操作: **步骤1: 定义自定义注解(可选,但推荐用于明确切入点)** 参考引用[5],创建一个注解标记需要获取Session的方法: ```java import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GetSessionValue { String key() default ""; // 用于指定Session中的键名 } ``` **步骤2: 创建切面类并获取Session** - 使用`@Aspect`和`@Component`注解定义切面。 - 在通知方法(如`@Around`或`@Before`)中,通过`RequestContextHolder`获取HttpServletRequest。 - 示例代码: ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; 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 javax.servlet.http.HttpSession; @Aspect @Component public class SessionAspect { // 定义切入点:拦截所有带@GetSessionValue注解的方法 @Pointcut("@annotation(com.example.annotation.GetSessionValue)") public void sessionPointcut() {} // 环绕通知,获取Session值 @Around("sessionPointcut()") public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { // 1. 获取当前HttpServletRequest ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 2. 从Request中获取Session HttpSession session = request.getSession(false); // false表示如果Session不存在则返回null if (session == null) { throw new RuntimeException("Session未初始化"); } // 3. 获取Session中的值(例如用户ID) String sessionKey = getAnnotationKey(joinPoint); // 从注解中读取key Object sessionValue = session.getAttribute(sessionKey); System.out.println("获取Session值: " + sessionValue); // 4. 执行业务方法 return joinPoint.proceed(); } // 辅助方法:从注解中提取key private String getAnnotationKey(ProceedingJoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); GetSessionValue annotation = signature.getMethod().getAnnotation(GetSessionValue.class); return annotation.key(); } } ``` **关键点说明**: - **线程安全**:`RequestContextHolder`基于ThreadLocal实现,确保在多线程环境下正确获取当前请求[^3]。 - **Session存在性检查**:使用`request.getSession(false)`避免自动创建新Session。 - **应用场景**:适用于Controller层方法,如权限校验(引用[4]的权限检查逻辑)。 #### 3. **使用示例** 在Controller方法上添加自定义注解,指定Session键名: ```java @RestController public class UserController { @GetSessionValue(key = "userId") // 指定获取Session中的"userId" @GetMapping("/user/profile") public String getUserProfile() { // 业务逻辑 return "用户信息页面"; } } ``` - 当访问`/user/profile`时,切面会自动获取Session中的`userId`值。 #### 4. **注意事项** - **作用域限制**:此方法仅适用于Web请求上下文(如Controller方法)。在Service层直接使用可能失效,因为Service可能被非Web线程调用。 - **依赖注入**:确保项目中包含Spring Web依赖(如`spring-boot-starter-web`)。 - **错误处理**:添加异常处理逻辑,应对Session过期或未登录场景。 - **性能**:频繁访问Session可能影响性能,建议在切面中缓存值或优化逻辑。 #### 5. **替代方案** - **注入HttpServletRequest**:在Controller方法参数中添加`HttpServletRequest request`,然后通过切面获取参数值(需修改切入点)。 - **使用Spring Security**:如果涉及权限,可直接集成Spring Security,其内置的`SecurityContextHolder`可获取用户信息,避免手动操作Session[^4]。 ### 相关问题 1. **如何在切面中处理Session过期或无效的情况?** (涉及自定义异常和重定向逻辑) 2. **AOP切面如何与Spring Security集成实现权限控制?** (参考引用[4]的权限检查机制) 3. **在非Web环境下(如定时任务),能否使用AOP获取类似Session的数据?** (讨论ThreadLocal或自定义上下文的应用) 4. **如何优化AOP切面以减少对Session的频繁访问?** (引入缓存或懒加载策略) [^1]: AOP面向切面编程,将横切关注点封装到可重用模块,提高代码模块化。 [^3]: Spring Boot的AOP通过动态代理实现,支持过滤器、拦截器和切面。 [^4]: 使用@Pointcut和前置通知检查权限,从请求中获取用户角色。 [^5]: 自定义注解拦截Controller或Service方法,便于定义切入点。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值