前言介绍
在实际的业务开发中按照不同的场景需要,会有不同的业务架构也就同时会有不同的技术框架来支撑。那么这个专题想把一些常用的框架整理下,方便平时使用的同时也做一些技术沉淀。那么本章节会先搭建一个比较适合个人项目或者一些小公司开发项目的单体架构模型。服务功能展示页面如下;
工程环境
-
JDK1.8
-
Maven 3.2.3
-
Spring 4.3.24.RELEASE + SpringMvc + Mybatis 3.3.0
-
Mysql 5.6 + dbcp2
-
layui 2.5.4
工程模型
整体的工程模型采用DDD四层架构,相对于MVC模式来讲。嗯!相当于家里三居换四居了!
1itstack-demo-frame-ssm 2└── src 3 ├── main 4 │ ├── java 5 │ │ └── org.itstack.demo 6 │ │ ├── application 7 │ │ │ └── UserService.java 8 │ │ ├── domain 9 │ │ │ ├── model 10 │ │ │ │ ├── aggregates 11 │ │ │ │ │ └── UserInfoCollect.java 12 │ │ │ │ ├── req 13 │ │ │ │ │ └── UserReq.java 14 │ │ │ │ └── vo 15 │ │ │ │ └── UserInfo.java 16 │ │ │ ├── repository 17 │ │ │ │ └── IUserRepository.java 18 │ │ │ └── service 19 │ │ │ └── UserServiceImpl.java 20 │ │ ├── infrastructure 21 │ │ │ ├── common 22 │ │ │ │ ├── EasyResult.java 23 │ │ │ │ └── PageRequest.java 24 │ │ │ ├── dao 25 │ │ │ │ └── IUserDao.java 26 │ │ │ ├── po 27 │ │ │ │ └── User.java 28 │ │ │ └── repository 29 │ │ │ └── UserRepository.java 30 │ │ └── interfaces 31 │ │ └── UserController.java 32 │ ├── resources 33 │ │ ├── mapper 34 │ │ ├── props 35 │ │ ├── spring 36 │ │ ├── logback.xml 37 │ │ ├── mybatis-config.xml 38 │ │ └── spring-config.xml 39 │ └── webapp 40 │ ├── page 41 │ ├── res 42 │ ├── WEB-INF 43 │ ├── index.html 44 │ └── res_layui.html 45 └── test 46 └── java 47 └── org.itstack.demo.test 48 └── ApiTest.java
以下对工程模块进行介绍,整体源码获取,可以关注公众号:bugstack虫洞栈,回复:框架搭建
application应用层
应用层是比较薄的一层,不做具体逻辑开发。本工程里只包括服务的定义,具体逻辑有领域层实现。如果需要扩展可以做一些应用服务编排。
application/UserService.java & 定义接口
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public interface UserService { 7 8 UserInfoCollect queryUserInfoList(UserReq req); 9 10}
domain领域层
领域层是整个工程的核心服务层,这里负责处理具体的核心功能,完成领域服务。domain下可以有多个领域,每个领域里包括;聚合、请求对象、业务对象、仓储、服务。
domain/model/aggregates/UserInfoCollect.java & 定义聚合查询结果
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class UserInfoCollect { 7 8 private Long count; 9 private List<UserInfo> userInfoList; 10 11 public UserInfoCollect() { 12 } 13 14 public UserInfoCollect(Long count, List<UserInfo> userInfoList) { 15 this.count = count; 16 this.userInfoList = userInfoList; 17 } 18 19 public Long getCount() { 20 return count; 21 } 22 23 public void setCount(Long count) { 24 this.count = count; 25 } 26 27 public List<UserInfo> getUserInfoList() { 28 return userInfoList; 29 } 30 31 public void setUserInfoList(List<UserInfo> userInfoList) { 32 this.userInfoList = userInfoList; 33 } 34}
domain/repository/IUserRepository.java & 定义仓储服务
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public interface IUserRepository { 7 8 UserInfoCollect queryUserInfoList(UserReq req); 9 10}
domain/service/UserServiceImpl.java & 对业务层功能进行实现
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6@Service("userService") 7public class UserServiceImpl implements UserService { 8 9 @Resource(name = "userRepository") 10 private IUserRepository userRepository; 11 12 @Override 13 public UserInfoCollect queryUserInfoList(UserReq req) { 14 return userRepository.queryUserInfoList(req); 15 } 16 17}
infrastructure基础层
-
实现领域层仓储定义
-
数据库操作为非业务属性的功能操作
-
在仓储实现层进行组合装配DAO&Redis&Cache等
infrastructure/dao/IUserDao.java & 数据库操作
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public interface IUserDao { 7 8 List<User> queryUserInfoList(UserReq req); 9 10 Long queryUserInfoCount(UserReq req); 11 12}
infrastructure/repository/UserRepository.java & 仓储功能实现如果有redis可以进行包装使用
1/** 2 * 微信公众号:bugstack虫洞栈 | 欢迎关注学习专题案例 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6@Repository("userRepository") 7public class UserRepository implements IUserRepository { 8 9 @Resource 10 private IUserDao userDao; 11 12 @Override 13 public UserInfoCollect queryUserInfoList(UserReq req) { 14 Long count = userDao.queryUserInfoCount(req); 15 List<User> userList = userDao.queryUserInfoList(req); 16 List<UserInfo> userInfoList = new ArrayList<>(); 17 userList.forEach(user -> { 18 UserInfo userInfo = new UserInfo(); 19 userInfo.setUserId(user.getId()); 20 userInfo.setName(user.getName()); 21 userInfo.setAge(user.getAge()); 22 userInfo.setAddress(user.getAddress()); 23 userInfo.setEntryTime(user.getEntryTime()); 24 userInfo.setStatus(user.getStatus()); 25 userInfoList.add(userInfo); 26 }); 27 return new UserInfoCollect(count, userInfoList); 28 } 29 30}
interfaces接口层
-
包装应用接口对外提供api,目前这一层比较简单只需要进行接口使用即可
-
如果是对外部提供服务接口,那么可以使用DTO方式进行转换,避免污染到业务类
interfaces/UserController.java & 提供接口服务
1@Controller 2@RequestMapping("/api/user/") 3public class UserController { 4 5 private Logger logger = LoggerFactory.getLogger(UserController.class); 6 7 @Resource 8 private UserService userService; 9 10 @RequestMapping(path = "queryUserInfoList", method = RequestMethod.GET) 11 @ResponseBody 12 public EasyResult queryUserInfoList(String json, String page, String limit) { 13 try { 14 logger.info("查询用户信息列表开始。json:{}", json); 15 UserReq req = JSON.parseObject(json, UserReq.class); 16 if (null == req) req = new UserReq(); 17 req.setPage(page, limit); 18 UserInfoCollect userInfoCollect = userService.queryUserInfoList(req); 19 logger.info("查询用户信息列表完成。userInfoCollect:{}", JSON.toJSONString(userInfoCollect)); 20 return EasyResult.buildEasyResultSuccess(userInfoCollect.getCount(), userInfoCollect.getUserInfoList()); 21 } catch (Exception e) { 22 logger.error("查询用户信息列表失败。json:{}", json, e); 23 return EasyResult.buildEasyResultError(e); 24 } 25 } 26 27}
resource配置
这里包括了Spring、SpringMvc、mybatis、以及日志信息的配置;
mapper/User_Mapper.xml
1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6<mapper namespace="org.itstack.demo.infrastructure.dao.IUserDao"> 7 8 <select id="queryUserInfoCount" resultType="java.lang.Long"> 9 select count(id) 10 from user 11 <where> 12 <if test="name != null"> 13 and name = #{name} 14 </if> 15 <if test="status != null"> 16 and status = #{status} 17 </if> 18 </where> 19 </select> 20 21 <select id="queryUserInfoList" resultType="org.itstack.demo.infrastructure.po.User"> 22 SELECT id, name, age, address, entryTime, status, remark, createTime, updateTime 23 FROM user 24 <where> 25 <if test="name != null"> 26 and name = #{name} 27 </if> 28 <if test="status != null"> 29 and status = #{status} 30 </if> 31 </where> 32 limit #{pageStart},#{pageEnd} 33 </select> 34 35</mapper>
props/jdbc.properties & 数据库链接信息
1db.jdbc.driverClassName=com.mysql.jdbc.Driver 2db.jdbc.url=jdbc:mysql://127.0.0.1:3306/itstack?createDatabaseIfNotExist=true&characterEncoding=utf-8&useUnicode=true 3db.jdbc.username=root 4db.jdbc.password=123456
spring/spring-config-datasource.xml & dbcp2数据源配置以及扫描Mapper等
1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <!-- 1.数据库连接池 --> 8 <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> 9 <property name="driverClassName" value="${db.jdbc.driverClassName}" /> 10 <property name="url" value="${db.jdbc.url}" /> 11 <property name="username" value="${db.jdbc.username}" /> 12 <property name="password" value="${db.jdbc.password}" /> 13 <property name="maxTotal" value="20" /> 14 <property name="maxIdle" value="3" /> 15 <property name="maxWaitMillis" value="15000" /> 16 <property name="timeBetweenEvictionRunsMillis" value="60000" /> 17 <property name="minEvictableIdleTimeMillis" value="180000" /> 18 </bean> 19 20 <!-- 2.配置SqlSessionFactory对象 --> 21 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 22 <!-- 注入数据库连接池 --> 23 <property name="dataSource" ref="dataSource" /> 24 <!-- 配置MyBaties全局配置文件:mybatis-config.xml --> 25 <property name="configLocation" value="classpath:mybatis-config.xml" /> 26 <!-- 扫描entity包 使用别名 --> 27 <property name="typeAliasesPackage" value="com.soecode.lyf.entity" /> 28 <!-- 扫描sql配置文件:mapper需要的xml文件 --> 29 <property name="mapperLocations" value="classpath:mapper/*.xml" /> 30 </bean> 31 32 <!-- 3.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 --> 33 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 34 <!-- 注入sqlSessionFactory --> 35 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> 36 <!-- 给出需要扫描Dao接口包 --> 37 <property name="basePackage" value="org.itstack.demo.infrastructure.dao" /> 38 </bean> 39 40</beans>
resources/mybatis-config.xml
1<?xml version="1.0" encoding="UTF-8" ?> 2<!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5<configuration> 6 <!-- 配置全局属性 --> 7 <settings> 8 <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 --> 9 <setting name="useGeneratedKeys" value="true" /> 10 <!-- 使用列别名替换列名 默认:true --> 11 <setting name="useColumnLabel" value="true" /> 12 <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} --> 13 <setting name="mapUnderscoreToCamelCase" value="true" /> 14 </settings> 15</configuration>
resources/spring-config.xml
1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" 7 default-autowire="byName"> 8 9 <context:component-scan base-package="org.itstack"/> 10 <aop:aspectj-autoproxy/> 11 12 <!-- 属性文件读入 --> 13 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 14 <property name="locations"> 15 <list> 16 <value>classpath:props/*.properties</value> 17 </list> 18 </property> 19 </bean> 20 21 <import resource="classpath:spring/spring-*.xml"/> 22 23</beans> 24
itstack.sql
1DROP TABLE user; 2CREATE TABLE user ( id bigint(11) NOT NULL AUTO_INCREMENT, name varchar(32), age int(4), address varchar(128), entryTime datetime, remark varchar(64), createTime datetime, updateTime datetime, status int(4) DEFAULT '0', PRIMARY KEY (id), INDEX idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 3insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status) values (1, '水水', 18, '吉林省榆树市黑林镇尹家村5组', '2019-12-22 00:00:00', '无', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 0); 4insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status) values (2, '豆豆', 18, '辽宁省大连市清河湾司马道407路', '2019-12-22 00:00:00', '无', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 1); 5insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status) values (3, '花花', 19, '辽宁省大连市清河湾司马道407路', '2019-12-22 00:00:00', '无', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 0);
综上总结
-
此工程模型基于SSM比较适合开发ERP服务,ERP使用layui页面清新,功能完善
-
工程框架采用了DDD架构模式,在此架构模式下可以更容易的开发系统,适应后比MVC更加方便
-
后续将继续拓展架构服务搭建,包括一些Dubbo、Redis、mq等使用,方便自己也方便他人