兩個項目之間的通信


最近公司有一個之前已經上線的項目,因為這個項目中有一些報表經常搞死tom貓的原因,現在要將報表的部分拆分出來成為一個獨立的系統,在專門的一個貓上跑。

  最終實現的一個效果如圖所示:

  1.非報表業務訪問主系統走的是7088服務器

  

  2.報表業務訪問的是8082服務器上的信息

  

  注意:報表業務鏈接后面攜帶了一個參數

-------------------------------------------------------------------------------------------------------------------------------

  開始的一些准備

    1.報表系統是復制原系統一份,修改一下另一個系統的名字(不過用的只有報表的部分而已,別的沒必要刪除,太復雜了,牽扯到一些權限的問題,那些報表在那個角色下該不該顯示等等)

    2.准備兩個一樣的tomcat(這兩貓要在同一個機器上啟動,所以這時候要注意端口的沖突問題,里面有關port的都要改一下)

    3.這兩個項目不要放在同一個myeclipse或者eclipse中運行(原因:雖然可以正常啟動訪問,但是沒法調試,兩個除了名字不一樣,其它都一樣的項目在一個工作空間中的debug的時候,永遠找的都是放在第一位的項目)

    4.在每個工具里安裝准備好的貓即可

    5.復制相同的數據庫,一個用於A系統,一個用於A_report系統

    6.在A系統的數據庫的權限表中加入一個開關,用來標記哪些是報表的URL,這個用來在頁面遍歷出的URL中進行判斷(boolean ipflag)

--------------------------------------------------------------------------------------------------------------------------------------------------

  開始具體的操作:(這里以A和A_report兩個項目名為例)

    考慮的問題:(1).兩個系統要保證是同一個用戶登陸,A_report系統何時觸發登陸,怎么登陸   (2).在A_report系統中要去掉登陸超時的一些類似驗證   。。。。

    1.在A系統中添加一個properties屬性文件,內容:reportIP=localhost:8082

    2.當A系統的側邊欄目加載的時候,報表部分的URL變成A_report系統的對應欄目的地址,比如上面第二張圖中所示

     實現:(1)在加載A系統側邊欄目的action中入讀取1中的IP屬性文件,並聲明一個變量,get,set 使其可以在前端頁面中可以接收到,(其實是將需要的數據傳遞到前端,然后拼成相應的地址)

aciton類:

 String fileName="reportIP.properties";
          String reportIP = "";
          try {
            Properties p = new Properties();    
            //InputStream is=new FileInputStream(fileName);
            InputStream in = PromissionAction.class.getClassLoader().getResourceAsStream(fileName);
            p.load(in);
            reportIP = p.getProperty("reportIP");
            System.out.println(reportIP);
            
        } catch (Exception e) {
            e.printStackTrace();
        }

//獲取當前登陸賬戶的唯一標識,(將此標識傳遞到第二個系統中,第二個系統根據此值實現登陸)

SysAccounts so =  (SysAccounts) getRequest().getSession().getAttribute("SYSaccount");
            String opercode = so.getOpercode();
            
            getRequest().setAttribute("opercode", opercode);

 

前端頁面判斷:(用的是freemarker模版)

<#if p1.action?exists>      <!--這里的p1就是權限表promission-->

  <#if p1.ipflag==true>'http://${reportIP}${p1.action?if_exists}?opercode=${opercode?if_exists}'

  <#else>'${p1.action?if_exists}'

</#if>

        (2)至此,A系統的完成

    3.A_report系統:

      PS:在這個系統中有A系統的URL訪問的時候,實現登陸,而且只能登陸一次,每次都登陸有影響

      (1)首先得在這個系統中定義一個攔截器,將此攔截器配置到這個系統的action 的xml文件中,然后每個報表的action都需要ref一下,這樣一來,不管在A系統中先點那個報表的URL,都會實現第二個系統的登陸操作

public class ReportPamamInterceptor implements Interceptor {
    
    private SysAccounts accounts;

    public void destroy() {}

    public void init() {}
    
    public String intercept(ActionInvocation invocation) throws Exception {
        
        //從系統session中獲取登陸用戶信息
        HttpServletRequest req = ServletActionContext.getRequest();
        SysAccounts accounts = (SysAccounts) req.getSession().getAttribute("SYSaccount");
        
        //以下3句是得知那個action訪問的,從而判斷返回哪個報表
        String namespace = invocation.getProxy().getNamespace(); String method = invocation.getProxy().getActionName(); String url = namespace + "/" + method + ".do"; //判斷用戶如果不為空,就不再登陸,直接返回具體的相應頁面,在report.xml中的 <global-results>進行接收
        if (accounts != null) {
            return JudgeResult.toGoal(url);
        }
        
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        
        String opercode = request.getParameter("opercode");
        accounts = new SysAccounts();
        accounts.setOpercode(opercode);
        
        session.setAttribute("accounts", accounts);
        //用於在登陸頁面進行判斷跳轉的報表
        session.setAttribute("url", url);
        return "goLogin";
    }

}

xml文件中配置:

<package name="querycardinfo" namespace="/unionfb/report/querycardinfo" extends="default">
    
        <!-- 新增攔截器,作用是 當第一個系統訪問此action的時候觸發攔截器,攔截器接收第一個系統傳遞的值 -->
        <interceptors>  
            <interceptor name="reportPamamInterceptor"  
                class="com.zframework.system.interceptor.ReportPamamInterceptor">  
            </interceptor>  
            <!-- 攔截器棧 -->  
            <interceptor-stack name="mydefault">  
                <interceptor-ref name="defaultStack" />  
                <interceptor-ref name="reportPamamInterceptor" />  
            </interceptor-stack>  
        </interceptors> 
<!-- 定義全局的,攔截器返回之后跳轉到本系統進行登陸操作 --> <global-results> <!-- 沒有登陸的時候執行--> <result name="goLogin" type="redirect">/Login.do</result> <!-- 已經登陸跳轉 攔截器中檢測到用戶已經登陸,就不再做登陸操作,直接在這里返回具體的相應頁面 --> <result name="/unionfb/report/querycardinfo/cro.do" type="redirect">/unionfb/report/querycardinfo/cro1.do</result> </global-results> <!-- 第二個系統對第一個系統的接應點 --> <action name="cro" class=""> //這里的class屬性不能丟,這個action只是一個接應點,觸發攔截器的作用是攔截器觸發之后判斷第二個系統是否已經登陸, <interceptor-ref name="reportPamamInterceptor"/> </action> <action name="cro1" class="queryCardAction" method="cro" > <result name="success">/templates/unionfb/report/card/query.html</result> <result name="error" type="dispatcher">/templates/common/message.html</result>

      (2)定義一個普通的Java類進行判斷

public class JudgeResult {
    // 注意:以下的路徑不是地址,僅是一個標記而已
    public static String toGoal(String url) {

        switch (url) {
        
        // 網店交易匯總表
        case "/report/wdsellcardquery.do":
            return "/report/wdsellcardquery.do";

                ......

      (3)A系統每次的URL都會觸發這個攔截器,所以在攔截器中判斷;如果已經登陸了根據JudgeResult.toGoal(url)判斷直接跳到<global-results>的result返回

      (4)如果沒有登陸,那么跳轉到A_report的登陸action中,再在此調用返回JudgeResult.toGoal(url)結果

------------------------------------------------------------------------over-----------------------------------------------------------------------------------

這種做法比較low,如果大家有比較好的想法,可以交流下。

 

PS:剛剛做完發現一個bug,這是兩個系統,也就是說會產生兩個session,后一個系統生成的session會把前一個系統的session覆蓋掉,所以A_report還要放在不同的服務器上

PS:數據庫的主從庫之間要同步,報表里的數據是來自於非報表錄入的了,此時的從庫只能設置為只讀的,這樣的話,A_report系統中會發生一個數據庫錯誤:ORA-16000(Oracle數據庫),出現此錯誤的原因:系統的一些查詢語句有添加的操作,導致這樣的錯誤發生

 

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM