GVKun编程网logo

kubernetes 权威指南学习笔记(1) -- mysql 小例子(kubesphere mysql)

3

最近很多小伙伴都在问kubernetes权威指南学习笔记(1)--mysql小例子和kubespheremysql这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展activiti用

最近很多小伙伴都在问kubernetes 权威指南学习笔记(1) -- mysql 小例子kubesphere mysql这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑、ActivityMq的使用(小例子)、ajax xml 实现数据交互 小例子、android 自学之 sqlitedatabase 小例子等相关知识,下面开始了哦!

本文目录一览:

kubernetes 权威指南学习笔记(1) -- mysql 小例子(kubesphere mysql)

kubernetes 权威指南学习笔记(1) -- mysql 小例子(kubesphere mysql)

mysql 小例子

  1. 创建一个mysql-rc.yaml 文件
apiVersion: v1
kind: ReplicationController # 副本控制器RC
metadata:
  name: mysql # RC 的名称,全局唯一
spec:
  replicas: 1 # 副本期待数量
  selector: 
    app: mysql   # 符合目标的Pod拥有此标签
  template:      # 根据此磨吧创建Pod的副本(实例)
    metadata:
      labels:
        app: mysql  # Pod 副本拥有的标签,对应的RC的Selector
    spec:
      containers:     # Pod 内容器的定义部分
      - name: mysql   # 容器的名称
        image: mysql  # 容器对应的Docker Image
        ports:
        - containerPort: 3306   # 容器应用监听的端口号
        env:                    # 注入容器的环境变量
        - name: MYSQL_ROOT_PASSWORD   # 这里第一次写错了 MySQL_ROOT_PASSWORD
          value: "root"

发布RC文件:

kubectl create -f mysql-rc.yaml

查看创建的RC

kubectl get rc

查看Pod的创建情况

kubectl get pods

创建失败,查看更多失败信息

kubectl describe pod example
kubectl get events

查看日志,错误信息

kubectl logs -p <pod name>

错误

➜  k8s kubectl logs -p mysql-lvq7v
error: database is uninitialized and password option is not specified
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

这个是rc文件mysql 密码这里写的有问题,改掉就好了

  1. 创建一个service, 文件名mysql-svc.yaml
apiVersion: v1
kind: Service         # 表明是Kubernetes Service 
metadata:
  name: mysql         # Service 的全局唯一名称
spec:
  ports:
    - port: 3306      # Service 提供服务的端口号,这里写的时候写成了  - port:3306 没有用空格隔开
  selector:           # Service 对应的Pod 拥有这里定义的标签
    app: mysql

创建

kubectl create -f mysql-svc.yaml

查看刚才创建的service

kubectl get svc

碰到一个错误, 是由于缩进引起的

error: error validating "mysql-svc.yaml": error validating data: ValidationError(Service.spec.ports[0]): invalid type for io.k8s.api.core.v1.ServicePort: got "string", expected "map"; if you choose to ignore these errors, turn validation off with --validate=false

根据 service的唯一名字,容器可以从环境变量中获取到Service对应的Cluster IP 地址和端口,就可以发起TCP/IP连接请求了。

这样就创建了一个mysql 的服务。

activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑

activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑

 

看mossle的 5.16 用户手册中的  快速起步:10分钟教程 

 

想自己跑一下,虽然官方文档已经写的非常详细了,但是实际操作中还是遇到各种坑,这里记录下来。

 

首先官网下载最新的 5版本 full Guide

方法如下:

百度搜索 activiti,点

 

往下拉页面,

 

点 no thanks continue,跳转页面到:

 

往下拉页面,找到

 

 

点 5.x Full Guide连接,点进去

点图中红框部分下载。

==============================

 下载解压后,得到这个目录:

目录简介:

1) database:里面存放的是Activiti使用到的数据库信息的sql文件,使用时只需执行你自己的数据库类型的文件即可。如:你的数据库是MySQL,那么就执行activiti.mysql.create.*.sql即可。

2) docs:毫无疑问,api文档是也【但是这个api貌似都是英文的,如果英文不好,还是建议看中文版本: http://www.mossle.com/docs/activiti/index.html】。

3) libs:使用Activiti所需要的所有的jar包和源文件。

4) wars:官方给我们提供的示例Demo,通过使用Demo可以更加快速的了解Activiti【还可以用这个项目直接画xml流程图,避免了在编辑器 如eclipse中安装activiti流程图绘制插件
================

 

将其中的 wars目录中的

放到本地tomcat下,我用的是7版本,

然后直接启动,就可以了通过如下地址访问了:

可以参考

Activity工作流(2)-入门安装运行第一个例子

这里需要说明的就是,这个Demo默认采用的是h2内存数据库,如果想用你自己的数据库,就需要修改web应用WEB-INF/classes目录下的db.properties。然后,按上面说的,把database里的create文件夹里的数据库文件导入你自己的数据库。

改为MySQL数据库具体方法

这里用哪个库都行,但是为了后面的代码演示,我们将上面项目的库改为mysql,

首先在本地电脑上,创建一个mysql数据库,名字随意,我这里叫 activiti1

 

然后,在刚才下载的目录下找到

在我们自己创建的数据库里执行上面框住的3个脚本,数据库中就有表了。

然后,

修改tomcat下项目中的数据库配置:

再重启tomcat,就会用我们本地的tomcat数据库了。

然后就可以根据以下文章,操作一遍这个官方项目了:

Activiti工作流的应用示例

 

=================================================================

下面我们用代码方式创建,也就是根据 5.16中文用户手册上的 10分钟例子,简单测试下,

参考:5.16中文用户手册上的 10分钟例子

 但是这里我们的项目中不用Spring,不用安装Eclipse的activiti流程图插件(此插件及其难装,而且我觉得还不如直接在上面的官方项目中画流程图,再导出来好用

 

因为不想用spring,所以 我们创建一个 maven的jar项目

这个项目中,首先是 pom文件中要引入 activiti的jar包,和mysql的连接jar包:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.my</groupId>
  <artifactId>activitiTest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <!-- Activiti -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <!-- <version>5.15.1</version> -->
            <version>5.22.0</version>
        </dependency>
        
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-explorer</artifactId>
            <version>5.22.0</version>
        </dependency>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.29</version>
        </dependency>
    
    </dependencies>
</project>

可以看到,整个pom文件中只需要 activiti的jar包和 mysql的连接包,非常简单。

=====================

第一个出现了:

就是pom中的 activiti 版本

<dependency>
            <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <!-- <version>5.15.1</version> --> <version>5.22.0</version> </dependency>

注意:这个版本一定要和我们数据库中的  act_ge_property 表

 

中数据版本一致

否则一会运行代码就会报如下异常:

 

可以参考:

Could not update Activiti database schema: unknown version from database: ''5.20.0.1''

==============================================

配置好pom,就要配置代码需要访问的数据库,为了后面测试,我们要让代码的数据库和我们之前下载好的官方guide项目中的数据库使用同一个

而我们代码因为没有用spring集成,所以不能直接用 db.properties,而是要 一个

 activiti.cfg.xml 配置文件

配置文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="processEngineConfiguration"
        class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti1?characterEncoding=utf-8" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="123" />
        <property name="databaseSchemaUpdate" value="true" />
    </bean>

</beans>

这里面就是配我们本地的那个数据库。

手册中的创建ProcessEngine部分有这个配置文件的内容:

 

还可以参考文章:

(activiti入门列子一个简单的activiti请假流程)  或

我的第一个activiti实例

=====================================================

然后可以创建一个类,编写java代码:

【注意:这个类中,创建 ProcessEngine 对象,不要用手册中10分钟例子那的那个方法,而是要用 getDefaultProcessEngine() 这个方法,这样才会用我们本地的activiti.cfg.xml数据库配置

package activitiTest;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;

public class T1 {

    public static void main(String[] args) {

// Create Activiti process engine 这个是用spring集成时用的,如果不用spring则用下面的getDefaultProcessEngine
//        ProcessEngine processEngine = ProcessEngineConfiguration
//                .createStandaloneProcessEngineConfiguration()
//                .buildProcessEngine();
        
        ///用这个方法,才会去加载 activiti.cfg.xml 配置文件中配置的数据库
          ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

          // Get Activiti services
          RepositoryService repositoryService = processEngine.getRepositoryService();
          RuntimeService runtimeService = processEngine.getRuntimeService();

          // Deploy the process definition
          repositoryService.createDeployment()
            .addClasspathResource("FinancialReportProcess1.bpmn20.xml")
            .deploy();

          // Start a process instance
          runtimeService.startProcessInstanceByKey("financialReport");
        }
}

 

然后我们就可以继续根据官网的 10分钟教程,编写 xml 流程文件了,这时要,注意:

官方手册中给出了一个财务月报提交审批的流程的xml,说是为了熟悉流程需要手工编写,直接把那个流程拿过来放到我们项目的resouce目录下用Eclipse用我们刚才的T1代码运行是可以的【也就是说,如果只是需要在Eclipse中运行项目,我们只需要用上面的xml即可,根本不用其他任何activiti额外的流程配置】

 

但是,如果你想额外测试,将这个复制过来的“手写xml”导入到我们官网下的guide项目中是不行的,因为其缺少了 bpmn图像信息,会报错如下:

当然,用户手册 10分钟例子处,在这个 “手写流程xml”下面 还有一个连接,说是可以下载带bpmn图像信息的 xml,是可以下载的,而且其中也确实包含bpmn元素,但是,你下载下来,往tomcat项目中导入,还是会报错:

不止如此,如果你直接把它放在Eclipse中resource目录下,运行我们的T1代码,发现会直接报错:

 

其实原因是,用户手册中提供的 xml 虽然包含了图像元素信息,但是却缺少了bpmn图像元素标签相关的头约束定义,所以Eclipse解析xml时会报错,官网guide项目无法导入也是同样原因。解决办法就是加入相关头约束,但是这个头约束在哪里找呢?

不用在网上找,只需要在官网guide项目中随便画一个流程图(或者用已存在的流程图)导出到本地,然后用编辑器打开,就会发现,人家官网项目导出的xml中包含的头是全的,我们只需要把其复制到我们手写的 xml中即可

下面是我添加好头部约束定义,即各种注释的 手写 财务月报流程xml:

FinancialReportProcess1.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义开始 -->
<!-- 下面3行是头文件,如果包含 bpmndi:BPMNDiagram 标签则不能只用这3行,要用下面那个多的 -->
<!-- <definitions id="definitions" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 
    xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples"> -->

<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
    xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
    typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
    targetNamespace="http://www.activiti.org/processdef">


    <process id="financialReport" name="Monthly financial report reminder process">
        <!-- 开始事件 -->
        <startEvent id="theStart"></startEvent>
        <!-- 从开始到第一个用户任务之间的箭头连线(会包含定义箭头起始点对应的节点 id) -->
        <sequenceFlow id="flow1" targetRef="writeReportTask"
            sourceRef="theStart"></sequenceFlow>
        <!-- 第一个用户任务(写月财报) -->
        <userTask id="writeReportTask" name="Write monthly financial report">
            <!-- 描述信息,可有可无 (各个标签上的name属性也是同理) -->
            <documentation>
                write monthly finacial reoport for publication to
                sharehollders.
            </documentation>
            <!-- 潜在拥有者 -->
            <potentialOwner>
                <!-- 资源分配表达式 -->
                <resourceAssignmentExpression>
                    <!-- 真正的表达式 -->
                    <formalExpression>
                        <!-- 没有显示指明是用户还是组,默认为组,这里是之会计组的成员 -->
                        accountancy
                    </formalExpression>
                </resourceAssignmentExpression>
            </potentialOwner>
        </userTask>

        <!-- 从第一个用户任务到第二个用户任务之间的箭头连线(会包含定义箭头起始点对应的节点 id) -->
        <sequenceFlow id="flow2" targetRef="verifyReportTask"
            sourceRef="writeReportTask"></sequenceFlow>

        <!-- 第二个用户任务(领导审批任务) -->
        <userTask id="verifyReportTask" name="Verigy monthly financial report">
            <documentation>
                Verify monthly financial report composed by the
                accountancy department.
                This financial report is going to be sent to
                all the company
                shareholders.
            </documentation>
            <potentialOwner>
                <resourceAssignmentExpression>
                    <!-- 这个任务的潜在用户是管理组成员 -->
                    <formalExpression>management</formalExpression>
                </resourceAssignmentExpression>
            </potentialOwner>
        </userTask>

        <!-- 第二个用户任务到结束节点的箭头连线 -->
        <sequenceFlow id="flow3" targetRef="theEnd" sourceRef="verifyReportTask"></sequenceFlow>

        <!-- 结束事件节点 -->
        <endEvent id="theEnd"></endEvent>

    </process>

    <!-- 下面是用编辑器画流程图时生成的图像信息,在Eclipse中用代码方式可以把下面的都注释 -->
    <bpmndi:BPMNDiagram>
        <bpmndi:BPMNPlane bpmnElement="financialReport">
            <bpmndi:BPMNShape bpmnElement="theStart">
                <omgdc:Bounds height="30.0" width="30.0" x="75.0" y="225.0" />
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="writeReportTask">
                <omgdc:Bounds height="80.0" width="100.0" x="165.0" y="200.0" />
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="verifyReportTask">
                <omgdc:Bounds height="80.0" width="100.0" x="330.0" y="200.0" />
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="theEnd">
                <omgdc:Bounds height="28.0" width="28.0" x="480.0" y="226.0" />
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge bpmnElement="flow1">
                <omgdi:waypoint x="105.0" y="240.0" />
                <omgdi:waypoint x="165.0" y="240.0" />
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow2">
                <omgdi:waypoint x="265.0" y="240.0" />
                <omgdi:waypoint x="330.0" y="240.0" />
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow3">
                <omgdi:waypoint x="430.0" y="240.0" />
                <omgdi:waypoint x="480.0" y="240.0" />
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>

</definitions>

(上面这个xml不仅在Eclipse执行没有问题,甚至还可以直接导入到官方项目中

 

这时,我们的项目就搭建完成了,就可以按照用户手册 10分钟教程中的流程继续学习了,比如 用T1代码创建并部署、启动流程后,在官方项目中通过浏览器查看启动好的财务月报流程,并进行任务领取,执行等各种操作【因为他们共有同一个数据库,而activiti最大的特点就是几乎所有与activiti相关的内容都是保存在数据库中持久化的】。

 =============

我们使用官方guide时还要注意,每次一个用户进行流程相关操作后,如果想让另一个流程相关用户登录的信息发生变化,通常需要另一个用户先注销(退出)再重新登录,信息才会同步显示,同理如果我们用eclipse代码进行流程操作后,在guide项目中也需要用户注销再重新登录才会数据同步更新显示

 

================

其他知识:

 摘自: activiti入门列子一个简单的activiti请假流程

 

通过ProcessEngines.getDefaultProcessEngine获取流程引擎

        //通过activiti.cfg.xml获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();


通过源码可以看到  getDefaultProcessEngine方法会通过默认的activiti.cfg.xml文件名或者是activiti-context.xml文件名读取xml文件

 


当获取到的processEngine对象不为空时   就会在数据库创建关于activiti的23张表

具体作用如下:

 


更详细的情况可以去下面这个地址了解:

http://www.cnblogs.com/llzgzljl/archive/2013/10/07/3356108.html

此时你可以在数据库中看到act_ge_property表中插入了3条数据

ActivityMq的使用(小例子)

ActivityMq的使用(小例子)

什么时候使用mq。https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651960012&idx=1&sn=c6af5c79ecead98daa4d742e5ad20ce5&chksm=bd2d07108a5a8e0624ae6ad95001c4efe09d7ba695f2ddb672064805d771f3f84bee8123b8a6&mpshare=1&scene=1&srcid=04054h4e90lz5Qc2YKnLNuvY

一、ActivityMq的介绍:

  1.什么是消息中间件?与传统的传输通讯有什么区别?

    异步,无需等待,消息存放在队列里面。

  2.为什么要使用消息中间件?

    消息中间件可以解决高并发。

    两种通讯方式:01.点对点通讯。(Queue)

           02.发布订阅。(Topic)

    生产者:发送消息,提供接口的,主要向队列中发送消息

    队列:存放消息地址

    消息:发送的报文信息

    消费者:调用接口的,主要从队列中获取消息

  3.步骤:

    01、生产者向队列进行发送消息,如果消费者不在,队列就会将消息缓存

    02、消费者向队列中获取到消息之后,消费成功之后, 该消息队列直接被清除掉。(不清除就会产生重复消费问题)

  4.生产者向队列中生产高并发流量,消费者会不会挂掉?

    不会,因为队列会缓存消息。

  5.为什么MQ能够解决高并发问题?

    不会立马处理那么多的消息,队列会进行缓存,进行排队。

  6.JMS:java发送消息,客户端与服务器进行通讯的方式,可以理解成java的消息 中间件

    消息模型:

        01、点对点通讯方式:

        流程:生产者 队列 消费者。

        特点:一对一 异步通讯,生产者生产的消息 只允许有一个消费者进行消费。

        02、发布订阅:

        流程:生产者 主题 消费者

        特点:发布订阅 一个生产者 可以多个消费者 一对多。

二、ActivityMq安装:

  1.下载ActivityMQ

  官方网站:http://activemq.apache.org/download.html 

  2.运行ActivityMQ

   解压apache-activemq-5.15.9-bin.zip,进入该文件夹的bin目录。

     有两种方式启动ActivityMQ服务

     01、在bin目录下用cmd命令activemq start 启动服务,关掉黑窗口服务即停止

     02、进入bin目录下对应电脑位数的文件夹,64位进入win64,双击InstallService.bat批处理文件安装ActiveMQ服务,然后打开任务管理器启动ActiveMQ服务

        启动服务后打开浏览器输入:http://localhost:8161/admin/  输入默认设置的账户:admin密码admin   

        点击队列(Queues),输入队列名称(Queue Name)FirstQueue,然后点创建(Craete)

  3.创建maven项目

     添加一个activemq-all-5.15.3.jar即可,在pom.xml加入

   

<dependencies>
 	<dependency>
   		<groupId>org.apache.activemq</groupId>
   		<artifactId>activemq-all</artifactId>
   		<version>5.15.3</version>
	</dependency>
  </dependencies>

三、创建producer.java和consumer.java

  producer.java

package main;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Producer {

    // 默认连接用户名
    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
    // 默认连接密码
    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    // 默认连接地址
    private static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args) {
        // 连接工厂
        ConnectionFactory connectionFactory =
                new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);

        try {
            // 连接
            Connection connection = connectionFactory.createConnection();
            // 启动连接
            connection.start();
            // 创建session
            Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            // 消息目的地
            Destination destination = session.createQueue("FirstQueue");
            // 消息生产者
            MessageProducer producer = session.createProducer(null);
            // 设置不持久化,此处学习,实际根据项目决定
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

            // 发送消息
            for (int i = 0; i < 10; i++) {
                // 创建一条文本消息
                TextMessage message = session.createTextMessage("ActiveMQ: 这是第 " + i + " 条消息");
                // Destination destination = session.createTopic("FirstQueueTopic");
                // 生产者发送消息
                producer.send(destination, message);
            }
            session.commit();
            session.close();
            connection.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

  consumer.java

package main;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Consumer {

    // 默认连接用户名
    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
    // 默认连接密码
    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    // 默认连接地址
    private static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args) {
        // 连接工厂
        ConnectionFactory connectionFactory =
                new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);
        try {
            // 连接
            Connection connection = connectionFactory.createConnection();
            // 启动连接
            connection.start();
            // 创建session
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 消息目的地
            Destination destination = session.createQueue("FirstQueue");
            // Destination destination = session.createTopic("FirstQueueTopic");
            // 消息消费者
            MessageConsumer consumer = session.createConsumer(destination);
            while (true) {
                TextMessage message = (TextMessage) consumer.receive();
                if (message != null) {
                    System.out.println("接收到消息: " + message.getText());
                } else {
                    break;
                }
            }
            session.close();
            connection.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

四、测试:

  先运行producer.java,再运行consumer.java。

五、项目中使用:

  spring-activemq.xml配置文件:

  生产者

<?xml version="1.0" encoding="UTF-8"?>
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
    xmlns:jms="http://www.springframework.org/schema/jms"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jms
        http://www.springframework.org/schema/jms/spring-jms.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core.xsd"> 
 
    <amq:connectionFactory id="amqConnectionFactory" 
    	brokerURL="${activemq.brokerURL}" userName="${activemq.username}" password="${activemq.password}" />    	
 
    <bean id="connectionFactory">
        <constructor-arg ref="amqConnectionFactory" />
        <property name="sessionCacheSize" value="100" />
    </bean>
     
    <!-- 定义JmsTemplate的Queue类型 -->
	<bean id="jmsQueueTemplate">
		<constructor-arg ref="connectionFactory" />
        <!-- 非pub/sub模型(发布/订阅),即队列模式 -->
		<property name="pubSubDomain" value="false" />
	</bean>
     
    <!-- 定义JmsTemplate的Topic类型 -->
	<bean id="jmsTopicTemplate">
		<constructor-arg ref="connectionFactory" />
        <!-- pub/sub模型(发布/订阅) -->
		<property name="pubSubDomain" value="true" />
	</bean>
     
</beans>

  

config.properties配置用户名,密码,url等信息。

activemq.brokerURL=failover:(tcp://10.135.100.59:9203,tcp://10.135.100.60:9203)
#activemq.brokerURL=tcp://10.135.100.59:9203
activemq.username=admin
activemq.password=admin

代码中的使用:

@Autowired
    @Qualifier("jmsQueueTemplate")
    private JmsTemplate jmsTemplate;// 通过@Qualifier修饰符来注入对应的bean

    /** 
     * @Title: send 发送一条消息到指定的队列(目标)
     * @Description: 
     * @param queueName 队列名称
     * @param message 消息内容
     * @date 2016年10月12日 上午10:15:56
     */
    public void send(String queueName, final String message) {
        jmsTemplate.send(queueName, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(message);
            }
        });
    }

  

 

 

 

ajax xml 实现数据交互 小例子

ajax xml 实现数据交互 小例子

berfore:

虽然自己的方向一直是在Web上,但是自己总是急于求成,所以越是到后面,越发觉基础不牢固,导致有时在综合思考的一些问题寻找突破口的时候就难上加难。 所以在此告诫自己,做技术要认真,脚踏实地。做人做事都要脚踏实地。 只有这样,站的更稳,走的越坚强。
老规矩,学习类的内容都写在csdn上。

正题

ajax

什么是ajax呢

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。

所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。

XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

所以现在大部分的网站 都是使用 ajax+xml 在后台实现数据交互。
前台通过 div 来更新页面。

就这样。为了加深理解,写了一个小例子

需求

search.html 为查询页面 选择指定产品,点击查询,然后会通过ajax向服务器发送查询信息,服务器返回xml数据。
html页面解析xml替换innerhtml显示返回结果

api.PHP
接受两种查询
第一种是接受参数c=list返回 产品名列表
第二种是接受c=search&pname=name返回每种产品的详细信息

写完了感觉没什么难的,不过其中写的时候有很多细节没有注意到。也感觉到了自己的js功底真是匮乏。

<!DOCTYPE html>
<html>
<head>
<Meta charset="utf-8">
<script language="javascript"> window.onload=function() { var xmlhttp=null; if (window.XMLHttpRequest) {// code for IE7+,Firefox,Chrome,Opera,Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6,IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { var xmlDoc=xmlhttp.responseXML; var elements = xmlDoc.getElementsByTagName("name"); for(var i=0;i<elements.length;i++) { var ele=elements[i].firstChild.nodeValue; var se=document.getElementById('product'); se.add(new Option(ele,ele)); } } } xmlhttp.open("GET","/api/api.PHP?c=list",true); xmlhttp.send(); } function search() { var xmlhttp=null; if (window.XMLHttpRequest) {// code for IE7+,IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { // var xmlDoc=xmlhttp.responseText; var xmlDoc=xmlhttp.responseXML; // <root><id>1</id><name>test</name><num>1</num><price>200</price></root> var id=xmlDoc.getElementsByTagName('id')[0].innerHTML; var name=xmlDoc.getElementsByTagName('name')[0].innerHTML; var num=xmlDoc.getElementsByTagName('num')[0].innerHTML; var price=xmlDoc.getElementsByTagName('price')[0].innerHTML; var res="" res+='id='+id+"<br/>"; res+='name='+name+"<br/>"; res+='num='+num+"<br/>"; res+='price='+price+"<br/>"; document.getElementById('result').innerHTML=res; } } var pname=document.getElementById('product').getElementsByTagName('option')[ document.getElementById('product').selectedindex ].innerHTML; xmlhttp.open("GET","/api/api.PHP?c=search&pname="+pname,true); xmlhttp.send(); } </script>
</head>
<body>

<form action="" style="margin-top: 15px;">
<label>请选择一种产品:</label>   
<select name="product" id='product'>
<!-- <option value="test2">test2</option> -->
<input type="button" value="search" onclick="search();return false;" />
<br/>
<hr/><br/>
<div id="result">这里显示结果</div>
</select>

</body>
</html>
<?PHP
header("Content-type: text/xml; charset=utf-8"); 

/** * @authors:F001 * @blog: ev1l.cc */
//api/api.PHP
//
class ArrayToXML {
    /** * The main function for converting to an XML document. * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document. * * @param array $data * @param string $rootNodeName - what you want the root node to be - defaultsto data. * @param SimpleXMLElement $xml - should only be used recursively * @return string XML */
    public static function toXml($data,$rootNodeName = 'root',$xml=null) {
        // turn off compatibility mode as simple xml throws a wobbly if you don't.
        if (ini_get('zend.ze1_compatibility_mode') == 1)
        {
            ini_set ('zend.ze1_compatibility_mode',0);
        }

        if ($xml == null)
        {
            $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
        }

        // loop through the data passed in.
        foreach($data as $key => $value)
        {
            // no numeric keys in our xml please!
            if (is_numeric($key))
            {
                // make string key...
                // $key = "unkNownNode_". (string) $key;
                $key='name';
            }

            // replace anything not alpha numeric
            // $key = preg_replace('/[^a-z]/i','',$key);

            // if there is another array found recrusively call this function
            if (is_array($value))
            {
                $node = $xml->addChild($key);
                // recrusive call.
                ArrayToXML::toXml($value,$rootNodeName,$node);
            }
            else 
            {
                // add single node.
                $value = htmlentities($value);
                $xml->addChild($key,$value);
            }

        }
        // pass back as string. or simple xml object if you want!
        return $xml->asXML();
    }
};


$conn=MysqL_connect('localhost','root','qtxz');
if(!$conn)
{
    die('can\'t connect to the MysqL server');
}
MysqL_selectdb('ajax');

if(isset($_GET['c']) && $_GET['c']=='list')
{
    $sql='select name from product';
    $rows=MysqL_query($sql);
    $res=array();
    while ($row=MysqL_fetch_array($rows)) {
        array_push($res,$row['name']);
}
echo ArrayToXML::toXml($res);
exit();
}
else if(isset($_GET['c']) &&   $_GET['c']=='search' && isset($_GET['pname']))
{
    $pname=$_GET['pname'];
    $sql="select * from product where name='".$pname."'";
    $rows=MysqL_query($sql);
    $res=MysqL_fetch_assoc($rows);

    echo ArrayToXML::toXml($res);
}
MysqL_close($conn);
?>

大体思路就是 前台一个简陋的 search.html
里面有select标签,当打开search.html的时候,会访问api.PHP?c=list 从服务器返回当前的产品列表,然后将每个产品add到select标签内,当点击查询的时候通过ajax产生形如api.PHP?c=search&pname=test,的请求返回有关该产品的详细信息xml, 通过解析xml 然后动态修改div id=result就可以显示返回的数据。

在var xmlDoc=xmlhttp.responseXML;时,多次遇到了返回xml为NUll但是如果改成responseText时还有数据的情况。总结一下,发现有以下几种原因。
1. 设置content type = text/xml
(本遇述问题由问题解决程序强制使用utf-8使用句header(“Content-Type: text/html;charset=UTF-8”)家已经知道)
2. 确定请求发送服务器并返
3. alert/检查 responseText候否看其些该信息(例xml信息)
4. 直接打浏览器打xml文档(浏览器输入请求页面能需要传递参数或者构建表单)浏览器告诉xml文档格式否确确

效果展示

打开时

查询后

最后

做技术,要认真,要踏实。就这样!

android 自学之 sqlitedatabase 小例子

android 自学之 sqlitedatabase 小例子

 功能实现单词本的添加与查询单词

查询结果图如下

 

代码如下:

查询结果使用的 activity 是 dialog 风格的 activity,在 manifest 文件中如此配置


  
  
  1. <activity android:name=".ResultActivity" 
  2.            android:label="查询结果" 
  3.            android:theme="@android:style/Theme.Dialog"></activity> 

要实现数据库的增删改查,需要三步:

1. 继承 SQLiteOpenHelper 复写 onCreate 方法,一般在里面实现创建表的工作。

2. 通过 SQLiteOpenHelper 的 getReadableDatabase 或者 getWriteableDatabase 方法创建数据库

3. 调用数据库增删改查方法进行数据操作

java 代码如下 


  
  
  1. package com.example.mysqliitedatabase; 
  2.  
  3. import android.provider.BaseColumns; 
  4. import android.provider.SyncStateContract.Columns; 
  5. //定义数据库表的名字及表的列名 
  6. public class Words 
  7.     static class MyColumn implements BaseColumns
  8.         final static String TABLE_NAME="dict"
  9.         final static String _ID="_id"
  10.         final static String WORD="word"
  11.         final static String DETAIL="detail"
  12.     } 

  
  
  1. package com.example.mysqliitedatabase; 
  2.  
  3. import android.content.Context; 
  4. import android.database.sqlite.SQLiteDatabase; 
  5. import android.database.sqlite.SQLiteDatabase.CursorFactory; 
  6. import android.database.sqlite.SQLiteOpenHelper; 
  7.  
  8. public class MySqliteDatabaseHelper extends SQLiteOpenHelper 
  9.      
  10.     String CreateTable="create table dict"+"("+Words.MyColumn._ID+"integer primary key ,"+Words.MyColumn.WORD+","+Words.MyColumn.DETAIL+")"
  11.      
  12.     public MySqliteDatabaseHelper(Context context, String name, 
  13.             CursorFactory factory, int version) 
  14.         super(context, name, factory, version); 
  15.         // TODO Auto-generated constructor stub 
  16.     } 
  17.  
  18.     @Override 
  19.     public void onCreate(SQLiteDatabase db) 
  20.         // TODO Auto-generated method stub 
  21.         db.execSQL(CreateTable); 
  22.     } 
  23.  
  24.     @Override 
  25.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
  26.         // TODO Auto-generated method stub 
  27.          
  28.     } 
  29.  
  30.  

  
  
  1. package com.example.mysqliitedatabase; 
  2.  
  3.  
  4. import java.util.ArrayList; 
  5. import java.util.HashMap; 
  6. import java.util.Map; 
  7. import java.util.Stack; 
  8.  
  9. import android.os.Bundle; 
  10. import android.app.Activity; 
  11. import android.content.ContentValues; 
  12. import android.content.Intent; 
  13. import android.database.Cursor; 
  14. import android.database.sqlite.SQLiteDatabase; 
  15. import android.text.TextUtils; 
  16. //import android.view.Menu; 
  17. import android.view.View; 
  18. import android.view.View.OnClickListener; 
  19. import android.widget.Button; 
  20. import android.widget.EditText; 
  21. import android.widget.Toast; 
  22.  
  23. public class MainActivity extends Activity { 
  24.  
  25.     private EditText wordString; 
  26.     private EditText detailString; 
  27.     private EditText queryString; 
  28.     private SQLiteDatabase database; 
  29.     private Button addButton; 
  30.     private Button queryButton; 
  31.     String[] returnColums={Words.MyColumn.WORD,Words.MyColumn.DETAIL}; 
  32.  
  33.     @Override 
  34.     protected void onCreate(Bundle savedInstanceState) { 
  35.         super.onCreate(savedInstanceState); 
  36.         setContentView(R.layout.activity_main); 
  37.          
  38.         final MySqliteDatabaseHelper datanaseHelper=new MySqliteDatabaseHelper(getApplicationContext(), "dict.db",null,1); 
  39.         wordString=(EditText) findViewById(R.id.editText1); 
  40.         detailString=(EditText) findViewById(R.id.editText2); 
  41.         queryString=(EditText) findViewById(R.id.editText3); 
  42.         addButton= (Button) findViewById(R.id.button1); 
  43.         queryButton=(Button) findViewById(R.id.button2); 
  44.      
  45.         addButton.setOnClickListener(new OnClickListener() { 
  46.             @Override 
  47.             public void onClick(View v) { 
  48.                 // TODO Auto-generated method stub 
  49.                 final String word=wordString.getText().toString(); 
  50.                 final String detail=detailString.getText().toString(); 
  51.                  
  52.                 database=datanaseHelper.getWritableDatabase(); 
  53.                  
  54.                 ContentValues contentValues=new ContentValues(); 
  55.                 contentValues.put(Words.MyColumn.WORD,word); 
  56.                 contentValues.put(Words.MyColumn.DETAIL,detail); 
  57.                  
  58.                 database.insert("dict"null,contentValues); 
  59.                  
  60.                 Toast.makeText(getApplicationContext(), "add success",1000).show(); 
  61.             } 
  62.         }); 
  63.          
  64.         queryButton.setOnClickListener(new OnClickListener() { 
  65.              
  66.             @Override 
  67.             public void onClick(View v) { 
  68.                 // TODO Auto-generated method stub 
  69.                 database=datanaseHelper.getWritableDatabase(); 
  70.                 String query=queryString.getText().toString(); 
  71.                 String[] selectionArgs = null
  72.                 String selection = null
  73.                 Cursor cursor; 
  74.                 if (!TextUtils.isEmpty(query)) { 
  75.                     selectionArgs=new String[]{query}; 
  76.                     selection=Words.MyColumn.WORD+"= ?"
  77.                 } 
  78.                  
  79.                 cursor=database.query("dict", returnColums, selection, selectionArgs, null,null,null); 
  80.                 ArrayList<Map<String,String>> list=new ArrayList<Map<String,String>>(); 
  81.                 if (cursor!=null) { 
  82.                     while (cursor.moveToNext()) { 
  83.                         Map<String,String> map=new HashMap<StringString>(); 
  84.                         int wordIndex=cursor.getColumnIndex(Words.MyColumn.WORD); 
  85.                         int detailIndex=cursor.getColumnIndex(Words.MyColumn.DETAIL); 
  86.                         map.put(Words.MyColumn.WORD,cursor.getString(wordIndex)); 
  87.                         map.put(Words.MyColumn.DETAIL,cursor.getString(detailIndex)); 
  88.                         list.add(map); 
  89.                     } 
  90.                     Toast.makeText(getApplicationContext(), "query success",1000).show(); 
  91.                     Intent intent=new Intent(getApplicationContext(), ResultActivity.class); 
  92.                     Bundle bundle=new Bundle(); 
  93.                     bundle.putSerializable("data",list); 
  94.                     intent.putExtras(bundle); 
  95.                     startActivity(intent); 
  96.                 } 
  97.                 else { 
  98.                     Toast.makeText(getApplicationContext(), "cursor is null",1000).show(); 
  99.                 } 
  100.             } 
  101.         }); 
  102.     } 

  
  
  1. package com.example.mysqliitedatabase; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5. import java.util.Map; 
  6.  
  7. import android.app.Activity; 
  8. import android.content.Intent; 
  9. import android.os.Bundle; 
  10. import android.widget.ListView; 
  11. import android.widget.SimpleAdapter; 
  12.  
  13. public class ResultActivity extends Activity 
  14. @Override 
  15. protected void onCreate(Bundle savedInstanceState) { 
  16.     // TODO Auto-generated method stub 
  17.     super.onCreate(savedInstanceState); 
  18.     ListView listView=new ListView(getApplicationContext()); 
  19.     setContentView(listView); 
  20.  
  21.     Intent intent=getIntent(); 
  22.     ArrayList<Map<String,String>> list=(ArrayList<Map<StringString>>) intent.getSerializableExtra("data"); 
  23.     SimpleAdapter adapter=new SimpleAdapter(getApplicationContext(), list, R.layout.main, new String[]{Words.MyColumn.WORD,Words.MyColumn.DETAIL},new int[]{R.id.text1,R.id.text2}); 
  24.     listView.setAdapter(adapter); 

 

关于kubernetes 权威指南学习笔记(1) -- mysql 小例子kubesphere mysql的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑、ActivityMq的使用(小例子)、ajax xml 实现数据交互 小例子、android 自学之 sqlitedatabase 小例子的相关知识,请在本站寻找。

本文标签: