目录
- 返回数据格式
- POM.xml
- 包路径
- 核心代码
- ResultCode.java
- Result.java
- ErrorResult.java
- ServiceException.java
- JsonUtil.java
- GlobalExceptionHandler.java
- ResponseHandler.java
- 测试代码
- UserVO.java
- UserController.java
返回数据格式
{
"status":10000,
"desc":"成功",
"data":{}
}
POM.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo1</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>demo1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
包路径
com
example
demo
rest
advice
GlobalExceptionHandler.java
ResponseHandler.java
ctrl
UserController.java
utils
JsonUtil.java
vo
ErrorResult.java
Result.java
ResultCode.java
ServiceException.java
UserVO.java
核心代码
ResultCode.java
package com.example.demo.rest.vo;
public enum ResultCode {
SUCCESS(0, "成功"),
SYSTEM_ERROR(10000, "系统异常,请稍后重试"),
UNAUTHORIZED(10410, "签名验证失败"),
PARAM_IS_INVALID(10001, "参数无效"),
USER_HAS_EXSISTED(20001, "用户名已存在"),
USER_NOT_FIND(20002, "用户名不存在");
private Integer code;
private String message;
private ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
}
Result.java
package com.example.demo.rest.vo;
public class Result {
private Integer status;
private String desc;
private Object data;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result suc() {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
return result;
}
public static Result suc(Object data) {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
result.setData(data);
return result;
}
public static Result fail(Integer status, String desc) {
Result result = new Result();
result.setStatus(status);
result.setDesc(desc);
return result;
}
public static Result fail(ResultCode resultCode) {
Result result = new Result();
result.setResultCode(resultCode);
return result;
}
private void setResultCode(ResultCode resultCode) {
this.status = resultCode.getCode();
this.desc = resultCode.getMessage();
}
}
ErrorResult.java
package com.example.demo.rest.vo;
public class ErrorResult {
private Integer status;
private String message;
private String exception;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getException() {
return exception;
}
public void setException(String exception) {
this.exception = exception;
}
@Override
public String toString() {
return "ErrorResult [status=" + status + ", message=" + message + ", exception=" + exception + "]";
}
public static ErrorResult fail(ResultCode resultCode, Throwable e, String message) {
ErrorResult errorResult = ErrorResult.fail(resultCode, e);
errorResult.setMessage(message);
return errorResult;
}
public static ErrorResult fail(ResultCode resultCode, Throwable e) {
ErrorResult errorResult = new ErrorResult();
errorResult.setStatus(resultCode.getCode());
errorResult.setMessage(resultCode.getMessage());
errorResult.setException(e.getClass().getName());
return errorResult;
}
}
ServiceException.java
package com.example.demo.rest.vo;
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 2797060340861735113L;
protected Integer code;
protected String message;
public ServiceException(ResultCode resultCode) {
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
public ServiceException(ResultCode resultCode, Throwable cause) {
super(cause);
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
JsonUtil.java
package com.example.demo.rest.utils;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class JsonUtil {
private static final ObjectMapper objectMapper;
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
objectMapper.setSerializationInclusion(Include.NON_NULL);
objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.setDateFormat(new SimpleDateFormat(DATE_TIME_FORMAT));
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
}
public static <T> T json2Object(String json, Class<T> clazz) {
try {
return objectMapper.readValue(json, clazz);
} catch (IOException e) {
throw new RuntimeException("解析json错误");
}
}
public static <T> T json2Object(String json, TypeReference<T> tr) {
try {
return (T)objectMapper.readValue(json, tr);
} catch (IOException e) {
throw new RuntimeException("解析json错误", e);
}
}
public static <T> String object2Json(T entity) {
try {
return objectMapper.writeValueAsString(entity);
} catch (IOException e) {
throw new RuntimeException("转换json错误");
}
}
public static JsonNode object2TreeJson(Object obj) {
try {
return objectMapper.valueToTree(obj);
} catch (Exception e) {
throw new RuntimeException("转换json错误");
}
}
@SuppressWarnings("unchecked")
public static <T> T decode(String json, Class<?> valueType) {
try {
return (T) objectMapper.readValue(json, valueType);
} catch (Exception e) {
throw new RuntimeException(json, e);
}
}
}
GlobalExceptionHandler.java
package com.example.demo.rest.advice;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.example.demo.rest.vo.ErrorResult;
import com.example.demo.rest.vo.ResultCode;
import com.example.demo.rest.vo.ServiceException;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Throwable.class)
public ErrorResult handleThrowable(Throwable e, HttpServletRequest request) {
ErrorResult error = ErrorResult.fail(ResultCode.SYSTEM_ERROR, e);
logger.error("URL: {}, 系统异常!", request.getRequestURI(), e);
return error;
}
@ExceptionHandler(ServiceException.class)
public ErrorResult handleServiceException(ServiceException e, HttpServletRequest request) {
ErrorResult error = new ErrorResult();
error.setStatus(e.getCode());
error.setMessage(e.getMessage());
error.setException(e.getClass().getName());
logger.warn("URL: {}, 业务异常: {}", request.getRequestURI(), error, e);
return error;
}
@ExceptionHandler(BindException.class)
public ErrorResult handleBindException(BindException e, HttpServletRequest request) {
ErrorResult error = ErrorResult.fail(ResultCode.PARAM_IS_INVALID, e, e.getAllErrors().get(0).getDefaultMessage());
logger.warn("URL: {}, 参数校验异常", request.getRequestURI(), e);
return error;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
ErrorResult error = ErrorResult.fail(ResultCode.PARAM_IS_INVALID, e, e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
logger.warn("URL: {}, 参数校验异常", request.getRequestURI(), e);
return error;
}
@ExceptionHandler(ConstraintViolationException.class)
public ErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
StringBuilder builder = new StringBuilder();
for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
builder.append(constraintViolation.getMessage());
}
ErrorResult error = ErrorResult.fail(ResultCode.PARAM_IS_INVALID, e, builder.toString());
logger.warn("URL: {}, 参数校验异常", request.getRequestURI(), e);
return error;
}
}
ResponseHandler.java
package com.example.demo.rest.advice;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.example.demo.rest.utils.JsonUtil;
import com.example.demo.rest.vo.ErrorResult;
import com.example.demo.rest.vo.Result;
@ControllerAdvice(basePackages = "com.example.demo.rest")
public class ResponseHandler implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if (body instanceof ErrorResult) {
ErrorResult errorResult = (ErrorResult) body;
return Result.fail(errorResult.getStatus(), errorResult.getMessage());
} else if (body instanceof String) {
return JsonUtil.object2Json(Result.suc(body));
}
return Result.suc(body);
}
}
测试代码
UserVO.java
package com.example.demo.rest.vo;
import java.util.Date;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
public class UserVO {
@Min(value = 3)
private Integer id;
@NotBlank(message = "用户名不能为空")
private String username;
private String password;
private String email;
private String phone;
private String idCard;
private Byte sex;
private Byte deleted;
private Date updateTime;
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public Byte getSex() {
return sex;
}
public void setSex(Byte sex) {
this.sex = sex;
}
public Byte getDeleted() {
return deleted;
}
public void setDeleted(Byte deleted) {
this.deleted = deleted;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "UserVO [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email
+ ", phone=" + phone + ", idCard=" + idCard + ", sex=" + sex + ", deleted=" + deleted + ", updateTime="
+ updateTime + ", createTime=" + createTime + "]";
}
}
UserController.java
package com.example.demo.rest.ctrl;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.rest.vo.ResultCode;
import com.example.demo.rest.vo.ServiceException;
import com.example.demo.rest.vo.UserVO;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("getStr")
public String getStr() {
return "test";
}
@GetMapping("getInt")
public int getInt() {
return 1;
}
@GetMapping("/getObject")
public UserVO getObject() {
UserVO vo = new UserVO();
vo.setUsername("xxx");
return vo;
}
@GetMapping("/empty")
public void empty() {
}
@GetMapping("/error")
public void error() {
int i = 1 / 0;
}
@GetMapping("/error2")
public void error2() {
Integer.valueOf("aa");
}
@GetMapping("/error3")
public void error3() {
throw new ServiceException(ResultCode.USER_HAS_EXSISTED);
}
@GetMapping("/error4")
public void error4() {
throw new RuntimeException("用户不存在!!");
}
@GetMapping("/createUser")
public void createUser(@Valid UserVO userVO) {
}
}