SpringBoot-AOP

来源:互联网 发布:linux中文字符乱码 编辑:程序博客网 时间:2024/05/18 01:42

SpringBoot-AOP

使用AOP统一处理请求日志

1.AOP的概念

AOP:AOP是一种编程范式,与语言无关,是一种程序设计思想

面向切面(AOP) Aspect Oriented Programming面向对象(OOP) Object Oriented Programming面向过程(POP) Procedure Oriented Programming

面向过程到面向对象:

功能:下雨了,我打开了雨伞面向过程:假如下雨了,我打开了雨伞面向对象:天气-->下雨;我-->打伞

即:换个角度看世界,换个姿势处理问题

面向对象:关注的是将需求功能垂直划分为不同的并且相对独立的,会封装成良好的类并且让他们有属于自己的行为。面向切面:利用横切的技术,将面向对象构建的庞大的类的体系进行水平的切割,并且将其中会影响到多个类的公共行为封装成一个可重用的模块,该模块就成为切面

AOP的思想:将通用的逻辑从业务逻辑中分离出来

2.实现AOP

网络请求和数据库操作请求:

1.jpg

使用AOP思想:

2.jpg

3.实现使用AOP记录每一个http请求

需求:授权访问(必须先登录才能访问)

第一步:添加依赖:

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

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>    <!--项目的基本描述-->    <groupId>com.hcx</groupId>    <artifactId>girl</artifactId>    <version>0.0.1-SNAPSHOT</version>    <packaging>jar</packaging>    <name>girl</name>    <description>Demo project for Spring Boot</description>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>1.5.6.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>    <dependencies>        <!--web项目必须引入的依赖-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!--单元测试时需要用到的-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-aop</artifactId>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

第二步:编写切面类:

@Aspect@Componentpublic class HttpAspect {    //在http请求到方法之前记录    /**     * @Before注解:在方法执行之前执行     * com.hcx包下的girlcontroller里面的girlList方法,不管是什么参数都会被拦截     * 所有方法都拦截:execution(public * com.hcx.controller.GirlController.*(..))     */    @Before("execution(public * com.hcx.controller.GirlController.girlList(..))")    public void log(){        System.out.println("被拦截了");    }    @After("execution(public * com.hcx.controller.GirlController.girlList(..))")    public void doAfter(){        System.out.println("我是方法执行之后被拦截");    }}

第三步:拦截controller中的方法:

@RestControllerpublic class GirlController {    @Autowired    private GirlRepository girlRepository;    @Autowired    private GirlService girlService;    /**     * 查询所有女生     * @return     */    @GetMapping(value = "/girls")    public List<Girl> girlList(){        System.out.println("我是girlList方法");        return girlRepository.findAll();    }}

运行结果:

3.jpg

4.jpg

注意:以上代码可以看出有重复,在切面类中优化:

HttpAspect:

@Aspect@Componentpublic class HttpAspect {    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class); //该类是org.slf4j的    //在http请求到方法之前记录    /**     * @Before注解:在方法执行之前执行     * com.hcx包下的girlcontroller里面的girlList方法,不管是什么参数都会被拦截     * 所有方法都拦截:execution(public * com.hcx.controller.GirlController.*(..))     */    /*@Before("execution(public * com.hcx.controller.GirlController.girlList(..))")    public void log(){        System.out.println("被拦截了");    }*/    /**     * 公用的方法,使用@Pointcut注解     */    @Pointcut("execution(public * com.hcx.controller.GirlController.girlList(..))")    public void log(){    }    @Before("log()")    public void doBefore(){//        System.out.println("我是方法执行之前被拦截");        logger.info("前日志信息"); //打印info、error等日志    }    @After("log()")    public void doAfter(){//        System.out.println("我是方法执行之后被拦截");        logger.info("后日志信息");    }}

GirlController:

@RestControllerpublic class GirlController {    /**     * getLogger方法中的参数与类名对应     */    private final static Logger logger = LoggerFactory.getLogger(GirlController.class);    @Autowired    private GirlRepository girlRepository;    @Autowired    private GirlService girlService;    /**     * 查询所有女生     * @return     */    @GetMapping(value = "/girls")    public List<Girl> girlList(){//        System.out.println("我是girlList方法");        logger.info("我是girlList方法");        return girlRepository.findAll();    }}

5.jpg

6.jpg

记录http请求:

HttpAspect:

@Aspect@Componentpublic class HttpAspect {    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class); //该类是org.slf4j的    /**     * 公用的方法,使用@Pointcut注解     */    @Pointcut("execution(public * com.hcx.controller.GirlController.girlList(..))")    public void log(){    }    @Before("log()")    public void doBefore(JoinPoint joinPoint){        /**         * 请求路径:url         * 请求方式:method         * 客户端ip:ip         * 请求的是哪个类方法:类方法         * 方法的参数         */        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();        HttpServletRequest request = attributes.getRequest();//注意:选择的HttpServletRequest选的是javax.servlet.http的        //url        logger.info("url={}",request.getRequestURL());        //method        logger.info("method={}",request.getMethod());        //ip        logger.info("ip={}",request.getRemoteAddr());        //getDeclaringTypeName():获取类名,getName:获取类方法        logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());        //方法的参数        logger.info("args={}",joinPoint.getArgs());    }    @After("log()")    public void doAfter(){//        System.out.println("我是方法执行之后被拦截");        logger.info("后日志信息");    }    /**获取返回的内容:     * {     "id": 2,     "cupSize": "B",     "age": 19     }     */    @AfterReturning(returning = "object",pointcut = "log()")    public void doAfterReturning(Object object){        logger.info("response={}",object.toString());    }}

GirlController:

@RestControllerpublic class GirlController {    /**     * getLogger方法中的参数与类名对应     */    private final static Logger logger = LoggerFactory.getLogger(GirlController.class);    @Autowired    private GirlRepository girlRepository;    @Autowired    private GirlService girlService;    /**     * 查询所有女生     * @return     */    @GetMapping(value = "/girls")    public List<Girl> girlList(){//        System.out.println("我是girlList方法");        logger.info("我是girlList方法");        return girlRepository.findAll();    }}

Girl:

@Entity //该注解表示该类在数据库中有对应的表 不用创建该表public class Girl {    @Id    @GeneratedValue    private Integer id;    private String cupSize;    /**     * 给年龄加上限制:年龄必须大于18岁     * value:值     * message:提示信息     */    @Min(value =18,message = "年龄必须大于18岁")    private Integer age;    public Girl() {    }    @Override    public String toString() {        return "Girl{" +                "id=" + id +                ", cupSize='" + cupSize + '\'' +                ", age=" + age +                '}';    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getCupSize() {        return cupSize;    }    public void setCupSize(String cupSize) {        this.cupSize = cupSize;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

7.jpg

原创粉丝点击