Springboot项目中,在使用RouterFunction而非controller作为接口声明的情况下,原来的全局异常处理注解不生效了(@RestControllerAdvice),转而会直接触发spring默认的错误页面。
跟踪异常堆栈信息可以发现进入HandlerExceptionResolver类进行异常处理,那么只要能介入这一步逻辑就可以实现自定义全局异常处理了,根据这个信息查资料后得知可以继承SimpleMappingExceptionResolver来实现。代码如下:
package xxx.common.handler;
import xxx.common2.result.ResultDTO;
import xxx.common.exception.InvalidTokenException;
import xxx.common.exception.NotAuthException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @date 2024/5/6 15:22
*/
@Component
public class RouterExceptionHandler extends SimpleMappingExceptionResolver {
private static final Logger log = LoggerFactory.getLogger(RouterExceptionHandler.class);
private ObjectMapper objectMapper;
public RouterExceptionHandler(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ResultDTO result = ResultDTO.failure();
if (ex instanceof NotAuthException) {
result.setMsg(ex.getMessage());
result.setStatus(NotAuthException.CODE);
} else if (ex instanceof InvalidTokenException) {
result.setMsg(ex.getMessage());
result.setStatus(InvalidTokenException.CODE);
} else {
log.error(ex.getMessage(), ex);
result.setMsg(ex.getMessage());
}
try {
response.addHeader("Content-Type", "application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().write(objectMapper.writeValueAsString(result));
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return new ModelAndView();
}
}