1. 异常处理
1). 定义枚举类,管理异常分类
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.util.LinkedHashMap;
@NoArgsConstructor
@AllArgsConstructor
public enum ResponseCode {
/*-----Basic-----*/
SUCCESS(200,"操作成功"),
FAIL(500,"操作失败"),
/*-----User (StartCode: 1000)-----*/
USER_PASSWORD_ERROR(1000,"密码错误"),
USER_NOT_FOUND(1001,"用户不存在");
public Integer code;
public String msg;
public static LinkedHashMap<Integer,String> getArrayMessage(){
LinkedHashMap<Integer,String> responseMessages = new LinkedHashMap<>();
for (ResponseCode statusEnum : ResponseCode.values()) {
responseMessages.put(statusEnum.code,statusEnum.msg);
}
return responseMessages;
}
}
这个枚举类比较重要,后面都会用到。
2). 编写自定义异常
import lombok.*;
import com.xxx.xxx.response.ResponseCode;
import java.io.Serializable;
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
//如果在编译时出现“java: 已在类 top.yuanmen.oa、
// .exception.RequestException中定义了构造器
// RequestException()”则删除此注解
//@NoArgsConstructor
public class RequestException extends RuntimeException implements Serializable {
private Integer code;
private String msg;
private Exception e;
public RequestException(ResponseCode responseCode, Exception e) {
this.code = responseCode.code;
this.msg = responseCode.msg;
this.e = e;
}
public RequestException(ResponseCode responseCode) {
this.code = responseCode.code;
this.msg = responseCode.msg;
}
public synchronized static RequestException fail(String msg){
return RequestException.builder().code(ResponseCode.FAIL.code).msg(msg).build();
}
public synchronized static RequestException fail(String msg,Exception e){
return RequestException.builder().code(ResponseCode.FAIL.code).msg(msg).e(e).build();
}
public synchronized static RequestException fail(Integer code,String msg,Exception e){
return RequestException.builder().code(code).msg(msg).e(e).build();
}
}
3). 使用
@Override
public void addUser(User user) {
try {
boolean res = this.insert(user);
if (!res) throw new RequestException(ResponseCode.FAIL);
} catch (Exception e){
throw new RequestException(ResponseCode.FAIL);
}
}
我这里的方法是添加一个用户信息,我在表中用户的phone是规定的11位,就用这个来造成异常:
@Test
public void userServiceTest() {
User user = User.builder().loginId("875044497").username("admin").password("123456")
.gender(1).phone("13980449849000").email("8750444497").department_id("1032513234847997954").build();
userService.addUser(user);
}
4. 全局异常处理
全局异常处理主要用来处理我们上面自定义的异常没考虑到的范围。这里的全局异常主要是针对controller层的。
使用注解@ControllerAdvice将一个类标记为全局异常处理类即可:
import com.xxx.xxx.exception.RequestException;
import com.xxx.xxx.response.ResponseCode;
import com.xxx.xxx.response.ResponseResult;
import lombok.extern.log4j.Log4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
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 java.util.List;
@ControllerAdvice(basePackages = {"com.xxx.xxx.controller"})
@Log4j
public class GlobalDefaultExceptionHandler {
//请求异常
@ExceptionHandler(value = RequestException.class)
@ResponseBody
public ResponseResult requestExceptionHandler(RequestException e){
if(e.getE()!=null) e.printStackTrace();
return ResponseResult.builder().msg(e.getMsg()).code(e.getCode()).build();
}
//参数验证异常
@ExceptionHandler(value = DataIntegrityViolationException.class)
@ResponseBody
public ResponseResult requestExceptionHandler(DataIntegrityViolationException e){
return ResponseResult.builder().msg(ResponseCode.SYSTEM_DATA_FAIL.msg).code(ResponseCode.FAIL.code).build();
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
BindingResult result = e.getBindingResult();
String s = "参数验证失败";
if(result.hasErrors()){
List<ObjectError> errors = result.getAllErrors();
s = errors.get(0).getDefaultMessage();
}
return ResponseResult.builder().code(ResponseCode.SYSTEM_PARAM_FAIL.code).msg(s).build();
}
//所有异常
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResponseResult requestExceptionHandler(Exception e){
e.printStackTrace();
return ResponseResult.builder().msg("系统出现了一点小问题,正在修复中~").code(ResponseCode.FAIL.code).build();
}
}
2. 统一响应数据体结构
1). 编写统一结果响应体
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(value = "请求结果响应体")
public class ResponseResult<T> implements Serializable {
@ApiModelProperty("错误码")
private Integer code;
@ApiModelProperty("数据体")
private T data;
@ApiModelProperty("消息")
private String msg;
@ApiModelProperty("响应时间戳")
private final long timestamps = System.currentTimeMillis();
public synchronized static <T> ResponseResult<T> build(ResponseCode statusEnum) {
return build(statusEnum,null);
}
public synchronized static <T> ResponseResult<T> build(ResponseCode responseCode, T data) {
ResponseResult<T> res = new ResponseResult<>();
res.setCode(responseCode.code);
res.setMsg(responseCode.msg);
res.setData(data);
return res;
}
public synchronized static <T> ResponseResult<T> ok() {
return build(ResponseCode.SUCCESS,null);
}
public synchronized static <T> ResponseResult<T> okHasData(T data) {
return build(ResponseCode.SUCCESS,data);
}
private static final long serialVersionUID = 8992436576262574064L;
}
2). 使用
主要是在controller中使用:
import com.baomidou.mybatisplus.plugins.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.xxx.xxx.dto.UserDTO;
import com.xxx.xxx.entity.User;
import com.xxx.xxx.response.ResponseResult;
import com.xxx.xxx.service.IUserService;
@RequestMapping("/user")
@RestController
@Api(tags = {"用户操作"})
public class UserController {
@Autowired
private IUserService userService;
@PostMapping("/list")
@ApiOperation("用户列表")
@ApiImplicitParam(paramType = "header",name = "Authorization",value = "身份认证Token")
public ResponseResult<Page<User>> list(@RequestBody @ApiParam("分页信息")UserDTO page){
Page<User> resultPage = userService.selectPage(new Page<>(page.getPage(), page.getPageSize()));
return ResponseResult.okHasData(resultPage);
}
}