Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合

接着上一次Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<三>--Vue3 + Vue CLI 项Vue3 + Vue CLI 项目搭建目搭建的继续往下学习,这次的目标就是前后端进行功能的联调了。

集成HTTP库Axios:

简述:

对于Vue前端来说,需要发起后台的请求来拿到相关的数据进行前后端的联调,通常都会借用三方的库来进行网络请求,这里也不例会,会用Axios这个HTTP库,先上官网了解一下它Axios:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第1张图片

看一下它的github的star,就知道有多有名:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第2张图片

安装:

所以接下来咱们将它安装到咱们的工程中:

npm install [email protected] --save

其中指定的0.21.0不是如今最新的版本,是为了跟课程的版本保持一致,这样可以保证学习的节奏不会受版本的影响,执行一下:

(base) localhost:web xiongwei$ npm install [email protected] --save
npm WARN deprecated [email protected]: Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410
+ [email protected]
added 1 package from 1 contributor in 13.41s

127 packages are looking for funding
  run `npm fund` for details

此时则可以看到添加了相关的依赖了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第3张图片

体验请求:

接下来则来使用一下这个库,来将咱们后台电子书的列表数据给拉取下来:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第4张图片

其中setup是Vue3新增的初始化的方法,当组件加载完之后,初始执行的地方,而测试的地址刚好就是我们之前写后端测试用例时用到的:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第5张图片

好,接下来咱们启动一下咱们的服务端,然后执行看一下是否能正常请求到后端的数据:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第6张图片

报错了。。“Access-Control-Allow-Origin”,这个就是最常见的跨域问题,那什么叫跨域呢?通俗点说其实就是后端不信任前端,其中从日志中也能看出:

所以后端就会把前端的这次请求给拦截掉,跨域可以这样理解:来自一个ip端口的页面(Vue项目),要访问另一个ip端口的资源(springboot请求接口),则会产生跨域访问,所有前后端分离的项目都会存在跨域访问的问题。

解决跨域问题:

要想解决跨域问题,需要在后端增加这么一个配置类:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第7张图片

package com.cexo.wiki.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//解决跨域问题
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedHeaders(CorsConfiguration.ALL)
                .allowedMethods(CorsConfiguration.ALL)
                .allowCredentials(true)
                .maxAge(3600); // 1小时内不需要再预检(发OPTIONS请求)
    }

}

其中:
addMapping:映射的请求地址,/**表示针对所有的接口,比如目前的ebook接口。

allowedOriginPatterns:允许来源。

allowedHeaders:允许所有的头信息。

allowedMethods:允许所有的请求方式,如GET、POST等。

allowCredentials:允许前端带上凭证,如带上它的cookie信息等,

maxAge: 配置预检的时间,啥叫预检呢?在调用电子书接口之前,前端会偷偷发一个OPTIONS请求,这个请求它是不会处理业务逻辑的,它只是检查一下该接口是否存在、是否正常,只有预检成功了才会真正发起接口的请求,而配置3600的意思是如果成功发送OPTIONS请求之后,1小时之内则就不再发OPTIONS请求了。

配置了跨域请求之后,重启再来运行一下,就正常了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第8张图片

成功解决。

Vue3数据绑定显示列表数据:

概述:

数据双向绑定是Vue的核心功能,前端拿到后端的数据之后,要把它展示到页面上, 

Vue2代码结构示例:

在正式学习Vue3的数据绑定之前,先来大概了解一下Vue2的数据绑定的结构:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第9张图片

而这些数据会被用在界面上:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第10张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第11张图片

而其中它是调用了list()方法进行数据的获取,具体这个方法的定义是在另外一个methods中:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第12张图片

有木有发现,数据定义是在data里,而它数据的赋值是在methods的方法调用中进行,但是!!!到了Vue3之后,data、mounted、methods这三个方法合成了一个了,就是之前咱们已经见过的setup方法:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第13张图片

所以接下来对它进行一个了解。

Vue3的setup()生命周期方法了解:

在setup中,像Vue2中的mounted也有类似的,这样写写:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第14张图片

这里为了看执行顺序,我们在onMounted中加入一个日志:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第15张图片

运行看一下:

使用Vue3 ref实现数据绑定:

接下来咱们则将查出来的数据渲染到界面上,怎么做呢?当然先解析请求回来的数据:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第16张图片

而content节点才是我们想要的电子书的列表数据:
 

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第17张图片

那么我们解析这个列表数据之后,如何显示在页面上呢?这里就需要使用到Vue3中的ref来实现数据绑定了,具体看一下的写法:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第18张图片

其中ref在Vue3中就是用来定义响应式数据用的,最后还有一个注意点,就是需要将数据从setup方法中return出去,这样html才能拿到响应式的变量,如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第19张图片

这时运行看一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第20张图片

使用Vue3 reactive实现数据绑定:

除了上面这种ref()实现数据的绑定之外,还有另外一种,使用reactive,它相对而言稍麻烦一些,如下:

此时运行发现也能正常显示出来:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第21张图片

总结:

关于ref和reactive这两种绑定数据的方式,可以任选其一,不过通常在一个项目使用一种既可,我们这里使用稍简单一点的ref来进行界面数据的绑定了。

电子书列表界面展示:

找Ant Design Vue现成的组件:

现在咱们已经可以成功的将后端的列表数据展现在h5界面上了,但是样式不对,接下来咱们上Ant Design Vue中来找相关的列表组件样式:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第22张图片

往下拉可以找到这么一个列表样式:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第23张图片

其中分页效果也已经有了,我们可以基于它来进行改造。

将Ant Design Vue样式集成到工程中:

接下来我们拷贝一下代码,将其弄到我们的vue页面中,整个Home.vue的代码如下:



其中主要是改了这几块,代码是原封不动的从Ant Design Vue中来拷贝的:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第24张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第25张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第26张图片

此时预览一下效果:

效果还挺赞的。

解决图标显示不出的问题:

对于目前集成的效果中,有一个样式上的问题,就是对于这块的图标木有显示出来:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第27张图片

看看目前长的样子:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第28张图片

接下来解决它,其实是因为我们没有安装图标库,从官网了解一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第29张图片

所以安装一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第30张图片

此时在package.json中就多了这么一个依赖了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第31张图片

接下来则需要将图标导入进来,具体如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第32张图片

这样图标就可以正常的显示了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第33张图片

删除多余的列表元素:

接下来将界面上不需要的元素给删除,首先是这两块:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第34张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第35张图片

将其删掉:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第36张图片

预览一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第37张图片

接下来将这两块去掉:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第38张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第39张图片

将其删掉:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第40张图片

再预览一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第41张图片

将列表数据按组件样式显示在界面上:

接下来则将改一下数据源,改成咱们的电子书列表,如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第42张图片

此时咱们不可以把Ant Design Value拷过来的假数据源代码给去掉了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第43张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第44张图片

预览看一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第45张图片

配置列表一行显示三个电子书:

目前一行只显示一个,咱们需要配置一下,比较简单:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第46张图片

目前由于接口请求只返回了一条数据,所以为了看到效果,咱们将接口请求的条件去掉一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第47张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第48张图片

此时接口就需要更改了,也比较简单:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第49张图片

热部署一下,此时再预览效果就可以看到了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第50张图片

修改图标的样式:

最后咱们来修改一下图标的样式,通过开发者工具可以看到它的css标识:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第51张图片

所以css样式可以这样写:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第52张图片

.ant-avatar {
  width: 50px;
  height: 50px;
  line-height: 50px;
  border-radius: 8%;
  margin: 5px 0;
}

再预览一下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第53张图片

Vue CLI多环境配置:

多环境配置:

目前咱们有一个细节问题,就是我们在请求接口时,其baseUrl是写死的:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第54张图片

通常应该是需要区分环境动态配置的,比如测试和线上两个环境,在Vue中对于环境的配置很简单,比如先配置开发环境,新建".env.dev"这么一个文件:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第55张图片

接下来再来配置一下正式环境:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第56张图片

线上环境是随意写的,我也没有真正的云服务器,这里仅是功能测试用。目前我们启动的命令中没有区分环境:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第57张图片

接下来则需要改造一下,让其在打包编译时能够根据环境来:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第58张图片

接下来为了测试,通过日志打印来验证一下是否多环境配置生效了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第59张图片

先来编译开发环境,然后刷新一下界面,此时到控制台上看一下日志输出:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第60张图片

然后再编译正式环境,再刷新界面看日志输出:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第61张图片

Vue CLI修改启动端口:

对于Vue项目的编译启动后,其默认的端口号是8080对吧:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第62张图片

那如果想要更改端口号咋改呢?其实很简单,修改编译启动命令:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第63张图片

再启动,端口号就变了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第64张图片

这里我们还是将其改回到8080。

axios增加baseUrl:

目前多环境已经配置好了,但是还木有用到请求接口上,咱们来将baseUrl给改活,如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第65张图片

另外还有一个优化的空间,就是每一次接口请求都需要加这个baseUrl,而baseUrl是不会变的,那么,有木有axios有木有一个全局配置baseUrl的地方从而可以让我们在写请求地址时就不用拼baseUrl了?答案是有的,如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第66张图片

此时我们在写请求时就方便多了,直接:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第67张图片

使用Axios拦截器打印前端日志:

对于前端接口的访问,为了方便调试,我们需要将请求的入参及出参打印出来,如果每个接口加那太繁锁了,所以此时可以用到Axios的拦截器功能,而具体接口日志的日志打印的代码也不需要手敲,直接拷贝用就可以了:

// axios拦截器
axios.interceptors.request.use(function (config) {
    console.log('请求参数:', config);
    return config;
}, error => {
    console.log('请求错误:', error);
    return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
    console.log('返回结果:', response);
    return response;
}, error => {
    console.log('返回错误:', error);
    return Promise.reject(error);
});

将它放到main.ts中【是不是只要涉及到全局通用的配置都得有到这个文件?】:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第68张图片

好,接下来测试一下效果,由于已经有了reponse的拦截日志打印,所以我们可以将这块的打印给去掉了:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第69张图片

编译运行:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第70张图片

SpringBoot过滤器的使用:

接下来则需要学习一些SpringBoot非常有用的功能,第一个是过滤器,用它可以打印接口的耗时情况,具体使用如下:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第71张图片

其具体的代码:

package com.cexo.wiki.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
public class LogFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 打印请求信息
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        LOG.info("------------- LogFilter 开始 -------------");
        LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("远程地址: {}", request.getRemoteAddr());

        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        LOG.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
    }
}

其中看到了一个当年学习java web的身影了,还是很亲切的:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第72张图片

接下来编译,然后测试一下效果:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第73张图片

SpringBoot拦截器的使用:

接下来再来学习一个拦截器的功能,其实验效果也是打印接口耗时,感受一下它跟filter的不同,先新建一个拦截器类:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第74张图片

package com.cexo.wiki.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器:Spring框架特有的,常用于登录校验,权限校验,请求日志打印
 */
