eXistDB简单Tirgger示例02

  • XCONF文件中指定XQuery文件路径
  • XCONF文件中包含XQuery文件
  • XCONF文件中指定Java类

第二种方式,是用XCONF文件通知eXistDB要对哪个collection中的哪些操作做触发,然后将XQuery语句包含在XCONF文件中。

1、在你需要触发的collection的对应配置collection中,增加一个xconf文件,文件名任意,官方推荐collection.xconf。配置collection与原collection的对应关系为,在/db/system/config/db下,建立/db下相同的collection。
比如,如果你希望监控/db/cda02路径,就需要在/db/system/config/db/cda02路径下,新增一个collection.xconf。
collection.xconf

<collection xmlns="http://exist-db.org/collection-config/1.0">
    <triggers>
        <trigger event="create" class="org.exist.collections.triggers.XQueryTrigger">
            <parameter name="query" value="
             xquery version '3.0';

             module namespace trigger='http://exist-db.org/xquery/trigger';
             declare namespace xmldb='http://exist-db.org/xquery/xmldb';

             declare function trigger:before-create-document($uri as xs:anyURI)
             {
                 local:log-event('before', 'create', 'document', $uri)
             };

             declare function trigger:after-create-document($uri as xs:anyURI)
             {
                 local:log-event('after', 'create', 'document', $uri)
             };
             
             declare function trigger:before-delete-document($uri as xs:anyURI)
             {
                 local:log-event('before', 'delete', 'document', $uri)
             };
             
             declare function trigger:after-delete-document($uri as xs:anyURI)
             {
                 local:log-event('after', 'delete', 'document', $uri)
             };
             
             declare function local:log-event($type as xs:string, $event as xs:string, $object-type as xs:string, $uri as xs:string)
             {
                 let $log-collection := '/db/Triggers'
                 let $log := 'log02.xml'
                 let $log-uri := concat($log-collection, '/', $log)
                 return
                 (
                     (: util:log does not work at all
                         util:log('warn', 'trigger fired'),
                     :)
                     
                     (: create the log file if it does not exist :)
                     if (not(doc-available($log-uri))) then
                         xmldb:store($log-collection, $log, &lt;triggers/&gt;)
                     else ()
                     ,
                     (: log the trigger details to the log file :)
                     update insert &lt;trigger event='{string-join(($type, $event, $object-type), '-')}' uri='{$uri}' timestamp='{current-dateTime()}'/&gt; into doc($log-uri)/triggers                 )             };"/>
        </trigger>
    </triggers>
</collection>

Continue reading eXistDB简单Tirgger示例02

eXistDB简单Tirgger示例01

  • XCONF文件中指定XQuery文件路径
  • XCONF文件中包含XQuery文件
  • XCONF文件中指定Java类

第一种方式,是用XCONF文件通知eXistDB要对哪个collection中的哪些操作做触发,然后触发器指向一个XQM的文件。

1、首先,编写触发器的xqm文件,比如我的保存路径为/db/Triggers/TriggerTest01.xqm
TriggerTest01.xqm

xquery version "3.0";

module namespace trigger="http://exist-db.org/xquery/trigger";

declare namespace xmldb="http://exist-db.org/xquery/xmldb";

declare function trigger:before-create-collection($uri as xs:anyURI)
{
    local:log-event("before", "create", "collection", $uri)
};

declare function trigger:after-create-collection($uri as xs:anyURI)
{
    local:log-event("after", "create", "collection", $uri)
};

declare function trigger:before-copy-collection($uri as xs:anyURI, $new-uri as xs:anyURI)
{
    local:log-event("before", "copy", "collection", concat("from: ", $uri, " to:", $new-uri))
};

declare function trigger:after-copy-collection($new-uri as xs:anyURI, $uri as xs:anyURI)
{
    local:log-event("after", "copy", "collection", concat("from: ", $uri, " to:", $new-uri))
};

declare function trigger:before-move-collection($uri as xs:anyURI, $new-uri as xs:anyURI)
{
    local:log-event("before", "move", "collection", concat("from: ", $uri, " to:", $new-uri))
};

