我的编码习惯 - 配置规范

原文出处:晓风轻

导读:程序员你为什么这么累?

导读(请先仔细阅读):分享我工作中制定配置文件的习惯

工作中少不了要制定各种各样的配置文件,这里和大家分享一下工作中我是如何制定配置文件的,这是个人习惯,结合强大的spring,效果很不错。

=============================需求==========================

如我们现在有一个这样的配置需求,顶层是Server,有port和shutdown2个属性,包含一个service集合,service对象有name一个属性,并包含一个connector集合,connector对象有port和protocol2个属性。

我一上来不会去考虑是用xml还是json还是数据库配置,我会第一步写好对应的配置bean。如上面的需求,就写3个bean。bean和bean之间的包含关系要体现出来。(使用了lombok)

@Data
public class ServerCfg {
  private int port = 8005;
  private String shutDown = "SHUTDOWN";
  private List<ServiceCfg> services;
}

@Data
public class ServiceCfg {
  private String name;
  private List<ConnectorCfg> connectors;
}

@Data
public class ConnectorCfg {
  private int port = 8080;
  private String protocol = "HTTP/1.1";
}

然后找一个地方先用代码产生这个bean:

@Configuration
public class Configs {

  @Bean
  public ServerCfg createTestBean() {
    ServerCfg server = new ServerCfg();

    //
    List<ServiceCfg> services = new ArrayList<ServiceCfg>();
    server.setServices(services);

    //
    ServiceCfg service = new ServiceCfg();
    services.add(service);

    service.setName("Kitty");

    //
    List<ConnectorCfg> connectors = new ArrayList<ConnectorCfg>();
    service.setConnectors(connectors);

    //
    ConnectorCfg connectorhttp11 = new ConnectorCfg();

    connectorhttp11.setPort(8088);
    connectorhttp11.setProtocol("HTTP/1.1");

    connectors.add(connectorhttp11);

    //
    ConnectorCfg connectorAJP = new ConnectorCfg();

    connectorAJP.setPort(8089);
    connectorAJP.setProtocol("AJP");

    connectors.add(connectorAJP);

    return server;
  }
}

然后先测试,看看是否ok。为了演示,我就直接在controller里面调用一下

@Autowired
ServerCfg cfg;

@GetMapping(value = "/configTest")
@ResponseBody
public ResultBean<ServerCfg> configTest() {
  return new ResultBean<ServerCfg>(cfg);
}

测试一下,工作正常

然后进行业务代码编写,等到所有功能测试完毕,就是【开发后期】,再来定义配置文件。中途当然少不了修改格式,字段等各种修改,对于我们来说只是修改bean定义,so easy。

都ok了,再决定使用哪种配置文件。如果是json,我们这样:

==============================JSON===========================

把上面接口调用的json复制下来,报存到配置文件。

json内容

{
  "port": 8005,
  "shutDown": "SHUTDOWN",
  "services": [
    {
      "name": "Kitty",
      "connectors": [
        {
          "port": 8088,
          "protocol": "HTTP/1.1",
          "executor": null
        },
        {
          "port": 8089,
          "protocol": "AJP",
          "executor": null
        }
      ]
    }
  ]
}

然后修改config的bean生成的代码为:

import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class Configs {
  @Value("classpath:config/tomcat.json")
  File serverConfigJson;

  @Bean
  public ServerCfg readServerConfig() throws IOException {
    return new ObjectMapper().readValue(serverConfigJson, ServerCfg.class);
  }
}

代码太简洁了,有没有?!

==============================XML===========================

如果使用XML,麻烦一点,我这里使用XStream序列化和反序列化xml。

首先在bean上增加XStream相关注解

@Data
@XStreamAlias("Server")
public class ServerCfg {

  @XStreamAsAttribute
  private int port = 8005;

  @XStreamAsAttribute
  private String shutDown = "SHUTDOWN";

  private List<ServiceCfg> services;

}

@Data
@XStreamAlias("Service")
public class ServiceCfg {

  @XStreamAsAttribute
  private String name;

  private List<ConnectorCfg> connectors;
}

@Data
@XStreamAlias("Connector")
public class ConnectorCfg {
  @XStreamAsAttribute
  private int port = 8080;

  @XStreamAsAttribute
  private String protocol = "HTTP/1.1";
}

然后修改产品文件的bean代码如下:

@Configuration
public class Configs {
  @Value("classpath:config/tomcat.xml")
  File serverConfigXML;

  @Bean
  public ServerCfg readServerConfig() throws IOException {
    return XMLConfig.toBean(serverConfigXML, ServerCfg.class);
  }
}

XMLConfig工具类相关代码:

public class XMLConfig {

  public static String toXML(Object obj) {
    XStream xstream = new XStream();

    xstream.autodetectAnnotations(true);
    // xstream.processAnnotations(Server.class);

    return xstream.toXML(obj);
  }

  public static <T> T toBean(String xml, Class<T> cls) {
    XStream xstream = new XStream();

    xstream.processAnnotations(cls);
    T obj = (T) xstream.fromXML(xml);

    return obj;
  }

  public static <T> T toBean(File file, Class<T> cls) {
    XStream xstream = new XStream();

    xstream.processAnnotations(cls);
    T obj = (T) xstream.fromXML(file);

    return obj;
  }

}

XStream库需要增加以下依赖:

<dependency>
  <groupId>com.thoughtworks.xstream</groupId>
  <artifactId>xstream</artifactId>
  <version>1.4.10</version>
</dependency>

所以个人爱好,格式推荐json格式配置。

=========================编码习惯=========================

