最近很多小伙伴都在问kubernetes权威指南学习笔记(1)--mysql小例子和kubespheremysql这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展activiti用
最近很多小伙伴都在问kubernetes 权威指南学习笔记(1) -- mysql 小例子和kubesphere mysql这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑、ActivityMq的使用(小例子)、ajax xml 实现数据交互 小例子、android 自学之 sqlitedatabase 小例子等相关知识,下面开始了哦!
本文目录一览:- kubernetes 权威指南学习笔记(1) -- mysql 小例子(kubesphere mysql)
- activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑
- ActivityMq的使用(小例子)
- ajax xml 实现数据交互 小例子
- android 自学之 sqlitedatabase 小例子
kubernetes 权威指南学习笔记(1) -- mysql 小例子(kubesphere mysql)
mysql 小例子
- 创建一个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 密码这里写的有问题,改掉就好了
- 创建一个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分钟 小例子 简单代码搭建 及 其中的 各种坑
看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的使用(小例子)
什么时候使用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 实现数据交互 小例子
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 小例子
功能实现单词本的添加与查询单词
查询结果图如下
代码如下:
查询结果使用的 activity 是 dialog 风格的 activity,在 manifest 文件中如此配置
- <activity android:name=".ResultActivity"
- android:label="查询结果"
- android:theme="@android:style/Theme.Dialog"></activity>
要实现数据库的增删改查,需要三步:
1. 继承 SQLiteOpenHelper 复写 onCreate 方法,一般在里面实现创建表的工作。
2. 通过 SQLiteOpenHelper 的 getReadableDatabase 或者 getWriteableDatabase 方法创建数据库
3. 调用数据库增删改查方法进行数据操作
java 代码如下
- package com.example.mysqliitedatabase;
-
- import android.provider.BaseColumns;
- import android.provider.SyncStateContract.Columns;
- //定义数据库表的名字及表的列名
- public class Words {
- static class MyColumn implements BaseColumns{
- final static String TABLE_NAME="dict";
- final static String _ID="_id";
- final static String WORD="word";
- final static String DETAIL="detail";
- }
- }
- package com.example.mysqliitedatabase;
-
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
-
- public class MySqliteDatabaseHelper extends SQLiteOpenHelper {
-
- String CreateTable="create table dict"+"("+Words.MyColumn._ID+"integer primary key ,"+Words.MyColumn.WORD+","+Words.MyColumn.DETAIL+")";
-
- public MySqliteDatabaseHelper(Context context, String name,
- CursorFactory factory, int version) {
- super(context, name, factory, version);
- // TODO Auto-generated constructor stub
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- // TODO Auto-generated method stub
- db.execSQL(CreateTable);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO Auto-generated method stub
-
- }
-
- }
- package com.example.mysqliitedatabase;
-
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Stack;
-
- import android.os.Bundle;
- import android.app.Activity;
- import android.content.ContentValues;
- import android.content.Intent;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.text.TextUtils;
- //import android.view.Menu;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
-
- public class MainActivity extends Activity {
-
- private EditText wordString;
- private EditText detailString;
- private EditText queryString;
- private SQLiteDatabase database;
- private Button addButton;
- private Button queryButton;
- String[] returnColums={Words.MyColumn.WORD,Words.MyColumn.DETAIL};
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- final MySqliteDatabaseHelper datanaseHelper=new MySqliteDatabaseHelper(getApplicationContext(), "dict.db",null,1);
- wordString=(EditText) findViewById(R.id.editText1);
- detailString=(EditText) findViewById(R.id.editText2);
- queryString=(EditText) findViewById(R.id.editText3);
- addButton= (Button) findViewById(R.id.button1);
- queryButton=(Button) findViewById(R.id.button2);
-
- addButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- final String word=wordString.getText().toString();
- final String detail=detailString.getText().toString();
-
- database=datanaseHelper.getWritableDatabase();
-
- ContentValues contentValues=new ContentValues();
- contentValues.put(Words.MyColumn.WORD,word);
- contentValues.put(Words.MyColumn.DETAIL,detail);
-
- database.insert("dict", null,contentValues);
-
- Toast.makeText(getApplicationContext(), "add success",1000).show();
- }
- });
-
- queryButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- database=datanaseHelper.getWritableDatabase();
- String query=queryString.getText().toString();
- String[] selectionArgs = null;
- String selection = null;
- Cursor cursor;
- if (!TextUtils.isEmpty(query)) {
- selectionArgs=new String[]{query};
- selection=Words.MyColumn.WORD+"= ?";
- }
-
- cursor=database.query("dict", returnColums, selection, selectionArgs, null,null,null);
- ArrayList<Map<String,String>> list=new ArrayList<Map<String,String>>();
- if (cursor!=null) {
- while (cursor.moveToNext()) {
- Map<String,String> map=new HashMap<String, String>();
- int wordIndex=cursor.getColumnIndex(Words.MyColumn.WORD);
- int detailIndex=cursor.getColumnIndex(Words.MyColumn.DETAIL);
- map.put(Words.MyColumn.WORD,cursor.getString(wordIndex));
- map.put(Words.MyColumn.DETAIL,cursor.getString(detailIndex));
- list.add(map);
- }
- Toast.makeText(getApplicationContext(), "query success",1000).show();
- Intent intent=new Intent(getApplicationContext(), ResultActivity.class);
- Bundle bundle=new Bundle();
- bundle.putSerializable("data",list);
- intent.putExtras(bundle);
- startActivity(intent);
- }
- else {
- Toast.makeText(getApplicationContext(), "cursor is null",1000).show();
- }
- }
- });
- }
- }
- package com.example.mysqliitedatabase;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
-
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
-
- public class ResultActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- ListView listView=new ListView(getApplicationContext());
- setContentView(listView);
-
- Intent intent=getIntent();
- ArrayList<Map<String,String>> list=(ArrayList<Map<String, String>>) intent.getSerializableExtra("data");
- 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});
- listView.setAdapter(adapter);
- }
- }
关于kubernetes 权威指南学习笔记(1) -- mysql 小例子和kubesphere mysql的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑、ActivityMq的使用(小例子)、ajax xml 实现数据交互 小例子、android 自学之 sqlitedatabase 小例子的相关知识,请在本站寻找。
本文标签: