评论

收藏

[Java] 详解spring-boot下如何满足多生产环境中个性化定制功能

编程语言 编程语言 发布于:2021-09-17 22:28 | 阅读数:328 | 评论:0

这篇文章主要介绍了详解spring-boot下如何满足多生产环境中个性化定制功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
在项目的开发中,我们很难做到开发一套标准的流程来解决所有客户的需求。比如,我们当前的计量项目,分别运行于赤峰市和河北省。虽然两个区域处理的业务相同,但是对细节的实现要求却不同。前面也学习过计量检定软件,其为了解决各个定制者使用的功能需求,最后采取的方案是:将基础项目复制多份,进而满足不同的客户需求。优点当然是有的,但比起缺点来,优点便不值一提。缺点很明显,总结为一句话就是:项目变得难以维护。所以,当前让我们看到的就是,几个开发人员,每天处于解决问题当中。本文将给出一种方案,来有效的规避上述问题。
资源与环境
示例代码:https://github.com/mengyunzhi/springbootsamplecode/tree/master/dynamic-autowire
开发环境:java1.8 + spring-boot:2.1.3.release
需求假设

  • 假设使用本项目的人员为:中国人、美国人,分别能接受的语言为中文和英文。
  • 项目运行后,可以根据当前的访问人员是国籍来动态显示:你好或hello
  • 有新的需求后,比如:增加德国人并显示hallo。增加功能时,不更改核心代码。
  • 不使用if else
注意:如果你看完需求假设后,毫无触动,请忽略本文以下内容
解决方案
解决方案中,我们涉及了两种设计模块,分别为:策略模式及工厂模式。
策略模式:一般用于将具体的算法进行抽象及剥离。此项目中,我们的具体算法是说你好。
工厂模式:一般用于根据环境来动态的创建bean的情况下。引项目中,我们将根据不同国家的人,来返回不同的说你好这个算法。
先给出uml图:
DSC0000.png

speakservice
speakservice即为我们供其它模块调用的说话服务,调用其中的sayhello()来完成说你好功能。
package com.mengyunzhi.demo.dynamicautowire;
 
/**
 * 你好
 */
public interface speakservice {
  void sayhello();
}
在其实现类中,我们注入sayhellofactory,让其来返回正确的sayhelloservice,最终调用sayhello()来完成目标。
package com.mengyunzhi.demo.dynamicautowire;
 
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.service;
 
/**
 * 你好
 */
@service
public class speakserviceimpl implements speakservice {
  private final
  sayhellofactory sayhellofactory; // 说话工厂
 
  @autowired
  public speakserviceimpl(sayhellofactory sayhellofactory) {
  this.sayhellofactory = sayhellofactory;
  }
 
  @override
  public void sayhello() {
  this.sayhellofactory.getsayhelloservice().sayhello();
  }
}
sayhellofactory
package com.mengyunzhi.demo.dynamicautowire;
 
/**
 * 说话工厂
 */
public interface sayhellofactory {
 
  void setcountrycode(countrycode countrycode);
 
  sayhelloservice getsayhelloservice();
}
在此,我们增加一个countrycode表示当前访问者的国家。其实在获取访问者国家时,我们也可以调用其它bean的其它来实现。
package com.mengyunzhi.demo.dynamicautowire;
 
/**
 * 国家代码
 */
public enum countrycode {
  china((byte) 0, "中国"),
  usa((byte) 1, "美国");
  private byte code;
  private string name;
 
  countrycode(byte code, string name) {
  this.code = code;
  this.name = name;
  }
 
  public byte getcode() {
  return code;
  }
  public string getname() {
  return name;
  }
}
使用enum来控制范围,避免factory在获取bean时发生异常。
package com.mengyunzhi.demo.dynamicautowire;
 
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.service;
 
import java.util.hashmap;
import java.util.list;
import java.util.map;
 
/**
 * 说话工厂
 */
@service
public class sayhellofactoryimpl implements sayhellofactory {
  /**
   * bean列表
   */
  private final map<byte, sayhelloservice> servicesbycode = new hashmap<>();
  /**
   * 国家代码
   */
  private countrycode countrycode = countrycode.china;
 
  @override
  public void setcountrycode(countrycode countrycode) {
  this.countrycode = countrycode;
  }
 
  /**
   * 初始化
   *
   * @param sayhelloservices spring获取到的所以实现了speakservice的bean
   */
  @autowired
  public void init(list<sayhelloservice> sayhelloservices) {
  for (sayhelloservice sayhelloservice : sayhelloservices) {
    this.register(sayhelloservice.getcode(), sayhelloservice);
  }
  }
 
