异常处理
常用异常
import jakarta.servlet.Servlet;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.unit.DataSize;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.*;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@Component
@RestControllerAdvice
public class GlobalExceptionAdvice {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionAdvice.class);
@ExceptionHandler(value = BaseRuntimeException.class)
public void handleBaseRuntimeException(BaseRuntimeException e, HttpServletResponse response) {
e.log(log);
ResponseUtils.writeExceptionToResponse(e, response, e.getHttpStatus());
}
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
public Result<Void> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
return Result.failByMessage("预期的请求方法类型:" + StringUtils.join(e.getSupportedMethods(), "、"));
}
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
public Result<Void> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
return Result.failByMessage("预期的请求数据类型:" + StringUtils.join(e.getSupportedMediaTypes(), "、"));
}
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
@ExceptionHandler(value = HttpMediaTypeNotAcceptableException.class)
public Result<Void> handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException e) {
return Result.failByMessage("预期的响应数据类型:" + StringUtils.join(e.getSupportedMediaTypes(), "、"));
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(value = MissingPathVariableException.class)
public Result<Void> handleMissingPathVariableException(MissingPathVariableException e) {
log.error("缺少路径变量", e);
return Result.failByMessage("缺少路径变量: " + e.getVariableName());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MissingRequestHeaderException.class)
public Result<Void> handleMissingRequestHeaderException(MissingRequestHeaderException e) {
return Result.failByMessage("缺少请求头:" + e.getHeaderName());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public Result<Void> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
return Result.failByMessage("缺少请求参数:" + e.getParameterName());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MissingRequestValueException.class)
public Result<Void> handleMissingRequestValueException(MissingRequestValueException e) {
return Result.failByMessage(e.getMessage());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MissingServletRequestPartException.class)
public Result<Void> handleMissingServletRequestPartException(MissingServletRequestPartException e) {
return Result.failByMessage("缺少请求文件:" + e.getRequestPartName());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = ServletRequestBindingException.class)
public Result<Void> handleServletRequestBindingException(ServletRequestBindingException e) {
log.error("请求参数绑定异常", e);
return Result.failByMessage("请求参数不正确");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = ConversionNotSupportedException.class)
public Result<Void> handleConversionNotSupportedException(ConversionNotSupportedException e) {
log.error("请求参数转换异常", e);
return Result.failByMessage("请求参数转换失败");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
public Result<Void> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
return Result.failByMessage("参数:" + StringUtils.defaultString(e.getName()) + "类型不正确");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = HttpMessageNotReadableException.class)
public Result<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
log.error("请求体读取失败", e);
return Result.failByMessage("请求体读取失败");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MaxUploadSizeExceededException.class)
public Result<Void> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
log.error("上传文件大小超过限制", e);
if (e.getMaxUploadSize() == -1) {
if (Objects.nonNull(e.getCause()) &&
e.getCause() instanceof IllegalStateException illegalStateException &&
Objects.nonNull(illegalStateException.getCause()) &&
illegalStateException.getCause() instanceof SizeLimitExceededException sizeLimitExceededException) {
return Result.failByMessage("上传文件大小超过" + DataSize.ofBytes(sizeLimitExceededException.getPermittedSize()).toMegabytes() + "MB");
}
return Result.failByMessage("上传文件大小超过限制");
}
return Result.failByMessage("上传文件大小超过" + DataSize.ofBytes(e.getMaxUploadSize()).toMegabytes() + "MB");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MultipartException.class)
public Result<Void> handleMultipartException(MultipartException e) {
log.error("上传文件失败", e);
return Result.failByMessage("上传文件失败");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = HttpMessageNotWritableException.class)
public Result<Void> handleHttpMessageNotWritableException(HttpMessageNotWritableException e) {
log.error("响应体写入失败", e);
return Result.failByMessage("响应体写入失败");
}
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Result<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
List<ObjectError> objectErrors = bindingResult.getAllErrors();
if (!objectErrors.isEmpty()) {
FieldError fieldError = (FieldError) objectErrors.iterator().next();
return Result.fail(ConstantPool.VALIDATION_ERROR_RESPONSE_CODE, StringUtils.defaultString(fieldError.getDefaultMessage()));
}
return Result.fail(ConstantPool.VALIDATION_ERROR_RESPONSE_CODE, "请求参数验证不合法");
}
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = ConstraintViolationException.class)
public Result<Void> handleConstraintViolationException(ConstraintViolationException e) {
Set<ConstraintViolation<?>> constraints = e.getConstraintViolations();
if (!constraints.isEmpty()) {
ConstraintViolation<?> constraint = constraints.iterator().next();
return Result.fail(ConstantPool.VALIDATION_ERROR_RESPONSE_CODE, StringUtils.defaultString(constraint.getMessage()));
}
return Result.fail(ConstantPool.VALIDATION_ERROR_RESPONSE_CODE, "请求参数验证不合法");
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(value = NoHandlerFoundException.class)
public Result<Void> handleNoHandlerFoundException(NoHandlerFoundException e) {
return Result.failByMessage("请求路径:" + e.getRequestURL() + "不存在");
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(value = NoResourceFoundException.class)
public Result<Void> handleNoResourceFoundException(NoResourceFoundException e) {
return Result.failByMessage("请求资源:" + e.getResourcePath() + "不存在");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = AsyncRequestTimeoutException.class)
public Result<Void> handleAsyncRequestTimeoutException(AsyncRequestTimeoutException e) {
log.error("异步请求超时", e);
return Result.failByMessage("异步请求超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = IOException.class)
public Result<Void> handleIOException(IOException e) {
log.error("IO异常", e);
return Result.fail(ConstantPool.SERVER_ERROR_RESPONSE_CODE, "服务器内部错误");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = RuntimeException.class)
public Result<Void> handleRuntimeException(RuntimeException e) {
log.error("运行时异常", e);
return Result.fail(ConstantPool.SERVER_ERROR_RESPONSE_CODE, "服务器内部错误");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = Exception.class)
public Result<Void> handleException(Exception e) {
log.error("系统级异常", e);
return Result.fail(ConstantPool.SERVER_ERROR_RESPONSE_CODE, "服务器内部错误");
}
}
MyBatis和MyBatis Plus相关异常
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import jakarta.servlet.Servlet;
import org.apache.ibatis.exceptions.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;
import java.util.Objects;
import java.util.Optional;
@Component
@RestControllerAdvice
public class MybatisExceptionAdvice {
private static final Logger log = LoggerFactory.getLogger(MybatisExceptionAdvice.class);
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = CannotGetJdbcConnectionException.class)
public Result<Void> handleMybatisPlusException(CannotGetJdbcConnectionException e) {
log.error("JDBC连接超时", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "数据库连接超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MybatisPlusException.class)
public Result<Void> handleMybatisPlusException(MybatisPlusException e) {
log.error("mybatis-plus抛出异常", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "服务器内部错误");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = PersistenceException.class)
public Result<Void> handlePersistenceException(PersistenceException e) {
log.error("mybatis抛出异常", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "服务器内部错误");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = DataAccessException.class)
public Result<Void> handleDataAccessException(DataAccessException e) {
log.error("数据访问异常", e);
if (Objects.nonNull(e.getCause())) {
Class<?> clz = Optional.ofNullable(e.getCause())
.map(Throwable::getCause)
.map(Throwable::getClass)
.orElse(null);
if (Objects.nonNull(clz) && CannotGetJdbcConnectionException.class.isAssignableFrom(clz)) {
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "数据库连接超时");
}
}
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "服务器内部错误");
}
}
Redis相关异常
import jakarta.servlet.Servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;
@Component
@RestControllerAdvice
public class RedisExceptionAdvice {
private static final Logger log = LoggerFactory.getLogger(RedisExceptionAdvice.class);
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = RedisConnectionFailureException.class)
public Result<Void> handleRedisConnectionFailureException(RedisConnectionFailureException e) {
log.error("redis连接超时异常", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "Redis连接超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = DataAccessException.class)
public Result<Void> handleDataAccessException(DataAccessException e) {
log.error("数据访问异常", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "服务器内部错误");
}
}
MongoDB相关异常
import com.mongodb.MongoException;
import com.mongodb.MongoExecutionTimeoutException;
import com.mongodb.MongoSocketReadTimeoutException;
import com.mongodb.MongoTimeoutException;
import jakarta.servlet.Servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;
@Component
@RestControllerAdvice
public class MongoDBExceptionAdvice {
private static final Logger log = LoggerFactory.getLogger(MongoDBExceptionAdvice.class);
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MongoExecutionTimeoutException.class)
public Result<Void> handleMongoExecutionTimeoutException(MongoExecutionTimeoutException e) {
log.error("MongoDB执行超时", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "MongoDB执行超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MongoTimeoutException.class)
public Result<Void> handleMongoTimeoutException(MongoTimeoutException e) {
log.error("MongoDB连接超时", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "MongoDB连接超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MongoSocketReadTimeoutException.class)
public Result<Void> handleMongoSocketReadTimeoutException(MongoSocketReadTimeoutException e) {
log.error("MongoDB读取超时", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "MongoDB读取超时");
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MongoException.class)
public Result<Void> handleMongoException(MongoException e) {
log.error("MongoDB抛出异常", e);
return Result.fail(ConstantPool.DATA_ERROR_RESPONSE_CODE, "MongoDB错误");
}
}
相关代码
响应结构(Result)
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record Result<T>(
String message,
Integer code,
T data) {
public static Result<Void> ok() {
return new Result<>("请求成功", 0, null);
}
public static Result<Void> okByMessage(String message) {
return new Result<>(message, 0, null);
}
public static <T> Result<T> ok(T data) {
return new Result<>("请求成功", 0, data);
}
public static <E extends BaseRuntimeException> Result<Void> failByException(E e) {
return new Result<>(e.getMessage(), e.getCode(), null);
}
public static Result<Void> fail() {
return new Result<>("请求失败", -1, null);
}
public static Result<Void> failByMessage(String message) {
return new Result<>(message, -1, null);
}
public static Result<Void> fail(int code, String message) {
return new Result<>(message, code, null);
}
public static <T> Result<T> fail(T data) {
return new Result<>("请求失败", -1, data);
}
public static <T> Result<T> fail(int code, String message, T data) {
return new Result<>(message, code, data);
}
@Override
public String toString() {
return JsonUtils.toString(this);
}
}
自定义异常基类(BaseRuntimeException)
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.event.Level;
public abstract class BaseRuntimeException extends RuntimeException {
private int code;
private int httpStatus;
protected BaseRuntimeException(String message) {
super(message);
this.code = -1;
this.httpStatus = 200;
}
protected BaseRuntimeException(int code, String message) {
super(message);
this.code = code;
this.httpStatus = 200;
}
protected BaseRuntimeException(String message, Throwable cause) {
super(message, cause);
this.code = -1;
this.httpStatus = 200;
}
protected BaseRuntimeException(int code, String message, Throwable cause) {
super(message, cause);
this.code = code;
this.httpStatus = 200;
}
public int getCode() {
return code;
}
protected void setCode(int code) {
this.code = code;
}
public int getHttpStatus() {
return httpStatus;
}
protected void setHttpStatus(int httpStatus) {
this.httpStatus = httpStatus;
}
public void log(Logger logger) {
logger.error(this.getMessage(), this);
}
public void log(Logger logger, Level level) {
logger.atLevel(level)
.setCause(this)
.log(this.getMessage());
}
public Throwable getRootCause() {
Throwable rootCause = null;
Throwable cause = this.getCause();
while (cause != null && cause != rootCause) {
rootCause = cause;
cause = cause.getCause();
}
return (rootCause != null ? rootCause : this);
}
public Throwable getMostSpecificCause() {
return ObjectUtils.defaultIfNull(getRootCause(), this);
}
public boolean contains(Class<?> exType) {
if (exType == null) {
return false;
}
if (exType.isInstance(this)) {
return true;
}
Throwable cause = getCause();
if (cause == this) {
return false;
}
if (cause instanceof BaseRuntimeException e) {
return e.contains(exType);
} else {
while (cause != null) {
if (exType.isInstance(cause)) {
return true;
}
if (cause.getCause() == cause) {
break;
}
cause = cause.getCause();
}
return false;
}
}
}
业务异常(ServiceException)
package cn.changtech.framework.core.exception.base;
import org.slf4j.Logger;
import org.slf4j.event.Level;
public class ServiceException extends BaseRuntimeException {
private final String reason;
public ServiceException(String message) {
super(-40000, message);
this.reason = message;
}
public ServiceException(String message, String reason) {
super(-40000, message);
this.reason = reason;
}
public ServiceException(String message, Throwable cause) {
super(-40000, message, cause);
this.reason = message;
}
public ServiceException(String message, String reason, Throwable cause) {
super(-40000, message, cause);
this.reason = reason;
}
protected ServiceException(int code, String message) {
super(code, message);
this.reason = message;
}
protected ServiceException(int code, String message, String reason) {
super(code, message);
this.reason = reason;
}
protected ServiceException(int code, String message, Throwable cause) {
super(code, message, cause);
this.reason = message;
}
protected ServiceException(int code, String message, String reason, Throwable cause) {
super(code, message, cause);
this.reason = reason;
}
public String getReason() {
return reason;
}
@Override
public void log(Logger logger) {
logger.error(this.reason, this);
}
@Override
public void log(Logger logger, Level level) {
logger.atLevel(level)
.setCause(this)
.log(this.reason);
}
}
服务端异常(ServerException)
import org.slf4j.Logger;
import org.slf4j.event.Level;
public class ServerException extends BaseRuntimeException {
protected static final String DEFAULT_MESSAGE = "服务器内部错误";
private final String reason;
public ServerException() {
super(-50000, DEFAULT_MESSAGE);
this.reason = DEFAULT_MESSAGE;
this.setHttpStatus(500);
}
public ServerException(String reason) {
super(-50000, DEFAULT_MESSAGE);
this.reason = reason;
this.setHttpStatus(500);
}
public ServerException(Throwable cause) {
super(-50000, DEFAULT_MESSAGE, cause);
this.reason = DEFAULT_MESSAGE;
this.setHttpStatus(500);
}
public ServerException(String reason, Throwable cause) {
super(-50000, DEFAULT_MESSAGE, cause);
this.reason = reason;
this.setHttpStatus(500);
}
protected ServerException(int code, String reason) {
super(code, DEFAULT_MESSAGE);
this.reason = reason;
this.setHttpStatus(500);
}
protected ServerException(int code, String reason, Throwable cause) {
super(code, DEFAULT_MESSAGE, cause);
this.reason = reason;
this.setHttpStatus(500);
}
public String getReason() {
return reason;
}
@Override
public void log(Logger logger) {
logger.error(this.reason, this);
}
@Override
public void log(Logger logger, Level level) {
logger.atLevel(level)
.setCause(this)
.log(this.reason);
}
}
响应工具类(ResponseUtils)
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class ResponseUtils {
protected static final Logger logger = LoggerFactory.getLogger(ResponseUtils.class);
protected ResponseUtils() {
}
public static void setAttachmentHeader(final HttpServletResponse response, final String filename) {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8));
}
public static void writeBytesToResponse(final byte[] bytes, final HttpServletResponse response) {
writeBytesToResponse(bytes, response, HttpStatus.OK.value());
}
public static void writeBytesToResponse(final byte[] bytes, final HttpServletResponse response, final HttpStatus status) {
writeBytesToResponse(bytes, response, status.value());
}
public static void writeBytesToResponse(final byte[] bytes, final HttpServletResponse response, int status) {
try (OutputStream outputStream = response.getOutputStream()) {
response.setStatus(status);
outputStream.write(bytes);
} catch (IOException e) {
throw new ServerException("Http Servlet 响应值写入失败", e);
}
}
public static void writeInputStreamToResponse(final InputStream inputStream, final HttpServletResponse response) {
writeInputStreamToResponse(inputStream, response, HttpStatus.OK.value());
}
public static void writeInputStreamToResponse(final InputStream inputStream, final HttpServletResponse response, final HttpStatus status) {
writeInputStreamToResponse(inputStream, response, status.value());
}
public static void writeInputStreamToResponse(final InputStream inputStream, final HttpServletResponse response, int status) {
try (OutputStream outputStream = response.getOutputStream()) {
response.setStatus(status);
inputStream.transferTo(outputStream);
} catch (IOException e) {
throw new ServerException("Http Servlet 响应值写入失败", e);
}
}
public static <T> void writeBeanToResponse(final T bean, final HttpServletResponse response) {
writeResultToResponse(Result.ok(bean), response, HttpStatus.OK.value());
}
public static <T> void writeBeanToResponse(final T bean, final HttpServletResponse response, final HttpStatus status) {
writeResultToResponse(Result.ok(bean), response, status.value());
}
public static <E extends BaseRuntimeException> void writeExceptionToResponse(final E exception, final HttpServletResponse response) {
exception.log(logger);
writeResultToResponse(Result.failByException(exception), response, exception.getHttpStatus());
}
public static <E extends BaseRuntimeException> void writeExceptionToResponse(final E exception, final HttpServletResponse response, final HttpStatus httpStatus) {
exception.log(logger);
writeResultToResponse(Result.failByException(exception), response, httpStatus.value());
}
public static <E extends BaseRuntimeException> void writeExceptionToResponse(final E exception, final HttpServletResponse response, int httpStatus) {
exception.log(logger);
writeResultToResponse(Result.failByException(exception), response, httpStatus);
}
public static <T> void writeResultToResponse(final Result<T> data, final HttpServletResponse response, final HttpStatus httpStatus) {
writeResultToResponse(data, response, httpStatus.value());
}
public static <T> void writeResultToResponse(final Result<T> data, final HttpServletResponse response, int status) {
try (OutputStream outputStream = response.getOutputStream()) {
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
response.setStatus(status);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
outputStream.write(JsonUtils.toString(data).getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new ServerException("Http Servlet 响应值写入失败", e);
}
}
}
JSON工具类(JsonUtils)
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class JsonUtils {
public static final Gson DEFAULT_GSON;
static {
DEFAULT_GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
}
protected JsonUtils() {
}
public static JsonElement parseString(final String json) {
if (StringUtils.isBlank(json)) {
return JsonNull.INSTANCE;
}
return JsonParser.parseString(json);
}
public static <T> T fromString(final String json) {
return fromString(json, DEFAULT_GSON, new TypeToken<T>() {
});
}
public static <T> T fromString(final String json, final TypeToken<T> typeToken) {
return fromString(json, DEFAULT_GSON, typeToken);
}
public static <T> T fromString(final String json, final Gson gson) {
return fromString(json, gson, new TypeToken<T>() {
});
}
public static <T> T fromString(final String json, final Gson gson, final TypeToken<T> typeToken) {
if (StringUtils.isBlank(json)) {
return null;
}
return gson.fromJson(json, typeToken.getType());
}
public static <T> String toString(final T src) {
return toString(src, DEFAULT_GSON, new TypeToken<T>() {
});
}
public static <T> String toString(final T src, final TypeToken<T> typeToken) {
return toString(src, DEFAULT_GSON, typeToken);
}
public static <T> String toString(final T src, final Gson gson) {
return toString(src, gson, new TypeToken<T>() {
});
}
public static <T> String toString(final T src, final Gson gson, final TypeToken<T> typeToken) {
if (Objects.isNull(src)) {
return StringUtils.EMPTY;
}
return gson.toJson(src, typeToken.getType());
}
public static <T> T fromJson(final JsonElement json) {
return fromJson(json, DEFAULT_GSON, new TypeToken<T>() {
});
}
public static <T> T fromJson(final JsonElement json, final TypeToken<T> typeToken) {
return fromJson(json, DEFAULT_GSON, typeToken);
}
public static <T> T fromJson(final JsonElement json, final Gson gson) {
return fromJson(json, gson, new TypeToken<T>() {
});
}
public static <T> T fromJson(final JsonElement json, final Gson gson, final TypeToken<T> typeToken) {
return gson.fromJson(json, typeToken.getType());
}
public static <T> JsonElement toJson(final T src) {
return toJson(src, DEFAULT_GSON, new TypeToken<T>() {
});
}
public static <T> JsonElement toJson(final T src, final TypeToken<T> typeToken) {
return toJson(src, DEFAULT_GSON, typeToken);
}
public static <T> JsonElement toJson(final T src, final Gson gson) {
return toJson(src, gson, new TypeToken<T>() {
});
}
public static <T> JsonElement toJson(final T src, final Gson gson, final TypeToken<T> typeToken) {
if (Objects.isNull(src)) {
return JsonNull.INSTANCE;
}
return gson.toJsonTree(src, typeToken.getType());
}
public static <T> List<T> fromJsonArray(final JsonArray array) {
return fromJsonArray(array, DEFAULT_GSON, new TypeToken<List<T>>() {
});
}
public static <T> List<T> fromJsonArray(final JsonArray array, final TypeToken<? extends List<T>> typeToken) {
return fromJsonArray(array, DEFAULT_GSON, typeToken);
}
public static <T> List<T> fromJsonArray(final JsonArray json, final Gson gson) {
return fromJsonArray(json, gson, new TypeToken<List<T>>() {
});
}
public static <T> List<T> fromJsonArray(final JsonArray json, final Gson gson, final TypeToken<? extends List<T>> typeToken) {
if (json == null || json.isEmpty()) {
return Collections.emptyList();
}
return gson.fromJson(json, typeToken.getType());
}
public static <T> JsonArray toJsonArray(final Collection<T> collection) {
return toJsonArray(collection, DEFAULT_GSON, new TypeToken<Collection<T>>() {
});
}
public static <T> JsonArray toJsonArray(final Collection<T> collection, final Gson gson) {
return toJsonArray(collection, gson, new TypeToken<Collection<T>>() {
});
}
public static <T> JsonArray toJsonArray(final Collection<T> collection, final Gson gson, final TypeToken<Collection<T>> typeToken) {
if (CollectionUtils.isEmpty(collection)) {
return new JsonArray();
}
JsonElement jsonElement = gson.toJsonTree(collection, typeToken.getType());
return jsonElement.getAsJsonArray();
}
}