@Component
public class LogInterceptor implements HandlerInterceptor {

    private static final Logger LOG = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 打印请求信息
        LOG.info("------------- LogInterceptor 开始 -------------");
        LOG.info("请求地址:{} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("远程地址:{}", request.getRemoteAddr());

        long startTime = System.currentTimeMillis();
        request.setAttribute("requestStartTime", startTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        long startTime = (Long) request.getAttribute("requestStartTime");
        LOG.info("------------- LogInterceptor 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
    }
}

其中有木有感受到跟filter的区别?拦截器中木有涉及到业务代码的调用,回忆一下之前学习的filter:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第75张图片

而拦截器完全不需要管业务代码的执行,只有在业务代码执行前和执行后的两个回调中来处理拦截的逻辑:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第76张图片

最后要想让这个拦截器生效,还需要有一个配置类:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第77张图片

重新运行看一下效果:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第78张图片

SpringBoot AOP的使用:

最后再来看一个AOP的效果,说到Spring都会提到它,同样使用AOP来打印接口耗时、请求参数、返回参数,下面来看一下如何来集成。

1、增加依赖:

 
            org.springframework.boot
            spring-boot-starter-aop
        
        
            com.alibaba
            fastjson
            1.2.70
        

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第79张图片

2、添加AOP类:

这块代码也直接copy既可:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第80张图片

package com.cexo.wiki.aspect;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
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.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspect {

    private final static Logger LOG = LoggerFactory.getLogger(LogAspect.class);

    /**
     * 定义一个切点
     */
    @Pointcut("execution(public * com.cexo.*.controller..*Controller.*(..))")
    public void controllerPointcut() {
    }

    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) {

        // 开始打印请求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();

        // 打印请求信息
        LOG.info("------------- 开始 -------------");
        LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name);
        LOG.info("远程地址: {}", request.getRemoteAddr());

        // 打印请求参数
        Object[] args = joinPoint.getArgs();
        // LOG.info("请求参数: {}", JSONObject.toJSONString(args));

        Object[] arguments = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest
                    || args[i] instanceof ServletResponse
                    || args[i] instanceof MultipartFile) {
                continue;
            }
            arguments[i] = args[i];
        }
        // 排除字段,敏感字段或太长的字段不显示
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();
        excludefilter.addExcludes(excludeProperties);
        LOG.info("请求参数: {}", JSONObject.toJSONString(arguments, excludefilter));
    }

    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        // 排除字段,敏感字段或太长的字段不显示
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();
        excludefilter.addExcludes(excludeProperties);
        LOG.info("返回结果: {}", JSONObject.toJSONString(result, excludefilter));
        LOG.info("------------- 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
        return result;
    }

}

3、运行:

接下来运行看一下效果:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第81张图片

4、理解AOP代码:

接下来咱们来熟悉一下这块AOP的代码。

1、@Aspect注解:

要想让此类成为切面,则需要加上这个注解:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第82张图片

2、@Pointcut切点:

定义一个切点:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第83张图片

也就是这里配置的是哪些接口会被这个切面给拦截到,我们这里配置的是所有Controller定义的接口。简单理解这个切点的含义就是针对所有的Controller所有的方法,所有的参数都会进入到这个AOP里面。

3、@Before:

它表示前置通知:

也就是业务代码执行之前需要做的事情就放到这个方法里面,其中AOP跟过滤器有一点不同,就是它拿到的参数是通过这个连接点jointPoint:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第84张图片

通过它,就可以拿到方法中的参数,比如:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第85张图片

另外有一些敏感字段是不应该打印出来的,此时就可以通过这种方式将其过滤掉:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第86张图片

4、@Around: 

环绕通知:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第87张图片

环绕的意思是在接口执行的业务内容的前面执行一点东东,后面执行一点东东,也就是:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第88张图片

有点像过滤器:

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第89张图片

5、切面:

整个切点加上通知(前置通知、环绕通知)就构成了一个切面,也就是Aspect的意思了。

目前过滤器、拦截器、AOP都有接口耗时打印的功能,咱们保留一个既可,这里保留AOP的方式,其它两个暂且可以注释掉。

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第90张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第91张图片

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<四>--前后端交互整合_第92张图片

 关注个人公众号,获得实时推送

你可能感兴趣的:(java后端开发,spring,boot,前端,后端)