1、背景说明
小程序项目中,使用Filter对用户身份认证,用户未登录时,抛出系统自定义异常,系统中有使用全局捕获异常对自定义异常做处理。才测试时候,发现全局异常未生效。经过查询资料,知道其中问题点。
【代码示例:】
- 全局捕获异常
@Component
@ControllerAdvice
public class GlobalExceptionHandler {
@Autowired
@Qualifier("configMessage")
private MessageSource msgSource;
@ResponseBody
@ExceptionHandler(CustomException.class)
public UniformResultTemplate<Object> handleCustomException(CustomException customException) {
if (customException == null) {
return new UniformResultTemplate<>(Code.SYS_ERROR.getCode(), Code.SYS_ERROR.getDesc());
}
String code = StringUtils.isEmpty(customException.getCode()) ? Code.FAIL.getCode():customException.getCode();
return new UniformResultTemplate<>(code, getMessage(customException.getMsg()));
}
@ResponseBody
@ExceptionHandler(Exception.class)
public UniformResultTemplate<Object> handleCustomException(Exception e) {
e.printStackTrace();
if (e instanceof CustomException) {
CustomException exception = (CustomException) e;
return new UniformResultTemplate<>(exception.getCode(), exception.getMsg());
}
return new UniformResultTemplate<>(Code.SYS_ERROR.getCode(), Code.SYS_ERROR.getDesc());
}
// 配置国际化翻译
public String getMessage(String message){
String str = "";
try{
str = msgSource.getMessage(message,null, LocaleContextHolder.getLocale());
}catch (Exception e){
return message;
}
return str;
}
}
- 过滤器
// 过滤Token
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String token = req.getHeader("token");
// 检查白名单 白名单接口不需要判断是否有token
if(chechWhiteList(req.getRequestURI())){
filterChain.doFilter(servletRequest,servletResponse);
return;
}
if(StringUtils.isEmpty(token)){
// throw new CustomerException("401","身份认证失败");
req.setAttribute("auth.error", new CustomException("401","身份认证失败"));
req.getRequestDispatcher("/excepion/error").forward(servletRequest, servletResponse);
}
// 会员信息
Object obj = redisTemplate.opsForValue().get("token:"+token);
if(obj == null ){
// throw new CustomerException("401","身份认证失败");
req.setAttribute("auth.error", new CustomException("401","用户登录已过期"));
req.getRequestDispatcher("/excepion/error").forward(servletRequest, servletResponse);
}
UserInfoResp userInfo = (UserInfoResp) obj;
userInfo.setSid(token);
UserUtils.setLoginUser(userInfo);
filterChain.doFilter(servletRequest, servletResponse);
}
2、全局捕获异常原理
2.1 Filter过滤器发生在Controller之前。
拦截到控制层的异常,而Filter在Controller之前,Controller层的异常捕获,是无法捕获到还没有请求到Controller时发生的异常的。
2.2 全局捕获异常是对Controller中的异常处理。
3、实现对Filter中异常处理
方案一:将异常抛到controller层,交由全局捕获异常处理
如果要捕获Filter异常,只能通过控制器层定义的全局异常处理来捕获;那么也就只能想办法让Filter中的异常发送到Controller,再由Controller抛出异常,最后由全局异常捕获。
方案二:
网友评论