一个电商项目的Web服务化改造
项目,早期是随便瞎做的,没啥架构,连基本的设计也没。
有需求,实现需求,再反复修改。
大致就是这么做的。
最近,项目要重新架构,和某boss协商的结果是,采用阿里开源的dubbo实现服务化。
前几天,写了一篇dubbo入门案例,分布式服务框架Dubbo入门案例和项目源码
最近,开始实现基本业务功能模块的开发。完成1个模块,原有项目就接入进来,从而完成项目的服务化改造。
在和某boss的商讨之后,我们的做法是
1.只做单表操作,mysql数据库层次不写“关联查询”。
2.针对单个表,实现CRUD等基本操作。
3.层次划分
mapper:基本的数据库CRUD,全部是原子操作
dao:对mapper的数据进行组装,比如关联查询。
之前,是在service层进行代码组装的。
bizService:业务逻辑操作
webService:对外服务层
由于当前阶段,我们的业务逻辑比较简单,bizService和webService可以看成是1层的。
好处:严格的层次划分,上层可以调用下层,同层之间不能互相调用。比如service不能调用其它的service。
4.结合Freemarker,写代码自动生成的工具。根据数据库表,自动生成标准化的代码。
书写中...
类结构
Base*:基础的公共的类
Brand: 具体的,以品牌brand表为例
brand表结构
CREATE TABLE `brand` (
`id` varchar(50) NOT NULL COMMENT 'ID',
`name` varchar(30) DEFAULT NULL COMMENT '品牌名称',
`logo` varchar(100) DEFAULT NULL COMMENT '品牌LOGO',
`isDelete` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
`createTime` datetime DEFAULT NULL COMMENT '创建日期',
`updateTime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='品牌表';
Brand.java:数据库表对应的模型
/**
* 品牌
*
*/
public class Brand {
private String id;
private String name;
private String logo;
private Date createTime;
private Date updateTime;
private Integer isDelete;
}
BaseMapper.java:定义最通用的sql映射。注意,这个mapper没有对应的Mybatis xml配置。
import java.util.List;
public interface BaseMapper<ID, Entity> {
Entity get(ID id);
List<Entity> listByIdList(List<String> idList);
List<Entity> listAll();
int add(Entity entity);
int update(Entity entity);
int remove(ID id);
int removeByIdList(List<ID> idList);
}
BrandMapper.java:品牌的sql映射,Java接口定义
import java.util.List;
@Mapper
public interface BrandMapper extends BaseMapper<String, Brand> {
// read
List<Brand> listByShopIdList(List<String> shopIdList);
List<Brand> list(BrandBean brandBean);
// write
}
BrandMapper.xml:品牌的sql映射,sql语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.webservice.mapper.BrandMapper">
<sql id="columns">
id,name,logo,createTime,updateTime,isDelete
</sql>
<select id="get" resultType="Brand">
select
<include refid="columns" />
from brand
where id =
#{id}
</select>
<select id="list" resultType="Brand">
select
<include refid="columns" />
from brand where
isDelete=0
<if test="name != null and name !=''">
and name like '%${name}%'
</if>
order by createTime desc
</select>
...
}
BaseDao.java:定义最基础、最通用的dao层接口。
import java.util.List;
public interface BaseDao<ID, Entity,Bean> {
//read
Entity get(ID id);
List<Entity> listByIdList(List<String> idList);
List<Entity> list(Bean bean);
List<Entity> listAll();
//write
int add(Entity entity);
int update(Entity entity);
int remove(ID id);
int removeByIdList(List<ID> idList);
}
BrandDao.java: 品牌的dao接口
import java.util.List;
public interface BrandDao extends BaseDao<String, Brand,BrandBean> {
// read
List<Brand> listByShopIdList(List<String> shopIdList);
List<String> listLogoByIdList(List<String> idList);
// write
}
BrandDaoImpl.java:品牌的dao接口实现类
@Component
public class BrandDaoImpl implements BrandDao {
@Autowired
private BrandMapper brandMapper;
private Logger logger = Logger.getLogger(getClass());
@Override
public Brand get(String id) {
if(StringUtils.isEmpty(id)){
logger.error("The id is null");
return null;
}
return brandMapper.get(id);
}
@Override
public List<Brand> listByIdList(List<String> idList) {
if (CollectionUtils.isEmpty(idList)) {
logger.error("The idList is empty");
return null;
}
return brandMapper.listByIdList(idList);
}
}
BrandService.java: 品牌,业务层的接口定义
代码类似
BrandServiceImpl.java:品牌,业务层的接口实现
代码类似
junit单元测试:测dao和service层,mapper层忽视
BaseDaoTest.java:dao基础配置
//单元测试的mysql数据库,最好是单独的一套库,没有任何数据。如果开发和单元测试共用数据库,listAll之类的方法会有影响。
//单元测试:1.构造数据,2.执行操作,3.断言,4.回滚
//设置自动回滚
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
@ContextConfiguration(locations={"classpath*:spring-dataSource.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class BaseDaoTest {
public static final String NOT_EXIST_ID_STRING="not_exist_id_string";
public static final String NOT_EXIST_ID_INT="not_exist_id_int";
public static final String EXIST_NAME = "test";
public static final String NOT_EXIST_NAME = "not_exist_name";
}
BrandDaoTest.java:brand的基础测试用例
public class BrandDaoTest extends BaseDaoTest {
@Autowired
private BrandDao brandDao;
// //read//
@Test
public void testGet() {
Brand brand = TestDataCenter.brand();
brandDao.add(brand);
Brand dbBrand = brandDao.get(brand.getId());
assertNotNull(dbBrand);
}
@Test
public void testGetNotExist() {
Brand brand = TestDataCenter.brand();
brandDao.add(brand);
Brand nullBrand = brandDao.get(NOT_EXIST_ID_STRING);
assertNull(nullBrand);
}
}
BaseServiceTest.java:service基础配置
代码类似
BrandServiceTest.java:brand的基础测试用例
代码类似
单元测试结果图
spring数据源配置,spring-dataSource.xml
除了Base基础接口,具体的业务类,计划通过代码生成工具自动生成。
我们保证内部代码mapper层和dao层代码正确,保证service层正确,然后用dubbo把service的代码,稍微做点配置,对外提供服务。
其它项目,比如front前端商城系统、mobile移动App、backend后端运营系统,直接调用咱们的服务接口即可。
标签:Web,java,服务化,int,brand,List,id,电商,public From: https://blog.51cto.com/fansunion/6245773