记录贴-
先说发现:调/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());
}
}