java110 лет назад: 6
Родитель
Сommit
b58df982bd

+ 75 - 0
java110-bean/src/main/java/com/java110/dto/order/OrderDto.java

@@ -5,6 +5,25 @@ import com.java110.dto.PageDto;
 import java.io.Serializable;
 
 public class OrderDto extends PageDto implements Serializable {
+
+    public static final String APP_ID = "APP-ID";
+    public static final String TRANSACTION_ID = "TRANSACTION-ID";
+    public static final String REQUEST_TIME = "REQUEST-TIME";
+
+    public static final String O_ID = "O-ID";
+
+    //受理单
+    public static final String ORDER_TYPE_DEAL = "D";
+
+
+    private String appId;
+    private String extTransactionId;
+    private String userId;
+    private String requestTime;
+    private String orderTypeCd;
+    private String finishTime;
+    private String remark;
+
     private String oId;
 
     private String bId;
@@ -45,4 +64,60 @@ public class OrderDto extends PageDto implements Serializable {
     public void setBusinessTypeCds(String[] businessTypeCds) {
         this.businessTypeCds = businessTypeCds;
     }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getExtTransactionId() {
+        return extTransactionId;
+    }
+
+    public void setExtTransactionId(String extTransactionId) {
+        this.extTransactionId = extTransactionId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getRequestTime() {
+        return requestTime;
+    }
+
+    public void setRequestTime(String requestTime) {
+        this.requestTime = requestTime;
+    }
+
+    public String getOrderTypeCd() {
+        return orderTypeCd;
+    }
+
+    public void setOrderTypeCd(String orderTypeCd) {
+        this.orderTypeCd = orderTypeCd;
+    }
+
+    public String getFinishTime() {
+        return finishTime;
+    }
+
+    public void setFinishTime(String finishTime) {
+        this.finishTime = finishTime;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
 }

+ 91 - 0
java110-bean/src/main/java/com/java110/dto/order/OrderItemDto.java

@@ -0,0 +1,91 @@
+package com.java110.dto.order;
+
+import com.java110.dto.PageDto;
+
+import java.io.Serializable;
+
+public class OrderItemDto extends PageDto implements Serializable {
+
+
+    private String bId;
+    private String oId;
+    private String createTime;
+    private String action;
+    private String actionObj;
+    private String finishTime;
+    private String remark;
+    private String serviceName;
+    private String logText;
+
+    public String getbId() {
+        return bId;
+    }
+
+    public void setbId(String bId) {
+        this.bId = bId;
+    }
+
+    public String getoId() {
+        return oId;
+    }
+
+    public void setoId(String oId) {
+        this.oId = oId;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public String getActionObj() {
+        return actionObj;
+    }
+
+    public void setActionObj(String actionObj) {
+        this.actionObj = actionObj;
+    }
+
+    public String getFinishTime() {
+        return finishTime;
+    }
+
+    public void setFinishTime(String finishTime) {
+        this.finishTime = finishTime;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getLogText() {
+        return logText;
+    }
+
+    public void setLogText(String logText) {
+        this.logText = logText;
+    }
+}

+ 33 - 0
java110-core/src/main/java/com/java110/core/aop/FeignRequestInterceptor.java

@@ -0,0 +1,33 @@
+package com.java110.core.aop;
+
+import com.java110.core.factory.Java110TransactionalFactory;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+/**
+ * @ClassName FeignRequestInterceptor
+ * @Description TODO feign 调用拦截器
+ * @Author wuxw
+ * @Date 2020/7/5 22:44
+ * @Version 1.0
+ * add by wuxw 2020/7/5
+ **/
+@Configuration
+public class FeignRequestInterceptor implements RequestInterceptor {
+
+
+    /**
+     * 传入事务ID
+     *
+     * @param requestTemplate
+     */
+    @Override
+    public void apply(RequestTemplate requestTemplate) {
+        String oId = Java110TransactionalFactory.getOId();
+        if (!StringUtils.isEmpty(oId)) {
+            requestTemplate.header(Java110TransactionalFactory.O_ID, oId);
+        }
+    }
+}

+ 29 - 4
java110-core/src/main/java/com/java110/core/aop/Java110TransactionalAop.java

@@ -1,6 +1,7 @@
 package com.java110.core.aop;
 
 import com.java110.core.factory.Java110TransactionalFactory;
+import com.java110.dto.order.OrderDto;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.After;
@@ -15,8 +16,12 @@ import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
+import java.util.Enumeration;
 
 /**
  * @ClassName Java110TransactionalAop
@@ -45,11 +50,29 @@ public class Java110TransactionalAop {
     @Before("dataProcess()")
     public void deBefore(JoinPoint joinPoint) throws Throwable {
         // 接收到请求,记录请求内容
-        logger.debug("方法调用前执行deBefore()");
-
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = attributes.getRequest();
+        Enumeration<String> headerNames = request.getHeaderNames();
+        OrderDto orderDto = new OrderDto();
+        while (headerNames.hasMoreElements()) {
+            String key = (String) headerNames.nextElement();
+            String value = request.getHeader(key);
+            if (OrderDto.APP_ID.equals(key.toUpperCase())) {
+                orderDto.setAppId(value);
+            }
+            if (OrderDto.TRANSACTION_ID.equals(key.toUpperCase())) {
+                orderDto.setExtTransactionId(value);
+            }
+            if (OrderDto.REQUEST_TIME.equals(key.toUpperCase())) {
+                orderDto.setRequestTime(value);
+            }
+            if (OrderDto.O_ID.equals(key.toUpperCase())) {
+                orderDto.setoId(value);
+            }
+        }
+        orderDto.setOrderTypeCd(OrderDto.ORDER_TYPE_DEAL);
         //全局事务ID申请
-        Java110TransactionalFactory.getOrCreateTId();
-
+        Java110TransactionalFactory.getOrCreateOId(orderDto);
     }
 
     @AfterReturning(returning = "ret", pointcut = "dataProcess()")
@@ -63,6 +86,8 @@ public class Java110TransactionalAop {
     public void throwException(JoinPoint jp) {
         logger.debug("方法调用异常执行throwException()");
 
+        //回退事务
+        Java110TransactionalFactory.fallbackOId();
     }
 
     //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行

+ 113 - 8
java110-core/src/main/java/com/java110/core/factory/Java110TransactionalFactory.java

@@ -1,6 +1,20 @@
 package com.java110.core.factory;
 
+import com.alibaba.fastjson.JSONObject;
+import com.java110.dto.order.OrderDto;
+import com.java110.utils.constant.ServiceConstant;
+import com.java110.utils.factory.ApplicationContextFactory;
 import com.java110.utils.util.StringUtil;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.client.RestTemplate;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -15,11 +29,27 @@ import java.util.Map;
  **/
 public class Java110TransactionalFactory {
 
+    private static Logger logger = LoggerFactory.getLogger(Java110TransactionalFactory.class);
+
+    //订单服务
+    private static final String URL_API = ServiceConstant.SERVICE_ORDER_URL + "/order/oIdApi";
+
+    /**
+     * 创建事务ID
+     */
+    private static final String CREATE_O_ID = URL_API + "/createOId";
+
+    /**
+     * 回退事务ID
+     */
+    private static final String FALLBACK_O_ID = URL_API + "/fallBackOId";
+
+
     //全局事务ID
-    public static final String T_ID = "t-id";
+    public static final String O_ID = "O-ID";
 
     //当前服务ID
-    public static final String SERVICE_ID = "service-id";
+    public static final String SERVICE_ID = "SERVICE-ID";
 
     private static ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<Map<String, String>>() {
         @Override
@@ -44,17 +74,92 @@ public class Java110TransactionalFactory {
         return threadLocal.get();
     }
 
-    public static String getOrCreateTId(){
-        String tId = get(T_ID);
+    public static String getOrCreateOId(OrderDto orderDto) {
+        //全局事务开启者
+        if (StringUtils.isEmpty(orderDto.getoId())) {
+            createOId(orderDto);
+        }
+        String oId = get(O_ID);
+        return oId;
+    }
+
+    /**
+     * 获取事务ID
+     *
+     * @return
+     */
+    public static String getOId() {
+        String oId = get(O_ID);
+        return oId;
+    }
 
-        if(StringUtil.isEmpty(tId)){
+    /**
+     * 创建事务
+     *
+     * @param orderDto
+     */
+    private static void createOId(OrderDto orderDto) {
+        RestTemplate restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
+        HttpHeaders header = new HttpHeaders();
+        HttpEntity<String> httpEntity = new HttpEntity<String>(JSONObject.toJSONString(orderDto), header);
+        ResponseEntity<String> responseEntity = null;
+        try {
+            responseEntity = restTemplate.exchange(CREATE_O_ID, HttpMethod.POST, httpEntity, String.class);
+        } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
+            responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
+        } catch (Exception e) {
+            responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+        } finally {
+            logger.debug("请求地址为,{} 请求订单服务信息,{},订单服务返回信息,{}", CREATE_O_ID, httpEntity, responseEntity);
+        }
+        if (responseEntity.getStatusCode() != HttpStatus.OK) {
+            throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
+        }
+        JSONObject order = JSONObject.parseObject(responseEntity.getBody());
 
+        if (!order.containsKey("oId") || StringUtils.isEmpty(order.getString("oId"))) {
+            throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
         }
-        return "";
+        orderDto.setoId(order.getString("oId"));
+        //将事务ID 存放起来
+        put(O_ID, orderDto.getoId());
     }
 
-    private void createTId(){
+    /**
+     * 处理失败,回退事务
+     */
+    public static void fallbackOId() {
+        String oId = getOId();
+        if (StringUtil.isEmpty(oId)) {
+            //当前没有开启事务无需回退
+            logger.debug("当前没有开启事务无需回退");
+            return;
+        }
+        OrderDto orderDto = new OrderDto();
+        orderDto.setoId(oId);
+        RestTemplate restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
+        HttpHeaders header = new HttpHeaders();
+        HttpEntity<String> httpEntity = new HttpEntity<String>(JSONObject.toJSONString(orderDto), header);
+        ResponseEntity<String> responseEntity = null;
+        try {
+            responseEntity = restTemplate.exchange(FALLBACK_O_ID, HttpMethod.POST, httpEntity, String.class);
+        } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
+            responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
+        } catch (Exception e) {
+            responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+        } finally {
+            logger.debug("回退事务 请求地址为,{} 请求订单服务信息,{},订单服务返回信息,{}", FALLBACK_O_ID, httpEntity, responseEntity);
+        }
 
-    }
+        if (responseEntity.getStatusCode() == HttpStatus.NOT_FOUND) {
+            //当前没有开启事务无需回退
+            logger.debug("当前没有开启事务无需回退");
+            return;
+        }
+
+        if (responseEntity.getStatusCode() == HttpStatus.BAD_REQUEST) {
+            throw new IllegalArgumentException("回退事务失败" + responseEntity.getBody());
+        }
 
+    }
 }

+ 34 - 0
java110-db/src/main/resources/mapper/center/CenterServiceDAOImplMapper.xml

@@ -4,6 +4,40 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="centerServiceDAOImpl">
 
+
+    <!-- 查询订单信息 -->
+    <select id="getOrder" resultType="Map" parameterType="Map">
+        SELECT `o_id` oId, `app_id` appId, `ext_transaction_id` extTransactionId, `user_id` userId, `request_time`
+        requestTime,
+        `create_time` createTime,`order_type_cd` orderTypeCd, `finish_time` finishTime, `remark`
+        from c_orders t
+        where t.status_cd = '0'
+        <if test="oId != null and oId != ''">
+            and t.o_id = #{oId}
+        </if>
+        <if test="extTransactionId != null and extTransactionId != ''">
+            and t.ext_transaction_id = #{extTransactionId}
+        </if>
+        <if test="appId != null and appId != ''">
+            and t.app_id = #{appId}
+        </if>
+    </select>
+
+    <!-- 查询订单项信息 -->
+    <select id="getOrderItems" resultType="Map" parameterType="Map">
+        select t.b_id bId,t.o_id oId,t.create_time createTime,t.action,t.action_obj actionObj,
+        t.finish_time finishTime,t.remark,ul.service_name serviceName,ul.log_text logText
+        from c_order_item t
+        LEFT JOIN unitem_log ul on t.b_id = ul.b_id and t.o_id = ul.o_id and ul.status_cd = '0'
+        where t.status_cd = '0'
+        <if test="oId != null and oId != ''">
+            and t.o_id = #{oId}
+        </if>
+        <if test="bId != null and bId != ''">
+            and t.b_id = #{bId}
+        </if>
+    </select>
+
     <!--保存订单信息 c_orders 中 -->
     <insert id="saveOrder" parameterType="Map">
         <![CDATA[

+ 5 - 0
java110-utils/src/main/java/com/java110/utils/constant/ServiceConstant.java

@@ -11,5 +11,10 @@ public class ServiceConstant {
      */
     public static final  String SERVICE_API_URL = "http://api-service";
 
+    /**
+     * API中心服务
+     */
+    public static final  String SERVICE_ORDER_URL = "http://order-service";
+
     //public  static final String SERVICE_API_URL = "http://api.java110.com:8008";
 }

+ 8 - 0
java110-utils/src/main/java/com/java110/utils/factory/ApplicationContextFactory.java

@@ -35,6 +35,14 @@ public class ApplicationContextFactory {
         return null;
     }
 
+    /**
+     * 获取应用名称
+     * @return
+     */
+    public static String getApplicationName(){
+        return applicationContext.getEnvironment().getProperty("spring.application.name");
+    }
+
 
     // 国际化使用
     public static String getMessage(String key) {

+ 51 - 0
service-order/src/main/java/com/java110/order/api/OIdApi.java

@@ -0,0 +1,51 @@
+package com.java110.order.api;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.dto.order.OrderDto;
+import com.java110.order.smo.IOIdServiceSMO;
+import com.java110.utils.util.BeanConvertUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @ClassName TApi
+ * @Description TODO 事务处理类
+ * @Author wuxw
+ * @Date 2020/7/5 20:27
+ * @Version 1.0
+ * add by wuxw 2020/7/5
+ **/
+@RestController
+@RequestMapping(path = "/order/oIdApi")
+public class OIdApi {
+    @Autowired
+    private IOIdServiceSMO tServiceSMOImpl;
+
+    /**
+     * 创建事务ID
+     *
+     * @return
+     */
+    @RequestMapping(path = "/createOId", method = RequestMethod.POST)
+    public ResponseEntity<String> createOId(@RequestBody String order) {
+        JSONObject orderObj = JSONObject.parseObject(order);
+        OrderDto orderDto = BeanConvertUtil.covertBean(orderObj, OrderDto.class);
+        return tServiceSMOImpl.createOId(orderDto);
+    }
+
+    /**
+     * 回退事务
+     * @param order
+     * @return
+     */
+    @RequestMapping(path = "/fallBackOId", method = RequestMethod.POST)
+    public ResponseEntity<String> fallBackOId(@RequestBody String order){
+        JSONObject orderObj = JSONObject.parseObject(order);
+        OrderDto orderDto = BeanConvertUtil.covertBean(orderObj, OrderDto.class);
+        return tServiceSMOImpl.fallBackOId(orderDto);
+    }
+}

+ 17 - 0
service-order/src/main/java/com/java110/order/dao/ICenterServiceDAO.java

@@ -11,6 +11,23 @@ import java.util.Map;
  */
 public interface ICenterServiceDAO {
 
+
+    /**
+     * 查询订单
+     * @param order
+     * @return
+     * @throws DAOException
+     */
+    public Map getOrder(Map order) throws DAOException;
+
+    /**
+     * 查询订单项
+     * @param orderItem
+     * @return
+     * @throws DAOException
+     */
+    public List<Map> getOrderItems(Map orderItem) throws DAOException;
+
     /**
      * 保存订单信息
      *

+ 16 - 0
service-order/src/main/java/com/java110/order/dao/impl/CenterServiceDAOImpl.java

@@ -25,6 +25,22 @@ public class CenterServiceDAOImpl extends BaseServiceDao implements ICenterServi
 
     protected final static Logger logger = LoggerFactory.getLogger(CenterServiceDAOImpl.class);
 
+    @Override
+    public Map getOrder(Map order) throws DAOException {
+        List<Map> orders = sqlSessionTemplate.selectList("centerServiceDAOImpl.getOrder", order);
+        if (orders != null && orders.size() > 0) {
+            return orders.get(0);
+        }
+        return null;
+    }
+
+    @Override
+    public List<Map> getOrderItems(Map orderItem) throws DAOException {
+        List<Map> orderItems = sqlSessionTemplate.selectList("centerServiceDAOImpl.getOrderItems", orderItem);
+
+        return orderItems;
+    }
+
     /**
      * 保存订单信息
      *

+ 27 - 0
service-order/src/main/java/com/java110/order/smo/IOIdServiceSMO.java

@@ -0,0 +1,27 @@
+package com.java110.order.smo;
+
+import com.java110.dto.order.OrderDto;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @ClassName TServiceSMO
+ * @Description TODO
+ * @Author wuxw
+ * @Date 2020/7/5 20:30
+ * @Version 1.0
+ * add by wuxw 2020/7/5
+ **/
+public interface IOIdServiceSMO {
+
+    /**
+     * 创建全局事务ID
+     * @return
+     */
+    ResponseEntity<String> createOId(OrderDto orderDto);
+
+    /**
+     * 创建全局事务ID
+     * @return
+     */
+    ResponseEntity<String> fallBackOId(OrderDto orderDto);
+}

+ 112 - 0
service-order/src/main/java/com/java110/order/smo/impl/OIdServiceSMOImpl.java

@@ -0,0 +1,112 @@
+package com.java110.order.smo.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.client.RestTemplate;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.dto.order.OrderDto;
+import com.java110.dto.order.OrderItemDto;
+import com.java110.order.dao.ICenterServiceDAO;
+import com.java110.order.smo.IOIdServiceSMO;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.utils.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 事务处理服务类
+ * Created by wuxw on 2018/4/13.
+ */
+@Service("oIdServiceSMOImpl")
+public class OIdServiceSMOImpl implements IOIdServiceSMO {
+
+    private static Logger logger = LoggerFactory.getLogger(OIdServiceSMOImpl.class);
+
+
+    public static final String FALLBACK_URL = "http://SERVICE_NAME/fallBack";
+
+    public static final String SERVICE_NAME = "SERVICE_NAME";
+
+
+    @Autowired
+    private ICenterServiceDAO centerServiceDAOImpl;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+
+    @Override
+    public ResponseEntity<String> createOId(OrderDto orderDto) {
+
+        orderDto.setoId(GenerateCodeFactory.getOId());
+        if (StringUtil.isEmpty(orderDto.getAppId())) {
+            throw new IllegalArgumentException("未包含appId");
+        }
+
+        if (StringUtil.isEmpty(orderDto.getExtTransactionId())) {
+            throw new IllegalArgumentException("未包含交互日志");
+        }
+
+        if (StringUtil.isEmpty(orderDto.getRequestTime())) {
+            throw new IllegalArgumentException("未包含请求时间");
+        }
+
+        //保存订单信息
+        centerServiceDAOImpl.saveOrder(BeanConvertUtil.beanCovertMap(orderDto));
+        return new ResponseEntity<String>(JSONObject.toJSONString(orderDto), HttpStatus.OK);
+    }
+
+    @Override
+    public ResponseEntity<String> fallBackOId(OrderDto orderDto) {
+        if (StringUtil.isEmpty(orderDto.getoId())) {
+            throw new IllegalArgumentException("未包含事务ID");
+        }
+
+        //判断OID是否存在
+        orderDto = BeanConvertUtil.covertBean(centerServiceDAOImpl.getOrder(BeanConvertUtil.beanCovertMap(orderDto)), OrderDto.class);
+
+        if (orderDto == null) {
+            return new ResponseEntity<String>("没有需要回退事务", HttpStatus.NOT_FOUND);
+        }
+
+        //查询 事务项
+        Map orderItem = new HashMap();
+        orderItem.put("oId", orderDto.getoId());
+        List<Map> orderItemMaps = centerServiceDAOImpl.getOrderItems(orderItem);
+        if (orderItemMaps == null || orderItemMaps.size() < 1) {
+            return new ResponseEntity<String>("没有需要回退事务", HttpStatus.NOT_FOUND);
+        }
+        List<OrderItemDto> orderItemDtos = BeanConvertUtil.covertBeanList(orderItemMaps, OrderItemDto.class);
+
+        HttpEntity<String> httpEntity = null;
+        HttpHeaders header = new HttpHeaders();
+        List<OrderItemDto> errorOrderItemDtos = new ArrayList<>();
+        for (OrderItemDto orderItemDto : orderItemDtos) {
+            try {
+                httpEntity = new HttpEntity<String>(JSONObject.toJSONString(orderItemDto), header);
+                restTemplate.exchange(FALLBACK_URL.replace(SERVICE_NAME, orderItemDto.getServiceName()), HttpMethod.POST, httpEntity, String.class);
+            } catch (Exception e) {
+                logger.error("回退事务失败", e);
+                errorOrderItemDtos.add(orderItemDto);
+            }
+        }
+        if (errorOrderItemDtos.size() > 0) {
+            return new ResponseEntity<String>(JSONArray.toJSONString(errorOrderItemDtos), HttpStatus.BAD_REQUEST);
+        } else {
+            return new ResponseEntity<String>("", HttpStatus.OK);
+        }
+    }
+}