  /**
   * 注册bean
   *
   * @param code   代码
   * @param sayhelloservice bean
   */
  private void register(byte code, sayhelloservice sayhelloservice) {
  this.servicesbycode.put(code, sayhelloservice);
  }
 
  /**
   * 获取bean
   *
   * @return 对应的sayhelloservice bean
   */
  @override
  public sayhelloservice getsayhelloservice() {
  return this.servicesbycode.get(this.countrycode.getcode());
  }
}
增加map<byte, sayhelloservice> servicesbycode来存储对应国家的sayhelloservicebean。增加getsayhelloservice()来根据当前国家代码来返回相应的bean。
sayhelloservice
package com.mengyunzhi.demo.dynamicautowire;
 
/**
 * 说话
 */
public interface sayhelloservice {
  void sayhello();
 
  byte getcode();
}
将sayhello()方法抽离,getcode()以获取国家代码。
中国人你好
package com.mengyunzhi.demo.dynamicautowire;
 
import org.springframework.stereotype.component;
 
/**
 * 中国话
 */
@component
public class sayhelloservicechineseimpl implements sayhelloservice {
  @override
  public void sayhello() {
  system.out.println("您好");
  }
 
  @override
  public byte getcode() {
  return countrycode.china.getcode();
  }
}
美国人hello
package com.mengyunzhi.demo.dynamicautowire;
 
import org.springframework.stereotype.component;
 
/**
 * 美国话
 */
@component
public class sayhelloserviceenglishimpl implements sayhelloservice {
  @override
  public void sayhello() {
  system.out.println("hello");
  }
 
  @override
  public byte getcode() {
  return countrycode.usa.getcode();
  }
}
测试
package com.mengyunzhi.demo.dynamicautowire;
 
import org.junit.test;
import org.junit.runner.runwith;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;
import org.springframework.test.context.junit4.springrunner;
 
@springboottest
@runwith(springrunner.class)
public class speakserviceimpltest {
  @autowired
  speakservice speakservice;
  @autowired
  sayhellofactory sayhellofactory;
 
  @test
  public void sayhello() {
  // 默认说你好
  speakservice.sayhello();
 
  // 将国家设置为美国,再说你好
  sayhellofactory.setcountrycode(countrycode.usa);
  speakservice.sayhello();
 
  // 将国家设置为中国,再说你好
  sayhellofactory.setcountrycode(countrycode.china);
  speakservice.sayhello();
  }
}
您好
hello
您好
时序图
DSC0001.jpg

增加德国人
增加德国人sayhelloservicegermanyimpl.
在countrycode中,增加德国.
package com.mengyunzhi.demo.dynamicautowire;
 
import org.springframework.stereotype.component;
 
@component
public class sayhelloservicegermanyimpl implements sayhelloservice {
  @override
  public void sayhello() {
  system.out.println("hallo");
  }
 
  @override
  public byte getcode() {
  return countrycode.germany.getcode();
  }
}
package com.mengyunzhi.demo.dynamicautowire;
 
/**
 * 国家代码
 */
public enum countrycode {
  china((byte) 0, "中国"),
  usa((byte) 1, "美国"),
  germany((byte) 2, "德国");
  private byte code;
  private string name;
 
  countrycode(byte code, string name) {
  this.code = code;
  this.name = name;
  }
 
  public byte getcode() {
  return code;
  }
 
  public string getname() {
  return name;
  }
}
单元测试
@test
 public void sayhello1() {
   // 默认说你好
   speakservice.sayhello();
 
   // 将国家设置为美国,再说你好
   sayhellofactory.setcountrycode(countrycode.usa);
   speakservice.sayhello();
 
   // 将国家设置为德国,再说你好
   sayhellofactory.setcountrycode(countrycode.germany);
   speakservice.sayhello();
 
   // 将国家设置为中国,再说你好
   sayhellofactory.setcountrycode(countrycode.china);
   speakservice.sayhello();
 }
测试结果如下:
您好
hello
hallo
您好
总结
在解决问题时,只所有我们看的不够远,可能是由于自己站的不够高。同样的问题,困惑我了多日,直到近期系统的学习设计模式 、angular官方教程、spring 实战后,结合近期项目变更带来的新需求,才在使用设计模式解决此问题上有所启发。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家
原文链接:https://segmentfault.com/a/1190000018673552

关注下面的标签,发现更多相似文章