SpringMVC的專案架構思想

xd會飛的貓發表於2020-07-03

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

三、層次結構

  1. dao層:定義XXXMapper介面、對應的XXXMapper.xml在resource目錄下的mapper資料夾裡,使用資料模型DO(Data Object)

  2. 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;
        }
    }
  3. 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層的響應資訊

  1. 定義一個公共的返回值型別

    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;
        }
    }
  2. 在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);
    }
  3. 前端得到的返回正確的結果

    {
        "status":"success",
        "data":{
            "id":1,
            "name":"張三",
            "gender":false,
            "age":12,
            "telphone":"123456"
        }
    }
  4. 異常結果的處理(見下一Part)

五、 包裝器業務異常類的實現

  1. 定義一個公共錯誤介面/error

    public interface CommonError {
        public int getErrCode();
        public String getErrMsg();
        public CommonError setErrMsg(String errMsg);
    }
  2. 定義一個列舉錯誤類/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;
        }
    }
  3. 定義異常包裝類/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;
        }
    }
  4. 在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);
    }

六、異常的處理

  1. 定義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;
    }
  2. 前端得到的JSON資料

    {"status":"fail",
     "data":{
         "errCode":10001,
         "errMsg":"使用者不存在"
     }
    }
  3. 優化異常處理,定義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");
        }
    }

     

相關文章