SpringMVC的项目架构思想
一、DO和Model的区别
DO是对数据库表的映射。Model是处理业务逻辑的模型(领域模型)。例如:用户信息表和用户密码表分别是两个DO,但是对于实体用户来说,密码表的字段也属于用户,所以需要在Service层使用Model来处理业务逻辑,Model包含了两张表的字段的并集。在Mapper层使用DO,在Service层使用Model。
public class UserDO { private Integer id; private String name; private Boolean gender; private Integer age; private String telphone; private String registerType; private String thirdPartyId; //getter、setter
public class UserPasswordDO { private Integer id; private String encrptPassword; private Integer userId; //getter、setter
二、VO和Model的区别
VO(View Object视图对象),用于前端展示。Model中包含了用户的密码数据,不应该通过Controller层返回给前端,这是不安全的操作。在Controller层通过VO返回部分可以展示到前端的数据即可。
public class UserModel { private Integer id; private String name; private Boolean gender; private Integer age; private String telphone; private String registerMode; private String thirdPartyId; private String encrptPassword; //getter、setter
public class UserVO { private Integer id; private String name; private Boolean gender; private Integer age; private String telphone; //getter、setter
三、层次结构
dao层:定义XXXMapper接口、对应的XXXMapper.xml在resource目录下的mapper文件夹里,使用数据模型DO(Data Object)
service层:定义XXXService接口、实现类XXXServiceImpl、领域模型Model
@Service public class UserServiceImpl implements UserService { @Autowired private UserDOMapper userDOMapper; @Autowired private UserPasswordDOMapper userPasswordDOMapper; @Override public UserModel getUserById(Integer id) { UserDO userDO = userDOMapper.selectByPrimaryKey(id); if (userDO == null) { return null; } UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUid(userDO.getId()); return covertFromDataObject(userDO, userPasswordDO); } private UserModel covertFromDataObject(UserDO userDO, UserPasswordDO userPasswordDO) { if (userDO == null) { return null; } UserModel userModel = new UserModel(); BeanUtils.copyProperties(userDO, userModel); if (userPasswordDO != null) { userModel.setEncrptPassword(userPasswordDO.getEncrptPassword()); } return userModel; } }
controller层:定义XXXController类、视图模型VO(View Object)
@RestController("user") @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/get") public UserVO getUser(@RequestParam(name = "id") Integer id){ UserModel userModel = userService.getUserById(id); //将核心的领域模型对象转化为可供UI使用的VO return convertFromModel(userModel); } private UserVO convertFromModel(UserModel userModel){ if(userModel == null){ return null; } UserVO userVO = new UserVO(); BeanUtils.copyProperties(userModel, userVO); return userVO; } }
四、归一化Controller层的响应信息
定义一个公共的返回值类型
public class CommonReturnType { //处理结果 success/fail //fail 返回通用的错误码格式 //success 返回数据 private String status; private Object data; public static CommonReturnType create(Object result, String status) { CommonReturnType returnType = new CommonReturnType(); returnType.setStatus(status); returnType.setData(result); return returnType; } public static CommonReturnType create(Object result) { return CommonReturnType.create(result, "success"); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
在Controller层返回CommonResultType
@RequestMapping("/get") public CommonReturnType getUser(@RequestParam(name = "id") Integer id){ UserModel userModel = userService.getUserById(id); //将核心的领域模型对象转化为可供UI使用的VO UserVO userVO = convertFromModel(userModel); //返回通用对象 return CommonReturnType.create(userVO); }
前端得到的返回正确的结果
{ "status":"success", "data":{ "id":1, "name":"张三", "gender":false, "age":12, "telphone":"123456" } }
异常结果的处理(见下一Part)
五、 包装器业务异常类的实现
定义一个公共错误接口/error
public interface CommonError { public int getErrCode(); public String getErrMsg(); public CommonError setErrMsg(String errMsg); }
定义一个枚举错误类/error
public enum EmBusinessError implements CommonError { //通用错误类型 00001 PARAMETER_VALIDATION_ERROR(00001,"参数不合法"), //用户信息相关 1000X USER_NOT_EXIST(10001,"用户不存在") // ; private EmBusinessError(int errCode, String errMsg){ this.errCode = errCode; this.errMsg = errMsg; } private int errCode; private String errMsg; @Override public int getErrCode() { return this.errCode; } @Override public String getErrMsg() { return this.errMsg; } @Override public CommonError setErrMsg(String errMsg) { this.errMsg = errMsg; return this; } }
定义异常包装类/exception
//包装器业务异常类的实现 public class BusinessException extends Exception implements CommonError { private CommonError commonError; //直接接收EmBusinessError的传参用于构造业务异常 public BusinessException(CommonError commonError){ super(); this.commonError = commonError; } //接收自定义errMsg的方式构造业务异常 public BusinessException(CommonError commonError, String errMsg){ super(); this.commonError = commonError; this.commonError.setErrMsg(errMsg); } @Override public int getErrCode() { return this.commonError.getErrCode(); } @Override public String getErrMsg() { return this.commonError.getErrMsg(); } @Override public CommonError setErrMsg(String errMsg) { this.commonError.setErrMsg(errMsg); return this; } }
在Controller层抛出异常
@RequestMapping("/get") public CommonReturnType getUser(@RequestParam(name = "id") Integer id) throws BusinessException { UserModel userModel = userService.getUserById(id); if(userModel == null){ throw new BusinessException(EmBusinessError.USER_NOT_EXIST); } //将核心的领域模型对象转化为可供UI使用的VO UserVO userVO = convertFromModel(userModel); //返回通用对象 return CommonReturnType.create(userVO); }
六、异常的处理
定义exceptionHandler解决未被Controller层吸收的exception
@ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.OK) public Object handlerException(HttpServletRequest request, Exception ex){ BusinessException businessException = (BusinessException) ex; CommonReturnType commonReturnType = new CommonReturnType(); commonReturnType.setStatus("fail"); Map<String, Object> responseData = new HashMap<>(); responseData.put("errCode",businessException.getErrCode()); responseData.put("errMsg",businessException.getErrMsg()); commonReturnType.setData(responseData); return commonReturnType; }
前端得到的JSON数据
{"status":"fail", "data":{ "errCode":10001, "errMsg":"用户不存在" } }
优化异常处理,定义BaseController,其余Controller继承基类。
@RestController public class BaseController { @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.OK) public Object handlerException(HttpServletRequest request, Exception ex){ Map<String, Object> responseData = new HashMap<>(); if(ex instanceof BusinessException){ BusinessException businessException = (BusinessException) ex; CommonReturnType commonReturnType = new CommonReturnType(); commonReturnType.setStatus("fail"); responseData.put("errCode",businessException.getErrCode()); responseData.put("errMsg",businessException.getErrMsg()); } else{ responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode()); responseData.put("errMsg",EmBusinessError.UNKNOWN_ERROR.getErrMsg()); } return CommonReturnType.create(responseData,"fail"); } }