配置文件编码禁忌

1. 读取配置的代码和业务代码耦合在一起!大忌!千万千万不要!

如下,业务代码里面出现了json的配置代码。

public void someServiceCode() {
  // 使用json配置,这里读取到了配置文件,返回的是json格式
  JSONObject config = readJsonConfig();

  // 如果某个配置了
  if(config.getBoolean("somekey")){
    // dosomething
  }
  else{

  }
}

2. 开发初期就定配置文件

毫无意义,还导致频繁改动!先定义bean,改bean简单多了。我的习惯是转测试前一天才生成配置文件。

=============================重要============================

最主要的思想是,不要直接和配置文件发生关系,一定要有第三者(这里是配置的bean)。你可以说是中间件,中介都行。 否则,一开始说用xml配置,后面说用json配置,再后面说配置放数据库?这算不算需求变更?你们说算不算?算吗?不算吗?何必这么认真呢?只是1,2行代码的问题,这里使用xml还是json,代码修改量是2行。而且改了测试的话,写个main函数或者junit测试即可,不需要测试业务,工程都不用起,你自己算算节约多少时间

另外,代码里面是使用spring的习惯,没有spring也是一样的,或者配置的bean你不用spring注入,而用工具类获取也是一样,区别不大。

时间: 2024-07-31 14:25:54

我的编码习惯 - 配置规范的相关文章

我的编码习惯 - 如何应对需求变更

原文出处:晓风轻 我之前的文章 程序员你为什么这么累? 中,我个人观点是加班原因是编码质量占了大部分因素,但是不少同学都不认为是代码质量导致的加班,都认为是不断的需求改动导致的加班.这位同学,说的好像别人的需求就不会变动似的!谁的需求不改动啊?不改动的能叫需求吗?哈哈. 先看几个程序员的段子娱乐一下 杀一个程序员不需要用枪,改三次需求就可以了. 看一个宫保鸡丁的段子娱乐一下:这TM就是设计师不想改图的真正原因!!! 客户被绑,蒙眼,惊问:"想干什么?"对方不语,鞭笞之,客户求饶:&qu

我的编码习惯 - 参数校验和国际化规范

原文出处:晓风轻 导读:程序员你为什么这么累? 今天我们说说参数校验和国际化,这些代码没有什么技术含量,却大量充斥在业务代码上,很可能业务代码只有几行,参数校验代码却有十几行,非常影响代码阅读,所以很有必要把这块的代码量减下去. 今天的目的主要是把之前例子里面的和业务无关的国际化参数隐藏掉,以及如何封装好校验函数. 先看对比图,修改前: service中: 修改后: service中: Controll的非业务代码如何去掉参考我的编码习惯 - Controller规范,下面说说去掉Local参数

程序员你为什么这么累【续】:编码习惯之日志建议

转自:https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247484164&idx=1&sn=8351e9fb42e6471e31d1c060d46bfafa&chksm=9bd0ae9caca7278a0941e8044a042775a707ec0dc8873f4da4bc1a7628f2462a10085a83206c&mpshare=1&scene=23&srcid=0924D5ojS

C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义(转载)

C#与Java对比学习:类型判断.类与接口继承.代码规范与编码习惯.常量定义 类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 instanceof 符号判断 类与接口的继承: C#:public class MDataRow : List<MDataCell>, IDataRecord, ICustomTypeDescriptor Java:publi

JS 的5个不良编码习惯,现在就改掉吧 &#225452;

原文: http://blog.gqylpy.com/gqy/422 置顶:来自一名75后老程序员的武林秘籍--必读(博主推荐) 来,先呈上武林秘籍链接:http://blog.gqylpy.com/gqy/401/ 你好,我是一名极客!一个 75 后的老工程师! 我将花两分钟,表述清楚我让你读这段文字的目的! 如果你看过武侠小说,你可以把这个经历理解为,你失足落入一个山洞遇到了一位垂暮的老者!而这位老者打算传你一套武功秘籍! 没错,我就是这个老者! 干研发 20 多年了!我也年轻过,奋斗过!我

JS 的5个不良编码习惯

1.不要使用隐式类型转换 JavaScript是一种松散类型的语言.如果使用得当,这是一个好处,因为它给你带来了灵活性. 大多数运算符 +-*/==(不包括 ===)在处理不同类型的操作数时会进行隐式转换. 语句 if(condition){...}, while(condition){...}隐式地将条件转换为布尔值. 下面的示例依赖于类型的隐式转换,这种有时候会让人感到很困惑: console.log("2" + "1"); // => "21&

我的编码习惯 - 接口定义

原文出处: 晓风轻 工作中,少不了要定义各种接口,系统集成要定义接口,前后台掉调用也要定义接口.接口定义一定程度上能反应程序员的编程功底.列举一下工作中我发现大家容易出现的问题: 1. 返回格式不统一 同一个接口,有时候返回数组,有时候返回单个:成功的时候返回对象,失败的时候返回错误信息字符串.工作中有个系统集成就是这样定义的接口,真是辣眼睛.这个对应代码上,返回的类型是map,json,object,都是不应该的.实际工作中,我们会定义一个统一的格式,就是ResultBean,分页的有另外一个

ArcGIS API for JS的一般编码习惯

1.引用claro.css和esri.css <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/dojo/dijit/themes/claro/claro.css"> <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css"> 2.页面布局 &

java良好的编码习惯

1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控制资源的并发访问: 第二,控制实例的产生,以达到节约资源的目的: 第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信. 2. 尽量避免随意使用静态变量 要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如 Java代码 p