zoukankan      html  css  js  c++  java
  • 一个电商项目的Web服务化改造

    一个电商项目的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后端运营系统,直接调用咱们的服务接口即可。
  • 相关阅读:
    演示使用string对象(续)
    P2216 [HAOI2007]理想的正方形 单调队列
    SP1805 HISTOGRA
    P4556 [Vani有约会]雨天的尾巴 树链剖分 线段树合并
    codeforces 600E 线段树合并
    HDU2197 本原串
    P3806 【模板】点分治1
    牛客10 Popping Balloons
    P3261 [JLOI2015]城池攻占 左偏树
    P4549 【模板】裴蜀定理
  • 原文地址:https://www.cnblogs.com/qitian1/p/6462434.html
Copyright © 2011-2022 走看看