外贸网站域名赏析,wordpress oss ftp,现代简约装修三室两厅两卫样,建设部门户网站条例免费下载1. 为什么需要事务? 事务定义 将一组操作封装成一个执行单元 (封装到一起)#xff0c;这一组的执行具备原子性, 那么就要么全部成功#xff0c;要么全部失败. 为什么要用事务? 比如转账分为两个操作: 第一步操作:A 账户-100 元。 第二步操作:B账户 100 元。 如果没有事务这一组的执行具备原子性, 那么就要么全部成功要么全部失败. 为什么要用事务? 比如转账分为两个操作: 第一步操作:A 账户-100 元。 第二步操作:B账户 100 元。 如果没有事务第一步执行成功了第二步执行失败了那么 A 账户平白无故的 100 元就“人间蒸发”了。而如果使用事务就可以解决这个问题让这一组操作要么一起成功要么一起失败。 2. Spring中事务的实现 Spring中的事务操作分为两类: 编程式事务(手动写代码操作事务)声明式事务(利用注解自动开启和提交事务) 在开始讲解它们之前咱们先来回顾事务在MSQL 中是如何使用的? 2.1 MySQL中的事务使用 事务在 MySQL 有 3个重要的操作: 开启事务、提交事务、回滚事务它们对应的操作命令如下: -- 开启事务
start transaction;
-- 业务执行-- 提交事务
commit;-- 回滚事务
rollback; 2.2 Spring 编程式事务(手动) Spring 手动操作事务和上面MySQL 操作事务类似它也是有3个重要操作步骤: 开启事务(获取事务)提交事务回滚事务 SpringBoot 内置了两个对象DataSourceTransactionManager 用来获取事务(开启事务)、提交或回滚事务的而 TransactionDefinition 是事务的属性在获取事务的时候需要将TransactionDefinition 传递进去从而获得一个事务 TransactionStatus实现代码如下: RestController
RequestMapping(/user)
public class UserController {Autowiredprivate UserService userService;// 编程式事务// JDBC 事务管理器Autowiredprivate DataSourceTransactionManager transactionManager;// 定义事务属性 (使用TransactionDefinition记录事务属性)Autowiredprivate TransactionDefinition transactionDefinition;RequestMapping(/del)public int del(Integer id) {if (id null || id 0) return 0;// 1. 开启事务TransactionStatus transactionStatus null;int result 0;try {transactionStatus transactionManager.getTransaction(transactionDefinition);// 业务操作: 删除用户result userService.del(id);System.out.println(删除: result);// 2. 提交事务 / 回滚事务
// transactionManager.commit(transactionStatus); // 提交事务} catch (Exception e) {if (transactionStatus ! null) {transactionManager.rollback(transactionStatus); // 回滚事务}}return result;}
} 业务操作相关代码如下: Service
public class UserService {Autowiredprivate UserMapper userMapper;public int del(Integer id){return userMapper.del(id);}
} Mapper
public interface UserMapper {int del(Param(id) Integer id);
} delete iddeldelete from userinfo where id#{id}/delete 运行结果: 可以看到, 删除的业务操作已经成功了, 但是因为回滚操作, 所以在执行前后查询数据库的时候是可以看到对应的数据依然存在. 从上述代码可以看出以上代码虽然可以实现事务但操作也很繁琐有没有更简单的实现方法呢?请看下面声明式事务。 2.3 Spring 声明式事务 (自动) 声明式事务的实现很简单只需要在需要的方法上添加 Transactional 注解就可以实现了无需手动开启事务和提交事务进入方法时自动开启事务方法执行完会自动提交事务如果中途发生了没有处理的异常会自动回滚事务具体实现代码如下: RestController
RequestMapping(/user2)
public class UserController2 {Autowiredprivate UserService userService;Transactional // 在方法开始之前开启事务, 方法正常执行结束之后提交事务, 如果执行途中发生异常, 则回滚事务.RequestMapping(/del)public int del(Integer id) {if (id null || id 0) return 0;return userService.del(id);}
} 执行前后查询数据库, 可以看到由于正常执行所以没有触发回滚. 2.3.1 Transactional作用范围 Transactional 可以用来修饰方法或类 修饰方法时:需要注意只能应用到 public 方法上否则不生效。推荐此种用法修饰类时:表明该注解对该类中所有的 public 方法都生效。 2.3.2 Transactional 参数说明 参数 作用 value 当配置了多个事务管理器时可以使用该属性指定选择哪个事务管理器 transactionManager 当配置了多个事务管理器时可以使用该属性指定选择哪个事务管理器 propagation 事务的传播行为,默认值为 Propagation.REQUIRED isolation 事务的隔离级别.默认值为 Isolation.DEFAULT timeout 事务的超时时间,默认值为-1. 如果超过该时间限制但事务还没有完成,则自动回滚事务. readOnly 指定事务是否为只读事务.默认值为 false; 为了忽略那些不需要事务的方法,比如读取数据可以设置read-only为 true. rollbackFor 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型 rollbackForClassName 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型 noRollbackFor 抛出指定的异常类型,不回滚事务,也可以指定多个异常类型 noRollbackForClassName 抛出指定的异常类型,不回滚事务,也可以指定多个异常类型 2.3.3 注意事项 Transactional 在异常被捕获的情况下不会进行事务自动回滚验证以下代码是否会发生事务回滚: RestController
RequestMapping(/user2)
public class UserController2 {Autowiredprivate UserService userService;Transactional RequestMapping(/del)public int del(Integer id) {if (id null || id 0) return 0;int result userService.del(id);System.out.println(删除: result);try {int num 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());}return result;}
} 执行前后查询数据库, 可以看到在异常被捕获的情况下并不会进行事务自动回滚. 事务不会自动回滚解决方案 解决方案1 对于捕获的异常事务是会自动回滚的因此解决方案1就是可以将异常重新抛出具体实现如下: RestController
RequestMapping(/user2)
public class UserController2 {Autowiredprivate UserService userService;Transactional RequestMapping(/del)public int del(Integer id) {if (id null || id 0) return 0;int result userService.del(id);System.out.println(删除: result);try {int num 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());throw e;}return result;}
} 执行前后查询数据库, 可以看到这里是有异常, 触发了回滚. 解决方案2 手动回滚事务在方法中使用 TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务然后设置回滚方法 setRollbackOnly 就可以实现回滚了具体实现代码如下: public class UserController2 {// .. 省略代码, 同上try {int num 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());// 手动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
} 执行前后访问数据库可以看到, 这里成功实现了回滚操作. 2.3.4 Transactional 工作原理 Transactional 是基于 AOP 实现的AOP 又是使用动态代理实现的。如果目标对象实现了接口默认情况下会采用JDK 的动态代理如果目标对象没有实现了接口,会使用CGLIB 动态代理。 Transactional 在开始执行业务之前通过代理先开启事务在执行成功之后再提交事务。如果中途遇到的异常则回滚事务。 Transactional 实现思路预览: Transactional 具体执行细节如下图所示: 3. 事务隔离级别 3.1 事务特性回顾 事务有4 大特性 (ACID)原子性、持久性、一致性和隔离性具体概念如下: 原子性: 一个事务(transaction)中的所有操作要么全部完成要么全部不完成不会结束在中间某个环节。事务在执行过程中发生错误会被回滚 (Rollback)到事务开始前的状态就像这个事务从来没有执行过一样。一致性: 在事务开始之前和事务结束以后数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。持久性: 事务处理结束后对数据的修改就是永久的即便系统故障也不会丢失。隔离性: 数据库允许多个并发事务同时对其数据进行读写和修改的能力隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别包括读未提交 (Read uncommitted)、读提交 (read committed) 、可重复读 (repeatable read) 和串行化(Serializable)。 上面 4个属性可以简称为ACID 原子性 (Atomicity或称不可分割性) 一致性 (Consistency) 隔离性 (lsolation又称独立性) 持久性 (Durability) 而这 4 种特性中只有隔离性 (隔离级别) 是可以设置的。 为什么要设置事务的隔离级别? 设置事务的隔离级别是用来保障多个并发事务执行更可控更符合操作者预期的。 什么是可控呢? 比如近几年比较严重的新冠病毒我们会把直接接触到确诊病例的人员隔离到酒店而把间接接触者 (和直接接触着但未确诊的人) 隔离在自己的家中也就是针对不同的人群采取不同的隔离级别这种隔离方式就和事务的隔离级别类似都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止其他的事务影响当前事务执行的一种策略。 3.2 Spring 中设置事务隔离级别 Spring 中事务隔离级别可以通过 Transactional 中的 isolation 属性进行设置具体操作如下图所示: 3.2.1 MySQL事务隔离级别有 4 种 READ UNCOMMITTED: 读未提交也叫未提交读该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据而未提交的数据可能会发生回滚因此我们把该级别读取到的数据称之为脏数据把这个问题称之为脏读。READ COMMITTED: 读已提交也叫提交读该隔离级别的事务能读取到已经提交事务的数据因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果所以在不同时间的相同 SQL查询中可能会得到不同的结果这种现象叫做不可重复读。REPEATABLE READ: 可重复读是MySQL的默认事务隔离级别它能确保同一事务多次查询的结果一致。但也会有新的问题比如此级别的事务正在执行时另一个事务成功的插入了某条数据但因为它每次查询的结果都是一样的所以会导致查询不到这条数据自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息但自己就是插入不进去这就叫幻读(Phantom Read)SERIALIZABLE: 序列化事务最高隔离级别它会强制事务排序使之不会发生冲突从而解决了脏读、不可重复读和幻读问题但因为执行效率低所以真正使用的场景并不多 1. 脏读: 一个事务读取到了另一个事务修改的数据之后后一个事务又进行了回滚操作从而导致第一个事务读取的数据是错误的。 2. 不可重复读: 一个事务两次查询得到的结果不同因为在两次查询中间有另一个事务把数据修改了。 3. 幻读: 一个事务两次查询中得到的结果集不同因为在两次查询中另一个事务有新增了一部分数据。 在数据库中通过以下SQL 查询全局事务隔离级别和当前连接的事务隔离级别: select global.tx_isolation,tx_isolation; 以上SQL的执行结果如下: 3.2.2 Spring 中事务隔离级别有 5 种 Spring 中事务隔离级别包含以下 5 种: Isolation.DEFAULT: 以连接的数据库的事务隔离级别为主lsolation.READ_UNCOMMITTED: 读未提交可以读取到未提交的事务存在脏读Isolation.READ_COMMITTED: 读已提交只能读取到已经提交的事务解决了脏读存在不可重复读。Isolation.REPEATABLE_READ: 可重复读解决了不可重复读但存在幻读(MVSQL默认级lsolation.SERIALIZABLE: 串行化可以解决所有并发问题但性能太低。 从上述介绍可以看出相比于 MySQL 的事务隔离级别Spring 的事务隔离级别只是多了一个lsolation.DEFAULT (以数据库的全局事务隔离级别为主)。 Spring 中事务隔离级别只需要设置 Transactional 里的 isolation 属性即可具体实现代码如下: RequestMapping(/save)
Transactional(isolation Isolation.SERIALIZABLE)
public Object save(User user) {// 业务实现
} 4. Spring 事务传播机制 4.1 事务传播机制是什么? Spring 事务传播机制定义了多个包含了事务的方法相互调用时事务是如何在这些方法间进行传递的。 4.2 为什么需要事务传播机制? 事务隔离级别是保证多个并发事务执行的可控性的(稳定性的)而事务传播机制是保证一个事务在多个调用方法间的可控性的 (稳定性的)。 例子: 像新冠病毒一样它有不同的隔离方式(酒店隔离还是居家隔离)是为了保证疫情可控然而在每个人的隔离过程中会有很多个执行的环节比如酒店隔离需要负责人员运送、物品运送消杀原生活区域、定时核算检查和定时送餐等很多环节而事务传播机制就是保证一个事务在传递过程中是可靠性的回到本身案例中就是保证每个人在隔离的过程中可控的。 事务隔离级别解决的是多个事务同时调用一个数据库的问题如下图所示: 而事务传播机制解决的是一个事务在多个节点(方法) 中传递的问题如下图所示: 4.3 事务传播机制有哪些? Spring 事务传播机制包含以下 7种: Propagation.REQUIRED: 默认的事务传播级别它表示如果当前存在事务则加入该事务;如果当前没有事务则创建一个新的事务。Propagation.SUPPORTS: 如果当前存在事务则加入该事务; 如果当前没有事务则以非事务的方式继续运行。Propagation.MANDATORY: (mandatory: 强制性) 如果当前存在事务则加入该事务;如果当前没有事务则抛出异常。Propagation.REQUIRES_NEW: 表示创建一个新的事务如果当前存在事务则把当前事务挂起。也就是说不管外部方法是否开启事务Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务且开启的事务相互独立互不干扰。Propagation.NOT_SUPPORTED: 以非事务方式运行如果当前存在事务则把当前事务挂起。Propagation.NEVER: 以非事务方式运行如果当前存在事务则抛出异常Propagation.NESTED: 如果当前存在事务则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务则该取值等价于 PROPAGATION_REQUIRED。 以上 7 种传播行为可以根据是否支持当前事务分为以下 3类: 以情侣关系为例来理解以上分类: 4.4 Spring 事务传播机制使用和各种场景演示 4.4.1 支持当前事务(REQUIRED) 我们有多个方法进行数据的传递. 不考虑拦截器, 考虑标准的分层, 比如要执行用户User的添加add操作, 下图为该执行流程图 首先要执行add, 就会先在UserController加Transactional, 下面为了演示事务的传播机制, 就需要让用户调用UserService, 并加上Transactional. 在UserService中, 我们需要操作两张表, 先调用UserMapper中的add添加方法, 这个方法是添加用户的, 再调用日志添加类. 从上图可见, Transactional是通过UserController传递到UserService, 再从UserService传递到LogService. 注意, 正常来说在*Service要调用*Mapper类, 但是这里如果使用LogMapper是Interface, 就无法演示清楚预期效果, 所以这里调用LogService. 在mycnblog中创建日志表. CREATE TABLE log (id int(11) NOT NULL AUTO_INCREMENT,timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,message text COLLATE utf8mb4_unicode_ci NOT NULL,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT12 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci 在项目中创建实体类: Data
public class UserInfo {private int id;private String username;private String password;private String photo;private LocalDateTime createtime;private LocalDateTime updatetime;private int state;
} Data
public class Log {private int id;private LocalDateTime timestamp;private String message;
} 演示事务传播机制代码实现: User RestController
RequestMapping(/user3)
public class UserController3 {Autowiredprivate UserService userService;RequestMapping(/add)Transactional(propagation Propagation.REQUIRED)public int add(String username, String password){if (null username || null password ||username.equals() || password.equals()) return 0;UserInfo user new UserInfo();user.setUsername(username);user.setPassword(password);int result userService.add(user);// 用户添加操作return 0;}
} UserService 实现代码如下: Service
public class UserService {Autowiredprivate UserMapper userMapper;Autowiredprivate LogService logService;Transactional(propagation Propagation.REQUIRED)public int add(UserInfo userInfo) {// 给用户表添加用户信息int addUserResult userMapper.add(userInfo);System.out.println(添加用户结果: addUserResult);// 添加日志信息Log log new Log();log.setMessage(添加用户信息); logService.add(log);return addUserResult;}
} 在UserMapper中写添加add方法. Mapper
public interface UserMapper {int add(UserInfo userInfo);
} 在xml中写具体的实现: insert idaddinsert into userinfo(username, password) values(#{username},#{password})/insert Log LogMapper.interface Mapper
public interface LogMapper {int add(Log log);
} LogMapper.xml insert idaddinsert into log(message) values(#{message})/insert LogService: Service
public class LogService {Autowiredprivate LogMapper logMapper;Transactional(propagation Propagation.REQUIRED)public int add(Log log) {int result logMapper.add(log);System.out.println(添加日志结果: result);// 回滚操作TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();int num 10 / 0;return result;}
} 接下来我们观察一下在UserService中已经执行成功的user添加操作有没有回滚事务, 如果user中没有正常添加数据, 那么就说明REQUIRED是支持当前的事务, 并且是以加入的方式去进行的. 可以看到, 添加用户和添加日志都已经成功了, 最终有一个算数异常报出. 我们再来看一下数据库. 可以看到, log回滚了, 符合预期, 然而userinfo中并没有将前面url所传数据wangwu添加过来, 那么这就说明, REQUIRED这种事务传播机制是支持当前事务的, 并且是加入事务的方式, 让自己变成事务的一部分, 如果其中有任何一个地方出现问题, 不论前面做了多少业务, 那么整条调用链上所有的方法都会进行回滚. 4.4.2 不支持当前事务(REQUIRESNEW) 将整条事务调用链上的所有方法修改为 REQUIRES_NEW不支持当前事务重新创建事务观察执行结果: Transactional(propagation Propagation.REQUIRES_NEW) 预期执行结果: 在一个调用链上的事务各自执行相互不干扰。 对上面的示例来说, 是用户添加 (事务) 成功、但是日志添加 (事务) 失败。 可以看到, 我们的执行结果并没有符合我们的预计结果. 原因是由于没有处理 by zero的异常, 导致整个调用链上的其他对象都感知到了, 所以进行了回滚. 此时修改LogService代码: Service
public class LogService {Autowiredprivate LogMapper logMapper;Transactional(propagation Propagation.REQUIRES_NEW)public int add(Log log) {int result logMapper.add(log);System.out.println(添加日志结果: result);// 回滚操作TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();return result;}
} 这个时候便不会报错了. 可以看到, 用户和日志都添加成功了, 但是日志中进行了手动回滚. 验证一下: 说明符合了预期. 4.4.3 嵌套事务 (NESTED) 和加入事务 (REQUIRED )的区别 整个事务如果全部执行成功二者的结果是一样的。如果事务执行到一半失败了那么加入事务整个事务会全部回滚;而嵌套事务会局部回滚不会影响上一个方法中执行的结果 至此, 整个JavaEE专栏的知识介绍就到这里.
文章转载自: http://www.morning.rwjtf.cn.gov.cn.rwjtf.cn http://www.morning.xsfg.cn.gov.cn.xsfg.cn http://www.morning.mhcys.cn.gov.cn.mhcys.cn http://www.morning.smggx.cn.gov.cn.smggx.cn http://www.morning.jcwrb.cn.gov.cn.jcwrb.cn http://www.morning.xprzq.cn.gov.cn.xprzq.cn http://www.morning.rrdch.cn.gov.cn.rrdch.cn http://www.morning.wrkhf.cn.gov.cn.wrkhf.cn http://www.morning.rbjf.cn.gov.cn.rbjf.cn http://www.morning.wdply.cn.gov.cn.wdply.cn http://www.morning.wbqk.cn.gov.cn.wbqk.cn http://www.morning.rnrwq.cn.gov.cn.rnrwq.cn http://www.morning.jtnph.cn.gov.cn.jtnph.cn http://www.morning.dnls.cn.gov.cn.dnls.cn http://www.morning.dpjtn.cn.gov.cn.dpjtn.cn http://www.morning.rkwwy.cn.gov.cn.rkwwy.cn http://www.morning.wjhdn.cn.gov.cn.wjhdn.cn http://www.morning.lzjxn.cn.gov.cn.lzjxn.cn http://www.morning.wfyzs.cn.gov.cn.wfyzs.cn http://www.morning.xstfp.cn.gov.cn.xstfp.cn http://www.morning.txqgd.cn.gov.cn.txqgd.cn http://www.morning.dnqliv.cn.gov.cn.dnqliv.cn http://www.morning.nkdmd.cn.gov.cn.nkdmd.cn http://www.morning.sjqml.cn.gov.cn.sjqml.cn http://www.morning.fnbtn.cn.gov.cn.fnbtn.cn http://www.morning.fhykt.cn.gov.cn.fhykt.cn http://www.morning.mlwhd.cn.gov.cn.mlwhd.cn http://www.morning.jgttx.cn.gov.cn.jgttx.cn http://www.morning.qfkxj.cn.gov.cn.qfkxj.cn http://www.morning.qfrsm.cn.gov.cn.qfrsm.cn http://www.morning.nsppc.cn.gov.cn.nsppc.cn http://www.morning.lnbyk.cn.gov.cn.lnbyk.cn http://www.morning.tyjp.cn.gov.cn.tyjp.cn http://www.morning.zgqysw.cn.gov.cn.zgqysw.cn http://www.morning.huxinzuche.cn.gov.cn.huxinzuche.cn http://www.morning.tkxyx.cn.gov.cn.tkxyx.cn http://www.morning.sfphz.cn.gov.cn.sfphz.cn http://www.morning.llllcc.com.gov.cn.llllcc.com http://www.morning.bphqd.cn.gov.cn.bphqd.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.xtkw.cn.gov.cn.xtkw.cn http://www.morning.ymdhq.cn.gov.cn.ymdhq.cn http://www.morning.nrjr.cn.gov.cn.nrjr.cn http://www.morning.gqfbh.cn.gov.cn.gqfbh.cn http://www.morning.mjqms.cn.gov.cn.mjqms.cn http://www.morning.xesrd.com.gov.cn.xesrd.com http://www.morning.qpfmh.cn.gov.cn.qpfmh.cn http://www.morning.zlnkq.cn.gov.cn.zlnkq.cn http://www.morning.npmcf.cn.gov.cn.npmcf.cn http://www.morning.qkqjz.cn.gov.cn.qkqjz.cn http://www.morning.tntgc.cn.gov.cn.tntgc.cn http://www.morning.kdnrp.cn.gov.cn.kdnrp.cn http://www.morning.jpgfq.cn.gov.cn.jpgfq.cn http://www.morning.wbhzr.cn.gov.cn.wbhzr.cn http://www.morning.dfltx.cn.gov.cn.dfltx.cn http://www.morning.rkrcd.cn.gov.cn.rkrcd.cn http://www.morning.yxmcx.cn.gov.cn.yxmcx.cn http://www.morning.mdgb.cn.gov.cn.mdgb.cn http://www.morning.jqwpw.cn.gov.cn.jqwpw.cn http://www.morning.nhdmh.cn.gov.cn.nhdmh.cn http://www.morning.sqhtg.cn.gov.cn.sqhtg.cn http://www.morning.xuejitest.com.gov.cn.xuejitest.com http://www.morning.rhkmn.cn.gov.cn.rhkmn.cn http://www.morning.sgfgz.cn.gov.cn.sgfgz.cn http://www.morning.nnhfz.cn.gov.cn.nnhfz.cn http://www.morning.lqffg.cn.gov.cn.lqffg.cn http://www.morning.hyxwh.cn.gov.cn.hyxwh.cn http://www.morning.rpwm.cn.gov.cn.rpwm.cn http://www.morning.ymsdr.cn.gov.cn.ymsdr.cn http://www.morning.lnrr.cn.gov.cn.lnrr.cn http://www.morning.bxch.cn.gov.cn.bxch.cn http://www.morning.lqqqh.cn.gov.cn.lqqqh.cn http://www.morning.rkqkb.cn.gov.cn.rkqkb.cn http://www.morning.mgkb.cn.gov.cn.mgkb.cn http://www.morning.gdljq.cn.gov.cn.gdljq.cn http://www.morning.phtqr.cn.gov.cn.phtqr.cn http://www.morning.yqlrq.cn.gov.cn.yqlrq.cn http://www.morning.rjljb.cn.gov.cn.rjljb.cn http://www.morning.drjll.cn.gov.cn.drjll.cn http://www.morning.llcgz.cn.gov.cn.llcgz.cn