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");
    }
    }

SpringMVC的项目架构思想的更多相关文章

  1. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用

    再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...

  2. 剥析surging的架构思想

    1.前言   前面第一篇阐述了采用基于.NET CORE微服务架构,应用surging服务端与客户端之间进行通信的简单示例以及对于surging服务化框架简单介绍.在这篇文章中,我们将剥析surgin ...

  3. 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来

    [前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...

  4. iOS swift的xcworkspace多项目管理(架构思想)

    iOS  swift的xcworkspace多项目管理(架构思想) 技术说明: 今天在这里分享 swift下的 xcworkspace多项目管理(架构思想),能为我们在开发中带来哪些便捷?能为我们对整 ...

  5. 前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战

    一.MongoDB数据库 1.1 NoSQL简介 随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNS(social network ...

  6. 『练手』005 Laura.SqlForever历史遗留 的 架构思想缺陷

    005 Laura.SqlForever历史遗留 的 架构思想缺陷 我们 比较一下 Laura.WinFramework 和 Laura.XtraFramework 的差异: Laura.WinFra ...

  7. 大数据项目之_15_电信客服分析平台_01&02_项目背景+项目架构+项目实现+数据生产+数据采集/消费(存储)

    一.项目背景二.项目架构三.项目实现3.1.数据生产3.1.1.数据结构3.1.2.编写代码3.1.3.打包测试3.2.数据采集/消费(存储)3.2.1.数据采集:采集实时产生的数据到 kafka 集 ...

  8. Restful架构思想

    java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢.通常是让java作为一个app的服务端,为app客户 ...

  9. 架构思想之CAP原理

    由于自己负责后端的设计已经有一段时间,对设计的一些思想和理论有一些理解,但最近被问到什么是CAP时,却一脸懵逼,下来后专门针对CAP架构思想进行了一些专题学习,在这里也将这个概念引入给大家,大家可以有 ...

随机推荐

  1. Java实现 蓝桥杯VIP 算法提高 分苹果

    算法提高 分苹果 时间限制:1.0s 内存限制:256.0MB 问题描述 小朋友排成一排,老师给他们分苹果. 小朋友从左到右标号1-N.有M个老师,每次第i个老师会给第Li个到第Ri个,一共Ri-Li ...

  2. Java实现 蓝桥杯 算法训练 字符串合并

    试题 算法训练 字符串合并 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输入两个字符串,将其合并为一个字符串后输出. 输入格式 输入两个字符串 输出格式 输出合并后的字符串 样例 ...

  3. 第七届蓝桥杯JavaB组国(决)赛部分真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.愤怒小鸟 题目描述 X星球愤怒的小鸟喜欢撞火车! 一根平直的铁轨上两火车间相距 1000 米 两火车 (不妨称A和B) 以时速 10米 ...

  4. Javascript实现万年历(日历表)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. Java实现 蓝桥杯 历届试题 约数倍数选卡片

    问题描述 闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数.例如,某次福尔摩斯拿走的卡片上写着数字" ...

  6. java实现第五届蓝桥杯圆周率

    圆周率 数学发展历史上,圆周率的计算曾有许多有趣甚至是传奇的故事.其中许多方法都涉及无穷级数. 图1.png中所示,就是一种用连分数的形式表示的圆周率求法. 下面的程序实现了该求解方法.实际上数列的收 ...

  7. TZOJ 1214: 数据结构练习题――线性表操作

    描述 请你定义一个线性表,可以对表进行“在某个位置之前插入一个元素”.“删除某个位置的元素”.“清除所有元素”.“获取某个位置的元素”等操作.键盘输入一些命令,可以执行上述操作.本题中,线性表元素为整 ...

  8. 初学python笔记

    一.关于python ① 由荷兰人Guido van Rossum(龟叔)于1989年圣诞节为打发无聊时间所编写的编程语言. ② python的特点:优雅 明确 简单.代码量少,运行速度快. 缺点:运 ...

  9. EasyARM-iMX257 linux两年前的笔记

    我依然清晰的记得刚拿到Imx283 257的情景,兴奋中充满忧虑,对操作系统的概念只知一二,不知三四!!周立功出品的资料我一直觉得是比较精品的,同样这款iMX283配套的文档资料(v1.04)也是比较 ...

  10. 数据误操作,删库跑路?教你使用ApexSQLLog工具从 SQLServer日志恢复数据!

    前几天同事不小心误操作,将SQLServer库的一张表的一个状态字段给刷成了一个统一状态,由于是update执行所以原来的相关状态无法确定.发生这种事情的时候我的小伙伴背后 一凉,估计心里里面想这怕是 ...