springboot项目遇到的问题,请求接口时,发现拦截器拦截了两次请求

记录贴-

先说发现:调/user/addUser接口,发现拦截器在拦截request信息显示正常,放行后,却又拦截了一次uri为/error的请求,最后发现是SpringBoot 默认提供了一个全局的 handler 来处理所有的 HTTP 错误, 并把它映射为 /error。当发生一个 HTTP 错误, 例如 404 错误时, SpringBoot 内部的机制会将页面重定向到 /error 中。

解决办法:可以通过拦截器放行/error

registration.excludePathPatterns("/error");

-------------------------分割线--------------------------

我遇到的问题叙述如下图中所示:

通过debug 断点,第一次拦截到的请求,通过getRequestURI()方法,确认当前路径确实为所请求的路径。

放行断点后,竟又拦截到一个请求,通过getRequestURI()方法,看得出这次请求是/error请求

接口调试工具apipost响应的是这样的

<!doctype html>
   <html lang="en">
      <head>
         <title>
            HTTP Status 500 – Internal Server Error
         </title>
         <style type="text/css">
            body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}
         </style>
</head>
      <body>
         <h1>
            HTTP Status 500 – Internal Server Error
         </h1>
</body>
</html>

挺纳闷的,后来上网查了很多资料来找原因,有的说是可能与controller层注解有关系是这么说的:

        1.当一个客户端发出请求访问某个资源,当该资源不存在,springboot默认会重定向到/error路径。/error路径被拦截器拦截。(/error + 你发送的请求=等于两次)。

        2.在Spring MVC控制器类中,当使用@ResponseBody注解时,Spring会将方法的返回值直接写入HTTP响应体中。而如果不加上@ResponseBody注解Spring会尝试将方法作为视图解析,请求到达方法的时候,此时这个方法会被当作视图解析也就是再发送一次请求,找不到这个视图,重定向到/error也会执行一次。(视图解析+ 你发送的请求+/error=等于三次)

我这个问题再通过不断测试后发现:是由于/user/addUser接口在权限校验时报错了,导致调用了/error请求。在去掉权限校验的代码后,就不会出现这样问题了。

之后,我没有选择放行/error,而是加了异常处理层代码,也算是个解决的方法吧

package com.Frame.controller;

import com.Frame.bean.common.Result;
import com.Frame.exception.CustomException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Set;

@ControllerAdvice
public class CustomExceptionController {
    private static final Logger log = LoggerFactory.getLogger(CustomExceptionController.class);

    /**
     * 系统异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result handler(Exception e) {
        //获取异常信息,获取异常堆栈的完整异常信息
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        //日志输出异常详情
        log.error(sw.toString());

        return Result.error(701, "服务异常,请稍候再试");
    }

    /**
     * 自定义异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public Result CustomException(CustomException e) {
        return Result.error(701, e.getErrorMsg());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result handleException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage(), e);
        return Result.error(702,"不支持' " + e.getMethod() + "'请求");
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public Result notFount(RuntimeException e) {
        log.error("运行时异常:", e);
        return Result.error(703,"运行时异常:" + e.getMessage());
    }

    /**
     * 处理校验异常,对于参数类型的数据的校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public Result handler(ConstraintViolationException e) {
        StringBuffer sb = new StringBuffer();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        constraintViolations.forEach(msg -> sb.append(msg.getMessage()).append(";"));
        log.error("get校验方式:" + sb.toString());
        return Result.error(705, sb.toString());
    }


    /**
     * 处理校验异常,对于对象类型的数据的校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result handler(MethodArgumentNotValidException e) {
        StringBuffer sb = new StringBuffer();
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        allErrors.forEach(msg -> sb.append(msg.getDefaultMessage()).append(";"));
        log.error("post校验方式:" + sb.toString());
        return Result.error(707, sb.toString());
    }

    /**
     * 校验异常
     */
    @ExceptionHandler(BindException.class)
    public Result validationExceptionHandler(BindException e) {
        StringBuffer sb = new StringBuffer();
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        allErrors.forEach(msg -> sb.append(msg.getDefaultMessage()).append(";"));
        return Result.error(709, sb.toString());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值