declare function trigger:after-move-collection($new-uri as xs:anyURI, $uri as xs:anyURI)
{
    local:log-event("after", "move", "collection", concat("from: ", $uri, " to:", $new-uri))
};

declare function trigger:before-delete-collection($uri as xs:anyURI)
{
    local:log-event("before", "delete", "collection", $uri)
};

declare function trigger:after-delete-collection($uri as xs:anyURI)
{
    local:log-event("after", "delete", "collection", $uri)
};

declare function trigger:before-create-document($uri as xs:anyURI)
{
    local:log-event("before", "create", "document", $uri)
};

declare function trigger:after-create-document($uri as xs:anyURI)
{
    local:log-event("after", "create", "document", $uri)
};

declare function trigger:before-update-document($uri as xs:anyURI)
{
    local:log-event("before", "update", "document", $uri)
};

declare function trigger:after-update-document($uri as xs:anyURI)
{
    local:log-event("after", "update", "document", $uri)
};

declare function trigger:before-copy-document($uri as xs:anyURI, $new-uri as xs:anyURI)
{
    local:log-event("before", "copy", "document", concat("from: ", $uri, " to: ", $new-uri))
};

declare function trigger:after-copy-document($new-uri as xs:anyURI, $uri as xs:anyURI)
{
    local:log-event("after", "copy", "document", concat("from: ", $uri, " to: ", $new-uri))
};

declare function trigger:before-move-document($uri as xs:anyURI, $new-uri as xs:anyURI)
{
    local:log-event("before", "move", "document", concat("from: ", $uri, " to: ", $new-uri))
};

declare function trigger:after-move-document($new-uri as xs:anyURI, $uri as xs:anyURI)
{
    local:log-event("after", "move", "document", concat("from: ", $uri, " to: ", $new-uri))
};

declare function trigger:before-delete-document($uri as xs:anyURI)
{
    local:log-event("before", "delete", "document", $uri)
};

declare function trigger:after-delete-document($uri as xs:anyURI)
{
    local:log-event("after", "delete", "document", $uri)
};

declare function local:log-event($type as xs:string, $event as xs:string, $object-type as xs:string, $uri as xs:string)
{
    let $log-collection := "/db/Triggers"
    let $log := "log01.xml"
    let $log-uri := concat($log-collection, "/", $log)
    return
    (
        (: create the log file if it does not exist :)
        if (not(doc-available($log-uri))) then
            xmldb:store($log-collection, $log, <triggers/>)
        else ()
        ,
        (: log the trigger details to the log file :)
        update insert <trigger event="{string-join(($type, $event, $object-type), '-')}" uri="{$uri}" timestamp="{current-dateTime()}"/> into doc($log-uri)/triggers
    )
};

Continue reading eXistDB简单Tirgger示例01

Redis与Tomcat集群集成

在网站访问量急剧上升时,通常需要使用集群的方法进行横向扩展。
对于没有状态的应用来说,直接用nginx进行处理即可。
但对于有状态的应用来说,比如登录状态等,除了使用nginx进行扩展外,就需要考虑到Session共享的问题了。

大家知道可以用apache+tomcat来实现Session共享,但效率太低了,而且容易出错。
今天说的主要是用nginx+tomcat+redis+tomcat-redis-session-manager的方式实现共享。
原理比较简单:

1、tomcat-redis-session-manage扩展了
org.apache.catalina.valves.ValveBase;
org.apache.catalina.session.ManagerBase;
org.apache.catalina.session.StandardSession;
并通过Tomcat配置,替代了这几个类。

2、Set属性时,用session id作为key,将Tomcat的整个Session拆分为SessionSerializationMetadata+RedisSession然后序列化为byte[],存放到Redis。

3、Get属性时,用session id作为key,从Redis获取byte[],然后反序列化为SessionSerializationMetadata+RedisSession,供Tomcat使用。

配置也很简单:
1、从github下载源码tomcat-redis-session-manager

2、用gradle进行编译

#master分支下面,要把signing段和uploadArchives段删掉,才能正常编译
#release就不需要了
gradle build

3、将三个Jar包拷贝到Tomcat的lib文件夹下

#%TOMCAT_HOME%/lib
tomcat-redis-session-manager-master-2.0.0.jar
commons-pool2-2.2.jar
jedis-2.5.2.jar

4、修改context.xml配置文件,新增下面内容就搞定咯

<!--%TOMCAT_HOME%/conf/context.xml-->
  <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
  <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" 
  host="localhost" port="6379" database="0" maxInactiveInterval="60"/>

好处是:不需要修改应用
坏处是:要耗费一定的时间来(序列化+保存到Redis)、(反序列化+从Redis读取)。

eXistDB简单通讯12(HTTP_SOAP)

  • 保存文件
  • 取回文件
  • 查询

1、QueryFileSOAP.java

package com.neohope.existdb.test;

import org.exist.soap.Query;
import org.exist.soap.QueryResponse;
import org.exist.soap.QueryService;
import org.exist.soap.QueryServiceLocator;

import java.net.URL;
import java.nio.charset.Charset;

public class QueryFileSOAP {
    public static void QueryXML(String xquery, String user, String pwd) throws Exception {
        QueryService service = new QueryServiceLocator();
        Query query = service.getQuery(new URL("http://localhost:8080/exist/services/Query"));
        String sessionId = query.connect("neotest", "neotest");

        byte[] queryData = xquery.getBytes(Charset.forName("UTF-8"));
        QueryResponse resp = query.xquery( sessionId, queryData );
        System.out.println( "found: " + resp.getHits() );
        if(resp.getHits() == 0) {
            return;
        }
        else {
            //get 10 results
            byte[][] hits = query.retrieveData(sessionId, 1, 10,
                    true, false, "elements").getElements();
            for (int i = 0; i < hits.length; i++) {
                System.out.println(new String(hits[i], "UTF-8"));
            }
        }

        query.disconnect(sessionId);
    }

    public static void main(String args[]) throws Exception {
        String user = "neotest";
        String pwd = "neotest";
        String query ="for $name in collection('/db/CDA')/ClinicalDocument/recordTarget/patientRole/patient/name \n" +
                "return \n" +
                "<name>{$name}</name> ";
        QueryXML(query, user, pwd);
    }
}

eXistDB简单通讯11(HTTP_SOAP)

  • 保存文件
  • 取回文件
  • 查询

1、GetFileSOAP.java

package com.neohope.existdb.test;

import org.exist.soap.Query;
import org.exist.soap.QueryService;
import org.exist.soap.QueryServiceLocator;

import java.net.URL;


public class GetFileSOAP {
    public static void GetXML(String fileId, String user, String pwd) throws Exception {
        QueryService service = new QueryServiceLocator();
        Query query = service.getQuery(new URL("http://localhost:8080/exist/services/Query"));
        String session = query.connect(user, pwd);

        byte[] data = query.getResourceData(session,
                "/db/CDA/"+fileId,
                true, false, false);
        System.out.println(new String(data, "UTF-8"));
        query.disconnect(session);
    }

    public static void main(String args[]) throws Exception {
        String user = "neotest";
        String pwd = "neotest";
        GetXML("入院患者护理评估单01.xml",user,pwd);
    }
}

eXistDB简单通讯10(HTTP_SOAP)

  • 保存文件
  • 取回文件
  • 查询

1、SaveFileSOAP.java

package com.neohope.existdb.test;

import org.exist.soap.*;

import java.io.BufferedReader;
import java.io.FileReader;
import java.net.URL;
import java.nio.charset.Charset;

public class SaveFileSOAP {
    public static void SaveXML(String xmlFilePath, String user, String pwd) throws Exception {
        AdminService adminService = new AdminServiceLocator();
        Admin admin = adminService.getAdmin(new URL("http://localhost:8080/exist/services/Admin"));
        String session = admin.connect("neotest", "neotest");

        BufferedReader f = new BufferedReader(new FileReader(xmlFilePath));
        String line;
        StringBuffer xml = new StringBuffer();
        while ((line = f.readLine()) != null)
            xml.append(line);
        f.close();

        admin.store(session, xml.toString().getBytes(Charset.forName("UTF-8")), "UTF-8", "/db/CDA/入院患者护理评估单02.xml", true);
        admin.disconnect(session);
    }

    public static void main( String[] args ) throws Exception {
        String user = "neotest";
        String pwd = "neotest";
        SaveXML("PATH_TO_FILE\\入院患者护理评估单02.xml", user, pwd);
    }
}

eXistDB简单通讯09(HTTP_REST)

  • 保存文件
  • 取回文件
  • 查询

1、QueryFileHTTP.java

package com.neohope.existdb.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

public class QueryFileHTTP {
    public static void QueryXML(String query) throws IOException {
        URL url = new URL("http://localhost:8080/exist/rest/db/CDA");
        HttpURLConnection connect = (HttpURLConnection) url.openConnection();
        connect.setRequestProperty("Content-Type", "application/xml");
        connect.setRequestMethod("POST");
        connect.setDoOutput(true);

        OutputStream os = connect.getOutputStream();
        os.write(query.getBytes(Charset.forName("UTF-8")));
        connect.connect();

        BufferedReader is = new BufferedReader(new InputStreamReader(connect.getInputStream()));
        String line;
        while((line = is.readLine()) != null)
            System.out.println(line);
    }

    public static void main(String[] args) throws IOException {
        String query ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<query xmlns=\"http://exist.sourceforge.net/NS/exist\" start=\"1\" max=\"10\" cache=\"no\">\n";
        query +="<text><![CDATA[\n" +
                "for $name01 in /ClinicalDocument/recordTarget/patientRole/patient/name \n" +
                "return \n" +
                "<name>{$name01}</name> \n" +
                "]]></text> \n";
        query +="<properties> \n";
        query +="<property name=\"indent\" value=\"yes\"/> \n";
        query +="<property name=\"encoding\" value=\"UTF-8\"/> \n";
        query +="</properties> \n";
        query +="</query>";
        System.out.println(query);
        QueryXML(query);
    }
}

eXistDB简单通讯08(HTTP_REST)

  • 保存文件
  • 取回文件
  • 查询

1、GetFileHTTP.java

package com.neohope.existdb.test;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


public class GetFileHTTP {
    public static void GetXML(String fileId) throws IOException {
        URL url = new URL("http://localhost:8080/exist/rest/db/CDA/" + fileId);
        System.out.println("GET file from " + url.toString());

        HttpURLConnection connect = (HttpURLConnection) url.openConnection();
        connect.setRequestMethod("GET");
        connect.connect();
        System.out.println("Result:");

        BufferedReader bis = new BufferedReader(new InputStreamReader(connect.getInputStream()));
        String line;
        while ((line = bis.readLine()) != null) {
            System.out.println(line);
        }
    }

    public static void main(String[] args) throws IOException {
        GetXML("入院患者护理评估单01.xml");
    }
}

eXistDB简单通讯07(HTTP_REST)

  • 保存文件
  • 取回文件
  • 查询

1、SaveFileHTTP.java

package com.neohope.existdb.test;

//apache的base64会多一个换行符
//import org.apache.ws.commons.util.Base64;
//import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.sun.xml.internal.messaging.saaj.util.Base64;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class SaveFileHTTP {
    public static void SaveXML(String inFileName, String fileId) throws IOException {
        URL url = new URL("http://localhost:8080/exist/rest/db/CDA/" + fileId);
        System.out.println("Save file to " + url.toString());

        HttpURLConnection connect = (HttpURLConnection) url.openConnection();
        connect.setRequestMethod("PUT");
        connect.setDoOutput(true);
        connect.setRequestProperty("Content-Type", "application/xml");
        String userCredentials = "neotest:neotest";
        String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
        System.out.println(basicAuth);
        connect.setRequestProperty ("Authorization", basicAuth);

        File file = new File(inFileName);
        InputStream is = new FileInputStream(file);
        OutputStream os = connect.getOutputStream();

        byte[] buf = new byte[1024];
        int c;
        while ((c = is.read(buf)) > -1) {
            os.write(buf, 0, c);
        }
        os.flush();
        os.close();
        System.out.println("Statuscode " + connect.getResponseCode()
                + " (" + connect.getResponseMessage() + ")");
    }

    public static void main(String[] args) throws IOException {
        SaveXML("D:\\MyProjects\\IDEA14\\TestExistDB\\XMLFiles\\医惠\\入院患者护理评估单01.xml", "入院患者护理评估单01.xml");
    }
}