若依框架拦截器

拦截器讲解

前端拦截器

前置拦截器

前置拦截器的代码位于request.js文件中,具体路径为:src/utils/request.js
代码展示如下:

// request拦截器
// 其作用就是有一些功能,在从前端向后端发送数据时进行拦截,将数据进行自定义的处理操作,随后再发送给后端
//		即拦截下后,做一些公共操作
// 这里service就是创建的axios实例,由前面的const service = axios.create部分可知
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  // 是否需要防止数据重复提交
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // 1、让每个请求携带自定义token 请根据实际情况自行修改
  }
  // 2、get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    }
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {										 // 3、避免重复提交重复请求
      const s_url = sessionObj.url;                  // 请求地址
      const s_data = sessionObj.data;                // 请求数据
      const s_time = sessionObj.time;                // 请求时间
      const interval = 1000;                         // 间隔时间(ms),小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理,请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
      } else {
        cache.session.setJSON('sessionObj', requestObj)
      }
    }
  }
  return config
}, error => {
    console.log(error)
    Promise.reject(error)
})

 可见request.js文件中有axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'这一句,其作用是对axios发送请求的组件,其含义是在每次发送请求时头部的内容(Content)类型(Type)都设置为此编码格式(application/json;charset=utf-8)
 那么前置拦截器实际上做了哪些事清呢?

  1. 在请求头中添加token(这玩意每个用户都有其token值,相当于权限钥匙串,传到后台后就知道该用户可以完成什么操作)(若依框架是把这个添加token操作放到了公共地方,而不必在每次发请求时都传递一个token,以此提高了代码的利用率)
  2. get请求映射params参数
  3. 阻止重复请求重复提交(这里虽进行了处理,但在后台还是会有接口幂等性校验操作,即后端的不信任前端原则)

响应拦截器

其使用是在后台给前台返回数据,前端在渲染页面之前,进行拦截操作。
代码展示如下:

// 响应拦截器
service.interceptors.response.use(res => {
    // 未设置状态码则默认成功状态(code有值就取值,没值就赋200)
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.msg || errorCode['default']
    // 二进制数据则直接返回
    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
      return res.data
    }
    if (code === 401) {
      if (!isRelogin.show) {
        isRelogin.show = true;
        MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
          isRelogin.show = false;
          store.dispatch('LogOut').then(() => {
            location.href = '/index';
          })
      }).catch(() => {
        isRelogin.show = false;
      });
    }
      return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
    } else if (code === 500) {
      Message({ message: msg, type: 'error' })
      return Promise.reject(new Error(msg))
    } else if (code === 601) {
      Message({ message: msg, type: 'warning' })
      return Promise.reject('error')
    } else if (code !== 200) {
      Notification.error({ title: msg })
      return Promise.reject('error')
    } else {
      return res.data
    }
  },
  error => {
    console.log('err' + error)
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({ message: message, type: 'error', duration: 5 * 1000 })
    return Promise.reject(error)
  }
)

res实际就是后台给前台返回的数据对象
具体应用如图所示:
在这里插入图片描述
{
 其中出现code==500 或 401等时,login.vue中就不会有后面的操作,而是会直接进行弹窗,显示出现的错误。
}

后端拦截器

若依框架中的后端拦截器是用于处理一些公共的判断逻辑

防止重复提交拦截器

(此处与前置拦截器中提到的不信任原则相呼应)
代码展示:

/**
 * 防止重复提交拦截器
 *
 * @author ruoyi
 */
@Component
// 首先明确此为一个抽象类
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
{
	// 这里为前置方法,即前端给后端发的请求都会经过此拦截器
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
    	// 判断该请求是否要请求一个资源或方法
        if (handler instanceof HandlerMethod)
        {
        	// 因为属于HandlerMethod,因而直接进行强转
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 使用getMethod方法获取到的Method这个方法对象就是指 传来的请求给到某个接口的方法
            Method method = handlerMethod.getMethod();
            // 看该method方法上是否有注解(仅能查看是否含有RepeatSubmit注解)(RepeatSubmit是若依自定义的)
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            // 若该方法打了RepeatSubmit注解
            if (annotation != null)
            {
            	// 此isRepeatSubmit方法会通过使用唯一标识(指定key+url+消息头),存入Redis,并在Redis中进行比对,看时间差是否小于5000ms,以此判断是否重复提交,若重复提交会返回true。
                if (this.isRepeatSubmit(request, annotation))
                {
                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
                    return false;
                }
            }
            return true;
        }
        else
        {
        	// 直接放行(请求静态资源时)
            return true;
        }
    }

    /**
     * 验证是否重复提交由子类实现具体的防重复提交的规则
     *
     * @param request
     * @return
     * @throws Exception
     */
    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
}

上述代码中提到的method就是这里的List方法(即method对象代表所请求的整个方法/接口),其中getAnnotation是用来查看是否含有@RepeatSubmit注解的。(至于为何要新建一个RepeatSubmit注解来防止重新提交,而不对所有方法都进行防重提交操作呢:原因为并非所有的方法都会进行提交操作,如此处的List方法,便仅仅是进行查询操作,因而会新建一个注解来对提交的方法进行拦截)
在这里插入图片描述
 当preHandle方法返回false后,通常表示对传递过来的请求进行拦截,并阻止执行后续操作,同时也不会返回响应给前端,使其不会进入到具体的业务逻辑中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值