利用AOP实现统一功能处理

简介: 利用AOP实现统一功能处理

一、实现用户登录校验

在之前的项目中,在需要验证用户登录的部分,每次都需要利用Session会话信息来进行判断用户是否处于登录状态,那么利用AOP思想可以进行统一处理,首先想到的是利用Spring AOP来进行实现,但是获取Session信息时需要HttpSession会话以及Request对象,这点StringAOP的五大通知都无法实现,并且在实际项目中并不是指定包或者指定类要进行拦截,适用AspectJ表达式就无法满足需求了,因此,就需要Spring拦截器来实现用户的登录的校验。

使用Spring拦截器的步骤:

  1. 实现自定义拦截器,实现Spring中的HandlerInterceptor接口中的preHandler方法。
  2. 将自定义的拦截器添加到框架的配置中,并且设置拦截的规则。

实现自定义拦截器

重写HandlerInterceptor接口中的preHandler方法,先获取到session对象,判断对象是否为空来判断登录状态,若未登录则自动跳转到登录页面。

@Component
public class LoginIntercept implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //先得到session对象,传入参数为false,表示Session为空时不会自动创建,传入参数为true则反之。
        HttpSession session = request.getSession(false);
        if(session != null && session.getAttribute("user") != null){
            //表示登录成功
            return true;
        }
        //表示未登录,则请求重定向到登录页面
        response.sendRedirect("/login.html");
        return false;
    }
}

将自定义的拦截器添加到框架的配置中,并且设置拦截的规则

将自定义的拦截器添加到框架的配置中,设置所有页面都要判断登录状态,除了一些指定页面。

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Resource
    private LoginIntercept loginIntercept;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginIntercept)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/**/*.css")
                .excludePathPatterns("/**/*.js")
                .excludePathPatterns("/**/*.jpg")
                .excludePathPatterns("/**/*.png");
 
    }
}

userController类的内容如下:

RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public boolean login(HttpServletRequest request, String userName, String password){
        if(StringUtils.hasLength(userName) && StringUtils.hasLength(password)){
            if(userName.equals("zhangsan") && password.equals("1234")){
                HttpSession session = request.getSession();
                session.setAttribute("user","user");
                return true;
            }
        }
        return false;
    }
    @RequestMapping("/test")
    public boolean test(){
        return true;
    }
}

那么访问test页面时就会出现:

此时就会进行拦截,并且重定向到登录页面。

二、实现统一异常处理

统一异常处理使用的是@ControllerAdvice注解,在方法前使用@ExceptionHandler注解,其中的参数为捕捉的异常类.class。

@RestControllerAdvice //表示当前处理异常的页面返回的是数据
public class MyExceptionAdvice {
    @ExceptionHandler(NullPointerException.class)
    public HashMap<String,Object> nullPointException(NullPointerException e){
        HashMap<String,Object> res = new HashMap<>();
        res.put("data",-1);
        res.put("state",-1);
        res.put("msg",e.getMessage());
        return res;
    }
}

那么访问一个空指针异常的页面:

    @RequestMapping("/test")
    public boolean test(){
       Object test = null;
       test.toString();
       return true;
    }

进行访问:

但是我们不可能将所有的异常都列举出来,就可以定义一个方法处理所有的异常。

@ExceptionHandler(Exception.class)
    public HashMap<String,Object> allException(Exception e){
        HashMap<String,Object> res = new HashMap<>();
        res.put("data",-1);
        res.put("state",-1);
        res.put("msg",e.getMessage());
        return res;
    }

三、实现统一数据格式封装

对数据进行统一的格式封装,给当前类添加@Controller注解,实现ResponseBodyAdvice接口,并重写其方法。

@RestControllerAdvice
public class MyResponseAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
        //返回true则表示对之前的数据进行重写,才会调用下面的beforeBodyWrite方法,若传入false则反之。
    }
 
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
       //此处也可以设置为别的格式
        HashMap<String,Object> res = new HashMap<>();
        res.put("data",body);
        res.put("state",1);
        res.put("msg","");
        return res;
    }
}

UserController类的test方法如下:

@RequestMapping("/test")
    public String test(){
       return "hello";
    }

访问test:

也可以设置为别的数据格式:

@Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
       //此处也可以设置为别的格式
        return body;
    }

再次访问:

 

目录
相关文章
|
2月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
61 1
|
1月前
|
XML Java 数据格式
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
本文介绍了如何使用Spring框架的注解方式实现AOP(面向切面编程)。当目标对象没有实现接口时,Spring会自动采用CGLIB库进行动态代理。文中详细解释了常用的AOP注解,如`@Aspect`、`@Pointcut`、`@Before`等,并提供了完整的示例代码,包括业务逻辑类`User`、配置类`SpringConfiguration`、切面类`LoggingAspect`以及测试类`TestAnnotationConfig`。通过这些示例,展示了如何在方法执行前后添加日志记录等切面逻辑。
85 2
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
|
1月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
58 2
|
5月前
|
缓存 监控 安全
AOP则关注如何将那些影响多个类的功能模块化
AOP则关注如何将那些影响多个类的功能模块化
|
2月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
46 13
|
5月前
|
缓存 监控 安全
在 Spring Boot 中使用 AOP(Aspect-Oriented Programming)实现日志记录功能
在 Spring Boot 中使用 AOP(Aspect-Oriented Programming)实现日志记录功能
290 1
|
5月前
|
Java Spring
实现AOP(Aspect-Oriented Programming)以及其他功能
实现AOP(Aspect-Oriented Programming)以及其他功能
20 1
|
6月前
|
XML Java 数据格式
使用Spring AOP添加统计时间的功能
使用Spring AOP添加统计时间的功能
|
Java API 数据安全/隐私保护
一张思维导图带你学会SpringBoot使用AOP实现日志管理功能
一张思维导图带你学会SpringBoot使用AOP实现日志管理功能
169 0
|
Java Spring
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
143 0