今天主要改写昨天的组合模式成Web系统。
容器接口为
public interface TreeProduct {
/**
* 展示所有产品
* @return
*/
List<TreeProduct> allProducts();
/**
* 增加一个产品
* @param product
* @return
*/
boolean addProduct(TreeProduct product);
/**
* 增加一组产品
* @param products
* @return
*/
boolean addProducts(List<TreeProduct> products);
/**
* 移除产品
* @param product
* @return
*/
boolean removeProduct(TreeProduct product);
/**
* 保存数据进数据库
* @param product
* @return
*/
int save(TreeProduct product);
}
产品分类表结构如下
产品表结构如下
对数据库操作的Dao
@Mapper
public interface ProductDao {
@Insert("insert into type_product (id,name) values (#{id},#{name})")
int saveType(TypeProduct type);
@Insert("insert into product (id,name,model,price) values (#{id},#{name},#{model},#{price})")
int saveProduct(Product product);
@Update("update type_product t set t.parent_id=#{sourceId} where t.id=#{id}")
int addType(Param param);
@Update("update product p set p.type_id=#{sourceId} where p.id=#{id}")
int addProduct(Param param);
@Delete("delete from type_product where id=#{id}")
int removeType(Long id);
@Delete("delete from product where id=#{id}")
int removeProduct(Long id);
}
SpringBoot上下文工具
public class SpringBootUtil {
private static ApplicationContext applicationContext = null;
public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringBootUtil.applicationContext == null){
SpringBootUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
在Springboot main方法中获取SpringbootApplication上下文
@EnableTransactionManagement
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(ProductApplication.class, args);
SpringBootUtil.setApplicationContext(applicationContext);
}
}
产品类型类
@NoArgsConstructor
@ToString
public class TypeProduct implements TreeProduct {
@Getter
@Setter
private Long id;
@Getter
@Setter
private String name;
//下级产品列表
@Getter
private List<TreeProduct> treeProducts = new CopyOnWriteArrayList<>();
public TypeProduct(Long id,String name) {
this.id = id;
this.name = name;
}
@Override
public List<TreeProduct> allProducts() {
return this.treeProducts;
}
@Override
public boolean addProduct(TreeProduct product) {
ProductDao productDao = SpringBootUtil.getBean(ProductDao.class);
Param param = null;
if (product instanceof TypeProduct) {
param = new Param(this.id,((TypeProduct) product).getId());
productDao.addType(param);
}else if (product instanceof Product) {
param = new Param(this.id,((Product) product).getId());
productDao.addProduct(param);
}
return treeProducts.add(product);
}
@Override
public boolean removeProduct(TreeProduct product) {
ProductDao productDao = SpringBootUtil.getBean(ProductDao.class);
if (product instanceof TypeProduct) {
productDao.removeType(((TypeProduct) product).getId());
}else if (product instanceof Product) {
productDao.removeProduct(((Product) product).getId());
}
return treeProducts.remove(product);
}
@Override
public boolean addProducts(List<TreeProduct> products) {
for (TreeProduct product:products) {
this.addProduct(product);
}
return true;
}
@Override
public int save(TreeProduct product) {
ProductDao productDao = SpringBootUtil.getBean(ProductDao.class);
if (product instanceof TypeProduct) {
return productDao.saveType((TypeProduct) product);
}
return 0;
}
}
产品类
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Product implements TreeProduct {
private Long id;
private String name;
private String model;
private BigDecimal price;
@Override
public List<TreeProduct> allProducts() {
return Arrays.asList(this);
}
@Override
public boolean addProduct(TreeProduct product) {
throw new RuntimeException("不支持此方法");
}
@Override
public boolean removeProduct(TreeProduct product) {
throw new RuntimeException("不支持此方法");
}
@Override
public boolean addProducts(List<TreeProduct> products) {
throw new RuntimeException("不支持此方法");
}
@Override
public int save(TreeProduct product) {
ProductDao productDao = SpringBootUtil.getBean(ProductDao.class);
if (product instanceof Product) {
return productDao.saveProduct((Product) product);
}
return 0;
}
}
跟以往的贫血模式不同,我们将所有的业务方法放在了实体类中。
产品工厂
public class ProductFactory {
public static TreeProduct createType(Long id,String name) {
TreeProduct product = new TypeProduct(id,name);
product.save(product);
return product;
}
public static TreeProduct createProduct(Long id, String name, String model, BigDecimal price) {
TreeProduct product = new Product(id,name,model,price);
product.save(product);
return product;
}
}
由产品工厂类,我们可以看到,当工厂生产一个产品时,就在数据库中产生一条数据。
对外部的Controller
@RestController
public class ProductController {
@Autowired
private IdService idService;
@Transactional
@GetMapping("/showall")
public TreeProduct showAll() {
//生产一个根目录
TreeProduct root = ProductFactory.createType(idService.genId(),"根目录");
//生产一个可乐的产品类型
TreeProduct type1 = ProductFactory.createType(idService.genId(),"可乐");
//生产一个咖啡的产品类型
TreeProduct type2 = ProductFactory.createType(idService.genId(),"咖啡");
//产品类型列表
List<TreeProduct> types1 = new ArrayList<>();
types1.add(type1);
types1.add(type2);
//生产一个可口可乐的产品
TreeProduct product1 = ProductFactory.createProduct(idService.genId(),"可口可乐","500ml",new BigDecimal(3));
//生产一个雀巢咖啡的产品
TreeProduct product2 = ProductFactory.createProduct(idService.genId(),"雀巢咖啡","600ml",new BigDecimal(6));
//将产品类型列表添加到根目录中
root.addProducts(types1);
//将可口可乐放入可乐类型中
type1.addProduct(product1);
//将雀巢咖啡放入咖啡类型中
type2.addProduct(product2);
//返回整个产品类型和产品
return root;
}
}
对比昨天的Java SE的代码,我们可以看到,这里跟昨天的代码没有什么太大区别,都是对象间的操作,看不到数据库操作的痕迹。
在浏览器访问后的结果
数据库中也有了相应的数据