SpringMVC的项目架构思想
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");
}
}
SpringMVC的项目架构思想的更多相关文章
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用
再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...
- 剥析surging的架构思想
1.前言 前面第一篇阐述了采用基于.NET CORE微服务架构,应用surging服务端与客户端之间进行通信的简单示例以及对于surging服务化框架简单介绍.在这篇文章中,我们将剥析surgin ...
- 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来
[前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...
- iOS swift的xcworkspace多项目管理(架构思想)
iOS swift的xcworkspace多项目管理(架构思想) 技术说明: 今天在这里分享 swift下的 xcworkspace多项目管理(架构思想),能为我们在开发中带来哪些便捷?能为我们对整 ...
- 前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战
一.MongoDB数据库 1.1 NoSQL简介 随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNS(social network ...
- 『练手』005 Laura.SqlForever历史遗留 的 架构思想缺陷
005 Laura.SqlForever历史遗留 的 架构思想缺陷 我们 比较一下 Laura.WinFramework 和 Laura.XtraFramework 的差异: Laura.WinFra ...
- 大数据项目之_15_电信客服分析平台_01&02_项目背景+项目架构+项目实现+数据生产+数据采集/消费(存储)
一.项目背景二.项目架构三.项目实现3.1.数据生产3.1.1.数据结构3.1.2.编写代码3.1.3.打包测试3.2.数据采集/消费(存储)3.2.1.数据采集:采集实时产生的数据到 kafka 集 ...
- Restful架构思想
java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢.通常是让java作为一个app的服务端,为app客户 ...
- 架构思想之CAP原理
由于自己负责后端的设计已经有一段时间,对设计的一些思想和理论有一些理解,但最近被问到什么是CAP时,却一脸懵逼,下来后专门针对CAP架构思想进行了一些专题学习,在这里也将这个概念引入给大家,大家可以有 ...
随机推荐
- Java实现 LeetCode 127 单词接龙
127. 单词接龙 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度.转换需遵循如下规则: 每次转换只能改变一个字 ...
- Java实现最大流量问题
1 问题描述 何为最大流量问题? 给定一个有向图,并为每一个顶点设定编号为0~n,现在求取从顶点0(PS:也可以称为源点)到顶点n(PS:也可以称为汇点)后,顶点n能够接收的最大流量.图中每条边的权值 ...
- 数据结构&算法
20个最常用.最基础数据结构与算法: 10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树. 10个 算法 :递归.排序.二分查找.搜索.哈希.贪心.分治.回溯. ...
- nacos部署注意点
官方Naming Configuration Service https://nacos.io/zh-cn/docs/deployment.html 划重点 单机部署 单机部署默认嵌入式存储数据 支持 ...
- Flutter 中由 BuildContext 引发的血案
今天和各位分享一个博主在实际开发中遇到的问题,以及解决方法.废话不多说,我们先来看需求: 我们要做一个iOS风格的底部菜单弹出组件,具体涉及showCupertinoModalPopup()方法,该方 ...
- Python字符串处理 - str/bytes
目录 1. str 2. bytes / bytearray 3. printf-style String Formatting 1. str homepage str.count(sub[, sta ...
- iOS-键盘弹出或隐藏时调整输入框的位置
要达到自动调整的目标需要监听 keyboardWillShowNotification 跟 keyboardWillHideNotification, 同时需要实现点击其它地方时,通知隐藏键盘的事件 ...
- Spark GraphX从入门到实战
第1章 Spark GraphX 概述 1.1 什么是 Spark GraphX Spark GraphX 是一个分布式图处理框架,它是基于 Spark 平台提供对图计算和图挖掘简洁易用的而丰 ...
- python基础--程序交互、格式化输出、流程控制、break、continue
在此申明一下,博客参照了https://www.cnblogs.com/jin-xin/,自己做了部分的改动 (1) 程序交互 #!/usr/bin/env python # -*- coding: ...
- 性能测试之JVM的故障分析工具VisualVM
VisualVM 是随JDK一同发布的jvm诊断工具,通过插件可以扩展很多功能,插件扩展也是其精华所在. 提供了一个可视界面,用于在Java应用程序在Java虚拟机上运行时查看有关Java应用程序的详 ...