Spring boot AOP(切面)使用方法和解析

最近开始实习,终于有时间写博客了。因为需要使用springboot,大三学Oracle数据库的时候使用过springboot,之前没怎么用java写网页后台,发现网上很多的博客要不就是复制粘贴,要不就是存在默认知识现象(就是跳过了很多以为新人懂而新人不懂的东西)。AOP的简单的应用例子很少,所以在本章会用很多代码例子和结果来说明,当然我尽量除掉默认知识现象。

目录

MAVEN 基本介绍(懂的跳过)

Spring boot 基本介绍(懂的跳过)

简介

文档和结构

例子1

例子2

正题:AOP使用

基本情况

@Pointcut

@annotation

在拦截器的拦截方法中获取session


MAVEN 基本介绍(懂的跳过)

maven百度就能查到,是通过pom.xml快速下载依赖jar包的工具。在IDEA或者eclipse或者Spring Tool Suite(简写STS,首字母)这三款开发工具(高级记事本)新建maven项目就会有pom.xml在项目根目录生成。我用的IDEA

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
<!-- 以下是当前项目(项目名,包名等,maven生成的是jar包还是war包)的设置 -->
	<groupId>com.JieShao</groupId>
	<artifactId>evm</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>evm</name>
	<description>ElectricVehicleManagement</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
<!-- 这里就是依赖了,因为我这个是是用了Springboot,所以包了很多jar -->
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.15</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
<!-- 创建工具 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

pom.xml是maven项目核心,编辑保存后他会自动下载<dependency></dependency>标签里的jar包并导入到项目里

项目截图

Spring boot 基本介绍(懂的跳过)

我们进Spring boot官网https://spring.io/projects/spring-boot,百度就查到了

简介

Spring boot是一个快速构建spring项目的项目,依赖于Maven,可以看做一个在Maven下的Spring工具包(Jar包集)。

只要在Maven的pom.xml中增加

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
<dependencies>
		<!-- 依赖的jar包 -->
	</dependencies>

这就是Springboot项目了,这个配置是什么意思呢,配置repository(仓库)的目录。Maven一般会在当前用户的文件夹里创建jar包的仓库,把需要的依赖全部下载到里面。我们进入那个目录看看

比如我需要使用Spring的AOP(我的项目的完整配置在Maven简介里)

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

就是这个了,spring-boot-starter-aop,我的已经下载好了,下载好一次,只要不删除就不用重复下载。

文档和结构

Spring Framework是Springboot的核心了,Spring Data是数据存储方面的,里面是一些数据库工具的文档,这些要使用都要在pom.xml里包含它的jar包的。

例子1

比如我不知道怎么使用MongoDB,这个肯定是扩展包,那门首先我得知道这个是数据方面的于是我们打开Spring Data,发现这是个菜单。那么我们看看他有什么列表

先看看JPA有没有MongoDb

文档太长了 使用浏览器自带的查找一般是ctrl+f

找到了,建议还是去Spring Data Mongo 看吧,JPA只有10个关键字,应该只是提及

没错了JPA and Spring Data Mongo,他们文档分开的

当然是看最新的啦

然后就看文档咯

例子2

从代码找注解的文档

这是一个Spring boot + MongoDB的简单项目,这是一个管理员的控制器

假如PostMapping注解我不会用,怎么办呢

我们去看看他在哪个包里

没有找到PostMapping啊

我们利用代码提醒,先删掉.*,再.PostMapping

没打完已经出来了,没错他就是藏在这里了,我们来猜猜它的文档叫啥

猜一下Spring Web Bind有没有

没有这个包,你想想,肯定在核心里啊,Spring MVC,控制器中的Post方法,不是核心是什么

然后懒得看那么长,惯例查找@PostMapping

正题:AOP使用

基本情况

ManagerController的所有方法都写好了

先贴全的代码,因为使用了Mongo数据库,一个类肯定是运行不起来的

package com.jieshao.evm.Controller;

import com.alibaba.fastjson.JSON;
import com.jieshao.evm.Empty.Manager;
import com.jieshao.evm.Empty.User;
import com.jieshao.evm.Repository.ManagerRepository;
import com.jieshao.evm.Repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController//表示这个是一个回答控制器,能直接返回类,处理成Json
@RequestMapping(value = "/api/manager")//这个控制器的根路径
public class ManagerController {
    @Autowired
    private ManagerRepository managerRepository;
    //对应芒果DB的Manager表的持久仓库
    @Autowired
    private UserRepository userRepository;
    @Resource
    private MongoTemplate mongoTemplate;
    //这个用于直接用MongoDb语法,因为仓库我现在搞不定ID先通过方法Update
    //*****************登录模块*****************************************
    @PostMapping("/login")
    public String login(HttpSession session,@RequestParam String username,@RequestParam String password){
        if (managerRepository.count()==0){//如果没有用户那么创建一个初始账户
            managerRepository.save(new Manager("admin", "123456"));
        //DigestUtils.md5DigestAsHex()md5加密
        }
        Manager manager=managerRepository.findByusername(username);
        Map result = new HashMap<String, String>();
        if (manager.getPassword().equals(password)){
            session.setAttribute("username",username);
            session.setAttribute("power",username);

            result.put("errno", "0");
            result.put("errmsg", "登录成功");
            return JSON.toJSONString(result);
        }else{
            result.put("errno", "-1");
            result.put("errmsg", "登录失败,检查用户名和密码");
            return JSON.toJSONString(result);
        }
    }
    //显示登录用户信息
    @GetMapping("/login")
    public String logininfo(HttpSession session){
        if (session.getAttribute("username")==null){//没有登录
            Map result = new HashMap<String,String>();
            result.put("errno","-1");
            result.put("errmsg","管理用户未登录");
            return JSON.toJSONString(result);
        }else{
            Manager manager=managerRepository.findByusername(session.getAttribute("username").toString());
            manager.setPassword("");
            return  JSON.toJSONString(manager);
        }
    }

    //注销用户信息
    @GetMapping("/login/logout")
    public String loginout(HttpSession session){
        if (session.getAttribute("username")==null) {//没有登录
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理用户未登录");
            return JSON.toJSONString(result);
        }else {
            session.removeAttribute("username");
            session.removeAttribute("errmsg");
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "管理用户成功注销");
            return JSON.toJSONString(result);
        }
    }

    //***************对管理员进行操作*****************************************************
    @GetMapping("/manager/all")//查看所有
    //public String managerlistbypage(@RequestParam(value = "page",defaultValue = "0") Integer page,@RequestParam(defaultValue = "15") Integer size){
    public List<Manager> managerlist(){
        return managerRepository.findAll();
    }
    @GetMapping("/manager/search/{username}")//查找一个
    public Manager findmanager(@PathVariable String username){
        return managerRepository.findByusername(username);
    }
    @GetMapping("/manager/")//分页查看
    //public String managerlistbypage(@RequestParam(value = "page",defaultValue = "0") Integer page,@RequestParam(defaultValue = "15") Integer size){
    public Page<Manager> managerlistbypage(@PageableDefault(sort = "username")Pageable pageable){
        return managerRepository.findAll(pageable);
    }
    @PostMapping(path = "/manager/add",consumes = "application/json")//增加
    public String addmanager(@RequestBody Manager manager){
        if (managerRepository.findByusername(manager.getUsername())==null){
            managerRepository.save(manager);
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "成功添加管理员"+manager.getUsername());
            return JSON.toJSONString(result);
        }else{
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员已存在"+manager.getUsername());
            return JSON.toJSONString(result);
        }
    }
    @PostMapping("/manager/update")//更新用户
    public String updatemanager(@RequestBody Manager manager){
        if (managerRepository.findByusername(manager.getUsername())==null){
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员不存在"+manager.getUsername());
            return JSON.toJSONString(result);
        }else{
            Map result = new HashMap<String, String>();
            Query query = new Query(Criteria.where("username").is(manager.getUsername()));
            Update update = new Update();
            update.set("username", manager.getUsername());
            update.set("password", manager.getPassword());
            update.set("power", manager.getPower());
            mongoTemplate.updateFirst(query,update,Manager.class);
            //managerRepository.saveByusername(manager);
            result.put("errno", "0");
            result.put("errmsg", "成功更新管理员"+manager.getUsername());
            return JSON.toJSONString(result);
        }
    }
    @GetMapping("/manager/delete/{username}")//删除用户
    public String deletemanager(@PathVariable String username){
            if(managerRepository.deleteByusername(username)!=0){
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "成功删除管理员"+username);
            return JSON.toJSONString(result);
        } else{
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员不存在"+username);
            return JSON.toJSONString(result);
        }
    }
}

出于试验我们简化一下

import org.springframework.web.bind.annotation.*;

@RestController//表示这个是一个回答控制器,能直接返回类,处理成Json
@RequestMapping(value = "/api/manager")//这个控制器的根路径
public class ManagerController {
    //*****************登录模块*****************************************
    @PostMapping("/login")//post的路径(完整的URL是/api/manager/login)
    public String login(@RequestParam String username,@RequestParam String password){//接收两个post字段
            System.out.println("run");//便于知道什么时候运行了login方法
            return "{\"errno\":\"0\",\"errmsg\":\"登陆成功\"}";//返回json
    }
}

主要就是Post username 和 password到http://localhost:8080(Spring boot项目的配置文件resource/appliction.properties里规定的端口,当前server.port=8080)/api/manager/login返回一个登录成功的Json。

@Pointcut

然后我们开始拦截这个 public String login(@RequestParam String username,@RequestParam String password)方法,我们要在他执行之前和之后干点什么

新建一个Aspect(方向(切面))类

LoginAspect.java

package com.jieshao.evm.AOP;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect//切面注解
@Component//构成
public class LoginAspect
{
    //设置在ManagerController的login方法的切点
    @Pointcut("execution(public * com.jieshao.evm.Controller.ManagerController.login(..))")
    public void login(){//切点映射,命名不规定
        System.out.println("aspect");
    }
    //在本类的login执行之前
    @Before("login()")
    public void beforelogin()
    {
        System.out.println("before");
    }
    //在本类的login执行之后执行
    @After("login()")
    public void afterlogin(){System.out.println("after");}
}

最核心的就是@Pointcut("execution(public * com.jieshao.evm.Controller.ManagerController.login(..))"),什么意思呢,我们要切的方法叫什么呢,我们看看要拦截的方法

不就是public * com.jieshao.evm.Controller.ManagerController.login(..))么

具体的execution表达式我就不多赘述了,传送门https://blog.csdn.net/u012887385/article/details/54600706

结果

注意LoginAspect.login()方法中的输出没有输出来

package com.jieshao.evm.AOP;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component//不加的话识别不了表达式
public class LoginAspect
{
    //Before就是在函数运行之前
    @Before("execution( public String com.jieshao.evm.Controller.ManagerController.login(javax.servlet.http.HttpSession,String,String))")
    public void beforelogin()
    {
        System.out.println("before");
    }
}

这样精确的表述也是可以的

@annotation

要做登录拦截的话,我使用@annotation

创建一个自定义注解

NeedManagerPower.java

/**
 * 用户登录检测
 */
public @interface NeedManagerPower {

}

然后在拦截器对所有打上这个注解的函数进行拦截

package com.jieshao.evm.AOP;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoginAspect
{
    //@Around是在函数运行的之前和之后,能决定是否运行函数
    @Around("@annotation(NeedManagerPower)))")
    public void checklogin()
    {
        System.out.println("around");
    }
}

现在将所有需要登录的权限全打上我们的自定义注解@NeedManagerPower

import org.springframework.web.bind.annotation.*;

@RestController//表示这个是一个回答控制器,能直接返回类,处理成Json
@RequestMapping(value = "/api/manager")//这个控制器的根路径
public class ManagerController {
    //*****************登录模块*****************************************
    @NeedManagerPower//自定义的注解
    @PostMapping("/login")//post的路径(完整的URL是/api/manager/login)
    public String login(@RequestParam String username,@RequestParam String password){//接收两个post字段
            System.out.println("run");//便于知道什么时候运行了login方法
            return "{\"errno\":\"0\",\"errmsg\":\"登陆成功\"}";//返回json
    }

        //显示登录用户信息
    @GetMapping("/login")
    @NeedManagerPower
    public String logininfo(HttpSession session){
        if (session.getAttribute("username")==null){//没有登录
            Map result = new HashMap<String,String>();
            result.put("errno","-1");
            result.put("errmsg","管理用户未登录");
            return JSON.toJSONString(result);
        }else{
            Manager manager=managerRepository.findByusername(session.getAttribute("username").toString());
            manager.setPassword("");
            return  JSON.toJSONString(manager);
        }
    }
    
}

这样打上注解的就会被拦截

在拦截器的拦截方法中获取session

在拦截器的拦截方法中获取session(session是用来做登录验证的),我用的是(HttpSession session),可以看做是一个缓存在客户机(cookieid(用于标识哪个session))和服务器上(Session)对应每个客户端和服务器的一个变量的集,存的方法session.setAttribute("关键字","值"),取session.getAttribute("关键字")。session应用于单个浏览器和服务器之间。

 public String checklogin(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpSession session= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        if (session.getAttribute("username")!=null){
            if(session.getAttribute("power").equals(KeyWord.MANAGER_ROOT)) {
                //通过登录和权限检测
                //正常运行
                return (String)joinPoint.proceed();
            }else{
                return "{\"errno\":\"-2\",\"errmsg\":\"管理员权限不足\"}";
            }
        }else{
            return "{\"errno\":\"-1\",\"errmsg\":\"管理员未登录\"}";
        }
    }

这就是登陆验证了,session通过RequestContextHolder来获取需要注意的是1.JoinPoint.proceed就是执行打上断点的函数返回的是Object(所有类的父类),2.打上断点的方法最好返回值统一,像我的控制器中的方法返回的全是String,因为JoinPoint映射的就是打上断点的函数,JoinPoint的返回值就是断点函数的返回值,如果不统一五花八门,那么转换会很麻烦。3.万能的类转JSON类型String需要jar包依赖。

<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.15</version>
		</dependency>

下面贴上完整的登陆验证程序

控制器ManagerController

package com.jieshao.evm.Controller;

import com.alibaba.fastjson.JSON;
import com.jieshao.evm.AOP.NeedManagerPower;
import com.jieshao.evm.Empty.Manager;
import com.jieshao.evm.Empty.User;
import com.jieshao.evm.KeyWord;
import com.jieshao.evm.Repository.ManagerRepository;
import com.jieshao.evm.Repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController//表示这个是一个回答控制器,能直接返回类,处理成Json
@RequestMapping(value = "/api/manager")//这个控制器的根路径
public class ManagerController {
    @Autowired
    private ManagerRepository managerRepository;
    //对应芒果DB的Manager表的持久仓库
    @Autowired
    private UserRepository userRepository;
    @Resource
    private MongoTemplate mongoTemplate;
    //这个用于直接用MongoDb语法,因为仓库我现在搞不定ID先通过语句Update
    //*****************登录模块*****************************************
    @PostMapping("/login")
    public String login(HttpSession session,@RequestParam String username,@RequestParam String password){
        if (managerRepository.count()==0){//如果没有用户那么创建一个初始账户
            managerRepository.save(new Manager("admin", "123456",KeyWord.MANAGER_ROOT));
        //DigestUtils.md5DigestAsHex()md5加密
        }
        Manager manager=managerRepository.findByusername(username);
        Map result = new HashMap<String, String>();
        if (manager.getPassword().equals(password)){
            session.setAttribute("username",username);
            session.setAttribute("power",manager.getPower());

            result.put("errno", "0");
            result.put("errmsg", "登录成功");
            return JSON.toJSONString(result);
        }else{
            result.put("errno", "-1");
            result.put("errmsg", "登录失败,检查用户名和密码");
            return JSON.toJSONString(result);
        }
    }
    //显示登录用户信息
    @GetMapping("/login")
    public String logininfo(HttpSession session){
        if (session.getAttribute("username")==null){//没有登录
            Map result = new HashMap<String,String>();
            result.put("errno","-1");
            result.put("errmsg","管理用户未登录");
            return JSON.toJSONString(result);
        }else{
            Manager manager=managerRepository.findByusername(session.getAttribute("username").toString());
            manager.setPassword("");
            return  JSON.toJSONString(manager);
        }
    }

    //注销用户信息
    @GetMapping("/login/logout")
    public String loginout(HttpSession session){
        if (session.getAttribute("username")==null) {//没有登录
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理用户未登录");
            return JSON.toJSONString(result);
        }else {
            session.removeAttribute("username");
            session.removeAttribute("errmsg");
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "管理用户成功注销");
            return JSON.toJSONString(result);
        }
    }

    //***************对管理员进行操作*****************************************************
    @GetMapping("/manager/all")//查看所有
    @NeedManagerPower
    //public String managerlistbypage(@RequestParam(value = "page",defaultValue = "0") Integer page,@RequestParam(defaultValue = "15") Integer size){
    public String managerlist(){
        return JSON.toJSONString(managerRepository.findAll());
    }

    @GetMapping("/manager/search/{username}")//查找一个
    @NeedManagerPower
    public String findmanager(@PathVariable String username){
        return JSON.toJSONString(managerRepository.findByusername(username));
    }

    @GetMapping("/manager/")//分页查看
    @NeedManagerPower
    //public String managerlistbypage(@RequestParam(value = "page",defaultValue = "0") Integer page,@RequestParam(defaultValue = "15") Integer size){
    public String managerlistbypage(@PageableDefault(sort = "username")Pageable pageable){
        return JSON.toJSONString(managerRepository.findAll(pageable));
    }

    @NeedManagerPower
    @PostMapping(path = "/manager/add",consumes = "application/json")//增加
    public String addmanager(@RequestBody Manager manager){
        if (managerRepository.findByusername(manager.getUsername())==null){
            managerRepository.save(manager);
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "成功添加管理员"+manager.getUsername());
            return JSON.toJSONString(result);
        }else{
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员已存在"+manager.getUsername());
            return JSON.toJSONString(result);
        }
    }

    @PostMapping("/manager/update")//更新用户
    @NeedManagerPower
    public String updatemanager(@RequestBody Manager manager){
        if (managerRepository.findByusername(manager.getUsername())==null){
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员不存在"+manager.getUsername());
            return JSON.toJSONString(result);
        }else{
            Map result = new HashMap<String, String>();
            Query query = new Query(Criteria.where("username").is(manager.getUsername()));
            Update update = new Update();
            update.set("username", manager.getUsername());
            update.set("password", manager.getPassword());
            update.set("power", manager.getPower());
            mongoTemplate.updateFirst(query,update,Manager.class);
            //managerRepository.saveByusername(manager);
            result.put("errno", "0");
            result.put("errmsg", "成功更新管理员"+manager.getUsername());
            return JSON.toJSONString(result);
        }
    }

    @NeedManagerPower
    @GetMapping("/manager/delete/{username}")//删除用户
    public String deletemanager(@PathVariable String username){
            if(managerRepository.deleteByusername(username)!=0){
            Map result = new HashMap<String, String>();
            result.put("errno", "0");
            result.put("errmsg", "成功删除管理员"+username);
            return JSON.toJSONString(result);
        } else{
            Map result = new HashMap<String, String>();
            result.put("errno", "-1");
            result.put("errmsg", "管理员不存在"+username);
            return JSON.toJSONString(result);
        }
    }
}

自定义注解NeedManagerPower

package com.jieshao.evm.AOP;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

/**
 * 用户登录检测
 */
public @interface NeedManagerPower {

}

拦截器LoginAspect

package com.jieshao.evm.AOP;

import com.jieshao.evm.KeyWord;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpSession;

@Aspect
@Component
public class LoginAspect
{
    /**
     * 策略一,在所有的自定义注解NeedManagetPower方法上打断点
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("@annotation(NeedManagerPower)))")

    /**
     * 策略二,将整个ManagerController除了Public String login()方法全打上切面
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    //@Around("within(com.jieshao.evm.Controller.ManagerController)&&!execution(public String com.jieshao.evm.Controller.ManagerController.login(..))")
    public String checklogin(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpSession session= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        if (session.getAttribute("username")!=null){
            if(session.getAttribute("power").equals(KeyWord.MANAGER_ROOT)) {
                //通过登录和权限检测
                //正常运行
                return (String)joinPoint.proceed();
            }else{
                return "{\"errno\":\"-2\",\"errmsg\":\"管理员权限不足\"}";
            }
        }else{
            return "{\"errno\":\"-1\",\"errmsg\":\"管理员未登录\"}";
        }
    }
}

跑起来后的逻辑是这样的,浏览器访问需要登录检测的URL,服务器检测到访问的是打上checklogin断点的方法,那么进入到checklogin并把原来的函数映射为joinPoint,获取session进行验证,1如果验证通过,joinPoint.proceed()执行原来打上断点的方法并返回原来方法的返回值,checklogin再返回;2如果不通过,不执行原来方法,返回JSONString。

  • 56
    点赞
  • 189
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
Spring Boot切面(Aspect)是Spring AOP(面向切面编程)的一个基本概念。切面允许你定义一段代码,这段代码通常被称为“通知”(Advice),并在程序的特定时间点执行。这个特定的时间点被称为“切点”(Pointcut)。通过这种方式,你可以在不影响应用程序主要功能的情况下,对应用程序的特定行为进行增强。 Spring Boot切面的主要组成部分包括: 1. 通知(Advice):这是切面的核心部分,它定义了要在哪个方法调用前后执行哪些代码。通知可以是前置通知(Before advice)、后置通知(After advice)、返回通知(AfterReturning advice)、异常通知(Throwing advice)或环绕通知(Around advice)。 2. 切点(Pointcut):这是定义通知何时执行的关键部分。切点可以匹配特定的方法、类、包或任何其他特定的条件。 3. 切面定位器(Pointcut Scanning):Spring Boot支持基于类路径扫描的自动配置,自动识别切面类,并将它们注册到Spring的IoC容器中。 4. 代理(Proxy):当Spring容器处理对象时,它会在对象的类上创建一个代理对象。这个代理对象包含了所有定义在切面中的通知,并在实际方法调用前后执行这些通知。 使用Spring Boot切面,你可以实现诸如日志记录、权限验证、性能优化、事务管理、安全拦截等常见功能。通过将这些功能封装在切面中,你可以轻松地在应用程序中复用这些功能,而无需修改应用程序的主要代码。 以下是一个简单的Spring Boot切面示例: ```java @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.myapp.MyClass.myMethod(..))") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("About to execute method: " + joinPoint.getSignature().getName()); } } ``` 在这个例子中,我们定义了一个名为`LoggingAspect`的切面,它包含一个名为`beforeAdvice`的前置通知。这个通知会在`com.example.myapp.MyClass`类的`myMethod`方法被调用之前执行。 这只是Spring Boot切面的基础用法,实际上它提供了非常强大的功能,可以用于实现各种复杂的业务逻辑和功能增强。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值