长沙网站建设  鼎誉,网站建设前的问卷,东莞高埗网站建设,网站正在建设中怎么办Java#xff1a;性能优化细节01-10 
在Java程序开发过程中#xff0c;性能优化是一个重要的考虑因素。常见的误解是将性能问题归咎于Java语言本身#xff0c;然而实际上#xff0c;性能瓶颈更多地源于程序设计和代码实现方式的不当。因此#xff0c;培养良好的编码习惯不仅…Java性能优化细节01-10 
在Java程序开发过程中性能优化是一个重要的考虑因素。常见的误解是将性能问题归咎于Java语言本身然而实际上性能瓶颈更多地源于程序设计和代码实现方式的不当。因此培养良好的编码习惯不仅对提升程序性能至关重要同时也有助于增强代码的可读性和可维护性。 
1、尽量在合适的场合使用单例 
使用单例模式是一种有效的设计策略用于在整个应用程序中管理资源的使用、实例的创建以及数据的共享。这种模式通过确保一个类只有一个实例并提供一个全局访问点来访问该实例可以在多种情况下提高效率和性能。不过单例模式的应用需要根据具体场景谨慎考虑因为不恰当的使用可能会带来一些问题如过度使用可能会导致代码的耦合度增高测试难度加大等。下面是单例模式主要适用场景的扩展和优化说明 控制资源的使用在许多应用场景中某些资源如数据库连接、线程池等是稀缺资源过度创建和销毁不仅消耗大量系统资源还可能导致性能瓶颈。单例模式通过确保这类资源在应用程序中仅有一个实例可以有效地控制资源的使用通过线程同步机制控制对这些资源的并发访问从而确保资源使用的高效性和安全性。  控制实例的产生单例模式限制了类的实例化次数帮助节约系统资源。在一些场景下如配置管理器、连接池等确保全局只有一个实例不仅可以节省资源还可以避免潜在的冲突和错误。此外单例也有助于实现延迟初始化即实例在首次使用时才被创建进一步优化资源的使用和程序启动时间。  控制数据共享在分布式系统或多线程环境中需要在不同的进程或线程间共享数据时单例模式提供了一个简洁有效的解决方案。通过共享的单例实例可以方便地在各个组件之间共享和访问状态信息或配置数据而无需建立复杂的通信机制或直接依赖。这种方式简化了数据共享的逻辑降低了系统的复杂度。  
 然而单例模式并非万能钥匙其使用场景应当根据具体需求仔细考量。例如在需要考虑扩展性和灵活性时单例可能会限制系统设计的灵活度。此外单例模式在多线程环境下可能会遇到同步问题需要通过额外的同步机制来确保线程安全这可能会影响到系统的性能。因此设计时应权衡单例模式的优点与潜在的限制确保其最终能够为系统带来预期的收益。 
2、尽量避免随意使用静态变量 
在Java编程中静态变量因其全局访问性和持久存储特性而被广泛使用。静态变量存储在JVM的方法区中与类的加载和卸载周期相同。正因为此静态变量提供了在应用程序的整个生命周期中共享数据的便利方式。然而不恰当的使用静态变量可能会导致内存泄漏和资源管理问题尤其是在大型应用程序中这些问题可能会导致严重的性能下降。 
当某个对象被定义为static变量所引用那么GC通常是不会回收这个对象所占有的内存如 
public class A{
private static B b  new B();
}静态变量使用注意事项 内存管理正如例子中所示静态变量b的生命周期与类A相绑定。如果A类始终不被卸载那么b也将常驻内存即使它在实际应用中已不再需要。这种情况在使用第三方库、框架或长时间运行的应用中尤为常见。  设计选择在设计软件时应优先考虑实例变量而非静态变量除非有明确的理由需要将数据或状态与类本身而非其实例关联。使用实例变量可以帮助更好地管理资源因为它们的生命周期与对象实例相关联可以通过垃圾收集器有效回收。  内存泄漏风险静态变量如果引用了大型数据结构或其他资源密集型对象而且在应用程序的生命周期内不再需要这些对象就可能导致内存泄漏。即使是小型对象随着时间的推移也可能累积成为显著的内存占用。  
解决策略 使用弱引用对于必须使用静态变量但又想避免内存泄漏的情况可以考虑使用WeakReference或SoftReference。这样当JVM需要回收内存时即使这些变量还有引用也可以被垃圾回收器回收。  及时清理在不再需要持有静态变量时应显式将其设置为null这可以帮助垃圾收集器回收那些不再需要的对象减少内存占用。  审慎设计在使用静态变量之前应仔细考虑是否有其他更适合的设计方案。例如可以使用依赖注入等设计模式来管理对象的生命周期而不是依赖静态变量。  
3. 尽量避免过多过地创建Java对象 
在Java中对象的创建和垃圾回收GC是两个影响性能的关键因素。虽然现代JVM的垃圾回收机制非常高效但频繁创建和销毁大量对象仍然会对性能产生负面影响尤其是在需要高效执行的代码块如频繁调用的方法和循环体内。遵循“尽量避免过多过常地创建Java对象”的原则有助于优化性能减少GC的压力以下是一些具体策略 
对象重用 
对象池对于创建成本高昂的对象如数据库连接、线程等可以采用对象池技术。对象池允许复用一组已经初始化的对象避免了频繁创建和销毁对象的开销。缓存实例对于经常被重复使用的对象可以考虑将这些对象缓存起来以供重用特别是当对象的状态不变或可预测时。 
使用基本数据类型和数组 
基本类型代替包装类在可能的情况下使用基本数据类型如int, double, boolean等而不是它们的包装类如Integer, Double, Boolean等因为基本类型存储在栈上更加高效。数组和集合在处理大量数据时合理选择数据结构也很重要。数组相比于对象集合如ArrayList或LinkedList在存储和访问效率上通常更优。但是如果需要频繁的插入、删除操作选择正确的集合类型如ArrayList、LinkedList可能更合适。 
延迟初始化 
按需创建对于一些不一定会被用到的对象可以采用延迟初始化的策略即只有在真正需要时才创建这些对象。这种策略不仅可以节省资源还可以加快程序的启动速度。 
循环内部优化 
减少循环内对象创建在循环结构中应尽量避免在每次迭代时创建新的对象。如果需要可以在循环外创建对象并在循环内部重用。 
函数式编程 
利用流和Lambda表达式Java 8 引入的流StreamAPI和Lambda表达式可以在某些情况下减少对象的创建。通过流的链式调用可以在内部优化迭代和数据处理尽量减少不必要的对象创建。 
4. 尽量使用final修饰符 
使用final修饰符在Java编程中是一个提升性能的技巧尤其在关键路径hot paths或性能敏感的应用中。final可以用于变量、方法、和类具有不同的效果 对变量final变量一旦被初始化后其值就不能被改变。对于基本类型这意味着数值常量不变对于引用类型这意味着引用不变但被引用的对象的状态是可以改变的。  对方法将方法声明为final意味着该方法不能在子类中被重写。这对于编译器优化很有帮助因为这样编译器就知道这个方法的实现是不会改变的可以安全地应用内联优化。方法内联是一种常用的优化手段可以减少方法调用的开销因为它避免了调用过程中的一些额外操作如跳转指令直接在调用处展开方法体。  对类用final修饰类表示这个类不能被继承。这样做的一个好处是安全性如String类就是一个很好的例子通过防止继承来避免破坏其不可变性。从性能角度看这同样允许编译器对该类的所有方法应用内联优化因为这些方法不会被子类重写。  
 通过将简单的getter和setter方法声明为final你可以向编译器明确表示这些方法不会被进一步修改或重写。这种明确性允许编译器进行方法内联优化例如将方法调用直接替换为字段访问。这种优化减少了方法调用的开销尤其是在这些方法非常频繁被调用的情况下可以显著提升性能。 
然而使用final修饰符也应该是有选择的。过度使用final可能会限制代码的灵活性和可扩展性。例如将类声明为final可能会阻碍继承和多态的使用这在需要扩展或修改现有类的行为时会是一个限制。因此决定何时使用final修饰符应该基于对性能、安全性、以及代码维护灵活性需求的综合考虑。 
如让访问实例内变量的getter/setter方法变成”final简单的getter/setter方法应该被置成final这会告诉编译器这个方法不会被重载所以可以变成”inlined”内联,例子 
class MAF {
public void setSize (int size) {
_size  size; 
}
private int _size; 
} 
// 更正
class DAF_fixed {
final public void setSize (int size) { 
_size  size;
}
private int _size;
}5. 尽量使用局部变量 
尽量使用局部变量的建议源于Java内存管理机制的工作方式。Java虚拟机JVM中的内存主要分为堆内存Heap和栈内存Stack它们在功能和目的上有所不同这直接影响到变量存取速度和效率。 
堆Heap 
堆内存用于存储Java运行时数据区主要存放对象实例和数组。访问速度相对较慢因为堆内存是线程共享的对堆内存的操作需要更多的时间来管理内存和垃圾回收。堆内存的对象生命周期较长可能导致更频繁的垃圾回收活动从而影响性能。 
栈Stack 
栈内存用于执行线程存储局部变量、方法调用和基本类型变量包括方法的局部变量和方法调用时的参数。访问速度快因为每个线程都有自己的栈避免了线程间的竞争。栈内存中的变量生命周期短暂随着方法的结束而消失这使得栈内存的管理效率更高几乎无需垃圾回收。 
使用局部变量的好处 
提高性能由于局部变量存储在栈上它们的访问速度快于堆内存中的变量。这对于性能敏感的应用尤其重要。减少内存开销局部变量随着方法的结束而被清除这有助于减少内存使用避免了长时间占用堆内存和潜在的内存泄漏问题。提高代码清晰度使用局部变量可以提高方法的自封闭性和独立性使得代码更容易理解和维护。 
实践建议 
尽可能将变量的作用域限制在最小范围内。例如如果一个变量仅在方法内部使用就应该将其声明为局部变量。考虑在性能关键的代码段中使用基本类型而不是包装类因为基本类型可以存储在栈上。避免在循环或频繁调用的方法中创建不必要的对象以减少对堆内存的使用和垃圾回收的压力。 
6、尽量处理好包装类型和基本类型两者的使用场所 
Java中的基本类型如int, double, boolean等和它们的包装类如Integer, Double, Boolean等在使用上确实有着不同的内存和性能特性。基本类型的数据直接存储在栈上而包装类型的实例则存储在堆上。这个区别导致了它们在性能和使用场景上的不同考虑。 
基本类型 
性能优势基本类型存储在栈上访问速度快且没有额外的内存开销因为它们存储的是实际的值不涉及对象的构造和垃圾回收。使用场景适用于数值运算、逻辑操作等场景尤其是性能敏感的环境中。在不需要对象特性的情况下应优先考虑使用基本类型。 
包装类型 
功能丰富包装类型是类提供了许多有用的方法如转换、比较等。此外包装类型支持null值可以表示缺失或未定义的状态。使用场景在需要使用对象特性的场景中使用如需要将数值作为对象存储在集合中Java集合库中的类如ArrayList, HashMap等不支持基本类型或者在需要利用包装类型提供的方法时。在处理可能为null的数值时也需要使用包装类型。 
自动装箱与拆箱 
Java提供了自动装箱autoboxing和拆箱unboxing机制允许基本类型和包装类型之间的自动转换。但是这种便利性并不是没有代价的 
性能考虑自动装箱和拆箱虽然在代码中提供了便利但会带来额外的性能开销因为这涉及到在基本类型和包装类型之间转换时的对象创建和解包。隐藏的对象创建频繁的自动装箱操作可能会导致大量的临时对象被创建增加垃圾回收的负担。 
最佳实践 
在性能敏感的环境中尽量使用基本类型以减少内存消耗和提高性能。在需要使用集合、或者可能有null值的场景中使用包装类型。明智地使用自动装箱和拆箱了解代码中的自动装箱和拆箱操作避免在循环或频繁执行的代码段中进行无意识的自动装箱/拆箱以减少不必要的性能开销。 
7、慎用synchronized尽量减小synchronize的方法 
正确地使用synchronized关键字对于确保Java多线程程序的线程安全至关重要。synchronized可以确保在同一时刻只有一个线程能够访问同步的方法或代码块从而防止多线程环境下的数据一致性和完整性问题。然而过度或不当使用synchronized确实会引入显著的性能开销并有可能导致死锁等问题。因此合理地使用synchronized并采取措施减少需要同步的代码量是提高多线程程序性能的关键。 
尽量减小同步范围 使用同步代码块代替同步方法在可能的情况下优先考虑同步关键的代码段而不是整个方法。这可以通过将synchronized关键字应用于代码块来实现而不是方法。同步代码块可以减少锁定的范围从而减少线程等待的时间提高程序的并发性和性能。 public void method() {// 非同步区域synchronized(this) {// 需要同步的区域}// 非同步区域
}减少锁的粒度 
使用更细粒度的锁考虑使用不同的锁对象对数据进行更细粒度的控制。这样可以减少不同线程间的竞争允许更高的并发度。例如如果有多个资源或数据结构需要同步为每个资源或数据结构提供独立的锁对象。 
避免死锁 
小心锁的顺序在多个线程需要获取多个锁时确保所有线程以相同的顺序获取锁这是避免死锁的一种简单而有效的策略。 
使用其他并发控制工具 
利用java.util.concurrent包Java平台提供了丰富的并发工具类如ReentrantLock、ReadWriteLock、Semaphore等它们提供了比synchronized更灵活的锁定机制和更高级的并发控制功能。这些工具可以提供更细粒度的锁控制并且在某些情况下比synchronized更高效。 
精心设计对象的并发访问 
最小化锁持有时间尽量确保持有锁的时间尽可能短这样可以减少线程阻塞的可能性提高系统的响应性和吞吐量。考虑使用不可变对象不可变对象天生是线程安全的因为它们的状态在创建之后不能改变因此不需要同步控制。在多线程环境中尽可能使用不可变对象可以简化程序设计减少同步需求。 
8、尽量不要使用finalize方法 
Java的finalize()方法曾经被用作在对象被垃圾回收器回收之前执行清理工作的一种机制。然而依赖finalize()方法进行资源清理确实有几个显著的缺点这也是为什么现代Java开发中强烈建议避免使用它 
不确定性 
finalize()的调用时机非常不确定取决于垃圾回收器的执行时机这可能导致资源过长时间未被释放比如文件句柄或数据库连接等从而可能耗尽资源。由于finalize()执行时间的不可预测性可能导致对象的清理延迟增加了内存泄露和资源耗尽的风险。 
性能影响 
当垃圾回收器执行finalize()方法时会延迟对象的回收因为需要将这些对象放入一个称为finalization queue的队列中等待下一轮垃圾回收。这不仅增加了垃圾回收的负担还可能导致更频繁的垃圾回收影响程序性能。使用finalize()可能导致显著的性能下降尤其是在需要快速回收资源的高性能应用中。 
安全风险 
在finalize()方法中如果抛出异常且未被捕获会导致垃圾回收过程中的异常终止而这个异常不会被打印或警告可能导致难以发现和调试的错误。finalize()还可以被恶意用于对象复活在finalize()方法中重新赋予对象引用这可能导致安全漏洞或逻辑错误。 
替代方案 
对于需要清理的资源最佳实践是使用try-with-resources语句Java 7及以上版本这确保了每个资源在用完后立即被正确关闭而无需依赖垃圾回收器的调度。对于非自动关闭资源的清理推荐显式地管理资源的生命周期例如在使用完资源后立即手动释放它们使用try/finally块确保资源在所有情况下都被释放。 
9、尽量使用基本数据类型代替对象 
在Java中基本数据类型如int, double, boolean等与对象如String以及包装类如Integer, Double, Boolean等之间的选择对性能有显著影响。基本数据类型直接存储值而对象则需要在堆上分配内存来存储数据和对象的元数据这不仅增加了内存使用还增加了垃圾回收的负担。因此尽可能使用基本数据类型而不是它们的包装类可以提高性能。 
字符串对象示例 
您提到的两种创建String对象的方式展示了如何通过字面量和构造函数创建字符串并且它们在内存使用上有显著的不同 使用字面量创建字符串 String str  hello;这种方式首先检查字符串池中是否已经包含了一个等于此字符串的字符串即值为hello。如果存在则返回引用到池中的现有字符串否则新的字符串将被创建并放入池中。这种方式避免了重复创建相同的字符串对象节省了内存。  使用new关键字创建字符串对象 String str  new String(hello);这种方式实际上创建了两个字符串对象如果hello不在字符串池中的话。首先是字面量hello会被添加到字符串池如果它还不在池中的话然后new表达式创建了一个新的String对象在堆上该对象包含一个指向内部字符数组char[]的引用这个数组存储了字符串的实际字符。这不仅消耗了更多的内存而且在创建过程中增加了性能开销。  
性能建议 优先使用字符串字面量在创建字符串时尽可能使用字面量的方式以利用Java字符串池的优势避免不必要的对象创建。  基本类型 vs 包装类型对于基本数据类型应尽量使用它们而不是它们的包装类尤其是在需要大量数值操作的场景中。这样做可以减少堆内存的使用和垃圾回收的开销从而提高性能。  显式使用intern()方法如果确实需要通过new String()创建新的字符串对象并希望后续利用字符串池的优势可以调用intern()方法。这个方法会确保字符串被加入到池中并返回池中字符串的引用。不过需要注意的是intern()方法的使用也应该是有选择的因为维护字符串池本身也是有成本的。  
10、多线程在未发生线程安全前提下应尽量使用HashMap、ArrayList 
在Java中确实存在多种集合类它们在性能和线程安全方面各有特点。当你的应用场景中不存在线程安全问题时优先选择非同步的集合类是提高性能的一个好策略。 
HashMap vs Hashtable 
HashMap是非同步的因此在没有外部同步机制的情况下不保证线程安全。这意味着如果多个线程同时访问一个HashMap并且至少有一个线程从结构上修改了映射它必须保持外部同步。由于缺少同步机制HashMap在单线程环境下或在读多写少的并发环境中使用时性能要优于Hashtable。Hashtable是线程安全的每个方法都是同步的这会带来额外的性能开销。因此当不需要线程安全的保证时使用Hashtable会导致不必要的性能损失。 
ArrayList vs Vector 
ArrayList是非同步的提供了快速的迭代和随机访问能力。由于它不是线程安全的所以在多线程环境下使用时需要注意。但在单线程或读多写少的并发控制下其性能通常优于Vector。Vector是同步的这意味着它在多线程环境下是安全的但这种线程安全是以牺牲性能为代价的。Vector的每个操作几乎都是同步的这使得在高并发场景下可能会成为瓶颈。 
并发集合作为替代 
在需要线程安全的并发访问时Java的java.util.concurrent包提供了一系列性能更好的线程安全集合如ConcurrentHashMap、CopyOnWriteArrayList等。这些集合使用了更先进的并发控制策略如分段锁和写时复制旨在减少锁竞争从而提供比Hashtable和Vector更高的性能。 
最佳实践 
在非线程安全的场景下优先使用HashMap和ArrayList以获得更好的性能。当需要线程安全的集合时考虑使用java.util.concurrent包中的集合如ConcurrentHashMap而不是旧的线程安全集合如Hashtable和Vector。如果确实需要在多线程环境中使用HashMap和ArrayList确保访问这些集合的操作是适当同步的或者考虑使用Collections.synchronizedMap(Map)和Collections.synchronizedList(List)来包装非同步的集合提供线程安全的访问。 文章转载自: http://www.morning.ccphj.cn.gov.cn.ccphj.cn http://www.morning.bangaw.cn.gov.cn.bangaw.cn http://www.morning.xwlmg.cn.gov.cn.xwlmg.cn http://www.morning.jfxth.cn.gov.cn.jfxth.cn http://www.morning.fpngg.cn.gov.cn.fpngg.cn http://www.morning.rdnkx.cn.gov.cn.rdnkx.cn http://www.morning.xrsqb.cn.gov.cn.xrsqb.cn http://www.morning.rxydr.cn.gov.cn.rxydr.cn http://www.morning.smj78.cn.gov.cn.smj78.cn http://www.morning.rnzjc.cn.gov.cn.rnzjc.cn http://www.morning.nnykz.cn.gov.cn.nnykz.cn http://www.morning.dmfdl.cn.gov.cn.dmfdl.cn http://www.morning.lsfrc.cn.gov.cn.lsfrc.cn http://www.morning.ppghc.cn.gov.cn.ppghc.cn http://www.morning.cszbj.cn.gov.cn.cszbj.cn http://www.morning.xgkxy.cn.gov.cn.xgkxy.cn http://www.morning.qgwpx.cn.gov.cn.qgwpx.cn http://www.morning.mywnk.cn.gov.cn.mywnk.cn http://www.morning.ggnfy.cn.gov.cn.ggnfy.cn http://www.morning.bxch.cn.gov.cn.bxch.cn http://www.morning.kfqzd.cn.gov.cn.kfqzd.cn http://www.morning.rzbgn.cn.gov.cn.rzbgn.cn http://www.morning.txmkx.cn.gov.cn.txmkx.cn http://www.morning.qnxtz.cn.gov.cn.qnxtz.cn http://www.morning.bqxxq.cn.gov.cn.bqxxq.cn http://www.morning.zhqfn.cn.gov.cn.zhqfn.cn http://www.morning.jcrlx.cn.gov.cn.jcrlx.cn http://www.morning.cbnlg.cn.gov.cn.cbnlg.cn http://www.morning.rqlqd.cn.gov.cn.rqlqd.cn http://www.morning.gnbfj.cn.gov.cn.gnbfj.cn http://www.morning.rmltt.cn.gov.cn.rmltt.cn http://www.morning.mdmxf.cn.gov.cn.mdmxf.cn http://www.morning.jspnx.cn.gov.cn.jspnx.cn http://www.morning.gcqs.cn.gov.cn.gcqs.cn http://www.morning.dpplr.cn.gov.cn.dpplr.cn http://www.morning.dxzcr.cn.gov.cn.dxzcr.cn http://www.morning.qsbcg.cn.gov.cn.qsbcg.cn http://www.morning.nwqyq.cn.gov.cn.nwqyq.cn http://www.morning.dbnpz.cn.gov.cn.dbnpz.cn http://www.morning.hnrpk.cn.gov.cn.hnrpk.cn http://www.morning.bdypl.cn.gov.cn.bdypl.cn http://www.morning.wrtsm.cn.gov.cn.wrtsm.cn http://www.morning.gsyns.cn.gov.cn.gsyns.cn http://www.morning.ynstj.cn.gov.cn.ynstj.cn http://www.morning.jfymz.cn.gov.cn.jfymz.cn http://www.morning.lqznq.cn.gov.cn.lqznq.cn http://www.morning.rwnx.cn.gov.cn.rwnx.cn http://www.morning.sgbss.cn.gov.cn.sgbss.cn http://www.morning.xhsxj.cn.gov.cn.xhsxj.cn http://www.morning.qdrhf.cn.gov.cn.qdrhf.cn http://www.morning.bfmq.cn.gov.cn.bfmq.cn http://www.morning.jjnry.cn.gov.cn.jjnry.cn http://www.morning.frtt.cn.gov.cn.frtt.cn http://www.morning.bpmmq.cn.gov.cn.bpmmq.cn http://www.morning.kwfnt.cn.gov.cn.kwfnt.cn http://www.morning.gblrn.cn.gov.cn.gblrn.cn http://www.morning.yrddl.cn.gov.cn.yrddl.cn http://www.morning.errnull.com.gov.cn.errnull.com http://www.morning.ksbmx.cn.gov.cn.ksbmx.cn http://www.morning.nmqdk.cn.gov.cn.nmqdk.cn http://www.morning.cptzd.cn.gov.cn.cptzd.cn http://www.morning.bxbkq.cn.gov.cn.bxbkq.cn http://www.morning.zffps.cn.gov.cn.zffps.cn http://www.morning.wnwjf.cn.gov.cn.wnwjf.cn http://www.morning.tsqrc.cn.gov.cn.tsqrc.cn http://www.morning.bxbnf.cn.gov.cn.bxbnf.cn http://www.morning.rmltt.cn.gov.cn.rmltt.cn http://www.morning.jfzbk.cn.gov.cn.jfzbk.cn http://www.morning.lhxkl.cn.gov.cn.lhxkl.cn http://www.morning.bpmtr.cn.gov.cn.bpmtr.cn http://www.morning.ai-wang.cn.gov.cn.ai-wang.cn http://www.morning.wmnpm.cn.gov.cn.wmnpm.cn http://www.morning.mjbkp.cn.gov.cn.mjbkp.cn http://www.morning.ttkns.cn.gov.cn.ttkns.cn http://www.morning.nzcgj.cn.gov.cn.nzcgj.cn http://www.morning.mmzhuti.com.gov.cn.mmzhuti.com http://www.morning.bsghk.cn.gov.cn.bsghk.cn http://www.morning.yzfrh.cn.gov.cn.yzfrh.cn http://www.morning.nyhtf.cn.gov.cn.nyhtf.cn http://www.morning.zrlwl.cn.gov.cn.zrlwl.cn